@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
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-model-profiles.js","names":[],"sources":["../../../../src/features/ai/react/use-model-profiles.ts"],"sourcesContent":["import { useMemo } from 'react'\nimport type {
|
|
1
|
+
{"version":3,"file":"use-model-profiles.js","names":[],"sources":["../../../../src/features/ai/react/use-model-profiles.ts"],"sourcesContent":["import { useMemo } from 'react'\nimport type { ModelRole } from '../../../settings'\nimport { useEditorContext } from '../../../react/context'\nimport { useStore } from '../../../react/use-store'\nimport { modelProfiles } from '../model-profiles'\nimport type { ModelProfile, ModelRef, UserModelProfile } from '../protocol'\n\n/**\n * Model profiles the AI features run on, shared by all editors of the app (see `modelProfiles`): Model presets plus\n * the user profiles of this browser. Re-renders when either or the settings' Model role assignment changes.\n */\nexport function useModelProfiles(): {\n presets: ModelProfile[]\n userProfiles: UserModelProfile[]\n profiles: ModelProfile[]\n slotProfile: (slot: ModelRole) => ModelProfile | undefined\n modelRef: (slot: ModelRole) => ModelRef\n saveUserProfile: (profile: UserModelProfile) => void\n removeUserProfile: (id: string) => void\n} {\n const app = useEditorContext()\n const model = modelProfiles(app)\n // `slotProfile`/`modelRef` read the settings' Model role assignment: re-render when it changes.\n useStore(app.settings)\n const presets = useStore(model.presets)\n const userProfiles = useStore(model.userProfiles)\n // `profiles()` is derived from both stores: recomputed when either changed.\n const profiles = useMemo(() => model.profiles(), [model, presets, userProfiles])\n return {\n presets,\n userProfiles,\n profiles,\n slotProfile: model.slotProfile,\n modelRef: model.modelRef,\n saveUserProfile: model.saveUserProfile,\n removeUserProfile: model.removeUserProfile,\n }\n}\n"],"mappings":";;;;;;;;;AAWA,SAAgB,mBAQd;CACA,MAAM,MAAM,iBAAiB;CAC7B,MAAM,QAAQ,cAAc,GAAG;CAE/B,SAAS,IAAI,QAAQ;CACrB,MAAM,UAAU,SAAS,MAAM,OAAO;CACtC,MAAM,eAAe,SAAS,MAAM,YAAY;CAGhD,OAAO;EACL;EACA;EACA,UAJe,cAAc,MAAM,SAAS,GAAG;GAAC;GAAO;GAAS;EAAY,CAIrE;EACP,aAAa,MAAM;EACnB,UAAU,MAAM;EAChB,iBAAiB,MAAM;EACvB,mBAAmB,MAAM;CAC3B;AACF"}
|
|
@@ -3,7 +3,7 @@ import { Editor } from "@tiptap/core";
|
|
|
3
3
|
import { MaybeRefOrGetter } from "vue";
|
|
4
4
|
//#region src/features/ai/use-ai-assistant.d.ts
|
|
5
5
|
/**
|
|
6
|
-
* Streams the backend's `generate` into Vue refs on the task's
|
|
6
|
+
* Streams the backend's `generate` into Vue refs on the task's Model role: a thin hook over `createAiAssistant`. Call it
|
|
7
7
|
* during component setup (it injects the editor context); the request stops with the component's scope. The 429 notice
|
|
8
8
|
* goes to `editor`'s surface (else the app's notifier).
|
|
9
9
|
*/
|
|
@@ -6,7 +6,7 @@ import { useStoreRef } from "../../vue/store-ref.js";
|
|
|
6
6
|
import { computed, getCurrentScope, onScopeDispose } from "vue";
|
|
7
7
|
//#region src/features/ai/use-ai-assistant.ts
|
|
8
8
|
/**
|
|
9
|
-
* Streams the backend's `generate` into Vue refs on the task's
|
|
9
|
+
* Streams the backend's `generate` into Vue refs on the task's Model role: a thin hook over `createAiAssistant`. Call it
|
|
10
10
|
* during component setup (it injects the editor context); the request stops with the component's scope. The 429 notice
|
|
11
11
|
* goes to `editor`'s surface (else the app's notifier).
|
|
12
12
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-ai-assistant.js","names":[],"sources":["../../../src/features/ai/use-ai-assistant.ts"],"sourcesContent":["import type { Editor } from '@tiptap/core'\nimport { computed, getCurrentScope, type MaybeRefOrGetter, onScopeDispose } from 'vue'\nimport { useEditorContext } from '../../vue/context'\nimport { useStoreRef } from '../../vue/store-ref'\nimport { useNotifier } from '../../vue/use-notifier'\nimport { createAiAssistant } from './assistant'\nimport { modelProfiles } from './model-profiles'\n\nexport type { AiRunBody, AiStatus } from './assistant'\n\n/**\n * Streams the backend's `generate` into Vue refs on the task's
|
|
1
|
+
{"version":3,"file":"use-ai-assistant.js","names":[],"sources":["../../../src/features/ai/use-ai-assistant.ts"],"sourcesContent":["import type { Editor } from '@tiptap/core'\nimport { computed, getCurrentScope, type MaybeRefOrGetter, onScopeDispose } from 'vue'\nimport { useEditorContext } from '../../vue/context'\nimport { useStoreRef } from '../../vue/store-ref'\nimport { useNotifier } from '../../vue/use-notifier'\nimport { createAiAssistant } from './assistant'\nimport { modelProfiles } from './model-profiles'\n\nexport type { AiRunBody, AiStatus } from './assistant'\n\n/**\n * Streams the backend's `generate` into Vue refs on the task's Model role: a thin hook over `createAiAssistant`. Call it\n * during component setup (it injects the editor context); the request stops with the component's scope. The 429 notice\n * goes to `editor`'s surface (else the app's notifier).\n */\nexport function useAiAssistant(editor?: MaybeRefOrGetter<Editor | undefined>) {\n const context = useEditorContext()\n const assistant = createAiAssistant({ ai: context.backend.ai, modelRef: modelProfiles(context).modelRef, notify: useNotifier(editor), t: context.t })\n const snapshot = useStoreRef(assistant.state)\n if (getCurrentScope()) onScopeDispose(assistant.abort)\n const { run, abort, reset, clearError } = assistant\n return {\n /** The underlying model, for flows that act on it (`createAiSidebarFlow`). */\n model: assistant,\n status: computed(() => snapshot.value.status),\n output: computed(() => snapshot.value.output),\n error: computed(() => snapshot.value.error),\n run,\n abort,\n reset,\n clearError,\n }\n}\n"],"mappings":";;;;;;;;;;;;AAeA,SAAgB,eAAe,QAA+C;CAC5E,MAAM,UAAU,iBAAiB;CACjC,MAAM,YAAY,kBAAkB;EAAE,IAAI,QAAQ,QAAQ;EAAI,UAAU,cAAc,OAAO,CAAC,CAAC;EAAU,QAAQ,YAAY,MAAM;EAAG,GAAG,QAAQ;CAAE,CAAC;CACpJ,MAAM,WAAW,YAAY,UAAU,KAAK;CAC5C,IAAI,gBAAgB,GAAG,eAAe,UAAU,KAAK;CACrD,MAAM,EAAE,KAAK,OAAO,OAAO,eAAe;CAC1C,OAAO;;EAEL,OAAO;EACP,QAAQ,eAAe,SAAS,MAAM,MAAM;EAC5C,QAAQ,eAAe,SAAS,MAAM,MAAM;EAC5C,OAAO,eAAe,SAAS,MAAM,KAAK;EAC1C;EACA;EACA;EACA;CACF;AACF"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ModelRole } from "../../settings/values.js";
|
|
2
2
|
import "../../settings/index.js";
|
|
3
3
|
import { ModelProfile, ModelRef } from "../../core/backend-types.js";
|
|
4
4
|
import { UserModelProfile } from "./protocol/models.js";
|
|
@@ -7,7 +7,7 @@ import { ComputedRef, Ref } from "vue";
|
|
|
7
7
|
//#region src/features/ai/use-model-profiles.d.ts
|
|
8
8
|
/**
|
|
9
9
|
* Model profiles the AI features run on, as Vue refs: a thin hook over the app's `modelProfiles` model (see there for
|
|
10
|
-
* the sources). `slotProfile`/`modelRef` read the
|
|
10
|
+
* the sources). `slotProfile`/`modelRef` read the Model role settings, so calling them inside `computed`/templates tracks
|
|
11
11
|
* both the profiles and the settings. Call it during component setup (it injects the app's editor context); the returned
|
|
12
12
|
* functions work anywhere afterwards.
|
|
13
13
|
*/
|
|
@@ -15,8 +15,8 @@ export declare function useModelProfiles(): {
|
|
|
15
15
|
presets: Readonly<Ref<ModelProfile[]>>;
|
|
16
16
|
userProfiles: Readonly<Ref<UserModelProfile[]>>;
|
|
17
17
|
profiles: ComputedRef<ModelProfile[]>;
|
|
18
|
-
slotProfile: (slot:
|
|
19
|
-
modelRef: (slot:
|
|
18
|
+
slotProfile: (slot: ModelRole) => ModelProfile | undefined;
|
|
19
|
+
modelRef: (slot: ModelRole) => ModelRef;
|
|
20
20
|
saveUserProfile: (profile: UserModelProfile) => void;
|
|
21
21
|
removeUserProfile: (id: string) => void;
|
|
22
22
|
};
|
|
@@ -5,7 +5,7 @@ import { computed } from "vue";
|
|
|
5
5
|
//#region src/features/ai/use-model-profiles.ts
|
|
6
6
|
/**
|
|
7
7
|
* Model profiles the AI features run on, as Vue refs: a thin hook over the app's `modelProfiles` model (see there for
|
|
8
|
-
* the sources). `slotProfile`/`modelRef` read the
|
|
8
|
+
* the sources). `slotProfile`/`modelRef` read the Model role settings, so calling them inside `computed`/templates tracks
|
|
9
9
|
* both the profiles and the settings. Call it during component setup (it injects the app's editor context); the returned
|
|
10
10
|
* functions work anywhere afterwards.
|
|
11
11
|
*/
|
|
@@ -16,7 +16,7 @@ function useModelProfiles() {
|
|
|
16
16
|
const presets = useStoreRef(model.presets);
|
|
17
17
|
const userProfiles = useStoreRef(model.userProfiles);
|
|
18
18
|
const settings = useStoreRef(context.settings);
|
|
19
|
-
/** Changes with the profiles and with the
|
|
19
|
+
/** Changes with the profiles and with the Model role settings: `slotProfile` depends on both. */
|
|
20
20
|
const track = () => {
|
|
21
21
|
presets.value;
|
|
22
22
|
userProfiles.value;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-model-profiles.js","names":[],"sources":["../../../src/features/ai/use-model-profiles.ts"],"sourcesContent":["import { computed, type ComputedRef, type Ref } from 'vue'\nimport { useEditorContext } from '../../vue/context'\nimport { useStoreRef } from '../../vue/store-ref'\nimport type {
|
|
1
|
+
{"version":3,"file":"use-model-profiles.js","names":[],"sources":["../../../src/features/ai/use-model-profiles.ts"],"sourcesContent":["import { computed, type ComputedRef, type Ref } from 'vue'\nimport { useEditorContext } from '../../vue/context'\nimport { useStoreRef } from '../../vue/store-ref'\nimport type { ModelRole } from '../../settings'\nimport { modelProfiles } from './model-profiles'\nimport type { ModelProfile, ModelRef, UserModelProfile } from './protocol'\n\n/**\n * Model profiles the AI features run on, as Vue refs: a thin hook over the app's `modelProfiles` model (see there for\n * the sources). `slotProfile`/`modelRef` read the Model role settings, so calling them inside `computed`/templates tracks\n * both the profiles and the settings. Call it during component setup (it injects the app's editor context); the returned\n * functions work anywhere afterwards.\n */\nexport function useModelProfiles(): {\n presets: Readonly<Ref<ModelProfile[]>>\n userProfiles: Readonly<Ref<UserModelProfile[]>>\n profiles: ComputedRef<ModelProfile[]>\n slotProfile: (slot: ModelRole) => ModelProfile | undefined\n modelRef: (slot: ModelRole) => ModelRef\n saveUserProfile: (profile: UserModelProfile) => void\n removeUserProfile: (id: string) => void\n} {\n const context = useEditorContext()\n context.load()\n const model = modelProfiles(context)\n\n const presets = useStoreRef(model.presets)\n const userProfiles = useStoreRef(model.userProfiles)\n const settings = useStoreRef(context.settings)\n /** Changes with the profiles and with the Model role settings: `slotProfile` depends on both. */\n const track = () => {\n void presets.value\n void userProfiles.value\n void settings.value\n }\n\n const profiles = computed<ModelProfile[]>(() => {\n track()\n return model.profiles()\n })\n const slotProfile = (slot: ModelRole): ModelProfile | undefined => {\n track()\n return model.slotProfile(slot)\n }\n const modelRef = (slot: ModelRole): ModelRef => {\n track()\n return model.modelRef(slot)\n }\n\n return { presets, userProfiles, profiles, slotProfile, modelRef, saveUserProfile: model.saveUserProfile, removeUserProfile: model.removeUserProfile }\n}\n"],"mappings":";;;;;;;;;;;AAaA,SAAgB,mBAQd;CACA,MAAM,UAAU,iBAAiB;CACjC,QAAQ,KAAK;CACb,MAAM,QAAQ,cAAc,OAAO;CAEnC,MAAM,UAAU,YAAY,MAAM,OAAO;CACzC,MAAM,eAAe,YAAY,MAAM,YAAY;CACnD,MAAM,WAAW,YAAY,QAAQ,QAAQ;;CAE7C,MAAM,cAAc;EAClB,QAAa;EACb,aAAkB;EAClB,SAAc;CAChB;CAEA,MAAM,WAAW,eAA+B;EAC9C,MAAM;EACN,OAAO,MAAM,SAAS;CACxB,CAAC;CACD,MAAM,eAAe,SAA8C;EACjE,MAAM;EACN,OAAO,MAAM,YAAY,IAAI;CAC/B;CACA,MAAM,YAAY,SAA8B;EAC9C,MAAM;EACN,OAAO,MAAM,SAAS,IAAI;CAC5B;CAEA,OAAO;EAAE;EAAS;EAAc;EAAU;EAAa;EAAU,iBAAiB,MAAM;EAAiB,mBAAmB,MAAM;CAAkB;AACtJ"}
|
|
@@ -20,13 +20,17 @@ export declare function actionSurfacesOf(editor: Editor): Record<BlockActionSurf
|
|
|
20
20
|
export declare function sameBlock(editor: Editor, hovered: BlockTarget, selected: BlockTarget): boolean;
|
|
21
21
|
/**
|
|
22
22
|
* The actions `target` offers on `surface`: those whose `placement` (default both) includes it, whose `ability` the
|
|
23
|
-
* block has and whose `isVisible` does not refuse. A `menu` action only when its menu has items.
|
|
23
|
+
* block has, whose `requires` capabilities the block has all of (`capabilitiesOf`), whose `blockTypes` include its Block type and whose `isVisible` does not refuse. A `menu` action only when its menu has items.
|
|
24
|
+
* On the toolbar an action with `target: 'typedBlock'` is checked against, and runs with, the Typed block around `target`
|
|
25
|
+
* (`typedBlockAround`) instead of `target`; it is absent when none encloses `target`.
|
|
24
26
|
*/
|
|
25
27
|
export declare function blockActionsFor(editor: Editor, target: BlockTarget, actions: readonly BlockAction[], surface: BlockActionSurface): BlockActionEntry[];
|
|
26
28
|
/**
|
|
27
|
-
* The block holding the selection, for the toolbar surface: the
|
|
28
|
-
* block around the
|
|
29
|
-
*
|
|
29
|
+
* The block holding the selection, for the toolbar surface: `outerBlockAt` the selection start, or, for a node
|
|
30
|
+
* selection, the block around the selected node (the selected node itself when it sits directly in a block container).
|
|
31
|
+
* A caret in a list item thus addresses the list, one in a quote the quote, one in a paragraph of a Typed block the
|
|
32
|
+
* paragraph, one in Typed block chrome the Typed block. Null when the editor is not editable, when the selection spans
|
|
33
|
+
* several top-level blocks, or when it sits outside any block.
|
|
30
34
|
*/
|
|
31
35
|
export declare function selectedBlockOf(editor: Editor): BlockTarget | null;
|
|
32
36
|
/**
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { abilitiesAt } from "../../core/abilities.js";
|
|
2
|
-
import { editorEntryOf } from "../../core/editor-ui.js";
|
|
3
2
|
import { isChromeNode } from "../../core/schema/node-flags.js";
|
|
3
|
+
import { blockTypeIdOf, capabilitiesOf } from "../../core/capabilities.js";
|
|
4
|
+
import { editorEntryOf } from "../../core/editor-ui.js";
|
|
5
|
+
import { outerBlockAt, typedBlockAround } from "./block-target.js";
|
|
4
6
|
import { NodeSelection } from "@tiptap/pm/state";
|
|
5
7
|
//#region src/features/block-ui/block-actions.ts
|
|
6
8
|
/** Hovering a composite's title/description/tags row addresses the composite itself. */
|
|
@@ -30,18 +32,40 @@ function sameBlock(editor, hovered, selected) {
|
|
|
30
32
|
}
|
|
31
33
|
/**
|
|
32
34
|
* The actions `target` offers on `surface`: those whose `placement` (default both) includes it, whose `ability` the
|
|
33
|
-
* block has and whose `isVisible` does not refuse. A `menu` action only when its menu has items.
|
|
35
|
+
* block has, whose `requires` capabilities the block has all of (`capabilitiesOf`), whose `blockTypes` include its Block type and whose `isVisible` does not refuse. A `menu` action only when its menu has items.
|
|
36
|
+
* On the toolbar an action with `target: 'typedBlock'` is checked against, and runs with, the Typed block around `target`
|
|
37
|
+
* (`typedBlockAround`) instead of `target`; it is absent when none encloses `target`.
|
|
34
38
|
*/
|
|
35
39
|
function blockActionsFor(editor, target, actions, surface) {
|
|
36
|
-
const
|
|
37
|
-
...
|
|
40
|
+
const contextOf = (at) => ({
|
|
41
|
+
...at,
|
|
38
42
|
editor,
|
|
39
|
-
abilities: abilitiesAt(editor,
|
|
40
|
-
};
|
|
43
|
+
abilities: abilitiesAt(editor, at.pos, at.node)
|
|
44
|
+
});
|
|
45
|
+
const blockCtx = contextOf(target);
|
|
46
|
+
let typedCtx;
|
|
41
47
|
return actions.flatMap((action) => {
|
|
42
48
|
const placement = action.placement ?? "both";
|
|
43
49
|
if (placement !== "both" && placement !== surface) return [];
|
|
44
|
-
|
|
50
|
+
let ctx = blockCtx;
|
|
51
|
+
if (surface === "toolbar" && action.target === "typedBlock") {
|
|
52
|
+
if (typedCtx === void 0) {
|
|
53
|
+
const typed = typedBlockAround(editor, target);
|
|
54
|
+
typedCtx = typed && (typed === target ? blockCtx : contextOf(typed));
|
|
55
|
+
}
|
|
56
|
+
if (!typedCtx) return [];
|
|
57
|
+
ctx = typedCtx;
|
|
58
|
+
}
|
|
59
|
+
if (action.ability && !ctx.abilities.has(action.ability)) return [];
|
|
60
|
+
if (action.requires?.length) {
|
|
61
|
+
const capabilities = capabilitiesOf(editor, ctx.node);
|
|
62
|
+
if (!action.requires.every((id) => capabilities.has(id))) return [];
|
|
63
|
+
}
|
|
64
|
+
if (action.blockTypes) {
|
|
65
|
+
const blockTypeId = blockTypeIdOf(ctx.node);
|
|
66
|
+
if (blockTypeId === null || !action.blockTypes.includes(blockTypeId)) return [];
|
|
67
|
+
}
|
|
68
|
+
if (action.isVisible?.(ctx) === false) return [];
|
|
45
69
|
if (!action.menu) return [{
|
|
46
70
|
action,
|
|
47
71
|
ctx
|
|
@@ -55,27 +79,19 @@ function blockActionsFor(editor, target, actions, surface) {
|
|
|
55
79
|
});
|
|
56
80
|
}
|
|
57
81
|
/**
|
|
58
|
-
* The block holding the selection, for the toolbar surface: the
|
|
59
|
-
* block around the
|
|
60
|
-
*
|
|
82
|
+
* The block holding the selection, for the toolbar surface: `outerBlockAt` the selection start, or, for a node
|
|
83
|
+
* selection, the block around the selected node (the selected node itself when it sits directly in a block container).
|
|
84
|
+
* A caret in a list item thus addresses the list, one in a quote the quote, one in a paragraph of a Typed block the
|
|
85
|
+
* paragraph, one in Typed block chrome the Typed block. Null when the editor is not editable, when the selection spans
|
|
86
|
+
* several top-level blocks, or when it sits outside any block.
|
|
61
87
|
*/
|
|
62
88
|
function selectedBlockOf(editor) {
|
|
63
89
|
if (editor.isDestroyed || !editor.isEditable) return null;
|
|
64
90
|
const { selection } = editor.state;
|
|
65
|
-
if (selection instanceof NodeSelection && selection.node.isBlock) return
|
|
66
|
-
node: selection.node,
|
|
67
|
-
pos: selection.from
|
|
68
|
-
});
|
|
91
|
+
if (selection instanceof NodeSelection && selection.node.isBlock) return outerBlockAt(editor.state.doc.resolve(selection.from));
|
|
69
92
|
const { $from } = selection;
|
|
70
93
|
if ($from.sharedDepth(selection.to) < 1) return null;
|
|
71
|
-
|
|
72
|
-
const node = $from.node(depth);
|
|
73
|
-
if (node.isBlock && !isChromeNode(node)) return {
|
|
74
|
-
node,
|
|
75
|
-
pos: $from.before(depth)
|
|
76
|
-
};
|
|
77
|
-
}
|
|
78
|
-
return null;
|
|
94
|
+
return outerBlockAt($from);
|
|
79
95
|
}
|
|
80
96
|
/**
|
|
81
97
|
* Attribute a block's own chrome sets on the elements it shows in its top-right corner (status badges, kind or menu
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"block-actions.js","names":[],"sources":["../../../src/features/block-ui/block-actions.ts"],"sourcesContent":["import type { Editor } from '@tiptap/core'\nimport { NodeSelection } from '@tiptap/pm/state'\nimport { abilitiesAt, type BlockAction, type BlockActionContext, type BlockActionSurface, type BlockTarget, editorEntryOf, type MenuItem } from '../../core'\nimport { isChromeNode } from '../../core/schema'\n\n/** An action `target` offers, with the context it runs with and, for a `menu` action, its items. */\nexport interface BlockActionEntry {\n action: BlockAction\n ctx: BlockActionContext\n menu?: MenuItem[]\n}\n\n/** Hovering a composite's title/description/tags row addresses the composite itself. */\nexport function effectiveTarget(editor: Editor, target: BlockTarget): BlockTarget {\n if (!isChromeNode(target.node)) return target\n const $pos = editor.state.doc.resolve(target.pos)\n return { node: $pos.parent, pos: $pos.before() }\n}\n\n/**\n * The surfaces that render block actions for `editor` (its surface's `BlockUiOptions.actions`, hover by default). Pass the\n * raw editor instance (`editorEntryOf`).\n */\nexport function actionSurfacesOf(editor: Editor): Record<BlockActionSurface, boolean> {\n const mode = editorEntryOf(editor)?.blockUi?.actions ?? 'hover'\n return { hover: mode === 'hover' || mode === 'both', toolbar: mode === 'toolbar' || mode === 'both' }\n}\n\n/** Whether `hovered` and `selected` address the same block (hovering composite chrome counts as hovering the composite). */\nexport function sameBlock(editor: Editor, hovered: BlockTarget, selected: BlockTarget): boolean {\n if (hovered.pos < 0 || hovered.pos > editor.state.doc.content.size) return false\n return effectiveTarget(editor, hovered).pos === selected.pos\n}\n\n/**\n * The actions `target` offers on `surface`: those whose `placement` (default both) includes it, whose `ability` the\n * block has and whose `isVisible` does not refuse. A `menu` action only when its menu has items.\n */\nexport function blockActionsFor(editor: Editor, target: BlockTarget, actions: readonly BlockAction[], surface: BlockActionSurface): BlockActionEntry[] {\n const
|
|
1
|
+
{"version":3,"file":"block-actions.js","names":[],"sources":["../../../src/features/block-ui/block-actions.ts"],"sourcesContent":["import type { Editor } from '@tiptap/core'\nimport { NodeSelection } from '@tiptap/pm/state'\nimport { abilitiesAt, type BlockAction, type BlockActionContext, type BlockActionSurface, type BlockTarget, blockTypeIdOf, capabilitiesOf, editorEntryOf, type MenuItem } from '../../core'\nimport { isChromeNode } from '../../core/schema'\nimport { outerBlockAt, typedBlockAround } from './block-target'\n\n/** An action `target` offers, with the context it runs with and, for a `menu` action, its items. */\nexport interface BlockActionEntry {\n action: BlockAction\n ctx: BlockActionContext\n menu?: MenuItem[]\n}\n\n/** Hovering a composite's title/description/tags row addresses the composite itself. */\nexport function effectiveTarget(editor: Editor, target: BlockTarget): BlockTarget {\n if (!isChromeNode(target.node)) return target\n const $pos = editor.state.doc.resolve(target.pos)\n return { node: $pos.parent, pos: $pos.before() }\n}\n\n/**\n * The surfaces that render block actions for `editor` (its surface's `BlockUiOptions.actions`, hover by default). Pass the\n * raw editor instance (`editorEntryOf`).\n */\nexport function actionSurfacesOf(editor: Editor): Record<BlockActionSurface, boolean> {\n const mode = editorEntryOf(editor)?.blockUi?.actions ?? 'hover'\n return { hover: mode === 'hover' || mode === 'both', toolbar: mode === 'toolbar' || mode === 'both' }\n}\n\n/** Whether `hovered` and `selected` address the same block (hovering composite chrome counts as hovering the composite). */\nexport function sameBlock(editor: Editor, hovered: BlockTarget, selected: BlockTarget): boolean {\n if (hovered.pos < 0 || hovered.pos > editor.state.doc.content.size) return false\n return effectiveTarget(editor, hovered).pos === selected.pos\n}\n\n/**\n * The actions `target` offers on `surface`: those whose `placement` (default both) includes it, whose `ability` the\n * block has, whose `requires` capabilities the block has all of (`capabilitiesOf`), whose `blockTypes` include its Block type and whose `isVisible` does not refuse. A `menu` action only when its menu has items.\n * On the toolbar an action with `target: 'typedBlock'` is checked against, and runs with, the Typed block around `target`\n * (`typedBlockAround`) instead of `target`; it is absent when none encloses `target`.\n */\nexport function blockActionsFor(editor: Editor, target: BlockTarget, actions: readonly BlockAction[], surface: BlockActionSurface): BlockActionEntry[] {\n const contextOf = (at: BlockTarget): BlockActionContext => ({ ...at, editor, abilities: abilitiesAt(editor, at.pos, at.node) })\n const blockCtx = contextOf(target)\n let typedCtx: BlockActionContext | null | undefined\n return actions.flatMap((action): BlockActionEntry[] => {\n const placement = action.placement ?? 'both'\n if (placement !== 'both' && placement !== surface) return []\n let ctx = blockCtx\n if (surface === 'toolbar' && action.target === 'typedBlock') {\n if (typedCtx === undefined) {\n const typed = typedBlockAround(editor, target)\n typedCtx = typed && (typed === target ? blockCtx : contextOf(typed))\n }\n if (!typedCtx) return []\n ctx = typedCtx\n }\n if (action.ability && !ctx.abilities.has(action.ability)) return []\n if (action.requires?.length) {\n const capabilities = capabilitiesOf(editor, ctx.node)\n if (!action.requires.every(id => capabilities.has(id))) return []\n }\n if (action.blockTypes) {\n const blockTypeId = blockTypeIdOf(ctx.node)\n if (blockTypeId === null || !action.blockTypes.includes(blockTypeId)) return []\n }\n if (action.isVisible?.(ctx) === false) return []\n if (!action.menu) return [{ action, ctx }]\n const menu = action.menu(ctx)\n return menu.length ? [{ action, ctx, menu }] : []\n })\n}\n\n/**\n * The block holding the selection, for the toolbar surface: `outerBlockAt` the selection start, or, for a node\n * selection, the block around the selected node (the selected node itself when it sits directly in a block container).\n * A caret in a list item thus addresses the list, one in a quote the quote, one in a paragraph of a Typed block the\n * paragraph, one in Typed block chrome the Typed block. Null when the editor is not editable, when the selection spans\n * several top-level blocks, or when it sits outside any block.\n */\nexport function selectedBlockOf(editor: Editor): BlockTarget | null {\n if (editor.isDestroyed || !editor.isEditable) return null\n const { selection } = editor.state\n if (selection instanceof NodeSelection && selection.node.isBlock) {\n return outerBlockAt(editor.state.doc.resolve(selection.from))\n }\n const { $from } = selection\n if ($from.sharedDepth(selection.to) < 1) return null\n return outerBlockAt($from)\n}\n\n/**\n * Attribute a block's own chrome sets on the elements it shows in its top-right corner (status badges, kind or menu\n * buttons, ...). The hover bar docks immediately left of them, vertically centred on them, so both read as one row\n * instead of the bar covering the block's icons. A block without such elements gets the bar at the editor's right edge.\n */\nexport const BLOCK_CORNER_ATTR = 'data-block-corner'\n\n/** Where a block's corner elements sit, in viewport coordinates. */\nexport interface BlockCorner {\n /** Left edge of the leftmost corner element. */\n left: number\n /** Vertical centre of the first corner element. */\n centerY: number\n /** The marked elements, for a host that wants to watch them for size changes. */\n elements: HTMLElement[]\n}\n\n/**\n * The corner elements `dom` (a block's node view root) marks with `BLOCK_CORNER_ATTR`, or null when none is shown.\n * Elements inside a nested block's own node view belong to that block and do not count; neither do hidden ones (no\n * layout box).\n */\nexport function blockCornerOf(dom: HTMLElement): BlockCorner | null {\n const elements = [...dom.querySelectorAll<HTMLElement>(`[${BLOCK_CORNER_ATTR}]`)].filter((element) => {\n const owner = element.closest('[data-node-view-wrapper]')\n return !(owner && owner !== dom && dom.contains(owner))\n })\n const rects = elements.map(element => element.getBoundingClientRect()).filter(rect => rect.width > 0 && rect.height > 0)\n if (!rects.length) return null\n return {\n left: Math.min(...rects.map(rect => rect.left)),\n centerY: rects[0]!.top + rects[0]!.height / 2,\n elements,\n }\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { BlockTarget } from "../../core/extension-points.js";
|
|
2
|
+
import "../../core/index.js";
|
|
3
|
+
import { Editor } from "@tiptap/core";
|
|
4
|
+
import { ResolvedPos } from "@tiptap/pm/model";
|
|
5
|
+
import "@tiptap/extension-drag-handle";
|
|
6
|
+
//#region src/features/block-ui/block-target.d.ts
|
|
7
|
+
/**
|
|
8
|
+
* The blocks at `$pos`, outermost first: for every block container around it (the document, a Typed block, ...) the
|
|
9
|
+
* block directly below that container. A list item's paragraph is not a Block of its own, so inside a list or a quote
|
|
10
|
+
* the block below the document is the list or the quote. A Typed block's body is a container too, so a paragraph in it
|
|
11
|
+
* is a block of its own, below the Typed block. Chrome of a Typed block (its title, description and tags rows) stands for
|
|
12
|
+
* the Typed block, which already is in the list. A position directly between the blocks of a container offers the node
|
|
13
|
+
* after it (a node selection of a block, a block atom).
|
|
14
|
+
*/
|
|
15
|
+
export declare function outerBlocksAt($pos: ResolvedPos): BlockTarget[];
|
|
16
|
+
/**
|
|
17
|
+
* The block to act on at `$pos`: the innermost of `outerBlocksAt`, that is the outermost block below the nearest block
|
|
18
|
+
* container (caret in a list item: the list; in a quote: the quote; in a paragraph of a Typed block's body: that
|
|
19
|
+
* paragraph; in a Typed block's chrome: the Typed block). Null when `$pos` sits outside any block.
|
|
20
|
+
*/
|
|
21
|
+
export declare function outerBlockAt($pos: ResolvedPos): BlockTarget | null;
|
|
22
|
+
/**
|
|
23
|
+
* The Typed block a toolbar action addresses when the selected block is `target`: `target` itself when it is
|
|
24
|
+
* one, else its nearest Typed block ancestor. Null when none encloses it (a paragraph at the document root). A block
|
|
25
|
+
* action with `target: 'typedBlock'` is evaluated against this block on the toolbar surface.
|
|
26
|
+
*/
|
|
27
|
+
export declare function typedBlockAround(editor: Editor, target: BlockTarget): BlockTarget | null;
|
|
28
|
+
//#endregion
|
|
29
|
+
//# sourceMappingURL=block-target.d.ts.map
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { isBlockContainer, isChromeNode } from "../../core/schema/node-flags.js";
|
|
2
|
+
import "../../core/schema/persisted-names.js";
|
|
3
|
+
//#region src/features/block-ui/block-target.ts
|
|
4
|
+
/**
|
|
5
|
+
* The blocks at `$pos`, outermost first: for every block container around it (the document, a Typed block, ...) the
|
|
6
|
+
* block directly below that container. A list item's paragraph is not a Block of its own, so inside a list or a quote
|
|
7
|
+
* the block below the document is the list or the quote. A Typed block's body is a container too, so a paragraph in it
|
|
8
|
+
* is a block of its own, below the Typed block. Chrome of a Typed block (its title, description and tags rows) stands for
|
|
9
|
+
* the Typed block, which already is in the list. A position directly between the blocks of a container offers the node
|
|
10
|
+
* after it (a node selection of a block, a block atom).
|
|
11
|
+
*/
|
|
12
|
+
function outerBlocksAt($pos) {
|
|
13
|
+
const blocks = [];
|
|
14
|
+
for (let depth = 0; depth <= $pos.depth; depth++) {
|
|
15
|
+
if (!isBlockContainer($pos.node(depth))) continue;
|
|
16
|
+
const node = depth < $pos.depth ? $pos.node(depth + 1) : $pos.nodeAfter;
|
|
17
|
+
if (!node || node.isInline || isChromeNode(node)) continue;
|
|
18
|
+
blocks.push({
|
|
19
|
+
node,
|
|
20
|
+
pos: depth < $pos.depth ? $pos.before(depth + 1) : $pos.pos
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
return blocks;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* The block to act on at `$pos`: the innermost of `outerBlocksAt`, that is the outermost block below the nearest block
|
|
27
|
+
* container (caret in a list item: the list; in a quote: the quote; in a paragraph of a Typed block's body: that
|
|
28
|
+
* paragraph; in a Typed block's chrome: the Typed block). Null when `$pos` sits outside any block.
|
|
29
|
+
*/
|
|
30
|
+
function outerBlockAt($pos) {
|
|
31
|
+
return outerBlocksAt($pos).at(-1) ?? null;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* The Typed block a toolbar action addresses when the selected block is `target`: `target` itself when it is
|
|
35
|
+
* one, else its nearest Typed block ancestor. Null when none encloses it (a paragraph at the document root). A block
|
|
36
|
+
* action with `target: 'typedBlock'` is evaluated against this block on the toolbar surface.
|
|
37
|
+
*/
|
|
38
|
+
function typedBlockAround(editor, target) {
|
|
39
|
+
if (target.node.type.name === "typedBlock") return target;
|
|
40
|
+
const $pos = editor.state.doc.resolve(target.pos);
|
|
41
|
+
for (let depth = $pos.depth; depth > 0; depth--) {
|
|
42
|
+
const node = $pos.node(depth);
|
|
43
|
+
if (node.type.name === "typedBlock") return {
|
|
44
|
+
node,
|
|
45
|
+
pos: $pos.before(depth)
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Drag-handle targeting rule (`NestedOptions.rules`, with `defaultRules: false`): only a block of `outerBlocksAt` the
|
|
52
|
+
* hovered position is a target; everything else (list items and their paragraphs, quote content, table rows and cells,
|
|
53
|
+
* Typed block chrome) is excluded. Among the blocks of the chain the plugin picks the innermost, and the surfaces' own
|
|
54
|
+
* rules still hand the pointer in a nested block's gutter to its ancestors.
|
|
55
|
+
*/
|
|
56
|
+
const outerBlockRule = {
|
|
57
|
+
id: "outerBlock",
|
|
58
|
+
evaluate: ({ pos, $pos }) => outerBlocksAt($pos).some((block) => block.pos === pos) ? 0 : 1e3
|
|
59
|
+
};
|
|
60
|
+
//#endregion
|
|
61
|
+
export { outerBlockAt, outerBlockRule, outerBlocksAt, typedBlockAround };
|
|
62
|
+
|
|
63
|
+
//# sourceMappingURL=block-target.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"block-target.js","names":[],"sources":["../../../src/features/block-ui/block-target.ts"],"sourcesContent":["import type { DragHandleRule } from '@tiptap/extension-drag-handle'\nimport type { ResolvedPos } from '@tiptap/pm/model'\nimport type { Editor } from '@tiptap/core'\nimport type { BlockTarget } from '../../core'\nimport { isBlockContainer, isChromeNode, TYPED_BLOCK } from '../../core/schema'\n\n// Which block the block UI (hover bar, toolbar, drag handle) addresses at a position. Framework-free; the one place that\n// decides it, so the surfaces and the drag handle cannot disagree.\n\n/**\n * The blocks at `$pos`, outermost first: for every block container around it (the document, a Typed block, ...) the\n * block directly below that container. A list item's paragraph is not a Block of its own, so inside a list or a quote\n * the block below the document is the list or the quote. A Typed block's body is a container too, so a paragraph in it\n * is a block of its own, below the Typed block. Chrome of a Typed block (its title, description and tags rows) stands for\n * the Typed block, which already is in the list. A position directly between the blocks of a container offers the node\n * after it (a node selection of a block, a block atom).\n */\nexport function outerBlocksAt($pos: ResolvedPos): BlockTarget[] {\n const blocks: BlockTarget[] = []\n for (let depth = 0; depth <= $pos.depth; depth++) {\n if (!isBlockContainer($pos.node(depth))) continue\n const node = depth < $pos.depth ? $pos.node(depth + 1) : $pos.nodeAfter\n if (!node || node.isInline || isChromeNode(node)) continue\n blocks.push({ node, pos: depth < $pos.depth ? $pos.before(depth + 1) : $pos.pos })\n }\n return blocks\n}\n\n/**\n * The block to act on at `$pos`: the innermost of `outerBlocksAt`, that is the outermost block below the nearest block\n * container (caret in a list item: the list; in a quote: the quote; in a paragraph of a Typed block's body: that\n * paragraph; in a Typed block's chrome: the Typed block). Null when `$pos` sits outside any block.\n */\nexport function outerBlockAt($pos: ResolvedPos): BlockTarget | null {\n return outerBlocksAt($pos).at(-1) ?? null\n}\n\n/**\n * The Typed block a toolbar action addresses when the selected block is `target`: `target` itself when it is\n * one, else its nearest Typed block ancestor. Null when none encloses it (a paragraph at the document root). A block\n * action with `target: 'typedBlock'` is evaluated against this block on the toolbar surface.\n */\nexport function typedBlockAround(editor: Editor, target: BlockTarget): BlockTarget | null {\n if (target.node.type.name === TYPED_BLOCK) return target\n const $pos = editor.state.doc.resolve(target.pos)\n for (let depth = $pos.depth; depth > 0; depth--) {\n const node = $pos.node(depth)\n if (node.type.name === TYPED_BLOCK) return { node, pos: $pos.before(depth) }\n }\n return null\n}\n\n/**\n * Drag-handle targeting rule (`NestedOptions.rules`, with `defaultRules: false`): only a block of `outerBlocksAt` the\n * hovered position is a target; everything else (list items and their paragraphs, quote content, table rows and cells,\n * Typed block chrome) is excluded. Among the blocks of the chain the plugin picks the innermost, and the surfaces' own\n * rules still hand the pointer in a nested block's gutter to its ancestors.\n */\nexport const outerBlockRule: DragHandleRule = {\n id: 'outerBlock',\n evaluate: ({ pos, $pos }) => (outerBlocksAt($pos).some(block => block.pos === pos) ? 0 : 1000),\n}\n"],"mappings":";;;;;;;;;;;AAiBA,SAAgB,cAAc,MAAkC;CAC9D,MAAM,SAAwB,CAAC;CAC/B,KAAK,IAAI,QAAQ,GAAG,SAAS,KAAK,OAAO,SAAS;EAChD,IAAI,CAAC,iBAAiB,KAAK,KAAK,KAAK,CAAC,GAAG;EACzC,MAAM,OAAO,QAAQ,KAAK,QAAQ,KAAK,KAAK,QAAQ,CAAC,IAAI,KAAK;EAC9D,IAAI,CAAC,QAAQ,KAAK,YAAY,aAAa,IAAI,GAAG;EAClD,OAAO,KAAK;GAAE;GAAM,KAAK,QAAQ,KAAK,QAAQ,KAAK,OAAO,QAAQ,CAAC,IAAI,KAAK;EAAI,CAAC;CACnF;CACA,OAAO;AACT;;;;;;AAOA,SAAgB,aAAa,MAAuC;CAClE,OAAO,cAAc,IAAI,CAAC,CAAC,GAAG,EAAE,KAAK;AACvC;;;;;;AAOA,SAAgB,iBAAiB,QAAgB,QAAyC;CACxF,IAAI,OAAO,KAAK,KAAK,SAAA,cAAsB,OAAO;CAClD,MAAM,OAAO,OAAO,MAAM,IAAI,QAAQ,OAAO,GAAG;CAChD,KAAK,IAAI,QAAQ,KAAK,OAAO,QAAQ,GAAG,SAAS;EAC/C,MAAM,OAAO,KAAK,KAAK,KAAK;EAC5B,IAAI,KAAK,KAAK,SAAA,cAAsB,OAAO;GAAE;GAAM,KAAK,KAAK,OAAO,KAAK;EAAE;CAC7E;CACA,OAAO;AACT;;;;;;;AAQA,MAAa,iBAAiC;CAC5C,IAAI;CACJ,WAAW,EAAE,KAAK,WAAY,cAAc,IAAI,CAAC,CAAC,MAAK,UAAS,MAAM,QAAQ,GAAG,IAAI,IAAI;AAC3F"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { startBlockDrag } from "../../../core/block-drag.js";
|
|
2
2
|
import { useUiKit } from "../../../vue/kit/use-ui-kit.js";
|
|
3
|
-
import { firstLineCenterShift,
|
|
3
|
+
import { firstLineCenterShift, handleBlocksOf } from "../handle-geometry.js";
|
|
4
4
|
import { Fragment, createElementBlock, createVNode, defineComponent, normalizeClass, normalizeStyle, onBeforeUnmount, onMounted, openBlock, renderList, shallowRef, unref } from "vue";
|
|
5
5
|
//#region src/features/block-ui/components/BlockHandles.vue
|
|
6
6
|
const _hoisted_1 = { class: "absolute left-0 top-0 z-10 h-0 w-0" };
|
|
@@ -33,10 +33,10 @@ const _sfc_main = /*@__PURE__*/ defineComponent({
|
|
|
33
33
|
const originX = hostRect.left + host.clientLeft;
|
|
34
34
|
const originY = hostRect.top + host.clientTop;
|
|
35
35
|
const next = [];
|
|
36
|
-
for (const {
|
|
36
|
+
for (const { pos, dom } of handleBlocksOf(editor.view)) {
|
|
37
37
|
const rect = dom.getBoundingClientRect();
|
|
38
38
|
if (!rect.height || rect.bottom < -window.innerHeight || rect.top > 2 * window.innerHeight) continue;
|
|
39
|
-
const left = rect.left - 24 -
|
|
39
|
+
const left = rect.left - 24 - originX;
|
|
40
40
|
const top = rect.top + firstLineCenterShift(dom, rect.top, 24) - originY;
|
|
41
41
|
if (!next.some((other) => Math.abs(top - other.top) < 12 && left < other.left + 24 && other.left < left + 24)) next.push({
|
|
42
42
|
pos,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BlockHandles.js","names":["_openBlock","_createElementBlock","_Fragment","_renderList","_normalizeClass","_normalizeStyle","_unref","_createVNode"],"sources":["../../../../src/features/block-ui/components/BlockHandles.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { useUiKit } from '../../../vue/kit/use-ui-kit'\nimport type { Editor } from '@tiptap/vue-3'\nimport { onBeforeUnmount, onMounted, shallowRef } from 'vue'\nimport { startBlockDrag } from '../../../core'\nimport { firstLineCenterShift,
|
|
1
|
+
{"version":3,"file":"BlockHandles.js","names":["_openBlock","_createElementBlock","_Fragment","_renderList","_normalizeClass","_normalizeStyle","_unref","_createVNode"],"sources":["../../../../src/features/block-ui/components/BlockHandles.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { useUiKit } from '../../../vue/kit/use-ui-kit'\nimport type { Editor } from '@tiptap/vue-3'\nimport { onBeforeUnmount, onMounted, shallowRef } from 'vue'\nimport { startBlockDrag } from '../../../core'\nimport { firstLineCenterShift, HANDLE_SIZE, handleBlocksOf } from '../handle-geometry'\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 */\nconst props = defineProps<{ editor: Editor, host: HTMLElement }>()\n\nconst { Icon: UIcon } = useUiKit()\n\ninterface Handle { pos: number, left: number, top: number }\n\nconst handles = shallowRef<readonly Handle[]>([])\n// While a drag runs the handles let events through, so a drop over a handle's gutter still reaches the editor.\nconst dragging = shallowRef(false)\n\nlet raf = 0\nlet wasEditable = false\nfunction schedule() {\n if (!raf) raf = requestAnimationFrame(measure)\n}\n\nfunction measure() {\n raf = 0\n const { editor, host } = props\n wasEditable = !editor.isDestroyed && editor.isEditable\n if (!wasEditable || !editor.view.dom.getClientRects().length) {\n if (handles.value.length) handles.value = []\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 const prev = handles.value\n const changed = prev.length !== next.length || next.some((h, i) => {\n const before = prev[i]\n return !before || h.pos !== before.pos || h.left !== before.left || h.top !== before.top\n })\n if (changed) handles.value = next\n}\n\n// Documents change layout through edits, the column through resizes; `EditorSurface` dispatches a transaction after\n// `setEditable`.\nfunction onTransaction({ transaction }: { transaction: { docChanged: boolean } }) {\n if (transaction.docChanged || props.editor.isEditable !== wasEditable) schedule()\n}\n\nlet resizeObserver: ResizeObserver | undefined\nonMounted(() => {\n props.editor.on('transaction', onTransaction)\n window.addEventListener('resize', schedule)\n window.addEventListener('scroll', schedule, true)\n resizeObserver = new ResizeObserver(schedule)\n resizeObserver.observe(props.editor.view.dom)\n schedule()\n})\n\nonBeforeUnmount(() => {\n props.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\nfunction onDragStart(event: DragEvent, pos: number) {\n if (!startBlockDrag(props.editor, event, 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(() => { dragging.value = true })\n const abort = new AbortController()\n const end = () => {\n dragging.value = false\n abort.abort()\n }\n document.addEventListener('drop', end, { signal: abort.signal })\n document.addEventListener('dragend', end, { signal: abort.signal })\n}\n</script>\n\n<template>\n <div class=\"absolute left-0 top-0 z-10 h-0 w-0\">\n <div\n v-for=\"handle in handles\"\n :key=\"handle.pos\"\n draggable=\"true\"\n aria-hidden=\"true\"\n :class=\"['absolute flex cursor-grab items-center justify-center rounded text-[var(--sk-muted)] hover:bg-[var(--sk-bg-elevated)] hover:text-[var(--sk-fg-highlighted)]', 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 @dragstart=\"onDragStart($event, handle.pos)\"\n >\n <UIcon name=\"i-lucide-grip-vertical\" class=\"size-4\" />\n </div>\n </div>\n</template>\n"],"mappings":"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"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { editorEntryOf } from "../../../core/editor-ui.js";
|
|
2
|
-
import { isChromeNode } from "../../../core/schema/node-flags.js";
|
|
3
2
|
import { useUiKit } from "../../../vue/kit/use-ui-kit.js";
|
|
4
3
|
import { useEditorSettings } from "../../../vue/settings.js";
|
|
5
|
-
import { firstLineCenterShift,
|
|
4
|
+
import { firstLineCenterShift, handleLeftOf, hasBlockTypeIcon } from "../handle-geometry.js";
|
|
5
|
+
import { outerBlockRule } from "../block-target.js";
|
|
6
6
|
import { actionSurfacesOf, sameBlock, selectedBlockOf } from "../block-actions.js";
|
|
7
7
|
import _sfc_main$1 from "./BlockActionsOverlay.js";
|
|
8
8
|
import _sfc_main$2 from "./BlockHandles.js";
|
|
@@ -81,11 +81,9 @@ const _sfc_main = /*@__PURE__*/ defineComponent({
|
|
|
81
81
|
const { settings } = useEditorSettings();
|
|
82
82
|
const alwaysHandles = computed(() => settings.value.blocks.dragHandle === "always");
|
|
83
83
|
const handle = useTemplateRef("handle");
|
|
84
|
-
const
|
|
85
|
-
const hoverHandleHidden = computed(() => alwaysHandles.value ||
|
|
86
|
-
let handleGutterShift = 0;
|
|
84
|
+
const targetHasBlockTypeIcon = shallowRef(false);
|
|
85
|
+
const hoverHandleHidden = computed(() => alwaysHandles.value || targetHasBlockTypeIcon.value);
|
|
87
86
|
let dragTargetDom = null;
|
|
88
|
-
let dragTargetNode = null;
|
|
89
87
|
function trackDragTarget({ node, pos }) {
|
|
90
88
|
if (node) {
|
|
91
89
|
clearTimeout(hoverClearTimer);
|
|
@@ -96,15 +94,13 @@ const _sfc_main = /*@__PURE__*/ defineComponent({
|
|
|
96
94
|
} else scheduleHoverClear();
|
|
97
95
|
const dom = node ? props.editor.view.nodeDOM(pos) : null;
|
|
98
96
|
dragTargetDom = dom instanceof HTMLElement ? dom : null;
|
|
99
|
-
|
|
100
|
-
handleGutterShift = dragTargetDom && dragTargetNode ? gutterShiftOf(dragTargetNode, dragTargetDom) : 0;
|
|
101
|
-
targetHasKindIcon.value = dragTargetDom ? hasKindIcon(dragTargetDom) : false;
|
|
97
|
+
targetHasBlockTypeIcon.value = dragTargetDom ? hasBlockTypeIcon(dragTargetDom) : false;
|
|
102
98
|
}
|
|
103
99
|
function pointerReachesTarget() {
|
|
104
|
-
if (!pointer || !
|
|
100
|
+
if (!pointer || !dragTargetDom?.isConnected) return false;
|
|
105
101
|
const rect = dragTargetDom.getBoundingClientRect();
|
|
106
102
|
const { x, y } = pointer;
|
|
107
|
-
if (x < handleLeftOf(
|
|
103
|
+
if (x < handleLeftOf(dragTargetDom, handle.value?.$el.offsetWidth ?? 0) || x >= rect.right) return false;
|
|
108
104
|
if (y < (laidOutSibling(dragTargetDom, "previous")?.bottom ?? rect.top)) return false;
|
|
109
105
|
if (y >= (laidOutSibling(dragTargetDom, "next")?.top ?? rect.bottom)) return false;
|
|
110
106
|
return x < rect.left || y < rect.top || y >= rect.bottom;
|
|
@@ -117,12 +113,6 @@ const _sfc_main = /*@__PURE__*/ defineComponent({
|
|
|
117
113
|
return null;
|
|
118
114
|
}
|
|
119
115
|
const dragHandlePosition = { middleware: [{
|
|
120
|
-
name: "gutterShift",
|
|
121
|
-
fn: ({ x, y }) => ({
|
|
122
|
-
x: x - handleGutterShift,
|
|
123
|
-
y
|
|
124
|
-
})
|
|
125
|
-
}, {
|
|
126
116
|
name: "firstLineCenter",
|
|
127
117
|
fn: ({ x, y, elements, rects }) => ({
|
|
128
118
|
x,
|
|
@@ -131,21 +121,19 @@ const _sfc_main = /*@__PURE__*/ defineComponent({
|
|
|
131
121
|
}] };
|
|
132
122
|
const dragHandleNested = {
|
|
133
123
|
edgeDetection: "none",
|
|
124
|
+
defaultRules: false,
|
|
134
125
|
rules: [
|
|
135
|
-
|
|
136
|
-
id: "compositeChrome",
|
|
137
|
-
evaluate: ({ node }) => isChromeNode(node) ? 1e3 : 0
|
|
138
|
-
},
|
|
126
|
+
outerBlockRule,
|
|
139
127
|
{
|
|
140
128
|
id: "reachTarget",
|
|
141
129
|
evaluate: () => pointerReachesTarget() ? 1e3 : 0
|
|
142
130
|
},
|
|
143
131
|
{
|
|
144
132
|
id: "ownGutter",
|
|
145
|
-
evaluate: ({
|
|
133
|
+
evaluate: ({ pos, depth, view }) => {
|
|
146
134
|
if (depth < 2 || !pointer) return 0;
|
|
147
135
|
const dom = view.nodeDOM(pos);
|
|
148
|
-
return dom instanceof HTMLElement && pointer.x < handleLeftOf(
|
|
136
|
+
return dom instanceof HTMLElement && pointer.x < handleLeftOf(dom, handle.value?.$el.offsetWidth ?? 0) ? 1e3 : 0;
|
|
149
137
|
}
|
|
150
138
|
}
|
|
151
139
|
]
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BlockUi.js","names":["_openBlock","_createElementBlock","_Fragment","_createBlock","_Teleport","BlockActionsOverlay","_createCommentVNode","BlockHandles","_createVNode","_unref","_normalizeClass","_withCtx"],"sources":["../../../../src/features/block-ui/components/BlockUi.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { useUiKit } from '../../../vue/kit/use-ui-kit'\nimport { DragHandle, type DragHandleProps } from '@tiptap/extension-drag-handle-vue-3'\nimport type { Node } from '@tiptap/pm/model'\nimport type { Editor } from '@tiptap/vue-3'\nimport { type ComponentPublicInstance, computed, nextTick, onBeforeUnmount, onMounted, shallowRef, toRaw, useTemplateRef } from 'vue'\nimport { type BlockTarget, editorEntryOf } from '../../../core'\nimport { useEditorSettings } from '../../../vue/settings'\nimport { isChromeNode } from '../../../core/schema'\nimport { firstLineCenterShift, gutterShiftOf, handleLeftOf, hasKindIcon } from '../handle-geometry'\nimport { actionSurfacesOf, sameBlock, selectedBlockOf } from '../block-actions'\nimport BlockActionsOverlay from './BlockActionsOverlay.vue'\nimport BlockHandles from './BlockHandles.vue'\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 */\nconst props = defineProps<{ editor: Editor }>()\n\nconst { Icon: UIcon } = useUiKit()\n\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.\nconst host = shallowRef<HTMLElement | null>(null)\nconst hoverTarget = shallowRef<BlockTarget | null>(null)\nconst actions = computed(() => editorEntryOf(toRaw(props.editor))?.blockActions ?? [])\n// Read inside the teleport only: the surface registers its entry after its overlays have mounted.\nconst surfaces = computed(() => actionSurfacesOf(toRaw(props.editor)))\n// The block holding the selection follows every transaction (`editor.state` is reactive).\nconst selectedTarget = computed(() => {\n void props.editor.state\n return surfaces.value.toolbar ? selectedBlockOf(props.editor) : null\n})\n// One bar per block: the toolbar wins where the hover bar would sit on the same block.\nconst hoverBarTarget = computed(() => {\n const hovered = hoverTarget.value\n const selected = selectedTarget.value\n return hovered && selected && sameBlock(props.editor, hovered, selected) ? null : hovered\n})\nlet overlayHovered = false\nlet hoverClearTimer: ReturnType<typeof setTimeout> | undefined\n\n// The overlay is positioned inside the element that holds the editor content (`relative`). Tiptap's content component\n// moves the editor DOM into it on the tick after it mounted, so look it up after that one.\nonMounted(async () => {\n await nextTick()\n const dom = props.editor.isDestroyed ? null : props.editor.view.dom\n host.value = dom?.isConnected ? dom.parentElement : null\n dom?.addEventListener('keydown', onEditorKeydown)\n dom?.addEventListener('mousemove', onEditorMousemove)\n})\n\nonBeforeUnmount(() => {\n clearTimeout(hoverClearTimer)\n if (props.editor.isDestroyed) return\n props.editor.view.dom.removeEventListener('keydown', onEditorKeydown)\n props.editor.view.dom.removeEventListener('mousemove', onEditorMousemove)\n})\n\n// Pointer position for the targeting rules below. The plugin evaluates them in a frame callback after the mousemove,\n// so this is the position they see.\nlet pointer: { x: number, y: number } | null = null\nfunction onEditorMousemove(e: MouseEvent) {\n pointer = { x: e.clientX, y: e.clientY }\n}\n\n// Like the drag-handle plugin: a key pressed in the focused editor hides the actions.\nfunction onEditorKeydown() {\n clearTimeout(hoverClearTimer)\n hoverTarget.value = null\n}\n\nfunction scheduleHoverClear() {\n clearTimeout(hoverClearTimer)\n hoverClearTimer = setTimeout(() => {\n if (!overlayHovered) hoverTarget.value = null\n }, 200)\n}\n\nfunction onOverlayHover(hovered: boolean) {\n overlayHovered = hovered\n if (!hovered) scheduleHoverClear()\n}\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.\nfunction resetDragHandle() {\n const { editor } = props\n if (editor.isDestroyed) return\n editor.view.dispatch(editor.state.tr.setMeta('hideDragHandle', true).setMeta('addToHistory', false))\n}\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.\nconst { settings } = useEditorSettings()\nconst alwaysHandles = computed(() => settings.value.blocks.dragHandle === 'always')\nconst handle = useTemplateRef<ComponentPublicInstance>('handle')\nconst targetHasKindIcon = shallowRef(false)\nconst hoverHandleHidden = computed(() => alwaysHandles.value || targetHasKindIcon.value)\nlet handleGutterShift = 0\nlet dragTargetDom: HTMLElement | null = null\nlet dragTargetNode: Node | null = null\nfunction trackDragTarget({ node, pos }: { node: Node | null, pos: number }) {\n if (node) {\n clearTimeout(hoverClearTimer)\n hoverTarget.value = { node, pos }\n }\n else {\n scheduleHoverClear()\n }\n const dom = node ? props.editor.view.nodeDOM(pos) : null\n dragTargetDom = dom instanceof HTMLElement ? dom : null\n dragTargetNode = dragTargetDom ? node : null\n handleGutterShift = dragTargetDom && dragTargetNode ? gutterShiftOf(dragTargetNode, dragTargetDom) : 0\n targetHasKindIcon.value = dragTargetDom ? hasKindIcon(dragTargetDom) : false\n}\n\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.\nfunction pointerReachesTarget(): boolean {\n if (!pointer || !dragTargetNode || !dragTargetDom?.isConnected) return false\n const rect = dragTargetDom.getBoundingClientRect()\n const { x, y } = pointer\n if (x < handleLeftOf(dragTargetNode, dragTargetDom, handle.value?.$el.offsetWidth ?? 0) || x >= rect.right) return false\n if (y < (laidOutSibling(dragTargetDom, 'previous')?.bottom ?? rect.top)) return false\n if (y >= (laidOutSibling(dragTargetDom, 'next')?.top ?? rect.bottom)) return false\n return x < rect.left || y < rect.top || y >= rect.bottom\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 el = dom[`${side}ElementSibling`]; el; el = el[`${side}ElementSibling`]) {\n const rect = el.getBoundingClientRect()\n if (rect.height > 0) return rect\n }\n return null\n}\n\n// The plugin aligns the handle's top with the block's top, which sits above the middle of the\n// block's first text line: `firstLineCenterShift` moves the handle's centre to that line's centre.\nconst dragHandlePosition: DragHandleProps['computePositionConfig'] = {\n middleware: [\n { name: 'gutterShift', fn: ({ x, y }) => ({ x: x - handleGutterShift, y }) },\n {\n name: 'firstLineCenter',\n fn: ({ x, y, elements, rects }) => ({\n x,\n y: dragTargetDom ? y + firstLineCenterShift(dragTargetDom, elements.reference.getBoundingClientRect().top, rects.floating.height) : y,\n }),\n },\n ],\n}\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.\nconst dragHandleNested: DragHandleProps['nested'] = {\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 if (depth < 2 || !pointer) return 0\n const dom = view.nodeDOM(pos)\n return dom instanceof HTMLElement && pointer.x < handleLeftOf(node, dom, handle.value?.$el.offsetWidth ?? 0) ? 1000 : 0\n },\n },\n ],\n}\n</script>\n\n<template>\n <Teleport v-if=\"host\" :to=\"host\">\n <BlockActionsOverlay\n v-if=\"surfaces.hover\"\n :editor=\"editor\"\n :target=\"hoverBarTarget\"\n :host=\"host\"\n :actions=\"actions\"\n surface=\"hover\"\n @hover=\"onOverlayHover\"\n />\n <BlockActionsOverlay\n v-if=\"surfaces.toolbar\"\n :editor=\"editor\"\n :target=\"selectedTarget\"\n :host=\"host\"\n :actions=\"actions\"\n surface=\"toolbar\"\n persistent\n />\n <BlockHandles v-if=\"alwaysHandles\" :editor=\"editor\" :host=\"host\" />\n </Teleport>\n <DragHandle\n ref=\"handle\"\n :editor=\"editor\"\n :on-element-drag-end=\"resetDragHandle\"\n :on-node-change=\"trackDragTarget\"\n :compute-position-config=\"dragHandlePosition\"\n :nested=\"dragHandleNested\"\n :class=\"{ 'invisible! pointer-events-none!': hoverHandleHidden }\"\n class=\"flex size-6 cursor-grab items-center justify-center rounded text-[var(--sk-muted)] hover:bg-[var(--sk-bg-elevated)] hover:text-[var(--sk-fg-highlighted)] data-[dragging=true]:cursor-grabbing\"\n >\n <UIcon name=\"i-lucide-grip-vertical\" class=\"size-4\" />\n </DragHandle>\n</template>\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"BlockUi.js","names":["_openBlock","_createElementBlock","_Fragment","_createBlock","_Teleport","BlockActionsOverlay","_createCommentVNode","BlockHandles","_createVNode","_unref","_normalizeClass","_withCtx"],"sources":["../../../../src/features/block-ui/components/BlockUi.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { useUiKit } from '../../../vue/kit/use-ui-kit'\nimport { DragHandle, type DragHandleProps } from '@tiptap/extension-drag-handle-vue-3'\nimport type { Node } from '@tiptap/pm/model'\nimport type { Editor } from '@tiptap/vue-3'\nimport { type ComponentPublicInstance, computed, nextTick, onBeforeUnmount, onMounted, shallowRef, toRaw, useTemplateRef } from 'vue'\nimport { type BlockTarget, editorEntryOf } from '../../../core'\nimport { useEditorSettings } from '../../../vue/settings'\nimport { firstLineCenterShift, handleLeftOf, hasBlockTypeIcon } from '../handle-geometry'\nimport { outerBlockRule } from '../block-target'\nimport { actionSurfacesOf, sameBlock, selectedBlockOf } from '../block-actions'\nimport BlockActionsOverlay from './BlockActionsOverlay.vue'\nimport BlockHandles from './BlockHandles.vue'\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 */\nconst props = defineProps<{ editor: Editor }>()\n\nconst { Icon: UIcon } = useUiKit()\n\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.\nconst host = shallowRef<HTMLElement | null>(null)\nconst hoverTarget = shallowRef<BlockTarget | null>(null)\nconst actions = computed(() => editorEntryOf(toRaw(props.editor))?.blockActions ?? [])\n// Read inside the teleport only: the surface registers its entry after its overlays have mounted.\nconst surfaces = computed(() => actionSurfacesOf(toRaw(props.editor)))\n// The block holding the selection follows every transaction (`editor.state` is reactive).\nconst selectedTarget = computed(() => {\n void props.editor.state\n return surfaces.value.toolbar ? selectedBlockOf(props.editor) : null\n})\n// One bar per block: the toolbar wins where the hover bar would sit on the same block.\nconst hoverBarTarget = computed(() => {\n const hovered = hoverTarget.value\n const selected = selectedTarget.value\n return hovered && selected && sameBlock(props.editor, hovered, selected) ? null : hovered\n})\nlet overlayHovered = false\nlet hoverClearTimer: ReturnType<typeof setTimeout> | undefined\n\n// The overlay is positioned inside the element that holds the editor content (`relative`). Tiptap's content component\n// moves the editor DOM into it on the tick after it mounted, so look it up after that one.\nonMounted(async () => {\n await nextTick()\n const dom = props.editor.isDestroyed ? null : props.editor.view.dom\n host.value = dom?.isConnected ? dom.parentElement : null\n dom?.addEventListener('keydown', onEditorKeydown)\n dom?.addEventListener('mousemove', onEditorMousemove)\n})\n\nonBeforeUnmount(() => {\n clearTimeout(hoverClearTimer)\n if (props.editor.isDestroyed) return\n props.editor.view.dom.removeEventListener('keydown', onEditorKeydown)\n props.editor.view.dom.removeEventListener('mousemove', onEditorMousemove)\n})\n\n// Pointer position for the targeting rules below. The plugin evaluates them in a frame callback after the mousemove,\n// so this is the position they see.\nlet pointer: { x: number, y: number } | null = null\nfunction onEditorMousemove(e: MouseEvent) {\n pointer = { x: e.clientX, y: e.clientY }\n}\n\n// Like the drag-handle plugin: a key pressed in the focused editor hides the actions.\nfunction onEditorKeydown() {\n clearTimeout(hoverClearTimer)\n hoverTarget.value = null\n}\n\nfunction scheduleHoverClear() {\n clearTimeout(hoverClearTimer)\n hoverClearTimer = setTimeout(() => {\n if (!overlayHovered) hoverTarget.value = null\n }, 200)\n}\n\nfunction onOverlayHover(hovered: boolean) {\n overlayHovered = hovered\n if (!hovered) scheduleHoverClear()\n}\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.\nfunction resetDragHandle() {\n const { editor } = props\n if (editor.isDestroyed) return\n editor.view.dispatch(editor.state.tr.setMeta('hideDragHandle', true).setMeta('addToHistory', false))\n}\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.\nconst { settings } = useEditorSettings()\nconst alwaysHandles = computed(() => settings.value.blocks.dragHandle === 'always')\nconst handle = useTemplateRef<ComponentPublicInstance>('handle')\nconst targetHasBlockTypeIcon = shallowRef(false)\nconst hoverHandleHidden = computed(() => alwaysHandles.value || targetHasBlockTypeIcon.value)\nlet dragTargetDom: HTMLElement | null = null\nfunction trackDragTarget({ node, pos }: { node: Node | null, pos: number }) {\n if (node) {\n clearTimeout(hoverClearTimer)\n hoverTarget.value = { node, pos }\n }\n else {\n scheduleHoverClear()\n }\n const dom = node ? props.editor.view.nodeDOM(pos) : null\n dragTargetDom = dom instanceof HTMLElement ? dom : null\n targetHasBlockTypeIcon.value = dragTargetDom ? hasBlockTypeIcon(dragTargetDom) : false\n}\n\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.\nfunction pointerReachesTarget(): boolean {\n if (!pointer || !dragTargetDom?.isConnected) return false\n const rect = dragTargetDom.getBoundingClientRect()\n const { x, y } = pointer\n if (x < handleLeftOf(dragTargetDom, handle.value?.$el.offsetWidth ?? 0) || x >= rect.right) return false\n if (y < (laidOutSibling(dragTargetDom, 'previous')?.bottom ?? rect.top)) return false\n if (y >= (laidOutSibling(dragTargetDom, 'next')?.top ?? rect.bottom)) return false\n return x < rect.left || y < rect.top || y >= rect.bottom\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 el = dom[`${side}ElementSibling`]; el; el = el[`${side}ElementSibling`]) {\n const rect = el.getBoundingClientRect()\n if (rect.height > 0) return rect\n }\n return null\n}\n\n// The plugin aligns the handle's top with the block's top, which sits above the middle of the\n// block's first text line: `firstLineCenterShift` moves the handle's centre to that line's centre.\nconst dragHandlePosition: DragHandleProps['computePositionConfig'] = {\n middleware: [\n {\n name: 'firstLineCenter',\n fn: ({ x, y, elements, rects }) => ({\n x,\n y: dragTargetDom ? y + firstLineCenterShift(dragTargetDom, elements.reference.getBoundingClientRect().top, rects.floating.height) : y,\n }),\n },\n ],\n}\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.\nconst dragHandleNested: DragHandleProps['nested'] = {\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 if (depth < 2 || !pointer) return 0\n const dom = view.nodeDOM(pos)\n return dom instanceof HTMLElement && pointer.x < handleLeftOf(dom, handle.value?.$el.offsetWidth ?? 0) ? 1000 : 0\n },\n },\n ],\n}\n</script>\n\n<template>\n <Teleport v-if=\"host\" :to=\"host\">\n <BlockActionsOverlay\n v-if=\"surfaces.hover\"\n :editor=\"editor\"\n :target=\"hoverBarTarget\"\n :host=\"host\"\n :actions=\"actions\"\n surface=\"hover\"\n @hover=\"onOverlayHover\"\n />\n <BlockActionsOverlay\n v-if=\"surfaces.toolbar\"\n :editor=\"editor\"\n :target=\"selectedTarget\"\n :host=\"host\"\n :actions=\"actions\"\n surface=\"toolbar\"\n persistent\n />\n <BlockHandles v-if=\"alwaysHandles\" :editor=\"editor\" :host=\"host\" />\n </Teleport>\n <DragHandle\n ref=\"handle\"\n :editor=\"editor\"\n :on-element-drag-end=\"resetDragHandle\"\n :on-node-change=\"trackDragTarget\"\n :compute-position-config=\"dragHandlePosition\"\n :nested=\"dragHandleNested\"\n :class=\"{ 'invisible! pointer-events-none!': hoverHandleHidden }\"\n class=\"flex size-6 cursor-grab items-center justify-center rounded text-[var(--sk-muted)] hover:bg-[var(--sk-bg-elevated)] hover:text-[var(--sk-fg-highlighted)] data-[dragging=true]:cursor-grabbing\"\n >\n <UIcon name=\"i-lucide-grip-vertical\" class=\"size-4\" />\n </DragHandle>\n</template>\n"],"mappings":"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"}
|