import type { SerializedEditorState } from '@frogbotai/richtext-lexical/lexical'
import {
BlocksFeature,
type BlocksFeatureProps,
convertLexicalToMarkdown,
editorConfigFactory,
lexicalEditor,
} from '@frogbotai/richtext-lexical'
import type { CollectionConfig } from 'frogbot'
type Block = Exclude<NonNullable<BlocksFeatureProps['blocks']>[number], string>
type SanitizedRichTextField = Parameters<
typeof editorConfigFactory.fromField
>[0]['field']
function isNamedSanitizedRichTextField(
field: unknown,
name: string,
): field is SanitizedRichTextField {
return (
typeof field === 'object' &&
field !== null &&
'name' in field &&
field.name === name &&
'type' in field &&
field.type === 'richText' &&
'editor' in field
)
}
const BannerBlock: Block = {
slug: 'banner',
fields: [
{
name: 'tone',
type: 'select',
defaultValue: 'info',
options: ['info', 'warning', 'error'],
},
{
name: 'content',
type: 'richText',
editor: lexicalEditor({}),
},
],
jsx: {
export: ({ fields, lexicalToMarkdown }) => ({
children: lexicalToMarkdown({ editorState: fields.content }),
props: fields.tone ? { tone: fields.tone } : {},
}),
import: ({ children, markdownToLexical, props }) => ({
content: markdownToLexical({ markdown: children }),
tone: props?.tone,
}),
},
}
export const Pages: CollectionConfig = {
slug: 'pages',
fields: [
{
name: 'content',
type: 'richText',
editor: lexicalEditor({
features: ({ defaultFeatures }) => [
...defaultFeatures,
BlocksFeature({ blocks: [BannerBlock] }),
],
}),
},
{
name: 'markdown',
type: 'textarea',
hooks: {
afterRead: [
(args) => {
const data = args.siblingData.content as SerializedEditorState | undefined
const siblingFields =
'siblingFields' in args && Array.isArray(args.siblingFields)
? args.siblingFields
: []
const field = siblingFields.find(
(candidate) => isNamedSanitizedRichTextField(candidate, 'content'),
)
if (!data || !field) {
return ''
}
return convertLexicalToMarkdown({
data,
editorConfig: editorConfigFactory.fromField({ field }),
})
},
],
beforeChange: [
({ siblingData }) => {
delete siblingData.markdown
return null
},
],
},
},
],
}