@neuronection/assistant-ui 0.22.0 → 0.23.0

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/CHANGELOG.md CHANGED
@@ -1,5 +1,22 @@
1
1
  # @neuronection/assistant-ui
2
2
 
3
+ ## 0.23.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [`9be7c37`](https://github.com/neuronection/assistant-ui/commit/9be7c37787b25b658ff01573d13b9c540a9e6c67) Thanks [@constLiakos](https://github.com/constLiakos)! - RichTextEditor becomes hostable by full apps: `extensions` is now a **full
8
+ override** of the built-in `[StarterKit, Markdown]` set (apps declare their
9
+ complete extension set), and three composition props land — `contentClassName`
10
+ (merged onto the editable region), `onReady` (editor instance on create,
11
+ `null` on destroy — the app handle for commands and event wiring), and
12
+ `headingLevels` (one toggle per level; `labels.heading` is now
13
+ `(level) => string`, default `Heading ${level}`). History buttons now reflect
14
+ undo/redo availability and disable while there is nothing to undo/redo. Also
15
+ fixes a spurious mount-time `onValueChange`: the editable-state effect no
16
+ longer calls `setEditable` when it is already correct (tiptap v3 emits an
17
+ update event from `setEditable`, which surfaced the parsed value back to the
18
+ app on mount).
19
+
3
20
  ## 0.22.0
4
21
 
5
22
  ### Minor Changes
@@ -138,11 +138,16 @@ var RichTextEditor = React.forwardRef(
138
138
  editor.off("update", handler);
139
139
  };
140
140
  }, [editor, isMounted]);
141
+ const editableRef = React.useRef(!disabled);
141
142
  React.useEffect(() => {
142
143
  if (editor === null || editor.isDestroyed) {
143
144
  return;
144
145
  }
145
- editor.setEditable(!disabled);
146
+ if (editableRef.current === !disabled) {
147
+ return;
148
+ }
149
+ editableRef.current = !disabled;
150
+ editor.setEditable(!disabled, false);
146
151
  }, [editor, disabled]);
