edytor 1.0.0-rc.3 → 2.0.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/README.md +21 -39
- package/dist/block/block.svelte.d.ts +11 -84
- package/dist/block/block.svelte.js +30 -134
- package/dist/block/colors.d.ts +0 -9
- package/dist/block/colors.js +1 -18
- package/dist/block/contentRange.d.ts +5 -1
- package/dist/block/contentRange.js +15 -16
- package/dist/block/inlineBlock.svelte.d.ts +11 -9
- package/dist/block/inlineBlock.svelte.js +18 -21
- package/dist/clipboard/createClipboardFragment.js +22 -64
- package/dist/clipboard/fragmentData.js +17 -42
- package/dist/clipboard/htmlFlow.js +7 -7
- package/dist/clipboard/insertClipboardFragment.js +5 -4
- package/dist/clipboard/moveText.js +16 -8
- package/dist/clipboard/serializeClipboardFragment.d.ts +2 -0
- package/dist/clipboard/serializeClipboardFragment.js +32 -28
- package/dist/cloudflare/DocumentRoom.d.ts +4 -17
- package/dist/cloudflare/DocumentRoom.js +3 -5
- package/dist/cloudflare/move.d.ts +1 -18
- package/dist/cloudflare/move.js +2 -48
- package/dist/cloudflare/room/admission.d.ts +1 -60
- package/dist/cloudflare/room/admission.js +25 -29
- package/dist/cloudflare/room/comments.d.ts +1 -3
- package/dist/cloudflare/room/comments.js +6 -6
- package/dist/cloudflare/room/context.d.ts +25 -82
- package/dist/cloudflare/room/context.js +8 -8
- package/dist/cloudflare/room/forged.d.ts +1 -1
- package/dist/cloudflare/room/forged.js +2 -12
- package/dist/cloudflare/room/frames.d.ts +1 -1
- package/dist/cloudflare/room/frames.js +1 -1
- package/dist/cloudflare/room/history.d.ts +1 -25
- package/dist/cloudflare/room/history.js +39 -54
- package/dist/cloudflare/room/moves.d.ts +1 -13
- package/dist/cloudflare/room/moves.js +33 -57
- package/dist/cloudflare/room/presence.d.ts +1 -11
- package/dist/cloudflare/room/presence.js +4 -4
- package/dist/cloudflare/room/purge.d.ts +1 -2
- package/dist/cloudflare/room/purge.js +2 -2
- package/dist/cloudflare/room/replicas.d.ts +1 -7
- package/dist/cloudflare/room/replicas.js +2 -2
- package/dist/cloudflare/room/storage.d.ts +3 -32
- package/dist/cloudflare/room/storage.js +33 -108
- package/dist/cloudflare/room/updates.d.ts +4 -4
- package/dist/cloudflare/room/updates.js +17 -24
- package/dist/cloudflare/room/validation.d.ts +1 -5
- package/dist/cloudflare/room/validation.js +16 -37
- package/dist/collaboration/RemoteSelections.svelte +13 -17
- package/dist/collaboration/awarenessSelection.d.ts +22 -1
- package/dist/collaboration/awarenessSelection.js +42 -0
- package/dist/collaboration/comments/client.d.ts +2 -2
- package/dist/collaboration/comments/client.js +1 -1
- package/dist/collaboration/history/index.d.ts +5 -5
- package/dist/collaboration/history/index.js +5 -5
- package/dist/collaboration/history/panel.svelte.d.ts +91 -0
- package/dist/collaboration/history/panel.svelte.js +223 -0
- package/dist/collaboration/providers.d.ts +12 -3
- package/dist/collaboration/providers.js +5 -4
- package/dist/components/Block.svelte +42 -56
- package/dist/components/Block.svelte.d.ts +7 -5
- package/dist/components/Content.svelte +1 -5
- package/dist/components/Edytor.svelte +82 -99
- package/dist/components/Edytor.svelte.d.ts +16 -13
- package/dist/components/InlineBlock.svelte +1 -1
- package/dist/components/Ranges.svelte +96 -0
- package/dist/components/Ranges.svelte.d.ts +19 -0
- package/dist/components/Suggestion.svelte +3 -2
- package/dist/components/Text.svelte +2 -5
- package/dist/components/Text.svelte.d.ts +1 -1
- package/dist/crdt/admission.d.ts +2 -9
- package/dist/crdt/admission.js +3 -9
- package/dist/crdt/attribution/attribution.d.ts +11 -72
- package/dist/crdt/attribution/attribution.js +5 -52
- package/dist/crdt/attribution/block.d.ts +0 -78
- package/dist/crdt/attribution/block.js +1 -144
- package/dist/crdt/data.d.ts +18 -13
- package/dist/crdt/data.js +49 -71
- package/dist/crdt/doc/anchors.js +4 -4
- package/dist/crdt/doc/content.d.ts +5 -1
- package/dist/crdt/doc/content.js +3 -1
- package/dist/crdt/doc/delete.d.ts +1 -0
- package/dist/crdt/doc/funnel.d.ts +0 -23
- package/dist/crdt/doc/funnel.js +34 -85
- package/dist/crdt/doc/gate.d.ts +8 -9
- package/dist/crdt/doc/gate.js +7 -17
- package/dist/crdt/doc/history.d.ts +87 -14
- package/dist/crdt/doc/history.js +334 -149
- package/dist/crdt/doc/layout.d.ts +0 -1
- package/dist/crdt/doc/layout.js +2 -3
- package/dist/crdt/doc/meta.d.ts +4 -4
- package/dist/crdt/doc/meta.js +10 -21
- package/dist/crdt/doc/moves.d.ts +4 -4
- package/dist/crdt/doc/moves.js +5 -5
- package/dist/crdt/doc/plan.d.ts +2 -0
- package/dist/crdt/doc/plan.js +2 -0
- package/dist/crdt/doc/reads.d.ts +8 -5
- package/dist/crdt/doc/reads.js +49 -50
- package/dist/crdt/doc/seed.d.ts +15 -6
- package/dist/crdt/doc/seed.js +27 -26
- package/dist/crdt/doc/split-merge.d.ts +1 -3
- package/dist/crdt/doc/split-merge.js +4 -5
- package/dist/crdt/doc/steps.d.ts +3 -7
- package/dist/crdt/doc/steps.js +20 -9
- package/dist/crdt/doc/types.d.ts +0 -10
- package/dist/crdt/document.d.ts +32 -115
- package/dist/crdt/document.js +216 -302
- package/dist/crdt/edytor-doc.d.ts +689 -90
- package/dist/crdt/edytor-doc.js +74 -149
- package/dist/crdt/engine-api.d.ts +15 -47
- package/dist/crdt/engine.d.ts +7 -17
- package/dist/crdt/engine.js +9 -19
- package/dist/crdt/flow.d.ts +9 -37
- package/dist/crdt/flow.js +260 -238
- package/dist/crdt/index.d.ts +32 -85
- package/dist/crdt/index.js +21 -47
- package/dist/crdt/operations.d.ts +24 -33
- package/dist/crdt/operations.js +8 -17
- package/dist/crdt/placement/display.d.ts +0 -2
- package/dist/crdt/placement/display.js +0 -15
- package/dist/crdt/placement/model.d.ts +160 -12
- package/dist/crdt/placement/model.js +413 -414
- package/dist/crdt/placement/rank.d.ts +1 -5
- package/dist/crdt/placement/rank.js +28 -38
- package/dist/crdt/props.d.ts +32 -0
- package/dist/crdt/props.js +172 -0
- package/dist/crdt/protocol.d.ts +4 -5
- package/dist/crdt/protocol.js +3 -4
- package/dist/crdt/protocols/awareness.d.ts +3 -7
- package/dist/crdt/protocols/awareness.js +17 -33
- package/dist/crdt/protocols/envelope.d.ts +9 -29
- package/dist/crdt/protocols/envelope.js +8 -25
- package/dist/crdt/protocols/sync.d.ts +15 -30
- package/dist/crdt/protocols/sync.js +27 -89
- package/dist/crdt/providers/bound.d.ts +3 -1
- package/dist/crdt/providers/bound.js +3 -1
- package/dist/crdt/providers/container.d.ts +11 -17
- package/dist/crdt/providers/container.js +39 -27
- package/dist/crdt/providers/index.d.ts +34 -6
- package/dist/crdt/providers/index.js +106 -111
- package/dist/crdt/providers/indexeddb.d.ts +2 -12
- package/dist/crdt/providers/indexeddb.js +29 -90
- package/dist/crdt/providers/room.d.ts +58 -2
- package/dist/crdt/providers/room.js +38 -21
- package/dist/crdt/providers/websocket.d.ts +1 -1
- package/dist/crdt/providers/websocket.js +3 -4
- package/dist/crdt/purge.d.ts +2 -2
- package/dist/crdt/purge.js +69 -6
- package/dist/crdt/rangeDelete.d.ts +4 -42
- package/dist/crdt/rangeDelete.js +7 -6
- package/dist/crdt/restore.d.ts +21 -1
- package/dist/crdt/restore.js +54 -59
- package/dist/crdt/schema.d.ts +2 -2
- package/dist/crdt/schema.js +4 -5
- package/dist/crdt/semantics.d.ts +10 -15
- package/dist/crdt/semantics.js +22 -21
- package/dist/crdt/storage.d.ts +7 -13
- package/dist/crdt/storage.js +10 -24
- package/dist/crdt/structs.d.ts +42 -47
- package/dist/crdt/structs.js +76 -67
- package/dist/crdt/tables.d.ts +9 -0
- package/dist/crdt/tables.js +20 -0
- package/dist/crdt/text/delete-index.d.ts +0 -13
- package/dist/crdt/text/delete-index.js +7 -14
- package/dist/crdt/text/deletes.d.ts +9 -22
- package/dist/crdt/text/deletes.js +11 -74
- package/dist/crdt/text/index/cache.js +3 -3
- package/dist/crdt/text/index/fold.d.ts +1 -2
- package/dist/crdt/text/index/fold.js +15 -10
- package/dist/crdt/text/index/layout.d.ts +0 -10
- package/dist/crdt/text/index/layout.js +6 -20
- package/dist/crdt/text/index/records.js +2 -1
- package/dist/crdt/text/index/report.js +5 -6
- package/dist/crdt/text/index/shared.d.ts +11 -4
- package/dist/crdt/text/index/shared.js +8 -7
- package/dist/crdt/text/index/state.d.ts +3 -33
- package/dist/crdt/text/index/state.js +2 -4
- package/dist/crdt/text/model.d.ts +82 -2
- package/dist/crdt/text/model.js +344 -354
- package/dist/crdt/text/rows.d.ts +0 -2
- package/dist/crdt/text/rows.js +0 -11
- package/dist/crdt/text/runs.d.ts +6 -3
- package/dist/crdt/text/runs.js +132 -137
- package/dist/crdt/text/streams.d.ts +1 -1
- package/dist/crdt/text/streams.js +1 -1
- package/dist/crdt/vendor/yjs/API-NOTES.md +25 -8
- package/dist/crdt/vendor/yjs/UPSTREAM.md +288 -8
- package/dist/crdt/vendor/yjs/dts/global.d.ts +5 -26
- package/dist/crdt/vendor/yjs/dts/index.d.ts +10 -15
- package/dist/crdt/vendor/yjs/dts/structs/AbstractStruct.d.ts +2 -2
- package/dist/crdt/vendor/yjs/dts/structs/Item.d.ts +14 -219
- package/dist/crdt/vendor/yjs/dts/structs/Skip.d.ts +2 -2
- package/dist/crdt/vendor/yjs/dts/utils/BlockSet.d.ts +2 -2
- package/dist/crdt/vendor/yjs/dts/utils/Doc.d.ts +12 -123
- package/dist/crdt/vendor/yjs/dts/utils/ID.d.ts +1 -1
- package/dist/crdt/vendor/yjs/dts/utils/RangeCursor.d.ts +37 -58
- package/dist/crdt/vendor/yjs/dts/utils/Transaction.d.ts +3 -78
- package/dist/crdt/vendor/yjs/dts/utils/UpdateDecoder.d.ts +2 -81
- package/dist/crdt/vendor/yjs/dts/utils/UpdateEncoder.d.ts +2 -74
- package/dist/crdt/vendor/yjs/dts/utils/encoding-helpers.d.ts +4 -4
- package/dist/crdt/vendor/yjs/dts/utils/encoding.d.ts +6 -18
- package/dist/crdt/vendor/yjs/dts/utils/ids.d.ts +12 -237
- package/dist/crdt/vendor/yjs/dts/utils/positions.d.ts +5 -0
- package/dist/crdt/vendor/yjs/dts/utils/redo.d.ts +3 -0
- package/dist/crdt/vendor/yjs/dts/utils/transaction-helpers.d.ts +1 -3
- package/dist/crdt/vendor/yjs/dts/utils/updates.d.ts +6 -23
- package/dist/crdt/vendor/yjs/dts/ynode.d.ts +73 -498
- package/dist/crdt/vendor/yjs/global.d.ts +5 -26
- package/dist/crdt/vendor/yjs/src/index.js +11 -25
- package/dist/crdt/vendor/yjs/src/structs/AbstractStruct.js +1 -1
- package/dist/crdt/vendor/yjs/src/structs/GC.js +1 -1
- package/dist/crdt/vendor/yjs/src/structs/Item.js +10 -372
- package/dist/crdt/vendor/yjs/src/structs/Skip.js +1 -1
- package/dist/crdt/vendor/yjs/src/utils/BlockSet.js +2 -2
- package/dist/crdt/vendor/yjs/src/utils/Doc.js +14 -170
- package/dist/crdt/vendor/yjs/src/utils/ID.js +1 -1
- package/dist/crdt/vendor/yjs/src/utils/RangeCursor.js +61 -128
- package/dist/crdt/vendor/yjs/src/utils/StructStore.js +0 -22
- package/dist/crdt/vendor/yjs/src/utils/Transaction.js +17 -282
- package/dist/crdt/vendor/yjs/src/utils/UpdateDecoder.js +3 -130
- package/dist/crdt/vendor/yjs/src/utils/UpdateEncoder.js +2 -132
- package/dist/crdt/vendor/yjs/src/utils/encoding-helpers.js +4 -4
- package/dist/crdt/vendor/yjs/src/utils/encoding.js +49 -146
- package/dist/crdt/vendor/yjs/src/utils/ids.js +23 -900
- package/dist/crdt/vendor/yjs/src/utils/positions.js +115 -0
- package/dist/crdt/vendor/yjs/src/utils/redo.js +143 -0
- package/dist/crdt/vendor/yjs/src/utils/transaction-helpers.js +10 -127
- package/dist/crdt/vendor/yjs/src/utils/updates.js +7 -50
- package/dist/crdt/vendor/yjs/src/ynode.js +261 -2226
- package/dist/dnd/autoScroll.js +1 -2
- package/dist/{plugins/blockHandles → dnd}/dropIndicator.d.ts +2 -2
- package/dist/{plugins/blockHandles → dnd}/dropIndicator.js +52 -60
- package/dist/{plugins/blockHandles → dnd}/geometry.d.ts +4 -3
- package/dist/{plugins/blockHandles → dnd}/geometry.js +6 -6
- package/dist/dnd/placement.d.ts +200 -0
- package/dist/dnd/placement.js +426 -0
- package/dist/dnd/pragmatic.d.ts +4 -22
- package/dist/dnd/pragmatic.js +7 -26
- package/dist/dnd/track.d.ts +14 -0
- package/dist/dnd/track.js +55 -0
- package/dist/dnd/vendor/pragmatic/UPSTREAM.md +103 -0
- package/dist/dnd/vendor/pragmatic/bind-event-listener/LICENSE +21 -0
- package/dist/dnd/vendor/pragmatic/bind-event-listener/bind-all.js +46 -0
- package/dist/dnd/vendor/pragmatic/bind-event-listener/bind.js +7 -0
- package/dist/dnd/vendor/pragmatic/bind-event-listener/index.js +2 -0
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/LICENSE.md +11 -0
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/adapter/element-adapter-native-data-key.js +6 -0
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/adapter/element-adapter.d.ts +57 -0
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/adapter/element-adapter.js +306 -0
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/entry-point/element/adapter.d.ts +8 -0
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/entry-point/element/adapter.js +10 -0
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/entry-point/element/set-custom-native-drag-preview.d.ts +4 -0
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/entry-point/element/set-custom-native-drag-preview.js +6 -0
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/entry-point/types.d.ts +1 -0
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/honey-pot-fix/get-element-from-point-without-honey-pot.js +12 -0
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/honey-pot-fix/honey-pot-data-attribute.js +3 -0
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/honey-pot-fix/is-honey-pot-element.js +4 -0
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/honey-pot-fix/make-honey-pot-fix.js +333 -0
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/internal-types.d.ts +350 -0
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/ledger/dispatch-consumer-event.js +128 -0
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/ledger/lifecycle-manager.js +340 -0
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/ledger/usage-ledger.js +32 -0
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/make-adapter/make-adapter.js +59 -0
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/make-adapter/make-drop-target.js +288 -0
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/make-adapter/make-monitor.js +85 -0
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/public-utils/combine.js +6 -0
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/public-utils/element/custom-native-drag-preview/set-custom-native-drag-preview.d.ts +36 -0
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/public-utils/element/custom-native-drag-preview/set-custom-native-drag-preview.js +153 -0
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/public-utils/element/custom-native-drag-preview/types.d.ts +16 -0
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/public-utils/once.js +13 -0
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/util/add-attribute.js +7 -0
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/util/android.js +10 -0
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/util/changing-window/count-events-for-safari.js +104 -0
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/util/changing-window/is-from-another-window.js +16 -0
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/util/changing-window/is-leaving-window-in-safari.js +12 -0
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/util/changing-window/is-leaving-window.js +55 -0
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/util/detect-broken-drag.js +48 -0
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/util/get-input.js +14 -0
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/util/is-firefox.js +13 -0
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/util/is-safari.js +19 -0
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/util/max-z-index.js +3 -0
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/util/media-types/text-media-type.js +6 -0
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/util/media-types/url-media-type.js +6 -0
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/util/popover-reset-styles.js +40 -0
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/util/supports-popover.js +16 -0
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop-auto-scroll/LICENSE.md +11 -0
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop-auto-scroll/entry-point/element.d.ts +4 -0
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop-auto-scroll/entry-point/element.js +8 -0
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop-auto-scroll/internal-types.d.ts +50 -0
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop-auto-scroll/over-element/data-attributes.js +9 -0
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop-auto-scroll/over-element/get-scroll-by.js +117 -0
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop-auto-scroll/over-element/make-api.js +90 -0
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop-auto-scroll/over-element/try-scroll.js +183 -0
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop-auto-scroll/shared/axis.js +22 -0
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop-auto-scroll/shared/can-scroll-on-edge.js +17 -0
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop-auto-scroll/shared/configuration.js +49 -0
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop-auto-scroll/shared/edges.js +9 -0
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop-auto-scroll/shared/engagement-history.js +43 -0
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop-auto-scroll/shared/get-over-element-hitbox.js +50 -0
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop-auto-scroll/shared/get-percentage-in-range.js +19 -0
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop-auto-scroll/shared/get-scroll-change.js +106 -0
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop-auto-scroll/shared/is-axis-allowed.js +3 -0
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop-auto-scroll/shared/is-within.js +11 -0
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop-auto-scroll/shared/scheduler.js +104 -0
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop-auto-scroll/shared/side.js +6 -0
- package/dist/dnd/vendor/pragmatic/raf-schd/LICENSE +21 -0
- package/dist/dnd/vendor/pragmatic/raf-schd/raf-schd.esm.js +34 -0
- package/dist/edytor.svelte.d.ts +46 -63
- package/dist/edytor.svelte.js +126 -181
- package/dist/events/beforeInputCommands.d.ts +6 -11
- package/dist/events/beforeInputCommands.js +189 -181
- package/dist/events/beforeInputDeleteCommands.d.ts +20 -1
- package/dist/events/beforeInputDeleteCommands.js +153 -204
- package/dist/events/domTextOffset.d.ts +9 -9
- package/dist/events/domTextOffset.js +20 -48
- package/dist/events/events.utils.d.ts +0 -2
- package/dist/events/events.utils.js +0 -4
- package/dist/events/nativeInteractiveControl.d.ts +13 -13
- package/dist/events/nativeInteractiveControl.js +28 -56
- package/dist/events/onBeforeInput.d.ts +6 -1
- package/dist/events/onBeforeInput.js +207 -331
- package/dist/events/onCopy.js +1 -5
- package/dist/events/onDrop.d.ts +7 -1
- package/dist/events/onDrop.js +64 -78
- package/dist/events/onFocus.d.ts +9 -4
- package/dist/events/onFocus.js +45 -67
- package/dist/events/onInput.d.ts +8 -4
- package/dist/events/onInput.js +34 -147
- package/dist/events/onKeyDown.js +55 -122
- package/dist/events/onPaste.d.ts +14 -1
- package/dist/events/onPaste.js +51 -76
- package/dist/index.d.ts +11 -15
- package/dist/index.js +3 -3
- package/dist/kinds.d.ts +4 -6
- package/dist/kinds.js +28 -27
- package/dist/labels.d.ts +83 -320
- package/dist/labels.js +181 -408
- package/dist/plugins/Chrome.svelte +29 -0
- package/dist/plugins/Chrome.svelte.d.ts +32 -0
- package/dist/plugins/Control.svelte +23 -0
- package/dist/plugins/Control.svelte.d.ts +30 -0
- package/dist/plugins/anchored.svelte.d.ts +47 -0
- package/dist/plugins/anchored.svelte.js +73 -0
- package/dist/plugins/arrowMove/arrowMove.d.ts +2 -1
- package/dist/plugins/arrowMove/arrowMove.js +9 -5
- package/dist/plugins/bands.svelte.d.ts +57 -0
- package/dist/plugins/bands.svelte.js +95 -0
- package/dist/plugins/blockHandles/BlockHandle.svelte +14 -154
- package/dist/plugins/blockHandles/BlockHandle.svelte.d.ts +2 -2
- package/dist/plugins/blockHandles/BlockHandleController.svelte.d.ts +21 -196
- package/dist/plugins/blockHandles/BlockHandleController.svelte.js +158 -573
- package/dist/plugins/blockHandles/BlockHandles.svelte +15 -23
- package/dist/plugins/blockHandles/BlockHandles.svelte.d.ts +2 -2
- package/dist/plugins/blockHandles/blockHandlesPlugin.d.ts +25 -39
- package/dist/plugins/blockHandles/blockHandlesPlugin.js +130 -185
- package/dist/plugins/blockHandles/dragPreview.d.ts +8 -6
- package/dist/plugins/blockHandles/dragPreview.js +18 -16
- package/dist/plugins/blockMenu/BlockMenuController.svelte.d.ts +28 -38
- package/dist/plugins/blockMenu/BlockMenuController.svelte.js +116 -183
- package/dist/plugins/blockMenu/blockMenuPlugin.d.ts +1 -3
- package/dist/plugins/blockMenu/blockMenuPlugin.js +12 -29
- package/dist/plugins/brand.d.ts +8 -0
- package/dist/plugins/brand.js +8 -0
- package/dist/plugins/chrome.d.ts +45 -38
- package/dist/plugins/chrome.js +59 -36
- package/dist/plugins/code/CodeHeader.svelte +8 -38
- package/dist/plugins/code/CodePlugin.svelte +53 -56
- package/dist/plugins/code/CodePlugin.svelte.d.ts +0 -2
- package/dist/plugins/code/LanguageMenu.svelte +16 -125
- package/dist/plugins/code/LanguageMenu.svelte.d.ts +2 -1
- package/dist/plugins/code/code.css +5 -117
- package/dist/plugins/code/header.svelte.d.ts +2 -11
- package/dist/plugins/code/header.svelte.js +11 -38
- package/dist/plugins/code/languageMenu.svelte.d.ts +12 -32
- package/dist/plugins/code/languageMenu.svelte.js +30 -160
- package/dist/plugins/code/languages.d.ts +9 -22
- package/dist/plugins/code/languages.js +39 -128
- package/dist/plugins/columns/ColumnResize.svelte +16 -27
- package/dist/plugins/columns/ColumnResize.svelte.d.ts +1 -1
- package/dist/plugins/columns/ColumnsPlugin.svelte +46 -78
- package/dist/plugins/columns/ColumnsPlugin.svelte.d.ts +0 -12
- package/dist/plugins/columns/columns.css +7 -26
- package/dist/plugins/columns/gaps.d.ts +7 -5
- package/dist/plugins/columns/gaps.js +11 -6
- package/dist/plugins/columns/resize.svelte.d.ts +17 -54
- package/dist/plugins/columns/resize.svelte.js +80 -173
- package/dist/plugins/comments/CommentsController.svelte.d.ts +1 -4
- package/dist/plugins/comments/CommentsController.svelte.js +14 -25
- package/dist/plugins/comments/CommentsSidebar.svelte +82 -431
- package/dist/plugins/comments/CommentsSidebar.svelte.d.ts +4 -2
- package/dist/plugins/comments/commentsPlugin.d.ts +25 -9
- package/dist/plugins/comments/commentsPlugin.js +12 -10
- package/dist/plugins/equation/EquationEditor.svelte +16 -130
- package/dist/plugins/equation/EquationEditor.svelte.d.ts +1 -2
- package/dist/plugins/equation/EquationPlugin.svelte +109 -172
- package/dist/plugins/equation/EquationPlugin.svelte.d.ts +3 -2
- package/dist/plugins/equation/EquationView.svelte +20 -11
- package/dist/plugins/equation/equation.css +7 -0
- package/dist/plugins/equation/equation.svelte.d.ts +37 -24
- package/dist/plugins/equation/equation.svelte.js +20 -94
- package/dist/plugins/equation/katex.js +6 -9
- package/dist/plugins/fileDrop.d.ts +28 -0
- package/dist/plugins/fileDrop.js +116 -0
- package/dist/plugins/find/FindController.svelte.d.ts +8 -13
- package/dist/plugins/find/FindController.svelte.js +34 -55
- package/dist/plugins/find/findPlugin.d.ts +4 -8
- package/dist/plugins/find/findPlugin.js +29 -9
- package/dist/plugins/image/ImageChrome.svelte +6 -167
- package/dist/plugins/image/ImageChrome.svelte.d.ts +0 -2
- package/dist/plugins/image/ImagePlugin.svelte +71 -151
- package/dist/plugins/image/ImagePlugin.svelte.d.ts +12 -41
- package/dist/plugins/image/ImageToolbarHost.svelte +37 -0
- package/dist/plugins/image/ImageToolbarHost.svelte.d.ts +9 -0
- package/dist/plugins/image/controls.svelte.d.ts +6 -36
- package/dist/plugins/image/controls.svelte.js +43 -212
- package/dist/plugins/image/image.css +17 -0
- package/dist/plugins/image/image.d.ts +0 -5
- package/dist/plugins/image/image.js +0 -3
- package/dist/plugins/image/toolbar.svelte.d.ts +69 -0
- package/dist/plugins/image/toolbar.svelte.js +145 -0
- package/dist/plugins/index.d.ts +30 -26
- package/dist/plugins/index.js +28 -22
- package/dist/plugins/list.svelte.d.ts +128 -0
- package/dist/plugins/list.svelte.js +217 -0
- package/dist/plugins/markdownShortcuts.d.ts +1 -1
- package/dist/plugins/markdownShortcuts.js +10 -9
- package/dist/plugins/marquee/MarqueeBox.svelte +3 -20
- package/dist/plugins/marquee/MarqueeBox.svelte.d.ts +1 -1
- package/dist/plugins/marquee/MarqueeController.svelte.d.ts +0 -2
- package/dist/plugins/marquee/MarqueeController.svelte.js +20 -23
- package/dist/plugins/marquee/marquee.js +4 -21
- package/dist/plugins/marquee/marqueePlugin.d.ts +4 -3
- package/dist/plugins/marquee/marqueePlugin.js +16 -15
- package/dist/plugins/media/AudioPlugin.svelte +13 -88
- package/dist/plugins/media/AudioPlugin.svelte.d.ts +11 -4
- package/dist/plugins/media/BookmarkPlugin.svelte +113 -120
- package/dist/plugins/media/BookmarkPlugin.svelte.d.ts +10 -15
- package/dist/plugins/media/EmbedPlugin.svelte +82 -86
- package/dist/plugins/media/EmbedPlugin.svelte.d.ts +11 -17
- package/dist/plugins/media/EmptySlot.svelte +44 -0
- package/dist/plugins/media/EmptySlot.svelte.d.ts +25 -0
- package/dist/plugins/media/FilePlugin.svelte +45 -113
- package/dist/plugins/media/FilePlugin.svelte.d.ts +21 -4
- package/dist/plugins/media/MediaEmpty.svelte +51 -90
- package/dist/plugins/media/MediaEmpty.svelte.d.ts +26 -10
- package/dist/plugins/media/SourceBlock.svelte +200 -0
- package/dist/plugins/media/SourceBlock.svelte.d.ts +34 -0
- package/dist/plugins/media/UploadPreview.svelte +32 -0
- package/dist/plugins/media/UploadPreview.svelte.d.ts +11 -0
- package/dist/plugins/media/VideoPlugin.svelte +14 -97
- package/dist/plugins/media/VideoPlugin.svelte.d.ts +12 -5
- package/dist/plugins/media/empty.svelte.d.ts +47 -46
- package/dist/plugins/media/empty.svelte.js +67 -60
- package/dist/plugins/media/media.d.ts +97 -44
- package/dist/plugins/media/media.js +77 -99
- package/dist/plugins/media/upload.css +23 -0
- package/dist/plugins/media/urlPaste.svelte.d.ts +6 -37
- package/dist/plugins/media/urlPaste.svelte.js +32 -102
- package/dist/plugins/mention/MentionPlugin.svelte +84 -126
- package/dist/plugins/mention/MentionPlugin.svelte.d.ts +17 -27
- package/dist/plugins/mention/mention.css +6 -0
- package/dist/plugins/page/PageLink.svelte +54 -38
- package/dist/plugins/page/PagePlugin.svelte +20 -18
- package/dist/plugins/page/PagePlugin.svelte.d.ts +2 -4
- package/dist/plugins/page/page.d.ts +35 -9
- package/dist/plugins/page/page.js +3 -4
- package/dist/plugins/pageLink/PageLinkPlugin.svelte +154 -109
- package/dist/plugins/pageLink/PageLinkPlugin.svelte.d.ts +19 -26
- package/dist/plugins/pageLink/pageLink.css +6 -0
- package/dist/plugins/planned.d.ts +10 -0
- package/dist/plugins/planned.js +12 -0
- package/dist/plugins/richtext/CalloutIcon.svelte +13 -26
- package/dist/plugins/richtext/CalloutIconPicker.svelte +26 -0
- package/dist/plugins/richtext/CalloutIconPicker.svelte.d.ts +9 -0
- package/dist/plugins/richtext/EmptyBody.svelte +13 -20
- package/dist/plugins/richtext/RichTextControl.svelte +39 -0
- package/dist/plugins/richtext/RichTextControl.svelte.d.ts +8 -0
- package/dist/plugins/richtext/RichTextPlugin.svelte +174 -183
- package/dist/plugins/richtext/RichTextPlugin.svelte.d.ts +34 -34
- package/dist/plugins/richtext/TodoCheckbox.svelte +10 -21
- package/dist/plugins/richtext/TodoCheckbox.svelte.d.ts +0 -2
- package/dist/plugins/richtext/body.js +2 -2
- package/dist/plugins/richtext/calloutIcons.svelte.d.ts +50 -55
- package/dist/plugins/richtext/calloutIcons.svelte.js +86 -174
- package/dist/plugins/richtext/callouts.d.ts +15 -0
- package/dist/plugins/richtext/callouts.js +23 -0
- package/dist/plugins/richtext/controls.svelte.d.ts +110 -0
- package/dist/plugins/richtext/controls.svelte.js +126 -0
- package/dist/plugins/richtext/richTextOperations.js +37 -28
- package/dist/plugins/richtext/richtext.css +6 -0
- package/dist/plugins/slashMenu/SlashMenuController.svelte.d.ts +2 -14
- package/dist/plugins/slashMenu/SlashMenuController.svelte.js +34 -71
- package/dist/plugins/slashMenu/slashMenuPlugin.d.ts +9 -26
- package/dist/plugins/slashMenu/slashMenuPlugin.js +27 -68
- package/dist/plugins/suggestions/SuggestionBars.svelte +27 -84
- package/dist/plugins/suggestions/SuggestionBars.svelte.d.ts +9 -3
- package/dist/plugins/suggestions/suggestionsPlugin.d.ts +10 -18
- package/dist/plugins/suggestions/suggestionsPlugin.js +9 -24
- package/dist/plugins/table/TableChrome.svelte +40 -124
- package/dist/plugins/table/TablePlugin.svelte +106 -168
- package/dist/plugins/table/TablePlugin.svelte.d.ts +0 -4
- package/dist/plugins/table/chrome.svelte.d.ts +38 -141
- package/dist/plugins/table/chrome.svelte.js +340 -589
- package/dist/plugins/table/ops.d.ts +47 -0
- package/dist/plugins/table/ops.js +233 -0
- package/dist/plugins/table/table.css +16 -152
- package/dist/plugins/table/table.d.ts +15 -14
- package/dist/plugins/table/table.js +22 -16
- package/dist/plugins/toc/TableOfContents.svelte +32 -38
- package/dist/plugins/toc/TableOfContents.svelte.d.ts +1 -5
- package/dist/plugins/toc/TocPlugin.svelte +22 -22
- package/dist/plugins/toc/TocPlugin.svelte.d.ts +4 -6
- package/dist/plugins/toc/toc.d.ts +41 -10
- package/dist/plugins/toc/toc.js +2 -3
- package/dist/plugins/toolbar/ToolbarController.svelte.d.ts +4 -68
- package/dist/plugins/toolbar/ToolbarController.svelte.js +63 -89
- package/dist/plugins/toolbar/toolbarPlugin.d.ts +8 -18
- package/dist/plugins/toolbar/toolbarPlugin.js +28 -43
- package/dist/plugins/triggers/TriggerController.svelte.d.ts +4 -68
- package/dist/plugins/triggers/TriggerController.svelte.js +48 -129
- package/dist/plugins/triggers/place.d.ts +0 -9
- package/dist/plugins/triggers/place.js +1 -17
- package/dist/plugins/triggers/triggers.d.ts +31 -9
- package/dist/plugins/triggers/triggers.js +82 -62
- package/dist/plugins/uploads.svelte.d.ts +55 -24
- package/dist/plugins/uploads.svelte.js +123 -50
- package/dist/plugins.d.ts +187 -66
- package/dist/selection/domSelection.d.ts +13 -4
- package/dist/selection/domSelection.js +110 -183
- package/dist/selection/pointer.svelte.d.ts +8 -10
- package/dist/selection/pointer.svelte.js +32 -73
- package/dist/selection/replaceSelection.d.ts +21 -22
- package/dist/selection/replaceSelection.js +60 -69
- package/dist/selection/selection.svelte.d.ts +5 -73
- package/dist/selection/selection.svelte.js +224 -542
- package/dist/selection/selection.utils.d.ts +34 -11
- package/dist/selection/selection.utils.js +128 -247
- package/dist/selection/visibility.d.ts +3 -8
- package/dist/selection/visibility.js +7 -5
- package/dist/session/announcer.svelte.d.ts +2 -1
- package/dist/session/announcer.svelte.js +7 -3
- package/dist/session/attempt.d.ts +43 -39
- package/dist/session/attempt.js +62 -55
- package/dist/session/bindings.js +117 -145
- package/dist/session/commands.d.ts +47 -22
- package/dist/session/commands.js +208 -208
- package/dist/session/composition.svelte.d.ts +2 -4
- package/dist/session/composition.svelte.js +55 -65
- package/dist/session/editing/text.d.ts +6 -0
- package/dist/session/editing/text.js +17 -3
- package/dist/session/handles.d.ts +10 -1
- package/dist/session/handles.js +28 -0
- package/dist/session/history.d.ts +0 -4
- package/dist/session/history.js +16 -21
- package/dist/session/inputRules.d.ts +6 -3
- package/dist/session/inputRules.js +78 -83
- package/dist/session/keymap.d.ts +1 -6
- package/dist/session/keymap.js +17 -20
- package/dist/session/moves.d.ts +43 -10
- package/dist/session/moves.js +101 -59
- package/dist/session/navigation.d.ts +10 -2
- package/dist/session/navigation.js +140 -172
- package/dist/session/ports.d.ts +2 -7
- package/dist/session/props.d.ts +25 -25
- package/dist/session/props.js +62 -159
- package/dist/session/selection.d.ts +4 -3
- package/dist/session/selection.js +5 -0
- package/dist/session/suggestions.svelte.d.ts +1 -1
- package/dist/session/suggestions.svelte.js +42 -47
- package/dist/session/uploads.d.ts +29 -0
- package/dist/session/uploads.js +10 -0
- package/dist/session/virtual.d.ts +3 -3
- package/dist/session/virtual.js +18 -40
- package/dist/surface/attributes.d.ts +1 -0
- package/dist/surface/attributes.js +3 -26
- package/dist/surface/cells.d.ts +5 -0
- package/dist/surface/cells.js +5 -0
- package/dist/surface/lines.d.ts +2 -2
- package/dist/surface/lines.js +1 -1
- package/dist/surface/observer.svelte.d.ts +3 -20
- package/dist/surface/observer.svelte.js +52 -72
- package/dist/surface/overlay.d.ts +41 -3
- package/dist/surface/overlay.js +92 -37
- package/dist/surface/pin.svelte.d.ts +5 -0
- package/dist/surface/pin.svelte.js +5 -0
- package/dist/surface/projector.svelte.d.ts +4 -6
- package/dist/surface/projector.svelte.js +42 -69
- package/dist/text/text.svelte.d.ts +14 -40
- package/dist/text/text.svelte.js +35 -51
- package/dist/text/wordBoundary.d.ts +19 -0
- package/dist/text/wordBoundary.js +29 -44
- package/dist/themes/notion.css +272 -106
- package/dist/utils/json.d.ts +3 -1
- package/dist/utils/json.js +52 -51
- package/dist/utils/listen.d.ts +8 -0
- package/dist/utils/listen.js +19 -0
- package/package.json +4 -5
- package/dist/block/block.utils.d.ts +0 -340
- package/dist/block/block.utils.js +0 -356
- package/dist/collaboration/history/HistoryPanel.svelte +0 -554
- package/dist/collaboration/history/HistoryPanel.svelte.d.ts +0 -7
- package/dist/collaboration/history/panel.d.ts +0 -61
- package/dist/collaboration/history/panel.js +0 -3
- package/dist/components/SuggestionRanges.svelte +0 -58
- package/dist/components/SuggestionRanges.svelte.d.ts +0 -7
- package/dist/crdt/doc/table.d.ts +0 -21
- package/dist/crdt/doc/table.js +0 -288
- package/dist/crdt/migration/generation.d.ts +0 -58
- package/dist/crdt/migration/generation.js +0 -70
- package/dist/crdt/migration/legacy-schema.d.ts +0 -61
- package/dist/crdt/migration/legacy-schema.js +0 -151
- package/dist/crdt/migration/migrate.d.ts +0 -56
- package/dist/crdt/migration/migrate.js +0 -227
- package/dist/crdt/nodes.d.ts +0 -121
- package/dist/crdt/nodes.js +0 -56
- package/dist/crdt/text/index/checks.d.ts +0 -15
- package/dist/crdt/text/index/checks.js +0 -156
- package/dist/crdt/vendor/yjs/dts/utils/EventHandler.d.ts +0 -17
- package/dist/crdt/vendor/yjs/dts/utils/RelativePosition.d.ts +0 -80
- package/dist/crdt/vendor/yjs/dts/utils/UndoManager.d.ts +0 -205
- package/dist/crdt/vendor/yjs/dts/utils/YEvent.d.ts +0 -93
- package/dist/crdt/vendor/yjs/dts/utils/meta.d.ts +0 -25
- package/dist/crdt/vendor/yjs/dts/utils/renderer-helpers.d.ts +0 -98
- package/dist/crdt/vendor/yjs/dts/utils/schemas.d.ts +0 -2
- package/dist/crdt/vendor/yjs/src/utils/EventHandler.js +0 -75
- package/dist/crdt/vendor/yjs/src/utils/RelativePosition.js +0 -301
- package/dist/crdt/vendor/yjs/src/utils/UndoManager.js +0 -554
- package/dist/crdt/vendor/yjs/src/utils/YEvent.js +0 -158
- package/dist/crdt/vendor/yjs/src/utils/meta.js +0 -74
- package/dist/crdt/vendor/yjs/src/utils/renderer-helpers.js +0 -186
- package/dist/crdt/vendor/yjs/src/utils/schemas.js +0 -3
- package/dist/edytor.utils.d.ts +0 -50
- package/dist/edytor.utils.js +0 -67
- package/dist/plugins/blockMenu/BlockMenu.svelte +0 -335
- package/dist/plugins/blockMenu/BlockMenu.svelte.d.ts +0 -9
- package/dist/plugins/find/FindBar.svelte +0 -170
- package/dist/plugins/find/FindBar.svelte.d.ts +0 -9
- package/dist/plugins/find/FindHighlights.svelte +0 -75
- package/dist/plugins/find/FindHighlights.svelte.d.ts +0 -9
- package/dist/plugins/icons.d.ts +0 -2
- package/dist/plugins/icons.js +0 -63
- package/dist/plugins/image/ImageEmpty.svelte +0 -93
- package/dist/plugins/image/ImageEmpty.svelte.d.ts +0 -15
- package/dist/plugins/image/empty.svelte.d.ts +0 -56
- package/dist/plugins/image/empty.svelte.js +0 -83
- package/dist/plugins/keepInView.d.ts +0 -4
- package/dist/plugins/keepInView.js +0 -6
- package/dist/plugins/media/UrlPasteMenu.svelte +0 -92
- package/dist/plugins/media/UrlPasteMenu.svelte.d.ts +0 -9
- package/dist/plugins/richtext/CalloutIconMenu.svelte +0 -98
- package/dist/plugins/richtext/CalloutIconMenu.svelte.d.ts +0 -9
- package/dist/plugins/richtext/labels.d.ts +0 -9
- package/dist/plugins/richtext/labels.js +0 -7
- package/dist/plugins/slashMenu/SlashMenu.svelte +0 -276
- package/dist/plugins/slashMenu/SlashMenu.svelte.d.ts +0 -11
- package/dist/plugins/table/dragPreview.d.ts +0 -29
- package/dist/plugins/table/dragPreview.js +0 -103
- package/dist/plugins/toolbar/LinkCard.svelte +0 -122
- package/dist/plugins/toolbar/LinkCard.svelte.d.ts +0 -9
- package/dist/plugins/toolbar/Toolbar.svelte +0 -349
- package/dist/plugins/toolbar/Toolbar.svelte.d.ts +0 -9
- package/dist/plugins/triggers/TriggerMenu.svelte +0 -135
- package/dist/plugins/triggers/TriggerMenu.svelte.d.ts +0 -7
- package/dist/text/deltas.d.ts +0 -22
- package/dist/text/deltas.js +0 -46
- package/dist/text/text.utils.d.ts +0 -45
- package/dist/text/text.utils.js +0 -199
- /package/dist/{plugins/columns → dnd}/stacking.d.ts +0 -0
- /package/dist/{plugins/columns → dnd}/stacking.js +0 -0
|
@@ -1,31 +1,16 @@
|
|
|
1
1
|
import { Text } from '../text/text.svelte.js';
|
|
2
|
-
import {
|
|
3
|
-
import { clearDomSelection,
|
|
4
|
-
import {
|
|
2
|
+
import { getElementFromNode, getInlineBlockOfNode, getInlineBlockInSelectedRange, getTextOfNode, getYIndex, getMarkEdgeSide, offsetIn, ordered, isTextBoundSelectionPoint, normalizeUtf16Boundary, SYNTHETIC_TEXT_OVERLAY_SELECTOR } from './selection.utils.js';
|
|
3
|
+
import { clearDomSelection, createDomRange, getActiveElement } from './domSelection.js';
|
|
4
|
+
import { getDomSelectionSnapshot } from './domSelection.js';
|
|
5
5
|
import { SvelteSet } from 'svelte/reactivity';
|
|
6
6
|
import { InlineBlock } from '../block/inlineBlock.svelte.js';
|
|
7
|
-
import {
|
|
8
|
-
import { atomSelection, blockSelection, noSelection, project,
|
|
7
|
+
import { isKindControl, isNativeInteractiveControl, isOwnPoint } from '../events/nativeInteractiveControl.js';
|
|
8
|
+
import { atomSelection, blockSelection, noSelection, project, sameEnds, sameValue, serialize, textSelection } from '../session/selection.js';
|
|
9
9
|
import { seam } from '../crdt/anchors.js';
|
|
10
10
|
import { landed } from '../session/navigation.js';
|
|
11
11
|
import * as visibility from './visibility.js';
|
|
12
12
|
import { SelectionPointer } from './pointer.svelte.js';
|
|
13
13
|
import { caretBeside, shownText } from './replaceSelection.js';
|
|
14
|
-
/** The compatibility state of no (or an unresolvable) selection. */
|
|
15
|
-
const EMPTY_STATE = Object.freeze({
|
|
16
|
-
yStart: 0,
|
|
17
|
-
yEnd: 0,
|
|
18
|
-
isCollapsed: true,
|
|
19
|
-
isReversed: false,
|
|
20
|
-
texts: [],
|
|
21
|
-
blocks: [],
|
|
22
|
-
startText: null,
|
|
23
|
-
endText: null,
|
|
24
|
-
startBlock: null,
|
|
25
|
-
endBlock: null,
|
|
26
|
-
isBlockSpanning: false,
|
|
27
|
-
isVoidEditableElement: false
|
|
28
|
-
});
|
|
29
14
|
/**
|
|
30
15
|
* Whether a DOM selection runs backward (focus before anchor in document
|
|
31
16
|
* order), comparing boundary points — a focus on an ancestor element of the
|
|
@@ -38,7 +23,7 @@ export const isBackward = (selection) => {
|
|
|
38
23
|
if (anchorNode === focusNode)
|
|
39
24
|
return selection.focusOffset < selection.anchorOffset;
|
|
40
25
|
try {
|
|
41
|
-
const range = (anchorNode
|
|
26
|
+
const range = createDomRange(anchorNode);
|
|
42
27
|
range.setStart(anchorNode, selection.anchorOffset);
|
|
43
28
|
return range.comparePoint(focusNode, selection.focusOffset) < 0;
|
|
44
29
|
}
|
|
@@ -46,66 +31,42 @@ export const isBackward = (selection) => {
|
|
|
46
31
|
return Boolean(anchorNode.compareDocumentPosition(focusNode) & Node.DOCUMENT_POSITION_PRECEDING);
|
|
47
32
|
}
|
|
48
33
|
};
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
}
|
|
57
|
-
});
|
|
58
|
-
if (syntheticOverlay || !(node instanceof Element)) {
|
|
59
|
-
return syntheticOverlay;
|
|
60
|
-
}
|
|
61
|
-
for (const boundaryNode of [node.childNodes[offset], node.childNodes[offset - 1]]) {
|
|
62
|
-
if (!(boundaryNode instanceof HTMLElement)) {
|
|
34
|
+
/** A text suggestion's preview at a DOM point: around it, or the child at either side of it. */
|
|
35
|
+
const overlayAt = (node, offset) => {
|
|
36
|
+
const own = getElementFromNode(node)?.closest(SYNTHETIC_TEXT_OVERLAY_SELECTOR);
|
|
37
|
+
if (own || !(node instanceof Element))
|
|
38
|
+
return own ?? null;
|
|
39
|
+
for (const child of [node.childNodes[offset], node.childNodes[offset - 1]]) {
|
|
40
|
+
if (!(child instanceof HTMLElement))
|
|
63
41
|
continue;
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
if (descendant) {
|
|
70
|
-
return descendant;
|
|
71
|
-
}
|
|
42
|
+
if (child.matches(SYNTHETIC_TEXT_OVERLAY_SELECTOR))
|
|
43
|
+
return child;
|
|
44
|
+
const inner = child.querySelector(SYNTHETIC_TEXT_OVERLAY_SELECTOR);
|
|
45
|
+
if (inner)
|
|
46
|
+
return inner;
|
|
72
47
|
}
|
|
73
48
|
return null;
|
|
74
49
|
};
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
}
|
|
79
|
-
if (yStart !== startText.length || yEnd !== 0) {
|
|
80
|
-
return null;
|
|
81
|
-
}
|
|
82
|
-
const content = startText.parent.content;
|
|
83
|
-
const startIndex = content.indexOf(startText);
|
|
84
|
-
const endIndex = content.indexOf(endText);
|
|
85
|
-
if (startIndex === -1 || endIndex === -1 || endIndex <= startIndex) {
|
|
50
|
+
/** The one inline atom between the end of `start` and the start of `end`, in one block. */
|
|
51
|
+
const atomBetween = (start, end, yStart, yEnd) => {
|
|
52
|
+
if (!end || start.parent !== end.parent || yStart !== start.length || yEnd !== 0)
|
|
86
53
|
return null;
|
|
87
|
-
|
|
88
|
-
const
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
: null;
|
|
54
|
+
const content = start.parent.content;
|
|
55
|
+
const [from, to] = [content.indexOf(start), content.indexOf(end)];
|
|
56
|
+
const part = from !== -1 && to === from + 2 ? content[from + 1] : null;
|
|
57
|
+
return part instanceof InlineBlock ? part : null;
|
|
92
58
|
};
|
|
93
59
|
/**
|
|
94
|
-
* Where a range
|
|
95
|
-
* last shown line (a list's items, a code block's lines)
|
|
96
|
-
* shows none (a divider) passes to its neighbours as a caret does, the
|
|
97
|
-
* line first
|
|
98
|
-
* to the line after it, so the range still holds it — when a line lies on
|
|
99
|
-
* that side: a divider with none beyond it (it starts or ends the
|
|
100
|
-
* document, or only dividers follow to that edge) is left out.
|
|
60
|
+
* Where a range ending in `block` starts (`first`) or ends (`last`): its
|
|
61
|
+
* first or last shown line (a list's items, a code block's lines); a block
|
|
62
|
+
* that shows none (a divider) passes to its neighbours as a caret does, the
|
|
63
|
+
* next line first.
|
|
101
64
|
*/
|
|
102
|
-
const rangeEdge = (block, edge
|
|
65
|
+
const rangeEdge = (block, edge) => {
|
|
103
66
|
const text = shownText(block, edge);
|
|
104
67
|
if (text)
|
|
105
68
|
return { text, offset: edge === 'first' ? 0 : text.length };
|
|
106
|
-
|
|
107
|
-
return (caretBeside(block, before ? 'blockBefore' : 'blockAfter') ??
|
|
108
|
-
caretBeside(block, before ? 'blockAfter' : 'blockBefore'));
|
|
69
|
+
return caretBeside(block, 'blockAfter') ?? caretBeside(block, 'blockBefore');
|
|
109
70
|
};
|
|
110
71
|
/** One block's membership of the selected and focused sets, as its own two signals. */
|
|
111
72
|
class Membership {
|
|
@@ -154,12 +115,9 @@ export class EdytorSelection {
|
|
|
154
115
|
* @internal
|
|
155
116
|
*/
|
|
156
117
|
expectHistoryRestore = false;
|
|
157
|
-
/** A primary press in the host on a text, until its release (reactive: the chrome reads `dragging`). */
|
|
158
118
|
/** @internal The selection under a pointer: a press, its drag and its release. */
|
|
159
119
|
pointer = new SelectionPointer(this);
|
|
160
|
-
|
|
161
|
-
shouldKeepModelSelectionForNextTextInsertion = false;
|
|
162
|
-
modelSelectionPreservationBlock = null;
|
|
120
|
+
#document = null;
|
|
163
121
|
/**
|
|
164
122
|
* The selection: a value — none, a text range of two anchors,
|
|
165
123
|
* one inline atom, or a set of block ids. Read-only: only `select()`
|
|
@@ -181,12 +139,12 @@ export class EdytorSelection {
|
|
|
181
139
|
scrollOnDisplay = false;
|
|
182
140
|
/** @internal The intent serial (gestures but `input`) when the last display was requested. */
|
|
183
141
|
requestSerial = 0;
|
|
184
|
-
/**
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
142
|
+
/**
|
|
143
|
+
* DOM fields (Surface) observed with the value they describe: the
|
|
144
|
+
* mark-edge side a display or a DOM derive observed it with, and whether
|
|
145
|
+
* a DOM derive read it from a node-bound native range.
|
|
146
|
+
*/
|
|
188
147
|
#surface = null;
|
|
189
|
-
#compat = new WeakMap();
|
|
190
148
|
constructor(edytor, edytorOnSelectionChange) {
|
|
191
149
|
this.edytorOnSelectionChange = edytorOnSelectionChange;
|
|
192
150
|
this.edytor = edytor;
|
|
@@ -197,74 +155,43 @@ export class EdytorSelection {
|
|
|
197
155
|
return project(this.value, this.edytor.facade);
|
|
198
156
|
}
|
|
199
157
|
/**
|
|
200
|
-
* The
|
|
201
|
-
*
|
|
202
|
-
*
|
|
158
|
+
* The text segment and the offset in it that a projection point shows
|
|
159
|
+
* (`block.textAtOffset`, the one offset → segment mapper).
|
|
160
|
+
* @internal
|
|
203
161
|
*/
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
if (value.kind === 'atom') {
|
|
228
|
-
const all = segmentsOf(this.edytor.facade, start.block);
|
|
229
|
-
const index = all.findIndex((part) => part.kind === 'inline' && part.id === value.atomId);
|
|
230
|
-
parts = all.slice(index - 1, index + 2);
|
|
231
|
-
}
|
|
232
|
-
const segments = parts.filter((part) => part.kind === 'text');
|
|
233
|
-
const [startSegment, endSegment] = [segments[0], segments.at(-1)];
|
|
234
|
-
const startText = this.#textOf(startBlock, startSegment);
|
|
235
|
-
const endText = this.#textOf(endBlock, endSegment);
|
|
236
|
-
if (!startText || !endText || !startSegment || !endSegment)
|
|
237
|
-
return EMPTY_STATE;
|
|
238
|
-
const texts = segments.flatMap((part) => {
|
|
239
|
-
const block = blockOf(part.block);
|
|
240
|
-
return (block && this.#textOf(block, part)) ?? [];
|
|
241
|
-
});
|
|
242
|
-
const blocks = value.kind === 'blocks'
|
|
243
|
-
? value.ids
|
|
244
|
-
.filter((id) => this.edytor.facade.isVisibleBlock(id))
|
|
245
|
-
.sort((a, b) => this.edytor.facade.compare(a, b))
|
|
246
|
-
.flatMap((id) => blockOf(id) ?? [])
|
|
247
|
-
: projection.blocks.flatMap((id) => blockOf(id) ?? []);
|
|
248
|
-
const node = this.edytor.node;
|
|
249
|
-
return Object.defineProperty({
|
|
250
|
-
yStart: start.offset - startSegment.start,
|
|
251
|
-
yEnd: end.offset - endSegment.start,
|
|
252
|
-
isCollapsed: projection.isCollapsed,
|
|
253
|
-
isReversed: projection.isReversed,
|
|
254
|
-
isBlockSpanning: projection.isBlockSpanning,
|
|
255
|
-
texts,
|
|
256
|
-
blocks,
|
|
257
|
-
edge,
|
|
258
|
-
startText,
|
|
259
|
-
endText,
|
|
260
|
-
startBlock,
|
|
261
|
-
endBlock
|
|
262
|
-
}, 'isVoidEditableElement', {
|
|
263
|
-
enumerable: true,
|
|
264
|
-
get: () => projection.voidRoot !== null &&
|
|
265
|
-
['INPUT', 'TEXTAREA'].includes(getActiveElement(node)?.tagName.toUpperCase() ?? '')
|
|
266
|
-
});
|
|
162
|
+
textAt = (point) => (point && this.edytor.idToBlock.get(point.block)?.textAtOffset(point.offset)) || null;
|
|
163
|
+
/**
|
|
164
|
+
* A projection's endpoints in text segments (`textAt`) and the texts it
|
|
165
|
+
* covers (an atom's: the texts on its two sides): what the text-handle
|
|
166
|
+
* operations take.
|
|
167
|
+
* @internal
|
|
168
|
+
*/
|
|
169
|
+
textRange = (projection = this.projection) => {
|
|
170
|
+
const start = this.textAt(projection.start);
|
|
171
|
+
const end = this.textAt(projection.end);
|
|
172
|
+
const handles = this.edytor.idToBlock;
|
|
173
|
+
const texts = projection.kind === 'atom'
|
|
174
|
+
? [start, end].flatMap((at) => (at ? [at.text] : []))
|
|
175
|
+
: projection.segments.flatMap((part) => part.kind === 'text' && handles.has(part.block)
|
|
176
|
+
? [handles.text(part.block, part.segOrd)]
|
|
177
|
+
: []);
|
|
178
|
+
return {
|
|
179
|
+
startText: start?.text ?? null,
|
|
180
|
+
yStart: start?.offset ?? 0,
|
|
181
|
+
endText: end?.text ?? null,
|
|
182
|
+
yEnd: end?.offset ?? 0,
|
|
183
|
+
texts
|
|
184
|
+
};
|
|
267
185
|
};
|
|
186
|
+
/** @internal The mark-edge side the DOM showed the current caret with (`marksForInsertion`). */
|
|
187
|
+
get edge() {
|
|
188
|
+
return this.#surface?.value === this.value ? this.#surface.edge : undefined;
|
|
189
|
+
}
|
|
190
|
+
/** @internal Focus is in a void block's own `input` or `textarea`. */
|
|
191
|
+
get voidField() {
|
|
192
|
+
const tag = getActiveElement(this.edytor.node)?.tagName.toUpperCase();
|
|
193
|
+
return this.projection.voidRoot !== null && (tag === 'INPUT' || tag === 'TEXTAREA');
|
|
194
|
+
}
|
|
268
195
|
/**
|
|
269
196
|
* Replace the selection with `next` (none, a text range of two anchors,
|
|
270
197
|
* one inline atom, or a set of block ids), keeping the selected and
|
|
@@ -291,37 +218,29 @@ export class EdytorSelection {
|
|
|
291
218
|
this.edytor.surface.update();
|
|
292
219
|
else if (cause !== 'dom')
|
|
293
220
|
this.display();
|
|
294
|
-
this.cause = cause;
|
|
295
221
|
if (surface)
|
|
296
222
|
this.#surface = { value, ...surface };
|
|
297
223
|
const projection = project(value, this.edytor.facade);
|
|
298
|
-
const
|
|
299
|
-
const
|
|
300
|
-
? value.
|
|
301
|
-
.filter((id) => this.edytor.facade.isVisibleBlock(id))
|
|
302
|
-
.flatMap((id) => blockOf(id) ?? [])
|
|
303
|
-
: [];
|
|
304
|
-
const atom = value.kind === 'atom'
|
|
305
|
-
? blockOf(value.blockId)?.content.find((part) => part instanceof InlineBlock && part.id === value.atomId)
|
|
224
|
+
const blocksOf = (ids) => ids.flatMap((id) => this.edytor.idToBlock.get(id) ?? []);
|
|
225
|
+
const atom = value.kind === 'atom' && projection.start
|
|
226
|
+
? this.edytor.idToBlock.atom(value.blockId, value.atomId)
|
|
306
227
|
: undefined;
|
|
307
|
-
|
|
308
|
-
|
|
228
|
+
this.#sync(this.#selected, value.kind === 'blocks' ? blocksOf(value.ids) : [], 'selected');
|
|
229
|
+
this.#sync(this.#focused, value.kind === 'text'
|
|
230
|
+
? blocksOf(projection.blocks)
|
|
309
231
|
: value.kind === 'atom'
|
|
310
|
-
? [
|
|
311
|
-
: [];
|
|
312
|
-
this.#sync(this.#selected, selected, 'selected');
|
|
313
|
-
this.#sync(this.#focused, focused, 'focused');
|
|
232
|
+
? blocksOf([value.blockId])
|
|
233
|
+
: [], 'focused');
|
|
314
234
|
if (atom !== this.inlineBlockDeletionTarget || (!atom && this.selectedInlineBlock.size)) {
|
|
315
235
|
this.selectedInlineBlock.clear();
|
|
316
236
|
if (atom)
|
|
317
237
|
this.selectedInlineBlock.add(atom);
|
|
318
238
|
this.inlineBlockDeletionTarget = atom ?? null;
|
|
319
239
|
}
|
|
320
|
-
const state = this.state;
|
|
321
240
|
this.edytor.history?.selected(value);
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
this.#
|
|
241
|
+
const start = this.textAt(projection.start);
|
|
242
|
+
if (start) {
|
|
243
|
+
this.#lastText = start.text;
|
|
325
244
|
}
|
|
326
245
|
if (!changed)
|
|
327
246
|
return;
|
|
@@ -355,7 +274,7 @@ export class EdytorSelection {
|
|
|
355
274
|
setCaret = (caret) => {
|
|
356
275
|
const at = caret && caret.block.textAtOffset(Math.max(0, caret.offset));
|
|
357
276
|
if (at)
|
|
358
|
-
this.
|
|
277
|
+
this.selectText(at.text, at.offset);
|
|
359
278
|
};
|
|
360
279
|
/** The marks the next insertion at the caret takes (values kept). */
|
|
361
280
|
get pending() {
|
|
@@ -410,9 +329,8 @@ export class EdytorSelection {
|
|
|
410
329
|
const prev = this.value;
|
|
411
330
|
if (prev.kind !== 'text' || !prev.pending || next.kind !== 'text' || 'pending' in next)
|
|
412
331
|
return next;
|
|
413
|
-
const
|
|
414
|
-
|
|
415
|
-
return at(a.start, b.start) && at(a.end, b.end)
|
|
332
|
+
const a = project(prev, this.edytor.facade);
|
|
333
|
+
return a.start && sameEnds(a, project(next, this.edytor.facade))
|
|
416
334
|
? textSelection(next.anchor, next.focus, prev.pending)
|
|
417
335
|
: next;
|
|
418
336
|
};
|
|
@@ -482,15 +400,40 @@ export class EdytorSelection {
|
|
|
482
400
|
return isReversed ? textSelection(end, start) : textSelection(start, end);
|
|
483
401
|
};
|
|
484
402
|
/**
|
|
485
|
-
*
|
|
486
|
-
*
|
|
487
|
-
*
|
|
403
|
+
* Select from `yStart` of `startText` to `yEnd` of `endText` (a caret by
|
|
404
|
+
* default; endpoints in document order, `isReversed` makes the end the
|
|
405
|
+
* anchor; offsets clamped to each text). The anchors are minted now from
|
|
406
|
+
* each text's block record, live or not — the atoms of a text that died
|
|
407
|
+
* to a merge live on in the block that claimed them, so resolution follows
|
|
408
|
+
* them — else the selection lands at the seam of the start's block. The
|
|
409
|
+
* projector displays it after the flush.
|
|
410
|
+
* @internal
|
|
488
411
|
*/
|
|
489
|
-
|
|
490
|
-
|
|
412
|
+
selectText = (startText, yStart, endText = startText ?? null, yEnd = yStart, isReversed = false) => {
|
|
413
|
+
if (!startText || !endText)
|
|
414
|
+
return;
|
|
415
|
+
const at = (text, offset) => Math.min(Math.max(offset, 0), text.length);
|
|
416
|
+
const value = this.textValue(startText, at(startText, yStart), endText, at(endText, yEnd), isReversed, undefined, (text, offset, side) => text.parent.isRoot
|
|
491
417
|
? null
|
|
492
|
-
: this.edytor.facade.anchorAt(text.blockId, text.segStart +
|
|
493
|
-
|
|
418
|
+
: this.edytor.facade.anchorAt(text.blockId, text.segStart + offset, side));
|
|
419
|
+
const target = project(value, this.edytor.facade).start
|
|
420
|
+
? value
|
|
421
|
+
: this.#seamValue(startText.parent?.id ?? null);
|
|
422
|
+
if (target)
|
|
423
|
+
this.select(target);
|
|
424
|
+
};
|
|
425
|
+
/**
|
|
426
|
+
* Select `block`'s lines (Mod+A, a triple click): from its first shown
|
|
427
|
+
* line's start to its last's end (a list's items, a code block's lines),
|
|
428
|
+
* the start bound left so text typed before it stays inside. A block that
|
|
429
|
+
* shows no line keeps the current value.
|
|
430
|
+
* @internal
|
|
431
|
+
*/
|
|
432
|
+
selectLines = (block) => {
|
|
433
|
+
const [first, last] = block ? [shownText(block, 'first'), shownText(block, 'last')] : [];
|
|
434
|
+
if (first && last)
|
|
435
|
+
this.select(this.textValue(first, 0, last, last.length, false, 'left'));
|
|
436
|
+
};
|
|
494
437
|
/** @internal Ask the projector to display the current value after the flush. */
|
|
495
438
|
display = () => {
|
|
496
439
|
this.scrollOnDisplay =
|
|
@@ -500,7 +443,7 @@ export class EdytorSelection {
|
|
|
500
443
|
};
|
|
501
444
|
/** @internal The mark-edge side a display showed the current value with. */
|
|
502
445
|
observed = (surface) => {
|
|
503
|
-
this.#surface = { value: this.value, ...surface };
|
|
446
|
+
this.#surface = { value: this.value, nodeBound: this.hasNativeNodeSelection(), ...surface };
|
|
504
447
|
};
|
|
505
448
|
/**
|
|
506
449
|
* A pointer drag is in progress (a press in the host, until its release):
|
|
@@ -511,137 +454,41 @@ export class EdytorSelection {
|
|
|
511
454
|
get dragging() {
|
|
512
455
|
return this.pointer.dragging;
|
|
513
456
|
}
|
|
514
|
-
getBlockByPath = (path) => {
|
|
515
|
-
if (!path?.length) {
|
|
516
|
-
return null;
|
|
517
|
-
}
|
|
518
|
-
let block = this.edytor.root;
|
|
519
|
-
for (const index of path) {
|
|
520
|
-
block = block?.children[index];
|
|
521
|
-
}
|
|
522
|
-
return block ?? null;
|
|
523
|
-
};
|
|
524
457
|
/** @internal */
|
|
525
458
|
destroy = () => {
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
this.selectionDocument = null;
|
|
529
|
-
}
|
|
459
|
+
this.#document?.removeEventListener('selectionchange', this.onSelectionChange);
|
|
460
|
+
this.#document = null;
|
|
530
461
|
};
|
|
531
462
|
/**
|
|
532
|
-
*
|
|
533
|
-
*
|
|
534
|
-
*
|
|
535
|
-
* (a stale target feeds `deleteSelectedInlineBlock` and makes
|
|
536
|
-
* `restoreSelectionAfterRepair` bail forever).
|
|
463
|
+
* Leave an atom selection: a caret at the atom's start (the end of the
|
|
464
|
+
* text before it), else none. `selectedInlineBlock` and
|
|
465
|
+
* `inlineBlockDeletionTarget` follow the value (`commit`).
|
|
537
466
|
*/
|
|
538
467
|
clearInlineBlockSelection = () => {
|
|
539
468
|
const value = this.value;
|
|
540
469
|
if (value.kind !== 'atom')
|
|
541
470
|
return;
|
|
542
|
-
|
|
543
|
-
const
|
|
544
|
-
|
|
545
|
-
?.content.find((part) => part instanceof InlineBlock && part.id === value.atomId);
|
|
546
|
-
const before = atom?.parent.content[atom.parent.content.indexOf(atom) - 1];
|
|
547
|
-
this.select(before instanceof Text ? this.textValue(before, before.length) : noSelection);
|
|
471
|
+
const { start } = this.projection;
|
|
472
|
+
const before = start && this.textAt(start);
|
|
473
|
+
this.select(before ? this.textValue(before.text, before.offset) : noSelection);
|
|
548
474
|
};
|
|
549
475
|
selectInlineBlock = (inlineBlock, from = 'before') => {
|
|
550
476
|
this.select(atomSelection(inlineBlock.parent.id, inlineBlock.id, from));
|
|
551
477
|
};
|
|
552
478
|
/** @internal */
|
|
553
|
-
clearModelSelectionPreservation = () => {
|
|
554
|
-
this.shouldKeepModelSelectionForNextTextInsertion = false;
|
|
555
|
-
this.modelSelectionPreservationBlock = null;
|
|
556
|
-
};
|
|
557
|
-
isStateBlockContentRange = (block) => Boolean(!this.state.isCollapsed &&
|
|
558
|
-
this.state.startBlock === block &&
|
|
559
|
-
this.state.endBlock === block &&
|
|
560
|
-
this.state.startText === block.firstText &&
|
|
561
|
-
this.state.endText === block.lastText &&
|
|
562
|
-
this.state.yStart === 0 &&
|
|
563
|
-
this.state.yEnd === block.lastText.length);
|
|
564
|
-
/** @internal */
|
|
565
|
-
consumeModelSelectionPreservationForTextInsertion = () => {
|
|
566
|
-
const preservedBlock = this.modelSelectionPreservationBlock;
|
|
567
|
-
const shouldKeepPreservedBlock = this.shouldKeepModelSelectionForNextTextInsertion &&
|
|
568
|
-
preservedBlock instanceof Block &&
|
|
569
|
-
this.getBlockByPath(preservedBlock.path) === preservedBlock;
|
|
570
|
-
const shouldKeepSelection = shouldKeepPreservedBlock ||
|
|
571
|
-
(this.shouldKeepModelSelectionForNextTextInsertion &&
|
|
572
|
-
this.state.startBlock instanceof Block &&
|
|
573
|
-
this.isStateBlockContentRange(this.state.startBlock));
|
|
574
|
-
if (shouldKeepPreservedBlock) {
|
|
575
|
-
this.setStateFromBlockContentRange(preservedBlock);
|
|
576
|
-
}
|
|
577
|
-
this.shouldKeepModelSelectionForNextTextInsertion = false;
|
|
578
|
-
this.modelSelectionPreservationBlock = null;
|
|
579
|
-
return shouldKeepSelection;
|
|
580
|
-
};
|
|
581
|
-
/** @internal */
|
|
582
479
|
getTextOfNode = getTextOfNode.bind(this);
|
|
583
|
-
/** @internal */
|
|
584
|
-
getTextsInSelection = getTextsInSelection.bind(this);
|
|
585
|
-
/** @internal */
|
|
586
|
-
getInlineBlockOfNode = getInlineBlockOfNode.bind(this);
|
|
587
|
-
/** @internal */
|
|
588
|
-
getInlineBlockInSelectedRange = getInlineBlockInSelectedRange.bind(this);
|
|
589
480
|
/** @internal The block whose element holds `node`, in this editor. */
|
|
590
481
|
getBlockOfNode = (node) => {
|
|
591
|
-
const element = getElementFromNode(node);
|
|
592
|
-
const
|
|
593
|
-
|
|
594
|
-
return null;
|
|
595
|
-
}
|
|
596
|
-
const id = blockElement.dataset.edytorId;
|
|
597
|
-
return id ? (this.edytor.idToBlock.get(id) ?? null) : null;
|
|
598
|
-
};
|
|
599
|
-
getNonNativeEditableIslandBlock = (node) => {
|
|
600
|
-
const element = getElementFromNode(node);
|
|
601
|
-
const island = element?.closest('[contenteditable="false"]');
|
|
602
|
-
if (!(island instanceof HTMLElement) || !this.edytor.node?.contains(island)) {
|
|
603
|
-
return null;
|
|
604
|
-
}
|
|
605
|
-
if (island.closest('input, textarea, select, button, a[href]')) {
|
|
606
|
-
return null;
|
|
607
|
-
}
|
|
608
|
-
return this.getBlockOfNode(island);
|
|
609
|
-
};
|
|
610
|
-
normalizeTextRangePoints = (startText, startOffset, endText, endOffset, isReversed) => {
|
|
611
|
-
const clampedStart = Math.min(Math.max(startOffset, 0), startText.length);
|
|
612
|
-
const clampedEnd = Math.min(Math.max(endOffset, 0), endText.length);
|
|
613
|
-
const order = startText === endText
|
|
614
|
-
? clampedStart - clampedEnd
|
|
615
|
-
: startText.parent === endText.parent
|
|
616
|
-
? startText.index - endText.index
|
|
617
|
-
: this.edytor.compareBlocks(startText.parent, endText.parent);
|
|
618
|
-
if (order <= 0) {
|
|
619
|
-
return {
|
|
620
|
-
startText,
|
|
621
|
-
startOffset: clampedStart,
|
|
622
|
-
endText,
|
|
623
|
-
endOffset: clampedEnd,
|
|
624
|
-
isReversed: order === 0 ? false : isReversed
|
|
625
|
-
};
|
|
626
|
-
}
|
|
627
|
-
return {
|
|
628
|
-
startText: endText,
|
|
629
|
-
startOffset: clampedEnd,
|
|
630
|
-
endText: startText,
|
|
631
|
-
endOffset: clampedStart,
|
|
632
|
-
// Text atoms never reorder inside one text. Undo can nevertheless
|
|
633
|
-
// resolve the two deleted-boundary anchors on opposite sides of
|
|
634
|
-
// their restored atoms. Sort those offsets without changing the
|
|
635
|
-
// selection direction stored independently in the snapshot.
|
|
636
|
-
isReversed: startText === endText ? isReversed : !isReversed
|
|
637
|
-
};
|
|
482
|
+
const element = getElementFromNode(node)?.closest('[data-edytor-block]');
|
|
483
|
+
const id = element && this.edytor.node?.contains(element) && element.dataset.edytorId;
|
|
484
|
+
return (id && this.edytor.idToBlock.get(id)) || null;
|
|
638
485
|
};
|
|
639
486
|
/** @internal */
|
|
640
487
|
init = () => {
|
|
641
|
-
if (typeof document
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
488
|
+
if (typeof document === 'undefined')
|
|
489
|
+
return;
|
|
490
|
+
this.#document = this.edytor.node?.ownerDocument ?? document;
|
|
491
|
+
this.#document.addEventListener('selectionchange', this.onSelectionChange);
|
|
645
492
|
};
|
|
646
493
|
/**
|
|
647
494
|
* The block selection value over which the DOM caret was put — a primary
|
|
@@ -684,73 +531,48 @@ export class EdytorSelection {
|
|
|
684
531
|
// A block selection ignores the DOM, but the one a drag across columns made while it lasts.
|
|
685
532
|
if (this.selectedBlocks.size > 0 && !(this.dragging && this.pointer.across))
|
|
686
533
|
return;
|
|
534
|
+
// A selection in a kind's own control (a form control, a nested
|
|
535
|
+
// editable island) or a focused one belongs to it, not the model —
|
|
536
|
+
// deriving it would map the caret into the control's host text and
|
|
537
|
+
// corrupt the next model-routed write. Both endpoints are checked: a
|
|
538
|
+
// range anchored in host text but focused inside an island must not
|
|
539
|
+
// resolve either.
|
|
687
540
|
const container = this.edytor.node;
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
!container?.contains(selection.anchorNode) ||
|
|
691
|
-
!container.contains(selection.focusNode)) {
|
|
692
|
-
return;
|
|
693
|
-
}
|
|
694
|
-
const activeElement = getActiveElement(this.edytor.node);
|
|
695
|
-
if (activeElement instanceof Element &&
|
|
696
|
-
this.edytor.node?.contains(activeElement) &&
|
|
697
|
-
isNativeFormControl(activeElement)) {
|
|
541
|
+
const read = this.#read(selection);
|
|
542
|
+
if (!selection || !read || isKindControl(container, getActiveElement(container)))
|
|
698
543
|
return;
|
|
699
|
-
}
|
|
700
|
-
// A selection inside a nested foreign editable belongs to the
|
|
701
|
-
// island, not the model — deriving it would map the caret into the
|
|
702
|
-
// island's host text and corrupt the next model-routed write. Both
|
|
703
|
-
// endpoints are checked: a range anchored in host text but focused
|
|
704
|
-
// inside an island must not resolve either.
|
|
705
|
-
if (isNestedForeignEditableTarget(this.edytor.node, selection.anchorNode) ||
|
|
706
|
-
isNestedForeignEditableTarget(this.edytor.node, selection.focusNode)) {
|
|
707
|
-
return;
|
|
708
|
-
}
|
|
709
|
-
const { anchorNode, focusNode, anchorOffset, focusOffset } = selection;
|
|
710
|
-
const isCollapsed = selection.isCollapsed;
|
|
544
|
+
const { anchorNode, focusNode, isCollapsed } = selection;
|
|
711
545
|
// A native vertical move that landed on no caret stop takes the key's line stop.
|
|
712
546
|
if (isCollapsed &&
|
|
713
547
|
!isTextBoundSelectionPoint(anchorNode) &&
|
|
714
|
-
!this.
|
|
548
|
+
!getInlineBlockOfNode(this.edytor, anchorNode) &&
|
|
715
549
|
landed(this.edytor))
|
|
716
550
|
return;
|
|
717
|
-
const
|
|
718
|
-
const
|
|
719
|
-
const
|
|
720
|
-
|
|
721
|
-
const start = isReversed ? focusOffset : anchorOffset;
|
|
722
|
-
const end = isReversed ? anchorOffset : focusOffset;
|
|
723
|
-
const selectedInlineBlock = this.getInlineBlockInSelectedRange(ranges[0]);
|
|
724
|
-
const selectionParts = selectedInlineBlock
|
|
725
|
-
? { startText: null, endText: null, inlineBlock: selectedInlineBlock }
|
|
726
|
-
: this.getTextsInSelection(startNode, endNode, start, end);
|
|
727
|
-
let { startText, endText, inlineBlock } = selectionParts;
|
|
551
|
+
const { isReversed, startNode, start, endNode, end } = read;
|
|
552
|
+
const atom = getInlineBlockInSelectedRange(this.edytor, selection.rangeCount ? selection.getRangeAt(0) : undefined);
|
|
553
|
+
const startText = atom ? null : this.getTextOfNode(startNode, start);
|
|
554
|
+
let endText = startText && this.getTextOfNode(endNode, end);
|
|
728
555
|
if (!startText) {
|
|
729
|
-
const
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
556
|
+
const inlineBlock = atom ?? getInlineBlockOfNode(this.edytor, startNode);
|
|
557
|
+
// A press in a non-native editable island (contenteditable=false, no control).
|
|
558
|
+
const island = getElementFromNode(startNode)?.closest('[contenteditable="false"]');
|
|
559
|
+
const islandBlock = island && !isNativeInteractiveControl(island) && this.getBlockOfNode(island);
|
|
560
|
+
if (islandBlock && islandBlock.firstText)
|
|
561
|
+
return this.selectText(islandBlock.firstText, 0);
|
|
733
562
|
// A point on a white space node: the model caret is displayed again.
|
|
734
|
-
if (this.
|
|
735
|
-
this.display();
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
}
|
|
743
|
-
else {
|
|
744
|
-
this.clearInlineBlockSelection();
|
|
745
|
-
}
|
|
746
|
-
return;
|
|
747
|
-
}
|
|
563
|
+
if (!inlineBlock && this.textAt(this.projection.start))
|
|
564
|
+
return this.display();
|
|
565
|
+
clearDomSelection(this.edytor.node);
|
|
566
|
+
if (inlineBlock)
|
|
567
|
+
this.selectInlineBlock(inlineBlock);
|
|
568
|
+
else
|
|
569
|
+
this.clearInlineBlockSelection();
|
|
570
|
+
return;
|
|
748
571
|
}
|
|
749
|
-
const
|
|
750
|
-
if (
|
|
751
|
-
const
|
|
752
|
-
|
|
753
|
-
return this.setAtTextOffset(targetText, targetText.length);
|
|
572
|
+
const overlay = isCollapsed ? overlayAt(startNode, start) : null;
|
|
573
|
+
if (overlay) {
|
|
574
|
+
const text = this.getBlockOfNode(overlay)?.lastText ?? startText;
|
|
575
|
+
return this.selectText(text, text.length);
|
|
754
576
|
}
|
|
755
577
|
const rawYStart = getYIndex(startText, startNode, start);
|
|
756
578
|
const rawYEnd = isCollapsed ? rawYStart : getYIndex(endText, endNode, end);
|
|
@@ -760,77 +582,62 @@ export class EdytorSelection {
|
|
|
760
582
|
: endText
|
|
761
583
|
? normalizeUtf16Boundary(endText.stringContent, rawYEnd, 'forward')
|
|
762
584
|
: rawYEnd;
|
|
763
|
-
|
|
585
|
+
// An empty native range reads as a caret; the DOM is normalized to one.
|
|
586
|
+
let restore = yStart !== rawYStart ||
|
|
587
|
+
yEnd !== rawYEnd ||
|
|
588
|
+
(!isCollapsed && startText === endText && yStart === yEnd);
|
|
764
589
|
if (!isCollapsed &&
|
|
765
590
|
endText &&
|
|
766
591
|
startText.parent !== endText.parent &&
|
|
767
592
|
endText === endText.parent.firstText &&
|
|
768
593
|
yEnd === 0) {
|
|
769
594
|
// The shown block before: a closed toggle's header, not its hidden body.
|
|
770
|
-
const
|
|
771
|
-
if (
|
|
772
|
-
endText =
|
|
773
|
-
yEnd =
|
|
774
|
-
|
|
595
|
+
const previous = visibility.shown(endText.parent, 'blockBefore')?.lastText ?? null;
|
|
596
|
+
if (previous?.node?.isConnected) {
|
|
597
|
+
endText = previous;
|
|
598
|
+
yEnd = previous.length;
|
|
599
|
+
restore = true;
|
|
775
600
|
}
|
|
776
601
|
}
|
|
777
|
-
if (
|
|
778
|
-
//
|
|
779
|
-
|
|
780
|
-
}
|
|
781
|
-
if (startText?.parent.isEmpty && yStart > startText.length) {
|
|
782
|
-
// In case the placeholder or suggestion is not absolutely positioned, we need to set the selection to the start of the text because caret may be placed after the placeholder which is deceptive
|
|
783
|
-
return this.setAtTextOffset(startText, startText.length);
|
|
602
|
+
if (startText.parent.isEmpty && yStart > startText.length) {
|
|
603
|
+
// A caret after a placeholder or suggestion that is not absolutely positioned: its text's end.
|
|
604
|
+
return this.selectText(startText, startText.length);
|
|
784
605
|
}
|
|
785
|
-
const
|
|
786
|
-
if (
|
|
606
|
+
const between = atomBetween(startText, endText, yStart, yEnd);
|
|
607
|
+
if (between) {
|
|
787
608
|
clearDomSelection(this.edytor.node);
|
|
788
|
-
this.selectInlineBlock(
|
|
609
|
+
this.selectInlineBlock(between, isReversed ? 'after' : 'before');
|
|
789
610
|
return;
|
|
790
611
|
}
|
|
791
|
-
this.
|
|
792
|
-
|
|
612
|
+
const value = this.textValue(startText, yStart, endText ?? startText, yEnd, isReversed);
|
|
613
|
+
// A node-bound native range (endpoints outside text elements: a block
|
|
614
|
+
// node selection, a stray boundary node) is the shape engines extend
|
|
615
|
+
// their own way. They normalize it into text points asynchronously,
|
|
616
|
+
// so a keydown may find the DOM no longer node-bound: the same value
|
|
617
|
+
// derived again keeps the fact, any other derive clears it.
|
|
618
|
+
const nodeBound = !isTextBoundSelectionPoint(anchorNode) ||
|
|
619
|
+
!isTextBoundSelectionPoint(focusNode) ||
|
|
620
|
+
(this.hasNativeNodeSelection() && sameValue(this.value, value));
|
|
621
|
+
this.commit(value, 'dom', {
|
|
622
|
+
edge: isCollapsed ? getMarkEdgeSide(startText, startNode, yStart) : undefined,
|
|
623
|
+
nodeBound
|
|
793
624
|
});
|
|
794
625
|
this.edytor.projector.observe();
|
|
795
|
-
if (
|
|
626
|
+
if (restore && options.restoreNormalizedDomRange !== false && endText) {
|
|
796
627
|
// Writing the DOM under a pointer drag would reset its anchor: after it.
|
|
797
628
|
if (this.dragging)
|
|
798
629
|
this.pointer.hold();
|
|
799
630
|
else
|
|
800
|
-
this.
|
|
801
|
-
}
|
|
802
|
-
// Remember when the derived selection came from a node-bound
|
|
803
|
-
// native range (endpoints outside text elements — e.g. a block
|
|
804
|
-
// node selection or a stray boundary node). Engines asynchronously
|
|
805
|
-
// normalize such DOM selections into text points, so by the time a
|
|
806
|
-
// keydown arrives the live DOM selection may no longer look
|
|
807
|
-
// node-bound — the signature pins the flag to the derived
|
|
808
|
-
// selection it describes and any differently-shaped derive clears
|
|
809
|
-
// it.
|
|
810
|
-
const derivedKey = `${startText.id}:${yStart}:${endText?.id}:${yEnd}:${isReversed ? 1 : 0}`;
|
|
811
|
-
if (!isTextBoundSelectionPoint(selection.anchorNode) ||
|
|
812
|
-
!isTextBoundSelectionPoint(selection.focusNode)) {
|
|
813
|
-
this.#nodeBoundSelectionKey = derivedKey;
|
|
814
|
-
}
|
|
815
|
-
else if (this.#nodeBoundSelectionKey !== derivedKey) {
|
|
816
|
-
this.#nodeBoundSelectionKey = null;
|
|
631
|
+
this.selectText(startText, yStart, endText, yEnd, isReversed);
|
|
817
632
|
}
|
|
818
633
|
};
|
|
819
|
-
#nodeBoundSelectionKey = null;
|
|
820
634
|
/**
|
|
821
635
|
* Whether the live model selection was derived from a node-bound
|
|
822
636
|
* native range — the shape whose Shift+Arrow extension is
|
|
823
637
|
* engine-defined and therefore intercepted by the hotkey layer.
|
|
824
638
|
* @internal
|
|
825
639
|
*/
|
|
826
|
-
hasNativeNodeSelection = () =>
|
|
827
|
-
const { startText, endText, yStart, yEnd, isReversed } = this.state;
|
|
828
|
-
if (!startText || !endText) {
|
|
829
|
-
return false;
|
|
830
|
-
}
|
|
831
|
-
return (this.#nodeBoundSelectionKey ===
|
|
832
|
-
`${startText.id}:${yStart}:${endText.id}:${yEnd}:${isReversed ? 1 : 0}`);
|
|
833
|
-
};
|
|
640
|
+
hasNativeNodeSelection = () => this.#surface?.value === this.value && this.#surface.nodeBound === true;
|
|
834
641
|
/**
|
|
835
642
|
* Anchor a text position into the BACKING text that owns the atom at
|
|
836
643
|
* that display position — the v14 replacement for
|
|
@@ -864,19 +671,11 @@ export class EdytorSelection {
|
|
|
864
671
|
* bound item — callers fall back to id/path restore).
|
|
865
672
|
*/
|
|
866
673
|
resolveTextAnchor = (anchor) => {
|
|
867
|
-
const
|
|
868
|
-
|
|
869
|
-
return null;
|
|
870
|
-
}
|
|
871
|
-
const resolved = facade.resolveAnchor(anchor);
|
|
872
|
-
if (!resolved) {
|
|
873
|
-
return null;
|
|
874
|
-
}
|
|
875
|
-
return this.edytor.idToBlock.get(resolved.blockId)?.textAtOffset(resolved.offset) ?? null;
|
|
674
|
+
const resolved = this.edytor.facade?.resolveAnchor(anchor);
|
|
675
|
+
return resolved ? this.textAt({ block: resolved.blockId, offset: resolved.offset }) : null;
|
|
876
676
|
};
|
|
877
|
-
/** The text
|
|
677
|
+
/** The text the selection's start last resolved to (its block is the seam origin once it dies). */
|
|
878
678
|
#lastText = null;
|
|
879
|
-
#lastBlock = null;
|
|
880
679
|
/**
|
|
881
680
|
* Displayable (a fact of the rendering layer): the block's own content is mounted
|
|
882
681
|
* and not hidden by view state — a collapsed toggle's body, a `hidden`
|
|
@@ -925,6 +724,8 @@ export class EdytorSelection {
|
|
|
925
724
|
}
|
|
926
725
|
const { value } = this;
|
|
927
726
|
const facade = this.edytor.facade;
|
|
727
|
+
const { start, isCollapsed } = this.projection;
|
|
728
|
+
const at = this.textAt(start);
|
|
928
729
|
let dead;
|
|
929
730
|
if (value.kind === 'blocks') {
|
|
930
731
|
const live = value.ids.filter((id) => facade.isVisibleBlock(id));
|
|
@@ -937,7 +738,7 @@ export class EdytorSelection {
|
|
|
937
738
|
dead = value.ids[0] ?? null;
|
|
938
739
|
}
|
|
939
740
|
else if (value.kind === 'atom') {
|
|
940
|
-
if (
|
|
741
|
+
if (at)
|
|
941
742
|
return;
|
|
942
743
|
const anchor = facade.isVisibleBlock(value.blockId)
|
|
943
744
|
? facade.anchorAt(value.blockId, 0, 'left')
|
|
@@ -956,9 +757,7 @@ export class EdytorSelection {
|
|
|
956
757
|
this.#land(shown);
|
|
957
758
|
return;
|
|
958
759
|
}
|
|
959
|
-
|
|
960
|
-
const { start, isCollapsed } = this.projection;
|
|
961
|
-
if (state.startText && start && isCollapsed && value.anchor !== value.focus) {
|
|
760
|
+
if (at && start && isCollapsed && value.anchor !== value.focus) {
|
|
962
761
|
// A range whose content died is a caret at the seam (`sel.seam.covered-atom`):
|
|
963
762
|
// its two anchors would re-open around text re-inserted there.
|
|
964
763
|
const caret = facade.anchorAt(start.block, start.offset, 'left');
|
|
@@ -967,15 +766,14 @@ export class EdytorSelection {
|
|
|
967
766
|
return;
|
|
968
767
|
}
|
|
969
768
|
}
|
|
970
|
-
if (
|
|
769
|
+
if (at) {
|
|
971
770
|
// The text it was displayed in died while its anchor moved on: display again.
|
|
972
771
|
if (this.#lastText !== null && !this.#lastText.isInDocument)
|
|
973
772
|
this.display();
|
|
974
|
-
this.#lastText =
|
|
975
|
-
this.#lastBlock = state.startBlock?.id ?? null;
|
|
773
|
+
this.#lastText = at.text;
|
|
976
774
|
return;
|
|
977
775
|
}
|
|
978
|
-
dead = this.#
|
|
776
|
+
dead = this.#lastText?.blockId ?? null;
|
|
979
777
|
}
|
|
980
778
|
else {
|
|
981
779
|
// An emptied document rests the caret in its virtual paragraph (`doc.empty.virtual`).
|
|
@@ -996,148 +794,32 @@ export class EdytorSelection {
|
|
|
996
794
|
};
|
|
997
795
|
/** Select a repaired caret (the projector displays it). */
|
|
998
796
|
#land = (target) => this.commit(target, 'repair');
|
|
999
|
-
/**
|
|
1000
|
-
* A text range from `first`'s first shown line to `last`'s last (the
|
|
1001
|
-
* triple-click shape; `rangeEdge`); the start binds left. None when no
|
|
1002
|
-
* line is shown.
|
|
1003
|
-
*/
|
|
1004
|
-
#contentRange = (first, last = first) => {
|
|
1005
|
-
const [from, to] = [rangeEdge(first, 'first', true), rangeEdge(last, 'last', true)];
|
|
1006
|
-
return from && to
|
|
1007
|
-
? this.textValue(from.text, from.offset, to.text, to.offset, false, 'left')
|
|
1008
|
-
: null;
|
|
1009
|
-
};
|
|
1010
|
-
/** Select `block`'s content range (the triple-click shape), when it shows a line. */
|
|
1011
|
-
/**
|
|
1012
|
-
* Select `block`'s content (a triple click) and keep that selection for
|
|
1013
|
-
* the next text insertion.
|
|
1014
|
-
* @internal
|
|
1015
|
-
*/
|
|
1016
|
-
preserveBlockRange = (block) => {
|
|
1017
|
-
this.setStateFromBlockContentRange(block);
|
|
1018
|
-
this.shouldKeepModelSelectionForNextTextInsertion = true;
|
|
1019
|
-
this.modelSelectionPreservationBlock = block;
|
|
1020
|
-
};
|
|
1021
|
-
setStateFromBlockContentRange = (block) => {
|
|
1022
|
-
const range = this.#contentRange(block);
|
|
1023
|
-
if (range)
|
|
1024
|
-
this.select(range);
|
|
1025
|
-
};
|
|
1026
|
-
/**
|
|
1027
|
-
* Select a set of whole blocks. With no block, leave block selection:
|
|
1028
|
-
* the value becomes the text range the set showed, from its first shown
|
|
1029
|
-
* line to its last (a list's items; a divider at an edge stays covered
|
|
1030
|
-
* unless no line lies beyond it, `rangeEdge`), and stays as it is
|
|
1031
|
-
* when no line is shown anywhere.
|
|
1032
|
-
*/
|
|
1033
|
-
selectBlocks = (...blocks) => {
|
|
1034
|
-
if (blocks.length) {
|
|
1035
|
-
this.select(blockSelection(blocks.map((block) => block.id)));
|
|
1036
|
-
return;
|
|
1037
|
-
}
|
|
1038
|
-
const { value } = this;
|
|
1039
|
-
if (value.kind !== 'blocks')
|
|
1040
|
-
return;
|
|
1041
|
-
const [first, last] = [this.state.blocks[0], this.state.blocks.at(-1)];
|
|
1042
|
-
const range = first && last ? this.#contentRange(first, last) : noSelection;
|
|
1043
|
-
if (range)
|
|
1044
|
-
this.select(range);
|
|
1045
|
-
};
|
|
1046
|
-
addBlockToSelection = (block) => {
|
|
1047
|
-
const ids = this.value.kind === 'blocks' ? this.value.ids : [];
|
|
1048
|
-
if (!ids.includes(block.id))
|
|
1049
|
-
this.select(blockSelection([...ids, block.id]));
|
|
1050
|
-
};
|
|
1051
|
-
removeBlockFromSelection = (block) => {
|
|
1052
|
-
const ids = this.value.kind === 'blocks' ? this.value.ids : [];
|
|
1053
|
-
if (ids.includes(block.id))
|
|
1054
|
-
this.select(blockSelection(ids.filter((id) => id !== block.id)));
|
|
1055
|
-
};
|
|
1056
|
-
/**
|
|
1057
|
-
* Select a caret at `offset` of `text`; the projector displays it after
|
|
1058
|
-
* the flush. The value is minted now: a text that dies before the
|
|
1059
|
-
* display is followed through its atoms, else the seam of its block.
|
|
1060
|
-
*/
|
|
1061
|
-
setAtTextOffset = (text, textOffset = this.state.yStart) => {
|
|
1062
|
-
if (!text || typeof textOffset !== 'number')
|
|
1063
|
-
return;
|
|
1064
|
-
this.#admit(this.#intent(text, Math.min(Math.max(textOffset, 0), text.length)), text);
|
|
1065
|
-
};
|
|
1066
|
-
/**
|
|
1067
|
-
* A write's model-side fallback: the value minted when the write was
|
|
1068
|
-
* requested (anchors are captured at call time, before any await, so
|
|
1069
|
-
* a target merged away meanwhile is followed through its atoms), or the
|
|
1070
|
-
* seam of `origin`'s block when nothing of it resolves any more.
|
|
1071
|
-
*/
|
|
1072
|
-
#admit = (intended, origin) => {
|
|
1073
|
-
this.clearModelSelectionPreservation();
|
|
1074
|
-
if (project(intended, this.edytor.facade).start) {
|
|
1075
|
-
this.select(intended);
|
|
1076
|
-
return;
|
|
1077
|
-
}
|
|
1078
|
-
const target = origin && this.#seamValue(origin.parent?.id ?? null);
|
|
1079
|
-
if (target)
|
|
1080
|
-
this.select(target);
|
|
1081
|
-
};
|
|
1082
|
-
/** Select the whole content from `startText` to `endText` (the code block's select-all). */
|
|
1083
|
-
setAtTextsRange = (startText, endText) => {
|
|
1084
|
-
this.setAtRange(startText, 0, endText, endText.length);
|
|
1085
|
-
};
|
|
1086
|
-
/** Select a text range; the projector displays it after the flush. */
|
|
1087
|
-
setAtRange = (startText, startOffset, endText, endOffset, options = {}) => {
|
|
1088
|
-
if (!startText ||
|
|
1089
|
-
!endText ||
|
|
1090
|
-
typeof startOffset !== 'number' ||
|
|
1091
|
-
typeof endOffset !== 'number') {
|
|
1092
|
-
return;
|
|
1093
|
-
}
|
|
1094
|
-
const state = this.state;
|
|
1095
|
-
const range = this.normalizeTextRangePoints(startText, startOffset, endText, endOffset, options.isReversed ??
|
|
1096
|
-
(!state.isCollapsed &&
|
|
1097
|
-
state.isReversed &&
|
|
1098
|
-
state.startText === startText &&
|
|
1099
|
-
state.endText === endText &&
|
|
1100
|
-
state.yStart === startOffset &&
|
|
1101
|
-
state.yEnd === endOffset));
|
|
1102
|
-
this.#admit(this.#intent(range.startText, range.startOffset, range.endText, range.endOffset, range.isReversed), range.startText);
|
|
1103
|
-
};
|
|
1104
|
-
/**
|
|
1105
|
-
* Select `block`'s content (the whole of it by default): from its first
|
|
1106
|
-
* shown line to its last (a list's items, a code block's lines), the
|
|
1107
|
-
* offsets in those lines. A block that shows no line (a divider) keeps the
|
|
1108
|
-
* current value. Displayed after the flush.
|
|
1109
|
-
*/
|
|
1110
|
-
setAtBlockRange = (block, startOffset = 0, endOffset) => {
|
|
1111
|
-
const [first, last] = block ? [shownText(block, 'first'), shownText(block, 'last')] : [];
|
|
1112
|
-
if (!first || !last)
|
|
1113
|
-
return;
|
|
1114
|
-
const end = endOffset || last.length;
|
|
1115
|
-
if (!startOffset && end === last.length)
|
|
1116
|
-
this.select(this.textValue(first, 0, last, last.length, false, 'left'));
|
|
1117
|
-
else
|
|
1118
|
-
this.setAtRange(first, startOffset, last, end);
|
|
1119
|
-
};
|
|
1120
797
|
/**
|
|
1121
798
|
* Anchors from a DOM selection, without selecting them: the projector mints
|
|
1122
799
|
* an unobserved native move before a transaction it did not issue.
|
|
1123
800
|
* @internal
|
|
1124
801
|
*/
|
|
1125
802
|
mint = (snapshot) => {
|
|
1126
|
-
const
|
|
1127
|
-
|
|
1128
|
-
if (!container || !anchorNode || !focusNode)
|
|
803
|
+
const read = this.#read(snapshot);
|
|
804
|
+
if (!read)
|
|
1129
805
|
return null;
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
const reversed = isBackward(snapshot);
|
|
1134
|
-
const [startNode, start, endNode, end] = reversed
|
|
1135
|
-
? [focusNode, snapshot.focusOffset, anchorNode, snapshot.anchorOffset]
|
|
1136
|
-
: [anchorNode, snapshot.anchorOffset, focusNode, snapshot.focusOffset];
|
|
1137
|
-
const { startText, endText } = this.getTextsInSelection(startNode, endNode, start, end);
|
|
806
|
+
const { isReversed, startNode, start, endNode, end } = read;
|
|
807
|
+
const startText = this.getTextOfNode(startNode, start);
|
|
808
|
+
const endText = startText && this.getTextOfNode(endNode, end);
|
|
1138
809
|
if (!startText || !endText)
|
|
1139
810
|
return null;
|
|
1140
|
-
const
|
|
1141
|
-
return this.textValue(startText,
|
|
811
|
+
const from = offsetIn(startText, startNode, start);
|
|
812
|
+
return this.textValue(startText, from, endText, offsetIn(endText, endNode, end), isReversed);
|
|
813
|
+
};
|
|
814
|
+
/**
|
|
815
|
+
* A DOM selection whose two endpoints are this editor's own points (not
|
|
816
|
+
* in a kind's control): its endpoints in document order and its direction.
|
|
817
|
+
*/
|
|
818
|
+
#read = (dom) => {
|
|
819
|
+
const container = this.edytor.node;
|
|
820
|
+
if (!dom || !isOwnPoint(container, dom.anchorNode) || !isOwnPoint(container, dom.focusNode))
|
|
821
|
+
return null;
|
|
822
|
+
const isReversed = isBackward(dom);
|
|
823
|
+
return { isReversed, ...ordered(dom, isReversed) };
|
|
1142
824
|
};
|
|
1143
825
|
}
|