@dxos/react-ui-editor 0.10.0 → 0.11.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/dist/lib/index.mjs +1477 -0
- package/dist/lib/index.mjs.map +1 -0
- package/dist/lib/translations.mjs +32 -0
- package/dist/lib/translations.mjs.map +1 -0
- package/dist/types/src/components/Editor/Editor.d.ts +22 -17
- package/dist/types/src/components/Editor/Editor.d.ts.map +1 -1
- package/dist/types/src/components/Editor/EditorContext.d.ts +20 -0
- package/dist/types/src/components/Editor/EditorContext.d.ts.map +1 -0
- package/dist/types/src/components/Editor/EditorView.d.ts +1 -2
- package/dist/types/src/components/Editor/EditorView.d.ts.map +1 -1
- package/dist/types/src/components/Editor/index.d.ts +2 -0
- package/dist/types/src/components/Editor/index.d.ts.map +1 -1
- package/dist/types/src/components/EditorMenuProvider/EditorMenuProvider.d.ts +7 -1
- package/dist/types/src/components/EditorMenuProvider/EditorMenuProvider.d.ts.map +1 -1
- package/dist/types/src/components/EditorMenuProvider/menu.d.ts +4 -2
- package/dist/types/src/components/EditorMenuProvider/menu.d.ts.map +1 -1
- package/dist/types/src/components/EditorMenuProvider/useEditorMenu.d.ts +7 -2
- package/dist/types/src/components/EditorMenuProvider/useEditorMenu.d.ts.map +1 -1
- package/dist/types/src/components/EditorPreviewProvider/EditorPreviewContext.d.ts +18 -0
- package/dist/types/src/components/EditorPreviewProvider/EditorPreviewContext.d.ts.map +1 -0
- package/dist/types/src/components/EditorPreviewProvider/EditorPreviewProvider.d.ts +0 -6
- package/dist/types/src/components/EditorPreviewProvider/EditorPreviewProvider.d.ts.map +1 -1
- package/dist/types/src/components/EditorPreviewProvider/index.d.ts +1 -0
- package/dist/types/src/components/EditorPreviewProvider/index.d.ts.map +1 -1
- package/dist/types/src/components/EditorToolbar/EditorToolbar.d.ts +4 -1
- package/dist/types/src/components/EditorToolbar/EditorToolbar.d.ts.map +1 -1
- package/dist/types/src/components/EditorToolbar/index.d.ts +1 -0
- package/dist/types/src/components/EditorToolbar/index.d.ts.map +1 -1
- package/dist/types/src/components/EditorToolbar/lists.d.ts.map +1 -1
- package/dist/types/src/components/EditorToolbar/view-mode.d.ts +27 -2
- package/dist/types/src/components/EditorToolbar/view-mode.d.ts.map +1 -1
- package/dist/types/src/components/index.d.ts +1 -0
- package/dist/types/src/components/index.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +0 -1
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/stories/Assistant.stories.d.ts.map +1 -0
- package/dist/types/src/stories/Automerge.stories.d.ts +16 -39
- package/dist/types/src/stories/Automerge.stories.d.ts.map +1 -1
- package/dist/types/src/stories/Blocks.stories.d.ts +10 -0
- package/dist/types/src/stories/Blocks.stories.d.ts.map +1 -0
- package/dist/types/src/stories/Comments.stories.d.ts +53 -14
- package/dist/types/src/stories/Comments.stories.d.ts.map +1 -1
- package/dist/types/src/stories/Diff.stories.d.ts +32 -0
- package/dist/types/src/stories/Diff.stories.d.ts.map +1 -0
- package/dist/types/src/stories/Experimental.stories.d.ts +1 -0
- package/dist/types/src/stories/Experimental.stories.d.ts.map +1 -1
- package/dist/types/src/stories/Folding.stories.d.ts +18 -0
- package/dist/types/src/stories/Folding.stories.d.ts.map +1 -0
- package/dist/types/src/stories/Outliner.stories.d.ts +4 -4
- package/dist/types/src/stories/Outliner.stories.d.ts.map +1 -1
- package/dist/types/src/stories/Popover.stories.d.ts +3 -3
- package/dist/types/src/stories/Popover.stories.d.ts.map +1 -1
- package/dist/types/src/stories/Suggest.stories.d.ts +27 -0
- package/dist/types/src/stories/Suggest.stories.d.ts.map +1 -0
- package/dist/types/src/stories/TrackChanges.stories.d.ts +44 -0
- package/dist/types/src/stories/TrackChanges.stories.d.ts.map +1 -0
- package/dist/types/src/stories/Widgets.stories.d.ts +12 -0
- package/dist/types/src/stories/Widgets.stories.d.ts.map +1 -1
- package/dist/types/src/stories/components/EditorStory.d.ts.map +1 -1
- package/dist/types/src/stories/components/util.d.ts +16 -0
- package/dist/types/src/stories/components/util.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +40 -83
- package/src/components/Editor/Editor.tsx +142 -35
- package/src/components/Editor/EditorContext.ts +34 -0
- package/src/components/Editor/EditorView.tsx +9 -6
- package/src/components/Editor/index.ts +3 -0
- package/src/components/EditorMenuProvider/EditorMenuProvider.tsx +98 -8
- package/src/components/EditorMenuProvider/menu.ts +4 -2
- package/src/components/EditorMenuProvider/useEditorMenu.ts +114 -29
- package/src/components/EditorPreviewProvider/EditorPreviewContext.ts +21 -0
- package/src/components/EditorPreviewProvider/EditorPreviewProvider.tsx +1 -10
- package/src/components/EditorPreviewProvider/index.ts +2 -0
- package/src/components/EditorToolbar/EditorToolbar.tsx +6 -3
- package/src/components/EditorToolbar/index.ts +1 -0
- package/src/components/EditorToolbar/lists.ts +2 -6
- package/src/components/EditorToolbar/view-mode.ts +41 -12
- package/src/components/index.ts +1 -0
- package/src/index.ts +0 -1
- package/src/{extensions → stories}/Assistant.stories.tsx +7 -2
- package/src/stories/Automerge.stories.tsx +99 -78
- package/src/stories/Blocks.stories.tsx +83 -0
- package/src/stories/Comments.stories.tsx +273 -74
- package/src/stories/Diff.stories.tsx +48 -0
- package/src/stories/EditorToolbar.stories.tsx +2 -2
- package/src/stories/Experimental.stories.tsx +13 -2
- package/src/stories/Folding.stories.tsx +120 -0
- package/src/stories/Markdown.stories.tsx +1 -1
- package/src/stories/Outliner.stories.tsx +18 -7
- package/src/stories/Popover.stories.tsx +27 -5
- package/src/stories/Suggest.stories.tsx +199 -0
- package/src/stories/TrackChanges.stories.tsx +226 -0
- package/src/stories/Widgets.stories.tsx +162 -10
- package/src/stories/components/EditorStory.tsx +15 -6
- package/src/stories/components/util.tsx +40 -2
- package/dist/lib/browser/index.mjs +0 -1676
- package/dist/lib/browser/index.mjs.map +0 -7
- package/dist/lib/browser/meta.json +0 -1
- package/dist/lib/browser/translations.mjs +0 -39
- package/dist/lib/browser/translations.mjs.map +0 -7
- package/dist/lib/node-esm/index.mjs +0 -1678
- package/dist/lib/node-esm/index.mjs.map +0 -7
- package/dist/lib/node-esm/meta.json +0 -1
- package/dist/lib/node-esm/translations.mjs +0 -41
- package/dist/lib/node-esm/translations.mjs.map +0 -7
- package/dist/types/src/extensions/Assistant.stories.d.ts.map +0 -1
- package/dist/types/src/extensions/assistant-extension.d.ts +0 -24
- package/dist/types/src/extensions/assistant-extension.d.ts.map +0 -1
- package/dist/types/src/extensions/index.d.ts +0 -2
- package/dist/types/src/extensions/index.d.ts.map +0 -1
- package/src/extensions/assistant-extension.tsx +0 -223
- package/src/extensions/index.ts +0 -5
- /package/dist/types/src/{extensions → stories}/Assistant.stories.d.ts +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../../src/components/Editor/controller.ts","../../src/components/Editor/EditorContext.ts","../../src/components/EditorMenuProvider/menu.ts","../../src/components/EditorMenuProvider/popover.ts","../../src/components/EditorMenuProvider/menu-presets.ts","../../src/components/EditorMenuProvider/EditorMenuProvider.tsx","../../src/components/EditorMenuProvider/useEditorMenu.ts","../../src/components/EditorToolbar/blocks.ts","../../src/components/EditorToolbar/formatting.ts","../../src/components/EditorToolbar/headings.ts","../../src/components/EditorToolbar/image.ts","../../src/components/EditorToolbar/lists.ts","../../src/components/EditorToolbar/search.ts","../../src/components/EditorToolbar/view-mode.ts","../../src/components/EditorToolbar/EditorToolbar.tsx","../../src/hooks/useBasicMarkdownExtensions.ts","../../src/hooks/useTextEditor.ts","../../src/components/Editor/EditorView.tsx","../../src/components/Editor/Editor.tsx","../../src/components/EditorPreviewProvider/EditorPreviewContext.ts","../../src/components/EditorPreviewProvider/EditorPreviewProvider.tsx"],"sourcesContent":["//\n// Copyright 2025 DXOS.org\n//\n\nimport { type EditorView } from '@codemirror/view';\n\nexport interface EditorController {\n get view(): EditorView | null;\n getText: () => string;\n setText: (text: string, focus?: boolean) => void;\n focus: () => void;\n}\n\n// Hide `view` from own-enumerable traversal. Controllers are passed through React props/context, and the\n// live `EditorView` reaches the global `window` via `view.observer.win` (CodeMirror's DOMObserver). React\n// 19.2's dev render-logger walks changed props' object graphs and would otherwise descend into `window`,\n// enumerate `window[0]` (a cross-origin iframe) and throw SecurityError. Direct access is unaffected.\nconst withHiddenView = (controller: EditorController): EditorController => {\n Object.defineProperty(controller, 'view', { enumerable: false });\n return controller;\n};\n\nexport const noopController: EditorController = withHiddenView({\n get view() {\n return null;\n },\n getText: () => '',\n setText: () => {},\n focus: () => {},\n});\n\nexport const createEditorController = (view: EditorView | null): EditorController => {\n return withHiddenView({\n get view() {\n return view;\n },\n getText: () => {\n return view?.state.doc.toString() ?? '';\n },\n setText: (text: string, focus?: boolean) => {\n view?.dispatch({\n changes: {\n from: 0,\n to: view?.state.doc.length ?? 0,\n insert: text,\n },\n selection: {\n anchor: text.length,\n head: text.length,\n },\n });\n\n if (focus) {\n view?.focus();\n }\n },\n focus: () => view?.focus(),\n });\n};\n","//\n// Copyright 2025 DXOS.org\n//\n\nimport { type Extension } from '@codemirror/state';\nimport { type Atom } from '@effect-atom/atom-react';\nimport { createContext } from '@radix-ui/react-context';\n\nimport { type XmlWidgetState } from '@dxos/ui-editor';\n\nimport { type EditorToolbarState } from '../EditorToolbar/types';\nimport { type EditorController } from './controller';\n\n// Kept out of `Editor.tsx`: react-refresh only fast-refreshes a module whose exports are all\n// components, so a context and its hook exported beside them force a full page reload on every edit.\n\n//\n// Context\n//\n\nexport type EditorContextValue = {\n controller?: EditorController;\n setController: (controller: EditorController) => void;\n extensions?: Extension[];\n /** xmlTags widget portals (embedded blocks); rendered by `Editor.Blocks`, fed via `setWidgets`. */\n widgets?: XmlWidgetState[];\n state: Atom.Writable<EditorToolbarState>;\n};\n\nexport const [EditorContextProvider, useEditorContext] = createContext<EditorContextValue>('Editor');\n\n/**\n * Access the editor context. Must be used within `Editor.Root`.\n */\n","//\n// Copyright 2025 DXOS.org\n//\n\nimport { type EditorView } from '@codemirror/view';\n\nimport { type Label } from '@dxos/react-ui';\nimport { insertAtCursor } from '@dxos/ui-editor';\nimport { type MaybePromise } from '@dxos/util';\n\nexport type EditorMenuGroup = {\n id: string;\n label?: Label;\n items: EditorMenuItem[];\n};\n\nexport type EditorMenuItem = {\n id: string;\n label: Label;\n icon?: string;\n onSelect?: (event: { view: EditorView; head: number }) => MaybePromise<void>;\n};\n\nexport const getMenuItem = (groups: EditorMenuGroup[], id?: string): EditorMenuItem | undefined => {\n return groups.flatMap((group) => group.items).find((item) => item.id === id);\n};\n\n/** Undefined when the menu is empty; at either end the current item is returned unchanged. */\nexport const getNextMenuItem = (groups: EditorMenuGroup[], id?: string): EditorMenuItem | undefined => {\n const items = groups.flatMap((group) => group.items);\n const index = items.findIndex((item) => item.id === id);\n return index < items.length - 1 ? items[index + 1] : items[index];\n};\n\n/** Undefined when the menu is empty; at either end the current item is returned unchanged. */\nexport const getPreviousMenuItem = (groups: EditorMenuGroup[], id?: string): EditorMenuItem | undefined => {\n const items = groups.flatMap((group) => group.items);\n const index = items.findIndex((item) => item.id === id);\n return index > 0 ? items[index - 1] : items[index];\n};\n\nexport const createMenuGroup = ({\n id = 'menu',\n label,\n filter,\n items,\n}: {\n id?: string;\n label?: Label;\n filter?: string;\n items: string[];\n}): EditorMenuGroup => ({\n id,\n label,\n items: items\n .filter((item) => !filter || item.toLowerCase().includes(filter.toLowerCase()))\n .map((item, i) => ({\n id: `${id}-${i}`,\n label: item,\n onSelect: ({ view, head }) => insertAtCursor(view, head, item),\n })),\n});\n\nexport const filterMenuGroups = (\n groups: EditorMenuGroup[],\n filter: (item: EditorMenuItem) => boolean,\n): EditorMenuGroup[] => {\n return groups.map((group) => ({\n ...group,\n items: group.items.filter(filter),\n }));\n};\n","//\n// Copyright 2024 DXOS.org\n//\n\nimport { type Extension, Prec, RangeSetBuilder, StateEffect, StateField } from '@codemirror/state';\nimport {\n Decoration,\n type DecorationSet,\n EditorView,\n type KeyBinding,\n ViewPlugin,\n type ViewUpdate,\n keymap,\n} from '@codemirror/view';\n\nimport { type PlaceholderOptions, modalStateField, placeholder } from '@dxos/ui-editor';\nimport { type Range } from '@dxos/ui-editor/types';\nimport { isNonNullable, isTruthy } from '@dxos/util';\n\nconst DELIMITERS = [' ', ':'];\n\nexport type PopoverOptions = {\n trigger?: string | string[];\n triggerKey?: string;\n placeholder?: Partial<PlaceholderOptions>;\n delimiters?: string[];\n\n /**\n * Open the popover automatically while typing a word (no trigger character required).\n * The completion range covers the word under the cursor (delimited by {@link PopoverOptions.delimiters}).\n */\n activateOnTyping?: boolean;\n\n // Trigger update.\n onTextChange?: (event: { view: EditorView; pos: number; text: string; trigger?: string }) => void;\n onClose?: (event: { view: EditorView }) => void;\n\n // Menu specific.\n /** Returns true when the menu consumed the key (an item was selected); false falls through. */\n onEnter?: (event: { view: EditorView }) => boolean | void;\n onArrowUp?: (event: { view: EditorView }) => void;\n onArrowDown?: (event: { view: EditorView }) => void;\n};\n\n/**\n * Creates a popover that appears when the trigger character is inserted.\n * This can be used for context menus or autocompletion.\n */\nexport const popover = (options: PopoverOptions = {}): Extension => {\n return [\n Prec.highest(popoverKeymap(options)),\n popoverStateField,\n popoverTriggerListener(options),\n options.activateOnTyping && popoverAutoActivate(options),\n popoverAnchorDecoration(options),\n modalStateField,\n options.trigger &&\n placeholder({\n // TODO(burdon): Translations.\n content: `Press '${Array.isArray(options.trigger) ? options.trigger[0] : options.trigger}' for commands`,\n focusOnly: true,\n ...options.placeholder,\n }),\n ].filter(isTruthy);\n};\n\n/**\n * Listen for selection and document changes.\n */\nconst popoverTriggerListener = (options: PopoverOptions) =>\n EditorView.updateListener.of(({ view, docChanged }) => {\n const { range: activeRange, trigger } = view.state.field(popoverStateField) ?? {};\n if (!activeRange) {\n return;\n }\n\n const text = view.state.doc.sliceString(activeRange.from, activeRange.to);\n const selection = view.state.selection.main;\n const shouldClose =\n // Trigger deleted.\n (trigger ? trigger !== text[0] : false) ||\n // Whitespace in text.\n /\\s/.test(trigger ? text.slice(1) : text) ||\n // Cursor moved before the range.\n selection.head < activeRange.from ||\n // Cursor moved after the range (+1 to handle selection changing before doc).\n selection.head > activeRange.to + 1;\n\n const nextRange = shouldClose ? null : docChanged ? { from: activeRange.from, to: selection.head } : activeRange;\n if (nextRange !== activeRange) {\n view.dispatch({\n effects: popoverRangeEffect.of(nextRange ? { range: nextRange, trigger } : null),\n });\n }\n\n if (shouldClose) {\n options.onClose?.({ view });\n }\n });\n\n/**\n * Open the popover while typing a word, without requiring a trigger character. Once a range is\n * active, {@link popoverTriggerListener} keeps it in sync and closes it (whitespace, cursor moves).\n */\nconst popoverAutoActivate = (options: PopoverOptions) =>\n EditorView.updateListener.of(({ view, docChanged, transactions }) => {\n // Only user input opens the popover — programmatic syncs (e.g. a controlled `value` update on\n // mount) must not pop the menu.\n if (!docChanged || !transactions.some((tr) => tr.isUserEvent('input')) || view.state.field(popoverStateField)) {\n return;\n }\n const selection = view.state.selection.main;\n if (!selection.empty) {\n return;\n }\n const line = view.state.doc.lineAt(selection.head);\n const before = line.text.slice(0, selection.head - line.from);\n const idx = getLastIndexOf(before, options.delimiters ?? DELIMITERS);\n const token = before.slice(idx + 1);\n if (token.length === 0) {\n return;\n }\n view.dispatch({\n effects: popoverRangeEffect.of({ range: { from: line.from + idx + 1, to: selection.head } }),\n });\n });\n\n/**\n * Popover navigation.\n */\nconst popoverKeymap = (options: PopoverOptions) => {\n const triggers = Array.isArray(options.trigger) ? options.trigger : [options.trigger];\n return keymap.of(\n [\n // Prefix triggers.\n ...triggers.filter(isNonNullable).map((trigger) => ({\n key: trigger,\n run: (view: EditorView) => {\n // Determine if we should trigger the popover:\n // 1. Empty lines or at the beginning of a line.\n // 2. When there's a preceding space.\n const selection = view.state.selection.main;\n const line = view.state.doc.lineAt(selection.head);\n if (\n line.text.trim() === '' ||\n selection.head === line.from ||\n (selection.head > line.from && line.text[selection.head - line.from - 1] === ' ')\n ) {\n // Insert and select the trigger.\n view.dispatch({\n changes: { from: selection.head, insert: trigger },\n selection: { anchor: selection.head + 1, head: selection.head + 1 },\n effects: popoverRangeEffect.of({ trigger, range: { from: selection.head, to: selection.head + 1 } }),\n });\n\n return true;\n }\n\n return false;\n },\n })),\n\n //\n // Custom trigger.\n //\n options.triggerKey &&\n ({\n key: options.triggerKey,\n run: (view: EditorView) => {\n const selection = view.state.selection.main;\n const line = view.state.doc.lineAt(selection.head);\n\n // Get last word.\n let str = line.text.slice(0, selection.head - line.from);\n const idx = getLastIndexOf(str, options.delimiters ?? DELIMITERS);\n if (idx !== -1) {\n str = str.slice(idx + 1);\n }\n\n // Create anchor even if zero length (append space).\n const from = line.from + idx;\n view.dispatch({\n effects: popoverRangeEffect.of({ range: { from: from + 1, to: selection.head } }),\n changes:\n selection.head === view.state.doc.length\n ? { from: from + 1, to: selection.head, insert: ' ' }\n : undefined,\n });\n return true;\n },\n } satisfies KeyBinding),\n\n //\n // Nav keys.\n //\n {\n key: 'ArrowUp',\n run: (view: EditorView) => {\n const range = view.state.field(popoverStateField)?.range;\n if (range) {\n options.onArrowUp?.({ view });\n return true;\n }\n\n return false;\n },\n },\n {\n key: 'ArrowDown',\n run: (view: EditorView) => {\n const range = view.state.field(popoverStateField)?.range;\n if (range) {\n options.onArrowDown?.({ view });\n return true;\n }\n\n return false;\n },\n },\n {\n key: 'Enter',\n run: (view: EditorView) => {\n const range = view.state.field(popoverStateField)?.range;\n if (range) {\n // The consumer deletes the range when it selects an item; when nothing is selectable\n // (empty menu over an `activateOnTyping` range) the key must fall through so the\n // typed text is preserved.\n return options.onEnter?.({ view }) ?? false;\n }\n\n return false;\n },\n },\n ].filter(isTruthy),\n );\n};\n\n/**\n * Creates a <dx-anchor> tag, which is used to anchor the Popver.\n */\nconst popoverAnchorDecoration = (options: PopoverOptions) => {\n return ViewPlugin.fromClass(\n class {\n _decorations: DecorationSet = Decoration.none;\n\n constructor(readonly view: EditorView) {}\n\n // TODO(wittjosiah): The decorations are repainted on every update, this occasionally causes menu to flicker.\n update({ view, transactions }: ViewUpdate) {\n const builder = new RangeSetBuilder<Decoration>();\n const { range, trigger } = view.state.field(popoverStateField) ?? {};\n if (range) {\n // Check if we should show the widget (only if cursor is within the active command range).\n const selection = view.state.selection.main;\n const showWidget = selection.head >= range.from && selection.head <= range.to;\n if (showWidget) {\n builder.add(\n range.from,\n range.to + 1,\n Decoration.mark({\n tagName: 'dx-anchor',\n class: 'cm-popover-trigger',\n attributes: {\n 'data-visible-focus': 'false',\n 'data-auto-trigger': 'true',\n 'data-trigger': trigger ?? options.triggerKey ?? '',\n },\n }),\n );\n }\n\n const rangeChanged = transactions.some((tr) => tr.effects.some((effect) => effect.is(popoverRangeEffect)));\n if (rangeChanged) {\n // NOTE: Content skips the trigger character.\n const content = view.state.sliceDoc(range.from + (trigger ? trigger.length : 0), range.to);\n options.onTextChange?.({ view, pos: selection.head, text: content, trigger });\n }\n }\n\n this._decorations = builder.finish();\n }\n },\n {\n decorations: (v) => v._decorations,\n },\n );\n};\n\ntype PopoverState = {\n /**\n * Trigger prefix (in document).\n */\n trigger?: string;\n\n /**\n * Current document completion range.\n */\n range: Range;\n};\n\n// State effects for managing popover state.\nexport const popoverRangeEffect = StateEffect.define<PopoverState | null>();\n\n// State field to track the active popover trigger range.\nexport const popoverStateField = StateField.define<PopoverState | null>({\n create: () => null,\n update: (value, tr) => {\n let newValue = value;\n for (const effect of tr.effects) {\n if (effect.is(popoverRangeEffect)) {\n newValue = effect.value;\n }\n }\n\n return newValue;\n },\n});\n\nconst getLastIndexOf = (str: string, delimiters: string[]) =>\n Math.max(...delimiters.map((delim) => str.lastIndexOf(delim)));\n","//\n// Copyright 2025 DXOS.org\n//\n\nimport { type EditorView } from '@codemirror/view';\n\nimport { insertAtLineStart } from '@dxos/ui-editor';\n\nimport { type EditorMenuGroup } from './menu';\nimport { popoverRangeEffect } from './popover';\n\n/**\n * Re-open the popover in link-query (\"@\") mode at the cursor, seeding the same query shape the user\n * would get by typing the trigger manually: a single \"@\" for an inline link, \"@@\" for a block embed.\n * The consumer's `@` handler (e.g. plugin-markdown's link query) renders the object picker and, on\n * selection, replaces this range with the corresponding markdown link.\n *\n * Deferred to the next frame: selecting a slash-menu item deletes the \"/\" range, which closes the\n * popover; opening synchronously races that close (`onActivate` reads a stale open state) and the\n * picker never appears.\n */\nconst openLinkQuery = (view: EditorView, insert: '@' | '@@'): void => {\n requestAnimationFrame(() => {\n const { head } = view.state.selection.main;\n const to = head + insert.length;\n view.dispatch({\n changes: { from: head, insert },\n selection: { anchor: to, head: to },\n // The popover trigger is the single \"@\"; a second \"@\" lives in the query range and switches to block mode.\n effects: popoverRangeEffect.of({ trigger: '@', range: { from: head, to } }),\n });\n });\n};\n\nexport const formattingCommands: EditorMenuGroup = {\n id: 'markdown',\n label: 'Markdown',\n items: [\n {\n id: 'heading-1',\n label: 'Heading 1',\n icon: 'ph--text-h-one--regular',\n onSelect: ({ view, head }) => insertAtLineStart(view, head, '# '),\n },\n {\n id: 'heading-2',\n label: 'Heading 2',\n icon: 'ph--text-h-two--regular',\n onSelect: ({ view, head }) => insertAtLineStart(view, head, '## '),\n },\n {\n id: 'heading-3',\n label: 'Heading 3',\n icon: 'ph--text-h-three--regular',\n onSelect: ({ view, head }) => insertAtLineStart(view, head, '### '),\n },\n {\n id: 'heading-4',\n label: 'Heading 4',\n icon: 'ph--text-h-four--regular',\n onSelect: ({ view, head }) => insertAtLineStart(view, head, '#### '),\n },\n {\n id: 'heading-5',\n label: 'Heading 5',\n icon: 'ph--text-h-five--regular',\n onSelect: ({ view, head }) => insertAtLineStart(view, head, '##### '),\n },\n {\n id: 'heading-6',\n label: 'Heading 6',\n icon: 'ph--text-h-six--regular',\n onSelect: ({ view, head }) => insertAtLineStart(view, head, '###### '),\n },\n {\n id: 'bullet-list',\n label: 'Bullet List',\n icon: 'ph--list-bullets--regular',\n onSelect: ({ view, head }) => insertAtLineStart(view, head, '- '),\n },\n {\n id: 'numbered-list',\n label: 'Numbered List',\n icon: 'ph--list-numbers--regular',\n onSelect: ({ view, head }) => insertAtLineStart(view, head, '1. '),\n },\n {\n id: 'task-list',\n label: 'Task List',\n icon: 'ph--list-checks--regular',\n onSelect: ({ view, head }) => insertAtLineStart(view, head, '- [ ] '),\n },\n {\n id: 'quote',\n label: 'Quote',\n icon: 'ph--quotes--regular',\n onSelect: ({ view, head }) => insertAtLineStart(view, head, '> '),\n },\n {\n id: 'code-block',\n label: 'Code Block',\n icon: 'ph--code-block--regular',\n onSelect: ({ view, head }) => insertAtLineStart(view, head, '```\\n\\n```'),\n },\n {\n id: 'table',\n label: 'Table',\n icon: 'ph--table--regular',\n onSelect: ({ view, head }) => insertAtLineStart(view, head, '| | | |\\n|---|---|---|\\n| | | |'),\n },\n ],\n};\n\nexport const linkSlashCommands: EditorMenuGroup = {\n id: 'link',\n label: 'Link',\n items: [\n {\n id: 'inline-link',\n label: 'Inline link',\n icon: 'ph--link--regular',\n onSelect: ({ view }) => openLinkQuery(view, '@'),\n },\n {\n id: 'inline-object',\n label: 'Inline object',\n icon: 'ph--lego--regular',\n onSelect: ({ view }) => openLinkQuery(view, '@@'),\n },\n ],\n};\n","//\n// Copyright 2025 DXOS.org\n//\n\nimport { type EditorView } from '@codemirror/view';\nimport { useControllableState } from '@radix-ui/react-use-controllable-state';\nimport React, {\n Fragment,\n type KeyboardEvent,\n type PropsWithChildren,\n useCallback,\n useEffect,\n useRef,\n useState,\n} from 'react';\n\nimport { addEventListener } from '@dxos/async';\nimport { invariant } from '@dxos/invariant';\nimport {\n DX_ANCHOR_ACTIVATE,\n type DxAnchorActivate,\n Icon,\n Input,\n Popover,\n ScrollArea,\n toLocalizedString,\n useDynamicRef,\n useThemeContext,\n useTranslation,\n} from '@dxos/react-ui';\n\nimport { translationKey } from '#translations';\n\nimport { type EditorMenuGroup, type EditorMenuItem, getMenuItem } from './menu';\n\nexport type EditorMenuProviderProps = PropsWithChildren<{\n // Provided as a getter (not a value prop) so the live `EditorView` is never carried in a React prop that\n // the dev render-logger would walk into a cross-origin frame. See `controller.ts` for the full rationale.\n getView?: () => EditorView | null;\n groups?: EditorMenuGroup[];\n currentItem?: string;\n open?: boolean;\n defaultOpen?: boolean;\n numItems?: number;\n /** Render the menu as a combobox: the popover owns the query input and takes focus from the editor. */\n search?: boolean;\n query?: string;\n searchPlaceholder?: string;\n onOpenChange?: (event: { view: EditorView; open: boolean; trigger?: string }) => void;\n onActivate?: (event: { view: EditorView; trigger?: string }) => void;\n onSelect?: (event: { view: EditorView; item: EditorMenuItem }) => void;\n onCancel?: (event: { view: EditorView }) => void;\n onQueryChange?: (query: string) => void;\n onNavigate?: (direction: 'up' | 'down') => void;\n}>;\n\n/**\n * Implements the Popover and listens for the `dx-anchor-activate` event from the `popover` extension's decoration.\n * NOTE: We don't use DropdownMenu because the command menu needs to manage focus explicitly.\n * I.e., focus must remain in the editor while displaying the menu (for type-ahead).\n */\nexport const EditorMenuProvider = ({\n children,\n getView,\n groups,\n currentItem,\n open: openProp,\n defaultOpen,\n numItems = 8,\n search,\n query = '',\n searchPlaceholder,\n onOpenChange,\n onActivate,\n onSelect,\n onCancel,\n onQueryChange,\n onNavigate,\n}: EditorMenuProviderProps) => {\n const { t } = useTranslation(translationKey);\n const triggerRef = useRef<HTMLButtonElement | null>(null);\n\n // Hold the latest `getView` so callbacks/effects always read the current view without re-subscribing.\n const getViewRef = useDynamicRef(getView);\n const [open, setOpen] = useControllableState({\n prop: openProp,\n defaultProp: defaultOpen,\n onChange: (open) => {\n const view = getViewRef.current?.();\n invariant(view);\n onOpenChange?.({ view, open });\n },\n });\n\n const [root, setRoot] = useState<HTMLDivElement | null>(null);\n useEffect(() => {\n if (!root) {\n return;\n }\n\n // Listen for trigger.\n return addEventListener(\n root,\n DX_ANCHOR_ACTIVATE as any,\n (event: DxAnchorActivate) => {\n const { trigger, dxn } = event;\n if (!dxn) {\n triggerRef.current = trigger as HTMLButtonElement;\n if (onActivate) {\n const view = getViewRef.current?.();\n if (view) {\n onActivate({ view, trigger: trigger.getAttribute('data-trigger') ?? undefined });\n }\n } else {\n requestAnimationFrame(() => setOpen(true));\n }\n }\n },\n {\n capture: true,\n passive: false,\n },\n );\n }, [root, onActivate]);\n\n const handleSelect = useCallback<NonNullable<MenuProps['onSelect']>>(\n (item) => {\n const view = getViewRef.current?.();\n invariant(view);\n onSelect?.({ view, item });\n // Close the popover after acting (e.g. Delete) and return focus to the editor; otherwise the menu\n // lingers open over the now-changed document.\n setOpen(false);\n view.focus();\n },\n [getViewRef, onSelect, setOpen],\n );\n\n const menuGroups = groups?.filter((group) => group.items.length > 0) ?? [];\n\n // Handing off from the slash menu refocuses the editor and reopens the popover a frame later, so\n // neither `autoFocus` nor `onOpenAutoFocus` lands on the input. Claim focus a frame after the\n // modal-state dispatch `handleOpenChange` schedules, which otherwise hands focus back to CodeMirror.\n const searchInputRef = useRef<HTMLInputElement>(null);\n useEffect(() => {\n if (!search || !open) {\n return;\n }\n\n let inner: number;\n const outer = requestAnimationFrame(() => {\n inner = requestAnimationFrame(() => searchInputRef.current?.focus());\n });\n\n return () => {\n cancelAnimationFrame(outer);\n cancelAnimationFrame(inner);\n };\n }, [search, open]);\n\n const handleSearchKeyDown = useCallback(\n (event: KeyboardEvent<HTMLInputElement>) => {\n switch (event.key) {\n case 'ArrowUp':\n case 'ArrowDown': {\n event.preventDefault();\n onNavigate?.(event.key === 'ArrowUp' ? 'up' : 'down');\n break;\n }\n\n case 'Enter': {\n const item = getMenuItem(menuGroups, currentItem);\n if (item) {\n event.preventDefault();\n handleSelect(item);\n }\n break;\n }\n }\n },\n [menuGroups, currentItem, handleSelect, onNavigate],\n );\n\n return (\n <Popover.Root modal={false} open={open} onOpenChange={setOpen}>\n <Popover.VirtualTrigger virtualRef={triggerRef} />\n\n {/* Menu. */}\n <Popover.Portal>\n <Popover.Content\n align='start'\n classNames={['flex flex-col', !search && !menuGroups.length && 'hidden']}\n style={{\n // The search input shares the box, so `numItems` keeps meaning \"items visible\".\n maxBlockSize: 36 * numItems + 10 + (search ? 36 : 0),\n }}\n // NOTE: We keep the focus in the editor, but Radix routes escape key.\n onEscapeKeyDown={() => {\n const currentView = getViewRef.current?.();\n if (currentView) {\n onCancel?.({ view: currentView });\n }\n }}\n // In search mode the query is typed into the popover's own input, so it must take focus.\n onOpenAutoFocus={search ? undefined : (event) => event.preventDefault()}\n >\n {search && (\n <Input.Root>\n <Input.TextInput\n ref={searchInputRef}\n density='sm'\n variant='subdued'\n classNames='shrink-0 mbe-1'\n value={query}\n placeholder={searchPlaceholder}\n // Placeholder text is not a persistent accessible name, and it is optional — fall\n // back to the generic label so the input is never anonymous.\n aria-label={searchPlaceholder ?? t('search.label')}\n onChange={(event) => onQueryChange?.(event.target.value)}\n onKeyDown={handleSearchKeyDown}\n />\n </Input.Root>\n )}\n <Popover.Viewport asChild classNames='dx-container'>\n <ScrollArea.Root thin>\n <ScrollArea.Viewport>\n <Menu groups={menuGroups} currentItem={currentItem} onSelect={handleSelect} />\n </ScrollArea.Viewport>\n </ScrollArea.Root>\n </Popover.Viewport>\n <Popover.Arrow />\n </Popover.Content>\n </Popover.Portal>\n\n {/* Content */}\n <div className='contents' ref={setRoot}>\n {children}\n </div>\n </Popover.Root>\n );\n};\n\n//\n// Menu\n//\n\ntype MenuProps = {\n groups: EditorMenuGroup[];\n} & Pick<MenuGroupProps, 'currentItem' | 'onSelect'>;\n\nconst Menu = ({ groups, currentItem, onSelect }: MenuProps) => {\n const { tx } = useThemeContext();\n return (\n <ul>\n {groups.map((group, index) => (\n <Fragment key={group.id}>\n <MenuGroup group={group} currentItem={currentItem} onSelect={onSelect} />\n {index < groups.length - 1 && <div className={tx('menu.separator', {})} />}\n </Fragment>\n ))}\n </ul>\n );\n};\n\n//\n// Menu Group\n//\n\ntype MenuGroupProps = {\n group: EditorMenuGroup;\n currentItem?: string;\n} & Pick<MenuItemProps, 'onSelect'>;\n\nconst MenuGroup = ({ group, currentItem, onSelect }: MenuGroupProps) => {\n const { tx } = useThemeContext();\n const { t } = useTranslation();\n\n return (\n <>\n {group.label && (\n <div className={tx('menu.groupLabel', {})}>\n <span>{toLocalizedString(group.label, t)}</span>\n </div>\n )}\n\n {group.items.map((item) => (\n <MenuItem key={item.id} item={item} current={currentItem === item.id} onSelect={onSelect} />\n ))}\n </>\n );\n};\n\n//\n// Menu Item\n//\n\ntype MenuItemProps = {\n item: EditorMenuItem;\n current: boolean;\n onSelect?: (item: EditorMenuItem) => void;\n};\n\nconst MenuItem = ({ item, current, onSelect }: MenuItemProps) => {\n const { tx } = useThemeContext();\n const { t } = useTranslation();\n\n const listRef = useRef<HTMLLIElement>(null);\n useEffect(() => {\n if (current && listRef.current) {\n // Instant, not smooth: held arrow keys retarget faster than a smooth scroll can settle, and each\n // new animation supersedes the last, so the list stalls then jumps.\n listRef.current.scrollIntoView({ behavior: 'instant', block: 'nearest' });\n }\n }, [current]);\n\n const handleSelect = useCallback(() => onSelect?.(item), [item, onSelect]);\n\n return (\n <li ref={listRef} className={tx('menu.item', {}, [current && 'bg-hover-surface'])} onClick={handleSelect}>\n {item.icon && <Icon icon={item.icon} />}\n <span className='grow truncate'>{toLocalizedString(item.label, t)}</span>\n </li>\n );\n};\n","//\n// Copyright 2024 DXOS.org\n//\n\nimport { type Extension } from '@codemirror/state';\nimport { type EditorState } from '@codemirror/state';\nimport { type EditorView } from '@codemirror/view';\nimport { type RefObject, useCallback, useMemo, useRef, useState } from 'react';\n\nimport { invariant } from '@dxos/invariant';\nimport { modalStateEffect } from '@dxos/ui-editor';\nimport { type MaybePromise } from '@dxos/util';\n\nimport { type EditorMenuProviderProps } from './EditorMenuProvider';\nimport { type EditorMenuGroup, type EditorMenuItem } from './menu';\nimport { filterMenuGroups, getMenuItem, getNextMenuItem, getPreviousMenuItem } from './menu';\nimport { type PopoverOptions, popover, popoverRangeEffect, popoverStateField } from './popover';\n\nexport type GetMenuContext = {\n state: EditorState;\n pos: number;\n text: string;\n trigger?: string;\n};\n\nexport type UseEditorMenuProps = {\n filter?: boolean;\n /**\n * Triggers whose menu is rendered as a combobox: the popover owns a search input and the query is\n * typed there rather than into the document.\n */\n searchTriggers?: string[];\n getMenu?: (context: GetMenuContext) => MaybePromise<EditorMenuGroup[]>;\n} & Pick<PopoverOptions, 'trigger' | 'triggerKey' | 'placeholder' | 'activateOnTyping'>;\n\nexport type UseEditorMenu = {\n groupsRef: RefObject<EditorMenuGroup[]>;\n extension: Extension;\n} & Pick<\n EditorMenuProviderProps,\n | 'currentItem'\n | 'open'\n | 'search'\n | 'query'\n | 'onOpenChange'\n | 'onActivate'\n | 'onSelect'\n | 'onCancel'\n | 'onQueryChange'\n | 'onNavigate'\n>;\n\n/**\n * ```tsx\n * const { groupsRef, extension, ...menuProps } = useEditorMenu();\n * const { parentRef, viewRef } = useTextEditor({ extensions: [extension] });\n * return (\n * <EditorMenuProvider getView={() => viewRef.current} groups={groupsRef.current} {...menuProps}>\n * <div ref={parentRef} />\n * </EditorMenuProvider>\n * );\n * ```\n */\nexport const useEditorMenu = ({\n trigger,\n triggerKey,\n placeholder,\n activateOnTyping,\n filter = true,\n searchTriggers,\n getMenu,\n}: UseEditorMenuProps): UseEditorMenu => {\n const groupsRef = useRef<EditorMenuGroup[]>([]);\n const currentRef = useRef<EditorMenuItem | null>(null);\n const [currentItem, setCurrentItem] = useState<string>();\n const [open, setOpen] = useState(false);\n const [search, setSearch] = useState(false);\n const [query, setQuery] = useState('');\n const [_, refresh] = useState({});\n\n // The document range only supplies the trigger-relative prefix (e.g. the second \"@\" of a block\n // embed); in search mode the rest of the query comes from the popover's input.\n const contextRef = useRef<{ view: EditorView; pos: number; text: string; trigger?: string } | null>(null);\n\n // Monotonic token identifying the latest menu query; bumped per request and on close.\n const requestRef = useRef(0);\n\n /**\n * Get filtered options.\n */\n const getMenuOptions = useCallback<NonNullable<UseEditorMenuProps['getMenu']>>(\n async ({ text, trigger, ...props }) => {\n const groups = (await getMenu?.({ text, trigger, ...props })) ?? [];\n // The \"@\" menu can use \"@@\" as syntax for block embeds, so it owns its own query filtering.\n return filter && trigger !== '@'\n ? filterMenuGroups(groups, (item) =>\n text ? (item.label as string).toLowerCase().startsWith(text.toLowerCase()) : true,\n )\n : groups;\n },\n [getMenu, filter],\n );\n\n /**\n * Recompute the menu and preselect the first item.\n */\n const updateGroups = useCallback(\n async ({ view, pos, text, trigger }: { view: EditorView; pos: number; text: string; trigger?: string }) => {\n const request = ++requestRef.current;\n const groups = (await getMenuOptions({ state: view.state, pos, text, trigger })) ?? [];\n // Queries resolve out of order, so a slower earlier one must not overwrite a newer result\n // (or repopulate the menu after it closed).\n if (request !== requestRef.current) {\n return;\n }\n\n groupsRef.current = groups;\n const firstItem = groupsRef.current.filter((group) => group.items.length > 0)[0]?.items[0];\n if (firstItem) {\n setCurrentItem(firstItem.id);\n currentRef.current = firstItem;\n } else {\n // No matches: clear the selection so Enter falls through instead of\n // selecting a stale item from a previous query.\n setCurrentItem(undefined);\n currentRef.current = null;\n }\n\n refresh({});\n },\n [getMenuOptions],\n );\n\n const handleOpenChange = useCallback<NonNullable<UseEditorMenu['onOpenChange']>>(\n async ({ view, open }) => {\n invariant(view);\n setOpen(open);\n if (!open) {\n setCurrentItem(undefined);\n setSearch(false);\n setQuery('');\n contextRef.current = null;\n // Invalidate in-flight queries so a late response cannot repopulate the closed menu.\n requestRef.current++;\n groupsRef.current = [];\n currentRef.current = null;\n view.dispatch({\n effects: [popoverRangeEffect.of(null)],\n });\n }\n\n // TODO(burdon): Possible race condition.\n // useTextEditor.handleKeyDown will get called after this handler completes.\n requestAnimationFrame(() => {\n view.dispatch({\n effects: [modalStateEffect.of(open)],\n });\n });\n },\n [getMenuOptions],\n );\n\n const handleActivate = useCallback<NonNullable<UseEditorMenu['onActivate']>>(\n async ({ view, trigger }) => {\n const item = getMenuItem(groupsRef.current, currentItem);\n if (item) {\n currentRef.current = item;\n }\n\n if (!open) {\n handleOpenChange({ view, open: true, trigger });\n }\n },\n [open, handleOpenChange],\n );\n\n const handleSelect = useCallback<NonNullable<UseEditorMenu['onSelect']>>(({ view, item }) => {\n // Delete trigger range (e.g., \"/\" and any typed filter text).\n const { range } = view.state.field(popoverStateField) ?? {};\n if (range) {\n view.dispatch({ changes: { from: range.from, to: range.to, insert: '' } });\n }\n void item.onSelect?.({ view, head: view.state.selection.main.head });\n view.focus();\n }, []);\n\n const handleCancel = useCallback<NonNullable<UseEditorMenu['onCancel']>>(({ view }) => {\n // Delete trigger.\n const { range, trigger } = view.state.field(popoverStateField) ?? {};\n if (range && trigger) {\n view.dispatch({\n changes: { ...range, insert: '' },\n });\n }\n }, []);\n\n const handleQueryChange = useCallback<NonNullable<UseEditorMenu['onQueryChange']>>(\n (query) => {\n setQuery(query);\n const context = contextRef.current;\n if (context) {\n void updateGroups({ ...context, text: context.text + query });\n }\n },\n [updateGroups],\n );\n\n const handleNavigate = useCallback<NonNullable<UseEditorMenu['onNavigate']>>((direction) => {\n setCurrentItem((currentItem) => {\n const next =\n direction === 'up'\n ? getPreviousMenuItem(groupsRef.current, currentItem)\n : getNextMenuItem(groupsRef.current, currentItem);\n // A query that matches nothing leaves an empty menu; arrow keys then have nowhere to go.\n if (!next) {\n return currentItem;\n }\n\n currentRef.current = next;\n return next.id;\n });\n }, []);\n\n const serializedTrigger = Array.isArray(trigger) ? trigger.join(',') : trigger;\n const serializedSearchTriggers = searchTriggers?.join(',');\n const extension = useMemo<Extension>(() => {\n return popover({\n trigger,\n triggerKey,\n placeholder,\n activateOnTyping,\n onClose: ({ view }) => handleOpenChange({ view, open: false }),\n onEnter: ({ view }) => {\n if (currentRef.current) {\n handleSelect({ view, item: currentRef.current });\n return true;\n }\n return false;\n },\n onArrowUp: () => handleNavigate('up'),\n onArrowDown: () => handleNavigate('down'),\n onTextChange: async ({ view, pos, text, trigger }) => {\n contextRef.current = { view, pos, text, trigger };\n // The input is remounted per activation, so the query always starts empty.\n setSearch(!!trigger && !!searchTriggers?.includes(trigger));\n setQuery('');\n await updateGroups({ view, pos, text, trigger });\n },\n });\n }, [\n handleOpenChange,\n handleNavigate,\n updateGroups,\n serializedTrigger,\n serializedSearchTriggers,\n placeholder,\n activateOnTyping,\n ]);\n\n return {\n groupsRef,\n extension,\n currentItem,\n open,\n search,\n query,\n onOpenChange: handleOpenChange,\n onActivate: handleActivate,\n onSelect: handleSelect,\n onCancel: handleCancel,\n onQueryChange: handleQueryChange,\n onNavigate: handleNavigate,\n };\n};\n","//\n// Copyright 2025 DXOS.org\n//\n\nimport { type EditorView } from '@codemirror/view';\n\nimport { type ActionGroupBuilderFn, type ToolbarMenuActionGroupProperties } from '@dxos/react-ui-menu';\nimport { addBlockquote, addCodeblock, insertTable, removeBlockquote, removeCodeblock } from '@dxos/ui-editor';\n\nimport { translationKey } from '#translations';\n\nimport { type EditorToolbarState } from './types';\n\nconst blockTypes = {\n blockquote: 'ph--quotes--regular',\n codeblock: 'ph--code-block--regular',\n table: 'ph--table--regular',\n};\n\n/** Add block actions to the builder. */\nexport const addBlocks =\n (state: EditorToolbarState, getView: () => EditorView): ActionGroupBuilderFn =>\n (builder) => {\n const value = state?.blockQuote ? 'blockquote' : (state.blockType ?? '');\n builder.group(\n 'block',\n {\n label: ['block.label', { ns: translationKey }],\n iconOnly: true,\n variant: 'toggleGroup',\n selectCardinality: 'single',\n value,\n } as ToolbarMenuActionGroupProperties,\n (group) => {\n for (const [type, icon] of Object.entries(blockTypes)) {\n const checked = type === value;\n group.action(\n type,\n {\n label: [`block.${type}.label`, { ns: translationKey }],\n checked,\n ...(type === 'table' && { disabled: !!state.blankLine }),\n icon,\n },\n () => {\n const view = getView();\n if (!view) {\n return;\n }\n\n switch (type) {\n case 'blockquote':\n checked ? removeBlockquote(view) : addBlockquote(view);\n break;\n case 'codeblock':\n checked ? removeCodeblock(view) : addCodeblock(view);\n break;\n case 'table':\n insertTable(view);\n break;\n }\n },\n );\n }\n },\n );\n };\n","//\n// Copyright 2025 DXOS.org\n//\n\nimport { type EditorView } from '@codemirror/view';\n\nimport { type ActionGroupBuilderFn, type ToolbarMenuActionGroupProperties } from '@dxos/react-ui-menu';\nimport { type Formatting, Inline, addLink, removeLink, setStyle } from '@dxos/ui-editor';\n\nimport { translationKey } from '#translations';\n\nimport { type EditorToolbarState } from './types';\n\nconst formats = {\n strong: 'ph--text-b--regular',\n emphasis: 'ph--text-italic--regular',\n strikethrough: 'ph--text-strikethrough--regular',\n code: 'ph--code--regular',\n link: 'ph--link--regular',\n};\n\n/** Add formatting actions to the builder. */\nexport const addFormatting =\n (state: EditorToolbarState, getView: () => EditorView): ActionGroupBuilderFn =>\n (builder) => {\n const formatting: Formatting = state;\n builder.group(\n 'formatting',\n {\n label: ['formatting.label', { ns: translationKey }],\n iconOnly: true,\n variant: 'toggleGroup',\n selectCardinality: 'multiple',\n value: Object.keys(formats).filter((key) => !!formatting[key as keyof Formatting]),\n } as ToolbarMenuActionGroupProperties,\n (group) => {\n for (const [type, icon] of Object.entries(formats)) {\n const checked = !!formatting[type as keyof Formatting];\n group.action(type, { label: [`formatting.${type}.label`, { ns: translationKey }], checked, icon }, () => {\n const view = getView();\n if (!view) {\n return;\n }\n\n if (type === 'link') {\n checked ? removeLink(view) : addLink()(view);\n return;\n }\n\n setStyle(\n type === 'strong'\n ? Inline.Strong\n : type === 'emphasis'\n ? Inline.Emphasis\n : type === 'strikethrough'\n ? Inline.Strikethrough\n : Inline.Code,\n !checked,\n )(view);\n });\n }\n },\n );\n };\n","//\n// Copyright 2025 DXOS.org\n//\n\nimport { type EditorView } from '@codemirror/view';\n\nimport { type ActionGroupBuilderFn, type ToolbarMenuActionGroupProperties } from '@dxos/react-ui-menu';\nimport { setHeading } from '@dxos/ui-editor';\n\nimport { translationKey } from '#translations';\n\nimport { type EditorToolbarState } from './types';\n\nconst headingIcons: Record<string, string> = {\n 0: 'ph--paragraph--regular',\n 1: 'ph--text-h-one--regular',\n 2: 'ph--text-h-two--regular',\n 3: 'ph--text-h-three--regular',\n 4: 'ph--text-h-four--regular',\n 5: 'ph--text-h-five--regular',\n 6: 'ph--text-h-six--regular',\n};\n\nconst computeHeadingValue = (state: EditorToolbarState) => {\n const blockType = state ? state.blockType : 'paragraph';\n const heading = blockType && /heading(\\d)/.exec(blockType);\n return heading ? heading[1] : blockType === 'paragraph' || !blockType ? '0' : '';\n};\n\n/** Add heading actions to the builder. */\nexport const addHeadings =\n (state: EditorToolbarState, getView: () => EditorView): ActionGroupBuilderFn =>\n (builder) => {\n const headingValue = computeHeadingValue(state);\n builder.group(\n 'heading',\n {\n label: ['heading.label', { ns: translationKey }],\n icon: 'ph--text-h--regular',\n iconOnly: true,\n variant: 'dropdownMenu',\n applyActive: true,\n selectCardinality: 'single',\n // TODO(wittjosiah): Remove? Not sure this does anything.\n value: headingValue,\n } as ToolbarMenuActionGroupProperties,\n (group) => {\n for (const [levelStr, icon] of Object.entries(headingIcons)) {\n const level = parseInt(levelStr);\n group.action(\n `heading--${levelStr}`,\n {\n label: ['heading-level.label', { count: level, ns: translationKey }],\n icon,\n checked: levelStr === headingValue,\n },\n () => setHeading(level)(getView()),\n );\n }\n },\n );\n };\n","//\n// Copyright 2025 DXOS.org\n//\n\nimport { type ActionGroupBuilderFn } from '@dxos/react-ui-menu';\n\nimport { translationKey } from '#translations';\n\n/** Add image upload action to the builder. */\nexport const addImageUpload =\n (onImageUpload: () => void): ActionGroupBuilderFn =>\n (builder) => {\n builder.action(\n 'image',\n {\n label: ['image.label', { ns: translationKey }],\n testId: 'editor.toolbar.image',\n icon: 'ph--image-square--regular',\n },\n onImageUpload,\n );\n };\n","//\n// Copyright 2025 DXOS.org\n//\n\nimport { type EditorView } from '@codemirror/view';\n\nimport { type ActionGroupBuilderFn, type ToolbarMenuActionGroupProperties } from '@dxos/react-ui-menu';\nimport { List, toggleList } from '@dxos/ui-editor';\n\nimport { translationKey } from '#translations';\n\nimport { type EditorToolbarState } from './types';\n\nconst listStyles = {\n bullet: 'ph--list-bullets--regular',\n ordered: 'ph--list-numbers--regular',\n task: 'ph--list-checks--regular',\n};\n\n/** Add list actions to the builder. */\nexport const addLists =\n (state: EditorToolbarState, getView: () => EditorView): ActionGroupBuilderFn =>\n (builder) => {\n const value = state.listStyle ?? '';\n builder.group(\n 'list',\n {\n label: ['list.label', { ns: translationKey }],\n iconOnly: true,\n variant: 'toggleGroup',\n selectCardinality: 'single',\n value,\n } as ToolbarMenuActionGroupProperties,\n (group) => {\n for (const [listStyle, icon] of Object.entries(listStyles)) {\n const checked = value === listStyle;\n group.action(\n `list-${listStyle}`,\n { label: [`list.${listStyle}.label`, { ns: translationKey }], checked, icon },\n () => {\n const view = getView();\n if (!view) {\n return;\n }\n\n const listType =\n listStyle === 'ordered' ? List.Ordered : listStyle === 'bullet' ? List.Bullet : List.Task;\n toggleList(listType)(view);\n },\n );\n }\n },\n );\n };\n","//\n// Copyright 2025 DXOS.org\n//\n\nimport { openSearchPanel } from '@codemirror/search';\nimport { type EditorView } from '@codemirror/view';\n\nimport { type ActionGroupBuilderFn } from '@dxos/react-ui-menu';\n\nimport { translationKey } from '#translations';\n\n/** Add search action to the builder. */\nexport const addSearch =\n (getView: () => EditorView): ActionGroupBuilderFn =>\n (builder) => {\n builder.action(\n 'search',\n {\n label: ['search.label', { ns: translationKey }],\n testId: 'editor.toolbar.search',\n icon: 'ph--magnifying-glass--regular',\n },\n () => openSearchPanel(getView()),\n );\n };\n","//\n// Copyright 2025 DXOS.org\n//\n\nimport { type ActionGroupBuilderFn, type ToolbarMenuActionGroupProperties } from '@dxos/react-ui-menu';\nimport { type EditorViewMode } from '@dxos/ui-editor/types';\nimport { type Label } from '@dxos/ui-types';\n\nimport { translationKey } from '#translations';\n\nimport { type EditorToolbarState } from './types';\n\n/**\n * One entry in the editor's view-mode dropdown. A built-in entry references an {@link EditorViewMode}\n * by `id` and relies on the defaults (label `view-mode.<id>.label`, checked when it is the active view\n * mode, select via `onViewModeChange`). A contributed entry (e.g. a review \"Suggesting\" mode) supplies\n * its own `label`, `checked`, and `onSelect` so it can drive state other than the editor view mode.\n */\nexport type ViewModeItem = {\n id: string;\n icon: string;\n label?: Label;\n checked?: boolean;\n onSelect?: () => void;\n};\n\n/**\n * The built-in view modes: preview (rendered), source (raw edit), readonly (non-editable source). Typed\n * so each `id` is an {@link EditorViewMode}, letting callers pass `item.id` to `onViewModeChange` without a cast.\n */\nexport const defaultViewModeItems: Array<ViewModeItem & { id: EditorViewMode }> = [\n { id: 'preview', icon: 'ph--eye--regular' },\n { id: 'source', icon: 'ph--pencil-simple--regular' },\n { id: 'readonly', icon: 'ph--pencil-slash--regular' },\n];\n\n/**\n * Add view mode actions to the builder. `items` defaults to the three built-in editor view modes;\n * callers pass an extended list to surface contributed modes (see {@link ViewModeItem}) in the same\n * single-select dropdown. The trigger tracks the checked item (via the group's `applyActive`).\n */\nexport const addViewMode =\n (\n state: EditorToolbarState,\n onViewModeChange: (mode: EditorViewMode) => void,\n items: ViewModeItem[] = defaultViewModeItems,\n ): ActionGroupBuilderFn =>\n (builder) => {\n const value = state.viewMode ?? 'source';\n builder.group(\n 'viewMode',\n {\n label: ['view-mode.label', { ns: translationKey }],\n icon: 'ph--eye--regular',\n iconOnly: true,\n variant: 'dropdownMenu',\n applyActive: true,\n selectCardinality: 'single',\n value,\n } as ToolbarMenuActionGroupProperties,\n (group) => {\n for (const item of items) {\n // A contributed entry may drive non-view-mode state, so honour its explicit `checked`;\n // a built-in entry is checked when it matches the active editor view mode.\n const checked = item.checked ?? item.id === value;\n group.action(\n `view-mode--${item.id}`,\n {\n label: item.label ?? [`view-mode.${item.id}.label`, { ns: translationKey }],\n checked,\n icon: item.icon,\n },\n () => (item.onSelect ? item.onSelect() : onViewModeChange(item.id as EditorViewMode)),\n );\n }\n },\n );\n };\n","//\n// Copyright 2024 DXOS.org\n//\n\nimport { type EditorView } from '@codemirror/view';\nimport { Atom } from '@effect-atom/atom';\nimport React, { memo, useMemo } from 'react';\n\nimport { type Node } from '@dxos/app-graph';\nimport { ElevationProvider, type ThemedClassName } from '@dxos/react-ui';\nimport { type ActionGraphProps, Menu, type MenuAction, MenuBuilder, useMenuActions } from '@dxos/react-ui-menu';\nimport { type EditorViewMode } from '@dxos/ui-editor/types';\n\nimport { addBlocks } from './blocks';\nimport { addFormatting } from './formatting';\nimport { addHeadings } from './headings';\nimport { addImageUpload } from './image';\nimport { addLists } from './lists';\nimport { addSearch } from './search';\nimport { type EditorToolbarState } from './types';\nimport { type ViewModeItem, addViewMode } from './view-mode';\n\n// TODO(burdon): Enable toolbar variants (e.g., markdown, code).\n\n// Local copy of AppSurface.Section.role — react-ui-editor cannot depend on app-toolkit without a circular dep.\nconst SECTION_ROLE = 'org.dxos.role.section';\n\nexport type EditorToolbarFeatureFlags = Partial<{\n showHeadings: boolean;\n showFormatting: boolean;\n showLists: boolean;\n showBlocks: boolean;\n showSearch: boolean;\n\n // TODO(wittjosiah): Factor out (depends on plugin-level capabilities.)\n onImageUpload: () => void;\n onViewModeChange: (mode: EditorViewMode) => void;\n /** Override the view-mode dropdown entries (default: the three built-in modes). See {@link ViewModeItem}. */\n viewModes: ViewModeItem[];\n}>;\n\nexport type EditorToolbarActionGraphProps = {\n state: Atom.Atom<EditorToolbarState>;\n getView: () => EditorView;\n // TODO(wittjosiah): Control positioning.\n customActions?: Atom.Atom<ActionGraphProps>;\n};\n\nexport type EditorToolbarProps = ThemedClassName<\n {\n role?: string;\n attendableId?: string;\n /** Handler for executing actions. Required when customActions use Operation.invoke. */\n onAction?: (action: MenuAction, params: Node.InvokeProps) => void;\n } & (EditorToolbarActionGraphProps & EditorToolbarFeatureFlags)\n>;\n\nexport const EditorToolbar = memo(({ classNames, role, attendableId, onAction, ...props }: EditorToolbarProps) => {\n const menuActions = useMarkdownMenuActions(props);\n\n return (\n <ElevationProvider elevation={role === SECTION_ROLE ? 'positioned' : 'base'}>\n <Menu.Root {...menuActions} attendableId={attendableId} onAction={onAction}>\n <Menu.Toolbar classNames={classNames} />\n </Menu.Root>\n </ElevationProvider>\n );\n});\n\ntype ToolbarActionsProps = Pick<EditorToolbarActionGraphProps, 'state' | 'getView' | 'customActions'> &\n EditorToolbarFeatureFlags;\n\n// TODO(burdon): Some actions should toggle the state (e.g., toggle bullets on/off depending on the current state).\n// TODO(wittjosiah): Toolbar re-rendering is causing this graph to be recreated and breaking reactivity in some cases.\n// E.g. for toolbar dropdowns which use active icon, the icon is not updated when the active item changes.\n// This is currently only happening in the markdown plugin usage and should be reproduced in an editor story.\nconst useMarkdownMenuActions = ({ state, getView, customActions, ...features }: ToolbarActionsProps) => {\n const menuCreator = useMemo(\n () => createMarkdownActions({ state, getView, customActions, ...features }),\n [\n state,\n getView,\n customActions,\n features?.showHeadings,\n features?.showFormatting,\n features?.showLists,\n features?.showBlocks,\n features?.showSearch,\n features?.onImageUpload,\n features?.onViewModeChange,\n features?.viewModes,\n ],\n );\n\n return useMenuActions(menuCreator);\n};\n\nconst createMarkdownActions = ({\n state,\n getView,\n customActions,\n ...features\n}: ToolbarActionsProps): Atom.Atom<ActionGraphProps> => {\n return Atom.make((get) => {\n // Subscribe to state changes.\n const stateSnapshot = get(state);\n return MenuBuilder.make()\n .subgraph(features?.showHeadings !== false && addHeadings(stateSnapshot, getView))\n .subgraph(features?.showFormatting !== false && addFormatting(stateSnapshot, getView))\n .subgraph(features?.showLists !== false && addLists(stateSnapshot, getView))\n .subgraph(features?.showBlocks !== false && addBlocks(stateSnapshot, getView))\n .subgraph(features?.onImageUpload && addImageUpload(features.onImageUpload))\n .separator('gap')\n .subgraph(customActions && get(customActions))\n .subgraph(features?.showSearch !== false && addSearch(getView))\n .subgraph(features?.onViewModeChange && addViewMode(stateSnapshot, features.onViewModeChange, features.viewModes))\n .build();\n });\n};\n","//\n// Copyright 2026 DXOS.org\n//\n\nimport { type Extension } from '@codemirror/state';\nimport { useMemo } from 'react';\n\nimport { useThemeContext } from '@dxos/react-ui';\nimport {\n createBasicExtensions,\n createMarkdownExtensions,\n createThemeExtensions,\n decorateMarkdown,\n} from '@dxos/ui-editor';\n\nexport type UseBasicMarkdownExtensionsOptions = {\n /** Placeholder text shown when the editor is empty. */\n placeholder?: string;\n /** Enables markdown visual decorations. Pass `false` to disable. Defaults to `true`. */\n decorate?: boolean;\n /** Renders the editor read-only (selectable but not editable). Defaults to `false`. */\n readonly?: boolean;\n /**\n * Extra extensions appended to the returned array.\n * Callers must memoize this array — it is used as a dependency of {@link useMemo}.\n */\n extensions?: Extension[];\n};\n\n/**\n * Returns the standard CodeMirror extension stack for an inline markdown editor:\n * basic editor behaviors, themed syntax highlighting (theme mode read from {@link useThemeContext}),\n * markdown parsing, and visual decorations.\n *\n * Used by surfaces such as `AgentProperties` and `MagazineProperties` to render the\n * `instructions` field of an object as a small editable markdown block.\n *\n * The memoization depends on primitive option values plus the `extensions` array reference,\n * so callers passing fresh option literals each render still hit the cache.\n */\nexport const useBasicMarkdownExtensions = ({\n placeholder,\n decorate = true,\n readonly = false,\n extensions,\n}: UseBasicMarkdownExtensionsOptions = {}): Extension[] => {\n const { themeMode } = useThemeContext();\n return useMemo(\n () => [\n createBasicExtensions({ placeholder, readOnly: readonly }),\n createThemeExtensions({ syntaxHighlighting: true, themeMode }),\n createMarkdownExtensions(),\n ...(decorate ? [decorateMarkdown()] : []),\n ...(extensions ?? []),\n ],\n [placeholder, themeMode, decorate, readonly, extensions],\n );\n};\n","//\n// Copyright 2024 DXOS.org\n//\n\nimport { EditorState, type EditorStateConfig, type Text } from '@codemirror/state';\nimport { EditorView } from '@codemirror/view';\nimport {\n type ComponentPropsWithoutRef,\n type DependencyList,\n type KeyboardEventHandler,\n type RefObject,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\n\nimport { log } from '@dxos/log';\nimport {\n type EditorSelection,\n createEditorStateTransaction,\n debugDispatcher,\n documentId,\n modalStateField,\n} from '@dxos/ui-editor';\nimport { type MaybeProvider, getProviderValue, isTruthy } from '@dxos/util';\n\nlet instanceCount = 0;\n\nexport type CursorInfo = {\n from: number;\n to: number;\n line: number;\n lines: number;\n length: number;\n after?: string;\n};\n\nexport type UseTextEditor = {\n parentRef: RefObject<HTMLDivElement | null>;\n view: EditorView | null;\n focusAttributes?: ComponentPropsWithoutRef<'div'>;\n};\n\nexport type UseTextEditorProps = Pick<EditorStateConfig, 'extensions'> & {\n id?: string;\n doc?: Text;\n initialValue?: string;\n autoFocus?: boolean;\n scrollTo?: number;\n selection?: EditorSelection;\n selectionEnd?: boolean;\n debug?: boolean;\n};\n\n/**\n * Creates codemirror text editor.\n */\nexport const useTextEditor = (\n props: MaybeProvider<UseTextEditorProps> = {},\n deps: DependencyList = [],\n): UseTextEditor => {\n const { id, doc, initialValue, extensions, autoFocus, scrollTo, selection, selectionEnd, debug } =\n useMemo<UseTextEditorProps>(() => getProviderValue(props), deps ?? []);\n\n // NOTE: Increments by 2 in strict mode.\n const [instanceId] = useState(() => `text-editor-${++instanceCount}`);\n const [view, setView] = useState<EditorView | null>(null);\n const parentRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n let view: EditorView | null = null;\n if (parentRef.current) {\n log('create', { id, instanceId, doc: initialValue?.length ?? 0 });\n\n let initialSelection;\n if (selection?.anchor && initialValue?.length) {\n if (selection.anchor <= initialValue.length && (selection?.head ?? 0) <= initialValue.length) {\n initialSelection = selection;\n }\n } else if (selectionEnd && selection === undefined) {\n const index = initialValue?.indexOf('\\n');\n const anchor = !index || index === -1 ? 0 : index;\n initialSelection = { anchor };\n }\n\n // https://codemirror.net/docs/ref/#state.EditorStateConfig\n const state = EditorState.create({\n doc: doc ?? initialValue,\n // selection: initialSelection,\n extensions: [\n id && documentId.of(id),\n extensions,\n // NOTE: This doesn't catch errors in keymap functions.\n EditorView.exceptionSink.of((err) => {\n log.catch(err);\n }),\n ].filter(isTruthy),\n });\n\n // https://codemirror.net/docs/ref/#view.EditorViewConfig\n view = new EditorView({\n parent: parentRef.current,\n state,\n scrollTo: scrollTo ? EditorView.scrollIntoView(scrollTo, { yMargin: 96 }) : undefined, // TODO(burdon): Const.\n dispatchTransactions: debug ? debugDispatcher : undefined,\n });\n\n // Move to end of line after document loaded (unless selection is specified).\n if (selectionEnd && !initialSelection) {\n const { to } = view.state.doc.lineAt(0);\n if (to) {\n view.dispatch({ selection: { anchor: to } });\n }\n }\n\n setView(view);\n }\n\n return () => {\n log('destroy', { id });\n view?.destroy();\n };\n }, deps);\n\n useEffect(() => {\n if (view) {\n if (scrollTo || selection) {\n if (selection && selection.anchor > view.state.doc.length) {\n log.warn('invalid selection', { length: view.state.doc.length, scrollTo, selection });\n return;\n }\n\n view.dispatch(createEditorStateTransaction({ scrollTo, selection }));\n }\n }\n }, [view, scrollTo, selection]);\n\n useEffect(() => {\n if (view && autoFocus) {\n view.focus();\n }\n }, [autoFocus, view]);\n\n // Focus editor on Enter (e.g., when tabbing to this component).\n const handleKeyDown = useCallback<KeyboardEventHandler<HTMLDivElement>>(\n (event) => {\n const { key, target, currentTarget } = event;\n switch (key) {\n case 'Escape': {\n // Check if popover is open.\n const modal = view?.state.field(modalStateField, false);\n if (modal) {\n return;\n }\n\n // Focus the closest focusable parent.\n const element = view?.contentDOM.closest('[tabindex=\"0\"]') as HTMLDivElement | null;\n element?.focus();\n break;\n }\n\n case 'Enter': {\n event.preventDefault();\n if (target === currentTarget) {\n view?.focus();\n }\n break;\n }\n }\n },\n [view],\n );\n\n return {\n parentRef,\n view,\n focusAttributes: {\n tabIndex: 0 as const,\n onKeyDown: handleKeyDown,\n },\n };\n};\n","//\n// Copyright 2025 DXOS.org\n//\n\nimport { Transaction } from '@codemirror/state';\nimport { EditorView as NaturalEditorView } from '@codemirror/view';\nimport React, { forwardRef, useEffect, useImperativeHandle, useRef } from 'react';\n\nimport { type ThemedClassName } from '@dxos/react-ui';\nimport { initialSync } from '@dxos/ui-editor';\nimport { mx } from '@dxos/ui-theme';\n\nimport { type UseTextEditorProps, useTextEditor } from '../../hooks';\nimport { type EditorController, createEditorController } from './controller';\n\nexport type EditorViewProps = ThemedClassName<\n {\n focusable?: boolean;\n value?: string;\n onChange?: (value: string) => void;\n } & UseTextEditorProps\n>;\n\n/**\n * Minimal text editor.\n * NOTE: This shouold not be used with the automerge extension.\n */\n// TODO(burdon): Move controller to Root component, then make composable.\nexport const EditorView = forwardRef<EditorController, EditorViewProps>(\n ({ classNames, id, extensions, selectionEnd, focusable = true, value, onChange, ...props }, forwardedRef) => {\n // Hold the latest onChange in a ref so callers may pass an inline callback\n // without forcing the underlying editor to be destroyed and recreated on\n // every render — which would blur the focused input on each keystroke.\n const onChangeRef = useRef(onChange);\n onChangeRef.current = onChange;\n\n const { parentRef, focusAttributes, view } = useTextEditor(\n () => ({\n id,\n initialValue: value,\n selectionEnd,\n extensions: [\n extensions ?? [],\n NaturalEditorView.updateListener.of(({ view, docChanged, transactions }) => {\n const isInitialSync = transactions.some((tr) => tr.annotation(Transaction.userEvent) === initialSync.value);\n if (!isInitialSync && docChanged) {\n onChangeRef.current?.(view.state.doc.toString());\n }\n }),\n ],\n ...props,\n }),\n [id, extensions, selectionEnd],\n );\n\n // External controller.\n useImperativeHandle(forwardedRef, () => {\n return createEditorController(view);\n }, [id, view]);\n\n // Sync the editor doc to the controlled `value` prop, but only when they\n // disagree. After internal typing the prop will already match the editor's\n // doc, and dispatching anyway would race fast keystrokes — a stale rAF\n // closure can replace doc content with an older value, dropping characters.\n //\n // `undefined` means uncontrolled: the doc was seeded once from `value` at creation and the caller\n // isn't driving it, so leave it be (coalescing undefined→'' here would wipe that seed on mount). A\n // controlled caller clears the doc by passing '' explicitly.\n useEffect(() => {\n if (!view || value === undefined) {\n return;\n }\n const next = value;\n if (view.state.doc.toString() === next) {\n return;\n }\n requestAnimationFrame(() => {\n if (view.state.doc.toString() === next) {\n return;\n }\n view.dispatch({\n annotations: initialSync,\n changes: [{ from: 0, to: view.state.doc.length, insert: next }],\n selection: selectionEnd ? { anchor: next.length } : undefined,\n });\n\n if (selectionEnd) {\n view.focus();\n }\n });\n }, [view, value, selectionEnd]);\n\n // Focus chrome (border/ring) is the caller's responsibility (e.g. `dx-input`).\n return (\n <div\n className={mx('w-full outline-hidden', classNames)}\n {...(focusable ? focusAttributes : {})}\n ref={parentRef}\n />\n );\n },\n);\n","//\n// Copyright 2025 DXOS.org\n//\n\nimport { type EditorState, type Extension } from '@codemirror/state';\nimport { Atom } from '@effect-atom/atom';\nimport React, {\n type PropsWithChildren,\n forwardRef,\n useCallback,\n useEffect,\n useImperativeHandle,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { createPortal } from 'react-dom';\n\nimport { invariant } from '@dxos/invariant';\nimport { type ThemedClassName } from '@dxos/react-ui';\nimport { mx } from '@dxos/ui-theme';\nimport { isNonNullable } from '@dxos/util';\n\nimport {\n EditorMenuProvider,\n type EditorMenuProviderProps,\n type UseEditorMenuProps,\n useEditorMenu,\n} from '../EditorMenuProvider';\nimport {\n type EditorToolbarState,\n EditorToolbar as NaturalEditorToolbar,\n type EditorToolbarProps as NaturalEditorToolbarProps,\n} from '../EditorToolbar';\nimport { type EditorController, noopController } from './controller';\nimport { EditorContextProvider, type EditorContextValue, useEditorContext } from './EditorContext';\nimport { EditorView as NaturalEditorContent, type EditorViewProps as NaturalEditorContentProps } from './EditorView';\n\n//\n// Root\n//\n\ntype EditorRootProps = PropsWithChildren<\n Pick<EditorContextValue, 'extensions' | 'widgets'> &\n Omit<UseEditorMenuProps, 'viewRef'> &\n Pick<EditorMenuProviderProps, 'numItems' | 'searchPlaceholder'> & {\n viewMode?: EditorToolbarState['viewMode'];\n }\n>;\n\n/**\n * Root component for the Editor compound component.\n * Provides context for all child components and manages the editor controller state.\n */\nconst EditorRoot = forwardRef<EditorController | null, EditorRootProps>(\n (\n { children, extensions: extensionsProp, widgets, viewMode, numItems, searchPlaceholder, ...props },\n forwardedRef,\n ) => {\n // TODO(wittjosiah): Including initialState in the deps causes reactivity issues.\n const state = useMemo(() => Atom.make<EditorToolbarState>({ viewMode }), [viewMode]);\n\n // TODO(burdon): Consider lighter-weight approach if EditorMenuProvider is not needed.\n const { groupsRef, extension, ...menuProps } = useEditorMenu(props);\n const extensions = useMemo(\n () => [extension, extensionsProp].filter(isNonNullable).flat(),\n [extension, extensionsProp],\n );\n\n // External controller.\n const [controller, setController] = useState<EditorController>(noopController);\n useImperativeHandle(forwardedRef, () => controller, [controller]);\n const getView = useCallback(() => controller?.view ?? null, [controller]);\n\n return (\n <EditorContextProvider\n controller={controller}\n setController={setController}\n extensions={extensions}\n widgets={widgets}\n state={state}\n >\n <EditorMenuProvider\n getView={getView}\n groups={groupsRef.current}\n numItems={numItems}\n searchPlaceholder={searchPlaceholder}\n {...menuProps}\n >\n {children}\n </EditorMenuProvider>\n </EditorContextProvider>\n );\n },\n);\n\nEditorRoot.displayName = 'Editor.Root';\n\n//\n// Content\n//\n\nconst EDITOR_CONTENT_NAME = 'Editor.Content';\n\ntype EditorContentProps = ThemedClassName<PropsWithChildren<{}>>;\n\n/**\n * Content component that wraps the toolbar and editor view area.\n */\nconst EditorContent = ({ classNames, children }: EditorContentProps) => {\n return <div className={mx('grid grid-rows-[min-content_1fr] h-full overflow-hidden', classNames)}>{children}</div>;\n};\n\nEditorContent.displayName = EDITOR_CONTENT_NAME;\n\n//\n// View\n//\n\nconst EDITOR_VIEW_NAME = 'Editor.View';\n\ntype EditorViewProps = Omit<NaturalEditorContentProps, 'ref'>;\n\n/**\n * View component that renders the actual CodeMirror editor.\n * Automatically registers the editor controller with the context.\n */\nconst EditorView = ({ extensions: providedExtensions, ...props }: EditorViewProps) => {\n const { extensions: additionalExtensions = [], setController } = useEditorContext(EDITOR_VIEW_NAME);\n const extensions = useMemo(\n () => [additionalExtensions, providedExtensions].filter(isNonNullable).flat(),\n [providedExtensions, additionalExtensions],\n );\n\n return <NaturalEditorContent {...props} extensions={extensions} ref={setController} />;\n};\n\nEditorView.displayName = EDITOR_VIEW_NAME;\n\n//\n// Toolbar\n//\n\nconst EDITOR_TOOLBAR_NAME = 'Editor.Toolbar';\n\ntype EditorToolbarProps = Omit<NaturalEditorToolbarProps, 'getView' | 'state'>;\n\n/**\n * Toolbar component that provides editor formatting and control actions.\n * Automatically connects to the editor view through context.\n */\nconst EditorToolbar = (props: EditorToolbarProps) => {\n const { controller, state } = useEditorContext(EDITOR_TOOLBAR_NAME);\n const getView = useCallback(() => {\n invariant(controller?.view);\n return controller?.view;\n }, [controller]);\n\n return <NaturalEditorToolbar {...props} getView={getView} state={state} />;\n};\n\nEditorToolbar.displayName = EDITOR_TOOLBAR_NAME;\n\n//\n// Blocks\n//\n\nconst EDITOR_BLOCKS_NAME = 'Editor.Blocks';\n\n/**\n * Renders the xmlTags widget portals (embedded blocks) contributed via the editor's `setWidgets`\n * callback. Place inside `Editor.Root`; the widgets come from context (pass them to `Editor.Root`).\n */\nconst EditorBlocks = () => {\n const { widgets = [] } = useEditorContext(EDITOR_BLOCKS_NAME);\n return (\n <>\n {widgets.map(({ id, root, Component, props }) => (\n <div key={id}>{createPortal(<Component {...props} />, root)}</div>\n ))}\n </>\n );\n};\n\nEditorBlocks.displayName = EDITOR_BLOCKS_NAME;\n\n//\n// Diagnostics\n//\n\nconst EDITOR_DIAGNOSTICS_NAME = 'Editor.Diagnostics';\n\n/** Rough leaf count of a (recursively nested) CodeMirror extension tree. */\nconst countExtensions = (extension: Extension | undefined): number =>\n extension == null\n ? 0\n : Array.isArray(extension)\n ? extension.reduce((sum, child) => sum + countExtensions(child), 0)\n : 1;\n\ntype EditorDiagnosticsProps = ThemedClassName<{}>;\n\n/**\n * Developer panel showing live editor state read from the CodeMirror `EditorState` (document size,\n * selection, viewport, configured-extension count). A debugging aid — gate it behind a dev/debug\n * setting; unrelated to `@codemirror/lint` diagnostics. Place inside `Editor.Root`, below the content.\n */\nconst EditorDiagnostics = ({ classNames }: EditorDiagnosticsProps) => {\n const { controller, extensions } = useEditorContext(EDITOR_DIAGNOSTICS_NAME);\n const view = controller?.view ?? null;\n // `EditorState` is immutable (a new object per transaction), so a reference change signals an update.\n // Poll on animation frames while mounted — self-contained (no injected updateListener) and re-renders\n // only when the state actually changes; catches programmatic transactions too.\n const [, setRevision] = useState(0);\n const lastState = useRef<EditorState | null>(null);\n useEffect(() => {\n if (!view) {\n return;\n }\n let frame = 0;\n const tick = () => {\n if (view.state !== lastState.current) {\n lastState.current = view.state;\n setRevision((revision) => revision + 1);\n }\n frame = requestAnimationFrame(tick);\n };\n frame = requestAnimationFrame(tick);\n return () => cancelAnimationFrame(frame);\n }, [view]);\n\n if (!view) {\n return null;\n }\n\n const { state } = view;\n const { doc, selection } = state;\n const { main } = selection;\n const head = doc.lineAt(main.head);\n // The context holds the extensions passed to `Root`; count leaves (CodeMirror does not expose the\n // resolved extension set at runtime, so this is the configured, not the active, count).\n const extensionCount = countExtensions(extensions);\n const item = (label: string, value: string | number) => (\n <span>\n <span className='text-subdued'>{label} </span>\n {value}\n </span>\n );\n\n return (\n <div\n className={mx(\n 'flex flex-wrap gap-x-4 gap-y-0.5 border-bs border-separator px-2 py-1 text-xs font-mono text-description',\n classNames,\n )}\n data-testid='editor.diagnostics'\n >\n {item('chars', doc.length)}\n {item('lines', doc.lines)}\n {item(\n 'cursor',\n main.empty ? `${head.number}:${main.head - head.from + 1}` : `${main.from}–${main.to} (${main.to - main.from})`,\n )}\n {selection.ranges.length > 1 && item('ranges', selection.ranges.length)}\n {item('viewport', `${view.viewport.from}–${view.viewport.to}`)}\n {item('mode', state.readOnly ? 'read-only' : 'editable')}\n {item('extensions', extensionCount)}\n </div>\n );\n};\n\nEditorDiagnostics.displayName = EDITOR_DIAGNOSTICS_NAME;\n\n//\n// Editor\n//\n\nexport const Editor = {\n Root: EditorRoot,\n Toolbar: EditorToolbar,\n Content: EditorContent,\n View: EditorView,\n Blocks: EditorBlocks,\n Diagnostics: EditorDiagnostics,\n};\n\nexport type {\n EditorContentProps,\n EditorController,\n EditorRootProps,\n EditorToolbarProps,\n EditorToolbarState,\n EditorViewProps,\n};\n","//\n// Copyright 2025 DXOS.org\n//\n\nimport { createContext } from '@radix-ui/react-context';\n\nimport { type PreviewLinkRef, type PreviewLinkTarget } from '@dxos/ui-types';\n\n// Kept out of `EditorPreviewProvider.tsx`: react-refresh only fast-refreshes a module whose exports are all\n// components, so a context and its hook exported beside them force a full page reload on every edit.\n\nexport type EditorPreviewPopoverValue = Partial<{\n link: PreviewLinkRef;\n target: PreviewLinkTarget;\n pending: boolean;\n}>;\n\nexport const [EditorPreviewContextProvider, useEditorPreview] = createContext<EditorPreviewPopoverValue>(\n 'PreviewPopover',\n {},\n);\n","//\n// Copyright 2025 DXOS.org\n//\n\nimport React, { type PropsWithChildren, type RefObject, useCallback, useEffect, useRef, useState } from 'react';\n\nimport { addEventListener } from '@dxos/async';\nimport { DX_ANCHOR_ACTIVATE, type DxAnchorActivate, Popover } from '@dxos/react-ui';\nimport { type PreviewLinkRef, type PreviewLinkTarget } from '@dxos/ui-types';\n\nimport { EditorPreviewContextProvider, type EditorPreviewPopoverValue } from './EditorPreviewContext';\n\nexport type EditorPreviewProviderProps = PropsWithChildren<{\n onLookup?: (link: PreviewLinkRef) => Promise<PreviewLinkTarget | null | undefined>;\n}>;\n\n/**\n * Standalone anchor-preview popover for use outside Composer (storybook, tests).\n * In Composer, PreviewPlugin listens on window for DX_ANCHOR_ACTIVATE events and\n * dispatches LayoutOperation.UpdatePopover instead; this provider is not needed there.\n */\nexport const EditorPreviewProvider = ({ children, onLookup }: EditorPreviewProviderProps) => {\n const triggerRef = useRef<HTMLElement | null>(null);\n const [value, setValue] = useState<EditorPreviewPopoverValue>({});\n const [open, setOpen] = useState(false);\n\n const handleActivate = useCallback(\n (event: DxAnchorActivate) => {\n const { dxn, label, trigger } = event;\n setValue((value) => ({\n ...value,\n link: { label, dxn },\n pending: true,\n }));\n\n triggerRef.current = trigger;\n queueMicrotask(() => setOpen(true));\n void onLookup?.({ label, dxn }).then((target) =>\n setValue((value) => ({\n ...value,\n target: target ?? undefined,\n pending: false,\n })),\n );\n },\n [onLookup],\n );\n\n const [root, setRoot] = useState<HTMLDivElement | null>(null);\n useEffect(() => {\n if (!root || !handleActivate) {\n return;\n }\n\n return addEventListener(root, DX_ANCHOR_ACTIVATE as any, handleActivate, {\n capture: true,\n passive: false,\n });\n }, [root, handleActivate]);\n\n return (\n <EditorPreviewContextProvider pending={value.pending} link={value.link} target={value.target}>\n <Popover.Root open={open} onOpenChange={setOpen}>\n <Popover.VirtualTrigger virtualRef={triggerRef as unknown as RefObject<HTMLButtonElement>} />\n <div className='contents' ref={setRoot}>\n {children}\n </div>\n </Popover.Root>\n </EditorPreviewContextProvider>\n );\n};\n"],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
//#region src/translations.ts
|
|
2
|
+
var translationKey = "@dxos/react-ui-editor";
|
|
3
|
+
var translations = [{ "en-US": { [translationKey]: {
|
|
4
|
+
"comment.label": "Create comment",
|
|
5
|
+
"image.label": "Insert image",
|
|
6
|
+
"search.label": "Search",
|
|
7
|
+
"block.label": "Block",
|
|
8
|
+
"block.blockquote.label": "Block quote",
|
|
9
|
+
"block.codeblock.label": "Code block",
|
|
10
|
+
"block.table.label": "Create table",
|
|
11
|
+
"formatting.label": "Formatting",
|
|
12
|
+
"formatting.strong.label": "Bold",
|
|
13
|
+
"formatting.emphasis.label": "Italics",
|
|
14
|
+
"formatting.strikethrough.label": "Strikethrough",
|
|
15
|
+
"formatting.code.label": "Code",
|
|
16
|
+
"formatting.link.label": "Link",
|
|
17
|
+
"list.bullet.label": "Bullet list",
|
|
18
|
+
"list.ordered.label": "Numbered list",
|
|
19
|
+
"list.task.label": "Task list",
|
|
20
|
+
"heading.label": "Heading level",
|
|
21
|
+
"heading-level.label_zero": "Paragraph",
|
|
22
|
+
"heading-level.label_one": "Heading level {{count}}",
|
|
23
|
+
"heading-level.label_other": "Heading level {{count}}",
|
|
24
|
+
"view-mode.label": "Editor view",
|
|
25
|
+
"view-mode.preview.label": "Markdown",
|
|
26
|
+
"view-mode.source.label": "Plain text",
|
|
27
|
+
"view-mode.readonly.label": "Read only"
|
|
28
|
+
} } }];
|
|
29
|
+
//#endregion
|
|
30
|
+
export { translationKey, translations };
|
|
31
|
+
|
|
32
|
+
//# sourceMappingURL=translations.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"translations.mjs","names":[],"sources":["../../src/translations.ts"],"sourcesContent":["//\n// Copyright 2023 DXOS.org\n//\n\nimport { type Resource } from '@dxos/react-ui';\n\nexport const translationKey = '@dxos/react-ui-editor';\n\nexport const translations = [\n {\n 'en-US': {\n [translationKey]: {\n 'comment.label': 'Create comment',\n 'image.label': 'Insert image',\n 'search.label': 'Search',\n\n 'block.label': 'Block',\n 'block.blockquote.label': 'Block quote',\n 'block.codeblock.label': 'Code block',\n 'block.table.label': 'Create table',\n\n 'formatting.label': 'Formatting',\n 'formatting.strong.label': 'Bold',\n 'formatting.emphasis.label': 'Italics',\n 'formatting.strikethrough.label': 'Strikethrough',\n 'formatting.code.label': 'Code',\n 'formatting.link.label': 'Link',\n\n 'list.bullet.label': 'Bullet list',\n 'list.ordered.label': 'Numbered list',\n 'list.task.label': 'Task list',\n\n 'heading.label': 'Heading level',\n 'heading-level.label_zero': 'Paragraph',\n 'heading-level.label_one': 'Heading level {{count}}',\n 'heading-level.label_other': 'Heading level {{count}}',\n\n 'view-mode.label': 'Editor view',\n 'view-mode.preview.label': 'Markdown',\n 'view-mode.source.label': 'Plain text',\n 'view-mode.readonly.label': 'Read only',\n },\n },\n },\n] as const satisfies Resource[];\n"],"mappings":";AAMA,IAAa,iBAAiB;AAE9B,IAAa,eAAe,CAC1B,EACE,SAAS,GACN,iBAAiB;CAChB,iBAAiB;CACjB,eAAe;CACf,gBAAgB;CAEhB,eAAe;CACf,0BAA0B;CAC1B,yBAAyB;CACzB,qBAAqB;CAErB,oBAAoB;CACpB,2BAA2B;CAC3B,6BAA6B;CAC7B,kCAAkC;CAClC,yBAAyB;CACzB,yBAAyB;CAEzB,qBAAqB;CACrB,sBAAsB;CACtB,mBAAmB;CAEnB,iBAAiB;CACjB,4BAA4B;CAC5B,2BAA2B;CAC3B,6BAA6B;CAE7B,mBAAmB;CACnB,2BAA2B;CAC3B,0BAA0B;CAC1B,4BAA4B;AAC9B,EACF,EACF,CACF"}
|
|
@@ -1,22 +1,11 @@
|
|
|
1
|
-
import { type Extension } from '@codemirror/state';
|
|
2
|
-
import { Atom } from '@effect-atom/atom-react';
|
|
3
1
|
import React, { type PropsWithChildren } from 'react';
|
|
4
2
|
import { type ThemedClassName } from '@dxos/react-ui';
|
|
5
3
|
import { type EditorMenuProviderProps, type UseEditorMenuProps } from '../EditorMenuProvider';
|
|
6
4
|
import { type EditorToolbarState, type EditorToolbarProps as NaturalEditorToolbarProps } from '../EditorToolbar';
|
|
7
|
-
import { type EditorController
|
|
8
|
-
type EditorContextValue
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
extensions?: Extension[];
|
|
12
|
-
state: Atom.Writable<EditorToolbarState>;
|
|
13
|
-
};
|
|
14
|
-
declare const useEditorContext: (consumerName: string) => EditorContextValue;
|
|
15
|
-
/**
|
|
16
|
-
* Access the editor context. Must be used within `Editor.Root`.
|
|
17
|
-
*/
|
|
18
|
-
export { useEditorContext };
|
|
19
|
-
type EditorRootProps = PropsWithChildren<Pick<EditorContextValue, 'extensions'> & Omit<UseEditorMenuProps, 'viewRef'> & Pick<EditorMenuProviderProps, 'numItems'> & {
|
|
5
|
+
import { type EditorController } from './controller';
|
|
6
|
+
import { type EditorContextValue } from './EditorContext';
|
|
7
|
+
import { type EditorViewProps as NaturalEditorContentProps } from './EditorView';
|
|
8
|
+
type EditorRootProps = PropsWithChildren<Pick<EditorContextValue, 'extensions' | 'widgets'> & Omit<UseEditorMenuProps, 'viewRef'> & Pick<EditorMenuProviderProps, 'numItems' | 'searchPlaceholder'> & {
|
|
20
9
|
viewMode?: EditorToolbarState['viewMode'];
|
|
21
10
|
}>;
|
|
22
11
|
type EditorContentProps = ThemedClassName<PropsWithChildren<{}>>;
|
|
@@ -34,8 +23,17 @@ declare function EditorToolbar(props: EditorToolbarProps): React.JSX.Element;
|
|
|
34
23
|
declare namespace EditorToolbar {
|
|
35
24
|
var displayName: string;
|
|
36
25
|
}
|
|
26
|
+
declare function EditorBlocks(): React.JSX.Element;
|
|
27
|
+
declare namespace EditorBlocks {
|
|
28
|
+
var displayName: string;
|
|
29
|
+
}
|
|
30
|
+
type EditorDiagnosticsProps = ThemedClassName<{}>;
|
|
31
|
+
declare function EditorDiagnostics({ classNames }: EditorDiagnosticsProps): React.JSX.Element | null;
|
|
32
|
+
declare namespace EditorDiagnostics {
|
|
33
|
+
var displayName: string;
|
|
34
|
+
}
|
|
37
35
|
export declare const Editor: {
|
|
38
|
-
Root: React.ForwardRefExoticComponent<Pick<EditorContextValue, "extensions"> & Omit<UseEditorMenuProps, "viewRef"> & Pick<EditorMenuProviderProps, "numItems"> & {
|
|
36
|
+
Root: React.ForwardRefExoticComponent<Pick<EditorContextValue, "extensions" | "widgets"> & Omit<UseEditorMenuProps, "viewRef"> & Pick<EditorMenuProviderProps, "numItems" | "searchPlaceholder"> & {
|
|
39
37
|
viewMode?: EditorToolbarState['viewMode'];
|
|
40
38
|
} & {
|
|
41
39
|
children?: React.ReactNode | undefined;
|
|
@@ -52,7 +50,14 @@ export declare const Editor: {
|
|
|
52
50
|
({ extensions: providedExtensions, ...props }: EditorViewProps): React.JSX.Element;
|
|
53
51
|
displayName: string;
|
|
54
52
|
};
|
|
53
|
+
Blocks: {
|
|
54
|
+
(): React.JSX.Element;
|
|
55
|
+
displayName: string;
|
|
56
|
+
};
|
|
57
|
+
Diagnostics: {
|
|
58
|
+
({ classNames }: EditorDiagnosticsProps): React.JSX.Element | null;
|
|
59
|
+
displayName: string;
|
|
60
|
+
};
|
|
55
61
|
};
|
|
56
62
|
export type { EditorContentProps, EditorController, EditorRootProps, EditorToolbarProps, EditorToolbarState, EditorViewProps, };
|
|
57
|
-
export { createEditorController };
|
|
58
63
|
//# sourceMappingURL=Editor.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Editor.d.ts","sourceRoot":"","sources":["../../../../../src/components/Editor/Editor.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"Editor.d.ts","sourceRoot":"","sources":["../../../../../src/components/Editor/Editor.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,EACZ,KAAK,iBAAiB,EAQvB,MAAM,OAAO,CAAC;AAIf,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAItD,OAAO,EAEL,KAAK,uBAAuB,EAC5B,KAAK,kBAAkB,EAExB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,KAAK,kBAAkB,EAEvB,KAAK,kBAAkB,IAAI,yBAAyB,EACrD,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,KAAK,gBAAgB,EAAkB,MAAM,cAAc,CAAC;AACrE,OAAO,EAAyB,KAAK,kBAAkB,EAAoB,MAAM,iBAAiB,CAAC;AACnG,OAAO,EAAsC,KAAK,eAAe,IAAI,yBAAyB,EAAE,MAAM,cAAc,CAAC;AAMrH,KAAK,eAAe,GAAG,iBAAiB,CACtC,IAAI,CAAC,kBAAkB,EAAE,YAAY,GAAG,SAAS,CAAC,GAChD,IAAI,CAAC,kBAAkB,EAAE,SAAS,CAAC,GACnC,IAAI,CAAC,uBAAuB,EAAE,UAAU,GAAG,mBAAmB,CAAC,GAAG;IAChE,QAAQ,CAAC,EAAE,kBAAkB,CAAC,UAAU,CAAC,CAAC;CAC3C,CACJ,CAAC;AAwDF,KAAK,kBAAkB,GAAG,eAAe,CAAC,iBAAiB,CAAC,EAAE,CAAC,CAAC,CAAC;+BAK1C,EAAE,UAAU,EAAE,QAAQ,EAAE,EAAE,kBAAkB;;;;AAYnE,KAAK,eAAe,GAAG,IAAI,CAAC,yBAAyB,EAAE,KAAK,CAAC,CAAC;4BAM1C,EAAE,UAAU,EAAE,kBAAkB,EAAE,GAAG,KAAK,EAAE,EAAE,eAAe;;;;AAkBjF,KAAK,kBAAkB,GAAG,IAAI,CAAC,yBAAyB,EAAE,SAAS,GAAG,OAAO,CAAC,CAAC;+BAMxD,KAAK,EAAE,kBAAkB;;;;;;;;AAiDhD,KAAK,sBAAsB,GAAG,eAAe,CAAC,EAAE,CAAC,CAAC;mCAOvB,EAAE,UAAU,EAAE,EAAE,sBAAsB;;;;AAsEjE,eAAO,MAAM,MAAM;IACjB,IAAI;mBAxOW,kBAAkB,CAAC,UAAU,CAAC;;;;IAyO7C,OAAO;gBAhIqB,kBAAkB;;;IAiI9C,OAAO;mCA3KwC,kBAAkB;;;IA4KjE,IAAI;uDA1J4D,eAAe;;;IA2J/E,MAAM;;;;IACN,WAAW;yBA5E8B,sBAAsB;;;CA6EhE,CAAC;AAEF,YAAY,EACV,kBAAkB,EAClB,gBAAgB,EAChB,eAAe,EACf,kBAAkB,EAClB,kBAAkB,EAClB,eAAe,GAChB,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { type Extension } from '@codemirror/state';
|
|
2
|
+
import { type Atom } from '@effect-atom/atom-react';
|
|
3
|
+
import { type XmlWidgetState } from '@dxos/ui-editor';
|
|
4
|
+
import { type EditorToolbarState } from '../EditorToolbar/types';
|
|
5
|
+
import { type EditorController } from './controller';
|
|
6
|
+
export type EditorContextValue = {
|
|
7
|
+
controller?: EditorController;
|
|
8
|
+
setController: (controller: EditorController) => void;
|
|
9
|
+
extensions?: Extension[];
|
|
10
|
+
/** xmlTags widget portals (embedded blocks); rendered by `Editor.Blocks`, fed via `setWidgets`. */
|
|
11
|
+
widgets?: XmlWidgetState[];
|
|
12
|
+
state: Atom.Writable<EditorToolbarState>;
|
|
13
|
+
};
|
|
14
|
+
export declare const EditorContextProvider: import("react").FC<EditorContextValue & {
|
|
15
|
+
children: React.ReactNode;
|
|
16
|
+
}>, useEditorContext: (consumerName: string) => EditorContextValue;
|
|
17
|
+
/**
|
|
18
|
+
* Access the editor context. Must be used within `Editor.Root`.
|
|
19
|
+
*/
|
|
20
|
+
//# sourceMappingURL=EditorContext.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EditorContext.d.ts","sourceRoot":"","sources":["../../../../../src/components/Editor/EditorContext.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,KAAK,IAAI,EAAE,MAAM,yBAAyB,CAAC;AAGpD,OAAO,EAAE,KAAK,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAEtD,OAAO,EAAE,KAAK,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,cAAc,CAAC;AASrD,MAAM,MAAM,kBAAkB,GAAG;IAC/B,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAC9B,aAAa,EAAE,CAAC,UAAU,EAAE,gBAAgB,KAAK,IAAI,CAAC;IACtD,UAAU,CAAC,EAAE,SAAS,EAAE,CAAC;IACzB,mGAAmG;IACnG,OAAO,CAAC,EAAE,cAAc,EAAE,CAAC;IAC3B,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC,kBAAkB,CAAC,CAAC;CAC1C,CAAC;AAEF,eAAO,MAAO,qBAAqB;;IAAE,gBAAgB,8CAA+C,CAAC;AAErG;;GAEG"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { type ThemedClassName } from '@dxos/react-ui';
|
|
3
3
|
import { type UseTextEditorProps } from '../../hooks';
|
|
4
|
-
import { type EditorController
|
|
4
|
+
import { type EditorController } from './controller';
|
|
5
5
|
export type EditorViewProps = ThemedClassName<{
|
|
6
6
|
focusable?: boolean;
|
|
7
7
|
value?: string;
|
|
@@ -27,5 +27,4 @@ export declare const EditorView: React.ForwardRefExoticComponent<Omit<{
|
|
|
27
27
|
}, "className"> & {
|
|
28
28
|
classNames?: import("@dxos/ui-types").ClassNameValue;
|
|
29
29
|
} & React.RefAttributes<EditorController>>;
|
|
30
|
-
export { type EditorController, createEditorController, noopController };
|
|
31
30
|
//# sourceMappingURL=EditorView.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EditorView.d.ts","sourceRoot":"","sources":["../../../../../src/components/Editor/EditorView.tsx"],"names":[],"mappings":"AAMA,OAAO,KAA6D,MAAM,OAAO,CAAC;AAElF,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAItD,OAAO,EAAE,KAAK,kBAAkB,EAAiB,MAAM,aAAa,CAAC;AACrE,OAAO,EAAE,KAAK,gBAAgB,
|
|
1
|
+
{"version":3,"file":"EditorView.d.ts","sourceRoot":"","sources":["../../../../../src/components/Editor/EditorView.tsx"],"names":[],"mappings":"AAMA,OAAO,KAA6D,MAAM,OAAO,CAAC;AAElF,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAItD,OAAO,EAAE,KAAK,kBAAkB,EAAiB,MAAM,aAAa,CAAC;AACrE,OAAO,EAAE,KAAK,gBAAgB,EAA0B,MAAM,cAAc,CAAC;AAE7E,MAAM,MAAM,eAAe,GAAG,eAAe,CAC3C;IACE,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACpC,GAAG,kBAAkB,CACvB,CAAC;AAEF;;;GAGG;AAEH,eAAO,MAAM,UAAU;gBAXP,OAAO;YACX,MAAM;eACH,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI;;;;;;;;;;;;0CAkFrC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/components/Editor/index.ts"],"names":[],"mappings":"AAIA,cAAc,UAAU,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/components/Editor/index.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,gBAAgB,EAAE,sBAAsB,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC7F,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAEnD,cAAc,UAAU,CAAC"}
|
|
@@ -8,6 +8,10 @@ export type EditorMenuProviderProps = PropsWithChildren<{
|
|
|
8
8
|
open?: boolean;
|
|
9
9
|
defaultOpen?: boolean;
|
|
10
10
|
numItems?: number;
|
|
11
|
+
/** Render the menu as a combobox: the popover owns the query input and takes focus from the editor. */
|
|
12
|
+
search?: boolean;
|
|
13
|
+
query?: string;
|
|
14
|
+
searchPlaceholder?: string;
|
|
11
15
|
onOpenChange?: (event: {
|
|
12
16
|
view: EditorView;
|
|
13
17
|
open: boolean;
|
|
@@ -24,11 +28,13 @@ export type EditorMenuProviderProps = PropsWithChildren<{
|
|
|
24
28
|
onCancel?: (event: {
|
|
25
29
|
view: EditorView;
|
|
26
30
|
}) => void;
|
|
31
|
+
onQueryChange?: (query: string) => void;
|
|
32
|
+
onNavigate?: (direction: 'up' | 'down') => void;
|
|
27
33
|
}>;
|
|
28
34
|
/**
|
|
29
35
|
* Implements the Popover and listens for the `dx-anchor-activate` event from the `popover` extension's decoration.
|
|
30
36
|
* NOTE: We don't use DropdownMenu because the command menu needs to manage focus explicitly.
|
|
31
37
|
* I.e., focus must remain in the editor while displaying the menu (for type-ahead).
|
|
32
38
|
*/
|
|
33
|
-
export declare const EditorMenuProvider: ({ children, getView, groups, currentItem, open: openProp, defaultOpen, numItems, onOpenChange, onActivate, onSelect, onCancel, }: EditorMenuProviderProps) => React.JSX.Element;
|
|
39
|
+
export declare const EditorMenuProvider: ({ children, getView, groups, currentItem, open: openProp, defaultOpen, numItems, search, query, searchPlaceholder, onOpenChange, onActivate, onSelect, onCancel, onQueryChange, onNavigate, }: EditorMenuProviderProps) => React.JSX.Element;
|
|
34
40
|
//# sourceMappingURL=EditorMenuProvider.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EditorMenuProvider.d.ts","sourceRoot":"","sources":["../../../../../src/components/EditorMenuProvider/EditorMenuProvider.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAEnD,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"EditorMenuProvider.d.ts","sourceRoot":"","sources":["../../../../../src/components/EditorMenuProvider/EditorMenuProvider.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAEnD,OAAO,KAAK,EAAE,EAGZ,KAAK,iBAAiB,EAKvB,MAAM,OAAO,CAAC;AAmBf,OAAO,EAAE,KAAK,eAAe,EAAE,KAAK,cAAc,EAAe,MAAM,QAAQ,CAAC;AAEhF,MAAM,MAAM,uBAAuB,GAAG,iBAAiB,CAAC;IAGtD,OAAO,CAAC,EAAE,MAAM,UAAU,GAAG,IAAI,CAAC;IAClC,MAAM,CAAC,EAAE,eAAe,EAAE,CAAC;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,uGAAuG;IACvG,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE;QAAE,IAAI,EAAE,UAAU,CAAC;QAAC,IAAI,EAAE,OAAO,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IACtF,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE;QAAE,IAAI,EAAE,UAAU,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IACrE,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE;QAAE,IAAI,EAAE,UAAU,CAAC;QAAC,IAAI,EAAE,cAAc,CAAA;KAAE,KAAK,IAAI,CAAC;IACvE,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE;QAAE,IAAI,EAAE,UAAU,CAAA;KAAE,KAAK,IAAI,CAAC;IACjD,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,UAAU,CAAC,EAAE,CAAC,SAAS,EAAE,IAAI,GAAG,MAAM,KAAK,IAAI,CAAC;CACjD,CAAC,CAAC;AAEH;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,kMAiB5B,uBAAuB,sBAkKzB,CAAC"}
|
|
@@ -16,8 +16,10 @@ export type EditorMenuItem = {
|
|
|
16
16
|
}) => MaybePromise<void>;
|
|
17
17
|
};
|
|
18
18
|
export declare const getMenuItem: (groups: EditorMenuGroup[], id?: string) => EditorMenuItem | undefined;
|
|
19
|
-
|
|
20
|
-
export declare const
|
|
19
|
+
/** Undefined when the menu is empty; at either end the current item is returned unchanged. */
|
|
20
|
+
export declare const getNextMenuItem: (groups: EditorMenuGroup[], id?: string) => EditorMenuItem | undefined;
|
|
21
|
+
/** Undefined when the menu is empty; at either end the current item is returned unchanged. */
|
|
22
|
+
export declare const getPreviousMenuItem: (groups: EditorMenuGroup[], id?: string) => EditorMenuItem | undefined;
|
|
21
23
|
export declare const createMenuGroup: ({ id, label, filter, items, }: {
|
|
22
24
|
id?: string;
|
|
23
25
|
label?: Label;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"menu.d.ts","sourceRoot":"","sources":["../../../../../src/components/EditorMenuProvider/menu.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAEnD,OAAO,EAAE,KAAK,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAE5C,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C,MAAM,MAAM,eAAe,GAAG;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,KAAK,EAAE,cAAc,EAAE,CAAC;CACzB,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,KAAK,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE;QAAE,IAAI,EAAE,UAAU,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,KAAK,YAAY,CAAC,IAAI,CAAC,CAAC;CAC9E,CAAC;AAEF,eAAO,MAAM,WAAW,WAAY,eAAe,EAAE,OAAO,MAAM,KAAG,cAAc,GAAG,SAErF,CAAC;AAEF,eAAO,MAAM,eAAe,WAAY,eAAe,EAAE,OAAO,MAAM,KAAG,
|
|
1
|
+
{"version":3,"file":"menu.d.ts","sourceRoot":"","sources":["../../../../../src/components/EditorMenuProvider/menu.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAEnD,OAAO,EAAE,KAAK,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAE5C,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C,MAAM,MAAM,eAAe,GAAG;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,KAAK,EAAE,cAAc,EAAE,CAAC;CACzB,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,KAAK,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE;QAAE,IAAI,EAAE,UAAU,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,KAAK,YAAY,CAAC,IAAI,CAAC,CAAC;CAC9E,CAAC;AAEF,eAAO,MAAM,WAAW,WAAY,eAAe,EAAE,OAAO,MAAM,KAAG,cAAc,GAAG,SAErF,CAAC;AAEF,8FAA8F;AAC9F,eAAO,MAAM,eAAe,WAAY,eAAe,EAAE,OAAO,MAAM,KAAG,cAAc,GAAG,SAIzF,CAAC;AAEF,8FAA8F;AAC9F,eAAO,MAAM,mBAAmB,WAAY,eAAe,EAAE,OAAO,MAAM,KAAG,cAAc,GAAG,SAI7F,CAAC;AAEF,eAAO,MAAM,eAAe,kCAKzB;IACD,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB,KAAG,eAUF,CAAC;AAEH,eAAO,MAAM,gBAAgB,WACnB,eAAe,EAAE,UACjB,CAAC,IAAI,EAAE,cAAc,KAAK,OAAO,KACxC,eAAe,EAKjB,CAAC"}
|
|
@@ -13,12 +13,17 @@ export type GetMenuContext = {
|
|
|
13
13
|
};
|
|
14
14
|
export type UseEditorMenuProps = {
|
|
15
15
|
filter?: boolean;
|
|
16
|
+
/**
|
|
17
|
+
* Triggers whose menu is rendered as a combobox: the popover owns a search input and the query is
|
|
18
|
+
* typed there rather than into the document.
|
|
19
|
+
*/
|
|
20
|
+
searchTriggers?: string[];
|
|
16
21
|
getMenu?: (context: GetMenuContext) => MaybePromise<EditorMenuGroup[]>;
|
|
17
22
|
} & Pick<PopoverOptions, 'trigger' | 'triggerKey' | 'placeholder' | 'activateOnTyping'>;
|
|
18
23
|
export type UseEditorMenu = {
|
|
19
24
|
groupsRef: RefObject<EditorMenuGroup[]>;
|
|
20
25
|
extension: Extension;
|
|
21
|
-
} & Pick<EditorMenuProviderProps, 'currentItem' | 'open' | 'onOpenChange' | 'onActivate' | 'onSelect' | 'onCancel'>;
|
|
26
|
+
} & Pick<EditorMenuProviderProps, 'currentItem' | 'open' | 'search' | 'query' | 'onOpenChange' | 'onActivate' | 'onSelect' | 'onCancel' | 'onQueryChange' | 'onNavigate'>;
|
|
22
27
|
/**
|
|
23
28
|
* ```tsx
|
|
24
29
|
* const { groupsRef, extension, ...menuProps } = useEditorMenu();
|
|
@@ -30,5 +35,5 @@ export type UseEditorMenu = {
|
|
|
30
35
|
* );
|
|
31
36
|
* ```
|
|
32
37
|
*/
|
|
33
|
-
export declare const useEditorMenu: ({ trigger, triggerKey, placeholder, activateOnTyping, filter, getMenu, }: UseEditorMenuProps) => UseEditorMenu;
|
|
38
|
+
export declare const useEditorMenu: ({ trigger, triggerKey, placeholder, activateOnTyping, filter, searchTriggers, getMenu, }: UseEditorMenuProps) => UseEditorMenu;
|
|
34
39
|
//# sourceMappingURL=useEditorMenu.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useEditorMenu.d.ts","sourceRoot":"","sources":["../../../../../src/components/EditorMenuProvider/useEditorMenu.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"useEditorMenu.d.ts","sourceRoot":"","sources":["../../../../../src/components/EditorMenuProvider/useEditorMenu.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD,OAAO,EAAE,KAAK,SAAS,EAA0C,MAAM,OAAO,CAAC;AAI/E,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C,OAAO,EAAE,KAAK,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AACpE,OAAO,EAAE,KAAK,eAAe,EAAuB,MAAM,QAAQ,CAAC;AAEnE,OAAO,EAAE,KAAK,cAAc,EAAkD,MAAM,WAAW,CAAC;AAEhG,MAAM,MAAM,cAAc,GAAG;IAC3B,KAAK,EAAE,WAAW,CAAC;IACnB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,YAAY,CAAC,eAAe,EAAE,CAAC,CAAC;CACxE,GAAG,IAAI,CAAC,cAAc,EAAE,SAAS,GAAG,YAAY,GAAG,aAAa,GAAG,kBAAkB,CAAC,CAAC;AAExF,MAAM,MAAM,aAAa,GAAG;IAC1B,SAAS,EAAE,SAAS,CAAC,eAAe,EAAE,CAAC,CAAC;IACxC,SAAS,EAAE,SAAS,CAAC;CACtB,GAAG,IAAI,CACN,uBAAuB,EACrB,aAAa,GACb,MAAM,GACN,QAAQ,GACR,OAAO,GACP,cAAc,GACd,YAAY,GACZ,UAAU,GACV,UAAU,GACV,eAAe,GACf,YAAY,CACf,CAAC;AAEF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,aAAa,6FAQvB,kBAAkB,KAAG,aA0MvB,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { type PreviewLinkRef, type PreviewLinkTarget } from '@dxos/ui-types';
|
|
2
|
+
export type EditorPreviewPopoverValue = Partial<{
|
|
3
|
+
link: PreviewLinkRef;
|
|
4
|
+
target: PreviewLinkTarget;
|
|
5
|
+
pending: boolean;
|
|
6
|
+
}>;
|
|
7
|
+
export declare const EditorPreviewContextProvider: import("react").FC<Partial<{
|
|
8
|
+
link: PreviewLinkRef;
|
|
9
|
+
target: PreviewLinkTarget;
|
|
10
|
+
pending: boolean;
|
|
11
|
+
}> & {
|
|
12
|
+
children: React.ReactNode;
|
|
13
|
+
}>, useEditorPreview: (consumerName: string) => Partial<{
|
|
14
|
+
link: PreviewLinkRef;
|
|
15
|
+
target: PreviewLinkTarget;
|
|
16
|
+
pending: boolean;
|
|
17
|
+
}>;
|
|
18
|
+
//# sourceMappingURL=EditorPreviewContext.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EditorPreviewContext.d.ts","sourceRoot":"","sources":["../../../../../src/components/EditorPreviewProvider/EditorPreviewContext.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,KAAK,cAAc,EAAE,KAAK,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAK7E,MAAM,MAAM,yBAAyB,GAAG,OAAO,CAAC;IAC9C,IAAI,EAAE,cAAc,CAAC;IACrB,MAAM,EAAE,iBAAiB,CAAC;IAC1B,OAAO,EAAE,OAAO,CAAC;CAClB,CAAC,CAAC;AAEH,eAAO,MAAO,4BAA4B;UALlC,cAAc;YACZ,iBAAiB;aAChB,OAAO;;;IAG0B,gBAAgB;UALpD,cAAc;YACZ,iBAAiB;aAChB,OAAO;EAMjB,CAAC"}
|
|
@@ -1,10 +1,5 @@
|
|
|
1
1
|
import React, { type PropsWithChildren } from 'react';
|
|
2
2
|
import { type PreviewLinkRef, type PreviewLinkTarget } from '@dxos/ui-types';
|
|
3
|
-
declare const useEditorPreview: (consumerName: string) => Partial<{
|
|
4
|
-
link: PreviewLinkRef;
|
|
5
|
-
target: PreviewLinkTarget;
|
|
6
|
-
pending: boolean;
|
|
7
|
-
}>;
|
|
8
3
|
export type EditorPreviewProviderProps = PropsWithChildren<{
|
|
9
4
|
onLookup?: (link: PreviewLinkRef) => Promise<PreviewLinkTarget | null | undefined>;
|
|
10
5
|
}>;
|
|
@@ -14,5 +9,4 @@ export type EditorPreviewProviderProps = PropsWithChildren<{
|
|
|
14
9
|
* dispatches LayoutOperation.UpdatePopover instead; this provider is not needed there.
|
|
15
10
|
*/
|
|
16
11
|
export declare const EditorPreviewProvider: ({ children, onLookup }: EditorPreviewProviderProps) => React.JSX.Element;
|
|
17
|
-
export { useEditorPreview };
|
|
18
12
|
//# sourceMappingURL=EditorPreviewProvider.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EditorPreviewProvider.d.ts","sourceRoot":"","sources":["../../../../../src/components/EditorPreviewProvider/EditorPreviewProvider.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"EditorPreviewProvider.d.ts","sourceRoot":"","sources":["../../../../../src/components/EditorPreviewProvider/EditorPreviewProvider.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,EAAE,KAAK,iBAAiB,EAA4D,MAAM,OAAO,CAAC;AAIhH,OAAO,EAAE,KAAK,cAAc,EAAE,KAAK,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAI7E,MAAM,MAAM,0BAA0B,GAAG,iBAAiB,CAAC;IACzD,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,cAAc,KAAK,OAAO,CAAC,iBAAiB,GAAG,IAAI,GAAG,SAAS,CAAC,CAAC;CACpF,CAAC,CAAC;AAEH;;;;GAIG;AACH,eAAO,MAAM,qBAAqB,2BAA4B,0BAA0B,sBAiDvF,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/components/EditorPreviewProvider/index.ts"],"names":[],"mappings":"AAIA,cAAc,yBAAyB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/components/EditorPreviewProvider/index.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAE1D,cAAc,yBAAyB,CAAC"}
|