147
152
  React.useEffect(() => {
148
153
  if (editor === null || editor.isDestroyed) {
@@ -288,5 +293,5 @@ var RichTextEditor = React.forwardRef(
288
293
  );
289
294
 
290
295
  export { RichTextEditor };
291
- //# sourceMappingURL=chunk-4UJKXTWY.js.map
292
- //# sourceMappingURL=chunk-4UJKXTWY.js.map
296
+ //# sourceMappingURL=chunk-AY77TWLT.js.map
297
+ //# sourceMappingURL=chunk-AY77TWLT.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/rich-text-editor/RichTextEditor.tsx"],"names":["RichTextEditor"],"mappings":"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","file":"chunk-AY77TWLT.js","sourcesContent":["import * as React from 'react'\nimport { Editor, EditorContent, useEditor, type Extensions } from '@tiptap/react'\nimport StarterKit from '@tiptap/starter-kit'\nimport {\n Bold,\n Code,\n Heading2,\n Italic,\n List,\n ListOrdered,\n Quote,\n Redo2,\n Strikethrough,\n Undo2,\n type LucideIcon,\n} from 'lucide-react'\nimport { Markdown } from 'tiptap-markdown'\n\nimport { cn } from '../../lib/utils'\n\nexport type RichTextToolbarGroup = 'history' | 'heading' | 'format' | 'list' | 'quote'\n\nexport type RichTextHeadingLevel = 1 | 2 | 3 | 4\n\nconst DEFAULT_TOOLBAR: RichTextToolbarGroup[] = [\n 'history',\n 'heading',\n 'format',\n 'list',\n 'quote',\n]\n\nconst DEFAULT_HEADING_LEVELS: RichTextHeadingLevel[] = [2]\n\nconst DEFAULT_EXTENSIONS: Extensions = [StarterKit, Markdown]\n\nexport interface RichTextEditorLabels {\n toolbar?: string\n bold?: string\n italic?: string\n strike?: string\n code?: string\n heading?: (level: number) => string\n bulletList?: string\n orderedList?: string\n blockquote?: string\n undo?: string\n redo?: string\n}\n\nexport interface RichTextEditorIcons {\n bold?: LucideIcon\n italic?: LucideIcon\n strike?: LucideIcon\n code?: LucideIcon\n heading?: LucideIcon\n bulletList?: LucideIcon\n orderedList?: LucideIcon\n blockquote?: LucideIcon\n undo?: LucideIcon\n redo?: LucideIcon\n}\n\nconst DEFAULT_LABELS: Required<RichTextEditorLabels> = {\n toolbar: 'Formatting',\n bold: 'Bold',\n italic: 'Italic',\n strike: 'Strikethrough',\n code: 'Code',\n heading: (level) => `Heading ${level}`,\n bulletList: 'Bulleted list',\n orderedList: 'Numbered list',\n blockquote: 'Quote',\n undo: 'Undo',\n redo: 'Redo',\n}\n\nconst DEFAULT_ICONS: Required<RichTextEditorIcons> = {\n bold: Bold,\n italic: Italic,\n strike: Strikethrough,\n code: Code,\n heading: Heading2,\n bulletList: List,\n orderedList: ListOrdered,\n blockquote: Quote,\n undo: Undo2,\n redo: Redo2,\n}\n\ntype FormatKey =\n | 'bold'\n | 'italic'\n | 'strike'\n | 'code'\n | 'bulletList'\n | 'orderedList'\n | 'blockquote'\n | 'undo'\n | 'redo'\n\nexport interface RichTextEditorProps {\n value: string\n onValueChange: (markdown: string) => void\n ariaLabel: string\n disabled?: boolean\n toolbar?: RichTextToolbarGroup[] | false\n /** App-owned controls at the end of the toolbar; render-prop form receives the editor. */\n toolbarExtra?: React.ReactNode | ((editor: Editor | null) => React.ReactNode)\n /** Full override of the document extension set; default is `[StarterKit, Markdown]`. Apps declare their complete set. */\n extensions?: Extensions\n /** Extra classes for the editable region (merged after the built-ins via tailwind-merge). */\n contentClassName?: string\n /** Called once when the editor instance is created and again with `null` on destroy/unmount. */\n onReady?: (editor: Editor | null) => void\n /** Heading toggles rendered for the `heading` toolbar group, one button per level. */\n headingLevels?: RichTextHeadingLevel[]\n /** Map incoming app-domain markdown before it reaches the document. */\n parseMarkdown?: (markdown: string) => string\n /** Map the serialized document before it is emitted / echo-compared. */\n serializeMarkdown?: (markdown: string) => string\n labels?: Partial<RichTextEditorLabels>\n icons?: Partial<RichTextEditorIcons>\n className?: string\n}\n\nfunction getMarkdown(editor: Editor): string {\n const storage = editor.storage as { markdown?: { getMarkdown?: () => string } }\n return storage.markdown?.getMarkdown?.() ?? ''\n}\n\nfunction applyExternalValue(editor: Editor, markdown: string): void {\n const hadFocus = editor.isFocused\n const caret = editor.state.selection.head\n editor.commands.setContent(markdown, { emitUpdate: false })\n if (hadFocus) {\n editor.commands.setTextSelection(Math.min(caret, editor.state.doc.content.size))\n editor.commands.focus()\n }\n}\n\nexport const RichTextEditor = React.forwardRef<HTMLDivElement, RichTextEditorProps>(\n function RichTextEditor(\n {\n value,\n onValueChange,\n ariaLabel,\n disabled = false,\n toolbar = DEFAULT_TOOLBAR,\n toolbarExtra,\n extensions,\n contentClassName,\n onReady,\n headingLevels,\n parseMarkdown,\n serializeMarkdown,\n labels,\n icons,\n className,\n },\n ref,\n ) {\n const mergedLabels = { ...DEFAULT_LABELS, ...labels }\n const mergedIcons = { ...DEFAULT_ICONS, ...icons }\n const resolvedExtensions = React.useMemo(\n () => extensions ?? DEFAULT_EXTENSIONS,\n [extensions],\n )\n const levels = headingLevels ?? DEFAULT_HEADING_LEVELS\n const lastEmittedRef = React.useRef<string>(value)\n const onValueChangeRef = React.useRef(onValueChange)\n onValueChangeRef.current = onValueChange\n const onReadyRef = React.useRef(onReady)\n onReadyRef.current = onReady\n const hooksRef = React.useRef({ parseMarkdown, serializeMarkdown })\n hooksRef.current = { parseMarkdown, serializeMarkdown }\n const [, bump] = React.useReducer((count: number) => count + 1, 0)\n\n const toDocument = React.useCallback(\n (markdown: string) => (parseMarkdown ? parseMarkdown(markdown) : markdown),\n [parseMarkdown],\n )\n const toApp = React.useCallback(\n (markdown: string) => (serializeMarkdown ? serializeMarkdown(markdown) : markdown),\n [serializeMarkdown],\n )\n\n const editor = useEditor(\n {\n extensions: resolvedExtensions,\n content: toDocument(value),\n editable: !disabled,\n immediatelyRender: false,\n editorProps: {\n attributes: {\n 'aria-label': ariaLabel,\n class: cn(\n 'as-rich-text-editor__content min-h-24 w-full bg-transparent px-3 py-2 text-sm text-[var(--as-fg)] outline-none',\n contentClassName,\n ),\n },\n },\n onUpdate: ({ editor: current }) => {\n const markdown = toApp(getMarkdown(current))\n lastEmittedRef.current = markdown\n onValueChangeRef.current(markdown)\n },\n },\n )\n\n const isMounted = editor !== null\n\n React.useEffect(() => {\n if (editor === null) {\n return\n }\n onReadyRef.current?.(editor)\n return () => {\n onReadyRef.current?.(null)\n }\n }, [editor])\n\n React.useEffect(() => {\n if (!isMounted || editor === null) {\n return\n }\n const handler = () => bump()\n editor.on('transaction', handler)\n editor.on('update', handler)\n return () => {\n editor.off('transaction', handler)\n editor.off('update', handler)\n }\n }, [editor, isMounted])\n\n const editableRef = React.useRef(!disabled)\n React.useEffect(() => {\n if (editor === null || editor.isDestroyed) {\n return\n }\n if (editableRef.current === !disabled) {\n return\n }\n editableRef.current = !disabled\n editor.setEditable(!disabled, false)\n }, [editor, disabled])\n\n React.useEffect(() => {\n if (editor === null || editor.isDestroyed) {\n return\n }\n if (value === lastEmittedRef.current) {\n return\n }\n const current = toApp(getMarkdown(editor))\n if (value === current) {\n lastEmittedRef.current = value\n return\n }\n applyExternalValue(editor, toDocument(value))\n lastEmittedRef.current = value\n }, [editor, value, toApp, toDocument])\n\n const groups = toolbar === false ? [] : (toolbar ?? DEFAULT_TOOLBAR)\n\n const buttonClass = (active: boolean) =>\n cn(\n 'rounded p-1.5 text-[var(--as-muted-fg)] transition-colors hover:text-[var(--as-fg)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--as-focus-ring)] disabled:cursor-not-allowed disabled:opacity-50',\n active && 'bg-[var(--as-surface-active)] text-[var(--as-fg)]',\n )\n\n const renderButton = (\n key: FormatKey,\n group: RichTextToolbarGroup,\n onClick: () => void,\n active: boolean,\n buttonDisabled = disabled,\n ) => {\n const Icon = mergedIcons[key]\n const label = mergedLabels[key]\n return (\n <button\n key={`${group}-${key}`}\n type=\"button\"\n aria-label={label}\n aria-pressed={active}\n title={label}\n disabled={buttonDisabled}\n className={buttonClass(active)}\n onClick={onClick}\n >\n <Icon className=\"size-4\" aria-hidden />\n </button>\n )\n }\n\n const historyDisabled = (can: 'undo' | 'redo') =>\n disabled || editor === null || editor.can()[can]() !== true\n\n const renderHeadingButton = (level: RichTextHeadingLevel) => {\n const Icon = mergedIcons.heading\n const label = mergedLabels.heading(level)\n return (\n <button\n key={`heading-${level}`}\n type=\"button\"\n aria-label={label}\n aria-pressed={editor?.isActive('heading', { level }) === true}\n title={label}\n disabled={disabled}\n className={buttonClass(editor?.isActive('heading', { level }) === true)}\n onClick={() => editor?.chain().focus().toggleHeading({ level }).run()}\n >\n <Icon className=\"size-4\" aria-hidden />\n </button>\n )\n }\n\n return (\n <div\n ref={ref}\n data-as=\"rich-text-editor\"\n className={cn(\n 'w-full rounded-[var(--as-radius)] border border-[var(--as-border)] bg-[var(--as-surface)] text-[var(--as-fg)] focus-within:border-[var(--as-focus-ring)]',\n disabled && 'opacity-50',\n className,\n )}\n >\n {groups.length > 0 || toolbarExtra ? (\n <div\n role=\"toolbar\"\n aria-label={mergedLabels.toolbar}\n className=\"flex flex-wrap items-center gap-0.5 border-b border-[var(--as-border)] p-1\"\n >\n {groups.includes('history')\n ? renderButton(\n 'undo',\n 'history',\n () => editor?.chain().focus().undo().run(),\n false,\n historyDisabled('undo'),\n )\n : null}\n {groups.includes('history')\n ? renderButton(\n 'redo',\n 'history',\n () => editor?.chain().focus().redo().run(),\n false,\n historyDisabled('redo'),\n )\n : null}\n {groups.includes('heading') ? levels.map((level) => renderHeadingButton(level)) : null}\n {groups.includes('format')\n ? renderButton(\n 'bold',\n 'format',\n () => editor?.chain().focus().toggleBold().run(),\n editor?.isActive('bold') === true,\n )\n : null}\n {groups.includes('format')\n ? renderButton(\n 'italic',\n 'format',\n () => editor?.chain().focus().toggleItalic().run(),\n editor?.isActive('italic') === true,\n )\n : null}\n {groups.includes('format')\n ? renderButton(\n 'strike',\n 'format',\n () => editor?.chain().focus().toggleStrike().run(),\n editor?.isActive('strike') === true,\n )\n : null}\n {groups.includes('format')\n ? renderButton(\n 'code',\n 'format',\n () => editor?.chain().focus().toggleCode().run(),\n editor?.isActive('code') === true,\n )\n : null}\n {groups.includes('list')\n ? renderButton(\n 'bulletList',\n 'list',\n () => editor?.chain().focus().toggleBulletList().run(),\n editor?.isActive('bulletList') === true,\n )\n : null}\n {groups.includes('list')\n ? renderButton(\n 'orderedList',\n 'list',\n () => editor?.chain().focus().toggleOrderedList().run(),\n editor?.isActive('orderedList') === true,\n )\n : null}\n {groups.includes('quote')\n ? renderButton(\n 'blockquote',\n 'quote',\n () => editor?.chain().focus().toggleBlockquote().run(),\n editor?.isActive('blockquote') === true,\n )\n : null}\n {typeof toolbarExtra === 'function' ? toolbarExtra(editor) : toolbarExtra}\n </div>\n ) : null}\n <EditorContent editor={editor} />\n </div>\n )\n },\n)\n"]}
package/dist/index.js CHANGED
@@ -29,7 +29,7 @@ export { FieldLabel } from './chunk-I5J6SDLK.js';
29
29
  export { InfoButton } from './chunk-OT6EQFMP.js';
30
30
  export { PopoverButton } from './chunk-BE3XFZWU.js';
31
31
  export { Input } from './chunk-M4V7XHL7.js';
32
- export { RichTextEditor } from './chunk-4UJKXTWY.js';
32
+ export { RichTextEditor } from './chunk-AY77TWLT.js';
33
33
  export { CopyButton } from './chunk-CZ2BL2ZL.js';
34
34
  export { ContextMenu } from './chunk-YIGLULRG.js';
35
35
  export { ActionMenu, Menu, MenuCheckboxItem, MenuContent, MenuGroup, MenuItem, MenuLabel, MenuSeparator, MenuTrigger } from './chunk-XSJ3TWWZ.js';
@@ -1,3 +1,3 @@
1
- export { RichTextEditor } from './chunk-4UJKXTWY.js';
1
+ export { RichTextEditor } from './chunk-AY77TWLT.js';
2
2
  //# sourceMappingURL=rich-text-editor.js.map
3
3
  //# sourceMappingURL=rich-text-editor.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neuronection/assistant-ui",
3
- "version": "0.22.0",
3
+ "version": "0.23.0",
4
4
  "description": "Shared React component library for the Assistant family (career-, study-, health-assistant). Family look by default, app-flavored via CSS-variable tokens.",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/rich-text-editor/RichTextEditor.tsx"],"names":["RichTextEditor"],"mappings":"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","file":"chunk-4UJKXTWY.js","sourcesContent":["import * as React from 'react'\nimport { Editor, EditorContent, useEditor, type Extensions } from '@tiptap/react'\nimport StarterKit from '@tiptap/starter-kit'\nimport {\n Bold,\n Code,\n Heading2,\n Italic,\n List,\n ListOrdered,\n Quote,\n Redo2,\n Strikethrough,\n Undo2,\n type LucideIcon,\n} from 'lucide-react'\nimport { Markdown } from 'tiptap-markdown'\n\nimport { cn } from '../../lib/utils'\n\nexport type RichTextToolbarGroup = 'history' | 'heading' | 'format' | 'list' | 'quote'\n\nexport type RichTextHeadingLevel = 1 | 2 | 3 | 4\n\nconst DEFAULT_TOOLBAR: RichTextToolbarGroup[] = [\n 'history',\n 'heading',\n 'format',\n 'list',\n 'quote',\n]\n\nconst DEFAULT_HEADING_LEVELS: RichTextHeadingLevel[] = [2]\n\nconst DEFAULT_EXTENSIONS: Extensions = [StarterKit, Markdown]\n\nexport interface RichTextEditorLabels {\n toolbar?: string\n bold?: string\n italic?: string\n strike?: string\n code?: string\n heading?: (level: number) => string\n bulletList?: string\n orderedList?: string\n blockquote?: string\n undo?: string\n redo?: string\n}\n\nexport interface RichTextEditorIcons {\n bold?: LucideIcon\n italic?: LucideIcon\n strike?: LucideIcon\n code?: LucideIcon\n heading?: LucideIcon\n bulletList?: LucideIcon\n orderedList?: LucideIcon\n blockquote?: LucideIcon\n undo?: LucideIcon\n redo?: LucideIcon\n}\n\nconst DEFAULT_LABELS: Required<RichTextEditorLabels> = {\n toolbar: 'Formatting',\n bold: 'Bold',\n italic: 'Italic',\n strike: 'Strikethrough',\n code: 'Code',\n heading: (level) => `Heading ${level}`,\n bulletList: 'Bulleted list',\n orderedList: 'Numbered list',\n blockquote: 'Quote',\n undo: 'Undo',\n redo: 'Redo',\n}\n\nconst DEFAULT_ICONS: Required<RichTextEditorIcons> = {\n bold: Bold,\n italic: Italic,\n strike: Strikethrough,\n code: Code,\n heading: Heading2,\n bulletList: List,\n orderedList: ListOrdered,\n blockquote: Quote,\n undo: Undo2,\n redo: Redo2,\n}\n\ntype FormatKey =\n | 'bold'\n | 'italic'\n | 'strike'\n | 'code'\n | 'bulletList'\n | 'orderedList'\n | 'blockquote'\n | 'undo'\n | 'redo'\n\nexport interface RichTextEditorProps {\n value: string\n onValueChange: (markdown: string) => void\n ariaLabel: string\n disabled?: boolean\n toolbar?: RichTextToolbarGroup[] | false\n /** App-owned controls at the end of the toolbar; render-prop form receives the editor. */\n toolbarExtra?: React.ReactNode | ((editor: Editor | null) => React.ReactNode)\n /** Full override of the document extension set; default is `[StarterKit, Markdown]`. Apps declare their complete set. */\n extensions?: Extensions\n /** Extra classes for the editable region (merged after the built-ins via tailwind-merge). */\n contentClassName?: string\n /** Called once when the editor instance is created and again with `null` on destroy/unmount. */\n onReady?: (editor: Editor | null) => void\n /** Heading toggles rendered for the `heading` toolbar group, one button per level. */\n headingLevels?: RichTextHeadingLevel[]\n /** Map incoming app-domain markdown before it reaches the document. */\n parseMarkdown?: (markdown: string) => string\n /** Map the serialized document before it is emitted / echo-compared. */\n serializeMarkdown?: (markdown: string) => string\n labels?: Partial<RichTextEditorLabels>\n icons?: Partial<RichTextEditorIcons>\n className?: string\n}\n\nfunction getMarkdown(editor: Editor): string {\n const storage = editor.storage as { markdown?: { getMarkdown?: () => string } }\n return storage.markdown?.getMarkdown?.() ?? ''\n}\n\nfunction applyExternalValue(editor: Editor, markdown: string): void {\n const hadFocus = editor.isFocused\n const caret = editor.state.selection.head\n editor.commands.setContent(markdown, { emitUpdate: false })\n if (hadFocus) {\n editor.commands.setTextSelection(Math.min(caret, editor.state.doc.content.size))\n editor.commands.focus()\n }\n}\n\nexport const RichTextEditor = React.forwardRef<HTMLDivElement, RichTextEditorProps>(\n function RichTextEditor(\n {\n value,\n onValueChange,\n ariaLabel,\n disabled = false,\n toolbar = DEFAULT_TOOLBAR,\n toolbarExtra,\n extensions,\n contentClassName,\n onReady,\n headingLevels,\n parseMarkdown,\n serializeMarkdown,\n labels,\n icons,\n className,\n },\n ref,\n ) {\n const mergedLabels = { ...DEFAULT_LABELS, ...labels }\n const mergedIcons = { ...DEFAULT_ICONS, ...icons }\n const resolvedExtensions = React.useMemo(\n () => extensions ?? DEFAULT_EXTENSIONS,\n [extensions],\n )\n const levels = headingLevels ?? DEFAULT_HEADING_LEVELS\n const lastEmittedRef = React.useRef<string>(value)\n const onValueChangeRef = React.useRef(onValueChange)\n onValueChangeRef.current = onValueChange\n const onReadyRef = React.useRef(onReady)\n onReadyRef.current = onReady\n const hooksRef = React.useRef({ parseMarkdown, serializeMarkdown })\n hooksRef.current = { parseMarkdown, serializeMarkdown }\n const [, bump] = React.useReducer((count: number) => count + 1, 0)\n\n const toDocument = React.useCallback(\n (markdown: string) => (parseMarkdown ? parseMarkdown(markdown) : markdown),\n [parseMarkdown],\n )\n const toApp = React.useCallback(\n (markdown: string) => (serializeMarkdown ? serializeMarkdown(markdown) : markdown),\n [serializeMarkdown],\n )\n\n const editor = useEditor(\n {\n extensions: resolvedExtensions,\n content: toDocument(value),\n editable: !disabled,\n immediatelyRender: false,\n editorProps: {\n attributes: {\n 'aria-label': ariaLabel,\n class: cn(\n 'as-rich-text-editor__content min-h-24 w-full bg-transparent px-3 py-2 text-sm text-[var(--as-fg)] outline-none',\n contentClassName,\n ),\n },\n },\n onUpdate: ({ editor: current }) => {\n const markdown = toApp(getMarkdown(current))\n lastEmittedRef.current = markdown\n onValueChangeRef.current(markdown)\n },\n },\n )\n\n const isMounted = editor !== null\n\n React.useEffect(() => {\n if (editor === null) {\n return\n }\n onReadyRef.current?.(editor)\n return () => {\n onReadyRef.current?.(null)\n }\n }, [editor])\n\n React.useEffect(() => {\n if (!isMounted || editor === null) {\n return\n }\n const handler = () => bump()\n editor.on('transaction', handler)\n editor.on('update', handler)\n return () => {\n editor.off('transaction', handler)\n editor.off('update', handler)\n }\n }, [editor, isMounted])\n\n React.useEffect(() => {\n if (editor === null || editor.isDestroyed) {\n return\n }\n editor.setEditable(!disabled)\n }, [editor, disabled])\n\n React.useEffect(() => {\n if (editor === null || editor.isDestroyed) {\n return\n }\n if (value === lastEmittedRef.current) {\n return\n }\n const current = toApp(getMarkdown(editor))\n if (value === current) {\n lastEmittedRef.current = value\n return\n }\n applyExternalValue(editor, toDocument(value))\n lastEmittedRef.current = value\n }, [editor, value, toApp, toDocument])\n\n const groups = toolbar === false ? [] : (toolbar ?? DEFAULT_TOOLBAR)\n\n const buttonClass = (active: boolean) =>\n cn(\n 'rounded p-1.5 text-[var(--as-muted-fg)] transition-colors hover:text-[var(--as-fg)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--as-focus-ring)] disabled:cursor-not-allowed disabled:opacity-50',\n active && 'bg-[var(--as-surface-active)] text-[var(--as-fg)]',\n )\n\n const renderButton = (\n key: FormatKey,\n group: RichTextToolbarGroup,\n onClick: () => void,\n active: boolean,\n buttonDisabled = disabled,\n ) => {\n const Icon = mergedIcons[key]\n const label = mergedLabels[key]\n return (\n <button\n key={`${group}-${key}`}\n type=\"button\"\n aria-label={label}\n aria-pressed={active}\n title={label}\n disabled={buttonDisabled}\n className={buttonClass(active)}\n onClick={onClick}\n >\n <Icon className=\"size-4\" aria-hidden />\n </button>\n )\n }\n\n const historyDisabled = (can: 'undo' | 'redo') =>\n disabled || editor === null || editor.can()[can]() !== true\n\n const renderHeadingButton = (level: RichTextHeadingLevel) => {\n const Icon = mergedIcons.heading\n const label = mergedLabels.heading(level)\n return (\n <button\n key={`heading-${level}`}\n type=\"button\"\n aria-label={label}\n aria-pressed={editor?.isActive('heading', { level }) === true}\n title={label}\n disabled={disabled}\n className={buttonClass(editor?.isActive('heading', { level }) === true)}\n onClick={() => editor?.chain().focus().toggleHeading({ level }).run()}\n >\n <Icon className=\"size-4\" aria-hidden />\n </button>\n )\n }\n\n return (\n <div\n ref={ref}\n data-as=\"rich-text-editor\"\n className={cn(\n 'w-full rounded-[var(--as-radius)] border border-[var(--as-border)] bg-[var(--as-surface)] text-[var(--as-fg)] focus-within:border-[var(--as-focus-ring)]',\n disabled && 'opacity-50',\n className,\n )}\n >\n {groups.length > 0 || toolbarExtra ? (\n <div\n role=\"toolbar\"\n aria-label={mergedLabels.toolbar}\n className=\"flex flex-wrap items-center gap-0.5 border-b border-[var(--as-border)] p-1\"\n >\n {groups.includes('history')\n ? renderButton(\n 'undo',\n 'history',\n () => editor?.chain().focus().undo().run(),\n false,\n historyDisabled('undo'),\n )\n : null}\n {groups.includes('history')\n ? renderButton(\n 'redo',\n 'history',\n () => editor?.chain().focus().redo().run(),\n false,\n historyDisabled('redo'),\n )\n : null}\n {groups.includes('heading') ? levels.map((level) => renderHeadingButton(level)) : null}\n {groups.includes('format')\n ? renderButton(\n 'bold',\n 'format',\n () => editor?.chain().focus().toggleBold().run(),\n editor?.isActive('bold') === true,\n )\n : null}\n {groups.includes('format')\n ? renderButton(\n 'italic',\n 'format',\n () => editor?.chain().focus().toggleItalic().run(),\n editor?.isActive('italic') === true,\n )\n : null}\n {groups.includes('format')\n ? renderButton(\n 'strike',\n 'format',\n () => editor?.chain().focus().toggleStrike().run(),\n editor?.isActive('strike') === true,\n )\n : null}\n {groups.includes('format')\n ? renderButton(\n 'code',\n 'format',\n () => editor?.chain().focus().toggleCode().run(),\n editor?.isActive('code') === true,\n )\n : null}\n {groups.includes('list')\n ? renderButton(\n 'bulletList',\n 'list',\n () => editor?.chain().focus().toggleBulletList().run(),\n editor?.isActive('bulletList') === true,\n )\n : null}\n {groups.includes('list')\n ? renderButton(\n 'orderedList',\n 'list',\n () => editor?.chain().focus().toggleOrderedList().run(),\n editor?.isActive('orderedList') === true,\n )\n : null}\n {groups.includes('quote')\n ? renderButton(\n 'blockquote',\n 'quote',\n () => editor?.chain().focus().toggleBlockquote().run(),\n editor?.isActive('blockquote') === true,\n )\n : null}\n {typeof toolbarExtra === 'function' ? toolbarExtra(editor) : toolbarExtra}\n </div>\n ) : null}\n <EditorContent editor={editor} />\n </div>\n )\n },\n)\n"]}