@dxos/react-ui-editor 0.8.4-main.dedc0f3 → 0.8.4-main.e8ec1fe
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 +5638 -5200
- 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 +5638 -5200
- 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 +14 -4
- package/dist/types/src/extensions/autoscroll.d.ts.map +1 -1
- 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 +10 -5
- 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 +8 -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.map +1 -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/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/preview/preview.d.ts +6 -4
- 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/streamer.d.ts.map +1 -1
- package/dist/types/src/extensions/tags/xml-tags.d.ts +42 -16
- package/dist/types/src/extensions/tags/xml-tags.d.ts.map +1 -1
- 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 +0 -1
- package/dist/types/src/stories/Tags.stories.d.ts.map +1 -1
- 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 +1 -1
- package/dist/types/src/types/types.d.ts.map +1 -1
- package/dist/types/src/util/debug.d.ts +4 -0
- package/dist/types/src/util/debug.d.ts.map +1 -1
- package/dist/types/src/util/index.d.ts +0 -1
- package/dist/types/src/util/index.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +58 -59
- 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.ts → autocomplete/autocomplete.ts} +8 -76
- 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 +98 -86
- 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 +2 -1
- package/src/extensions/factories.ts +47 -16
- 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 +8 -1
- package/src/extensions/json.ts +1 -1
- package/src/extensions/listener.ts +14 -20
- package/src/extensions/markdown/bundle.ts +16 -4
- package/src/extensions/markdown/decorate.ts +9 -8
- package/src/extensions/markdown/formatting.ts +8 -10
- package/src/extensions/markdown/highlight.ts +1 -1
- package/src/extensions/markdown/image.ts +2 -2
- package/src/extensions/markdown/link.ts +3 -0
- package/src/extensions/markdown/table.ts +6 -6
- package/src/extensions/modal.ts +24 -0
- package/src/extensions/modes.ts +2 -2
- package/src/extensions/{command/floating-menu.ts → outliner/menu.ts} +15 -20
- package/src/extensions/outliner/outliner.test.ts +1 -1
- package/src/extensions/outliner/outliner.ts +4 -4
- package/src/extensions/outliner/tree.test.ts +1 -1
- package/src/extensions/preview/index.ts +1 -1
- package/src/extensions/preview/preview.ts +14 -14
- 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 +2 -1
- package/src/extensions/tags/streamer.ts +4 -5
- package/src/extensions/tags/xml-tags.ts +320 -155
- package/src/extensions/typewriter.ts +1 -1
- package/src/hooks/useTextEditor.ts +31 -43
- package/src/stories/{Command.stories.tsx → CommandDialog.stories.tsx} +20 -27
- package/src/stories/Comments.stories.tsx +8 -9
- package/src/stories/EditorToolbar.stories.tsx +14 -13
- package/src/stories/Experimental.stories.tsx +7 -7
- package/src/stories/Markdown.stories.tsx +6 -6
- package/src/stories/Outliner.stories.tsx +40 -31
- package/src/stories/Popover.stories.tsx +162 -0
- package/src/stories/Preview.stories.tsx +46 -42
- package/src/stories/Tags.stories.tsx +24 -10
- package/src/stories/TextEditor.stories.tsx +10 -35
- package/src/stories/components/EditorStory.tsx +29 -16
- 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 +5 -0
- package/src/util/index.ts +0 -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 -14
- package/dist/types/src/components/Popover/RefDropdownMenu.d.ts.map +0 -1
- package/dist/types/src/components/Popover/RefPopover.d.ts +0 -37
- 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 -26
- 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 -19
- 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/dist/types/src/util/domino.d.ts +0 -18
- package/dist/types/src/util/domino.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 -89
- package/src/components/Popover/RefPopover.tsx +0 -117
- package/src/components/Popover/index.ts +0 -7
- 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/CommandMenu.stories.tsx +0 -160
- package/src/testing/index.ts +0 -5
- package/src/testing/util.ts +0 -7
- package/src/util/domino.ts +0 -51
|
@@ -3,17 +3,34 @@
|
|
|
3
3
|
//
|
|
4
4
|
|
|
5
5
|
import { syntaxTree } from '@codemirror/language';
|
|
6
|
+
import { Prec } from '@codemirror/state';
|
|
6
7
|
import { type EditorState, type Extension, RangeSetBuilder, StateEffect, StateField } from '@codemirror/state';
|
|
7
|
-
import {
|
|
8
|
+
import { keymap } from '@codemirror/view';
|
|
9
|
+
import { Decoration, type DecorationSet, EditorView, ViewPlugin, type ViewUpdate, WidgetType } from '@codemirror/view';
|
|
8
10
|
import { type ComponentType, type FC } from 'react';
|
|
9
11
|
|
|
10
12
|
import { invariant } from '@dxos/invariant';
|
|
11
13
|
import { log } from '@dxos/log';
|
|
12
14
|
|
|
15
|
+
import { type Range } from '../../types';
|
|
13
16
|
import { decorationSetToArray } from '../../util';
|
|
17
|
+
import { scrollToLineEffect } from '../scrolling';
|
|
14
18
|
|
|
15
19
|
import { nodeToJson } from './xml-util';
|
|
16
20
|
|
|
21
|
+
/**
|
|
22
|
+
* StateEffect for navigating to previous bookmark.
|
|
23
|
+
*/
|
|
24
|
+
export const navigatePreviousEffect = StateEffect.define<void>();
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* StateEffect for navigating to next bookmark.
|
|
28
|
+
*/
|
|
29
|
+
export const navigateNextEffect = StateEffect.define<void>();
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Dispatch function for updating state.
|
|
33
|
+
*/
|
|
17
34
|
export type StateDispatch<T> = T | ((state: T) => T);
|
|
18
35
|
|
|
19
36
|
/**
|
|
@@ -28,9 +45,11 @@ export type XmlEventHandler<TEvent = any> = (event: TEvent) => void;
|
|
|
28
45
|
/**
|
|
29
46
|
* Widget component.
|
|
30
47
|
*/
|
|
31
|
-
export type XmlWidgetProps<
|
|
48
|
+
export type XmlWidgetProps<TProps = any, TContext = any> = TProps & {
|
|
32
49
|
_tag: string;
|
|
33
|
-
context
|
|
50
|
+
context?: TContext;
|
|
51
|
+
range?: { from: number; to: number };
|
|
52
|
+
view?: EditorView;
|
|
34
53
|
onEvent?: XmlEventHandler;
|
|
35
54
|
};
|
|
36
55
|
|
|
@@ -43,29 +62,37 @@ export type XmlWidgetFactory = (props: XmlWidgetProps, onEvent?: XmlEventHandler
|
|
|
43
62
|
* Widget registry definition.
|
|
44
63
|
*/
|
|
45
64
|
export type XmlWidgetDef = {
|
|
65
|
+
/** Block widget. */
|
|
46
66
|
block?: boolean;
|
|
47
|
-
|
|
67
|
+
|
|
68
|
+
/** Native widget (rendered inline). */
|
|
48
69
|
factory?: XmlWidgetFactory;
|
|
49
|
-
|
|
70
|
+
|
|
71
|
+
/** React widget (rendered in portals outside of the editor). */
|
|
50
72
|
Component?: FC<XmlWidgetProps>;
|
|
51
73
|
};
|
|
52
74
|
|
|
53
75
|
export type XmlWidgetRegistry = Record<string, XmlWidgetDef>;
|
|
54
76
|
|
|
77
|
+
export const getXmlTextChild = (children: any[]): string | null => {
|
|
78
|
+
const child = children?.[0];
|
|
79
|
+
return typeof child === 'string' ? child : null;
|
|
80
|
+
};
|
|
81
|
+
|
|
55
82
|
/**
|
|
56
83
|
* Update context.
|
|
57
84
|
*/
|
|
58
85
|
export const xmlTagContextEffect = StateEffect.define<any>();
|
|
59
86
|
|
|
60
87
|
/**
|
|
61
|
-
*
|
|
88
|
+
* Reset all state.
|
|
62
89
|
*/
|
|
63
|
-
export const
|
|
90
|
+
export const xmlTagResetEffect = StateEffect.define();
|
|
64
91
|
|
|
65
92
|
/**
|
|
66
|
-
*
|
|
93
|
+
* Update widget.
|
|
67
94
|
*/
|
|
68
|
-
export const
|
|
95
|
+
export const xmlTagUpdateEffect = StateEffect.define<{ id: string; value: any }>();
|
|
69
96
|
|
|
70
97
|
type WidgetDecorationSet = {
|
|
71
98
|
from: number;
|
|
@@ -76,9 +103,9 @@ type XmlWidgetStateMap = Record<string, any>;
|
|
|
76
103
|
|
|
77
104
|
export type XmlWidgetState = {
|
|
78
105
|
id: string;
|
|
79
|
-
props: any;
|
|
80
106
|
root: HTMLElement;
|
|
81
|
-
|
|
107
|
+
props: any;
|
|
108
|
+
Component: ComponentType<XmlWidgetProps>;
|
|
82
109
|
};
|
|
83
110
|
|
|
84
111
|
export interface XmlWidgetNotifier {
|
|
@@ -86,65 +113,243 @@ export interface XmlWidgetNotifier {
|
|
|
86
113
|
unmounted(id: string): void;
|
|
87
114
|
}
|
|
88
115
|
|
|
116
|
+
/**
|
|
117
|
+
* Context state.
|
|
118
|
+
*/
|
|
119
|
+
const widgetContextStateField = StateField.define<any>({
|
|
120
|
+
create: () => undefined,
|
|
121
|
+
update: (value, tr) => {
|
|
122
|
+
for (const effect of tr.effects) {
|
|
123
|
+
if (effect.is(xmlTagContextEffect)) {
|
|
124
|
+
return effect.value;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
return value;
|
|
129
|
+
},
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Widget state management.
|
|
134
|
+
*/
|
|
135
|
+
const widgetStateMapStateField = StateField.define<XmlWidgetStateMap>({
|
|
136
|
+
create: () => ({}),
|
|
137
|
+
update: (map, tr) => {
|
|
138
|
+
for (const effect of tr.effects) {
|
|
139
|
+
if (effect.is(xmlTagResetEffect)) {
|
|
140
|
+
return {};
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
if (effect.is(xmlTagUpdateEffect)) {
|
|
144
|
+
// Update accumulated widget props by id.
|
|
145
|
+
const { id, value } = effect.value;
|
|
146
|
+
log('widget updated', { id, value });
|
|
147
|
+
const state = typeof value === 'function' ? value(map[id]) : value;
|
|
148
|
+
return { ...map, [id]: state };
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
return map;
|
|
153
|
+
},
|
|
154
|
+
});
|
|
155
|
+
|
|
89
156
|
export type XmlTagsOptions = {
|
|
157
|
+
/** Tag registry. */
|
|
90
158
|
registry?: XmlWidgetRegistry;
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
*/
|
|
159
|
+
|
|
160
|
+
/** Called when widgets are mounted or unmounted. */
|
|
94
161
|
setWidgets?: (widgets: XmlWidgetState[]) => void;
|
|
162
|
+
|
|
163
|
+
/** Tags to bookmark. */
|
|
164
|
+
bookmarks?: string[];
|
|
95
165
|
};
|
|
96
166
|
|
|
97
167
|
/**
|
|
98
|
-
*
|
|
168
|
+
* Implements custom XML tags via CodeMirror-native Widgets and portaled React components.
|
|
169
|
+
*
|
|
170
|
+
* Basic mechanism:
|
|
171
|
+
* - Decorations are created from XML tags that matched the provided Widget registry.
|
|
172
|
+
* - Native widgets are rendered inline.
|
|
173
|
+
* - React widgets are rendered in portals outside of the editor via the PlaceholderWidget.
|
|
174
|
+
* - Widget state can be update via effects.
|
|
175
|
+
* - NOTE: Widget state may be updated BEFORE the widget is mounted.
|
|
99
176
|
*/
|
|
100
|
-
export const xmlTags = (
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
return value;
|
|
114
|
-
},
|
|
115
|
-
});
|
|
177
|
+
export const xmlTags = ({ registry, setWidgets, bookmarks }: XmlTagsOptions): Extension => {
|
|
178
|
+
const notifier = createWidgetMap(setWidgets);
|
|
179
|
+
const widgetDecorationsField = createWidgetDecorationsField(registry, notifier);
|
|
180
|
+
return [
|
|
181
|
+
widgetContextStateField,
|
|
182
|
+
widgetStateMapStateField,
|
|
183
|
+
widgetDecorationsField,
|
|
184
|
+
createWidgetUpdatePlugin(widgetDecorationsField, notifier),
|
|
185
|
+
createNavigationEffectPlugin(widgetDecorationsField, bookmarks),
|
|
186
|
+
bookmarks?.length ? Prec.highest(keyHandlers) : [],
|
|
187
|
+
];
|
|
188
|
+
};
|
|
116
189
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
190
|
+
/**
|
|
191
|
+
* Manages the collection of widgets.
|
|
192
|
+
*/
|
|
193
|
+
const createWidgetMap = (setWidgets?: (widgets: XmlWidgetState[]) => void): XmlWidgetNotifier => {
|
|
120
194
|
const widgets = new Map<string, XmlWidgetState>();
|
|
195
|
+
|
|
196
|
+
// TODO(burdon): Batch updates?
|
|
121
197
|
const notifier = {
|
|
122
|
-
mounted: (
|
|
123
|
-
|
|
124
|
-
|
|
198
|
+
mounted: (state: XmlWidgetState) => {
|
|
199
|
+
log('widget mounted', { id: state.id, tag: state.props._tag });
|
|
200
|
+
widgets.set(state.id, state);
|
|
201
|
+
setWidgets?.([...widgets.values()]);
|
|
125
202
|
},
|
|
126
203
|
unmounted: (id: string) => {
|
|
204
|
+
const state = widgets.get(id);
|
|
205
|
+
log('widget unmounted', { id, tag: state?.props._tag });
|
|
127
206
|
widgets.delete(id);
|
|
128
|
-
|
|
207
|
+
setWidgets?.([...widgets.values()]);
|
|
129
208
|
},
|
|
130
209
|
} satisfies XmlWidgetNotifier;
|
|
131
210
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
211
|
+
return notifier;
|
|
212
|
+
};
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Navigation keys.
|
|
216
|
+
*/
|
|
217
|
+
const keyHandlers = keymap.of([
|
|
218
|
+
{
|
|
219
|
+
key: 'Mod-ArrowUp',
|
|
220
|
+
run: (view) => {
|
|
221
|
+
view.dispatch({ effects: navigatePreviousEffect.of() });
|
|
222
|
+
return true;
|
|
223
|
+
},
|
|
224
|
+
},
|
|
225
|
+
{
|
|
226
|
+
key: 'Mod-ArrowDown',
|
|
227
|
+
run: (view) => {
|
|
228
|
+
view.dispatch({ effects: navigateNextEffect.of() });
|
|
229
|
+
return true;
|
|
230
|
+
},
|
|
231
|
+
},
|
|
232
|
+
]);
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* Effect processing plugin for navigation.
|
|
236
|
+
* Handles navigation up/down effects.
|
|
237
|
+
*/
|
|
238
|
+
const createNavigationEffectPlugin = (
|
|
239
|
+
widgetDecorationsField: StateField<WidgetDecorationSet>,
|
|
240
|
+
bookmarks?: string[],
|
|
241
|
+
) => {
|
|
242
|
+
return EditorView.updateListener.of((update) => {
|
|
243
|
+
update.transactions.forEach((transaction) => {
|
|
244
|
+
for (const effect of transaction.effects) {
|
|
245
|
+
if (effect.is(navigatePreviousEffect)) {
|
|
246
|
+
const view = update.view;
|
|
247
|
+
const cursorPos = view.state.doc.lineAt(view.state.selection.main.head).from;
|
|
248
|
+
let widget: { from: number; to: number; tag: string } | null = null;
|
|
249
|
+
const { decorations } = view.state.field(widgetDecorationsField);
|
|
250
|
+
for (const range of decorationSetToArray(decorations)) {
|
|
251
|
+
if (range.from < cursorPos) {
|
|
252
|
+
const tag = range.value.spec.tag;
|
|
253
|
+
if (bookmarks?.includes(tag)) {
|
|
254
|
+
if (!widget || range.from > widget.from) {
|
|
255
|
+
widget = { from: range.from, to: range.to, tag };
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
const line = view.state.doc.lineAt(widget?.from ?? 0);
|
|
262
|
+
view.dispatch({
|
|
263
|
+
selection: { anchor: line.from, head: line.from },
|
|
264
|
+
effects: scrollToLineEffect.of({ line: line.number, options: { offset: -16 } }),
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
continue;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
if (effect.is(navigateNextEffect)) {
|
|
271
|
+
const view = update.view;
|
|
272
|
+
const cursorPos = view.state.doc.lineAt(view.state.selection.main.head).to;
|
|
273
|
+
let widget: { from: number; to: number; tag: string } | null = null;
|
|
274
|
+
const { decorations } = view.state.field(widgetDecorationsField);
|
|
275
|
+
for (const range of decorationSetToArray(decorations)) {
|
|
276
|
+
if (range.from > cursorPos) {
|
|
277
|
+
const tag = range.value.spec.tag;
|
|
278
|
+
if (bookmarks?.includes(tag)) {
|
|
279
|
+
if (!widget || range.from < widget.from) {
|
|
280
|
+
widget = { from: range.from, to: range.to, tag };
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
if (widget) {
|
|
287
|
+
const line = view.state.doc.lineAt(widget?.from);
|
|
288
|
+
view.dispatch({
|
|
289
|
+
selection: { anchor: line.to, head: line.to },
|
|
290
|
+
effects: scrollToLineEffect.of({ line: line.number, options: { offset: -16 } }),
|
|
291
|
+
});
|
|
292
|
+
} else {
|
|
293
|
+
const line = view.state.doc.lineAt(view.state.doc.length);
|
|
294
|
+
view.dispatch({
|
|
295
|
+
selection: { anchor: line.to, head: line.to },
|
|
296
|
+
effects: scrollToLineEffect.of({ line: line.number, options: { position: 'end' } }),
|
|
297
|
+
});
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
continue;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
});
|
|
304
|
+
});
|
|
305
|
+
};
|
|
306
|
+
|
|
307
|
+
/**
|
|
308
|
+
* Handles effect that updates widget state.
|
|
309
|
+
*/
|
|
310
|
+
const createWidgetUpdatePlugin = (
|
|
311
|
+
widgetDecorationsField: StateField<WidgetDecorationSet>,
|
|
312
|
+
notifier: XmlWidgetNotifier,
|
|
313
|
+
) =>
|
|
314
|
+
ViewPlugin.fromClass(
|
|
315
|
+
class {
|
|
316
|
+
update(update: ViewUpdate) {
|
|
317
|
+
const widgetStateMap = update.state.field(widgetStateMapStateField);
|
|
318
|
+
const { decorations } = update.state.field(widgetDecorationsField);
|
|
319
|
+
|
|
320
|
+
// Check for widget update effects and re-render widgets.
|
|
321
|
+
for (const effect of update.transactions.flatMap((tr) => tr.effects)) {
|
|
322
|
+
if (effect.is(xmlTagUpdateEffect)) {
|
|
323
|
+
const widgetState = widgetStateMap[effect.value.id];
|
|
324
|
+
|
|
325
|
+
// Find and render widget.
|
|
326
|
+
for (const range of decorationSetToArray(decorations)) {
|
|
327
|
+
const deco = range.value;
|
|
328
|
+
const widget = deco?.spec?.widget;
|
|
329
|
+
|
|
330
|
+
// NOTE: If the widget has not yet been mounted, then the root will be null.
|
|
331
|
+
if (widget && widget instanceof PlaceholderWidget && widget.id === effect.value.id && widget.root) {
|
|
332
|
+
const props = { ...widget.props, ...widgetState };
|
|
333
|
+
notifier.mounted({ id: widget.id, props, root: widget.root, Component: widget.Component });
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
},
|
|
340
|
+
);
|
|
341
|
+
|
|
342
|
+
/**
|
|
343
|
+
* Builds and maintains decorations for XML widgets.
|
|
344
|
+
* Must be a StateField because block decorations cannot be provided via ViewPlugin.
|
|
345
|
+
*/
|
|
346
|
+
const createWidgetDecorationsField = (registry: XmlWidgetRegistry = {}, notifier: XmlWidgetNotifier) =>
|
|
347
|
+
StateField.define<WidgetDecorationSet>({
|
|
136
348
|
create: (state) => {
|
|
137
|
-
return buildDecorations(
|
|
138
|
-
state,
|
|
139
|
-
0,
|
|
140
|
-
state.doc.length,
|
|
141
|
-
state.field(contextState),
|
|
142
|
-
state.field(widgetState),
|
|
143
|
-
options,
|
|
144
|
-
notifier,
|
|
145
|
-
);
|
|
349
|
+
return buildDecorations(state, { from: 0, to: state.doc.length }, registry, notifier);
|
|
146
350
|
},
|
|
147
351
|
update: ({ from, decorations }, tr) => {
|
|
352
|
+
// Check for reset effect.
|
|
148
353
|
for (const effect of tr.effects) {
|
|
149
354
|
if (effect.is(xmlTagResetEffect)) {
|
|
150
355
|
return { from: 0, decorations: Decoration.none };
|
|
@@ -153,32 +358,22 @@ export const xmlTags = (options: XmlTagsOptions = {}): Extension => {
|
|
|
153
358
|
|
|
154
359
|
if (tr.docChanged) {
|
|
155
360
|
const { state } = tr;
|
|
156
|
-
|
|
157
361
|
// Flag if the transaction has modified the head of the document.
|
|
158
|
-
// (i.e., any changes that touch before the current `from` position).
|
|
159
362
|
const reset = tr.changes.touchesRange(0, from);
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
state,
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
state.
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
// Merge with existing decorations.
|
|
173
|
-
return {
|
|
174
|
-
from: result.from,
|
|
175
|
-
decorations: decorations.update({ add: decorationSetToArray(result.decorations) }),
|
|
176
|
-
};
|
|
363
|
+
if (reset) {
|
|
364
|
+
log('document reset', { from, to: state.doc.length });
|
|
365
|
+
// Full rebuild from start.
|
|
366
|
+
return buildDecorations(state, { from: 0, to: state.doc.length }, registry, notifier);
|
|
367
|
+
} else {
|
|
368
|
+
// Append-only: rebuild decorations from after the last widget and merge with existing decorations.
|
|
369
|
+
const result = buildDecorations(state, { from, to: state.doc.length }, registry, notifier);
|
|
370
|
+
return {
|
|
371
|
+
from: result.from,
|
|
372
|
+
decorations: decorations.update({ add: decorationSetToArray(result.decorations) }),
|
|
373
|
+
};
|
|
374
|
+
}
|
|
177
375
|
}
|
|
178
376
|
|
|
179
|
-
// No document changes: avoid mapping decorations through an empty ChangeSet,
|
|
180
|
-
// which can throw when the decoration set was created for a different base length.
|
|
181
|
-
// Simply return the existing decorations unchanged.
|
|
182
377
|
return { from, decorations };
|
|
183
378
|
},
|
|
184
379
|
provide: (field) => [
|
|
@@ -187,97 +382,66 @@ export const xmlTags = (options: XmlTagsOptions = {}): Extension => {
|
|
|
187
382
|
],
|
|
188
383
|
});
|
|
189
384
|
|
|
190
|
-
//
|
|
191
|
-
// Widget state management.
|
|
192
|
-
//
|
|
193
|
-
const widgetState = StateField.define<XmlWidgetStateMap>({
|
|
194
|
-
create: () => ({}),
|
|
195
|
-
update: (map, tr) => {
|
|
196
|
-
for (const effect of tr.effects) {
|
|
197
|
-
if (effect.is(xmlTagResetEffect)) {
|
|
198
|
-
return {};
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
if (effect.is(xmlTagUpdateEffect)) {
|
|
202
|
-
// Update accumulated widget props by id.
|
|
203
|
-
const { id, value } = effect.value;
|
|
204
|
-
const state = typeof value === 'function' ? value(map[id]) : value;
|
|
205
|
-
|
|
206
|
-
// Find and render widget.
|
|
207
|
-
const { decorations } = tr.state.field(decorationsState);
|
|
208
|
-
for (const range of decorationSetToArray(decorations)) {
|
|
209
|
-
const deco = range.value;
|
|
210
|
-
const widget = deco?.spec?.widget;
|
|
211
|
-
if (widget && widget instanceof PlaceholderWidget && widget.id === effect.value.id && widget.root) {
|
|
212
|
-
const props = { ...widget.props, ...state };
|
|
213
|
-
notifier.mounted({ id: widget.id, props, root: widget.root, Component: widget.Component });
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
return { ...map, [id]: state };
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
return map;
|
|
222
|
-
},
|
|
223
|
-
});
|
|
224
|
-
|
|
225
|
-
return [contextState, decorationsState, widgetState];
|
|
226
|
-
};
|
|
227
|
-
|
|
228
385
|
/**
|
|
229
386
|
* Creates widget decorations for XML tags in the document using the syntax tree.
|
|
230
387
|
*/
|
|
231
388
|
const buildDecorations = (
|
|
232
389
|
state: EditorState,
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
context: any,
|
|
236
|
-
widgetState: XmlWidgetStateMap,
|
|
237
|
-
options: XmlTagsOptions,
|
|
390
|
+
range: Range,
|
|
391
|
+
registry: XmlWidgetRegistry,
|
|
238
392
|
notifier: XmlWidgetNotifier,
|
|
239
393
|
): WidgetDecorationSet => {
|
|
394
|
+
const context = state.field(widgetContextStateField, false);
|
|
395
|
+
const widgetStateMap = state.field(widgetStateMapStateField, false) ?? {};
|
|
396
|
+
|
|
240
397
|
const builder = new RangeSetBuilder<Decoration>();
|
|
241
398
|
const tree = syntaxTree(state);
|
|
242
399
|
if (!tree || (tree.type.name === 'Program' && tree.length === 0)) {
|
|
243
|
-
return { from, decorations: Decoration.none };
|
|
400
|
+
return { from: range.from, decorations: Decoration.none };
|
|
244
401
|
}
|
|
245
402
|
|
|
403
|
+
let last = range.from;
|
|
246
404
|
tree.iterate({
|
|
247
|
-
from,
|
|
248
|
-
to,
|
|
405
|
+
from: range.from,
|
|
406
|
+
to: range.to,
|
|
249
407
|
enter: (node) => {
|
|
250
408
|
switch (node.type.name) {
|
|
251
409
|
// XML Element.
|
|
252
410
|
case 'Element': {
|
|
253
411
|
try {
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
412
|
+
const args = nodeToJson(state, node.node);
|
|
413
|
+
if (args) {
|
|
414
|
+
const def = registry[args._tag];
|
|
415
|
+
if (def) {
|
|
416
|
+
// NOTE: The widget state may already have been updated before the widget is mounted.
|
|
417
|
+
const { block, factory, Component } = def;
|
|
418
|
+
const widgetState = args.id ? widgetStateMap[args.id] : undefined;
|
|
419
|
+
const nodeRange = { from: node.node.from, to: node.node.to };
|
|
420
|
+
const props = { context, range: nodeRange, ...args, ...widgetState } satisfies XmlWidgetProps;
|
|
421
|
+
|
|
422
|
+
// Create widget.
|
|
423
|
+
const widget: WidgetType | undefined = factory
|
|
424
|
+
? factory(props)
|
|
425
|
+
: Component
|
|
426
|
+
? args.id && new PlaceholderWidget(args.id, Component, props, notifier)
|
|
427
|
+
: undefined;
|
|
428
|
+
|
|
429
|
+
// Add decoration.
|
|
430
|
+
if (widget) {
|
|
431
|
+
builder.add(
|
|
432
|
+
nodeRange.from,
|
|
433
|
+
nodeRange.to,
|
|
434
|
+
Decoration.replace({
|
|
435
|
+
widget,
|
|
436
|
+
block,
|
|
437
|
+
atomic: true,
|
|
438
|
+
inclusive: true,
|
|
439
|
+
tag: args._tag,
|
|
440
|
+
}),
|
|
441
|
+
);
|
|
442
|
+
|
|
443
|
+
// Track last widget (NOTE: range is inclusive).
|
|
444
|
+
last = nodeRange.to - 1;
|
|
281
445
|
}
|
|
282
446
|
}
|
|
283
447
|
}
|
|
@@ -285,19 +449,20 @@ const buildDecorations = (
|
|
|
285
449
|
log.catch(err);
|
|
286
450
|
}
|
|
287
451
|
|
|
288
|
-
|
|
452
|
+
// Don't descend into children.
|
|
453
|
+
return false;
|
|
289
454
|
}
|
|
290
455
|
}
|
|
291
456
|
},
|
|
292
457
|
});
|
|
293
458
|
|
|
294
|
-
return { from, decorations: builder.finish() };
|
|
459
|
+
return { from: last, decorations: builder.finish() };
|
|
295
460
|
};
|
|
296
461
|
|
|
297
462
|
/**
|
|
298
463
|
* Placeholder for React widgets.
|
|
299
464
|
*/
|
|
300
|
-
class PlaceholderWidget<TProps
|
|
465
|
+
class PlaceholderWidget<TProps extends XmlWidgetProps> extends WidgetType {
|
|
301
466
|
private _root: HTMLElement | null = null;
|
|
302
467
|
|
|
303
468
|
constructor(
|
|
@@ -310,25 +475,25 @@ class PlaceholderWidget<TProps = {}> extends WidgetType {
|
|
|
310
475
|
invariant(id);
|
|
311
476
|
}
|
|
312
477
|
|
|
313
|
-
get root() {
|
|
478
|
+
get root(): HTMLElement | null {
|
|
314
479
|
return this._root;
|
|
315
480
|
}
|
|
316
481
|
|
|
317
|
-
override eq(other:
|
|
318
|
-
return
|
|
482
|
+
override eq(other: this) {
|
|
483
|
+
return this.id === other.id;
|
|
319
484
|
}
|
|
320
485
|
|
|
321
486
|
override ignoreEvent() {
|
|
322
487
|
return true;
|
|
323
488
|
}
|
|
324
489
|
|
|
325
|
-
override toDOM(_view: EditorView)
|
|
490
|
+
override toDOM(_view: EditorView) {
|
|
326
491
|
this._root = document.createElement('span');
|
|
327
|
-
this.notifier.mounted({ id: this.id,
|
|
492
|
+
this.notifier.mounted({ id: this.id, root: this._root, props: this.props, Component: this.Component });
|
|
328
493
|
return this._root;
|
|
329
494
|
}
|
|
330
495
|
|
|
331
|
-
override destroy(_dom: HTMLElement)
|
|
496
|
+
override destroy(_dom: HTMLElement) {
|
|
332
497
|
this.notifier.unmounted(this.id);
|
|
333
498
|
this._root = null;
|
|
334
499
|
}
|
|
@@ -35,7 +35,7 @@ export const typewriter = ({ delay = 75, items = defaultItems }: DemoOptions = {
|
|
|
35
35
|
{
|
|
36
36
|
// Next prompt.
|
|
37
37
|
// TODO(burdon): Press 1-9 to select prompt?
|
|
38
|
-
key: "
|
|
38
|
+
key: "Shift-Meta-'",
|
|
39
39
|
run: (view) => {
|
|
40
40
|
clearTimeout(t);
|
|
41
41
|
// TODO(burdon): Add space if needed.
|