@panneau/editor 5.0.0-alpha.12 → 5.0.0-alpha.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/Toolbar.d.ts.map +1 -1
- package/dist/Toolbar.js +6 -6
- package/dist/Toolbar.js.map +1 -1
- package/package.json +5 -5
package/dist/Toolbar.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Toolbar.d.ts","sourceRoot":"","sources":["../src/Toolbar.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAY3C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAKvD,OAAO,EAAE,KAAK,cAAc,EAAkB,MAAM,WAAW,CAAC;AAChE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAG9C,MAAM,WAAW,YAAY;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,uFAAuF;IACvF,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IACzB,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;IAC5B,MAAM,EAAE,SAAS,aAAa,EAAE,CAAC;IACjC,MAAM,EAAE,WAAW,CAAC;IACpB,8EAA8E;IAC9E,OAAO,EAAE,SAAS,cAAc,EAAE,CAAC;CACtC;AAqED;;;GAGG;AACH,wBAAgB,OAAO,CAAC,EACpB,MAAM,EACN,KAAK,EACL,QAAQ,EACR,MAAM,EAAE,WAAW,EACnB,MAAM,EACN,OAAO,GACV,EAAE,YAAY,+
|
|
1
|
+
{"version":3,"file":"Toolbar.d.ts","sourceRoot":"","sources":["../src/Toolbar.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAY3C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAKvD,OAAO,EAAE,KAAK,cAAc,EAAkB,MAAM,WAAW,CAAC;AAChE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAG9C,MAAM,WAAW,YAAY;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,uFAAuF;IACvF,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IACzB,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;IAC5B,MAAM,EAAE,SAAS,aAAa,EAAE,CAAC;IACjC,MAAM,EAAE,WAAW,CAAC;IACpB,8EAA8E;IAC9E,OAAO,EAAE,SAAS,cAAc,EAAE,CAAC;CACtC;AAqED;;;GAGG;AACH,wBAAgB,OAAO,CAAC,EACpB,MAAM,EACN,KAAK,EACL,QAAQ,EACR,MAAM,EAAE,WAAW,EACnB,MAAM,EACN,OAAO,GACV,EAAE,YAAY,+BAqLd"}
|
package/dist/Toolbar.js
CHANGED
|
@@ -101,7 +101,7 @@ function Toolbar$1(t0) {
|
|
|
101
101
|
}]] : [];
|
|
102
102
|
})),
|
|
103
103
|
textStyle: getTextStyle(current),
|
|
104
|
-
canSetTextStyle: current.can().setParagraph(),
|
|
104
|
+
canSetTextStyle: current.can().setParagraph() || headings.some((level) => current.can().setHeading({ level })),
|
|
105
105
|
style: (() => {
|
|
106
106
|
const active = getActiveStyle(current.state, blockStyles);
|
|
107
107
|
return active !== null ? blockStyles.indexOf(active) : -1;
|
|
@@ -136,16 +136,16 @@ function Toolbar$1(t0) {
|
|
|
136
136
|
options: [{
|
|
137
137
|
value: "paragraph",
|
|
138
138
|
label: intl.formatMessage(editorMessages.paragraph)
|
|
139
|
-
}, ...levels.map((
|
|
140
|
-
value: `h${String(
|
|
141
|
-
label: intl.formatMessage(editorMessages.heading, { level })
|
|
139
|
+
}, ...levels.map((level_0) => ({
|
|
140
|
+
value: `h${String(level_0)}`,
|
|
141
|
+
label: intl.formatMessage(editorMessages.heading, { level: level_0 })
|
|
142
142
|
}))],
|
|
143
143
|
value: textStyle,
|
|
144
144
|
onChange: (value) => {
|
|
145
145
|
if (value === "paragraph") editor.chain().focus().setParagraph().run();
|
|
146
146
|
else if (typeof value === "string") {
|
|
147
|
-
const
|
|
148
|
-
if (
|
|
147
|
+
const level_1 = Number(value.slice(1));
|
|
148
|
+
if (level_1 >= 1 && level_1 <= 6) editor.chain().focus().setHeading({ level: level_1 }).run();
|
|
149
149
|
}
|
|
150
150
|
}
|
|
151
151
|
}, key);
|
package/dist/Toolbar.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Toolbar.js","names":["Editor","useEditorState","Link","useState","Button","AriaButton","Toolbar","AriaToolbar","Separator","ToggleButton","editorMessages","messages","RichTextStyle","IconComponent","Select","Tooltip","usePanneauIntl","LinkDialog","styles","RichTextButton","builtInButtons","NewTabLinks","applyStyle","canApplyStyle","getActiveStyle","ToolbarProps","editor","items","headings","newTab","buttons","SEPARATOR","NO_STYLE","getShownItems","known","name","shown","reduce","result","length","at","push","slice","getTextStyle","$from","state","selection","block","parent","type","String","attrs","level","ToolbarButton","t0","$","_c","label","icon","Icon","isActive","isDisabled","onPress","t1","t2","undefined","button","t3","blockStyles","intl","linkOpen","setLinkOpen","allButtons","Map","map","_temp","has","selector","current","Object","fromEntries","flatMap","name_0","button_0","get","active","disabled","textStyle","canSetTextStyle","can","setParagraph","style","indexOf","applicable","link","canLink","setLink","href","levels","includes","Number","formatMessage","toolbar","name_1","index","key","separator","select","value","paragraph","heading","chain","focus","run","level_0","setHeading","active_0","blockStyle","noStyle","style_0","styleIndex","value_0","style_1","button_1","buttonState","_c","styles","AriaButton","Toolbar","messages","_Fragment","AriaToolbar"],"sources":["../src/Toolbar.tsx"],"sourcesContent":["import type { Editor } from '@tiptap/core';\nimport { useEditorState } from '@tiptap/react';\nimport { Link } from 'lucide-react';\nimport { useState } from 'react';\nimport {\n Button as AriaButton,\n Toolbar as AriaToolbar,\n Separator,\n ToggleButton,\n} from 'react-aria-components';\n\nimport { editorMessages as messages } from '@panneau/intl';\nimport type { RichTextStyle } from '@panneau/protocol';\nimport { type IconComponent, Select, Tooltip, usePanneauIntl } from '@panneau/ui';\n\nimport { LinkDialog } from './LinkDialog';\nimport styles from './RichTextField.module.css';\nimport { type RichTextButton, builtInButtons } from './buttons';\nimport type { NewTabLinks } from './settings';\nimport { applyStyle, canApplyStyle, getActiveStyle } from './styles';\n\nexport interface ToolbarProps {\n editor: Editor;\n /** The items, in order: built-in names, names of `buttons`, and `|` between groups. */\n items: readonly string[];\n headings: readonly number[];\n styles: readonly RichTextStyle[];\n newTab: NewTabLinks;\n /** Buttons of plugins. One with the name of a built-in button replaces it. */\n buttons: readonly RichTextButton[];\n}\n\nconst SEPARATOR = '|';\nconst NO_STYLE = 'none';\n\n/** The items that show: known ones, without separators at the ends or next to each other. */\nfunction getShownItems(\n items: readonly string[],\n known: (name: string) => boolean,\n): readonly string[] {\n const shown = items.reduce<string[]>((result, name) => {\n if (name === SEPARATOR ? result.length > 0 && result.at(-1) !== SEPARATOR : known(name)) {\n result.push(name);\n }\n return result;\n }, []);\n return shown.at(-1) === SEPARATOR ? shown.slice(0, -1) : shown;\n}\n\n/** The block of the selection, as the text style select names it: `paragraph`, `h2`. */\nfunction getTextStyle(editor: Editor): string | null {\n const { $from } = editor.state.selection;\n const block = $from.parent;\n if (block.type.name === 'heading') {\n return `h${String(block.attrs.level)}`;\n }\n return block.type.name === 'paragraph' ? 'paragraph' : null;\n}\n\nfunction ToolbarButton({\n label,\n icon: Icon,\n isActive,\n isDisabled,\n onPress,\n}: {\n label: string;\n icon: IconComponent;\n isActive: boolean | undefined;\n isDisabled: boolean;\n onPress: () => void;\n}) {\n const icon = <Icon size={16} aria-hidden />;\n return (\n <Tooltip content={label}>\n {isActive !== undefined ? (\n <ToggleButton\n className={styles.button}\n aria-label={label}\n isSelected={isActive}\n isDisabled={isDisabled}\n onChange={onPress}\n >\n {icon}\n </ToggleButton>\n ) : (\n <AriaButton\n className={styles.button}\n aria-label={label}\n isDisabled={isDisabled}\n onPress={onPress}\n >\n {icon}\n </AriaButton>\n )}\n </Tooltip>\n );\n}\n\n/**\n * The toolbar of the rich text field: the text style (paragraph or a heading level), the block\n * styles, marks, links, lists and the buttons of plugins, as the field's `toolbar` lists them.\n */\nexport function Toolbar({\n editor,\n items,\n headings,\n styles: blockStyles,\n newTab,\n buttons,\n}: ToolbarProps) {\n const intl = usePanneauIntl();\n const [linkOpen, setLinkOpen] = useState(false);\n const allButtons = new Map(\n [...builtInButtons, ...buttons].map((button) => [button.name, button]),\n );\n const known = (name: string) =>\n allButtons.has(name) ||\n name === 'heading' ||\n name === 'link' ||\n (name === 'style' && blockStyles.length > 0);\n const shown = getShownItems(items, known);\n\n // Only what the toolbar shows: it renders again when it changes\n const state = useEditorState({\n editor,\n selector: ({ editor: current }) => ({\n buttons: Object.fromEntries(\n shown.flatMap((name) => {\n const button = allButtons.get(name);\n return button !== undefined\n ? [\n [\n name,\n {\n active: button.isActive?.(current),\n disabled: button.isDisabled?.(current) ?? false,\n },\n ],\n ]\n : [];\n }),\n ),\n textStyle: getTextStyle(current),\n canSetTextStyle: current.can().setParagraph(),\n style: (() => {\n const active = getActiveStyle(current.state, blockStyles);\n return active !== null ? blockStyles.indexOf(active) : -1;\n })(),\n applicable: blockStyles.map((style) => canApplyStyle(current.state, style)),\n link: current.isActive('link'),\n canLink: current.can().setLink({ href: '' }),\n }),\n });\n\n const textStyle = state.textStyle;\n const levels =\n textStyle !== null && textStyle !== 'paragraph' && !headings.includes(Number(textStyle[1]))\n ? [...headings, Number(textStyle[1])]\n : headings;\n\n return (\n <>\n <AriaToolbar\n aria-label={intl.formatMessage(messages.toolbar)}\n className={styles.toolbar}\n >\n {shown.map((name, index) => {\n const key = `${name}-${String(index)}`;\n if (name === SEPARATOR) {\n return (\n <Separator\n key={key}\n orientation=\"vertical\"\n className={styles.separator}\n />\n );\n }\n if (name === 'heading') {\n return (\n <Select\n key={key}\n aria-label={intl.formatMessage(messages.textStyle)}\n className={styles.select}\n isDisabled={!state.canSetTextStyle}\n options={[\n {\n value: 'paragraph',\n label: intl.formatMessage(messages.paragraph),\n },\n ...levels.map((level) => ({\n value: `h${String(level)}`,\n label: intl.formatMessage(messages.heading, { level }),\n })),\n ]}\n value={textStyle}\n onChange={(value) => {\n if (value === 'paragraph') {\n editor.chain().focus().setParagraph().run();\n } else if (typeof value === 'string') {\n const level = Number(value.slice(1));\n if (level >= 1 && level <= 6) {\n editor\n .chain()\n .focus()\n .setHeading({\n level: level as 1 | 2 | 3 | 4 | 5 | 6,\n })\n .run();\n }\n }\n }}\n />\n );\n }\n if (name === 'style') {\n const active = state.style;\n return (\n <Select\n key={key}\n aria-label={intl.formatMessage(messages.blockStyle)}\n className={styles.select}\n options={[\n {\n value: NO_STYLE,\n label: intl.formatMessage(messages.noStyle),\n },\n ...blockStyles.map((style, styleIndex) => ({\n value: String(styleIndex),\n label: style.label,\n disabled: state.applicable[styleIndex] !== true,\n })),\n ]}\n value={active >= 0 ? String(active) : NO_STYLE}\n onChange={(value) => {\n const style =\n value === NO_STYLE ? null : blockStyles[Number(value)];\n applyStyle(editor, style ?? null, blockStyles);\n }}\n />\n );\n }\n if (name === 'link') {\n return (\n <ToolbarButton\n key={key}\n label={intl.formatMessage(messages.link)}\n icon={Link}\n isActive={state.link}\n isDisabled={!state.canLink}\n onPress={() => setLinkOpen(true)}\n />\n );\n }\n const button = allButtons.get(name);\n if (button === undefined) {\n return null;\n }\n const buttonState = state.buttons[name];\n return (\n <ToolbarButton\n key={key}\n label={\n typeof button.label === 'string'\n ? button.label\n : intl.formatMessage(button.label)\n }\n icon={button.icon}\n isActive={buttonState?.active}\n isDisabled={buttonState?.disabled === true}\n onPress={() => button.run(editor)}\n />\n );\n })}\n </AriaToolbar>\n {shown.includes('link') ? (\n <LinkDialog\n editor={editor}\n newTab={newTab}\n isOpen={linkOpen}\n onOpenChange={setLinkOpen}\n />\n ) : null}\n </>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Toolbar.js","names":["Editor","useEditorState","Link","useState","Button","AriaButton","Toolbar","AriaToolbar","Separator","ToggleButton","editorMessages","messages","RichTextStyle","IconComponent","Select","Tooltip","usePanneauIntl","LinkDialog","styles","RichTextButton","builtInButtons","NewTabLinks","applyStyle","canApplyStyle","getActiveStyle","ToolbarProps","editor","items","headings","newTab","buttons","SEPARATOR","NO_STYLE","getShownItems","known","name","shown","reduce","result","length","at","push","slice","getTextStyle","$from","state","selection","block","parent","type","String","attrs","level","ToolbarButton","t0","$","_c","label","icon","Icon","isActive","isDisabled","onPress","t1","t2","undefined","button","t3","blockStyles","intl","linkOpen","setLinkOpen","allButtons","Map","map","_temp","has","selector","current","Object","fromEntries","flatMap","name_0","button_0","get","active","disabled","textStyle","canSetTextStyle","can","setParagraph","some","setHeading","style","indexOf","applicable","link","canLink","setLink","href","levels","includes","Number","formatMessage","toolbar","name_1","index","key","separator","select","value","paragraph","level_0","heading","chain","focus","run","level_1","active_0","blockStyle","noStyle","style_0","styleIndex","value_0","style_1","button_1","buttonState","_c","styles","AriaButton","Toolbar","messages","_Fragment","AriaToolbar"],"sources":["../src/Toolbar.tsx"],"sourcesContent":["import type { Editor } from '@tiptap/core';\nimport { useEditorState } from '@tiptap/react';\nimport { Link } from 'lucide-react';\nimport { useState } from 'react';\nimport {\n Button as AriaButton,\n Toolbar as AriaToolbar,\n Separator,\n ToggleButton,\n} from 'react-aria-components';\n\nimport { editorMessages as messages } from '@panneau/intl';\nimport type { RichTextStyle } from '@panneau/protocol';\nimport { type IconComponent, Select, Tooltip, usePanneauIntl } from '@panneau/ui';\n\nimport { LinkDialog } from './LinkDialog';\nimport styles from './RichTextField.module.css';\nimport { type RichTextButton, builtInButtons } from './buttons';\nimport type { NewTabLinks } from './settings';\nimport { applyStyle, canApplyStyle, getActiveStyle } from './styles';\n\nexport interface ToolbarProps {\n editor: Editor;\n /** The items, in order: built-in names, names of `buttons`, and `|` between groups. */\n items: readonly string[];\n headings: readonly number[];\n styles: readonly RichTextStyle[];\n newTab: NewTabLinks;\n /** Buttons of plugins. One with the name of a built-in button replaces it. */\n buttons: readonly RichTextButton[];\n}\n\nconst SEPARATOR = '|';\nconst NO_STYLE = 'none';\n\n/** The items that show: known ones, without separators at the ends or next to each other. */\nfunction getShownItems(\n items: readonly string[],\n known: (name: string) => boolean,\n): readonly string[] {\n const shown = items.reduce<string[]>((result, name) => {\n if (name === SEPARATOR ? result.length > 0 && result.at(-1) !== SEPARATOR : known(name)) {\n result.push(name);\n }\n return result;\n }, []);\n return shown.at(-1) === SEPARATOR ? shown.slice(0, -1) : shown;\n}\n\n/** The block of the selection, as the text style select names it: `paragraph`, `h2`. */\nfunction getTextStyle(editor: Editor): string | null {\n const { $from } = editor.state.selection;\n const block = $from.parent;\n if (block.type.name === 'heading') {\n return `h${String(block.attrs.level)}`;\n }\n return block.type.name === 'paragraph' ? 'paragraph' : null;\n}\n\nfunction ToolbarButton({\n label,\n icon: Icon,\n isActive,\n isDisabled,\n onPress,\n}: {\n label: string;\n icon: IconComponent;\n isActive: boolean | undefined;\n isDisabled: boolean;\n onPress: () => void;\n}) {\n const icon = <Icon size={16} aria-hidden />;\n return (\n <Tooltip content={label}>\n {isActive !== undefined ? (\n <ToggleButton\n className={styles.button}\n aria-label={label}\n isSelected={isActive}\n isDisabled={isDisabled}\n onChange={onPress}\n >\n {icon}\n </ToggleButton>\n ) : (\n <AriaButton\n className={styles.button}\n aria-label={label}\n isDisabled={isDisabled}\n onPress={onPress}\n >\n {icon}\n </AriaButton>\n )}\n </Tooltip>\n );\n}\n\n/**\n * The toolbar of the rich text field: the text style (paragraph or a heading level), the block\n * styles, marks, links, lists and the buttons of plugins, as the field's `toolbar` lists them.\n */\nexport function Toolbar({\n editor,\n items,\n headings,\n styles: blockStyles,\n newTab,\n buttons,\n}: ToolbarProps) {\n const intl = usePanneauIntl();\n const [linkOpen, setLinkOpen] = useState(false);\n const allButtons = new Map(\n [...builtInButtons, ...buttons].map((button) => [button.name, button]),\n );\n const known = (name: string) =>\n allButtons.has(name) ||\n name === 'heading' ||\n name === 'link' ||\n (name === 'style' && blockStyles.length > 0);\n const shown = getShownItems(items, known);\n\n // Only what the toolbar shows: it renders again when it changes\n const state = useEditorState({\n editor,\n selector: ({ editor: current }) => ({\n buttons: Object.fromEntries(\n shown.flatMap((name) => {\n const button = allButtons.get(name);\n return button !== undefined\n ? [\n [\n name,\n {\n active: button.isActive?.(current),\n disabled: button.isDisabled?.(current) ?? false,\n },\n ],\n ]\n : [];\n }),\n ),\n textStyle: getTextStyle(current),\n // `setParagraph()` can't run in a paragraph, and `setHeading()` can't run in a heading of\n // the same level: the select is usable when the selection can take any of its styles\n canSetTextStyle:\n current.can().setParagraph() ||\n headings.some((level) =>\n current.can().setHeading({ level: level as 1 | 2 | 3 | 4 | 5 | 6 }),\n ),\n style: (() => {\n const active = getActiveStyle(current.state, blockStyles);\n return active !== null ? blockStyles.indexOf(active) : -1;\n })(),\n applicable: blockStyles.map((style) => canApplyStyle(current.state, style)),\n link: current.isActive('link'),\n canLink: current.can().setLink({ href: '' }),\n }),\n });\n\n const textStyle = state.textStyle;\n const levels =\n textStyle !== null && textStyle !== 'paragraph' && !headings.includes(Number(textStyle[1]))\n ? [...headings, Number(textStyle[1])]\n : headings;\n\n return (\n <>\n <AriaToolbar\n aria-label={intl.formatMessage(messages.toolbar)}\n className={styles.toolbar}\n >\n {shown.map((name, index) => {\n const key = `${name}-${String(index)}`;\n if (name === SEPARATOR) {\n return (\n <Separator\n key={key}\n orientation=\"vertical\"\n className={styles.separator}\n />\n );\n }\n if (name === 'heading') {\n return (\n <Select\n key={key}\n aria-label={intl.formatMessage(messages.textStyle)}\n className={styles.select}\n isDisabled={!state.canSetTextStyle}\n options={[\n {\n value: 'paragraph',\n label: intl.formatMessage(messages.paragraph),\n },\n ...levels.map((level) => ({\n value: `h${String(level)}`,\n label: intl.formatMessage(messages.heading, { level }),\n })),\n ]}\n value={textStyle}\n onChange={(value) => {\n if (value === 'paragraph') {\n editor.chain().focus().setParagraph().run();\n } else if (typeof value === 'string') {\n const level = Number(value.slice(1));\n if (level >= 1 && level <= 6) {\n editor\n .chain()\n .focus()\n .setHeading({\n level: level as 1 | 2 | 3 | 4 | 5 | 6,\n })\n .run();\n }\n }\n }}\n />\n );\n }\n if (name === 'style') {\n const active = state.style;\n return (\n <Select\n key={key}\n aria-label={intl.formatMessage(messages.blockStyle)}\n className={styles.select}\n options={[\n {\n value: NO_STYLE,\n label: intl.formatMessage(messages.noStyle),\n },\n ...blockStyles.map((style, styleIndex) => ({\n value: String(styleIndex),\n label: style.label,\n disabled: state.applicable[styleIndex] !== true,\n })),\n ]}\n value={active >= 0 ? String(active) : NO_STYLE}\n onChange={(value) => {\n const style =\n value === NO_STYLE ? null : blockStyles[Number(value)];\n applyStyle(editor, style ?? null, blockStyles);\n }}\n />\n );\n }\n if (name === 'link') {\n return (\n <ToolbarButton\n key={key}\n label={intl.formatMessage(messages.link)}\n icon={Link}\n isActive={state.link}\n isDisabled={!state.canLink}\n onPress={() => setLinkOpen(true)}\n />\n );\n }\n const button = allButtons.get(name);\n if (button === undefined) {\n return null;\n }\n const buttonState = state.buttons[name];\n return (\n <ToolbarButton\n key={key}\n label={\n typeof button.label === 'string'\n ? button.label\n : intl.formatMessage(button.label)\n }\n icon={button.icon}\n isActive={buttonState?.active}\n isDisabled={buttonState?.disabled === true}\n onPress={() => button.run(editor)}\n />\n );\n })}\n </AriaToolbar>\n {shown.includes('link') ? (\n <LinkDialog\n editor={editor}\n newTab={newTab}\n isOpen={linkOpen}\n onOpenChange={setLinkOpen}\n />\n ) : null}\n </>\n );\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@panneau/editor",
|
|
3
|
-
"version": "5.0.0-alpha.
|
|
3
|
+
"version": "5.0.0-alpha.14",
|
|
4
4
|
"description": "The rich text field of Panneau, on TipTap 3: HTML storage, a toolbar and block styles set from the definition, and extensions from plugins.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -41,10 +41,10 @@
|
|
|
41
41
|
"react-intl": "^12.0.0"
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
|
-
"@panneau/fields": "5.0.0-alpha.
|
|
45
|
-
"@panneau/intl": "5.0.0-alpha.
|
|
46
|
-
"@panneau/protocol": "5.0.0-alpha.
|
|
47
|
-
"@panneau/ui": "5.0.0-alpha.
|
|
44
|
+
"@panneau/fields": "5.0.0-alpha.14",
|
|
45
|
+
"@panneau/intl": "5.0.0-alpha.14",
|
|
46
|
+
"@panneau/protocol": "5.0.0-alpha.14",
|
|
47
|
+
"@panneau/ui": "5.0.0-alpha.14",
|
|
48
48
|
"@tiptap/extension-blockquote": "^3.32.1",
|
|
49
49
|
"@tiptap/extension-bold": "^3.32.1",
|
|
50
50
|
"@tiptap/extension-code": "^3.32.1",
|