@ecsplico/editor 3.6.0 → 4.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/CHANGELOG.md +65 -0
- package/dist/adapters/direct-ai.d.ts +4 -4
- package/dist/adapters/direct-ai.js +2 -2
- package/dist/adapters/direct-ai.js.map +1 -1
- package/dist/adapters/document-state.d.ts +1 -1
- package/dist/adapters/document-state.js.map +1 -1
- package/dist/adapters/forge.d.ts +2 -2
- package/dist/adapters/forge.js.map +1 -1
- package/dist/adapters/nitro.d.ts +11 -3
- package/dist/adapters/nitro.js +3 -1
- package/dist/adapters/nitro.js.map +1 -1
- package/dist/adapters/shared.d.ts +6 -6
- package/dist/adapters/shared.js.map +1 -1
- package/dist/config/index.d.ts +14 -14
- package/dist/config/index.js +8 -8
- package/dist/config/index.js.map +1 -1
- package/dist/core/backend-types.d.ts +3 -3
- package/dist/core/backend-types.js.map +1 -1
- package/dist/core/backend.d.ts +4 -4
- package/dist/core/backend.js.map +1 -1
- package/dist/core/block-convert.d.ts +1 -1
- package/dist/core/block-convert.js +5 -5
- package/dist/core/block-convert.js.map +1 -1
- package/dist/core/block-transfer.d.ts +8 -4
- package/dist/core/block-transfer.js +23 -14
- package/dist/core/block-transfer.js.map +1 -1
- package/dist/core/capabilities.d.ts +113 -0
- package/dist/core/capabilities.js +155 -0
- package/dist/core/capabilities.js.map +1 -0
- package/dist/core/command-types.d.ts +1 -1
- package/dist/core/context.js.map +1 -1
- package/dist/core/convert.d.ts +5 -5
- package/dist/core/convert.js +5 -5
- package/dist/core/convert.js.map +1 -1
- package/dist/core/core-feature.js +1 -1
- package/dist/core/define-editor.d.ts +2 -2
- package/dist/core/define-editor.js +34 -6
- package/dist/core/define-editor.js.map +1 -1
- package/dist/core/derivation.d.ts +119 -0
- package/dist/core/derivation.js +187 -0
- package/dist/core/derivation.js.map +1 -0
- package/dist/core/derive.d.ts +61 -0
- package/dist/core/derive.js +69 -0
- package/dist/core/derive.js.map +1 -0
- package/dist/core/extension-points.d.ts +16 -0
- package/dist/core/feature-context.d.ts +5 -1
- package/dist/core/feature-context.js +10 -3
- package/dist/core/feature-context.js.map +1 -1
- package/dist/core/feature.d.ts +41 -19
- package/dist/core/feature.js.map +1 -1
- package/dist/core/fences.js +1 -1
- package/dist/core/fences.js.map +1 -1
- package/dist/core/index.d.ts +6 -2
- package/dist/core/index.js +5 -1
- package/dist/core/pipeline.d.ts +14 -5
- package/dist/core/pipeline.js +19 -7
- package/dist/core/pipeline.js.map +1 -1
- package/dist/core/properties.d.ts +22 -0
- package/dist/core/properties.js +17 -0
- package/dist/core/properties.js.map +1 -0
- package/dist/core/schema/block-ids.js +5 -5
- package/dist/core/schema/block-ids.js.map +1 -1
- package/dist/core/schema/index.d.ts +2 -1
- package/dist/core/schema/index.js +2 -1
- package/dist/core/schema/index.js.map +1 -1
- package/dist/core/schema/opaque-fence.d.ts +4 -4
- package/dist/core/schema/opaque-fence.js +7 -7
- package/dist/core/schema/opaque-fence.js.map +1 -1
- package/dist/core/schema/persisted-names.d.ts +58 -0
- package/dist/core/schema/persisted-names.js +96 -0
- package/dist/core/schema/persisted-names.js.map +1 -0
- package/dist/core/toolbar-items.js +1 -1
- package/dist/core/toolbar-items.js.map +1 -1
- package/dist/core/util.js +5 -1
- package/dist/core/util.js.map +1 -1
- package/dist/features/ai/agent-ops.js +1 -1
- package/dist/features/ai/ai-review.js +1 -1
- package/dist/features/ai/assistant.d.ts +4 -4
- package/dist/features/ai/assistant.js +1 -1
- package/dist/features/ai/assistant.js.map +1 -1
- package/dist/features/ai/components/AiSelectionMenu.js +1 -1
- package/dist/features/ai/components/AiSelectionMenu.js.map +1 -1
- package/dist/features/ai/components/ModelQuickSwitch.js +7 -7
- package/dist/features/ai/components/ModelQuickSwitch.js.map +1 -1
- package/dist/features/ai/components/ModelQuickSwitch.vue.d.ts +4 -4
- package/dist/features/ai/components/SettingsAiTab.js +8 -8
- package/dist/features/ai/components/SettingsAiTab.js.map +1 -1
- package/dist/features/ai/components/SettingsModelProfiles.js +1 -1
- package/dist/features/ai/components/SettingsModelProfiles.js.map +1 -1
- package/dist/features/ai/document-chat-model.d.ts +2 -2
- package/dist/features/ai/document-chat-model.js +5 -5
- package/dist/features/ai/document-chat-model.js.map +1 -1
- package/dist/features/ai/document-chat.js +2 -2
- package/dist/features/ai/document-chat.js.map +1 -1
- package/dist/features/ai/feature.d.ts +2 -2
- package/dist/features/ai/feature.js +2 -2
- package/dist/features/ai/feature.js.map +1 -1
- package/dist/features/ai/ghost-autocomplete.d.ts +4 -4
- package/dist/features/ai/ghost-autocomplete.js +1 -1
- package/dist/features/ai/ghost-autocomplete.js.map +1 -1
- package/dist/features/ai/index.d.ts +3 -3
- package/dist/features/ai/index.js +2 -2
- package/dist/features/ai/model-profiles.d.ts +9 -9
- package/dist/features/ai/model-profiles.js +13 -13
- package/dist/features/ai/model-profiles.js.map +1 -1
- package/dist/features/ai/protocol/agent-ops.d.ts +2 -2
- package/dist/features/ai/protocol/agent-ops.js +1 -1
- package/dist/features/ai/protocol/agent-ops.js.map +1 -1
- package/dist/features/ai/protocol/block-lines.d.ts +7 -7
- package/dist/features/ai/protocol/block-lines.js +10 -10
- package/dist/features/ai/protocol/block-lines.js.map +1 -1
- package/dist/features/ai/protocol/chat.d.ts +5 -5
- package/dist/features/ai/protocol/chat.js +12 -12
- package/dist/features/ai/protocol/chat.js.map +1 -1
- package/dist/features/ai/protocol/generate.d.ts +1 -1
- package/dist/features/ai/protocol/generate.js +1 -1
- package/dist/features/ai/protocol/generate.js.map +1 -1
- package/dist/features/ai/protocol/index.d.ts +3 -3
- package/dist/features/ai/protocol/index.js +2 -2
- package/dist/features/ai/protocol/models.d.ts +3 -3
- package/dist/features/ai/protocol/models.js +3 -3
- package/dist/features/ai/protocol/models.js.map +1 -1
- package/dist/features/ai/protocol/schemas.d.ts +1 -1
- package/dist/features/ai/protocol/schemas.js +1 -1
- package/dist/features/ai/protocol/schemas.js.map +1 -1
- package/dist/features/ai/protocol/tasks.d.ts +5 -5
- package/dist/features/ai/protocol/tasks.js +12 -12
- package/dist/features/ai/protocol/tasks.js.map +1 -1
- package/dist/features/ai/react/AiSelectionMenu.js.map +1 -1
- package/dist/features/ai/react/ModelQuickSwitch.d.ts +4 -4
- package/dist/features/ai/react/ModelQuickSwitch.js +6 -6
- package/dist/features/ai/react/ModelQuickSwitch.js.map +1 -1
- package/dist/features/ai/react/SettingsAiTab.d.ts +1 -1
- package/dist/features/ai/react/SettingsAiTab.js +8 -8
- package/dist/features/ai/react/SettingsAiTab.js.map +1 -1
- package/dist/features/ai/react/SettingsModelProfiles.d.ts +1 -1
- package/dist/features/ai/react/SettingsModelProfiles.js +1 -1
- package/dist/features/ai/react/SettingsModelProfiles.js.map +1 -1
- package/dist/features/ai/react/use-ai-assistant.d.ts +1 -1
- package/dist/features/ai/react/use-ai-assistant.js +1 -1
- package/dist/features/ai/react/use-ai-assistant.js.map +1 -1
- package/dist/features/ai/react/use-model-profiles.d.ts +5 -5
- package/dist/features/ai/react/use-model-profiles.js +2 -2
- package/dist/features/ai/react/use-model-profiles.js.map +1 -1
- package/dist/features/ai/use-ai-assistant.d.ts +1 -1
- package/dist/features/ai/use-ai-assistant.js +1 -1
- package/dist/features/ai/use-ai-assistant.js.map +1 -1
- package/dist/features/ai/use-model-profiles.d.ts +4 -4
- package/dist/features/ai/use-model-profiles.js +2 -2
- package/dist/features/ai/use-model-profiles.js.map +1 -1
- package/dist/features/block-ui/block-actions.d.ts +8 -4
- package/dist/features/block-ui/block-actions.js +38 -22
- package/dist/features/block-ui/block-actions.js.map +1 -1
- package/dist/features/block-ui/block-target.d.ts +29 -0
- package/dist/features/block-ui/block-target.js +63 -0
- package/dist/features/block-ui/block-target.js.map +1 -0
- package/dist/features/block-ui/components/BlockHandles.js +3 -3
- package/dist/features/block-ui/components/BlockHandles.js.map +1 -1
- package/dist/features/block-ui/components/BlockUi.js +11 -23
- package/dist/features/block-ui/components/BlockUi.js.map +1 -1
- package/dist/features/block-ui/feature.d.ts +3 -2
- package/dist/features/block-ui/feature.js +3 -2
- package/dist/features/block-ui/feature.js.map +1 -1
- package/dist/features/block-ui/handle-geometry.js +12 -23
- package/dist/features/block-ui/handle-geometry.js.map +1 -1
- package/dist/features/block-ui/index.d.ts +2 -1
- package/dist/features/block-ui/index.js +2 -1
- package/dist/features/block-ui/react/BlockHandles.d.ts +1 -1
- package/dist/features/block-ui/react/BlockHandles.js +4 -4
- package/dist/features/block-ui/react/BlockHandles.js.map +1 -1
- package/dist/features/block-ui/react/BlockUi.js +13 -25
- package/dist/features/block-ui/react/BlockUi.js.map +1 -1
- package/dist/features/comments/model.js +1 -1
- package/dist/features/composites/accepted-children.d.ts +5 -4
- package/dist/features/composites/accepted-children.js +26 -26
- package/dist/features/composites/accepted-children.js.map +1 -1
- package/dist/features/composites/ai-brief.d.ts +4 -4
- package/dist/features/composites/ai-brief.js +14 -12
- package/dist/features/composites/ai-brief.js.map +1 -1
- package/dist/features/composites/anchors.d.ts +1 -1
- package/dist/features/composites/anchors.js.map +1 -1
- package/dist/features/composites/baskets.d.ts +1 -1
- package/dist/features/composites/baskets.js.map +1 -1
- package/dist/features/composites/bibliography-command.d.ts +1 -1
- package/dist/features/composites/bibliography-form.js +1 -1
- package/dist/features/composites/bibliography-form.js.map +1 -1
- package/dist/features/composites/bibliography.js.map +1 -1
- package/dist/features/composites/block-types-json.d.ts +38 -0
- package/dist/features/composites/block-types-json.js +122 -0
- package/dist/features/composites/block-types-json.js.map +1 -0
- package/dist/features/composites/block-types.d.ts +119 -0
- package/dist/features/composites/block-types.js +343 -0
- package/dist/features/composites/block-types.js.map +1 -0
- package/dist/features/composites/capabilities.js +109 -0
- package/dist/features/composites/capabilities.js.map +1 -0
- package/dist/features/composites/components/BibliographyEditor.js +5 -5
- package/dist/features/composites/components/BibliographyEditor.js.map +1 -1
- package/dist/features/composites/components/CompositeBasketMenu.js +2 -2
- package/dist/features/composites/components/CompositeBasketMenu.js.map +1 -1
- package/dist/features/composites/components/CompositeChrome.js +18 -8
- package/dist/features/composites/components/CompositeChrome.js.map +1 -1
- package/dist/features/composites/components/CompositeChrome.vue.d.ts +1 -1
- package/dist/features/composites/components/CompositeDetails.js +11 -10
- package/dist/features/composites/components/CompositeDetails.js.map +1 -1
- package/dist/features/composites/components/CompositeDetails.vue.d.ts +1 -1
- package/dist/features/composites/components/CompositeFieldEditor.js +7 -7
- package/dist/features/composites/components/CompositeFieldEditor.js.map +1 -1
- package/dist/features/composites/components/CompositeFieldEditor.vue.d.ts +5 -5
- package/dist/features/composites/components/CompositeInspector.js +136 -113
- package/dist/features/composites/components/CompositeInspector.js.map +1 -1
- package/dist/features/composites/components/CompositeInspector.vue.d.ts +3 -3
- package/dist/features/composites/components/CompositeStatusMenu.js +2 -2
- package/dist/features/composites/components/CompositeStatusMenu.js.map +1 -1
- package/dist/features/composites/components/CompositeSummaryEditor.js +1 -1
- package/dist/features/composites/components/CompositeSummaryEditor.js.map +1 -1
- package/dist/features/composites/components/CompositeSummaryEditor.vue.d.ts +1 -1
- package/dist/features/composites/components/CompositeTable.js +2 -2
- package/dist/features/composites/components/CompositeTable.js.map +1 -1
- package/dist/features/composites/components/CompositeTagsEditor.js +1 -1
- package/dist/features/composites/components/CompositeTagsEditor.js.map +1 -1
- package/dist/features/composites/components/CompositeTagsEditor.vue.d.ts +1 -1
- package/dist/features/composites/components/CompositeView.js +19 -17
- package/dist/features/composites/components/CompositeView.js.map +1 -1
- package/dist/features/composites/components/DerivationBadge.js +15 -6
- package/dist/features/composites/components/DerivationBadge.js.map +1 -1
- package/dist/features/composites/components/FocusChip.js +1 -1
- package/dist/features/composites/components/FocusChip.js.map +1 -1
- package/dist/features/composites/components/FocusChip.vue.d.ts +1 -1
- package/dist/features/composites/components/ReferenceFieldSelect.js +3 -3
- package/dist/features/composites/components/ReferenceFieldSelect.js.map +1 -1
- package/dist/features/composites/components/ReferenceView.js +1 -1
- package/dist/features/composites/components/ReferenceView.js.map +1 -1
- package/dist/features/composites/components/SettingsEditingTab.js +18 -18
- package/dist/features/composites/components/SettingsEditingTab.js.map +1 -1
- package/dist/features/composites/components/SettingsEditingTab.vue.d.ts +3 -3
- package/dist/features/composites/convert.d.ts +4 -4
- package/dist/features/composites/convert.js +27 -28
- package/dist/features/composites/convert.js.map +1 -1
- package/dist/features/composites/derived-chrome.js +34 -28
- package/dist/features/composites/derived-chrome.js.map +1 -1
- package/dist/features/composites/editing-settings-keys.js +6 -6
- package/dist/features/composites/editing-settings-keys.js.map +1 -1
- package/dist/features/composites/feature.d.ts +10 -10
- package/dist/features/composites/feature.js +58 -46
- package/dist/features/composites/feature.js.map +1 -1
- package/dist/features/composites/fences.d.ts +3 -3
- package/dist/features/composites/fences.js +18 -13
- package/dist/features/composites/fences.js.map +1 -1
- package/dist/features/composites/focus.d.ts +10 -10
- package/dist/features/composites/focus.js +11 -11
- package/dist/features/composites/focus.js.map +1 -1
- package/dist/features/composites/heading-composites.d.ts +5 -5
- package/dist/features/composites/heading-composites.js +13 -16
- package/dist/features/composites/heading-composites.js.map +1 -1
- package/dist/features/composites/index.d.ts +20 -18
- package/dist/features/composites/index.js +9 -7
- package/dist/features/composites/inspector-model.d.ts +45 -22
- package/dist/features/composites/inspector-model.js +53 -14
- package/dist/features/composites/inspector-model.js.map +1 -1
- package/dist/features/composites/legacy.d.ts +5 -4
- package/dist/features/composites/legacy.js +16 -23
- package/dist/features/composites/legacy.js.map +1 -1
- package/dist/features/composites/markdown-export.js +3 -3
- package/dist/features/composites/markdown-export.js.map +1 -1
- package/dist/features/composites/merge.d.ts +8 -8
- package/dist/features/composites/merge.js +23 -22
- package/dist/features/composites/merge.js.map +1 -1
- package/dist/features/composites/meta-display.js +5 -5
- package/dist/features/composites/meta-display.js.map +1 -1
- package/dist/features/composites/meta-keys.d.ts +5 -5
- package/dist/features/composites/meta-keys.js +8 -8
- package/dist/features/composites/meta-keys.js.map +1 -1
- package/dist/features/composites/node-views.d.ts +3 -3
- package/dist/features/composites/node-views.js +2 -2
- package/dist/features/composites/node-views.js.map +1 -1
- package/dist/features/composites/nodes.d.ts +13 -13
- package/dist/features/composites/nodes.js +100 -77
- package/dist/features/composites/nodes.js.map +1 -1
- package/dist/features/composites/outline.d.ts +15 -12
- package/dist/features/composites/outline.js +24 -21
- package/dist/features/composites/outline.js.map +1 -1
- package/dist/features/composites/properties.d.ts +51 -0
- package/dist/features/composites/properties.js +89 -0
- package/dist/features/composites/properties.js.map +1 -0
- package/dist/features/composites/react/BibliographyEditor.js +5 -5
- package/dist/features/composites/react/BibliographyEditor.js.map +1 -1
- package/dist/features/composites/react/CompositeBasketMenu.js +2 -2
- package/dist/features/composites/react/CompositeBasketMenu.js.map +1 -1
- package/dist/features/composites/react/CompositeChrome.d.ts +1 -1
- package/dist/features/composites/react/CompositeChrome.js +15 -6
- package/dist/features/composites/react/CompositeChrome.js.map +1 -1
- package/dist/features/composites/react/CompositeDetails.d.ts +1 -1
- package/dist/features/composites/react/CompositeDetails.js +11 -10
- package/dist/features/composites/react/CompositeDetails.js.map +1 -1
- package/dist/features/composites/react/CompositeFieldEditor.d.ts +5 -5
- package/dist/features/composites/react/CompositeFieldEditor.js +6 -6
- package/dist/features/composites/react/CompositeFieldEditor.js.map +1 -1
- package/dist/features/composites/react/CompositeInspector.d.ts +3 -3
- package/dist/features/composites/react/CompositeInspector.js +142 -128
- package/dist/features/composites/react/CompositeInspector.js.map +1 -1
- package/dist/features/composites/react/CompositeStatusMenu.js +2 -2
- package/dist/features/composites/react/CompositeStatusMenu.js.map +1 -1
- package/dist/features/composites/react/CompositeSummaryEditor.d.ts +1 -1
- package/dist/features/composites/react/CompositeSummaryEditor.js +1 -1
- package/dist/features/composites/react/CompositeSummaryEditor.js.map +1 -1
- package/dist/features/composites/react/CompositeTable.d.ts +1 -1
- package/dist/features/composites/react/CompositeTable.js +3 -3
- package/dist/features/composites/react/CompositeTable.js.map +1 -1
- package/dist/features/composites/react/CompositeTagsEditor.d.ts +1 -1
- package/dist/features/composites/react/CompositeTagsEditor.js +1 -1
- package/dist/features/composites/react/CompositeTagsEditor.js.map +1 -1
- package/dist/features/composites/react/CompositeView.js +17 -15
- package/dist/features/composites/react/CompositeView.js.map +1 -1
- package/dist/features/composites/react/DerivationBadge.js +13 -4
- package/dist/features/composites/react/DerivationBadge.js.map +1 -1
- package/dist/features/composites/react/FocusChip.d.ts +1 -1
- package/dist/features/composites/react/FocusChip.js +1 -1
- package/dist/features/composites/react/FocusChip.js.map +1 -1
- package/dist/features/composites/react/ReferenceFieldSelect.js +3 -3
- package/dist/features/composites/react/ReferenceFieldSelect.js.map +1 -1
- package/dist/features/composites/react/ReferenceView.d.ts +1 -1
- package/dist/features/composites/react/ReferenceView.js +1 -1
- package/dist/features/composites/react/ReferenceView.js.map +1 -1
- package/dist/features/composites/react/SettingsEditingTab.d.ts +4 -4
- package/dist/features/composites/react/SettingsEditingTab.js +20 -20
- package/dist/features/composites/react/SettingsEditingTab.js.map +1 -1
- package/dist/features/composites/react.js +1 -1
- package/dist/features/composites/react.js.map +1 -1
- package/dist/features/composites/reference-ai.js +1 -1
- package/dist/features/composites/reference-ai.js.map +1 -1
- package/dist/features/composites/reference-label.d.ts +3 -3
- package/dist/features/composites/reference-label.js +6 -6
- package/dist/features/composites/reference-label.js.map +1 -1
- package/dist/features/composites/reference-suggestion.d.ts +1 -1
- package/dist/features/composites/reference-suggestion.js +3 -3
- package/dist/features/composites/reference-suggestion.js.map +1 -1
- package/dist/features/composites/reference-text.d.ts +2 -2
- package/dist/features/composites/reference-text.js +4 -4
- package/dist/features/composites/reference-text.js.map +1 -1
- package/dist/features/composites/reference.d.ts +3 -3
- package/dist/features/composites/reference.js +1 -1
- package/dist/features/composites/reference.js.map +1 -1
- package/dist/features/composites/reveal-source.d.ts +3 -3
- package/dist/features/composites/reveal-source.js +6 -6
- package/dist/features/composites/reveal-source.js.map +1 -1
- package/dist/features/composites/rows-model.d.ts +2 -2
- package/dist/features/composites/rows-model.js +4 -3
- package/dist/features/composites/rows-model.js.map +1 -1
- package/dist/features/composites/rows.d.ts +16 -28
- package/dist/features/composites/rows.js +20 -54
- package/dist/features/composites/rows.js.map +1 -1
- package/dist/features/composites/schema.d.ts +12 -11
- package/dist/features/composites/schema.js +10 -9
- package/dist/features/composites/schema.js.map +1 -1
- package/dist/features/composites/source.d.ts +20 -0
- package/dist/features/composites/source.js +40 -0
- package/dist/features/composites/source.js.map +1 -0
- package/dist/features/composites/split.d.ts +11 -11
- package/dist/features/composites/split.js +20 -20
- package/dist/features/composites/split.js.map +1 -1
- package/dist/features/composites/structure-mode.js +3 -3
- package/dist/features/composites/structure-mode.js.map +1 -1
- package/dist/features/composites/table-model.js +2 -2
- package/dist/features/composites/table-model.js.map +1 -1
- package/dist/features/composites/use-composite-inspector.js +3 -1
- package/dist/features/composites/use-composite-inspector.js.map +1 -1
- package/dist/features/composites/use-composite-rows.d.ts +2 -2
- package/dist/features/composites/use-composite-rows.js.map +1 -1
- package/dist/features/composites/vue.js +1 -1
- package/dist/features/composites/vue.js.map +1 -1
- package/dist/features/image-studio/components/ImageStudioDialog.js +1 -1
- package/dist/features/image-studio/components/ImageStudioDialog.js.map +1 -1
- package/dist/features/image-studio/components/ImageStudioDialog.vue.d.ts +1 -1
- package/dist/features/image-studio/components/ImageStudioView.js.map +1 -1
- package/dist/features/image-studio/feature.d.ts +1 -1
- package/dist/features/image-studio/feature.js +1 -1
- package/dist/features/image-studio/feature.js.map +1 -1
- package/dist/features/image-studio/node-core.d.ts +3 -3
- package/dist/features/image-studio/node-core.js +1 -1
- package/dist/features/image-studio/node-core.js.map +1 -1
- package/dist/features/image-studio/node-store.d.ts +1 -1
- package/dist/features/image-studio/node-store.js +1 -1
- package/dist/features/image-studio/node-store.js.map +1 -1
- package/dist/features/image-studio/react/ImageStudioDialog.d.ts +1 -1
- package/dist/features/image-studio/react/ImageStudioDialog.js +1 -1
- package/dist/features/image-studio/react/ImageStudioDialog.js.map +1 -1
- package/dist/features/image-studio/react/ImageStudioView.js +1 -1
- package/dist/features/image-studio/react/ImageStudioView.js.map +1 -1
- package/dist/features/image-studio/react/store.d.ts +3 -3
- package/dist/features/image-studio/react/store.js.map +1 -1
- package/dist/features/image-studio/react.d.ts +1 -1
- package/dist/features/image-studio/react.js +1 -1
- package/dist/features/image-studio/react.js.map +1 -1
- package/dist/features/image-studio/schema.d.ts +1 -1
- package/dist/features/image-studio/schema.js +1 -1
- package/dist/features/image-studio/schema.js.map +1 -1
- package/dist/features/image-studio/state.d.ts +3 -3
- package/dist/features/image-studio/state.js +2 -2
- package/dist/features/image-studio/state.js.map +1 -1
- package/dist/features/image-studio/store.d.ts +3 -3
- package/dist/features/image-studio/vue.d.ts +1 -1
- package/dist/features/image-studio/vue.js +1 -1
- package/dist/features/image-studio/vue.js.map +1 -1
- package/dist/features/media/index.js +1 -1
- package/dist/features/media/react/AudioRecorderModal.js +1 -1
- package/dist/features/media/react.js +1 -1
- package/dist/features/mentions/tag.js +2 -1
- package/dist/features/mentions/tag.js.map +1 -1
- package/dist/features/themes/components/SettingsAppearanceTab.js +1 -1
- package/dist/features/themes/components/SettingsAppearanceTab.js.map +1 -1
- package/dist/features/themes/feature.d.ts +1 -1
- package/dist/features/themes/feature.js.map +1 -1
- package/dist/features/themes/react/SettingsAppearanceTab.d.ts +1 -1
- package/dist/features/themes/react/SettingsAppearanceTab.js +1 -1
- package/dist/features/themes/react/SettingsAppearanceTab.js.map +1 -1
- package/dist/features/themes/theme-runtime.js +1 -1
- package/dist/features/themes/theme-runtime.js.map +1 -1
- package/dist/features/transcript/TranscriptSegmentView.js +1 -1
- package/dist/features/transcript/TranscriptSegmentView.js.map +1 -1
- package/dist/features/transcript/react/TranscriptSegmentView.js +1 -1
- package/dist/features/transcript/react/TranscriptSegmentView.js.map +1 -1
- package/dist/features/transcript/segment-node.js.map +1 -1
- package/dist/features/transfer/feature.js +1 -1
- package/dist/features/transfer/feature.js.map +1 -1
- package/dist/features/transfer/transforms.d.ts +4 -4
- package/dist/features/transfer/transforms.js +12 -12
- package/dist/features/transfer/transforms.js.map +1 -1
- package/dist/i18n/de/ai.js +4 -4
- package/dist/i18n/de/ai.js.map +1 -1
- package/dist/i18n/de/authors.js +1 -1
- package/dist/i18n/de/authors.js.map +1 -1
- package/dist/i18n/de/comments.js +1 -1
- package/dist/i18n/de/comments.js.map +1 -1
- package/dist/i18n/de/composites.js +62 -59
- package/dist/i18n/de/composites.js.map +1 -1
- package/dist/i18n/de/image-studio.js +2 -2
- package/dist/i18n/de/image-studio.js.map +1 -1
- package/dist/i18n/de/integrations.js +20 -20
- package/dist/i18n/de/integrations.js.map +1 -1
- package/dist/i18n/de/markdown.js +1 -1
- package/dist/i18n/de/markdown.js.map +1 -1
- package/dist/i18n/de/palette.js +1 -1
- package/dist/i18n/de/palette.js.map +1 -1
- package/dist/i18n/de/themes.js +3 -3
- package/dist/i18n/de/themes.js.map +1 -1
- package/dist/i18n/de/transfer.js +2 -2
- package/dist/i18n/de/transfer.js.map +1 -1
- package/dist/i18n/de/tree.js +6 -6
- package/dist/i18n/de/tree.js.map +1 -1
- package/dist/i18n/de.d.ts +101 -98
- package/dist/i18n/en/ai.js +2 -2
- package/dist/i18n/en/ai.js.map +1 -1
- package/dist/i18n/en/composites.js +64 -61
- package/dist/i18n/en/composites.js.map +1 -1
- package/dist/i18n/en/integrations.js +9 -9
- package/dist/i18n/en/integrations.js.map +1 -1
- package/dist/i18n/en/markdown.js +1 -1
- package/dist/i18n/en/markdown.js.map +1 -1
- package/dist/i18n/en/palette.js +1 -1
- package/dist/i18n/en/palette.js.map +1 -1
- package/dist/i18n/en/themes.js +4 -4
- package/dist/i18n/en/themes.js.map +1 -1
- package/dist/i18n/en/tree.js +5 -5
- package/dist/i18n/en/tree.js.map +1 -1
- package/dist/index.d.ts +4 -1
- package/dist/integrations/composite-ai/bibliography-fetch.d.ts +6 -6
- package/dist/integrations/composite-ai/bibliography-fetch.js +19 -19
- package/dist/integrations/composite-ai/bibliography-fetch.js.map +1 -1
- package/dist/integrations/composite-ai/composite-fill.d.ts +4 -4
- package/dist/integrations/composite-ai/composite-fill.js +5 -5
- package/dist/integrations/composite-ai/composite-fill.js.map +1 -1
- package/dist/integrations/composite-ai/composite-summary.d.ts +2 -2
- package/dist/integrations/composite-ai/composite-summary.js +5 -5
- package/dist/integrations/composite-ai/composite-summary.js.map +1 -1
- package/dist/integrations/composite-ai/derive.d.ts +17 -17
- package/dist/integrations/composite-ai/derive.js +27 -26
- package/dist/integrations/composite-ai/derive.js.map +1 -1
- package/dist/integrations/composite-ai/index.d.ts +14 -15
- package/dist/integrations/composite-ai/index.js +98 -77
- package/dist/integrations/composite-ai/index.js.map +1 -1
- package/dist/integrations/composite-ai/outline-sanitize.d.ts +1 -1
- package/dist/integrations/composite-ai/outline-sanitize.js +1 -1
- package/dist/integrations/composite-ai/outline-sanitize.js.map +1 -1
- package/dist/integrations/composite-ai/rendition.d.ts +9 -9
- package/dist/integrations/composite-ai/rendition.js +27 -27
- package/dist/integrations/composite-ai/rendition.js.map +1 -1
- package/dist/integrations/composite-ai/split.d.ts +8 -8
- package/dist/integrations/composite-ai/split.js +12 -12
- package/dist/integrations/composite-ai/split.js.map +1 -1
- package/dist/integrations/composite-ai/transfer-transforms.d.ts +2 -2
- package/dist/integrations/composite-ai/transfer-transforms.js +12 -12
- package/dist/integrations/composite-ai/transfer-transforms.js.map +1 -1
- package/dist/integrations/composite-media/index.d.ts +4 -3
- package/dist/integrations/composite-media/index.js +20 -14
- package/dist/integrations/composite-media/index.js.map +1 -1
- package/dist/markdown/document.js +1 -1
- package/dist/markdown/document.js.map +1 -1
- package/dist/nuxt/module.d.ts +30 -24
- package/dist/nuxt/module.js.map +1 -1
- package/dist/nuxt/runtime/server/plugins/editor-server.js +3 -2
- package/dist/nuxt/runtime/server/plugins/editor-server.js.map +1 -1
- package/dist/presets/compose.d.ts +6 -6
- package/dist/presets/compose.js +8 -5
- package/dist/presets/compose.js.map +1 -1
- package/dist/react/AdvancedEditor.d.ts +2 -2
- package/dist/react/AdvancedEditor.js +1 -1
- package/dist/react/AdvancedEditor.js.map +1 -1
- package/dist/react/compose.d.ts +1 -1
- package/dist/react/compose.js +2 -2
- package/dist/react/compose.js.map +1 -1
- package/dist/react/composed-surface.d.ts +5 -5
- package/dist/react/composed-surface.js +2 -2
- package/dist/react/composed-surface.js.map +1 -1
- package/dist/server/ai.d.ts +7 -7
- package/dist/server/ai.js +1 -1
- package/dist/server/ai.js.map +1 -1
- package/dist/server/auth.d.ts +1 -1
- package/dist/server/collab-state.d.ts +1 -1
- package/dist/server/collab-state.js.map +1 -1
- package/dist/server/collab.d.ts +4 -4
- package/dist/server/collab.js +22 -17
- package/dist/server/collab.js.map +1 -1
- package/dist/server/handlers/ai.d.ts +7 -4
- package/dist/server/handlers/ai.js +13 -17
- package/dist/server/handlers/ai.js.map +1 -1
- package/dist/server/handlers/context.d.ts +4 -0
- package/dist/server/handlers/context.js.map +1 -1
- package/dist/server/handlers/editor.d.ts +33 -32
- package/dist/server/handlers/editor.js +13 -8
- package/dist/server/handlers/editor.js.map +1 -1
- package/dist/server/handlers/images.d.ts +1 -1
- package/dist/server/handlers/images.js +1 -1
- package/dist/server/handlers/images.js.map +1 -1
- package/dist/server/host.d.ts +4 -0
- package/dist/server/host.js +10 -2
- package/dist/server/host.js.map +1 -1
- package/dist/server/index.d.ts +3 -3
- package/dist/server/ports.d.ts +8 -8
- package/dist/server/ports.js.map +1 -1
- package/dist/settings/index.d.ts +20 -19
- package/dist/settings/index.js +25 -24
- package/dist/settings/index.js.map +1 -1
- package/dist/settings/migrate.d.ts +18 -0
- package/dist/settings/migrate.js +46 -0
- package/dist/settings/migrate.js.map +1 -0
- package/dist/settings/values.d.ts +12 -12
- package/dist/settings/values.js +11 -11
- package/dist/settings/values.js.map +1 -1
- package/dist/styles/composites.css +10 -10
- package/dist/tree/DocumentTree.js +12 -5
- package/dist/tree/DocumentTree.js.map +1 -1
- package/dist/tree/drop-rules.js +5 -5
- package/dist/tree/drop-rules.js.map +1 -1
- package/dist/tree/react/DocumentTree.js +14 -5
- package/dist/tree/react/DocumentTree.js.map +1 -1
- package/dist/tree/tree-host.js +6 -6
- package/dist/tree/tree-host.js.map +1 -1
- package/dist/tree/tree-items.js +34 -28
- package/dist/tree/tree-items.js.map +1 -1
- package/dist/tree/tree-model.js +16 -16
- package/dist/tree/tree-model.js.map +1 -1
- package/dist/tree/tree-rows.js +2 -2
- package/dist/tree/tree-rows.js.map +1 -1
- package/dist/tree/tree-view-model.d.ts +2 -2
- package/dist/tree/tree-view-model.js.map +1 -1
- package/dist/vue/AdvancedEditor.js +2 -2
- package/dist/vue/AdvancedEditor.js.map +1 -1
- package/dist/vue/AdvancedEditor.vue.d.ts +6 -6
- package/dist/vue/compose.d.ts +1 -1
- package/dist/vue/compose.js +2 -2
- package/dist/vue/compose.js.map +1 -1
- package/package.json +1 -1
- package/dist/features/composites/derivation.d.ts +0 -62
- package/dist/features/composites/derivation.js +0 -102
- package/dist/features/composites/derivation.js.map +0 -1
- package/dist/features/composites/kinds.d.ts +0 -89
- package/dist/features/composites/kinds.js +0 -285
- package/dist/features/composites/kinds.js.map +0 -1
|
@@ -11,8 +11,9 @@ export interface BlockUiUi<C> {
|
|
|
11
11
|
* Block-level UI beside the editor content: the drag handle (upstream `@tiptap/extension-drag-handle`) with hover
|
|
12
12
|
* targeting, and the actions of the targeted block (features' and host block actions, `BlockActionsOverlay`), on the
|
|
13
13
|
* hover bar, the toolbar of the block holding the selection, or both (`BlockUiOptions.actions`; hover by default).
|
|
14
|
-
* Also adds block-range selection (`NodeRange`: Mod+drag, Shift+↑/↓).
|
|
15
|
-
*
|
|
14
|
+
* Also adds block-range selection (`NodeRange`: Mod+drag, Shift+↑/↓). The target is the outermost block below the nearest
|
|
15
|
+
* block container (`outerBlockAt`): a list item or a quote paragraph targets its list or quote; composite chrome
|
|
16
|
+
* (`editorChrome` nodes) targets its parent block.
|
|
16
17
|
*
|
|
17
18
|
* Opt-in: the simple editor has none of it. Installing a binding also bundles the drag handle's transitive collaboration
|
|
18
19
|
* support code (its upstream package imports `@tiptap/extension-collaboration` and `y-tiptap`), even without a live
|
|
@@ -4,8 +4,9 @@ import { NodeRange } from "@tiptap/extension-node-range";
|
|
|
4
4
|
* Block-level UI beside the editor content: the drag handle (upstream `@tiptap/extension-drag-handle`) with hover
|
|
5
5
|
* targeting, and the actions of the targeted block (features' and host block actions, `BlockActionsOverlay`), on the
|
|
6
6
|
* hover bar, the toolbar of the block holding the selection, or both (`BlockUiOptions.actions`; hover by default).
|
|
7
|
-
* Also adds block-range selection (`NodeRange`: Mod+drag, Shift+↑/↓).
|
|
8
|
-
*
|
|
7
|
+
* Also adds block-range selection (`NodeRange`: Mod+drag, Shift+↑/↓). The target is the outermost block below the nearest
|
|
8
|
+
* block container (`outerBlockAt`): a list item or a quote paragraph targets its list or quote; composite chrome
|
|
9
|
+
* (`editorChrome` nodes) targets its parent block.
|
|
9
10
|
*
|
|
10
11
|
* Opt-in: the simple editor has none of it. Installing a binding also bundles the drag handle's transitive collaboration
|
|
11
12
|
* support code (its upstream package imports `@tiptap/extension-collaboration` and `y-tiptap`), even without a live
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"feature.js","names":[],"sources":["../../../src/features/block-ui/feature.ts"],"sourcesContent":["import { NodeRange } from '@tiptap/extension-node-range'\nimport type { BlockUiOptions, EditorFeature } from '../../core'\n\n// The option types live in `core` (the editor entry carries them to the overlay); this is their public home.\nexport type { BlockActionSurface, BlockUiOptions } from '../../core'\n\n/** What a framework binding supplies to the block-ui feature. */\nexport interface BlockUiUi<C> {\n /** The block UI of an editor (drag handle, permanent handles, hover actions); mounted beside the editor content. */\n overlay: C\n}\n\n/**\n * Block-level UI beside the editor content: the drag handle (upstream `@tiptap/extension-drag-handle`) with hover\n * targeting, and the actions of the targeted block (features' and host block actions, `BlockActionsOverlay`), on the\n * hover bar, the toolbar of the block holding the selection, or both (`BlockUiOptions.actions`; hover by default).\n * Also adds block-range selection (`NodeRange`: Mod+drag, Shift+↑/↓).
|
|
1
|
+
{"version":3,"file":"feature.js","names":[],"sources":["../../../src/features/block-ui/feature.ts"],"sourcesContent":["import { NodeRange } from '@tiptap/extension-node-range'\nimport type { BlockUiOptions, EditorFeature } from '../../core'\n\n// The option types live in `core` (the editor entry carries them to the overlay); this is their public home.\nexport type { BlockActionSurface, BlockUiOptions } from '../../core'\n\n/** What a framework binding supplies to the block-ui feature. */\nexport interface BlockUiUi<C> {\n /** The block UI of an editor (drag handle, permanent handles, hover actions); mounted beside the editor content. */\n overlay: C\n}\n\n/**\n * Block-level UI beside the editor content: the drag handle (upstream `@tiptap/extension-drag-handle`) with hover\n * targeting, and the actions of the targeted block (features' and host block actions, `BlockActionsOverlay`), on the\n * hover bar, the toolbar of the block holding the selection, or both (`BlockUiOptions.actions`; hover by default).\n * Also adds block-range selection (`NodeRange`: Mod+drag, Shift+↑/↓). The target is the outermost block below the nearest\n * block container (`outerBlockAt`): a list item or a quote paragraph targets its list or quote; composite chrome\n * (`editorChrome` nodes) targets its parent block.\n *\n * Opt-in: the simple editor has none of it. Installing a binding also bundles the drag handle's transitive collaboration\n * support code (its upstream package imports `@tiptap/extension-collaboration` and `y-tiptap`), even without a live\n * collaboration session.\n *\n * The overlay is a component type the surface mounts without props, so `options` reach it through `EditorFeature.blockUi`\n * and the editor entry (`editorEntryOf(editor)?.blockUi`).\n */\nexport function blockUiFeatureCore<C>(ui: BlockUiUi<C>, options: BlockUiOptions = {}): EditorFeature<C> {\n return {\n id: 'block-ui',\n dimension: 'interaction',\n extensions: () => [NodeRange],\n blockUi: options,\n overlays: [ui.overlay],\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AA2BA,SAAgB,mBAAsB,IAAkB,UAA0B,CAAC,GAAqB;CACtG,OAAO;EACL,IAAI;EACJ,WAAW;EACX,kBAAkB,CAAC,SAAS;EAC5B,SAAS;EACT,UAAU,CAAC,GAAG,OAAO;CACvB;AACF"}
|
|
@@ -1,23 +1,13 @@
|
|
|
1
|
-
import { isChromeNode } from "../../core/schema/node-flags.js";
|
|
1
|
+
import { isBlockContainer, isChromeNode } from "../../core/schema/node-flags.js";
|
|
2
2
|
//#region src/features/block-ui/handle-geometry.ts
|
|
3
|
-
const LIST_ITEMS = ["listItem", "taskItem"];
|
|
4
|
-
const TABLE_STRUCTURE = [
|
|
5
|
-
"tableRow",
|
|
6
|
-
"tableCell",
|
|
7
|
-
"tableHeader"
|
|
8
|
-
];
|
|
9
3
|
/** Whether a block shows its own kind icon (a composite's `.composite__toggle`): the icon is its drag handle, so it gets no standard one. */
|
|
10
|
-
function
|
|
4
|
+
function hasBlockTypeIcon(dom) {
|
|
11
5
|
return dom.querySelector(":scope > .composite__toggle") !== null;
|
|
12
6
|
}
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
return list ? dom.getBoundingClientRect().left - list.getBoundingClientRect().left : 0;
|
|
16
|
-
}
|
|
17
|
-
/** Left edge of the handle column of the block `node` rendered as `dom` (the block's own left edge when it has no handle). */
|
|
18
|
-
function handleLeftOf(node, dom, handleWidth) {
|
|
7
|
+
/** Left edge of the handle column of the block rendered as `dom` (the block's own left edge when it has no handle). */
|
|
8
|
+
function handleLeftOf(dom, handleWidth) {
|
|
19
9
|
const left = dom.getBoundingClientRect().left;
|
|
20
|
-
return
|
|
10
|
+
return hasBlockTypeIcon(dom) ? left : left - handleWidth;
|
|
21
11
|
}
|
|
22
12
|
function firstLineCenterShift(dom, referenceTop, handleHeight) {
|
|
23
13
|
const textblock = dom.matches("p, h1, h2, h3, h4, h5, h6, pre") ? dom : dom.querySelector("p, h1, h2, h3, h4, h5, h6, pre");
|
|
@@ -27,19 +17,18 @@ function firstLineCenterShift(dom, referenceTop, handleHeight) {
|
|
|
27
17
|
return textblock.getBoundingClientRect().top + Number.parseFloat(style.paddingTop) - referenceTop + (lineHeight - handleHeight) / 2;
|
|
28
18
|
}
|
|
29
19
|
/**
|
|
30
|
-
* The blocks that get a permanent handle (`blocks.dragHandle: 'always'`): every block the hover handle can target
|
|
31
|
-
* depth, in document order
|
|
32
|
-
*
|
|
33
|
-
*
|
|
20
|
+
* The blocks that get a permanent handle (`blocks.dragHandle: 'always'`): every block the hover handle can target
|
|
21
|
+
* (`outerBlockRule`), at any depth, in document order: a block directly below a block container (the document or a
|
|
22
|
+
* Typed block's body). Not eligible: inline content, Typed block chrome (it stands for its Typed block), and everything
|
|
23
|
+
* inside a list, quote or table (the list, quote or table is the block). Blocks with a kind icon have the icon as their handle.
|
|
34
24
|
*/
|
|
35
25
|
function handleBlocksOf(view) {
|
|
36
26
|
const blocks = [];
|
|
37
|
-
view.state.doc.descendants((node, pos, parent
|
|
27
|
+
view.state.doc.descendants((node, pos, parent) => {
|
|
38
28
|
if (node.isInline || isChromeNode(node)) return false;
|
|
39
29
|
const dom = view.nodeDOM(pos);
|
|
40
30
|
if (!(dom instanceof HTMLElement)) return;
|
|
41
|
-
if (
|
|
42
|
-
node,
|
|
31
|
+
if (parent !== null && isBlockContainer(parent) && !hasBlockTypeIcon(dom)) blocks.push({
|
|
43
32
|
pos,
|
|
44
33
|
dom
|
|
45
34
|
});
|
|
@@ -47,6 +36,6 @@ function handleBlocksOf(view) {
|
|
|
47
36
|
return blocks;
|
|
48
37
|
}
|
|
49
38
|
//#endregion
|
|
50
|
-
export { firstLineCenterShift,
|
|
39
|
+
export { firstLineCenterShift, handleBlocksOf, handleLeftOf, hasBlockTypeIcon };
|
|
51
40
|
|
|
52
41
|
//# sourceMappingURL=handle-geometry.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handle-geometry.js","names":[],"sources":["../../../src/features/block-ui/handle-geometry.ts"],"sourcesContent":["import type {
|
|
1
|
+
{"version":3,"file":"handle-geometry.js","names":[],"sources":["../../../src/features/block-ui/handle-geometry.ts"],"sourcesContent":["import type { EditorView } from '@tiptap/pm/view'\nimport { isBlockContainer, isChromeNode } from '../../core/schema'\n\n// Where the drag handle sits and which blocks have one. Shared by the hover handle (`BlockUi`, upstream plugin) and the\n// permanent handles (`BlockHandles`), so both put the handle at the same place.\n\n/** Width and height of a handle: the hover handle's `size-6`. */\nexport const HANDLE_SIZE = 24\n\n/** Whether a block shows its own kind icon (a composite's `.composite__toggle`): the icon is its drag handle, so it gets no standard one. */\nexport function hasBlockTypeIcon(dom: HTMLElement): boolean {\n return dom.querySelector(':scope > .composite__toggle') !== null\n}\n\n/** Left edge of the handle column of the block rendered as `dom` (the block's own left edge when it has no handle). */\nexport function handleLeftOf(dom: HTMLElement, handleWidth: number): number {\n const left = dom.getBoundingClientRect().left\n return hasBlockTypeIcon(dom) ? left : left - handleWidth\n}\n\n// The plugin aligns the handle's top with the block's top, which sits above the middle of the block's first text line.\n// This shift puts the handle's centre on the centre of that line, counted from `referenceTop`.\nexport function firstLineCenterShift(dom: HTMLElement, referenceTop: number, handleHeight: number): number {\n const textblock = dom.matches('p, h1, h2, h3, h4, h5, h6, pre')\n ? dom\n : dom.querySelector<HTMLElement>('p, h1, h2, h3, h4, h5, h6, pre')\n if (!textblock) return 0\n const style = getComputedStyle(textblock)\n const lineHeight = Number.parseFloat(style.lineHeight) || Number.parseFloat(style.fontSize) * 1.2\n const lineTop = textblock.getBoundingClientRect().top + Number.parseFloat(style.paddingTop)\n return lineTop - referenceTop + (lineHeight - handleHeight) / 2\n}\n\n/**\n * The blocks that get a permanent handle (`blocks.dragHandle: 'always'`): every block the hover handle can target\n * (`outerBlockRule`), at any depth, in document order: a block directly below a block container (the document or a\n * Typed block's body). Not eligible: inline content, Typed block chrome (it stands for its Typed block), and everything\n * inside a list, quote or table (the list, quote or table is the block). Blocks with a kind icon have the icon as their handle.\n */\nexport function handleBlocksOf(view: EditorView): { pos: number, dom: HTMLElement }[] {\n const blocks: { pos: number, dom: HTMLElement }[] = []\n view.state.doc.descendants((node, pos, parent) => {\n if (node.isInline || isChromeNode(node)) return false\n const dom = view.nodeDOM(pos)\n if (!(dom instanceof HTMLElement)) return\n if (parent !== null && isBlockContainer(parent) && !hasBlockTypeIcon(dom)) blocks.push({ pos, dom })\n })\n return blocks\n}\n"],"mappings":";;;AAUA,SAAgB,iBAAiB,KAA2B;CAC1D,OAAO,IAAI,cAAc,6BAA6B,MAAM;AAC9D;;AAGA,SAAgB,aAAa,KAAkB,aAA6B;CAC1E,MAAM,OAAO,IAAI,sBAAsB,CAAC,CAAC;CACzC,OAAO,iBAAiB,GAAG,IAAI,OAAO,OAAO;AAC/C;AAIA,SAAgB,qBAAqB,KAAkB,cAAsB,cAA8B;CACzG,MAAM,YAAY,IAAI,QAAQ,gCAAgC,IAC1D,MACA,IAAI,cAA2B,gCAAgC;CACnE,IAAI,CAAC,WAAW,OAAO;CACvB,MAAM,QAAQ,iBAAiB,SAAS;CACxC,MAAM,aAAa,OAAO,WAAW,MAAM,UAAU,KAAK,OAAO,WAAW,MAAM,QAAQ,IAAI;CAE9F,OADgB,UAAU,sBAAsB,CAAC,CAAC,MAAM,OAAO,WAAW,MAAM,UAAU,IACzE,gBAAgB,aAAa,gBAAgB;AAChE;;;;;;;AAQA,SAAgB,eAAe,MAAuD;CACpF,MAAM,SAA8C,CAAC;CACrD,KAAK,MAAM,IAAI,aAAa,MAAM,KAAK,WAAW;EAChD,IAAI,KAAK,YAAY,aAAa,IAAI,GAAG,OAAO;EAChD,MAAM,MAAM,KAAK,QAAQ,GAAG;EAC5B,IAAI,EAAE,eAAe,cAAc;EACnC,IAAI,WAAW,QAAQ,iBAAiB,MAAM,KAAK,CAAC,iBAAiB,GAAG,GAAG,OAAO,KAAK;GAAE;GAAK;EAAI,CAAC;CACrG,CAAC;CACD,OAAO;AACT"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { BlockActionSurface, BlockUiOptions } from "../../core/extension-points.js";
|
|
2
2
|
import { BLOCK_CORNER_ATTR, BlockActionEntry, BlockCorner, actionSurfacesOf, blockActionsFor, blockCornerOf, effectiveTarget, sameBlock, selectedBlockOf } from "./block-actions.js";
|
|
3
|
+
import { outerBlockAt, outerBlocksAt, typedBlockAround } from "./block-target.js";
|
|
3
4
|
import { BlockUiUi, blockUiFeatureCore } from "./feature.js";
|
|
4
|
-
export { BLOCK_CORNER_ATTR, type BlockActionEntry, type BlockActionSurface, type BlockCorner, type BlockUiOptions, type BlockUiUi, actionSurfacesOf, blockActionsFor, blockCornerOf, blockUiFeatureCore, effectiveTarget, sameBlock, selectedBlockOf };
|
|
5
|
+
export { BLOCK_CORNER_ATTR, type BlockActionEntry, type BlockActionSurface, type BlockCorner, type BlockUiOptions, type BlockUiUi, actionSurfacesOf, blockActionsFor, blockCornerOf, blockUiFeatureCore, effectiveTarget, outerBlockAt, outerBlocksAt, sameBlock, selectedBlockOf, typedBlockAround };
|
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
import { blockUiFeatureCore } from "./feature.js";
|
|
2
|
+
import { outerBlockAt, outerBlocksAt, typedBlockAround } from "./block-target.js";
|
|
2
3
|
import { BLOCK_CORNER_ATTR, actionSurfacesOf, blockActionsFor, blockCornerOf, effectiveTarget, sameBlock, selectedBlockOf } from "./block-actions.js";
|
|
3
|
-
export { BLOCK_CORNER_ATTR, actionSurfacesOf, blockActionsFor, blockCornerOf, blockUiFeatureCore, effectiveTarget, sameBlock, selectedBlockOf };
|
|
4
|
+
export { BLOCK_CORNER_ATTR, actionSurfacesOf, blockActionsFor, blockCornerOf, blockUiFeatureCore, effectiveTarget, outerBlockAt, outerBlocksAt, sameBlock, selectedBlockOf, typedBlockAround };
|
|
@@ -4,7 +4,7 @@ import { Editor } from "@tiptap/core";
|
|
|
4
4
|
* The permanent drag handles (`blocks.dragHandle: 'always'`): one handle per block that the hover handle can target
|
|
5
5
|
* (`handleBlocksOf`), each where the hover handle would sit for that block, dragging the block like the hover handle
|
|
6
6
|
* does (`startBlockDrag`). Only blocks within a screen of the viewport get one. A nested block whose handle would cover
|
|
7
|
-
* another handle on the same line (
|
|
7
|
+
* another handle on the same line (a nested block flush with its container, say) has none: its container's handle moves it. Hidden
|
|
8
8
|
* while the editor is read-only. Positioned absolutely inside `host`, the `relative` element around the editor.
|
|
9
9
|
*/
|
|
10
10
|
export declare function BlockHandles({ editor, host }: {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { startBlockDrag } from "../../../core/block-drag.js";
|
|
2
2
|
import { cn } from "../../../react/ui/utils.js";
|
|
3
3
|
import { Icon } from "../../../react/Icon.js";
|
|
4
|
-
import { firstLineCenterShift,
|
|
4
|
+
import { firstLineCenterShift, handleBlocksOf } from "../handle-geometry.js";
|
|
5
5
|
import { useEffect, useState } from "react";
|
|
6
6
|
import { jsx } from "react/jsx-runtime";
|
|
7
7
|
//#region src/features/block-ui/react/BlockHandles.tsx
|
|
@@ -9,7 +9,7 @@ import { jsx } from "react/jsx-runtime";
|
|
|
9
9
|
* The permanent drag handles (`blocks.dragHandle: 'always'`): one handle per block that the hover handle can target
|
|
10
10
|
* (`handleBlocksOf`), each where the hover handle would sit for that block, dragging the block like the hover handle
|
|
11
11
|
* does (`startBlockDrag`). Only blocks within a screen of the viewport get one. A nested block whose handle would cover
|
|
12
|
-
* another handle on the same line (
|
|
12
|
+
* another handle on the same line (a nested block flush with its container, say) has none: its container's handle moves it. Hidden
|
|
13
13
|
* while the editor is read-only. Positioned absolutely inside `host`, the `relative` element around the editor.
|
|
14
14
|
*/
|
|
15
15
|
function BlockHandles({ editor, host }) {
|
|
@@ -32,10 +32,10 @@ function BlockHandles({ editor, host }) {
|
|
|
32
32
|
const originX = hostRect.left + host.clientLeft;
|
|
33
33
|
const originY = hostRect.top + host.clientTop;
|
|
34
34
|
const next = [];
|
|
35
|
-
for (const {
|
|
35
|
+
for (const { pos, dom } of handleBlocksOf(editor.view)) {
|
|
36
36
|
const rect = dom.getBoundingClientRect();
|
|
37
37
|
if (!rect.height || rect.bottom < -window.innerHeight || rect.top > 2 * window.innerHeight) continue;
|
|
38
|
-
const left = rect.left - 24 -
|
|
38
|
+
const left = rect.left - 24 - originX;
|
|
39
39
|
const top = rect.top + firstLineCenterShift(dom, rect.top, 24) - originY;
|
|
40
40
|
if (!next.some((other) => Math.abs(top - other.top) < 12 && left < other.left + 24 && other.left < left + 24)) next.push({
|
|
41
41
|
pos,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BlockHandles.js","names":[],"sources":["../../../../src/features/block-ui/react/BlockHandles.tsx"],"sourcesContent":["import type { Editor } from '@tiptap/core'\nimport { type DragEvent, useEffect, useState } from 'react'\nimport { startBlockDrag } from '../../../core'\nimport { Icon } from '../../../react/Icon'\nimport { cn } from '../../../react/ui/utils'\nimport { firstLineCenterShift,
|
|
1
|
+
{"version":3,"file":"BlockHandles.js","names":[],"sources":["../../../../src/features/block-ui/react/BlockHandles.tsx"],"sourcesContent":["import type { Editor } from '@tiptap/core'\nimport { type DragEvent, useEffect, useState } from 'react'\nimport { startBlockDrag } from '../../../core'\nimport { Icon } from '../../../react/Icon'\nimport { cn } from '../../../react/ui/utils'\nimport { firstLineCenterShift, HANDLE_SIZE, handleBlocksOf } from '../handle-geometry'\n\ninterface Handle { pos: number, left: number, top: number }\n\n/**\n * The permanent drag handles (`blocks.dragHandle: 'always'`): one handle per block that the hover handle can target\n * (`handleBlocksOf`), each where the hover handle would sit for that block, dragging the block like the hover handle\n * does (`startBlockDrag`). Only blocks within a screen of the viewport get one. A nested block whose handle would cover\n * another handle on the same line (a nested block flush with its container, say) has none: its container's handle moves it. Hidden\n * while the editor is read-only. Positioned absolutely inside `host`, the `relative` element around the editor.\n */\nexport function BlockHandles({ editor, host }: { editor: Editor, host: HTMLElement }) {\n const [handles, setHandles] = useState<readonly Handle[]>([])\n // While a drag runs the handles let events through, so a drop over a handle's gutter still reaches the editor.\n const [dragging, setDragging] = useState(false)\n\n useEffect(() => {\n let raf = 0\n let wasEditable = false\n const schedule = () => {\n if (!raf) raf = requestAnimationFrame(measure)\n }\n\n function measure() {\n raf = 0\n wasEditable = !editor.isDestroyed && editor.isEditable\n if (!wasEditable || !editor.view.dom.getClientRects().length) {\n setHandles(previous => (previous.length ? [] : previous))\n return\n }\n const hostRect = host.getBoundingClientRect()\n const originX = hostRect.left + host.clientLeft\n const originY = hostRect.top + host.clientTop\n const next: Handle[] = []\n for (const { pos, dom } of handleBlocksOf(editor.view)) {\n const rect = dom.getBoundingClientRect()\n if (!rect.height || rect.bottom < -window.innerHeight || rect.top > 2 * window.innerHeight) continue\n const left = rect.left - HANDLE_SIZE - originX\n const top = rect.top + firstLineCenterShift(dom, rect.top, HANDLE_SIZE) - originY\n const covered = next.some(other => Math.abs(top - other.top) < HANDLE_SIZE / 2 && left < other.left + HANDLE_SIZE && other.left < left + HANDLE_SIZE)\n if (!covered) next.push({ pos, left, top })\n }\n setHandles((previous) => {\n const changed = previous.length !== next.length || next.some((handle, index) => {\n const before = previous[index]\n return !before || handle.pos !== before.pos || handle.left !== before.left || handle.top !== before.top\n })\n return changed ? next : previous\n })\n }\n\n // Documents change layout through edits, the column through resizes; `EditorSurface` dispatches a transaction after\n // `setEditable`.\n const onTransaction = ({ transaction }: { transaction: { docChanged: boolean } }) => {\n if (transaction.docChanged || editor.isEditable !== wasEditable) schedule()\n }\n editor.on('transaction', onTransaction)\n window.addEventListener('resize', schedule)\n window.addEventListener('scroll', schedule, true)\n const resizeObserver = new ResizeObserver(schedule)\n resizeObserver.observe(editor.view.dom)\n schedule()\n return () => {\n editor.off('transaction', onTransaction)\n window.removeEventListener('resize', schedule)\n window.removeEventListener('scroll', schedule, true)\n resizeObserver.disconnect()\n if (raf) cancelAnimationFrame(raf)\n }\n }, [editor, host])\n\n function onDragStart(event: DragEvent<HTMLDivElement>, pos: number) {\n if (!startBlockDrag(editor, event.nativeEvent, pos)) {\n event.preventDefault()\n return\n }\n // Not inside `dragstart`: changing the source's styles there cancels the drag. The dropped block's handle may be\n // gone afterwards and send no `dragend`, so the document ends the drag.\n setTimeout(() => setDragging(true))\n const abort = new AbortController()\n const end = () => {\n setDragging(false)\n abort.abort()\n }\n document.addEventListener('drop', end, { signal: abort.signal })\n document.addEventListener('dragend', end, { signal: abort.signal })\n }\n\n return (\n <div className=\"absolute left-0 top-0 z-10 h-0 w-0\">\n {handles.map(handle => (\n <div\n key={handle.pos}\n draggable\n aria-hidden=\"true\"\n className={cn('absolute flex cursor-grab items-center justify-center rounded text-muted-foreground hover:bg-muted hover:text-foreground', dragging ? 'pointer-events-none' : 'pointer-events-auto')}\n style={{ left: `${handle.left}px`, top: `${handle.top}px`, width: `${HANDLE_SIZE}px`, height: `${HANDLE_SIZE}px` }}\n onDragStart={event => onDragStart(event, handle.pos)}\n >\n <Icon name=\"i-lucide-grip-vertical\" />\n </div>\n ))}\n </div>\n )\n}\n"],"mappings":"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"}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { editorEntryOf } from "../../../core/editor-ui.js";
|
|
2
|
-
import { isChromeNode } from "../../../core/schema/node-flags.js";
|
|
3
2
|
import { cn } from "../../../react/ui/utils.js";
|
|
4
3
|
import { Icon } from "../../../react/Icon.js";
|
|
5
4
|
import { useEditorSettings } from "../../../react/settings.js";
|
|
6
|
-
import { firstLineCenterShift,
|
|
5
|
+
import { firstLineCenterShift, handleLeftOf, hasBlockTypeIcon } from "../handle-geometry.js";
|
|
6
|
+
import { outerBlockRule } from "../block-target.js";
|
|
7
7
|
import { actionSurfacesOf, sameBlock, selectedBlockOf } from "../block-actions.js";
|
|
8
8
|
import { BlockActionsOverlay } from "./BlockActionsOverlay.js";
|
|
9
9
|
import { BlockHandles } from "./BlockHandles.js";
|
|
@@ -24,7 +24,7 @@ import { createPortal } from "react-dom";
|
|
|
24
24
|
function BlockUi({ editor }) {
|
|
25
25
|
const [host, setHost] = useState(null);
|
|
26
26
|
const [hoverTarget, setHoverTarget] = useState(null);
|
|
27
|
-
const [
|
|
27
|
+
const [targetHasBlockTypeIcon, setTargetHasBlockTypeIcon] = useState(false);
|
|
28
28
|
const { settings } = useEditorSettings();
|
|
29
29
|
const actions = editorEntryOf(editor)?.blockActions ?? [];
|
|
30
30
|
const surfaces = actionSurfacesOf(editor);
|
|
@@ -44,9 +44,7 @@ function BlockUi({ editor }) {
|
|
|
44
44
|
overlayHovered: false,
|
|
45
45
|
clearTimer: void 0,
|
|
46
46
|
pointer: null,
|
|
47
|
-
dom: null
|
|
48
|
-
node: null,
|
|
49
|
-
gutterShift: 0
|
|
47
|
+
dom: null
|
|
50
48
|
}).current;
|
|
51
49
|
const handleContent = useRef(null);
|
|
52
50
|
const handleWidth = () => handleContent.current?.parentElement?.offsetWidth ?? 0;
|
|
@@ -88,7 +86,7 @@ function BlockUi({ editor }) {
|
|
|
88
86
|
editor.view.dispatch(editor.state.tr.setMeta("hideDragHandle", true).setMeta("addToHistory", false));
|
|
89
87
|
}, [editor]);
|
|
90
88
|
const alwaysHandles = settings.blocks.dragHandle === "always";
|
|
91
|
-
const hoverHandleHidden = alwaysHandles ||
|
|
89
|
+
const hoverHandleHidden = alwaysHandles || targetHasBlockTypeIcon;
|
|
92
90
|
const trackDragTarget = useCallback(({ node, pos }) => {
|
|
93
91
|
if (node) {
|
|
94
92
|
clearTimeout(track.clearTimer);
|
|
@@ -99,21 +97,13 @@ function BlockUi({ editor }) {
|
|
|
99
97
|
} else scheduleHoverClear();
|
|
100
98
|
const dom = node ? editor.view.nodeDOM(pos) : null;
|
|
101
99
|
track.dom = dom instanceof HTMLElement ? dom : null;
|
|
102
|
-
track.
|
|
103
|
-
track.gutterShift = track.dom && track.node ? gutterShiftOf(track.node, track.dom) : 0;
|
|
104
|
-
setTargetHasKindIcon(track.dom ? hasKindIcon(track.dom) : false);
|
|
100
|
+
setTargetHasBlockTypeIcon(track.dom ? hasBlockTypeIcon(track.dom) : false);
|
|
105
101
|
}, [
|
|
106
102
|
editor,
|
|
107
103
|
track,
|
|
108
104
|
scheduleHoverClear
|
|
109
105
|
]);
|
|
110
106
|
const dragHandlePosition = useMemo(() => ({ middleware: [{
|
|
111
|
-
name: "gutterShift",
|
|
112
|
-
fn: ({ x, y }) => ({
|
|
113
|
-
x: x - track.gutterShift,
|
|
114
|
-
y
|
|
115
|
-
})
|
|
116
|
-
}, {
|
|
117
107
|
name: "firstLineCenter",
|
|
118
108
|
fn: ({ x, y, elements, rects }) => ({
|
|
119
109
|
x,
|
|
@@ -122,33 +112,31 @@ function BlockUi({ editor }) {
|
|
|
122
112
|
}] }), [track]);
|
|
123
113
|
const dragHandleNested = useMemo(() => {
|
|
124
114
|
const pointerReachesTarget = () => {
|
|
125
|
-
const { pointer,
|
|
126
|
-
if (!pointer || !
|
|
115
|
+
const { pointer, dom } = track;
|
|
116
|
+
if (!pointer || !dom?.isConnected) return false;
|
|
127
117
|
const rect = dom.getBoundingClientRect();
|
|
128
118
|
const { x, y } = pointer;
|
|
129
|
-
if (x < handleLeftOf(
|
|
119
|
+
if (x < handleLeftOf(dom, handleWidth()) || x >= rect.right) return false;
|
|
130
120
|
if (y < (laidOutSibling(dom, "previous")?.bottom ?? rect.top)) return false;
|
|
131
121
|
if (y >= (laidOutSibling(dom, "next")?.top ?? rect.bottom)) return false;
|
|
132
122
|
return x < rect.left || y < rect.top || y >= rect.bottom;
|
|
133
123
|
};
|
|
134
124
|
return {
|
|
135
125
|
edgeDetection: "none",
|
|
126
|
+
defaultRules: false,
|
|
136
127
|
rules: [
|
|
137
|
-
|
|
138
|
-
id: "compositeChrome",
|
|
139
|
-
evaluate: ({ node }) => isChromeNode(node) ? 1e3 : 0
|
|
140
|
-
},
|
|
128
|
+
outerBlockRule,
|
|
141
129
|
{
|
|
142
130
|
id: "reachTarget",
|
|
143
131
|
evaluate: () => pointerReachesTarget() ? 1e3 : 0
|
|
144
132
|
},
|
|
145
133
|
{
|
|
146
134
|
id: "ownGutter",
|
|
147
|
-
evaluate: ({
|
|
135
|
+
evaluate: ({ pos, depth, view }) => {
|
|
148
136
|
const { pointer } = track;
|
|
149
137
|
if (depth < 2 || !pointer) return 0;
|
|
150
138
|
const dom = view.nodeDOM(pos);
|
|
151
|
-
return dom instanceof HTMLElement && pointer.x < handleLeftOf(
|
|
139
|
+
return dom instanceof HTMLElement && pointer.x < handleLeftOf(dom, handleWidth()) ? 1e3 : 0;
|
|
152
140
|
}
|
|
153
141
|
}
|
|
154
142
|
]
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BlockUi.js","names":[],"sources":["../../../../src/features/block-ui/react/BlockUi.tsx"],"sourcesContent":["import type { Editor } from '@tiptap/core'\nimport { DragHandle, type DragHandleProps } from '@tiptap/extension-drag-handle-react'\nimport type { Node } from '@tiptap/pm/model'\nimport { useCallback, useEffect, useMemo, useReducer, useRef, useState } from 'react'\nimport { createPortal } from 'react-dom'\nimport { type BlockTarget, editorEntryOf } from '../../../core'\nimport { isChromeNode } from '../../../core/schema'\nimport { Icon } from '../../../react/Icon'\nimport { useEditorSettings } from '../../../react/settings'\nimport { cn } from '../../../react/ui/utils'\nimport { firstLineCenterShift, gutterShiftOf, handleLeftOf, hasKindIcon } from '../handle-geometry'\nimport { actionSurfacesOf, sameBlock, selectedBlockOf } from '../block-actions'\nimport { BlockActionsOverlay } from './BlockActionsOverlay'\nimport { BlockHandles } from './BlockHandles'\n\n/**\n * Block UI of an editor: the drag handle on the left of the hovered block (hidden while the editor is read-only) and the\n * block actions (`BlockActionsOverlay`) at the editor's right edge. The actions are those the surface registered for\n * `editor` (features' block actions, then the host's), shown per `BlockUiOptions.actions`: on a hover bar for the block\n * the drag handle targets, on a persistent toolbar for the block holding the selection, both, or neither. When both\n * would show a bar on the same block, only the toolbar does. A block with a kind icon (a composite) gets no handle: its\n * icon drags it. With `blocks.dragHandle: 'always'` the hover handle is replaced by permanent handles on every eligible\n * block (`BlockHandles`). Mounted by the block-ui feature beside the editor.\n */\nexport function BlockUi({ editor }: { editor: Editor }) {\n // Hover actions target the drag handle's block. The plugin drops its target when the pointer leaves the editor (also\n // onto the overlay, which sits outside it) and on keydown; a short grace keeps the overlay while the pointer moves\n // onto it, and typing hides it at once.\n const [host, setHost] = useState<HTMLElement | null>(null)\n const [hoverTarget, setHoverTarget] = useState<BlockTarget | null>(null)\n const [targetHasKindIcon, setTargetHasKindIcon] = useState(false)\n const { settings } = useEditorSettings()\n // Read while rendering: the surface registers its entry after its overlays have mounted, and the overlay renders\n // again once a block is hovered.\n const actions = editorEntryOf(editor)?.blockActions ?? []\n const surfaces = actionSurfacesOf(editor)\n\n // The toolbar follows the selection: render on each transaction, but only while that surface exists (the options are\n // read when the transaction happens, the entry being registered after this component mounted).\n const [, rerender] = useReducer((count: number) => count + 1, 0)\n useEffect(() => {\n const onTransaction = () => { if (actionSurfacesOf(editor).toolbar) rerender() }\n editor.on('transaction', onTransaction)\n return () => { editor.off('transaction', onTransaction) }\n }, [editor])\n const selectedTarget = surfaces.toolbar ? selectedBlockOf(editor) : null\n // One bar per block: the toolbar wins where the hover bar would sit on the same block.\n const hoverBarTarget = hoverTarget && selectedTarget && sameBlock(editor, hoverTarget, selectedTarget) ? null : hoverTarget\n\n // Everything the plugin callbacks and the targeting rules below read while the pointer moves: not render state.\n const track = useRef({\n overlayHovered: false,\n clearTimer: undefined as number | undefined,\n pointer: null as { x: number, y: number } | null,\n dom: null as HTMLElement | null,\n node: null as Node | null,\n gutterShift: 0,\n }).current\n // The handle's content; its parent is the handle element the plugin positions (`handleWidth`).\n const handleContent = useRef<HTMLSpanElement>(null)\n const handleWidth = () => handleContent.current?.parentElement?.offsetWidth ?? 0\n\n const scheduleHoverClear = useCallback(() => {\n clearTimeout(track.clearTimer)\n track.clearTimer = window.setTimeout(() => {\n if (!track.overlayHovered) setHoverTarget(null)\n }, 200)\n }, [track])\n\n // The overlay is positioned inside the element that holds the editor content (`relative`); Tiptap's content component\n // has moved the editor DOM into it by the time this effect runs.\n useEffect(() => {\n if (editor.isDestroyed) return\n const dom = editor.view.dom\n setHost(dom.isConnected ? dom.parentElement : null)\n // Like the drag-handle plugin: a key pressed in the focused editor hides the actions.\n const onKeydown = () => {\n clearTimeout(track.clearTimer)\n setHoverTarget(null)\n }\n // Pointer position for the targeting rules below. The plugin evaluates them in a frame callback after the\n // mousemove, so this is the position they see.\n const onMousemove = (event: MouseEvent) => {\n track.pointer = { x: event.clientX, y: event.clientY }\n }\n dom.addEventListener('keydown', onKeydown)\n dom.addEventListener('mousemove', onMousemove)\n return () => {\n clearTimeout(track.clearTimer)\n dom.removeEventListener('keydown', onKeydown)\n dom.removeEventListener('mousemove', onMousemove)\n setHost(null)\n }\n }, [editor, track])\n\n const onOverlayHover = useCallback((hovered: boolean) => {\n track.overlayHovered = hovered\n if (!hovered) scheduleHoverClear()\n }, [track, scheduleHoverClear])\n\n // The drag-handle plugin hides the handle on dragend but keeps its current target. A dropped\n // nested node is the same node object, so hovering it again would not re-show the handle.\n // The plugin's `hideDragHandle` meta clears the target.\n const resetDragHandle = useCallback(() => {\n if (editor.isDestroyed) return\n editor.view.dispatch(editor.state.tr.setMeta('hideDragHandle', true).setMeta('addToHistory', false))\n }, [editor])\n\n // The plugin puts the handle's right edge on the target block's left edge (`gutterShiftOf`: list items move further\n // left). The hover handle is hidden where the block has a handle of its own: the kind icon of a composite, or, with\n // `blocks.dragHandle: 'always'`, the permanent handles. Hiding keeps its layout, which the targeting rules below measure.\n const alwaysHandles = settings.blocks.dragHandle === 'always'\n const hoverHandleHidden = alwaysHandles || targetHasKindIcon\n const trackDragTarget = useCallback(({ node, pos }: { node: Node | null, pos: number }) => {\n if (node) {\n clearTimeout(track.clearTimer)\n setHoverTarget({ node, pos })\n }\n else {\n scheduleHoverClear()\n }\n const dom = node ? editor.view.nodeDOM(pos) : null\n track.dom = dom instanceof HTMLElement ? dom : null\n track.node = track.dom ? node : null\n track.gutterShift = track.dom && track.node ? gutterShiftOf(track.node, track.dom) : 0\n setTargetHasKindIcon(track.dom ? hasKindIcon(track.dom) : false)\n }, [editor, track, scheduleHoverClear])\n\n // The plugin re-registers when its configuration changes: both objects below are made once and read `track`.\n const dragHandlePosition = useMemo<DragHandleProps['computePositionConfig']>(() => ({\n // The plugin aligns the handle's top with the block's top, which sits above the middle of the block's first text\n // line: `firstLineCenterShift` moves the handle's centre to that line's centre.\n middleware: [\n { name: 'gutterShift', fn: ({ x, y }) => ({ x: x - track.gutterShift, y }) },\n {\n name: 'firstLineCenter',\n fn: ({ x, y, elements, rects }) => ({\n x,\n y: track.dom ? y + firstLineCenterShift(track.dom, elements.reference.getBoundingClientRect().top, rects.floating.height) : y,\n }),\n },\n ],\n }), [track])\n\n // Targeting among nested blocks. `compositeChrome`: hovering a composite's title, description or tags row targets the\n // composite itself (a deduction of 1000, the base score, excludes a node). `reachTarget`: see `pointerReachesTarget`.\n // `ownGutter`: a nested block is targeted only from its handle column rightwards; further left its ancestors are, so\n // on any row the gutter is partitioned by the handle columns of the blocks nested there. The plugin's edge detection\n // is off: its left strip is this partition, its top strip would hand the handle to the parent on the block's first\n // line, where the handle sits.\n const dragHandleNested = useMemo<DragHandleProps['nested']>(() => {\n // Left of a block, ProseMirror resolves the pointer to the position before the block, so the plugin only considers\n // the block's ancestors there: the target's own handle column would hand the handle to its parent before the pointer\n // reaches it. This keeps the target while the pointer is between its handle and its box, over its whole height\n // including the gaps to its neighbours, and in those gaps themselves (which resolve to the parent as well). The rule\n // then excludes every candidate, and the plugin keeps its target when the detection yields none. Inside the target's\n // own box the rule is off, so its descendants are still targeted.\n const pointerReachesTarget = (): boolean => {\n const { pointer, node, dom } = track\n if (!pointer || !node || !dom?.isConnected) return false\n const rect = dom.getBoundingClientRect()\n const { x, y } = pointer\n if (x < handleLeftOf(node, dom, handleWidth()) || x >= rect.right) return false\n if (y < (laidOutSibling(dom, 'previous')?.bottom ?? rect.top)) return false\n if (y >= (laidOutSibling(dom, 'next')?.top ?? rect.bottom)) return false\n return x < rect.left || y < rect.top || y >= rect.bottom\n }\n return {\n edgeDetection: 'none',\n rules: [\n { id: 'compositeChrome', evaluate: ({ node }) => isChromeNode(node) ? 1000 : 0 },\n { id: 'reachTarget', evaluate: () => pointerReachesTarget() ? 1000 : 0 },\n {\n id: 'ownGutter',\n evaluate: ({ node, pos, depth, view }) => {\n const { pointer } = track\n if (depth < 2 || !pointer) return 0\n const dom = view.nodeDOM(pos)\n return dom instanceof HTMLElement && pointer.x < handleLeftOf(node, dom, handleWidth()) ? 1000 : 0\n },\n },\n ],\n }\n }, [track])\n\n return (\n <>\n {host && createPortal(\n <>\n {surfaces.hover && (\n <BlockActionsOverlay editor={editor} target={hoverBarTarget} host={host} actions={actions} surface=\"hover\" onHover={onOverlayHover} />\n )}\n {surfaces.toolbar && (\n <BlockActionsOverlay editor={editor} target={selectedTarget} host={host} actions={actions} surface=\"toolbar\" persistent />\n )}\n {alwaysHandles && <BlockHandles editor={editor} host={host} />}\n </>,\n host,\n )}\n <DragHandle\n editor={editor}\n onElementDragEnd={resetDragHandle}\n onNodeChange={trackDragTarget}\n computePositionConfig={dragHandlePosition}\n nested={dragHandleNested}\n className={cn(\n 'flex size-6 cursor-grab items-center justify-center rounded text-muted-foreground hover:bg-muted hover:text-foreground data-[dragging=true]:cursor-grabbing',\n hoverHandleHidden && 'invisible! pointer-events-none!',\n )}\n >\n <span ref={handleContent} className=\"contents\">\n <Icon name=\"i-lucide-grip-vertical\" />\n </span>\n </DragHandle>\n </>\n )\n}\n\n// Nearest sibling with a layout box (a composite's hidden description/tags rows have none).\nfunction laidOutSibling(dom: Element, side: 'previous' | 'next'): DOMRect | null {\n for (let element = dom[`${side}ElementSibling`]; element; element = element[`${side}ElementSibling`]) {\n const rect = element.getBoundingClientRect()\n if (rect.height > 0) return rect\n }\n return null\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"BlockUi.js","names":[],"sources":["../../../../src/features/block-ui/react/BlockUi.tsx"],"sourcesContent":["import type { Editor } from '@tiptap/core'\nimport { DragHandle, type DragHandleProps } from '@tiptap/extension-drag-handle-react'\nimport type { Node } from '@tiptap/pm/model'\nimport { useCallback, useEffect, useMemo, useReducer, useRef, useState } from 'react'\nimport { createPortal } from 'react-dom'\nimport { type BlockTarget, editorEntryOf } from '../../../core'\nimport { Icon } from '../../../react/Icon'\nimport { useEditorSettings } from '../../../react/settings'\nimport { cn } from '../../../react/ui/utils'\nimport { firstLineCenterShift, handleLeftOf, hasBlockTypeIcon } from '../handle-geometry'\nimport { outerBlockRule } from '../block-target'\nimport { actionSurfacesOf, sameBlock, selectedBlockOf } from '../block-actions'\nimport { BlockActionsOverlay } from './BlockActionsOverlay'\nimport { BlockHandles } from './BlockHandles'\n\n/**\n * Block UI of an editor: the drag handle on the left of the hovered block (hidden while the editor is read-only) and the\n * block actions (`BlockActionsOverlay`) at the editor's right edge. The actions are those the surface registered for\n * `editor` (features' block actions, then the host's), shown per `BlockUiOptions.actions`: on a hover bar for the block\n * the drag handle targets, on a persistent toolbar for the block holding the selection, both, or neither. When both\n * would show a bar on the same block, only the toolbar does. A block with a kind icon (a composite) gets no handle: its\n * icon drags it. With `blocks.dragHandle: 'always'` the hover handle is replaced by permanent handles on every eligible\n * block (`BlockHandles`). Mounted by the block-ui feature beside the editor.\n */\nexport function BlockUi({ editor }: { editor: Editor }) {\n // Hover actions target the drag handle's block. The plugin drops its target when the pointer leaves the editor (also\n // onto the overlay, which sits outside it) and on keydown; a short grace keeps the overlay while the pointer moves\n // onto it, and typing hides it at once.\n const [host, setHost] = useState<HTMLElement | null>(null)\n const [hoverTarget, setHoverTarget] = useState<BlockTarget | null>(null)\n const [targetHasBlockTypeIcon, setTargetHasBlockTypeIcon] = useState(false)\n const { settings } = useEditorSettings()\n // Read while rendering: the surface registers its entry after its overlays have mounted, and the overlay renders\n // again once a block is hovered.\n const actions = editorEntryOf(editor)?.blockActions ?? []\n const surfaces = actionSurfacesOf(editor)\n\n // The toolbar follows the selection: render on each transaction, but only while that surface exists (the options are\n // read when the transaction happens, the entry being registered after this component mounted).\n const [, rerender] = useReducer((count: number) => count + 1, 0)\n useEffect(() => {\n const onTransaction = () => { if (actionSurfacesOf(editor).toolbar) rerender() }\n editor.on('transaction', onTransaction)\n return () => { editor.off('transaction', onTransaction) }\n }, [editor])\n const selectedTarget = surfaces.toolbar ? selectedBlockOf(editor) : null\n // One bar per block: the toolbar wins where the hover bar would sit on the same block.\n const hoverBarTarget = hoverTarget && selectedTarget && sameBlock(editor, hoverTarget, selectedTarget) ? null : hoverTarget\n\n // Everything the plugin callbacks and the targeting rules below read while the pointer moves: not render state.\n const track = useRef({\n overlayHovered: false,\n clearTimer: undefined as number | undefined,\n pointer: null as { x: number, y: number } | null,\n dom: null as HTMLElement | null,\n }).current\n // The handle's content; its parent is the handle element the plugin positions (`handleWidth`).\n const handleContent = useRef<HTMLSpanElement>(null)\n const handleWidth = () => handleContent.current?.parentElement?.offsetWidth ?? 0\n\n const scheduleHoverClear = useCallback(() => {\n clearTimeout(track.clearTimer)\n track.clearTimer = window.setTimeout(() => {\n if (!track.overlayHovered) setHoverTarget(null)\n }, 200)\n }, [track])\n\n // The overlay is positioned inside the element that holds the editor content (`relative`); Tiptap's content component\n // has moved the editor DOM into it by the time this effect runs.\n useEffect(() => {\n if (editor.isDestroyed) return\n const dom = editor.view.dom\n setHost(dom.isConnected ? dom.parentElement : null)\n // Like the drag-handle plugin: a key pressed in the focused editor hides the actions.\n const onKeydown = () => {\n clearTimeout(track.clearTimer)\n setHoverTarget(null)\n }\n // Pointer position for the targeting rules below. The plugin evaluates them in a frame callback after the\n // mousemove, so this is the position they see.\n const onMousemove = (event: MouseEvent) => {\n track.pointer = { x: event.clientX, y: event.clientY }\n }\n dom.addEventListener('keydown', onKeydown)\n dom.addEventListener('mousemove', onMousemove)\n return () => {\n clearTimeout(track.clearTimer)\n dom.removeEventListener('keydown', onKeydown)\n dom.removeEventListener('mousemove', onMousemove)\n setHost(null)\n }\n }, [editor, track])\n\n const onOverlayHover = useCallback((hovered: boolean) => {\n track.overlayHovered = hovered\n if (!hovered) scheduleHoverClear()\n }, [track, scheduleHoverClear])\n\n // The drag-handle plugin hides the handle on dragend but keeps its current target. A dropped\n // nested node is the same node object, so hovering it again would not re-show the handle.\n // The plugin's `hideDragHandle` meta clears the target.\n const resetDragHandle = useCallback(() => {\n if (editor.isDestroyed) return\n editor.view.dispatch(editor.state.tr.setMeta('hideDragHandle', true).setMeta('addToHistory', false))\n }, [editor])\n\n // The plugin puts the handle's right edge on the target block's left edge. The hover handle is hidden where the block\n // has a handle of its own: the kind icon of a composite, or, with `blocks.dragHandle: 'always'`, the permanent\n // handles. Hiding keeps its layout, which the targeting rules below measure.\n const alwaysHandles = settings.blocks.dragHandle === 'always'\n const hoverHandleHidden = alwaysHandles || targetHasBlockTypeIcon\n const trackDragTarget = useCallback(({ node, pos }: { node: Node | null, pos: number }) => {\n if (node) {\n clearTimeout(track.clearTimer)\n setHoverTarget({ node, pos })\n }\n else {\n scheduleHoverClear()\n }\n const dom = node ? editor.view.nodeDOM(pos) : null\n track.dom = dom instanceof HTMLElement ? dom : null\n setTargetHasBlockTypeIcon(track.dom ? hasBlockTypeIcon(track.dom) : false)\n }, [editor, track, scheduleHoverClear])\n\n // The plugin re-registers when its configuration changes: both objects below are made once and read `track`.\n const dragHandlePosition = useMemo<DragHandleProps['computePositionConfig']>(() => ({\n // The plugin aligns the handle's top with the block's top, which sits above the middle of the block's first text\n // line: `firstLineCenterShift` moves the handle's centre to that line's centre.\n middleware: [\n {\n name: 'firstLineCenter',\n fn: ({ x, y, elements, rects }) => ({\n x,\n y: track.dom ? y + firstLineCenterShift(track.dom, elements.reference.getBoundingClientRect().top, rects.floating.height) : y,\n }),\n },\n ],\n }), [track])\n\n // Targeting among nested blocks, without the plugin's default rules (they target list items). `outerBlock` (a\n // deduction of 1000, the base score, excludes a node): only the blocks of `outerBlocksAt` the hovered position are\n // targets, so a list item or a quote paragraph targets its list or quote, and a Typed block's chrome its Typed block.\n // `reachTarget`: see `pointerReachesTarget`.\n // `ownGutter`: a nested block is targeted only from its handle column rightwards; further left its ancestors are, so\n // on any row the gutter is partitioned by the handle columns of the blocks nested there. The plugin's edge detection\n // is off: its left strip is this partition, its top strip would hand the handle to the parent on the block's first\n // line, where the handle sits.\n const dragHandleNested = useMemo<DragHandleProps['nested']>(() => {\n // Left of a block, ProseMirror resolves the pointer to the position before the block, so the plugin only considers\n // the block's ancestors there: the target's own handle column would hand the handle to its parent before the pointer\n // reaches it. This keeps the target while the pointer is between its handle and its box, over its whole height\n // including the gaps to its neighbours, and in those gaps themselves (which resolve to the parent as well). The rule\n // then excludes every candidate, and the plugin keeps its target when the detection yields none. Inside the target's\n // own box the rule is off, so its descendants are still targeted.\n const pointerReachesTarget = (): boolean => {\n const { pointer, dom } = track\n if (!pointer || !dom?.isConnected) return false\n const rect = dom.getBoundingClientRect()\n const { x, y } = pointer\n if (x < handleLeftOf(dom, handleWidth()) || x >= rect.right) return false\n if (y < (laidOutSibling(dom, 'previous')?.bottom ?? rect.top)) return false\n if (y >= (laidOutSibling(dom, 'next')?.top ?? rect.bottom)) return false\n return x < rect.left || y < rect.top || y >= rect.bottom\n }\n return {\n edgeDetection: 'none',\n defaultRules: false,\n rules: [\n outerBlockRule,\n { id: 'reachTarget', evaluate: () => pointerReachesTarget() ? 1000 : 0 },\n {\n id: 'ownGutter',\n evaluate: ({ pos, depth, view }) => {\n const { pointer } = track\n if (depth < 2 || !pointer) return 0\n const dom = view.nodeDOM(pos)\n return dom instanceof HTMLElement && pointer.x < handleLeftOf(dom, handleWidth()) ? 1000 : 0\n },\n },\n ],\n }\n }, [track])\n\n return (\n <>\n {host && createPortal(\n <>\n {surfaces.hover && (\n <BlockActionsOverlay editor={editor} target={hoverBarTarget} host={host} actions={actions} surface=\"hover\" onHover={onOverlayHover} />\n )}\n {surfaces.toolbar && (\n <BlockActionsOverlay editor={editor} target={selectedTarget} host={host} actions={actions} surface=\"toolbar\" persistent />\n )}\n {alwaysHandles && <BlockHandles editor={editor} host={host} />}\n </>,\n host,\n )}\n <DragHandle\n editor={editor}\n onElementDragEnd={resetDragHandle}\n onNodeChange={trackDragTarget}\n computePositionConfig={dragHandlePosition}\n nested={dragHandleNested}\n className={cn(\n 'flex size-6 cursor-grab items-center justify-center rounded text-muted-foreground hover:bg-muted hover:text-foreground data-[dragging=true]:cursor-grabbing',\n hoverHandleHidden && 'invisible! pointer-events-none!',\n )}\n >\n <span ref={handleContent} className=\"contents\">\n <Icon name=\"i-lucide-grip-vertical\" />\n </span>\n </DragHandle>\n </>\n )\n}\n\n// Nearest sibling with a layout box (a composite's hidden description/tags rows have none).\nfunction laidOutSibling(dom: Element, side: 'previous' | 'next'): DOMRect | null {\n for (let element = dom[`${side}ElementSibling`]; element; element = element[`${side}ElementSibling`]) {\n const rect = element.getBoundingClientRect()\n if (rect.height > 0) return rect\n }\n return null\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAwBA,SAAgB,QAAQ,EAAE,UAA8B;CAItD,MAAM,CAAC,MAAM,WAAW,SAA6B,IAAI;CACzD,MAAM,CAAC,aAAa,kBAAkB,SAA6B,IAAI;CACvE,MAAM,CAAC,wBAAwB,6BAA6B,SAAS,KAAK;CAC1E,MAAM,EAAE,aAAa,kBAAkB;CAGvC,MAAM,UAAU,cAAc,MAAM,CAAC,EAAE,gBAAgB,CAAC;CACxD,MAAM,WAAW,iBAAiB,MAAM;CAIxC,MAAM,GAAG,YAAY,YAAY,UAAkB,QAAQ,GAAG,CAAC;CAC/D,gBAAgB;EACd,MAAM,sBAAsB;GAAE,IAAI,iBAAiB,MAAM,CAAC,CAAC,SAAS,SAAS;EAAE;EAC/E,OAAO,GAAG,eAAe,aAAa;EACtC,aAAa;GAAE,OAAO,IAAI,eAAe,aAAa;EAAE;CAC1D,GAAG,CAAC,MAAM,CAAC;CACX,MAAM,iBAAiB,SAAS,UAAU,gBAAgB,MAAM,IAAI;CAEpE,MAAM,iBAAiB,eAAe,kBAAkB,UAAU,QAAQ,aAAa,cAAc,IAAI,OAAO;CAGhH,MAAM,QAAQ,OAAO;EACnB,gBAAgB;EAChB,YAAY,KAAA;EACZ,SAAS;EACT,KAAK;CACP,CAAC,CAAC,CAAC;CAEH,MAAM,gBAAgB,OAAwB,IAAI;CAClD,MAAM,oBAAoB,cAAc,SAAS,eAAe,eAAe;CAE/E,MAAM,qBAAqB,kBAAkB;EAC3C,aAAa,MAAM,UAAU;EAC7B,MAAM,aAAa,OAAO,iBAAiB;GACzC,IAAI,CAAC,MAAM,gBAAgB,eAAe,IAAI;EAChD,GAAG,GAAG;CACR,GAAG,CAAC,KAAK,CAAC;CAIV,gBAAgB;EACd,IAAI,OAAO,aAAa;EACxB,MAAM,MAAM,OAAO,KAAK;EACxB,QAAQ,IAAI,cAAc,IAAI,gBAAgB,IAAI;EAElD,MAAM,kBAAkB;GACtB,aAAa,MAAM,UAAU;GAC7B,eAAe,IAAI;EACrB;EAGA,MAAM,eAAe,UAAsB;GACzC,MAAM,UAAU;IAAE,GAAG,MAAM;IAAS,GAAG,MAAM;GAAQ;EACvD;EACA,IAAI,iBAAiB,WAAW,SAAS;EACzC,IAAI,iBAAiB,aAAa,WAAW;EAC7C,aAAa;GACX,aAAa,MAAM,UAAU;GAC7B,IAAI,oBAAoB,WAAW,SAAS;GAC5C,IAAI,oBAAoB,aAAa,WAAW;GAChD,QAAQ,IAAI;EACd;CACF,GAAG,CAAC,QAAQ,KAAK,CAAC;CAElB,MAAM,iBAAiB,aAAa,YAAqB;EACvD,MAAM,iBAAiB;EACvB,IAAI,CAAC,SAAS,mBAAmB;CACnC,GAAG,CAAC,OAAO,kBAAkB,CAAC;CAK9B,MAAM,kBAAkB,kBAAkB;EACxC,IAAI,OAAO,aAAa;EACxB,OAAO,KAAK,SAAS,OAAO,MAAM,GAAG,QAAQ,kBAAkB,IAAI,CAAC,CAAC,QAAQ,gBAAgB,KAAK,CAAC;CACrG,GAAG,CAAC,MAAM,CAAC;CAKX,MAAM,gBAAgB,SAAS,OAAO,eAAe;CACrD,MAAM,oBAAoB,iBAAiB;CAC3C,MAAM,kBAAkB,aAAa,EAAE,MAAM,UAA8C;EACzF,IAAI,MAAM;GACR,aAAa,MAAM,UAAU;GAC7B,eAAe;IAAE;IAAM;GAAI,CAAC;EAC9B,OAEE,mBAAmB;EAErB,MAAM,MAAM,OAAO,OAAO,KAAK,QAAQ,GAAG,IAAI;EAC9C,MAAM,MAAM,eAAe,cAAc,MAAM;EAC/C,0BAA0B,MAAM,MAAM,iBAAiB,MAAM,GAAG,IAAI,KAAK;CAC3E,GAAG;EAAC;EAAQ;EAAO;CAAkB,CAAC;CAGtC,MAAM,qBAAqB,eAAyD,EAGlF,YAAY,CACV;EACE,MAAM;EACN,KAAK,EAAE,GAAG,GAAG,UAAU,aAAa;GAClC;GACA,GAAG,MAAM,MAAM,IAAI,qBAAqB,MAAM,KAAK,SAAS,UAAU,sBAAsB,CAAC,CAAC,KAAK,MAAM,SAAS,MAAM,IAAI;EAC9H;CACF,CACF,EACF,IAAI,CAAC,KAAK,CAAC;CAUX,MAAM,mBAAmB,cAAyC;EAOhE,MAAM,6BAAsC;GAC1C,MAAM,EAAE,SAAS,QAAQ;GACzB,IAAI,CAAC,WAAW,CAAC,KAAK,aAAa,OAAO;GAC1C,MAAM,OAAO,IAAI,sBAAsB;GACvC,MAAM,EAAE,GAAG,MAAM;GACjB,IAAI,IAAI,aAAa,KAAK,YAAY,CAAC,KAAK,KAAK,KAAK,OAAO,OAAO;GACpE,IAAI,KAAK,eAAe,KAAK,UAAU,CAAC,EAAE,UAAU,KAAK,MAAM,OAAO;GACtE,IAAI,MAAM,eAAe,KAAK,MAAM,CAAC,EAAE,OAAO,KAAK,SAAS,OAAO;GACnE,OAAO,IAAI,KAAK,QAAQ,IAAI,KAAK,OAAO,KAAK,KAAK;EACpD;EACA,OAAO;GACL,eAAe;GACf,cAAc;GACd,OAAO;IACL;IACA;KAAE,IAAI;KAAe,gBAAgB,qBAAqB,IAAI,MAAO;IAAE;IACvE;KACE,IAAI;KACJ,WAAW,EAAE,KAAK,OAAO,WAAW;MAClC,MAAM,EAAE,YAAY;MACpB,IAAI,QAAQ,KAAK,CAAC,SAAS,OAAO;MAClC,MAAM,MAAM,KAAK,QAAQ,GAAG;MAC5B,OAAO,eAAe,eAAe,QAAQ,IAAI,aAAa,KAAK,YAAY,CAAC,IAAI,MAAO;KAC7F;IACF;GACF;EACF;CACF,GAAG,CAAC,KAAK,CAAC;CAEV,OACE,qBAAA,YAAA,EAAA,UAAA,CACG,QAAQ,aACP,qBAAA,YAAA,EAAA,UAAA;EACG,SAAS,SACR,oBAAC,qBAAD;GAA6B;GAAQ,QAAQ;GAAsB;GAAe;GAAS,SAAQ;GAAQ,SAAS;EAAiB,CAAA;EAEtI,SAAS,WACR,oBAAC,qBAAD;GAA6B;GAAQ,QAAQ;GAAsB;GAAe;GAAS,SAAQ;GAAU,YAAA;EAAY,CAAA;EAE1H,iBAAiB,oBAAC,cAAD;GAAsB;GAAc;EAAO,CAAA;CAC7D,EAAA,CAAA,GACF,IACF,GACA,oBAAC,YAAD;EACU;EACR,kBAAkB;EAClB,cAAc;EACd,uBAAuB;EACvB,QAAQ;EACR,WAAW,GACT,+JACA,qBAAqB,iCACvB;EAEA,UAAA,oBAAC,QAAD;GAAM,KAAK;GAAe,WAAU;GAClC,UAAA,oBAAC,MAAD,EAAM,MAAK,yBAA0B,CAAA;EACjC,CAAA;CACI,CAAA,CACZ,EAAA,CAAA;AAEN;AAGA,SAAS,eAAe,KAAc,MAA2C;CAC/E,KAAK,IAAI,UAAU,IAAI,GAAG,KAAK,kBAAkB,SAAS,UAAU,QAAQ,GAAG,KAAK,kBAAkB;EACpG,MAAM,OAAO,QAAQ,sBAAsB;EAC3C,IAAI,KAAK,SAAS,GAAG,OAAO;CAC9B;CACA,OAAO;AACT"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { editorEntryOf } from "../../core/editor-ui.js";
|
|
2
1
|
import { newBlockId } from "../../core/schema/block-ids.js";
|
|
2
|
+
import { editorEntryOf } from "../../core/editor-ui.js";
|
|
3
3
|
import { createStore } from "../../core/store.js";
|
|
4
4
|
import { anchorResolverOf, releaseRanges, resolveRange } from "../../core/doc-anchors.js";
|
|
5
5
|
import { cancelCommentDraft, commentsDoc, commentsKey, commentsUser, setActiveComment, startCommentDraft } from "./comments-plugin.js";
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Translate } from "../../i18n/index.js";
|
|
2
2
|
import { Notifier } from "../../core/notify.js";
|
|
3
3
|
import "../../core/command-types.js";
|
|
4
|
+
import "./block-types.js";
|
|
4
5
|
import { Extension } from "@tiptap/core";
|
|
5
6
|
import { Node as Node$1 } from "@tiptap/pm/model";
|
|
6
7
|
//#region src/features/composites/accepted-children.d.ts
|
|
@@ -11,11 +12,11 @@ export interface AcceptedChildrenOptions {
|
|
|
11
12
|
t: Translate;
|
|
12
13
|
}
|
|
13
14
|
/**
|
|
14
|
-
* Enforces the kinds' accepted children (`
|
|
15
|
-
* leaves the document with more
|
|
16
|
-
* drag, „In
|
|
15
|
+
* Enforces the kinds' accepted children (`BlockType.accepts`) for every local edit at one place: a transaction that
|
|
16
|
+
* leaves the document with more Typed blocks nested in a Typed block that does not accept them than before is refused — block
|
|
17
|
+
* drag, „In Block umwandeln“, paste, AI inserts and review acceptance, `moveBlockInto` — and the user is told why.
|
|
17
18
|
* Existing violations stay: transactions that add none (typing, undoing) pass, and so do collaboration replays, undo/redo
|
|
18
|
-
* and loading a whole document. Client-only, no schema: kinds are read from the editor (`
|
|
19
|
+
* and loading a whole document. Client-only, no schema: kinds are read from the editor (`blockTypesOf`).
|
|
19
20
|
*/
|
|
20
21
|
export declare const AcceptedChildren: Extension<AcceptedChildrenOptions, any>;
|
|
21
22
|
//#endregion
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createTranslator } from "../../i18n/index.js";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { acceptsChild, blockTypeOf } from "./block-types.js";
|
|
3
|
+
import { blockTypesOf } from "./nodes.js";
|
|
4
4
|
import { Extension } from "@tiptap/core";
|
|
5
5
|
import { Plugin, PluginKey } from "@tiptap/pm/state";
|
|
6
6
|
import { AddMarkStep, AttrStep, RemoveMarkStep, ReplaceStep } from "@tiptap/pm/transform";
|
|
@@ -8,19 +8,19 @@ import { AddMarkStep, AttrStep, RemoveMarkStep, ReplaceStep } from "@tiptap/pm/t
|
|
|
8
8
|
/** The short sentence for a refused nesting, naming both kinds by label (German: „Notiz nimmt keine Aufgabe auf.“). */
|
|
9
9
|
function nestingReason(kinds, parent, child, t) {
|
|
10
10
|
return t("composites.nesting.refused", {
|
|
11
|
-
parent:
|
|
12
|
-
child:
|
|
11
|
+
parent: blockTypeOf(kinds, parent).label,
|
|
12
|
+
child: blockTypeOf(kinds, child).label
|
|
13
13
|
});
|
|
14
14
|
}
|
|
15
15
|
/**
|
|
16
|
-
* The
|
|
17
|
-
* directly inside it (not those nested in another
|
|
16
|
+
* The Typed blocks of `node`'s subtree, outermost first: `node` itself when it is a Typed block, otherwise the Typed blocks
|
|
17
|
+
* directly inside it (not those nested in another Typed block).
|
|
18
18
|
*/
|
|
19
19
|
function outermostComposites(node) {
|
|
20
|
-
if (node.type.name === "
|
|
20
|
+
if (node.type.name === "typedBlock") return [node];
|
|
21
21
|
const found = [];
|
|
22
22
|
node.descendants((child) => {
|
|
23
|
-
if (child.type.name === "
|
|
23
|
+
if (child.type.name === "typedBlock") {
|
|
24
24
|
found.push(child);
|
|
25
25
|
return false;
|
|
26
26
|
}
|
|
@@ -29,17 +29,17 @@ function outermostComposites(node) {
|
|
|
29
29
|
return found;
|
|
30
30
|
}
|
|
31
31
|
/**
|
|
32
|
-
* Every
|
|
33
|
-
* its
|
|
32
|
+
* Every Typed block in `doc` whose nearest Typed block ancestor (quotes and lists in between do not count) does not accept
|
|
33
|
+
* its Block type, in document order. Top-level Typed blocks have no parent and never violate.
|
|
34
34
|
*/
|
|
35
35
|
function nestingViolations(doc, kinds) {
|
|
36
36
|
const found = [];
|
|
37
37
|
function walk(node, parentKind) {
|
|
38
38
|
node.forEach((child) => {
|
|
39
39
|
if (child.isTextblock || child.isLeaf) return;
|
|
40
|
-
if (child.type.name === "
|
|
41
|
-
const kind = String(child.attrs.
|
|
42
|
-
if (parentKind !== null && !
|
|
40
|
+
if (child.type.name === "typedBlock") {
|
|
41
|
+
const kind = String(child.attrs.blockType);
|
|
42
|
+
if (parentKind !== null && !acceptsChild(kinds, parentKind, kind)) found.push({
|
|
43
43
|
parent: parentKind,
|
|
44
44
|
child: kind
|
|
45
45
|
});
|
|
@@ -51,24 +51,24 @@ function nestingViolations(doc, kinds) {
|
|
|
51
51
|
return found;
|
|
52
52
|
}
|
|
53
53
|
/**
|
|
54
|
-
* The insert guard of the composites feature: a
|
|
55
|
-
* nearest
|
|
56
|
-
* accepts that kind, or where there is none. Uses `
|
|
54
|
+
* The insert guard of the composites feature: a Typed block of Block type `creates.attrs.blockType` may be created only where the
|
|
55
|
+
* nearest Typed block around the insertion point (`$parent` and outward; quotes and lists in between do not count)
|
|
56
|
+
* accepts that kind, or where there is none. Uses `acceptsChild`, the rule `AcceptedChildren` enforces on transactions
|
|
57
57
|
* through `nestingViolations`, so the `/` menu and toolbar offer exactly what an edit would not be refused for.
|
|
58
58
|
*/
|
|
59
59
|
const compositeInsertGuard = (editor, $parent, creates) => {
|
|
60
|
-
const child = creates.attrs?.
|
|
61
|
-
if (creates.type !== "
|
|
60
|
+
const child = creates.attrs?.blockType;
|
|
61
|
+
if (creates.type !== "typedBlock" || typeof child !== "string") return true;
|
|
62
62
|
for (let depth = $parent.depth; depth >= 0; depth--) {
|
|
63
63
|
const node = $parent.node(depth);
|
|
64
|
-
if (node.type.name === "
|
|
64
|
+
if (node.type.name === "typedBlock") return acceptsChild(blockTypesOf(editor), String(node.attrs.blockType), child);
|
|
65
65
|
}
|
|
66
66
|
return true;
|
|
67
67
|
};
|
|
68
|
-
/** A step that cannot change which
|
|
68
|
+
/** A step that cannot change which Typed block sits in which: marks, text typed or deleted inside one textblock, attributes other than `blockType`. */
|
|
69
69
|
function keepsNesting(step, before) {
|
|
70
70
|
if (step instanceof AddMarkStep || step instanceof RemoveMarkStep) return true;
|
|
71
|
-
if (step instanceof AttrStep) return step.attr !== "
|
|
71
|
+
if (step instanceof AttrStep) return step.attr !== "blockType";
|
|
72
72
|
if (step instanceof ReplaceStep) {
|
|
73
73
|
const { slice } = step;
|
|
74
74
|
if (slice.openStart !== 0 || slice.openEnd !== 0 || !slice.content.content.every((child) => child.isInline)) return false;
|
|
@@ -97,11 +97,11 @@ function addedViolation(before, after) {
|
|
|
97
97
|
return after[0];
|
|
98
98
|
}
|
|
99
99
|
/**
|
|
100
|
-
* Enforces the kinds' accepted children (`
|
|
101
|
-
* leaves the document with more
|
|
102
|
-
* drag, „In
|
|
100
|
+
* Enforces the kinds' accepted children (`BlockType.accepts`) for every local edit at one place: a transaction that
|
|
101
|
+
* leaves the document with more Typed blocks nested in a Typed block that does not accept them than before is refused — block
|
|
102
|
+
* drag, „In Block umwandeln“, paste, AI inserts and review acceptance, `moveBlockInto` — and the user is told why.
|
|
103
103
|
* Existing violations stay: transactions that add none (typing, undoing) pass, and so do collaboration replays, undo/redo
|
|
104
|
-
* and loading a whole document. Client-only, no schema: kinds are read from the editor (`
|
|
104
|
+
* and loading a whole document. Client-only, no schema: kinds are read from the editor (`blockTypesOf`).
|
|
105
105
|
*/
|
|
106
106
|
const AcceptedChildren = Extension.create({
|
|
107
107
|
name: "acceptedChildren",
|
|
@@ -118,7 +118,7 @@ const AcceptedChildren = Extension.create({
|
|
|
118
118
|
if (!tr.docChanged || isReplay(tr)) return true;
|
|
119
119
|
if (tr.steps.some((step, index) => step instanceof ReplaceStep && step.from === 0 && step.to === tr.docs[index].content.size)) return true;
|
|
120
120
|
if (tr.steps.every((step, index) => keepsNesting(step, tr.docs[index]))) return true;
|
|
121
|
-
const kinds =
|
|
121
|
+
const kinds = blockTypesOf(editor);
|
|
122
122
|
const before = nestingViolations(state.doc, kinds);
|
|
123
123
|
const after = nestingViolations(tr.doc, kinds);
|
|
124
124
|
if (after.length <= before.length) return true;
|