@dxos/react-ui-editor 0.8.4-main.5ea62a8 → 0.8.4-main.72ec0f3
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/browser/{chunk-22UMM3QJ.mjs → chunk-HL3YF6WC.mjs} +2 -2
- package/dist/lib/browser/chunk-HL3YF6WC.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +5006 -3698
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/types/index.mjs +1 -1
- package/dist/lib/node-esm/{chunk-YXYQPV6R.mjs → chunk-YJZGD3LY.mjs} +2 -2
- package/dist/lib/node-esm/chunk-YJZGD3LY.mjs.map +7 -0
- package/dist/lib/node-esm/index.mjs +5006 -3698
- package/dist/lib/node-esm/index.mjs.map +4 -4
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/lib/node-esm/types/index.mjs +1 -1
- package/dist/types/src/components/Editor/Editor.d.ts +37 -15
- package/dist/types/src/components/Editor/Editor.d.ts.map +1 -1
- package/dist/types/src/components/Editor/Editor.stories.d.ts +20 -0
- package/dist/types/src/components/Editor/Editor.stories.d.ts.map +1 -0
- package/dist/types/src/components/EditorContent/EditorContent.d.ts +29 -0
- package/dist/types/src/components/EditorContent/EditorContent.d.ts.map +1 -0
- package/dist/types/src/components/EditorContent/EditorContent.stories.d.ts +26 -0
- package/dist/types/src/components/EditorContent/EditorContent.stories.d.ts.map +1 -0
- package/dist/types/src/components/EditorContent/controller.d.ts +10 -0
- package/dist/types/src/components/EditorContent/controller.d.ts.map +1 -0
- package/dist/types/src/components/EditorContent/index.d.ts +3 -0
- package/dist/types/src/components/EditorContent/index.d.ts.map +1 -0
- package/dist/types/src/components/EditorMenuProvider/EditorMenuProvider.d.ts +36 -0
- package/dist/types/src/components/EditorMenuProvider/EditorMenuProvider.d.ts.map +1 -0
- package/dist/types/src/components/EditorMenuProvider/index.d.ts +7 -0
- package/dist/types/src/components/EditorMenuProvider/index.d.ts.map +1 -0
- package/dist/types/src/components/EditorMenuProvider/menu-presets.d.ts +4 -0
- package/dist/types/src/components/EditorMenuProvider/menu-presets.d.ts.map +1 -0
- package/dist/types/src/components/EditorMenuProvider/menu.d.ts +28 -0
- package/dist/types/src/components/EditorMenuProvider/menu.d.ts.map +1 -0
- package/dist/types/src/components/EditorMenuProvider/popover.d.ts +47 -0
- package/dist/types/src/components/EditorMenuProvider/popover.d.ts.map +1 -0
- package/dist/types/src/components/EditorMenuProvider/useEditorMenu.d.ts +34 -0
- package/dist/types/src/components/EditorMenuProvider/useEditorMenu.d.ts.map +1 -0
- package/dist/types/src/components/EditorMenuProvider/util.d.ts +8 -0
- package/dist/types/src/components/EditorMenuProvider/util.d.ts.map +1 -0
- package/dist/types/src/components/EditorPreviewProvider/EditorPreviewProvider.d.ts +16 -0
- package/dist/types/src/components/EditorPreviewProvider/EditorPreviewProvider.d.ts.map +1 -0
- package/dist/types/src/components/EditorPreviewProvider/index.d.ts +2 -0
- package/dist/types/src/components/EditorPreviewProvider/index.d.ts.map +1 -0
- package/dist/types/src/components/EditorToolbar/EditorToolbar.d.ts +26 -2
- package/dist/types/src/components/EditorToolbar/EditorToolbar.d.ts.map +1 -1
- package/dist/types/src/components/EditorToolbar/actions.d.ts +39 -0
- package/dist/types/src/components/EditorToolbar/actions.d.ts.map +1 -0
- package/dist/types/src/components/EditorToolbar/blocks.d.ts +3 -3
- package/dist/types/src/components/EditorToolbar/blocks.d.ts.map +1 -1
- package/dist/types/src/components/EditorToolbar/formatting.d.ts +3 -3
- package/dist/types/src/components/EditorToolbar/formatting.d.ts.map +1 -1
- package/dist/types/src/components/EditorToolbar/headings.d.ts +3 -3
- package/dist/types/src/components/EditorToolbar/headings.d.ts.map +1 -1
- package/dist/types/src/components/EditorToolbar/index.d.ts +2 -1
- package/dist/types/src/components/EditorToolbar/index.d.ts.map +1 -1
- package/dist/types/src/components/EditorToolbar/useEditorToolbar.d.ts +11 -0
- package/dist/types/src/components/EditorToolbar/useEditorToolbar.d.ts.map +1 -0
- package/dist/types/src/components/EditorToolbar/view-mode.d.ts +3 -3
- package/dist/types/src/components/EditorToolbar/view-mode.d.ts.map +1 -1
- package/dist/types/src/components/index.d.ts +4 -2
- package/dist/types/src/components/index.d.ts.map +1 -1
- package/dist/types/src/extensions/autocomplete/autocomplete.d.ts +17 -0
- package/dist/types/src/extensions/autocomplete/autocomplete.d.ts.map +1 -0
- package/dist/types/src/extensions/autocomplete/index.d.ts +5 -0
- package/dist/types/src/extensions/autocomplete/index.d.ts.map +1 -0
- package/dist/types/src/extensions/autocomplete/match.d.ts +13 -0
- package/dist/types/src/extensions/autocomplete/match.d.ts.map +1 -0
- package/dist/types/src/extensions/autocomplete/placeholder.d.ts +20 -0
- package/dist/types/src/extensions/autocomplete/placeholder.d.ts.map +1 -0
- package/dist/types/src/extensions/autocomplete/typeahead.d.ts +10 -0
- package/dist/types/src/extensions/autocomplete/typeahead.d.ts.map +1 -0
- package/dist/types/src/extensions/automerge/automerge.d.ts +1 -1
- package/dist/types/src/extensions/automerge/automerge.d.ts.map +1 -1
- package/dist/types/src/extensions/automerge/automerge.stories.d.ts +1 -1
- package/dist/types/src/extensions/automerge/automerge.stories.d.ts.map +1 -1
- package/dist/types/src/extensions/automerge/cursor.d.ts +1 -1
- package/dist/types/src/extensions/automerge/cursor.d.ts.map +1 -1
- package/dist/types/src/extensions/automerge/sync.d.ts +3 -3
- package/dist/types/src/extensions/automerge/sync.d.ts.map +1 -1
- package/dist/types/src/extensions/automerge/update-automerge.d.ts +1 -1
- package/dist/types/src/extensions/automerge/update-automerge.d.ts.map +1 -1
- package/dist/types/src/extensions/autoscroll.d.ts +20 -0
- package/dist/types/src/extensions/autoscroll.d.ts.map +1 -0
- package/dist/types/src/extensions/awareness/awareness-provider.d.ts +1 -1
- package/dist/types/src/extensions/awareness/awareness-provider.d.ts.map +1 -1
- package/dist/types/src/extensions/blocks.d.ts +2 -0
- package/dist/types/src/extensions/blocks.d.ts.map +1 -0
- package/dist/types/src/extensions/bookmarks.d.ts +12 -0
- package/dist/types/src/extensions/bookmarks.d.ts.map +1 -0
- package/dist/types/src/extensions/comments.d.ts.map +1 -1
- package/dist/types/src/extensions/factories.d.ts +11 -11
- package/dist/types/src/extensions/factories.d.ts.map +1 -1
- package/dist/types/src/extensions/focus.d.ts.map +1 -1
- package/dist/types/src/extensions/folding.d.ts.map +1 -1
- package/dist/types/src/extensions/index.d.ts +10 -1
- package/dist/types/src/extensions/index.d.ts.map +1 -1
- package/dist/types/src/extensions/json.d.ts +1 -1
- package/dist/types/src/extensions/json.d.ts.map +1 -1
- package/dist/types/src/extensions/listener.d.ts +8 -6
- package/dist/types/src/extensions/listener.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/bundle.d.ts +6 -2
- package/dist/types/src/extensions/markdown/bundle.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/changes.d.ts +1 -1
- package/dist/types/src/extensions/markdown/changes.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/decorate.d.ts +9 -1
- package/dist/types/src/extensions/markdown/decorate.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/formatting.d.ts +1 -3
- package/dist/types/src/extensions/markdown/formatting.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/image.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/link.d.ts.map +1 -1
- package/dist/types/src/extensions/modal.d.ts +7 -0
- package/dist/types/src/extensions/modal.d.ts.map +1 -0
- package/dist/types/src/extensions/modes.d.ts +1 -1
- package/dist/types/src/extensions/modes.d.ts.map +1 -1
- package/dist/types/src/extensions/outliner/menu.d.ts +8 -0
- package/dist/types/src/extensions/outliner/menu.d.ts.map +1 -0
- package/dist/types/src/extensions/outliner/outliner.d.ts +1 -1
- package/dist/types/src/extensions/outliner/outliner.d.ts.map +1 -1
- package/dist/types/src/extensions/outliner/tree.d.ts +1 -1
- package/dist/types/src/extensions/outliner/tree.d.ts.map +1 -1
- package/dist/types/src/extensions/preview/preview.d.ts +8 -8
- package/dist/types/src/extensions/preview/preview.d.ts.map +1 -1
- package/dist/types/src/extensions/replacer.d.ts +21 -0
- package/dist/types/src/extensions/replacer.d.ts.map +1 -0
- package/dist/types/src/extensions/replacer.test.d.ts +2 -0
- package/dist/types/src/extensions/replacer.test.d.ts.map +1 -0
- package/dist/types/src/extensions/scrolling.d.ts +78 -0
- package/dist/types/src/extensions/scrolling.d.ts.map +1 -0
- package/dist/types/src/extensions/state.d.ts +2 -0
- package/dist/types/src/extensions/state.d.ts.map +1 -0
- package/dist/types/src/extensions/submit.d.ts +10 -0
- package/dist/types/src/extensions/submit.d.ts.map +1 -0
- package/dist/types/src/extensions/tab.d.ts +4 -0
- package/dist/types/src/extensions/tab.d.ts.map +1 -0
- package/dist/types/src/extensions/tags/extended-markdown.d.ts +10 -0
- package/dist/types/src/extensions/tags/extended-markdown.d.ts.map +1 -0
- package/dist/types/src/extensions/tags/extended-markdown.test.d.ts +2 -0
- package/dist/types/src/extensions/tags/extended-markdown.test.d.ts.map +1 -0
- package/dist/types/src/extensions/tags/index.d.ts +4 -0
- package/dist/types/src/extensions/tags/index.d.ts.map +1 -0
- package/dist/types/src/extensions/tags/streamer.d.ts +12 -0
- package/dist/types/src/extensions/tags/streamer.d.ts.map +1 -0
- package/dist/types/src/extensions/tags/xml-tags.d.ts +97 -0
- package/dist/types/src/extensions/tags/xml-tags.d.ts.map +1 -0
- package/dist/types/src/extensions/tags/xml-util.d.ts +10 -0
- package/dist/types/src/extensions/tags/xml-util.d.ts.map +1 -0
- package/dist/types/src/hooks/useTextEditor.d.ts +5 -9
- package/dist/types/src/hooks/useTextEditor.d.ts.map +1 -1
- package/dist/types/src/stories/{Command.stories.d.ts → CommandDialog.stories.d.ts} +2 -3
- package/dist/types/src/stories/CommandDialog.stories.d.ts.map +1 -0
- package/dist/types/src/stories/Comments.stories.d.ts +3 -4
- package/dist/types/src/stories/Comments.stories.d.ts.map +1 -1
- package/dist/types/src/stories/EditorToolbar.stories.d.ts +1 -2
- package/dist/types/src/stories/EditorToolbar.stories.d.ts.map +1 -1
- package/dist/types/src/stories/Experimental.stories.d.ts +3 -4
- package/dist/types/src/stories/Experimental.stories.d.ts.map +1 -1
- package/dist/types/src/stories/Markdown.stories.d.ts +3 -4
- package/dist/types/src/stories/Markdown.stories.d.ts.map +1 -1
- package/dist/types/src/stories/Outliner.stories.d.ts +0 -1
- package/dist/types/src/stories/Outliner.stories.d.ts.map +1 -1
- package/dist/types/src/stories/{CommandMenu.stories.d.ts → Popover.stories.d.ts} +6 -6
- package/dist/types/src/stories/Popover.stories.d.ts.map +1 -0
- package/dist/types/src/stories/Preview.stories.d.ts +4 -4
- package/dist/types/src/stories/Preview.stories.d.ts.map +1 -1
- package/dist/types/src/stories/Tags.stories.d.ts +16 -0
- package/dist/types/src/stories/Tags.stories.d.ts.map +1 -0
- package/dist/types/src/stories/TextEditor.stories.d.ts +3 -5
- package/dist/types/src/stories/TextEditor.stories.d.ts.map +1 -1
- package/dist/types/src/stories/components/EditorStory.d.ts +7 -5
- package/dist/types/src/stories/components/EditorStory.d.ts.map +1 -1
- package/dist/types/src/stories/components/util.d.ts.map +1 -1
- package/dist/types/src/styles/theme.d.ts.map +1 -1
- package/dist/types/src/types/types.d.ts +2 -2
- package/dist/types/src/types/types.d.ts.map +1 -1
- package/dist/types/src/util/debug.d.ts +5 -1
- package/dist/types/src/util/debug.d.ts.map +1 -1
- package/dist/types/src/util/decorations.d.ts +4 -0
- package/dist/types/src/util/decorations.d.ts.map +1 -0
- package/dist/types/src/util/dom.d.ts +2 -12
- package/dist/types/src/util/dom.d.ts.map +1 -1
- package/dist/types/src/util/index.d.ts +1 -0
- package/dist/types/src/util/index.d.ts.map +1 -1
- package/dist/types/src/util/react.d.ts +1 -1
- package/dist/types/src/util/react.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +68 -66
- package/src/components/Editor/Editor.stories.tsx +89 -0
- package/src/components/Editor/Editor.tsx +160 -25
- package/src/components/EditorContent/EditorContent.stories.tsx +70 -0
- package/src/components/EditorContent/EditorContent.tsx +70 -0
- package/src/components/EditorContent/controller.ts +50 -0
- package/src/components/EditorContent/index.ts +6 -0
- package/src/components/EditorMenuProvider/EditorMenuProvider.tsx +233 -0
- package/src/components/EditorMenuProvider/index.ts +11 -0
- package/src/components/EditorMenuProvider/menu-presets.ts +123 -0
- package/src/components/EditorMenuProvider/menu.ts +71 -0
- package/src/components/EditorMenuProvider/popover.ts +287 -0
- package/src/components/EditorMenuProvider/useEditorMenu.ts +175 -0
- package/src/components/EditorMenuProvider/util.ts +31 -0
- package/src/components/EditorPreviewProvider/EditorPreviewProvider.tsx +82 -0
- package/src/components/EditorPreviewProvider/index.ts +5 -0
- package/src/components/EditorToolbar/EditorToolbar.tsx +101 -91
- package/src/components/EditorToolbar/{lists.ts → actions.ts} +46 -16
- package/src/components/EditorToolbar/blocks.ts +2 -1
- package/src/components/EditorToolbar/formatting.ts +2 -1
- package/src/components/EditorToolbar/headings.ts +8 -5
- package/src/components/EditorToolbar/image.ts +1 -1
- package/src/components/EditorToolbar/index.ts +3 -7
- package/src/components/EditorToolbar/search.ts +1 -1
- package/src/components/EditorToolbar/useEditorToolbar.ts +20 -0
- package/src/components/EditorToolbar/view-mode.ts +2 -1
- package/src/components/index.ts +8 -2
- package/src/extensions/autocomplete/autocomplete.ts +151 -0
- package/src/extensions/autocomplete/index.ts +8 -0
- package/src/extensions/autocomplete/match.ts +46 -0
- package/src/extensions/{command → autocomplete}/placeholder.ts +21 -17
- package/src/extensions/{command → autocomplete}/typeahead.ts +6 -48
- package/src/extensions/automerge/automerge.stories.tsx +9 -9
- package/src/extensions/automerge/automerge.ts +28 -9
- package/src/extensions/automerge/cursor.ts +1 -1
- package/src/extensions/automerge/sync.ts +8 -4
- package/src/extensions/automerge/update-automerge.ts +1 -1
- package/src/extensions/autoscroll.ts +163 -0
- package/src/extensions/awareness/awareness-provider.ts +2 -2
- package/src/extensions/blocks.ts +131 -0
- package/src/extensions/bookmarks.ts +75 -0
- package/src/extensions/comments.ts +7 -2
- package/src/extensions/factories.ts +50 -32
- package/src/extensions/focus.ts +5 -4
- package/src/extensions/folding.tsx +3 -6
- package/src/extensions/hashtag.tsx +2 -2
- package/src/extensions/index.ts +10 -1
- package/src/extensions/json.ts +1 -1
- package/src/extensions/listener.ts +14 -20
- package/src/extensions/markdown/bundle.ts +37 -6
- package/src/extensions/markdown/decorate.ts +26 -17
- package/src/extensions/markdown/formatting.ts +8 -10
- package/src/extensions/markdown/highlight.ts +1 -1
- package/src/extensions/markdown/image.ts +5 -6
- package/src/extensions/markdown/link.ts +3 -0
- package/src/extensions/markdown/table.ts +13 -7
- package/src/extensions/modal.ts +24 -0
- package/src/extensions/modes.ts +2 -2
- package/src/extensions/{command/floating-menu.ts → outliner/menu.ts} +16 -21
- package/src/extensions/outliner/outliner.test.ts +1 -1
- package/src/extensions/outliner/outliner.ts +5 -5
- package/src/extensions/outliner/tree.test.ts +1 -1
- package/src/extensions/outliner/tree.ts +1 -1
- package/src/extensions/preview/index.ts +1 -1
- package/src/extensions/preview/preview.ts +69 -69
- package/src/extensions/replacer.test.ts +75 -0
- package/src/extensions/replacer.ts +93 -0
- package/src/extensions/scrolling.ts +189 -0
- package/src/extensions/selection.ts +3 -3
- package/src/extensions/state.ts +7 -0
- package/src/extensions/submit.ts +62 -0
- package/src/extensions/tab.ts +29 -0
- package/src/extensions/tags/extended-markdown.test.ts +262 -0
- package/src/extensions/tags/extended-markdown.ts +78 -0
- package/src/extensions/tags/index.ts +7 -0
- package/src/extensions/tags/streamer.ts +243 -0
- package/src/extensions/tags/xml-tags.ts +500 -0
- package/src/extensions/tags/xml-util.ts +94 -0
- package/src/extensions/typewriter.ts +1 -1
- package/src/hooks/useTextEditor.ts +31 -43
- package/src/stories/CommandDialog.stories.tsx +83 -0
- package/src/stories/Comments.stories.tsx +8 -9
- package/src/stories/EditorToolbar.stories.tsx +15 -14
- package/src/stories/Experimental.stories.tsx +7 -7
- package/src/stories/Markdown.stories.tsx +6 -6
- package/src/stories/Outliner.stories.tsx +40 -32
- package/src/stories/Popover.stories.tsx +162 -0
- package/src/stories/Preview.stories.tsx +46 -43
- package/src/stories/Tags.stories.tsx +95 -0
- package/src/stories/TextEditor.stories.tsx +10 -33
- package/src/stories/components/EditorStory.tsx +30 -17
- package/src/stories/components/util.tsx +40 -8
- package/src/styles/markdown.ts +1 -1
- package/src/styles/theme.ts +13 -11
- package/src/types/types.ts +1 -1
- package/src/util/debug.ts +7 -2
- package/src/util/decorations.ts +21 -0
- package/src/util/dom.ts +5 -27
- package/src/util/index.ts +1 -0
- package/src/util/react.tsx +1 -1
- package/dist/lib/browser/chunk-22UMM3QJ.mjs.map +0 -7
- package/dist/lib/browser/testing/index.mjs +0 -6
- package/dist/lib/browser/testing/index.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-YXYQPV6R.mjs.map +0 -7
- package/dist/lib/node-esm/testing/index.mjs +0 -8
- package/dist/lib/node-esm/testing/index.mjs.map +0 -7
- package/dist/types/src/components/EditorToolbar/lists.d.ts +0 -19
- package/dist/types/src/components/EditorToolbar/lists.d.ts.map +0 -1
- package/dist/types/src/components/EditorToolbar/util.d.ts +0 -51
- package/dist/types/src/components/EditorToolbar/util.d.ts.map +0 -1
- package/dist/types/src/components/Popover/CommandMenu.d.ts +0 -34
- package/dist/types/src/components/Popover/CommandMenu.d.ts.map +0 -1
- package/dist/types/src/components/Popover/RefDropdownMenu.d.ts +0 -21
- package/dist/types/src/components/Popover/RefDropdownMenu.d.ts.map +0 -1
- package/dist/types/src/components/Popover/RefPopover.d.ts +0 -34
- package/dist/types/src/components/Popover/RefPopover.d.ts.map +0 -1
- package/dist/types/src/components/Popover/index.d.ts +0 -4
- package/dist/types/src/components/Popover/index.d.ts.map +0 -1
- package/dist/types/src/extensions/autocomplete.d.ts +0 -13
- package/dist/types/src/extensions/autocomplete.d.ts.map +0 -1
- package/dist/types/src/extensions/command/action.d.ts +0 -17
- package/dist/types/src/extensions/command/action.d.ts.map +0 -1
- package/dist/types/src/extensions/command/command-menu.d.ts +0 -20
- package/dist/types/src/extensions/command/command-menu.d.ts.map +0 -1
- package/dist/types/src/extensions/command/command.d.ts +0 -6
- package/dist/types/src/extensions/command/command.d.ts.map +0 -1
- package/dist/types/src/extensions/command/floating-menu.d.ts +0 -7
- package/dist/types/src/extensions/command/floating-menu.d.ts.map +0 -1
- package/dist/types/src/extensions/command/hint.d.ts +0 -24
- package/dist/types/src/extensions/command/hint.d.ts.map +0 -1
- package/dist/types/src/extensions/command/index.d.ts +0 -7
- package/dist/types/src/extensions/command/index.d.ts.map +0 -1
- package/dist/types/src/extensions/command/placeholder.d.ts +0 -10
- package/dist/types/src/extensions/command/placeholder.d.ts.map +0 -1
- package/dist/types/src/extensions/command/state.d.ts +0 -16
- package/dist/types/src/extensions/command/state.d.ts.map +0 -1
- package/dist/types/src/extensions/command/typeahead.d.ts +0 -22
- package/dist/types/src/extensions/command/typeahead.d.ts.map +0 -1
- package/dist/types/src/extensions/command/useCommandMenu.d.ts +0 -26
- package/dist/types/src/extensions/command/useCommandMenu.d.ts.map +0 -1
- package/dist/types/src/stories/Command.stories.d.ts.map +0 -1
- package/dist/types/src/stories/CommandMenu.stories.d.ts.map +0 -1
- package/dist/types/src/testing/index.d.ts +0 -2
- package/dist/types/src/testing/index.d.ts.map +0 -1
- package/dist/types/src/testing/util.d.ts +0 -3
- package/dist/types/src/testing/util.d.ts.map +0 -1
- package/src/components/EditorToolbar/util.ts +0 -76
- package/src/components/Popover/CommandMenu.tsx +0 -279
- package/src/components/Popover/RefDropdownMenu.tsx +0 -85
- package/src/components/Popover/RefPopover.tsx +0 -99
- package/src/components/Popover/index.ts +0 -7
- package/src/extensions/autocomplete.ts +0 -69
- package/src/extensions/command/action.ts +0 -56
- package/src/extensions/command/command-menu.ts +0 -211
- package/src/extensions/command/command.ts +0 -34
- package/src/extensions/command/hint.ts +0 -103
- package/src/extensions/command/index.ts +0 -10
- package/src/extensions/command/state.ts +0 -90
- package/src/extensions/command/useCommandMenu.ts +0 -119
- package/src/stories/Command.stories.tsx +0 -101
- package/src/stories/CommandMenu.stories.tsx +0 -161
- package/src/testing/index.ts +0 -5
- package/src/testing/util.ts +0 -7
|
@@ -2,11 +2,13 @@
|
|
|
2
2
|
// Copyright 2024 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import { type EditorView } from '@codemirror/view';
|
|
6
|
+
import { Atom } from '@effect-atom/atom-react';
|
|
6
7
|
import React, { memo, useMemo } from 'react';
|
|
7
8
|
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
9
|
+
import { atomFromSignal } from '@dxos/app-graph';
|
|
10
|
+
import { type Live } from '@dxos/live-object';
|
|
11
|
+
import { ElevationProvider, type ThemedClassName } from '@dxos/react-ui';
|
|
10
12
|
import {
|
|
11
13
|
type ActionGraphProps,
|
|
12
14
|
MenuProvider,
|
|
@@ -15,120 +17,128 @@ import {
|
|
|
15
17
|
useMenuActions,
|
|
16
18
|
} from '@dxos/react-ui-menu';
|
|
17
19
|
|
|
20
|
+
import { type EditorViewMode } from '../../types';
|
|
21
|
+
|
|
22
|
+
import { createLists } from './actions';
|
|
18
23
|
import { createBlocks } from './blocks';
|
|
19
24
|
import { createFormatting } from './formatting';
|
|
20
25
|
import { createHeadings } from './headings';
|
|
21
26
|
import { createImageUpload } from './image';
|
|
22
|
-
import { createLists } from './lists';
|
|
23
27
|
import { createSearch } from './search';
|
|
24
|
-
import { type
|
|
28
|
+
import { type EditorToolbarState } from './useEditorToolbar';
|
|
25
29
|
import { createViewMode } from './view-mode';
|
|
26
30
|
|
|
31
|
+
export type EditorToolbarFeatureFlags = Partial<{
|
|
32
|
+
showHeadings: boolean;
|
|
33
|
+
showFormatting: boolean;
|
|
34
|
+
showLists: boolean;
|
|
35
|
+
showBlocks: boolean;
|
|
36
|
+
showSearch: boolean;
|
|
37
|
+
|
|
38
|
+
// TODO(wittjosiah): Factor out (depends on plugin-level capabilities.)
|
|
39
|
+
onImageUpload: () => void;
|
|
40
|
+
onViewModeChange: (mode: EditorViewMode) => void;
|
|
41
|
+
}>;
|
|
42
|
+
|
|
43
|
+
export type EditorToolbarActionGraphProps = {
|
|
44
|
+
state: Live<EditorToolbarState>;
|
|
45
|
+
getView: () => EditorView;
|
|
46
|
+
// TODO(wittjosiah): Control positioning.
|
|
47
|
+
customActions?: Atom.Atom<ActionGraphProps>;
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
export type EditorToolbarProps = ThemedClassName<
|
|
51
|
+
{
|
|
52
|
+
role?: string;
|
|
53
|
+
attendableId?: string;
|
|
54
|
+
} & (EditorToolbarActionGraphProps & EditorToolbarFeatureFlags)
|
|
55
|
+
>;
|
|
56
|
+
|
|
57
|
+
// TODO(burdon): Remove role dependency.
|
|
58
|
+
export const EditorToolbar = memo(({ classNames, role, attendableId, ...props }: EditorToolbarProps) => {
|
|
59
|
+
const menuProps = useEditorToolbarActionGraph(props);
|
|
60
|
+
|
|
61
|
+
return (
|
|
62
|
+
<ElevationProvider elevation={role === 'section' ? 'positioned' : 'base'}>
|
|
63
|
+
<MenuProvider {...menuProps} attendableId={attendableId}>
|
|
64
|
+
<ToolbarMenu classNames={classNames} textBlockWidth />
|
|
65
|
+
</MenuProvider>
|
|
66
|
+
</ElevationProvider>
|
|
67
|
+
);
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
type ToolbarActionsProps = Pick<EditorToolbarActionGraphProps, 'state' | 'getView' | 'customActions'> &
|
|
71
|
+
EditorToolbarFeatureFlags;
|
|
72
|
+
|
|
73
|
+
// TODO(wittjosiah): Toolbar re-rendering is causing this graph to be recreated and breaking reactivity in some cases.
|
|
74
|
+
// E.g. for toolbar dropdowns which use active icon, the icon is not updated when the active item changes.
|
|
75
|
+
// This is currently only happening in the markdown plugin usage and should be reproduced in an editor story.
|
|
76
|
+
const useEditorToolbarActionGraph = ({ state, getView, customActions, ...features }: ToolbarActionsProps) => {
|
|
77
|
+
const menuCreator = useMemo(
|
|
78
|
+
() => createToolbarActions({ state, getView, customActions, ...features }),
|
|
79
|
+
[
|
|
80
|
+
state,
|
|
81
|
+
getView,
|
|
82
|
+
customActions,
|
|
83
|
+
features?.showHeadings,
|
|
84
|
+
features?.showFormatting,
|
|
85
|
+
features?.showLists,
|
|
86
|
+
features?.showBlocks,
|
|
87
|
+
features?.showSearch,
|
|
88
|
+
features?.onImageUpload,
|
|
89
|
+
features?.onViewModeChange,
|
|
90
|
+
],
|
|
91
|
+
);
|
|
92
|
+
|
|
93
|
+
return useMenuActions(menuCreator);
|
|
94
|
+
};
|
|
95
|
+
|
|
27
96
|
const createToolbarActions = ({
|
|
28
|
-
getView,
|
|
29
97
|
state,
|
|
98
|
+
getView,
|
|
30
99
|
customActions,
|
|
31
100
|
...features
|
|
32
|
-
}:
|
|
33
|
-
|
|
34
|
-
return Rx.make((get) => {
|
|
101
|
+
}: ToolbarActionsProps): Atom.Atom<ActionGraphProps> => {
|
|
102
|
+
return Atom.make((get) => {
|
|
35
103
|
const graph: ActionGraphProps = {
|
|
36
104
|
nodes: [],
|
|
37
105
|
edges: [],
|
|
38
106
|
};
|
|
39
107
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
graph.nodes.push(...
|
|
43
|
-
graph.edges.push(...
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
graph
|
|
48
|
-
graph.edges.push(...formatting.edges);
|
|
108
|
+
// TODO(burdon): Builder pattern?
|
|
109
|
+
const addSubGraph = (graph: ActionGraphProps, subGraph: ActionGraphProps) => {
|
|
110
|
+
graph.nodes.push(...subGraph.nodes);
|
|
111
|
+
graph.edges.push(...subGraph.edges);
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
if (features?.showHeadings ?? true) {
|
|
115
|
+
addSubGraph(graph, get(atomFromSignal(() => createHeadings(state, getView))));
|
|
49
116
|
}
|
|
50
|
-
if (features
|
|
51
|
-
|
|
52
|
-
graph.nodes.push(...lists.nodes);
|
|
53
|
-
graph.edges.push(...lists.edges);
|
|
117
|
+
if (features?.showFormatting ?? true) {
|
|
118
|
+
addSubGraph(graph, get(atomFromSignal(() => createFormatting(state, getView))));
|
|
54
119
|
}
|
|
55
|
-
if (features
|
|
56
|
-
|
|
57
|
-
graph.nodes.push(...blocks.nodes);
|
|
58
|
-
graph.edges.push(...blocks.edges);
|
|
120
|
+
if (features?.showLists ?? true) {
|
|
121
|
+
addSubGraph(graph, get(atomFromSignal(() => createLists(state, getView))));
|
|
59
122
|
}
|
|
60
|
-
if (features
|
|
61
|
-
|
|
62
|
-
graph.nodes.push(...image.nodes);
|
|
63
|
-
graph.edges.push(...image.edges);
|
|
123
|
+
if (features?.showBlocks ?? true) {
|
|
124
|
+
addSubGraph(graph, get(atomFromSignal(() => createBlocks(state, getView))));
|
|
64
125
|
}
|
|
65
|
-
{
|
|
66
|
-
|
|
67
|
-
graph.nodes.push(...gap.nodes);
|
|
68
|
-
graph.edges.push(...gap.edges);
|
|
126
|
+
if (features?.onImageUpload) {
|
|
127
|
+
addSubGraph(graph, get(atomFromSignal(() => createImageUpload(features.onImageUpload!))));
|
|
69
128
|
}
|
|
129
|
+
|
|
130
|
+
addSubGraph(graph, createGapSeparator());
|
|
131
|
+
|
|
70
132
|
if (customActions) {
|
|
71
|
-
|
|
72
|
-
graph.nodes.push(...custom.nodes);
|
|
73
|
-
graph.edges.push(...custom.edges);
|
|
133
|
+
addSubGraph(graph, get(customActions));
|
|
74
134
|
}
|
|
75
|
-
if (features
|
|
76
|
-
|
|
77
|
-
graph.nodes.push(...search.nodes);
|
|
78
|
-
graph.edges.push(...search.edges);
|
|
135
|
+
if (features?.showSearch ?? true) {
|
|
136
|
+
addSubGraph(graph, get(atomFromSignal(() => createSearch(getView))));
|
|
79
137
|
}
|
|
80
|
-
if (features
|
|
81
|
-
|
|
82
|
-
graph.nodes.push(...viewMode.nodes);
|
|
83
|
-
graph.edges.push(...viewMode.edges);
|
|
138
|
+
if (features?.onViewModeChange) {
|
|
139
|
+
addSubGraph(graph, get(atomFromSignal(() => createViewMode(state, features.onViewModeChange!))));
|
|
84
140
|
}
|
|
85
141
|
|
|
86
142
|
return graph;
|
|
87
143
|
});
|
|
88
144
|
};
|
|
89
|
-
|
|
90
|
-
// TODO(wittjosiah): Toolbar re-rendering is causing this graph to be recreated and breaking reactivity in some cases.
|
|
91
|
-
// E.g. for toolbar dropdowns which use active icon, the icon is not updated when the active item changes.
|
|
92
|
-
// This is currently only happening in the markdown plugin usage and should be reproduced in an editor story.
|
|
93
|
-
const useEditorToolbarActionGraph = (props: EditorToolbarProps) => {
|
|
94
|
-
const menuCreator = useMemo(
|
|
95
|
-
() =>
|
|
96
|
-
createToolbarActions({
|
|
97
|
-
getView: props.getView,
|
|
98
|
-
state: props.state,
|
|
99
|
-
customActions: props.customActions,
|
|
100
|
-
headings: props.headings,
|
|
101
|
-
formatting: props.formatting,
|
|
102
|
-
lists: props.lists,
|
|
103
|
-
blocks: props.blocks,
|
|
104
|
-
image: props.image,
|
|
105
|
-
search: props.search,
|
|
106
|
-
viewMode: props.viewMode,
|
|
107
|
-
}),
|
|
108
|
-
[
|
|
109
|
-
props.getView,
|
|
110
|
-
props.state,
|
|
111
|
-
props.customActions,
|
|
112
|
-
props.headings,
|
|
113
|
-
props.formatting,
|
|
114
|
-
props.lists,
|
|
115
|
-
props.blocks,
|
|
116
|
-
props.image,
|
|
117
|
-
props.search,
|
|
118
|
-
props.viewMode,
|
|
119
|
-
],
|
|
120
|
-
);
|
|
121
|
-
|
|
122
|
-
return useMenuActions(menuCreator);
|
|
123
|
-
};
|
|
124
|
-
|
|
125
|
-
export const EditorToolbar = memo(({ classNames, attendableId, role, ...props }: EditorToolbarProps) => {
|
|
126
|
-
const menuProps = useEditorToolbarActionGraph(props);
|
|
127
|
-
return (
|
|
128
|
-
<ElevationProvider elevation={role === 'section' ? 'positioned' : 'base'}>
|
|
129
|
-
<MenuProvider {...menuProps} attendableId={attendableId}>
|
|
130
|
-
<ToolbarMenu classNames={classNames} textBlockWidth />
|
|
131
|
-
</MenuProvider>
|
|
132
|
-
</ElevationProvider>
|
|
133
|
-
);
|
|
134
|
-
});
|
|
@@ -4,12 +4,18 @@
|
|
|
4
4
|
|
|
5
5
|
import { type EditorView } from '@codemirror/view';
|
|
6
6
|
|
|
7
|
-
import { type NodeArg } from '@dxos/app-graph';
|
|
8
|
-
import {
|
|
7
|
+
import { type Action, type NodeArg } from '@dxos/app-graph';
|
|
8
|
+
import {
|
|
9
|
+
type MenuActionProperties,
|
|
10
|
+
type ToolbarMenuActionGroupProperties,
|
|
11
|
+
createMenuAction,
|
|
12
|
+
createMenuItemGroup,
|
|
13
|
+
} from '@dxos/react-ui-menu';
|
|
9
14
|
|
|
10
15
|
import { List, addList, removeList } from '../../extensions';
|
|
16
|
+
import { translationKey } from '../../translations';
|
|
11
17
|
|
|
12
|
-
import { type EditorToolbarState
|
|
18
|
+
import { type EditorToolbarState } from './useEditorToolbar';
|
|
13
19
|
|
|
14
20
|
const listStyles = {
|
|
15
21
|
bullet: 'ph--list-bullets--regular',
|
|
@@ -17,6 +23,43 @@ const listStyles = {
|
|
|
17
23
|
task: 'ph--list-checks--regular',
|
|
18
24
|
};
|
|
19
25
|
|
|
26
|
+
export const createLists = (state: EditorToolbarState, getView: () => EditorView) => {
|
|
27
|
+
const value = state.listStyle ?? '';
|
|
28
|
+
const listGroupAction = createListGroupAction(value);
|
|
29
|
+
const listActionsMap = createListActions(value, getView);
|
|
30
|
+
return {
|
|
31
|
+
nodes: [listGroupAction as NodeArg<any>, ...listActionsMap],
|
|
32
|
+
edges: [
|
|
33
|
+
{ source: 'root', target: 'list' },
|
|
34
|
+
...listActionsMap.map(({ id }) => ({ source: listGroupAction.id, target: id })),
|
|
35
|
+
],
|
|
36
|
+
};
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
export const createEditorAction = (id: string, props: Partial<MenuActionProperties>, invoke: () => void) => {
|
|
40
|
+
const { label = [`${id} label`, { ns: translationKey }], ...rest } = props;
|
|
41
|
+
|
|
42
|
+
return createMenuAction(id, invoke, {
|
|
43
|
+
label,
|
|
44
|
+
...rest,
|
|
45
|
+
}) as Action<MenuActionProperties>;
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
export const createEditorActionGroup = (
|
|
49
|
+
id: string,
|
|
50
|
+
props: Omit<ToolbarMenuActionGroupProperties, 'icon'>,
|
|
51
|
+
icon?: string,
|
|
52
|
+
) => {
|
|
53
|
+
const { label = [`${id} label`, { ns: translationKey }], ...rest } = props;
|
|
54
|
+
|
|
55
|
+
return createMenuItemGroup(id, {
|
|
56
|
+
label,
|
|
57
|
+
icon,
|
|
58
|
+
iconOnly: true,
|
|
59
|
+
...rest,
|
|
60
|
+
});
|
|
61
|
+
};
|
|
62
|
+
|
|
20
63
|
const createListGroupAction = (value: string) =>
|
|
21
64
|
createEditorActionGroup('list', {
|
|
22
65
|
variant: 'toggleGroup',
|
|
@@ -41,16 +84,3 @@ const createListActions = (value: string, getView: () => EditorView) =>
|
|
|
41
84
|
}
|
|
42
85
|
});
|
|
43
86
|
});
|
|
44
|
-
|
|
45
|
-
export const createLists = (state: EditorToolbarState, getView: () => EditorView) => {
|
|
46
|
-
const value = state.listStyle ?? '';
|
|
47
|
-
const listGroupAction = createListGroupAction(value);
|
|
48
|
-
const listActionsMap = createListActions(value, getView);
|
|
49
|
-
return {
|
|
50
|
-
nodes: [listGroupAction as NodeArg<any>, ...listActionsMap],
|
|
51
|
-
edges: [
|
|
52
|
-
{ source: 'root', target: 'list' },
|
|
53
|
-
...listActionsMap.map(({ id }) => ({ source: listGroupAction.id, target: id })),
|
|
54
|
-
],
|
|
55
|
-
};
|
|
56
|
-
};
|
|
@@ -9,7 +9,8 @@ import { type ToolbarMenuActionGroupProperties } from '@dxos/react-ui-menu';
|
|
|
9
9
|
|
|
10
10
|
import { addBlockquote, addCodeblock, insertTable, removeBlockquote, removeCodeblock } from '../../extensions';
|
|
11
11
|
|
|
12
|
-
import {
|
|
12
|
+
import { createEditorAction, createEditorActionGroup } from './actions';
|
|
13
|
+
import { type EditorToolbarState } from './useEditorToolbar';
|
|
13
14
|
|
|
14
15
|
const createBlockGroupAction = (value: string) =>
|
|
15
16
|
createEditorActionGroup('block', {
|
|
@@ -9,7 +9,8 @@ import { type ToolbarMenuActionGroupProperties } from '@dxos/react-ui-menu';
|
|
|
9
9
|
|
|
10
10
|
import { type Formatting, Inline, addLink, removeLink, setStyle } from '../../extensions';
|
|
11
11
|
|
|
12
|
-
import {
|
|
12
|
+
import { createEditorAction, createEditorActionGroup } from './actions';
|
|
13
|
+
import { type EditorToolbarState } from './useEditorToolbar';
|
|
13
14
|
|
|
14
15
|
const formats = {
|
|
15
16
|
strong: 'ph--text-b--regular',
|
|
@@ -10,7 +10,8 @@ import { type ToolbarMenuActionGroupProperties } from '@dxos/react-ui-menu';
|
|
|
10
10
|
import { setHeading } from '../../extensions';
|
|
11
11
|
import { translationKey } from '../../translations';
|
|
12
12
|
|
|
13
|
-
import {
|
|
13
|
+
import { createEditorAction, createEditorActionGroup } from './actions';
|
|
14
|
+
import { type EditorToolbarState } from './useEditorToolbar';
|
|
14
15
|
|
|
15
16
|
const createHeadingGroupAction = (value: string) =>
|
|
16
17
|
createEditorActionGroup(
|
|
@@ -19,12 +20,13 @@ const createHeadingGroupAction = (value: string) =>
|
|
|
19
20
|
variant: 'dropdownMenu',
|
|
20
21
|
applyActive: true,
|
|
21
22
|
selectCardinality: 'single',
|
|
23
|
+
// TODO(wittjosiah): Remove? Not sure this does anything.
|
|
22
24
|
value,
|
|
23
25
|
} as ToolbarMenuActionGroupProperties,
|
|
24
26
|
'ph--text-h--regular',
|
|
25
27
|
);
|
|
26
28
|
|
|
27
|
-
const createHeadingActions = (getView: () => EditorView) =>
|
|
29
|
+
const createHeadingActions = (currentLevel: string, getView: () => EditorView) =>
|
|
28
30
|
Object.entries({
|
|
29
31
|
'0': 'ph--paragraph--regular',
|
|
30
32
|
'1': 'ph--text-h-one--regular',
|
|
@@ -40,6 +42,7 @@ const createHeadingActions = (getView: () => EditorView) =>
|
|
|
40
42
|
{
|
|
41
43
|
label: ['heading level label', { count: level, ns: translationKey }],
|
|
42
44
|
icon,
|
|
45
|
+
checked: levelStr === currentLevel,
|
|
43
46
|
},
|
|
44
47
|
() => setHeading(level)(getView()),
|
|
45
48
|
);
|
|
@@ -47,14 +50,14 @@ const createHeadingActions = (getView: () => EditorView) =>
|
|
|
47
50
|
|
|
48
51
|
const computeHeadingValue = (state: EditorToolbarState) => {
|
|
49
52
|
const blockType = state ? state.blockType : 'paragraph';
|
|
50
|
-
const
|
|
51
|
-
return
|
|
53
|
+
const heading = blockType && /heading(\d)/.exec(blockType);
|
|
54
|
+
return heading ? heading[1] : blockType === 'paragraph' || !blockType ? '0' : '';
|
|
52
55
|
};
|
|
53
56
|
|
|
54
57
|
export const createHeadings = (state: EditorToolbarState, getView: () => EditorView) => {
|
|
55
58
|
const headingValue = computeHeadingValue(state);
|
|
56
59
|
const headingGroupAction = createHeadingGroupAction(headingValue);
|
|
57
|
-
const headingActions = createHeadingActions(getView);
|
|
60
|
+
const headingActions = createHeadingActions(headingValue, getView);
|
|
58
61
|
return {
|
|
59
62
|
nodes: [headingGroupAction as NodeArg<any>, ...headingActions],
|
|
60
63
|
edges: [
|
|
@@ -3,10 +3,6 @@
|
|
|
3
3
|
//
|
|
4
4
|
|
|
5
5
|
export * from './EditorToolbar';
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
useEditorToolbarState,
|
|
10
|
-
createEditorAction,
|
|
11
|
-
createEditorActionGroup,
|
|
12
|
-
} from './util';
|
|
6
|
+
|
|
7
|
+
export { type EditorToolbarState, useEditorToolbar } from './useEditorToolbar';
|
|
8
|
+
export { createEditorAction, createEditorActionGroup } from './actions';
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
import { openSearchPanel } from '@codemirror/search';
|
|
6
6
|
import { type EditorView } from '@codemirror/view';
|
|
7
7
|
|
|
8
|
-
import { createEditorAction } from './
|
|
8
|
+
import { createEditorAction } from './actions';
|
|
9
9
|
|
|
10
10
|
const createSearchAction = (getView: () => EditorView) =>
|
|
11
11
|
createEditorAction(
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { useMemo } from 'react';
|
|
6
|
+
|
|
7
|
+
import { type Live, live } from '@dxos/live-object';
|
|
8
|
+
|
|
9
|
+
import { type Formatting } from '../../extensions';
|
|
10
|
+
import { type EditorViewMode } from '../../types';
|
|
11
|
+
|
|
12
|
+
// TODO(burdon): Move to extensions.
|
|
13
|
+
export type EditorToolbarState = { viewMode?: EditorViewMode } & Formatting;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* @deprecated Use Editor.Root
|
|
17
|
+
*/
|
|
18
|
+
export const useEditorToolbar = (initialState: Partial<EditorToolbarState> = {}): Live<EditorToolbarState> => {
|
|
19
|
+
return useMemo(() => live<EditorToolbarState>(initialState), []);
|
|
20
|
+
};
|
|
@@ -8,7 +8,8 @@ import { type ToolbarMenuActionGroupProperties } from '@dxos/react-ui-menu';
|
|
|
8
8
|
import { translationKey } from '../../translations';
|
|
9
9
|
import { type EditorViewMode } from '../../types';
|
|
10
10
|
|
|
11
|
-
import {
|
|
11
|
+
import { createEditorAction, createEditorActionGroup } from './actions';
|
|
12
|
+
import { type EditorToolbarState } from './useEditorToolbar';
|
|
12
13
|
|
|
13
14
|
const createViewModeGroupAction = (value: string) =>
|
|
14
15
|
createEditorActionGroup(
|
package/src/components/index.ts
CHANGED
|
@@ -3,5 +3,11 @@
|
|
|
3
3
|
//
|
|
4
4
|
|
|
5
5
|
export * from './Editor';
|
|
6
|
-
|
|
7
|
-
export
|
|
6
|
+
|
|
7
|
+
// export { type GetMenuContext } from './EditorMenuProvider';
|
|
8
|
+
|
|
9
|
+
// TODO(burdon): Remove once Editor is fully migrated.
|
|
10
|
+
export { EditorContent, createEditorController } from './EditorContent';
|
|
11
|
+
export * from './EditorMenuProvider';
|
|
12
|
+
export * from './EditorPreviewProvider';
|
|
13
|
+
export { EditorToolbar, type EditorToolbarProps, type EditorToolbarState, useEditorToolbar } from './EditorToolbar';
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { type Extension, Prec } from '@codemirror/state';
|
|
6
|
+
import {
|
|
7
|
+
Decoration,
|
|
8
|
+
type DecorationSet,
|
|
9
|
+
EditorView,
|
|
10
|
+
ViewPlugin,
|
|
11
|
+
type ViewUpdate,
|
|
12
|
+
WidgetType,
|
|
13
|
+
keymap,
|
|
14
|
+
} from '@codemirror/view';
|
|
15
|
+
|
|
16
|
+
export type AutocompleteOptions = {
|
|
17
|
+
/**
|
|
18
|
+
* Function that returns a list of suggestions based on the current text.
|
|
19
|
+
* @param text The current text before the cursor
|
|
20
|
+
* @returns Array of suggestion strings
|
|
21
|
+
*/
|
|
22
|
+
onSuggest?: (text: string) => string[];
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Creates an autocomplete extension that shows inline suggestions.
|
|
27
|
+
* Pressing Tab will complete the suggestion.
|
|
28
|
+
*
|
|
29
|
+
* @deprecated Use typeahead.
|
|
30
|
+
*/
|
|
31
|
+
export const autocomplete = ({ onSuggest }: AutocompleteOptions = {}): Extension => {
|
|
32
|
+
const suggest = ViewPlugin.fromClass(
|
|
33
|
+
class {
|
|
34
|
+
_decorations: DecorationSet;
|
|
35
|
+
_currentSuggestion: string | null = null;
|
|
36
|
+
|
|
37
|
+
constructor(view: EditorView) {
|
|
38
|
+
this._decorations = this.computeDecorations(view);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
update(update: ViewUpdate) {
|
|
42
|
+
if (update.docChanged || update.selectionSet) {
|
|
43
|
+
this._decorations = this.computeDecorations(update.view);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
private computeDecorations(view: EditorView): DecorationSet {
|
|
48
|
+
const text = view.state.doc.toString();
|
|
49
|
+
const suggestions = onSuggest?.(text) ?? [];
|
|
50
|
+
if (!suggestions.length) {
|
|
51
|
+
this._currentSuggestion = null;
|
|
52
|
+
return Decoration.none;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Get the first suggestion.
|
|
56
|
+
this._currentSuggestion = suggestions[0];
|
|
57
|
+
const suffix = this._currentSuggestion.slice(text.length);
|
|
58
|
+
if (!suffix) {
|
|
59
|
+
return Decoration.none;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Always show ghost text at the end of the document.
|
|
63
|
+
return Decoration.set([
|
|
64
|
+
Decoration.widget({
|
|
65
|
+
widget: new InlineSuggestionWidget(suffix),
|
|
66
|
+
side: 1,
|
|
67
|
+
}).range(view.state.doc.length),
|
|
68
|
+
]);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
completeSuggestion(view: EditorView): boolean {
|
|
72
|
+
if (!this._currentSuggestion) {
|
|
73
|
+
return false;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const text = view.state.doc.toString();
|
|
77
|
+
const suffix = this._currentSuggestion.slice(text.length);
|
|
78
|
+
if (!suffix) {
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
view.dispatch({
|
|
83
|
+
changes: {
|
|
84
|
+
from: view.state.doc.length,
|
|
85
|
+
insert: suffix,
|
|
86
|
+
},
|
|
87
|
+
selection: {
|
|
88
|
+
anchor: view.state.doc.length + suffix.length,
|
|
89
|
+
},
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
return true;
|
|
93
|
+
}
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
decorations: (v) => v._decorations,
|
|
97
|
+
},
|
|
98
|
+
);
|
|
99
|
+
|
|
100
|
+
return [
|
|
101
|
+
suggest,
|
|
102
|
+
EditorView.theme({
|
|
103
|
+
'.cm-inline-suggestion': {
|
|
104
|
+
opacity: 0.4,
|
|
105
|
+
},
|
|
106
|
+
}),
|
|
107
|
+
|
|
108
|
+
Prec.highest(
|
|
109
|
+
keymap.of([
|
|
110
|
+
{
|
|
111
|
+
key: 'Tab',
|
|
112
|
+
preventDefault: true,
|
|
113
|
+
run: (view) => {
|
|
114
|
+
const plugin = view.plugin(suggest);
|
|
115
|
+
return plugin?.completeSuggestion(view) ?? false;
|
|
116
|
+
},
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
key: 'ArrowRight',
|
|
120
|
+
preventDefault: true,
|
|
121
|
+
run: (view) => {
|
|
122
|
+
// Only complete if cursor is at the end
|
|
123
|
+
if (view.state.selection.main.head !== view.state.doc.length) {
|
|
124
|
+
return false;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
const plugin = view.plugin(suggest);
|
|
128
|
+
return plugin?.completeSuggestion(view) ?? false;
|
|
129
|
+
},
|
|
130
|
+
},
|
|
131
|
+
]),
|
|
132
|
+
),
|
|
133
|
+
];
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
class InlineSuggestionWidget extends WidgetType {
|
|
137
|
+
constructor(private suffix: string) {
|
|
138
|
+
super();
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
override eq(other: this) {
|
|
142
|
+
return this.suffix === other.suffix;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
override toDOM() {
|
|
146
|
+
const span = document.createElement('span');
|
|
147
|
+
span.textContent = this.suffix;
|
|
148
|
+
span.className = 'cm-inline-suggestion';
|
|
149
|
+
return span;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
export type CompoetionContext = { line: string };
|
|
6
|
+
|
|
7
|
+
export type CompletionOptions = {
|
|
8
|
+
default?: string;
|
|
9
|
+
minLength?: number;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Util to match current line to a static list of completions.
|
|
14
|
+
*/
|
|
15
|
+
export const staticCompletion =
|
|
16
|
+
(completions: string[], options: CompletionOptions = {}) =>
|
|
17
|
+
({ line }: CompoetionContext) => {
|
|
18
|
+
if (line.length === 0 && options.default) {
|
|
19
|
+
return options.default;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const parts = line.split(/\s+/).filter(Boolean);
|
|
23
|
+
if (parts.length) {
|
|
24
|
+
const str = parts.at(-1)!;
|
|
25
|
+
if (str.length >= (options.minLength ?? 0)) {
|
|
26
|
+
for (const completion of completions) {
|
|
27
|
+
const match = matchCompletion(completion, str);
|
|
28
|
+
if (match) {
|
|
29
|
+
return match;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export const matchCompletion = (completion: string, str: string, minLength = 0): string | undefined => {
|
|
37
|
+
if (
|
|
38
|
+
str.length >= minLength &&
|
|
39
|
+
completion.length > str.length &&
|
|
40
|
+
completion.startsWith(str)
|
|
41
|
+
// TODO(burdon): If case insensitive, need to replace existing chars.
|
|
42
|
+
// completion.toLowerCase().startsWith(str.toLowerCase())
|
|
43
|
+
) {
|
|
44
|
+
return completion.slice(str.length);
|
|
45
|
+
}
|
|
46
|
+
};
|