@dxos/react-ui-editor 0.8.4-main.fffef41 → 0.9.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/LICENSE +102 -5
- package/README.md +1 -1
- package/dist/lib/browser/index.mjs +1126 -8845
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/translations.mjs +39 -0
- package/dist/lib/browser/translations.mjs.map +7 -0
- package/dist/lib/node-esm/index.mjs +1126 -8844
- package/dist/lib/node-esm/index.mjs.map +4 -4
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/lib/node-esm/translations.mjs +41 -0
- package/dist/lib/node-esm/translations.mjs.map +7 -0
- package/dist/types/src/components/Editor/Editor.d.ts +41 -24
- package/dist/types/src/components/Editor/Editor.d.ts.map +1 -1
- package/dist/types/src/components/Editor/Editor.stories.d.ts +7 -4
- package/dist/types/src/components/Editor/Editor.stories.d.ts.map +1 -1
- package/dist/types/src/components/{EditorContent/EditorContent.d.ts → Editor/EditorView.d.ts} +9 -7
- package/dist/types/src/components/Editor/EditorView.d.ts.map +1 -0
- package/dist/types/src/components/Editor/controller.d.ts.map +1 -0
- package/dist/types/src/components/EditorMenuProvider/EditorMenuProvider.d.ts +3 -5
- package/dist/types/src/components/EditorMenuProvider/EditorMenuProvider.d.ts.map +1 -1
- package/dist/types/src/components/EditorMenuProvider/index.d.ts +0 -1
- package/dist/types/src/components/EditorMenuProvider/index.d.ts.map +1 -1
- package/dist/types/src/components/EditorMenuProvider/menu-presets.d.ts.map +1 -1
- package/dist/types/src/components/EditorMenuProvider/menu.d.ts.map +1 -1
- package/dist/types/src/components/EditorMenuProvider/popover.d.ts +9 -3
- package/dist/types/src/components/EditorMenuProvider/popover.d.ts.map +1 -1
- package/dist/types/src/components/EditorMenuProvider/useEditorMenu.d.ts +3 -3
- package/dist/types/src/components/EditorMenuProvider/useEditorMenu.d.ts.map +1 -1
- package/dist/types/src/components/EditorPreviewProvider/EditorPreviewProvider.d.ts +1 -1
- package/dist/types/src/components/EditorPreviewProvider/EditorPreviewProvider.d.ts.map +1 -1
- package/dist/types/src/components/EditorToolbar/EditorToolbar.d.ts +8 -6
- package/dist/types/src/components/EditorToolbar/EditorToolbar.d.ts.map +1 -1
- package/dist/types/src/components/EditorToolbar/blocks.d.ts +4 -17
- package/dist/types/src/components/EditorToolbar/blocks.d.ts.map +1 -1
- package/dist/types/src/components/EditorToolbar/formatting.d.ts +4 -17
- package/dist/types/src/components/EditorToolbar/formatting.d.ts.map +1 -1
- package/dist/types/src/components/EditorToolbar/headings.d.ts +4 -17
- package/dist/types/src/components/EditorToolbar/headings.d.ts.map +1 -1
- package/dist/types/src/components/EditorToolbar/image.d.ts +3 -15
- package/dist/types/src/components/EditorToolbar/image.d.ts.map +1 -1
- package/dist/types/src/components/EditorToolbar/index.d.ts +1 -2
- package/dist/types/src/components/EditorToolbar/index.d.ts.map +1 -1
- package/dist/types/src/components/EditorToolbar/lists.d.ts +6 -0
- package/dist/types/src/components/EditorToolbar/lists.d.ts.map +1 -0
- package/dist/types/src/components/EditorToolbar/search.d.ts +3 -15
- package/dist/types/src/components/EditorToolbar/search.d.ts.map +1 -1
- package/dist/types/src/components/EditorToolbar/types.d.ts +6 -0
- package/dist/types/src/components/EditorToolbar/types.d.ts.map +1 -0
- package/dist/types/src/components/EditorToolbar/view-mode.d.ts +5 -18
- package/dist/types/src/components/EditorToolbar/view-mode.d.ts.map +1 -1
- package/dist/types/src/components/index.d.ts +0 -2
- package/dist/types/src/components/index.d.ts.map +1 -1
- package/dist/types/src/extensions/Assistant.stories.d.ts +10 -0
- package/dist/types/src/extensions/Assistant.stories.d.ts.map +1 -0
- package/dist/types/src/extensions/assistant-extension.d.ts +24 -0
- package/dist/types/src/extensions/assistant-extension.d.ts.map +1 -0
- package/dist/types/src/extensions/index.d.ts +1 -31
- package/dist/types/src/extensions/index.d.ts.map +1 -1
- package/dist/types/src/hooks/index.d.ts +1 -0
- package/dist/types/src/hooks/index.d.ts.map +1 -1
- package/dist/types/src/hooks/useBasicMarkdownExtensions.d.ts +25 -0
- package/dist/types/src/hooks/useBasicMarkdownExtensions.d.ts.map +1 -0
- package/dist/types/src/hooks/useTextEditor.d.ts +1 -1
- package/dist/types/src/hooks/useTextEditor.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +0 -9
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/stories/Automerge.stories.d.ts +44 -0
- package/dist/types/src/stories/Automerge.stories.d.ts.map +1 -0
- package/dist/types/src/stories/Comments.stories.d.ts +3 -2
- package/dist/types/src/stories/Comments.stories.d.ts.map +1 -1
- package/dist/types/src/stories/EditorToolbar.stories.d.ts +29 -27
- package/dist/types/src/stories/EditorToolbar.stories.d.ts.map +1 -1
- package/dist/types/src/stories/Experimental.stories.d.ts +4 -3
- package/dist/types/src/stories/Experimental.stories.d.ts.map +1 -1
- package/dist/types/src/stories/Markdown.stories.d.ts +3 -2
- package/dist/types/src/stories/Markdown.stories.d.ts.map +1 -1
- package/dist/types/src/stories/Outliner.stories.d.ts +2 -2
- package/dist/types/src/stories/Outliner.stories.d.ts.map +1 -1
- package/dist/types/src/stories/Popover.stories.d.ts +2 -2
- package/dist/types/src/stories/Popover.stories.d.ts.map +1 -1
- package/dist/types/src/stories/Preview.stories.d.ts +3 -2
- package/dist/types/src/stories/Preview.stories.d.ts.map +1 -1
- package/dist/types/src/stories/Tags.stories.d.ts.map +1 -1
- package/dist/types/src/stories/TextEditor.stories.d.ts +3 -2
- package/dist/types/src/stories/TextEditor.stories.d.ts.map +1 -1
- package/dist/types/src/stories/Theme.stories.d.ts +8 -0
- package/dist/types/src/stories/Theme.stories.d.ts.map +1 -0
- package/dist/types/src/stories/components/EditorStory.d.ts +9 -20
- package/dist/types/src/stories/components/EditorStory.d.ts.map +1 -1
- package/dist/types/src/stories/components/util.d.ts +4 -3
- package/dist/types/src/stories/components/util.d.ts.map +1 -1
- package/dist/types/src/translations.d.ts +26 -26
- package/dist/types/src/translations.d.ts.map +1 -1
- package/dist/types/src/util/index.d.ts +0 -5
- package/dist/types/src/util/index.d.ts.map +1 -1
- package/dist/types/src/util/react.d.ts +6 -5
- package/dist/types/src/util/react.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +93 -86
- package/src/components/Editor/Editor.stories.tsx +26 -26
- package/src/components/Editor/Editor.tsx +68 -55
- package/src/components/Editor/EditorView.tsx +99 -0
- package/src/components/{EditorContent → Editor}/controller.ts +13 -4
- package/src/components/EditorMenuProvider/EditorMenuProvider.tsx +40 -39
- package/src/components/EditorMenuProvider/index.ts +0 -1
- package/src/components/EditorMenuProvider/menu-presets.ts +3 -1
- package/src/components/EditorMenuProvider/menu.ts +1 -2
- package/src/components/EditorMenuProvider/popover.ts +42 -9
- package/src/components/EditorMenuProvider/useEditorMenu.ts +21 -7
- package/src/components/EditorPreviewProvider/EditorPreviewProvider.tsx +6 -9
- package/src/components/EditorToolbar/EditorToolbar.tsx +37 -68
- package/src/components/EditorToolbar/blocks.ts +55 -48
- package/src/components/EditorToolbar/formatting.ts +44 -46
- package/src/components/EditorToolbar/headings.ts +45 -51
- package/src/components/EditorToolbar/image.ts +16 -14
- package/src/components/EditorToolbar/index.ts +2 -3
- package/src/components/EditorToolbar/lists.ts +58 -0
- package/src/components/EditorToolbar/search.ts +16 -14
- package/src/components/EditorToolbar/types.ts +8 -0
- package/src/components/EditorToolbar/view-mode.ts +37 -43
- package/src/components/index.ts +0 -5
- package/src/extensions/Assistant.stories.tsx +112 -0
- package/src/extensions/assistant-extension.tsx +223 -0
- package/src/extensions/index.ts +2 -32
- package/src/hooks/index.ts +1 -0
- package/src/hooks/useBasicMarkdownExtensions.ts +55 -0
- package/src/hooks/useTextEditor.ts +9 -3
- package/src/index.ts +0 -13
- package/src/stories/Automerge.stories.tsx +177 -0
- package/src/stories/Comments.stories.tsx +48 -43
- package/src/stories/EditorToolbar.stories.tsx +40 -53
- package/src/stories/Experimental.stories.tsx +14 -16
- package/src/stories/Markdown.stories.tsx +16 -16
- package/src/stories/Outliner.stories.tsx +11 -12
- package/src/stories/Popover.stories.tsx +30 -34
- package/src/stories/Preview.stories.tsx +72 -58
- package/src/stories/Tags.stories.tsx +24 -15
- package/src/stories/TextEditor.stories.tsx +13 -19
- package/src/stories/Theme.stories.tsx +61 -0
- package/src/stories/components/EditorStory.tsx +33 -30
- package/src/stories/components/util.tsx +51 -52
- package/src/translations.ts +30 -25
- package/src/util/index.ts +1 -6
- package/src/util/react.tsx +8 -13
- package/dist/lib/browser/chunk-HL3YF6WC.mjs +0 -22
- package/dist/lib/browser/chunk-HL3YF6WC.mjs.map +0 -7
- package/dist/lib/browser/types/index.mjs +0 -13
- package/dist/lib/browser/types/index.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-YJZGD3LY.mjs +0 -24
- package/dist/lib/node-esm/chunk-YJZGD3LY.mjs.map +0 -7
- package/dist/lib/node-esm/types/index.mjs +0 -14
- package/dist/lib/node-esm/types/index.mjs.map +0 -7
- package/dist/types/src/components/EditorContent/EditorContent.d.ts.map +0 -1
- package/dist/types/src/components/EditorContent/EditorContent.stories.d.ts +0 -26
- package/dist/types/src/components/EditorContent/EditorContent.stories.d.ts.map +0 -1
- package/dist/types/src/components/EditorContent/controller.d.ts.map +0 -1
- package/dist/types/src/components/EditorContent/index.d.ts +0 -3
- package/dist/types/src/components/EditorContent/index.d.ts.map +0 -1
- package/dist/types/src/components/EditorMenuProvider/util.d.ts +0 -8
- package/dist/types/src/components/EditorMenuProvider/util.d.ts.map +0 -1
- package/dist/types/src/components/EditorToolbar/actions.d.ts +0 -39
- package/dist/types/src/components/EditorToolbar/actions.d.ts.map +0 -1
- package/dist/types/src/components/EditorToolbar/useEditorToolbar.d.ts +0 -11
- package/dist/types/src/components/EditorToolbar/useEditorToolbar.d.ts.map +0 -1
- package/dist/types/src/defaults.d.ts +0 -14
- package/dist/types/src/defaults.d.ts.map +0 -1
- package/dist/types/src/extensions/annotations.d.ts +0 -9
- package/dist/types/src/extensions/annotations.d.ts.map +0 -1
- package/dist/types/src/extensions/autocomplete/autocomplete.d.ts +0 -17
- package/dist/types/src/extensions/autocomplete/autocomplete.d.ts.map +0 -1
- package/dist/types/src/extensions/autocomplete/index.d.ts +0 -5
- package/dist/types/src/extensions/autocomplete/index.d.ts.map +0 -1
- package/dist/types/src/extensions/autocomplete/match.d.ts +0 -13
- package/dist/types/src/extensions/autocomplete/match.d.ts.map +0 -1
- package/dist/types/src/extensions/autocomplete/placeholder.d.ts +0 -20
- package/dist/types/src/extensions/autocomplete/placeholder.d.ts.map +0 -1
- package/dist/types/src/extensions/autocomplete/typeahead.d.ts +0 -10
- package/dist/types/src/extensions/autocomplete/typeahead.d.ts.map +0 -1
- package/dist/types/src/extensions/automerge/automerge.d.ts +0 -4
- package/dist/types/src/extensions/automerge/automerge.d.ts.map +0 -1
- package/dist/types/src/extensions/automerge/automerge.stories.d.ts +0 -47
- package/dist/types/src/extensions/automerge/automerge.stories.d.ts.map +0 -1
- package/dist/types/src/extensions/automerge/automerge.test.d.ts +0 -2
- package/dist/types/src/extensions/automerge/automerge.test.d.ts.map +0 -1
- package/dist/types/src/extensions/automerge/cursor.d.ts +0 -4
- package/dist/types/src/extensions/automerge/cursor.d.ts.map +0 -1
- package/dist/types/src/extensions/automerge/defs.d.ts +0 -17
- package/dist/types/src/extensions/automerge/defs.d.ts.map +0 -1
- package/dist/types/src/extensions/automerge/index.d.ts +0 -2
- package/dist/types/src/extensions/automerge/index.d.ts.map +0 -1
- package/dist/types/src/extensions/automerge/sync.d.ts +0 -17
- package/dist/types/src/extensions/automerge/sync.d.ts.map +0 -1
- package/dist/types/src/extensions/automerge/update-automerge.d.ts +0 -6
- package/dist/types/src/extensions/automerge/update-automerge.d.ts.map +0 -1
- package/dist/types/src/extensions/automerge/update-codemirror.d.ts +0 -5
- package/dist/types/src/extensions/automerge/update-codemirror.d.ts.map +0 -1
- package/dist/types/src/extensions/autoscroll.d.ts +0 -20
- package/dist/types/src/extensions/autoscroll.d.ts.map +0 -1
- package/dist/types/src/extensions/awareness/awareness-provider.d.ts +0 -31
- package/dist/types/src/extensions/awareness/awareness-provider.d.ts.map +0 -1
- package/dist/types/src/extensions/awareness/awareness.d.ts +0 -46
- package/dist/types/src/extensions/awareness/awareness.d.ts.map +0 -1
- package/dist/types/src/extensions/awareness/index.d.ts +0 -3
- package/dist/types/src/extensions/awareness/index.d.ts.map +0 -1
- package/dist/types/src/extensions/blast.d.ts +0 -25
- package/dist/types/src/extensions/blast.d.ts.map +0 -1
- package/dist/types/src/extensions/blocks.d.ts +0 -2
- package/dist/types/src/extensions/blocks.d.ts.map +0 -1
- package/dist/types/src/extensions/bookmarks.d.ts +0 -12
- package/dist/types/src/extensions/bookmarks.d.ts.map +0 -1
- package/dist/types/src/extensions/comments.d.ts +0 -95
- package/dist/types/src/extensions/comments.d.ts.map +0 -1
- package/dist/types/src/extensions/debug.d.ts +0 -3
- package/dist/types/src/extensions/debug.d.ts.map +0 -1
- package/dist/types/src/extensions/dnd.d.ts +0 -9
- package/dist/types/src/extensions/dnd.d.ts.map +0 -1
- package/dist/types/src/extensions/factories.d.ts +0 -83
- package/dist/types/src/extensions/factories.d.ts.map +0 -1
- package/dist/types/src/extensions/focus.d.ts +0 -7
- package/dist/types/src/extensions/focus.d.ts.map +0 -1
- package/dist/types/src/extensions/folding.d.ts +0 -7
- package/dist/types/src/extensions/folding.d.ts.map +0 -1
- package/dist/types/src/extensions/hashtag.d.ts +0 -3
- package/dist/types/src/extensions/hashtag.d.ts.map +0 -1
- package/dist/types/src/extensions/json.d.ts +0 -7
- package/dist/types/src/extensions/json.d.ts.map +0 -1
- package/dist/types/src/extensions/listener.d.ts +0 -13
- package/dist/types/src/extensions/listener.d.ts.map +0 -1
- package/dist/types/src/extensions/markdown/action.d.ts +0 -12
- package/dist/types/src/extensions/markdown/action.d.ts.map +0 -1
- package/dist/types/src/extensions/markdown/bundle.d.ts +0 -22
- package/dist/types/src/extensions/markdown/bundle.d.ts.map +0 -1
- package/dist/types/src/extensions/markdown/changes.d.ts +0 -10
- package/dist/types/src/extensions/markdown/changes.d.ts.map +0 -1
- package/dist/types/src/extensions/markdown/changes.test.d.ts +0 -2
- package/dist/types/src/extensions/markdown/changes.test.d.ts.map +0 -1
- package/dist/types/src/extensions/markdown/debug.d.ts +0 -11
- package/dist/types/src/extensions/markdown/debug.d.ts.map +0 -1
- package/dist/types/src/extensions/markdown/decorate.d.ts +0 -25
- package/dist/types/src/extensions/markdown/decorate.d.ts.map +0 -1
- package/dist/types/src/extensions/markdown/formatting.d.ts +0 -61
- package/dist/types/src/extensions/markdown/formatting.d.ts.map +0 -1
- package/dist/types/src/extensions/markdown/formatting.test.d.ts +0 -3
- package/dist/types/src/extensions/markdown/formatting.test.d.ts.map +0 -1
- package/dist/types/src/extensions/markdown/highlight.d.ts +0 -37
- package/dist/types/src/extensions/markdown/highlight.d.ts.map +0 -1
- package/dist/types/src/extensions/markdown/image.d.ts +0 -7
- package/dist/types/src/extensions/markdown/image.d.ts.map +0 -1
- package/dist/types/src/extensions/markdown/index.d.ts +0 -10
- package/dist/types/src/extensions/markdown/index.d.ts.map +0 -1
- package/dist/types/src/extensions/markdown/link.d.ts +0 -7
- package/dist/types/src/extensions/markdown/link.d.ts.map +0 -1
- package/dist/types/src/extensions/markdown/parser.test.d.ts +0 -2
- package/dist/types/src/extensions/markdown/parser.test.d.ts.map +0 -1
- package/dist/types/src/extensions/markdown/styles.d.ts +0 -4
- package/dist/types/src/extensions/markdown/styles.d.ts.map +0 -1
- package/dist/types/src/extensions/markdown/table.d.ts +0 -8
- package/dist/types/src/extensions/markdown/table.d.ts.map +0 -1
- package/dist/types/src/extensions/mention.d.ts +0 -7
- package/dist/types/src/extensions/mention.d.ts.map +0 -1
- package/dist/types/src/extensions/modal.d.ts +0 -7
- package/dist/types/src/extensions/modal.d.ts.map +0 -1
- package/dist/types/src/extensions/modes.d.ts +0 -10
- package/dist/types/src/extensions/modes.d.ts.map +0 -1
- package/dist/types/src/extensions/outliner/commands.d.ts +0 -10
- package/dist/types/src/extensions/outliner/commands.d.ts.map +0 -1
- package/dist/types/src/extensions/outliner/editor.d.ts +0 -5
- package/dist/types/src/extensions/outliner/editor.d.ts.map +0 -1
- package/dist/types/src/extensions/outliner/editor.test.d.ts +0 -2
- package/dist/types/src/extensions/outliner/editor.test.d.ts.map +0 -1
- package/dist/types/src/extensions/outliner/index.d.ts +0 -4
- package/dist/types/src/extensions/outliner/index.d.ts.map +0 -1
- package/dist/types/src/extensions/outliner/menu.d.ts +0 -8
- package/dist/types/src/extensions/outliner/menu.d.ts.map +0 -1
- package/dist/types/src/extensions/outliner/outliner.d.ts +0 -11
- package/dist/types/src/extensions/outliner/outliner.d.ts.map +0 -1
- package/dist/types/src/extensions/outliner/outliner.test.d.ts +0 -2
- package/dist/types/src/extensions/outliner/outliner.test.d.ts.map +0 -1
- package/dist/types/src/extensions/outliner/selection.d.ts +0 -12
- package/dist/types/src/extensions/outliner/selection.d.ts.map +0 -1
- package/dist/types/src/extensions/outliner/tree.d.ts +0 -79
- package/dist/types/src/extensions/outliner/tree.d.ts.map +0 -1
- package/dist/types/src/extensions/outliner/tree.test.d.ts +0 -2
- package/dist/types/src/extensions/outliner/tree.test.d.ts.map +0 -1
- package/dist/types/src/extensions/preview/index.d.ts +0 -2
- package/dist/types/src/extensions/preview/index.d.ts.map +0 -1
- package/dist/types/src/extensions/preview/preview.d.ts +0 -32
- package/dist/types/src/extensions/preview/preview.d.ts.map +0 -1
- package/dist/types/src/extensions/replacer.d.ts +0 -21
- package/dist/types/src/extensions/replacer.d.ts.map +0 -1
- package/dist/types/src/extensions/replacer.test.d.ts +0 -2
- package/dist/types/src/extensions/replacer.test.d.ts.map +0 -1
- package/dist/types/src/extensions/scrolling.d.ts +0 -78
- package/dist/types/src/extensions/scrolling.d.ts.map +0 -1
- package/dist/types/src/extensions/selection.d.ts +0 -24
- package/dist/types/src/extensions/selection.d.ts.map +0 -1
- package/dist/types/src/extensions/state.d.ts +0 -2
- package/dist/types/src/extensions/state.d.ts.map +0 -1
- package/dist/types/src/extensions/submit.d.ts +0 -10
- package/dist/types/src/extensions/submit.d.ts.map +0 -1
- package/dist/types/src/extensions/tab.d.ts +0 -4
- package/dist/types/src/extensions/tab.d.ts.map +0 -1
- package/dist/types/src/extensions/tags/extended-markdown.d.ts +0 -10
- package/dist/types/src/extensions/tags/extended-markdown.d.ts.map +0 -1
- package/dist/types/src/extensions/tags/extended-markdown.test.d.ts +0 -2
- package/dist/types/src/extensions/tags/extended-markdown.test.d.ts.map +0 -1
- package/dist/types/src/extensions/tags/index.d.ts +0 -4
- package/dist/types/src/extensions/tags/index.d.ts.map +0 -1
- package/dist/types/src/extensions/tags/streamer.d.ts +0 -12
- package/dist/types/src/extensions/tags/streamer.d.ts.map +0 -1
- package/dist/types/src/extensions/tags/xml-tags.d.ts +0 -97
- package/dist/types/src/extensions/tags/xml-tags.d.ts.map +0 -1
- package/dist/types/src/extensions/tags/xml-util.d.ts +0 -10
- package/dist/types/src/extensions/tags/xml-util.d.ts.map +0 -1
- package/dist/types/src/extensions/typewriter.d.ts +0 -10
- package/dist/types/src/extensions/typewriter.d.ts.map +0 -1
- package/dist/types/src/stories/CommandDialog.stories.d.ts +0 -14
- package/dist/types/src/stories/CommandDialog.stories.d.ts.map +0 -1
- package/dist/types/src/styles/index.d.ts +0 -4
- package/dist/types/src/styles/index.d.ts.map +0 -1
- package/dist/types/src/styles/markdown.d.ts +0 -8
- package/dist/types/src/styles/markdown.d.ts.map +0 -1
- package/dist/types/src/styles/theme.d.ts +0 -38
- package/dist/types/src/styles/theme.d.ts.map +0 -1
- package/dist/types/src/styles/tokens.d.ts +0 -3
- package/dist/types/src/styles/tokens.d.ts.map +0 -1
- package/dist/types/src/types/index.d.ts +0 -2
- package/dist/types/src/types/index.d.ts.map +0 -1
- package/dist/types/src/types/types.d.ts +0 -21
- package/dist/types/src/types/types.d.ts.map +0 -1
- package/dist/types/src/util/cursor.d.ts +0 -31
- package/dist/types/src/util/cursor.d.ts.map +0 -1
- package/dist/types/src/util/debug.d.ts +0 -21
- package/dist/types/src/util/debug.d.ts.map +0 -1
- package/dist/types/src/util/decorations.d.ts +0 -4
- package/dist/types/src/util/decorations.d.ts.map +0 -1
- package/dist/types/src/util/dom.d.ts +0 -10
- package/dist/types/src/util/dom.d.ts.map +0 -1
- package/dist/types/src/util/facet.d.ts +0 -3
- package/dist/types/src/util/facet.d.ts.map +0 -1
- package/src/components/EditorContent/EditorContent.stories.tsx +0 -70
- package/src/components/EditorContent/EditorContent.tsx +0 -70
- package/src/components/EditorContent/index.ts +0 -6
- package/src/components/EditorMenuProvider/util.ts +0 -31
- package/src/components/EditorToolbar/actions.ts +0 -86
- package/src/components/EditorToolbar/useEditorToolbar.ts +0 -20
- package/src/defaults.ts +0 -52
- package/src/extensions/annotations.ts +0 -55
- package/src/extensions/autocomplete/autocomplete.ts +0 -151
- package/src/extensions/autocomplete/index.ts +0 -8
- package/src/extensions/autocomplete/match.ts +0 -46
- package/src/extensions/autocomplete/placeholder.ts +0 -117
- package/src/extensions/autocomplete/typeahead.ts +0 -87
- package/src/extensions/automerge/automerge.stories.tsx +0 -149
- package/src/extensions/automerge/automerge.test.tsx +0 -78
- package/src/extensions/automerge/automerge.ts +0 -105
- package/src/extensions/automerge/cursor.ts +0 -28
- package/src/extensions/automerge/defs.ts +0 -31
- package/src/extensions/automerge/index.ts +0 -5
- package/src/extensions/automerge/sync.ts +0 -79
- package/src/extensions/automerge/update-automerge.ts +0 -50
- package/src/extensions/automerge/update-codemirror.ts +0 -115
- package/src/extensions/autoscroll.ts +0 -163
- package/src/extensions/awareness/awareness-provider.ts +0 -127
- package/src/extensions/awareness/awareness.ts +0 -315
- package/src/extensions/awareness/index.ts +0 -6
- package/src/extensions/blast.ts +0 -363
- package/src/extensions/blocks.ts +0 -131
- package/src/extensions/bookmarks.ts +0 -75
- package/src/extensions/comments.ts +0 -598
- package/src/extensions/debug.ts +0 -15
- package/src/extensions/dnd.ts +0 -37
- package/src/extensions/factories.ts +0 -278
- package/src/extensions/focus.ts +0 -36
- package/src/extensions/folding.tsx +0 -43
- package/src/extensions/hashtag.tsx +0 -68
- package/src/extensions/json.ts +0 -57
- package/src/extensions/listener.ts +0 -32
- package/src/extensions/markdown/action.ts +0 -117
- package/src/extensions/markdown/bundle.ts +0 -105
- package/src/extensions/markdown/changes.test.ts +0 -26
- package/src/extensions/markdown/changes.ts +0 -149
- package/src/extensions/markdown/debug.ts +0 -44
- package/src/extensions/markdown/decorate.ts +0 -601
- package/src/extensions/markdown/formatting.test.ts +0 -498
- package/src/extensions/markdown/formatting.ts +0 -1265
- package/src/extensions/markdown/highlight.ts +0 -183
- package/src/extensions/markdown/image.ts +0 -118
- package/src/extensions/markdown/index.ts +0 -13
- package/src/extensions/markdown/link.ts +0 -50
- package/src/extensions/markdown/parser.test.ts +0 -75
- package/src/extensions/markdown/styles.ts +0 -135
- package/src/extensions/markdown/table.ts +0 -150
- package/src/extensions/mention.ts +0 -41
- package/src/extensions/modal.ts +0 -24
- package/src/extensions/modes.ts +0 -41
- package/src/extensions/outliner/commands.ts +0 -270
- package/src/extensions/outliner/editor.test.ts +0 -33
- package/src/extensions/outliner/editor.ts +0 -184
- package/src/extensions/outliner/index.ts +0 -7
- package/src/extensions/outliner/menu.ts +0 -128
- package/src/extensions/outliner/outliner.test.ts +0 -100
- package/src/extensions/outliner/outliner.ts +0 -167
- package/src/extensions/outliner/selection.ts +0 -50
- package/src/extensions/outliner/tree.test.ts +0 -168
- package/src/extensions/outliner/tree.ts +0 -317
- package/src/extensions/preview/index.ts +0 -5
- package/src/extensions/preview/preview.ts +0 -193
- package/src/extensions/replacer.test.ts +0 -75
- package/src/extensions/replacer.ts +0 -93
- package/src/extensions/scrolling.ts +0 -189
- package/src/extensions/selection.ts +0 -100
- package/src/extensions/state.ts +0 -7
- package/src/extensions/submit.ts +0 -62
- package/src/extensions/tab.ts +0 -29
- package/src/extensions/tags/extended-markdown.test.ts +0 -262
- package/src/extensions/tags/extended-markdown.ts +0 -78
- package/src/extensions/tags/index.ts +0 -7
- package/src/extensions/tags/streamer.ts +0 -243
- package/src/extensions/tags/xml-tags.ts +0 -500
- package/src/extensions/tags/xml-util.ts +0 -94
- package/src/extensions/typewriter.ts +0 -68
- package/src/stories/CommandDialog.stories.tsx +0 -83
- package/src/styles/index.ts +0 -7
- package/src/styles/markdown.ts +0 -26
- package/src/styles/theme.ts +0 -269
- package/src/styles/tokens.ts +0 -17
- package/src/types/index.ts +0 -5
- package/src/types/types.ts +0 -32
- package/src/util/cursor.ts +0 -56
- package/src/util/debug.ts +0 -69
- package/src/util/decorations.ts +0 -21
- package/src/util/dom.ts +0 -34
- package/src/util/facet.ts +0 -13
- /package/dist/types/src/components/{EditorContent → Editor}/controller.d.ts +0 -0
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { Transaction } from '@codemirror/state';
|
|
6
|
+
import { EditorView as NaturalEditorView } from '@codemirror/view';
|
|
7
|
+
import React, { forwardRef, useEffect, useImperativeHandle, useRef } from 'react';
|
|
8
|
+
|
|
9
|
+
import { type ThemedClassName } from '@dxos/react-ui';
|
|
10
|
+
import { initialSync } from '@dxos/ui-editor';
|
|
11
|
+
import { mx } from '@dxos/ui-theme';
|
|
12
|
+
|
|
13
|
+
import { type UseTextEditorProps, useTextEditor } from '../../hooks';
|
|
14
|
+
import { type EditorController, createEditorController, noopController } from './controller';
|
|
15
|
+
|
|
16
|
+
export type EditorViewProps = ThemedClassName<
|
|
17
|
+
{
|
|
18
|
+
focusable?: boolean;
|
|
19
|
+
value?: string;
|
|
20
|
+
onChange?: (value: string) => void;
|
|
21
|
+
} & UseTextEditorProps
|
|
22
|
+
>;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Minimal text editor.
|
|
26
|
+
* NOTE: This shouold not be used with the automerge extension.
|
|
27
|
+
*/
|
|
28
|
+
// TODO(burdon): Move controller to Root component, then make composable.
|
|
29
|
+
export const EditorView = forwardRef<EditorController, EditorViewProps>(
|
|
30
|
+
({ classNames, id, extensions, selectionEnd, focusable = true, value, onChange, ...props }, forwardedRef) => {
|
|
31
|
+
// Hold the latest onChange in a ref so callers may pass an inline callback
|
|
32
|
+
// without forcing the underlying editor to be destroyed and recreated on
|
|
33
|
+
// every render — which would blur the focused input on each keystroke.
|
|
34
|
+
const onChangeRef = useRef(onChange);
|
|
35
|
+
onChangeRef.current = onChange;
|
|
36
|
+
|
|
37
|
+
const { parentRef, focusAttributes, view } = useTextEditor(
|
|
38
|
+
() => ({
|
|
39
|
+
id,
|
|
40
|
+
initialValue: value,
|
|
41
|
+
selectionEnd,
|
|
42
|
+
extensions: [
|
|
43
|
+
extensions ?? [],
|
|
44
|
+
NaturalEditorView.updateListener.of(({ view, docChanged, transactions }) => {
|
|
45
|
+
const isInitialSync = transactions.some((tr) => tr.annotation(Transaction.userEvent) === initialSync.value);
|
|
46
|
+
if (!isInitialSync && docChanged) {
|
|
47
|
+
onChangeRef.current?.(view.state.doc.toString());
|
|
48
|
+
}
|
|
49
|
+
}),
|
|
50
|
+
],
|
|
51
|
+
...props,
|
|
52
|
+
}),
|
|
53
|
+
[id, extensions, selectionEnd],
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
// External controller.
|
|
57
|
+
useImperativeHandle(forwardedRef, () => {
|
|
58
|
+
return createEditorController(view);
|
|
59
|
+
}, [id, view]);
|
|
60
|
+
|
|
61
|
+
// Sync the editor doc to the controlled `value` prop, but only when they
|
|
62
|
+
// disagree. After internal typing the prop will already match the editor's
|
|
63
|
+
// doc, and dispatching anyway would race fast keystrokes — a stale rAF
|
|
64
|
+
// closure can replace doc content with an older value, dropping characters.
|
|
65
|
+
useEffect(() => {
|
|
66
|
+
if (!view) {
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
const next = value ?? '';
|
|
70
|
+
if (view.state.doc.toString() === next) {
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
requestAnimationFrame(() => {
|
|
74
|
+
if (view.state.doc.toString() === next) {
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
view.dispatch({
|
|
78
|
+
annotations: initialSync,
|
|
79
|
+
changes: [{ from: 0, to: view.state.doc.length, insert: next }],
|
|
80
|
+
selection: selectionEnd ? { anchor: next.length } : undefined,
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
if (selectionEnd) {
|
|
84
|
+
view.focus();
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
}, [view, value, selectionEnd]);
|
|
88
|
+
|
|
89
|
+
return (
|
|
90
|
+
<div
|
|
91
|
+
className={mx('w-full outline-hidden focus:border-accent-bg focus-within:border-focus-ring-subtle', classNames)}
|
|
92
|
+
{...(focusable ? focusAttributes : {})}
|
|
93
|
+
ref={parentRef}
|
|
94
|
+
/>
|
|
95
|
+
);
|
|
96
|
+
},
|
|
97
|
+
);
|
|
98
|
+
|
|
99
|
+
export { type EditorController, createEditorController, noopController };
|
|
@@ -11,17 +11,26 @@ export interface EditorController {
|
|
|
11
11
|
focus: () => void;
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
// Hide `view` from own-enumerable traversal. Controllers are passed through React props/context, and the
|
|
15
|
+
// live `EditorView` reaches the global `window` via `view.observer.win` (CodeMirror's DOMObserver). React
|
|
16
|
+
// 19.2's dev render-logger walks changed props' object graphs and would otherwise descend into `window`,
|
|
17
|
+
// enumerate `window[0]` (a cross-origin iframe) and throw SecurityError. Direct access is unaffected.
|
|
18
|
+
const withHiddenView = (controller: EditorController): EditorController => {
|
|
19
|
+
Object.defineProperty(controller, 'view', { enumerable: false });
|
|
20
|
+
return controller;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export const noopController: EditorController = withHiddenView({
|
|
15
24
|
get view() {
|
|
16
25
|
return null;
|
|
17
26
|
},
|
|
18
27
|
getText: () => '',
|
|
19
28
|
setText: () => {},
|
|
20
29
|
focus: () => {},
|
|
21
|
-
};
|
|
30
|
+
});
|
|
22
31
|
|
|
23
32
|
export const createEditorController = (view: EditorView | null): EditorController => {
|
|
24
|
-
return {
|
|
33
|
+
return withHiddenView({
|
|
25
34
|
get view() {
|
|
26
35
|
return view;
|
|
27
36
|
},
|
|
@@ -46,5 +55,5 @@ export const createEditorController = (view: EditorView | null): EditorControlle
|
|
|
46
55
|
}
|
|
47
56
|
},
|
|
48
57
|
focus: () => view?.focus(),
|
|
49
|
-
};
|
|
58
|
+
});
|
|
50
59
|
};
|
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
type DxAnchorActivate,
|
|
14
14
|
Icon,
|
|
15
15
|
Popover,
|
|
16
|
+
ScrollArea,
|
|
16
17
|
toLocalizedString,
|
|
17
18
|
useDynamicRef,
|
|
18
19
|
useThemeContext,
|
|
@@ -22,7 +23,9 @@ import {
|
|
|
22
23
|
import { type EditorMenuGroup, type EditorMenuItem } from './menu';
|
|
23
24
|
|
|
24
25
|
export type EditorMenuProviderProps = PropsWithChildren<{
|
|
25
|
-
|
|
26
|
+
// Provided as a getter (not a value prop) so the live `EditorView` is never carried in a React prop that
|
|
27
|
+
// the dev render-logger would walk into a cross-origin frame. See `controller.ts` for the full rationale.
|
|
28
|
+
getView?: () => EditorView | null;
|
|
26
29
|
groups?: EditorMenuGroup[];
|
|
27
30
|
currentItem?: string;
|
|
28
31
|
open?: boolean;
|
|
@@ -35,18 +38,16 @@ export type EditorMenuProviderProps = PropsWithChildren<{
|
|
|
35
38
|
}>;
|
|
36
39
|
|
|
37
40
|
/**
|
|
38
|
-
* Implements the Popover and listens for the `dx-anchor-activate` event from the
|
|
39
|
-
* `popover` extension's decoration.
|
|
40
|
-
*
|
|
41
|
+
* Implements the Popover and listens for the `dx-anchor-activate` event from the `popover` extension's decoration.
|
|
41
42
|
* NOTE: We don't use DropdownMenu because the command menu needs to manage focus explicitly.
|
|
42
43
|
* I.e., focus must remain in the editor while displaying the menu (for type-ahead).
|
|
43
44
|
*/
|
|
44
45
|
export const EditorMenuProvider = ({
|
|
45
46
|
children,
|
|
46
|
-
|
|
47
|
+
getView,
|
|
47
48
|
groups,
|
|
48
49
|
currentItem,
|
|
49
|
-
open:
|
|
50
|
+
open: openProp,
|
|
50
51
|
defaultOpen,
|
|
51
52
|
numItems = 8,
|
|
52
53
|
onOpenChange,
|
|
@@ -57,13 +58,15 @@ export const EditorMenuProvider = ({
|
|
|
57
58
|
const { tx } = useThemeContext();
|
|
58
59
|
const triggerRef = useRef<HTMLButtonElement | null>(null);
|
|
59
60
|
|
|
60
|
-
|
|
61
|
+
// Hold the latest `getView` so callbacks/effects always read the current view without re-subscribing.
|
|
62
|
+
const getViewRef = useDynamicRef(getView);
|
|
61
63
|
const [open, setOpen] = useControllableState({
|
|
62
|
-
prop:
|
|
64
|
+
prop: openProp,
|
|
63
65
|
defaultProp: defaultOpen,
|
|
64
66
|
onChange: (open) => {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
+
const view = getViewRef.current?.();
|
|
68
|
+
invariant(view);
|
|
69
|
+
onOpenChange?.({ view, open });
|
|
67
70
|
},
|
|
68
71
|
});
|
|
69
72
|
|
|
@@ -78,13 +81,14 @@ export const EditorMenuProvider = ({
|
|
|
78
81
|
root,
|
|
79
82
|
DX_ANCHOR_ACTIVATE as any,
|
|
80
83
|
(event: DxAnchorActivate) => {
|
|
81
|
-
const { trigger,
|
|
82
|
-
|
|
83
|
-
// If this has a `refId`, then it’s probably a URL or DXN and out of scope for this component.
|
|
84
|
-
if (!refId) {
|
|
84
|
+
const { trigger, dxn } = event;
|
|
85
|
+
if (!dxn) {
|
|
85
86
|
triggerRef.current = trigger as HTMLButtonElement;
|
|
86
87
|
if (onActivate) {
|
|
87
|
-
|
|
88
|
+
const view = getViewRef.current?.();
|
|
89
|
+
if (view) {
|
|
90
|
+
onActivate({ view, trigger: trigger.getAttribute('data-trigger') ?? undefined });
|
|
91
|
+
}
|
|
88
92
|
} else {
|
|
89
93
|
requestAnimationFrame(() => setOpen(true));
|
|
90
94
|
}
|
|
@@ -99,10 +103,11 @@ export const EditorMenuProvider = ({
|
|
|
99
103
|
|
|
100
104
|
const handleSelect = useCallback<NonNullable<MenuProps['onSelect']>>(
|
|
101
105
|
(item) => {
|
|
102
|
-
|
|
103
|
-
|
|
106
|
+
const view = getViewRef.current?.();
|
|
107
|
+
invariant(view);
|
|
108
|
+
onSelect?.({ view, item });
|
|
104
109
|
},
|
|
105
|
-
[
|
|
110
|
+
[getViewRef, onSelect],
|
|
106
111
|
);
|
|
107
112
|
|
|
108
113
|
const menuGroups = groups?.filter((group) => group.items.length > 0) ?? [];
|
|
@@ -115,32 +120,32 @@ export const EditorMenuProvider = ({
|
|
|
115
120
|
<Popover.Portal>
|
|
116
121
|
<Popover.Content
|
|
117
122
|
align='start'
|
|
118
|
-
classNames={
|
|
119
|
-
'overflow-y-auto',
|
|
120
|
-
!menuGroups.length && 'hidden',
|
|
121
|
-
])}
|
|
123
|
+
classNames={['flex flex-col', !menuGroups.length && 'hidden']}
|
|
122
124
|
style={{
|
|
123
125
|
maxBlockSize: 36 * numItems + 10,
|
|
124
126
|
}}
|
|
125
|
-
|
|
126
|
-
* NOTE: We keep the focus in the editor, but Radix routes escape key.
|
|
127
|
-
*/
|
|
127
|
+
// NOTE: We keep the focus in the editor, but Radix routes escape key.
|
|
128
128
|
onEscapeKeyDown={() => {
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
129
|
+
const currentView = getViewRef.current?.();
|
|
130
|
+
if (currentView) {
|
|
131
|
+
onCancel?.({ view: currentView });
|
|
132
|
+
}
|
|
132
133
|
}}
|
|
133
134
|
onOpenAutoFocus={(event) => event.preventDefault()}
|
|
134
135
|
>
|
|
135
|
-
<Popover.Viewport classNames=
|
|
136
|
-
<
|
|
136
|
+
<Popover.Viewport asChild classNames='dx-container'>
|
|
137
|
+
<ScrollArea.Root thin>
|
|
138
|
+
<ScrollArea.Viewport>
|
|
139
|
+
<Menu groups={menuGroups} currentItem={currentItem} onSelect={handleSelect} />
|
|
140
|
+
</ScrollArea.Viewport>
|
|
141
|
+
</ScrollArea.Root>
|
|
137
142
|
</Popover.Viewport>
|
|
138
143
|
<Popover.Arrow />
|
|
139
144
|
</Popover.Content>
|
|
140
145
|
</Popover.Portal>
|
|
141
146
|
|
|
142
147
|
{/* Content */}
|
|
143
|
-
<div ref={setRoot}
|
|
148
|
+
<div className='contents' ref={setRoot}>
|
|
144
149
|
{children}
|
|
145
150
|
</div>
|
|
146
151
|
</Popover.Root>
|
|
@@ -162,7 +167,7 @@ const Menu = ({ groups, currentItem, onSelect }: MenuProps) => {
|
|
|
162
167
|
{groups.map((group, index) => (
|
|
163
168
|
<Fragment key={group.id}>
|
|
164
169
|
<MenuGroup group={group} currentItem={currentItem} onSelect={onSelect} />
|
|
165
|
-
{index < groups.length - 1 && <div className={tx('menu.separator',
|
|
170
|
+
{index < groups.length - 1 && <div className={tx('menu.separator', {})} />}
|
|
166
171
|
</Fragment>
|
|
167
172
|
))}
|
|
168
173
|
</ul>
|
|
@@ -185,7 +190,7 @@ const MenuGroup = ({ group, currentItem, onSelect }: MenuGroupProps) => {
|
|
|
185
190
|
return (
|
|
186
191
|
<>
|
|
187
192
|
{group.label && (
|
|
188
|
-
<div className={tx('menu.groupLabel',
|
|
193
|
+
<div className={tx('menu.groupLabel', {})}>
|
|
189
194
|
<span>{toLocalizedString(group.label, t)}</span>
|
|
190
195
|
</div>
|
|
191
196
|
)}
|
|
@@ -221,12 +226,8 @@ const MenuItem = ({ item, current, onSelect }: MenuItemProps) => {
|
|
|
221
226
|
const handleSelect = useCallback(() => onSelect?.(item), [item, onSelect]);
|
|
222
227
|
|
|
223
228
|
return (
|
|
224
|
-
<li
|
|
225
|
-
|
|
226
|
-
className={tx('menu.item', 'menu__item--exotic-unfocusable', {}, [current && 'bg-hoverSurface'])}
|
|
227
|
-
onClick={handleSelect}
|
|
228
|
-
>
|
|
229
|
-
{item.icon && <Icon icon={item.icon} size={5} />}
|
|
229
|
+
<li ref={listRef} className={tx('menu.item', {}, [current && 'bg-hover-surface'])} onClick={handleSelect}>
|
|
230
|
+
{item.icon && <Icon icon={item.icon} />}
|
|
230
231
|
<span className='grow truncate'>{toLocalizedString(item.label, t)}</span>
|
|
231
232
|
</li>
|
|
232
233
|
);
|
|
@@ -2,9 +2,10 @@
|
|
|
2
2
|
// Copyright 2025 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
+
import { insertAtLineStart } from '@dxos/ui-editor';
|
|
6
|
+
|
|
5
7
|
import { type EditorMenuGroup } from './menu';
|
|
6
8
|
import { popoverRangeEffect } from './popover';
|
|
7
|
-
import { insertAtLineStart } from './util';
|
|
8
9
|
|
|
9
10
|
export const formattingCommands: EditorMenuGroup = {
|
|
10
11
|
id: 'markdown',
|
|
@@ -109,6 +110,7 @@ export const linkSlashCommands: EditorMenuGroup = {
|
|
|
109
110
|
label: 'Block embed',
|
|
110
111
|
icon: 'ph--lego--regular',
|
|
111
112
|
onSelect: ({ view, head }) => {
|
|
113
|
+
// Seed the same query shape as typing "@@" manually.
|
|
112
114
|
view.dispatch({
|
|
113
115
|
changes: { from: head, insert: '@@' },
|
|
114
116
|
selection: { anchor: head + 2, head: head + 2 },
|
|
@@ -5,10 +5,9 @@
|
|
|
5
5
|
import { type EditorView } from '@codemirror/view';
|
|
6
6
|
|
|
7
7
|
import { type Label } from '@dxos/react-ui';
|
|
8
|
+
import { insertAtCursor } from '@dxos/ui-editor';
|
|
8
9
|
import { type MaybePromise } from '@dxos/util';
|
|
9
10
|
|
|
10
|
-
import { insertAtCursor } from './util';
|
|
11
|
-
|
|
12
11
|
export type EditorMenuGroup = {
|
|
13
12
|
id: string;
|
|
14
13
|
label?: Label;
|
|
@@ -13,11 +13,10 @@ import {
|
|
|
13
13
|
keymap,
|
|
14
14
|
} from '@codemirror/view';
|
|
15
15
|
|
|
16
|
+
import { type PlaceholderOptions, modalStateField, placeholder } from '@dxos/ui-editor';
|
|
17
|
+
import { type Range } from '@dxos/ui-editor/types';
|
|
16
18
|
import { isNonNullable, isTruthy } from '@dxos/util';
|
|
17
19
|
|
|
18
|
-
import { type PlaceholderOptions, modalStateField, placeholder } from '../../extensions';
|
|
19
|
-
import { type Range } from '../../types';
|
|
20
|
-
|
|
21
20
|
const DELIMITERS = [' ', ':'];
|
|
22
21
|
|
|
23
22
|
export type PopoverOptions = {
|
|
@@ -26,15 +25,19 @@ export type PopoverOptions = {
|
|
|
26
25
|
placeholder?: Partial<PlaceholderOptions>;
|
|
27
26
|
delimiters?: string[];
|
|
28
27
|
|
|
29
|
-
|
|
30
|
-
|
|
28
|
+
/**
|
|
29
|
+
* Open the popover automatically while typing a word (no trigger character required).
|
|
30
|
+
* The completion range covers the word under the cursor (delimited by {@link PopoverOptions.delimiters}).
|
|
31
|
+
*/
|
|
32
|
+
activateOnTyping?: boolean;
|
|
31
33
|
|
|
32
34
|
// Trigger update.
|
|
33
35
|
onTextChange?: (event: { view: EditorView; pos: number; text: string; trigger?: string }) => void;
|
|
34
36
|
onClose?: (event: { view: EditorView }) => void;
|
|
35
37
|
|
|
36
38
|
// Menu specific.
|
|
37
|
-
|
|
39
|
+
/** Returns true when the menu consumed the key (an item was selected); false falls through. */
|
|
40
|
+
onEnter?: (event: { view: EditorView }) => boolean | void;
|
|
38
41
|
onArrowUp?: (event: { view: EditorView }) => void;
|
|
39
42
|
onArrowDown?: (event: { view: EditorView }) => void;
|
|
40
43
|
};
|
|
@@ -48,12 +51,14 @@ export const popover = (options: PopoverOptions = {}): Extension => {
|
|
|
48
51
|
Prec.highest(popoverKeymap(options)),
|
|
49
52
|
popoverStateField,
|
|
50
53
|
popoverTriggerListener(options),
|
|
54
|
+
options.activateOnTyping && popoverAutoActivate(options),
|
|
51
55
|
popoverAnchorDecoration(options),
|
|
52
56
|
modalStateField,
|
|
53
57
|
options.trigger &&
|
|
54
58
|
placeholder({
|
|
55
59
|
// TODO(burdon): Translations.
|
|
56
60
|
content: `Press '${Array.isArray(options.trigger) ? options.trigger[0] : options.trigger}' for commands`,
|
|
61
|
+
focusOnly: true,
|
|
57
62
|
...options.placeholder,
|
|
58
63
|
}),
|
|
59
64
|
].filter(isTruthy);
|
|
@@ -93,6 +98,33 @@ const popoverTriggerListener = (options: PopoverOptions) =>
|
|
|
93
98
|
}
|
|
94
99
|
});
|
|
95
100
|
|
|
101
|
+
/**
|
|
102
|
+
* Open the popover while typing a word, without requiring a trigger character. Once a range is
|
|
103
|
+
* active, {@link popoverTriggerListener} keeps it in sync and closes it (whitespace, cursor moves).
|
|
104
|
+
*/
|
|
105
|
+
const popoverAutoActivate = (options: PopoverOptions) =>
|
|
106
|
+
EditorView.updateListener.of(({ view, docChanged, transactions }) => {
|
|
107
|
+
// Only user input opens the popover — programmatic syncs (e.g. a controlled `value` update on
|
|
108
|
+
// mount) must not pop the menu.
|
|
109
|
+
if (!docChanged || !transactions.some((tr) => tr.isUserEvent('input')) || view.state.field(popoverStateField)) {
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
const selection = view.state.selection.main;
|
|
113
|
+
if (!selection.empty) {
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
const line = view.state.doc.lineAt(selection.head);
|
|
117
|
+
const before = line.text.slice(0, selection.head - line.from);
|
|
118
|
+
const idx = getLastIndexOf(before, options.delimiters ?? DELIMITERS);
|
|
119
|
+
const token = before.slice(idx + 1);
|
|
120
|
+
if (token.length === 0) {
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
view.dispatch({
|
|
124
|
+
effects: popoverRangeEffect.of({ range: { from: line.from + idx + 1, to: selection.head } }),
|
|
125
|
+
});
|
|
126
|
+
});
|
|
127
|
+
|
|
96
128
|
/**
|
|
97
129
|
* Popover navigation.
|
|
98
130
|
*/
|
|
@@ -190,9 +222,10 @@ const popoverKeymap = (options: PopoverOptions) => {
|
|
|
190
222
|
run: (view: EditorView) => {
|
|
191
223
|
const range = view.state.field(popoverStateField)?.range;
|
|
192
224
|
if (range) {
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
225
|
+
// The consumer deletes the range when it selects an item; when nothing is selectable
|
|
226
|
+
// (empty menu over an `activateOnTyping` range) the key must fall through so the
|
|
227
|
+
// typed text is preserved.
|
|
228
|
+
return options.onEnter?.({ view }) ?? false;
|
|
196
229
|
}
|
|
197
230
|
|
|
198
231
|
return false;
|
|
@@ -7,10 +7,9 @@ import { type EditorState } from '@codemirror/state';
|
|
|
7
7
|
import { type RefObject, useCallback, useMemo, useRef, useState } from 'react';
|
|
8
8
|
|
|
9
9
|
import { invariant } from '@dxos/invariant';
|
|
10
|
+
import { modalStateEffect } from '@dxos/ui-editor';
|
|
10
11
|
import { type MaybePromise } from '@dxos/util';
|
|
11
12
|
|
|
12
|
-
import { modalStateEffect } from '../../extensions';
|
|
13
|
-
|
|
14
13
|
import { type EditorMenuProviderProps } from './EditorMenuProvider';
|
|
15
14
|
import { type EditorMenuGroup, type EditorMenuItem } from './menu';
|
|
16
15
|
import { filterMenuGroups, getMenuItem, getNextMenuItem, getPreviousMenuItem } from './menu';
|
|
@@ -26,7 +25,7 @@ export type GetMenuContext = {
|
|
|
26
25
|
export type UseEditorMenuProps = {
|
|
27
26
|
filter?: boolean;
|
|
28
27
|
getMenu?: (context: GetMenuContext) => MaybePromise<EditorMenuGroup[]>;
|
|
29
|
-
} & Pick<PopoverOptions, 'trigger' | 'triggerKey' | 'placeholder'>;
|
|
28
|
+
} & Pick<PopoverOptions, 'trigger' | 'triggerKey' | 'placeholder' | 'activateOnTyping'>;
|
|
30
29
|
|
|
31
30
|
export type UseEditorMenu = {
|
|
32
31
|
groupsRef: RefObject<EditorMenuGroup[]>;
|
|
@@ -38,7 +37,7 @@ export type UseEditorMenu = {
|
|
|
38
37
|
* const { groupsRef, extension, ...menuProps } = useEditorMenu();
|
|
39
38
|
* const { parentRef, viewRef } = useTextEditor({ extensions: [extension] });
|
|
40
39
|
* return (
|
|
41
|
-
* <EditorMenuProvider
|
|
40
|
+
* <EditorMenuProvider getView={() => viewRef.current} groups={groupsRef.current} {...menuProps}>
|
|
42
41
|
* <div ref={parentRef} />
|
|
43
42
|
* </EditorMenuProvider>
|
|
44
43
|
* );
|
|
@@ -48,6 +47,7 @@ export const useEditorMenu = ({
|
|
|
48
47
|
trigger,
|
|
49
48
|
triggerKey,
|
|
50
49
|
placeholder,
|
|
50
|
+
activateOnTyping,
|
|
51
51
|
filter = true,
|
|
52
52
|
getMenu,
|
|
53
53
|
}: UseEditorMenuProps): UseEditorMenu => {
|
|
@@ -63,7 +63,8 @@ export const useEditorMenu = ({
|
|
|
63
63
|
const getMenuOptions = useCallback<NonNullable<UseEditorMenuProps['getMenu']>>(
|
|
64
64
|
async ({ text, trigger, ...props }) => {
|
|
65
65
|
const groups = (await getMenu?.({ text, trigger, ...props })) ?? [];
|
|
66
|
-
|
|
66
|
+
// The "@" menu can use "@@" as syntax for block embeds, so it owns its own query filtering.
|
|
67
|
+
return filter && trigger !== '@'
|
|
67
68
|
? filterMenuGroups(groups, (item) =>
|
|
68
69
|
text ? (item.label as string).toLowerCase().startsWith(text.toLowerCase()) : true,
|
|
69
70
|
)
|
|
@@ -74,7 +75,6 @@ export const useEditorMenu = ({
|
|
|
74
75
|
|
|
75
76
|
const handleOpenChange = useCallback<NonNullable<UseEditorMenu['onOpenChange']>>(
|
|
76
77
|
async ({ view, open }) => {
|
|
77
|
-
console.log(view, open);
|
|
78
78
|
invariant(view);
|
|
79
79
|
setOpen(open);
|
|
80
80
|
if (!open) {
|
|
@@ -110,7 +110,13 @@ export const useEditorMenu = ({
|
|
|
110
110
|
);
|
|
111
111
|
|
|
112
112
|
const handleSelect = useCallback<NonNullable<UseEditorMenu['onSelect']>>(({ view, item }) => {
|
|
113
|
+
// Delete trigger range (e.g., "/" and any typed filter text).
|
|
114
|
+
const { range } = view.state.field(popoverStateField) ?? {};
|
|
115
|
+
if (range) {
|
|
116
|
+
view.dispatch({ changes: { from: range.from, to: range.to, insert: '' } });
|
|
117
|
+
}
|
|
113
118
|
void item.onSelect?.({ view, head: view.state.selection.main.head });
|
|
119
|
+
view.focus();
|
|
114
120
|
}, []);
|
|
115
121
|
|
|
116
122
|
const handleCancel = useCallback<NonNullable<UseEditorMenu['onCancel']>>(({ view }) => {
|
|
@@ -129,11 +135,14 @@ export const useEditorMenu = ({
|
|
|
129
135
|
trigger,
|
|
130
136
|
triggerKey,
|
|
131
137
|
placeholder,
|
|
138
|
+
activateOnTyping,
|
|
132
139
|
onClose: ({ view }) => handleOpenChange({ view, open: false }),
|
|
133
140
|
onEnter: ({ view }) => {
|
|
134
141
|
if (currentRef.current) {
|
|
135
142
|
handleSelect({ view, item: currentRef.current });
|
|
143
|
+
return true;
|
|
136
144
|
}
|
|
145
|
+
return false;
|
|
137
146
|
},
|
|
138
147
|
onArrowUp: () => {
|
|
139
148
|
setCurrentItem((currentItem) => {
|
|
@@ -155,12 +164,17 @@ export const useEditorMenu = ({
|
|
|
155
164
|
if (firstItem) {
|
|
156
165
|
setCurrentItem(firstItem.id);
|
|
157
166
|
currentRef.current = firstItem;
|
|
167
|
+
} else {
|
|
168
|
+
// No matches: clear the selection so Enter falls through instead of
|
|
169
|
+
// selecting a stale item from a previous query.
|
|
170
|
+
setCurrentItem(undefined);
|
|
171
|
+
currentRef.current = null;
|
|
158
172
|
}
|
|
159
173
|
|
|
160
174
|
refresh({});
|
|
161
175
|
},
|
|
162
176
|
});
|
|
163
|
-
}, [handleOpenChange, getMenuOptions, serializedTrigger, placeholder]);
|
|
177
|
+
}, [handleOpenChange, getMenuOptions, serializedTrigger, placeholder, activateOnTyping]);
|
|
164
178
|
|
|
165
179
|
return {
|
|
166
180
|
groupsRef,
|
|
@@ -7,8 +7,7 @@ import React, { type PropsWithChildren, type RefObject, useCallback, useEffect,
|
|
|
7
7
|
|
|
8
8
|
import { addEventListener } from '@dxos/async';
|
|
9
9
|
import { DX_ANCHOR_ACTIVATE, type DxAnchorActivate, Popover } from '@dxos/react-ui';
|
|
10
|
-
|
|
11
|
-
import { type PreviewLinkRef, type PreviewLinkTarget } from '../../extensions';
|
|
10
|
+
import { type PreviewLinkRef, type PreviewLinkTarget } from '@dxos/ui-editor';
|
|
12
11
|
|
|
13
12
|
type EditorPreviewPopoverValue = Partial<{
|
|
14
13
|
link: PreviewLinkRef;
|
|
@@ -33,16 +32,16 @@ export const EditorPreviewProvider = ({ children, onLookup }: EditorPreviewProvi
|
|
|
33
32
|
|
|
34
33
|
const handleActivate = useCallback(
|
|
35
34
|
(event: DxAnchorActivate) => {
|
|
36
|
-
const {
|
|
35
|
+
const { dxn, label, trigger } = event;
|
|
37
36
|
setValue((value) => ({
|
|
38
37
|
...value,
|
|
39
|
-
link: { label,
|
|
38
|
+
link: { label, dxn },
|
|
40
39
|
pending: true,
|
|
41
40
|
}));
|
|
42
41
|
|
|
43
|
-
triggerRef.current =
|
|
42
|
+
triggerRef.current = trigger;
|
|
44
43
|
queueMicrotask(() => setOpen(true));
|
|
45
|
-
void onLookup?.({ label,
|
|
44
|
+
void onLookup?.({ label, dxn }).then((target) =>
|
|
46
45
|
setValue((value) => ({
|
|
47
46
|
...value,
|
|
48
47
|
target: target ?? undefined,
|
|
@@ -69,9 +68,7 @@ export const EditorPreviewProvider = ({ children, onLookup }: EditorPreviewProvi
|
|
|
69
68
|
<EditorPreviewContextProvider pending={value.pending} link={value.link} target={value.target}>
|
|
70
69
|
<Popover.Root open={open} onOpenChange={setOpen}>
|
|
71
70
|
<Popover.VirtualTrigger virtualRef={triggerRef as unknown as RefObject<HTMLButtonElement>} />
|
|
72
|
-
|
|
73
|
-
{/* Content */}
|
|
74
|
-
<div ref={setRoot} role='none' className='contents'>
|
|
71
|
+
<div className='contents' ref={setRoot}>
|
|
75
72
|
{children}
|
|
76
73
|
</div>
|
|
77
74
|
</Popover.Root>
|