Skip to content

Commit

Permalink
feat: support inserting JSX nodes with children
Browse files Browse the repository at this point in the history
  • Loading branch information
petyosi committed Nov 2, 2023
1 parent b958500 commit b303a99
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 22 deletions.
37 changes: 26 additions & 11 deletions src/examples/jsx.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,17 +53,32 @@ const jsxComponentDescriptors: JsxComponentDescriptor[] = [
const InsertMyLeaf = () => {
const insertJsx = jsxPluginHooks.usePublisher('insertJsx')
return (
<Button
onClick={() =>
insertJsx({
name: 'MyLeaf',
kind: 'text',
props: { foo: 'bar', bar: 'baz' }
})
}
>
Leaf
</Button>
<>
<Button
onClick={() =>
insertJsx({
name: 'MyLeaf',
kind: 'text',
props: { foo: 'bar', bar: 'baz' }
})
}
>
Leaf
</Button>

<Button
onClick={() =>
insertJsx({
name: 'MyLeaf',
kind: 'text',
props: { foo: 'bar', bar: 'baz' },
children: [{ type: 'text', value: 'Hello' }]
})
}
>
Leaf with text
</Button>
</>
)
}
export const Example = () => {
Expand Down
50 changes: 40 additions & 10 deletions src/plugins/jsx/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,10 +77,28 @@ export interface JsxEditorProps {
descriptor: JsxComponentDescriptor
}

interface InsertJsxPayload {
type JsxTextPayload = {
kind: 'text'
name: string
props: Record<string, string>
children?: MdxJsxTextElement['children']
}

type JsxFlowPayload = {
kind: 'flow'
name: string
kind: 'flow' | 'text'
props: Record<string, string>
children?: MdxJsxFlowElement['children']
}

type InsertJsxPayload = JsxTextPayload | JsxFlowPayload

function toMdastJsxAttributes(attributes: Record<string, string>): MdastJsx['attributes'] {
return Object.entries(attributes).map(([name, value]) => ({
type: 'mdxJsxAttribute',
name,
value
}))
}

/** @internal */
Expand All @@ -91,14 +109,26 @@ export const jsxSystem = system(
r.link(
r.pipe(
insertJsx,
r.o.map(({ name, kind, props }) => {
return () =>
$createLexicalJsxNode({
name,
type: kind === 'flow' ? 'mdxJsxFlowElement' : 'mdxJsxTextElement',
attributes: Object.entries(props).map(([name, value]) => ({ type: 'mdxJsxAttribute', name, value })),
children: []
})
r.o.map(({ kind, name, children, props }) => {
return () => {
const attributes = toMdastJsxAttributes(props)

if (kind === 'flow') {
return $createLexicalJsxNode({
type: 'mdxJsxFlowElement',
name,
children: children ?? [],
attributes
})
} else {
return $createLexicalJsxNode({
type: 'mdxJsxTextElement',
name,
children: children ?? [],
attributes
})
}
}
})
),
insertDecoratorNode
Expand Down
2 changes: 1 addition & 1 deletion src/plugins/link-dialog/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ const linkDialogSystem = system(

if (url.trim() !== '') {
editor?.dispatchCommand(TOGGLE_LINK_COMMAND, { url, title })
// the dispatch command implementation fails to set the link for a fresh link creation.
// the dispatch command implementation fails to set the title for a fresh link creation.
// Work around with the code below.
setTimeout(() => {
editor?.update(() => {
Expand Down

0 comments on commit b303a99

Please sign in to comment.