@formicoidea/labre-core 0.41.0 → 0.43.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +384 -0
- package/dist/_pkgs/affine-block-bookmark/bookmark-block.js +2 -2
- package/dist/_pkgs/affine-block-data-view/configs/tooltips.js +1 -1
- package/dist/_pkgs/affine-block-database/configs/tooltips.js +1 -1
- package/dist/_pkgs/affine-block-edgeless-text/edgeless-text-block.js +4 -2
- package/dist/_pkgs/affine-block-edgeless-text/edgeless-toolbar/config.js +7 -1
- package/dist/_pkgs/affine-block-embed/common/iframe-sandbox.d.ts +39 -0
- package/dist/_pkgs/affine-block-embed/common/iframe-sandbox.js +39 -0
- package/dist/_pkgs/affine-block-embed/embed-figma-block/embed-figma-block.js +4 -1
- package/dist/_pkgs/affine-block-embed/embed-github-block/embed-github-block.js +2 -1
- package/dist/_pkgs/affine-block-embed/embed-iframe-block/components/embed-iframe-error-card.d.ts +14 -1
- package/dist/_pkgs/affine-block-embed/embed-iframe-block/components/embed-iframe-error-card.js +21 -2
- package/dist/_pkgs/affine-block-embed/embed-iframe-block/consts.js +2 -0
- package/dist/_pkgs/affine-block-embed/embed-iframe-block/embed-iframe-block.d.ts +2 -1
- package/dist/_pkgs/affine-block-embed/embed-iframe-block/embed-iframe-block.js +41 -11
- package/dist/_pkgs/affine-block-embed/embed-iframe-block/types.d.ts +16 -0
- package/dist/_pkgs/affine-block-embed/embed-iframe-block/types.js +17 -1
- package/dist/_pkgs/affine-block-embed/embed-iframe-block/utils.d.ts +8 -0
- package/dist/_pkgs/affine-block-embed/embed-iframe-block/utils.js +19 -0
- package/dist/_pkgs/affine-block-embed/embed-loom-block/embed-loom-block.js +4 -1
- package/dist/_pkgs/affine-block-embed/embed-youtube-block/embed-youtube-block.js +4 -1
- package/dist/_pkgs/affine-block-embed/index.d.ts +1 -0
- package/dist/_pkgs/affine-block-embed/index.js +1 -0
- package/dist/_pkgs/affine-block-embed/translations.d.ts +8 -0
- package/dist/_pkgs/affine-block-embed/translations.js +28 -0
- package/dist/_pkgs/affine-block-embed-doc/embed-linked-doc-block/embed-linked-doc-block.js +4 -2
- package/dist/_pkgs/affine-block-embed-doc/embed-synced-doc-block/embed-synced-doc-block.js +2 -2
- package/dist/_pkgs/affine-block-frame/frame-manager.js +6 -3
- package/dist/_pkgs/affine-block-frame/frame-tool.js +1 -1
- package/dist/_pkgs/affine-block-frame/frame-toolbar.js +6 -1
- package/dist/_pkgs/affine-block-list/list-keymap.js +7 -0
- package/dist/_pkgs/affine-block-list/utils/get-list-icon.js +3 -1
- package/dist/_pkgs/affine-block-note/configs/tooltips.js +1 -1
- package/dist/_pkgs/affine-block-note/note-keymap.js +7 -1
- package/dist/_pkgs/affine-block-paragraph/paragraph-keymap.js +7 -1
- package/dist/_pkgs/affine-block-root/adapters/html.js +2 -2
- package/dist/_pkgs/affine-block-root/commands/copy-link-commands.d.ts +2 -0
- package/dist/_pkgs/affine-block-root/commands/copy-link-commands.js +155 -0
- package/dist/_pkgs/affine-block-root/commands/pivot-commands.js +1 -8
- package/dist/_pkgs/affine-block-root/commands/tag-commands.js +1 -8
- package/dist/_pkgs/affine-block-root/edgeless/edgeless-keyboard.d.ts +9 -0
- package/dist/_pkgs/affine-block-root/edgeless/edgeless-keyboard.js +51 -0
- package/dist/_pkgs/affine-block-root/edgeless/edgeless-root-block.d.ts +22 -0
- package/dist/_pkgs/affine-block-root/edgeless/edgeless-root-block.js +46 -0
- package/dist/_pkgs/affine-block-root/edgeless/utils/pinch-zoom.d.ts +21 -0
- package/dist/_pkgs/affine-block-root/edgeless/utils/pinch-zoom.js +24 -0
- package/dist/_pkgs/affine-block-root/edgeless/utils/query.js +8 -0
- package/dist/_pkgs/affine-block-root/index.d.ts +1 -0
- package/dist/_pkgs/affine-block-root/index.js +1 -0
- package/dist/_pkgs/affine-block-root/keyboard/keymap.js +1 -16
- package/dist/_pkgs/affine-block-root/view.js +2 -0
- package/dist/_pkgs/affine-block-surface/element-model/index.d.ts +21 -3
- package/dist/_pkgs/affine-block-surface/element-model/index.js +14 -2
- package/dist/_pkgs/affine-block-surface/extensions/export-svg/command.d.ts +23 -0
- package/dist/_pkgs/affine-block-surface/extensions/export-svg/command.js +89 -0
- package/dist/_pkgs/affine-block-surface/extensions/export-svg/index.d.ts +7 -0
- package/dist/_pkgs/affine-block-surface/extensions/export-svg/index.js +5 -0
- package/dist/_pkgs/affine-block-surface/extensions/export-svg/render.d.ts +41 -0
- package/dist/_pkgs/affine-block-surface/extensions/export-svg/render.js +70 -0
- package/dist/_pkgs/affine-block-surface/extensions/export-svg/svg-context.d.ts +49 -0
- package/dist/_pkgs/affine-block-surface/extensions/export-svg/svg-context.js +257 -0
- package/dist/_pkgs/affine-block-surface/extensions/export-svg/tagged-path.d.ts +16 -0
- package/dist/_pkgs/affine-block-surface/extensions/export-svg/tagged-path.js +24 -0
- package/dist/_pkgs/affine-block-surface/extensions/export-svg/toolbar.d.ts +24 -0
- package/dist/_pkgs/affine-block-surface/extensions/export-svg/toolbar.js +66 -0
- package/dist/_pkgs/affine-block-surface/extensions/index.d.ts +4 -0
- package/dist/_pkgs/affine-block-surface/extensions/index.js +4 -0
- package/dist/_pkgs/affine-block-surface/extensions/interchange-import.d.ts +66 -4
- package/dist/_pkgs/affine-block-surface/extensions/interchange-import.js +253 -11
- package/dist/_pkgs/affine-block-surface/extensions/interchange.d.ts +18 -0
- package/dist/_pkgs/affine-block-surface/extensions/legend-toolbar.d.ts +81 -0
- package/dist/_pkgs/affine-block-surface/extensions/legend-toolbar.js +81 -0
- package/dist/_pkgs/affine-block-surface/extensions/legend.d.ts +144 -0
- package/dist/_pkgs/affine-block-surface/extensions/legend.js +495 -0
- package/dist/_pkgs/affine-block-surface/extensions/morph-toolbar.js +4 -0
- package/dist/_pkgs/affine-block-surface/extensions/reading-widget.d.ts +17 -3
- package/dist/_pkgs/affine-block-surface/extensions/reading-widget.js +35 -13
- package/dist/_pkgs/affine-block-surface/extensions/reading.d.ts +61 -1
- package/dist/_pkgs/affine-block-surface/extensions/reading.js +85 -39
- package/dist/_pkgs/affine-block-surface/extensions/record-action.d.ts +66 -0
- package/dist/_pkgs/affine-block-surface/extensions/record-action.js +145 -0
- package/dist/_pkgs/affine-block-surface/extensions/svg-sketch-translations.d.ts +3 -0
- package/dist/_pkgs/affine-block-surface/extensions/svg-sketch-translations.js +23 -0
- package/dist/_pkgs/affine-block-surface/extensions/svg-sketch.d.ts +1 -1
- package/dist/_pkgs/affine-block-surface/extensions/svg-sketch.js +12 -4
- package/dist/_pkgs/affine-block-surface/extensions/validation.d.ts +253 -28
- package/dist/_pkgs/affine-block-surface/extensions/validation.js +489 -41
- package/dist/_pkgs/affine-block-surface/framework-background/background-view.d.ts +115 -0
- package/dist/_pkgs/affine-block-surface/framework-background/background-view.js +185 -0
- package/dist/_pkgs/affine-block-surface/framework-background/fit.d.ts +36 -0
- package/dist/_pkgs/affine-block-surface/framework-background/fit.js +30 -0
- package/dist/_pkgs/affine-block-surface/framework-background/index.d.ts +2 -0
- package/dist/_pkgs/affine-block-surface/framework-background/index.js +2 -0
- package/dist/_pkgs/affine-block-surface/framework-background/labels.d.ts +16 -1
- package/dist/_pkgs/affine-block-surface/framework-background/labels.js +31 -21
- package/dist/_pkgs/affine-block-surface/framework-background/renderer.js +29 -5
- package/dist/_pkgs/affine-block-surface/framework-background/stacking.d.ts +6 -4
- package/dist/_pkgs/affine-block-surface/framework-background/stacking.js +56 -8
- package/dist/_pkgs/affine-block-surface/renderer/canvas-renderer.d.ts +12 -0
- package/dist/_pkgs/affine-block-surface/renderer/canvas-renderer.js +15 -0
- package/dist/_pkgs/affine-block-surface/renderer/element-highlight-overlay.js +2 -7
- package/dist/_pkgs/affine-block-surface/view.js +8 -1
- package/dist/_pkgs/affine-block-surface-ref/configs/slash-menu.js +1 -1
- package/dist/_pkgs/affine-block-surface-ref/configs/tooltips.js +2 -2
- package/dist/_pkgs/affine-components/color-picker/button.d.ts +56 -1
- package/dist/_pkgs/affine-components/color-picker/button.js +168 -23
- package/dist/_pkgs/affine-components/color-picker/framework-palette.d.ts +106 -0
- package/dist/_pkgs/affine-components/color-picker/framework-palette.js +177 -0
- package/dist/_pkgs/affine-components/color-picker/index.d.ts +2 -0
- package/dist/_pkgs/affine-components/color-picker/index.js +2 -0
- package/dist/_pkgs/affine-components/color-picker/palette-carousel.d.ts +85 -0
- package/dist/_pkgs/affine-components/color-picker/palette-carousel.js +445 -0
- package/dist/_pkgs/affine-components/color-picker/styles.js +1 -1
- package/dist/_pkgs/affine-components/context-menu/button.js +3 -1
- package/dist/_pkgs/affine-components/edgeless-shape-color-picker/color-picker.d.ts +31 -1
- package/dist/_pkgs/affine-components/edgeless-shape-color-picker/color-picker.js +189 -63
- package/dist/_pkgs/affine-components/icons/ai.js +3 -3
- package/dist/_pkgs/affine-components/icons/list.js +7 -1
- package/dist/_pkgs/affine-components/resource/resource.js +29 -16
- package/dist/_pkgs/affine-components/size-dropdown-menu/dropdown-menu.js +6 -1
- package/dist/_pkgs/affine-components/toolbar/index.d.ts +1 -1
- package/dist/_pkgs/affine-components/toolbar/index.js +1 -1
- package/dist/_pkgs/affine-components/toolbar/menu-button.d.ts +7 -0
- package/dist/_pkgs/affine-components/toolbar/menu-button.js +30 -0
- package/dist/_pkgs/affine-components/toolbar/picker-menu.d.ts +16 -1
- package/dist/_pkgs/affine-components/toolbar/picker-menu.js +2 -2
- package/dist/_pkgs/affine-components/toolbar/toolbar.d.ts +1 -0
- package/dist/_pkgs/affine-components/toolbar/toolbar.js +67 -0
- package/dist/_pkgs/affine-components/translations.d.ts +8 -0
- package/dist/_pkgs/affine-components/translations.js +17 -0
- package/dist/_pkgs/affine-foundation/view.js +2 -1
- package/dist/_pkgs/affine-fragment-frame-panel/card/frame-card-title-editor.js +1 -1
- package/dist/_pkgs/affine-fragment-frame-panel/card/frame-card.js +1 -1
- package/dist/_pkgs/affine-gfx-brush/element-renderer.js +2 -2
- package/dist/_pkgs/affine-gfx-brush/toolbar/components/eraser/icons.js +1 -1
- package/dist/_pkgs/affine-gfx-brush/toolbar/configs/brush.js +6 -1
- package/dist/_pkgs/affine-gfx-brush/toolbar/configs/highlighter.js +6 -1
- package/dist/_pkgs/affine-gfx-connector/connector-manager.d.ts +9 -1
- package/dist/_pkgs/affine-gfx-connector/connector-manager.js +61 -0
- package/dist/_pkgs/affine-gfx-connector/direction/direction-reveal.d.ts +11 -2
- package/dist/_pkgs/affine-gfx-connector/direction/direction-reveal.js +11 -2
- package/dist/_pkgs/affine-gfx-connector/element-renderer/connector-dom/index.d.ts +7 -1
- package/dist/_pkgs/affine-gfx-connector/element-renderer/connector-dom/index.js +87 -17
- package/dist/_pkgs/affine-gfx-connector/element-renderer/index.js +78 -17
- package/dist/_pkgs/affine-gfx-connector/element-renderer/utils.d.ts +24 -2
- package/dist/_pkgs/affine-gfx-connector/element-renderer/utils.js +31 -8
- package/dist/_pkgs/affine-gfx-connector/text/edgeless-connector-label-editor.d.ts +124 -3
- package/dist/_pkgs/affine-gfx-connector/text/edgeless-connector-label-editor.js +219 -56
- package/dist/_pkgs/affine-gfx-connector/text/text.d.ts +13 -4
- package/dist/_pkgs/affine-gfx-connector/text/text.js +13 -44
- package/dist/_pkgs/affine-gfx-connector/toolbar/config.d.ts +56 -0
- package/dist/_pkgs/affine-gfx-connector/toolbar/config.js +94 -10
- package/dist/_pkgs/affine-gfx-connector/toolbar/hollow-endpoint-icons.d.ts +8 -0
- package/dist/_pkgs/affine-gfx-connector/toolbar/hollow-endpoint-icons.js +118 -0
- package/dist/_pkgs/affine-gfx-connector/translations.d.ts +3 -0
- package/dist/_pkgs/affine-gfx-connector/translations.js +23 -0
- package/dist/_pkgs/affine-gfx-connector/view/view.d.ts +37 -1
- package/dist/_pkgs/affine-gfx-connector/view/view.js +97 -8
- package/dist/_pkgs/affine-gfx-group/command/group-api.js +1 -1
- package/dist/_pkgs/affine-gfx-group/store.js +0 -2
- package/dist/_pkgs/affine-gfx-group/translations.d.ts +9 -10
- package/dist/_pkgs/affine-gfx-group/translations.js +9 -13
- package/dist/_pkgs/affine-gfx-mindmap/indicator-overlay/index.js +6 -2
- package/dist/_pkgs/affine-gfx-mindmap/templates/index.js +1 -1
- package/dist/_pkgs/affine-gfx-mindmap/toolbar/basket-elements.js +1 -1
- package/dist/_pkgs/affine-gfx-mindmap/toolbar/config.js +4 -2
- package/dist/_pkgs/affine-gfx-mindmap/toolbar/utils/import-mindmap.js +2 -2
- package/dist/_pkgs/affine-gfx-mindmap/translations.d.ts +7 -1
- package/dist/_pkgs/affine-gfx-mindmap/translations.js +11 -1
- package/dist/_pkgs/affine-gfx-shape/element-renderer/highlighter.js +2 -2
- package/dist/_pkgs/affine-gfx-shape/overlay/polygon-drawing-overlay.d.ts +6 -0
- package/dist/_pkgs/affine-gfx-shape/overlay/polygon-drawing-overlay.js +30 -1
- package/dist/_pkgs/affine-gfx-shape/polygon-tool.d.ts +20 -1
- package/dist/_pkgs/affine-gfx-shape/polygon-tool.js +9 -1
- package/dist/_pkgs/affine-gfx-shape/toolbar/config.js +10 -3
- package/dist/_pkgs/affine-gfx-shape/toolbar/palette-color-action.js +11 -1
- package/dist/_pkgs/affine-gfx-shape/translations.d.ts +7 -0
- package/dist/_pkgs/affine-gfx-shape/translations.js +11 -0
- package/dist/_pkgs/affine-gfx-template/builtin/other.js +14 -8
- package/dist/_pkgs/affine-gfx-template/snapshot-from-action.js +32 -119
- package/dist/_pkgs/affine-gfx-template/toolbar/template-loading.js +1 -1
- package/dist/_pkgs/affine-gfx-template/toolbar/template-type.d.ts +1 -1
- package/dist/_pkgs/affine-gfx-template/translations.d.ts +5 -0
- package/dist/_pkgs/affine-gfx-template/translations.js +38 -0
- package/dist/_pkgs/affine-gfx-text/dblclick-add-edgeless-text.d.ts +13 -1
- package/dist/_pkgs/affine-gfx-text/dblclick-add-edgeless-text.js +19 -4
- package/dist/_pkgs/affine-gfx-text/edgeless-text-editor.d.ts +41 -0
- package/dist/_pkgs/affine-gfx-text/edgeless-text-editor.js +60 -4
- package/dist/_pkgs/affine-gfx-text/toolbar/actions.d.ts +8 -1
- package/dist/_pkgs/affine-gfx-text/toolbar/actions.js +14 -2
- package/dist/_pkgs/affine-gfx-text/translations.d.ts +9 -0
- package/dist/_pkgs/affine-gfx-text/translations.js +14 -1
- package/dist/_pkgs/affine-inline-latex/latex-node/latex-editor-menu.js +2 -1
- package/dist/_pkgs/affine-inline-preset/markdown.js +5 -1
- package/dist/_pkgs/affine-model/consts/connector.d.ts +28 -2
- package/dist/_pkgs/affine-model/consts/connector.js +26 -0
- package/dist/_pkgs/affine-model/consts/text.d.ts +15 -2
- package/dist/_pkgs/affine-model/consts/text.js +25 -1
- package/dist/_pkgs/affine-model/elements/bpmn/pool.js +1 -1
- package/dist/_pkgs/affine-model/elements/brush/brush.js +1 -1
- package/dist/_pkgs/affine-model/elements/c4/board.js +1 -1
- package/dist/_pkgs/affine-model/elements/c4/boundary.js +1 -1
- package/dist/_pkgs/affine-model/elements/connector/connector.d.ts +135 -0
- package/dist/_pkgs/affine-model/elements/connector/connector.js +246 -5
- package/dist/_pkgs/affine-model/elements/connector/end-label.d.ts +83 -0
- package/dist/_pkgs/affine-model/elements/connector/end-label.js +119 -0
- package/dist/_pkgs/affine-model/elements/connector/index.d.ts +1 -0
- package/dist/_pkgs/affine-model/elements/connector/index.js +1 -0
- package/dist/_pkgs/affine-model/elements/context-map/context-map.js +1 -1
- package/dist/_pkgs/affine-model/elements/core-domain/core-domain.d.ts +28 -0
- package/dist/_pkgs/affine-model/elements/core-domain/core-domain.js +129 -2
- package/dist/_pkgs/affine-model/elements/cynefin/cynefin.d.ts +8 -0
- package/dist/_pkgs/affine-model/elements/cynefin/cynefin.js +45 -2
- package/dist/_pkgs/affine-model/elements/edgy/board.js +1 -1
- package/dist/_pkgs/affine-model/elements/edgy/facets.js +1 -1
- package/dist/_pkgs/affine-model/elements/estuarine/estuarine.d.ts +6 -0
- package/dist/_pkgs/affine-model/elements/estuarine/estuarine.js +36 -2
- package/dist/_pkgs/affine-model/elements/event-storming/event-storming.d.ts +18 -7
- package/dist/_pkgs/affine-model/elements/event-storming/event-storming.js +23 -8
- package/dist/_pkgs/affine-model/elements/framework-background/background.d.ts +16 -0
- package/dist/_pkgs/affine-model/elements/framework-background/background.js +18 -0
- package/dist/_pkgs/affine-model/elements/highlighter/highlighter.js +1 -1
- package/dist/_pkgs/affine-model/elements/index.d.ts +8 -0
- package/dist/_pkgs/affine-model/elements/index.js +1 -0
- package/dist/_pkgs/affine-model/elements/shape/shape.js +1 -1
- package/dist/_pkgs/affine-model/elements/text/text.js +1 -1
- package/dist/_pkgs/affine-model/elements/uml/band.d.ts +39 -0
- package/dist/_pkgs/affine-model/elements/uml/band.js +31 -0
- package/dist/_pkgs/affine-model/elements/uml/diagram.d.ts +158 -0
- package/dist/_pkgs/affine-model/elements/uml/diagram.js +229 -0
- package/dist/_pkgs/affine-model/elements/uml/fragment.d.ts +161 -0
- package/dist/_pkgs/affine-model/elements/uml/fragment.js +205 -0
- package/dist/_pkgs/affine-model/elements/uml/index.d.ts +8 -0
- package/dist/_pkgs/affine-model/elements/uml/index.js +8 -0
- package/dist/_pkgs/affine-model/elements/uml/lifeline.d.ts +77 -0
- package/dist/_pkgs/affine-model/elements/uml/lifeline.js +89 -0
- package/dist/_pkgs/affine-model/elements/uml/node.d.ts +142 -0
- package/dist/_pkgs/affine-model/elements/uml/node.js +190 -0
- package/dist/_pkgs/affine-model/elements/uml/partition.d.ts +106 -0
- package/dist/_pkgs/affine-model/elements/uml/partition.js +172 -0
- package/dist/_pkgs/affine-model/elements/uml/region.d.ts +75 -0
- package/dist/_pkgs/affine-model/elements/uml/region.js +150 -0
- package/dist/_pkgs/affine-model/elements/uml/subject.d.ts +37 -0
- package/dist/_pkgs/affine-model/elements/uml/subject.js +108 -0
- package/dist/_pkgs/affine-model/elements/wardley/wardley.js +1 -1
- package/dist/_pkgs/affine-shared/services/embed-iframe/embed-iframe-config.d.ts +1 -0
- package/dist/_pkgs/affine-shared/services/font-loader/config.d.ts +18 -0
- package/dist/_pkgs/affine-shared/services/font-loader/config.js +82 -50
- package/dist/_pkgs/affine-shared/services/pivot-materiality-publisher.js +1 -9
- package/dist/_pkgs/affine-shared/services/telemetry-service/document-damage-watcher.d.ts +53 -0
- package/dist/_pkgs/affine-shared/services/telemetry-service/document-damage-watcher.js +95 -0
- package/dist/_pkgs/affine-shared/services/telemetry-service/index.d.ts +1 -0
- package/dist/_pkgs/affine-shared/services/telemetry-service/index.js +1 -0
- package/dist/_pkgs/affine-shared/services/telemetry-service/lifecycle.d.ts +26 -1
- package/dist/_pkgs/affine-shared/services/telemetry-service/telemetry-service.d.ts +2 -2
- package/dist/_pkgs/affine-shared/services/theme-service.d.ts +19 -0
- package/dist/_pkgs/affine-shared/services/theme-service.js +24 -0
- package/dist/_pkgs/affine-shared/services/toolbar-service/command-action.d.ts +34 -0
- package/dist/_pkgs/affine-shared/services/toolbar-service/command-action.js +63 -0
- package/dist/_pkgs/affine-shared/services/toolbar-service/index.d.ts +1 -0
- package/dist/_pkgs/affine-shared/services/toolbar-service/index.js +1 -0
- package/dist/_pkgs/affine-shared/services/translation-service/chrome.d.ts +97 -7
- package/dist/_pkgs/affine-shared/services/translation-service/chrome.js +178 -7
- package/dist/_pkgs/affine-shared/styles/index.d.ts +1 -0
- package/dist/_pkgs/affine-shared/styles/index.js +1 -0
- package/dist/_pkgs/affine-shared/styles/motion.d.ts +14 -0
- package/dist/_pkgs/affine-shared/styles/motion.js +38 -0
- package/dist/_pkgs/affine-shared/utils/event.d.ts +10 -0
- package/dist/_pkgs/affine-shared/utils/event.js +20 -0
- package/dist/_pkgs/affine-shared/utils/file/filesys.d.ts +16 -0
- package/dist/_pkgs/affine-shared/utils/file/filesys.js +25 -0
- package/dist/_pkgs/affine-shared/utils/index.d.ts +1 -0
- package/dist/_pkgs/affine-shared/utils/index.js +1 -0
- package/dist/_pkgs/affine-shared/utils/link-preview-refresh.d.ts +12 -0
- package/dist/_pkgs/affine-shared/utils/link-preview-refresh.js +13 -0
- package/dist/_pkgs/affine-widget-edgeless-dragging-area/edgeless-dragging-area-rect.js +2 -2
- package/dist/_pkgs/affine-widget-edgeless-selected-rect/utils.js +5 -1
- package/dist/_pkgs/affine-widget-edgeless-toolbar/catalogue/artefact-catalogue-widget.d.ts +12 -4
- package/dist/_pkgs/affine-widget-edgeless-toolbar/catalogue/artefact-catalogue-widget.js +27 -4
- package/dist/_pkgs/affine-widget-edgeless-toolbar/config/types.d.ts +15 -0
- package/dist/_pkgs/affine-widget-edgeless-toolbar/config/utils.d.ts +1 -1
- package/dist/_pkgs/affine-widget-edgeless-toolbar/config/utils.js +7 -2
- package/dist/_pkgs/affine-widget-edgeless-toolbar/create-popper.js +13 -0
- package/dist/_pkgs/affine-widget-edgeless-toolbar/index.d.ts +2 -0
- package/dist/_pkgs/affine-widget-edgeless-toolbar/index.js +2 -0
- package/dist/_pkgs/affine-widget-edgeless-toolbar/menu/command-menu.d.ts +80 -0
- package/dist/_pkgs/affine-widget-edgeless-toolbar/menu/command-menu.js +270 -81
- package/dist/_pkgs/affine-widget-edgeless-toolbar/menu/senior-menu-selection.d.ts +15 -0
- package/dist/_pkgs/affine-widget-edgeless-toolbar/menu/senior-menu-selection.js +15 -0
- package/dist/_pkgs/affine-widget-edgeless-toolbar/panel/font-family-panel.d.ts +18 -0
- package/dist/_pkgs/affine-widget-edgeless-toolbar/panel/font-family-panel.js +52 -6
- package/dist/_pkgs/affine-widget-edgeless-toolbar/panel/font-weight-and-style-panel.js +8 -1
- package/dist/_pkgs/affine-widget-edgeless-toolbar/placement/artefact-ghost-overlay.d.ts +42 -0
- package/dist/_pkgs/affine-widget-edgeless-toolbar/placement/artefact-ghost-overlay.js +100 -0
- package/dist/_pkgs/affine-widget-edgeless-toolbar/placement/artefact-placement-tool.d.ts +100 -0
- package/dist/_pkgs/affine-widget-edgeless-toolbar/placement/artefact-placement-tool.js +274 -0
- package/dist/_pkgs/affine-widget-edgeless-toolbar/placement/index.d.ts +3 -0
- package/dist/_pkgs/affine-widget-edgeless-toolbar/placement/index.js +3 -0
- package/dist/_pkgs/affine-widget-edgeless-toolbar/placement/translate-created.d.ts +25 -0
- package/dist/_pkgs/affine-widget-edgeless-toolbar/placement/translate-created.js +67 -0
- package/dist/_pkgs/affine-widget-edgeless-toolbar/translations.d.ts +6 -0
- package/dist/_pkgs/affine-widget-edgeless-toolbar/translations.js +10 -0
- package/dist/_pkgs/affine-widget-edgeless-toolbar/view.js +5 -0
- package/dist/_pkgs/affine-widget-frame-title/edgeless-frame-title-editor.js +2 -1
- package/dist/_pkgs/affine-widget-slash-menu/translations.d.ts +16 -0
- package/dist/_pkgs/affine-widget-slash-menu/translations.js +23 -1
- package/dist/_pkgs/affine-widget-toolbar/utils.js +57 -14
- package/dist/_pkgs/data-view/core/detail/field.js +2 -1
- package/dist/_pkgs/data-view/core/filter/literal/define.js +3 -1
- package/dist/_pkgs/data-view/core/group-by/renderer/boolean-group.js +1 -1
- package/dist/_pkgs/data-view/property-presets/checkbox/cell-renderer.js +8 -2
- package/dist/_pkgs/data-view/view-presets/kanban/pc/cell.js +1 -1
- package/dist/_pkgs/data-view/view-presets/kanban/pc/controller/drag.js +2 -1
- package/dist/_pkgs/data-view/view-presets/table/pc/controller/drag.js +2 -1
- package/dist/_pkgs/data-view/view-presets/table/pc/controller/selection.js +1 -1
- package/dist/_pkgs/data-view/view-presets/table/pc/header/vertical-indicator.js +2 -1
- package/dist/_pkgs/data-view/view-presets/table/pc/row/row-select-checkbox.js +3 -1
- package/dist/_pkgs/data-view/view-presets/table/pc-virtual/controller/drag.js +2 -1
- package/dist/_pkgs/data-view/view-presets/table/pc-virtual/controller/selection.js +1 -1
- package/dist/_pkgs/data-view/view-presets/table/pc-virtual/group/top/header/vertical-indicator.js +2 -1
- package/dist/_pkgs/data-view/view-presets/table/pc-virtual/row/row-header.js +3 -1
- package/dist/_pkgs/global/gfx/xywh.js +7 -0
- package/dist/_pkgs/std/extension/command-registry.d.ts +158 -1
- package/dist/_pkgs/std/extension/command-registry.js +22 -0
- package/dist/_pkgs/std/gfx/index.d.ts +1 -1
- package/dist/_pkgs/std/gfx/interactivity/gfx-view-event-handler.d.ts +12 -0
- package/dist/_pkgs/std/gfx/interactivity/gfx-view-event-handler.js +20 -1
- package/dist/_pkgs/std/gfx/interactivity/manager.d.ts +10 -0
- package/dist/_pkgs/std/gfx/interactivity/manager.js +12 -0
- package/dist/_pkgs/std/gfx/model/surface/element-model.js +12 -7
- package/dist/_pkgs/std/gfx/model/surface/role.d.ts +10 -5
- package/dist/_pkgs/std/gfx/model/surface/surface-model.d.ts +56 -0
- package/dist/_pkgs/std/gfx/model/surface/surface-model.js +84 -3
- package/dist/_pkgs/std/gfx/view/view.d.ts +11 -2
- package/dist/_pkgs/std/gfx/view/view.js +16 -2
- package/dist/commands.d.ts +6 -0
- package/dist/commands.js +10 -2
- package/dist/frameworks.d.ts +9 -0
- package/dist/frameworks.js +19 -0
- package/dist/translations.js +21 -0
- package/package.json +13 -4
- package/dist/_pkgs/affine-gfx-group/group-watcher.d.ts +0 -1
- package/dist/_pkgs/affine-gfx-group/group-watcher.js +0 -20
|
@@ -34,15 +34,20 @@ var __runInitializers = (this && this.__runInitializers) || function (thisArg, i
|
|
|
34
34
|
};
|
|
35
35
|
import { TextUtils } from '../../affine-block-surface/index.js';
|
|
36
36
|
import { FontFamily, FontFamilyList } from '../../affine-model/index.js';
|
|
37
|
+
import { fillPlaceholders, FontConfigIdentifier, translateKey, } from '../../affine-shared/services/index.js';
|
|
37
38
|
import { DoneIcon } from '@blocksuite/icons/lit';
|
|
38
39
|
import { css, html, LitElement, nothing } from 'lit';
|
|
39
40
|
import { property } from 'lit/decorators.js';
|
|
40
41
|
import { repeat } from 'lit/directives/repeat.js';
|
|
42
|
+
import { EDGELESS_TOOLBAR_FONT_FAMILY_UNAVAILABLE } from '../translations.js';
|
|
41
43
|
let EdgelessFontFamilyPanel = (() => {
|
|
42
44
|
let _classSuper = LitElement;
|
|
43
45
|
let _onSelect_decorators;
|
|
44
46
|
let _onSelect_initializers = [];
|
|
45
47
|
let _onSelect_extraInitializers = [];
|
|
48
|
+
let _std_decorators;
|
|
49
|
+
let _std_initializers = [];
|
|
50
|
+
let _std_extraInitializers = [];
|
|
46
51
|
let _value_decorators;
|
|
47
52
|
let _value_initializers = [];
|
|
48
53
|
let _value_extraInitializers = [];
|
|
@@ -50,8 +55,10 @@ let EdgelessFontFamilyPanel = (() => {
|
|
|
50
55
|
static {
|
|
51
56
|
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
|
|
52
57
|
_onSelect_decorators = [property({ attribute: false })];
|
|
58
|
+
_std_decorators = [property({ attribute: false })];
|
|
53
59
|
_value_decorators = [property({ attribute: false })];
|
|
54
60
|
__esDecorate(this, null, _onSelect_decorators, { kind: "accessor", name: "onSelect", static: false, private: false, access: { has: obj => "onSelect" in obj, get: obj => obj.onSelect, set: (obj, value) => { obj.onSelect = value; } }, metadata: _metadata }, _onSelect_initializers, _onSelect_extraInitializers);
|
|
61
|
+
__esDecorate(this, null, _std_decorators, { kind: "accessor", name: "std", static: false, private: false, access: { has: obj => "std" in obj, get: obj => obj.std, set: (obj, value) => { obj.std = value; } }, metadata: _metadata }, _std_initializers, _std_extraInitializers);
|
|
55
62
|
__esDecorate(this, null, _value_decorators, { kind: "accessor", name: "value", static: false, private: false, access: { has: obj => "value" in obj, get: obj => obj.value, set: (obj, value) => { obj.value = value; } }, metadata: _metadata }, _value_initializers, _value_extraInitializers);
|
|
56
63
|
if (_metadata) Object.defineProperty(this, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
57
64
|
}
|
|
@@ -67,26 +74,59 @@ let EdgelessFontFamilyPanel = (() => {
|
|
|
67
74
|
width: 100%;
|
|
68
75
|
}
|
|
69
76
|
`; }
|
|
77
|
+
/**
|
|
78
|
+
* The families the host configured: those with at least one face in its
|
|
79
|
+
* `FontConfig` (#396). Read from the config itself rather than from
|
|
80
|
+
* `document.fonts`, which the font loader fills a few seconds late for every
|
|
81
|
+
* non-critical family.
|
|
82
|
+
*
|
|
83
|
+
* `null` when no config is registered (the seam is absent, or empty, which
|
|
84
|
+
* the font loader also treats as absent): every family is offered, as before
|
|
85
|
+
* the seam narrowed the list. None of them has a file then, so each paints
|
|
86
|
+
* with the same fallback anyway.
|
|
87
|
+
*/
|
|
88
|
+
_configuredFamilies() {
|
|
89
|
+
const config = this.std?.getOptional(FontConfigIdentifier);
|
|
90
|
+
if (!config || config.length === 0)
|
|
91
|
+
return null;
|
|
92
|
+
return new Set(config.map(face => face.font));
|
|
93
|
+
}
|
|
70
94
|
_onSelect(value) {
|
|
71
95
|
this.value = value;
|
|
72
96
|
if (this.onSelect) {
|
|
73
97
|
this.onSelect(value);
|
|
74
98
|
}
|
|
75
99
|
}
|
|
100
|
+
_unavailableLabel(name) {
|
|
101
|
+
return this.std
|
|
102
|
+
? translateKey(this.std, ...EDGELESS_TOOLBAR_FONT_FAMILY_UNAVAILABLE, {
|
|
103
|
+
name,
|
|
104
|
+
})
|
|
105
|
+
: fillPlaceholders(EDGELESS_TOOLBAR_FONT_FAMILY_UNAVAILABLE[1], { name });
|
|
106
|
+
}
|
|
76
107
|
render() {
|
|
77
|
-
|
|
78
|
-
|
|
108
|
+
const configured = this._configuredFamilies();
|
|
109
|
+
// The current family stays listed even when the host no longer ships it:
|
|
110
|
+
// the element keeps it (and paints the fallback), so the picker names it
|
|
111
|
+
// rather than pretend the text has none. Greyed and never picked from
|
|
112
|
+
// here, so nothing rewrites the stored value behind the user's back.
|
|
113
|
+
const families = FontFamilyList.filter(([font]) => !configured || configured.has(font) || font === this.value);
|
|
114
|
+
return repeat(families, item => item[0], ([font, name]) => {
|
|
115
|
+
const unavailable = !!configured && !configured.has(font);
|
|
116
|
+
const current = this.value === font;
|
|
79
117
|
return html `
|
|
80
118
|
<edgeless-tool-icon-button
|
|
81
119
|
data-font="${name}"
|
|
82
120
|
style="font-family: ${TextUtils.wrapFontFamily(font)}"
|
|
83
121
|
.iconContainerPadding=${[4, 8]}
|
|
84
122
|
.justify=${'space-between'}
|
|
85
|
-
.active=${
|
|
123
|
+
.active=${current && !unavailable}
|
|
124
|
+
.disabled=${unavailable}
|
|
86
125
|
.iconSize=${'20px'}
|
|
87
|
-
@click=${() => this._onSelect(font)}
|
|
126
|
+
@click=${unavailable ? nothing : () => this._onSelect(font)}
|
|
88
127
|
>
|
|
89
|
-
${
|
|
128
|
+
${unavailable ? this._unavailableLabel(name) : name}
|
|
129
|
+
${current ? DoneIcon() : nothing}
|
|
90
130
|
</edgeless-tool-icon-button>
|
|
91
131
|
`;
|
|
92
132
|
});
|
|
@@ -94,7 +134,13 @@ let EdgelessFontFamilyPanel = (() => {
|
|
|
94
134
|
#onSelect_accessor_storage = __runInitializers(this, _onSelect_initializers, undefined);
|
|
95
135
|
get onSelect() { return this.#onSelect_accessor_storage; }
|
|
96
136
|
set onSelect(value) { this.#onSelect_accessor_storage = value; }
|
|
97
|
-
#
|
|
137
|
+
#std_accessor_storage = (__runInitializers(this, _onSelect_extraInitializers), __runInitializers(this, _std_initializers, undefined));
|
|
138
|
+
/** Set by the caller that has one (`gfx/text`'s `createTextActions`): it
|
|
139
|
+
* carries the host's `FontConfig` and translations. Optional, so the panel
|
|
140
|
+
* still renders (every family, in English) when created with none. */
|
|
141
|
+
get std() { return this.#std_accessor_storage; }
|
|
142
|
+
set std(value) { this.#std_accessor_storage = value; }
|
|
143
|
+
#value_accessor_storage = (__runInitializers(this, _std_extraInitializers), __runInitializers(this, _value_initializers, FontFamily.Inter));
|
|
98
144
|
get value() { return this.#value_accessor_storage; }
|
|
99
145
|
set value(value) { this.#value_accessor_storage = value; }
|
|
100
146
|
constructor() {
|
|
@@ -34,16 +34,23 @@ var __runInitializers = (this && this.__runInitializers) || function (thisArg, i
|
|
|
34
34
|
};
|
|
35
35
|
import { TextUtils } from '../../affine-block-surface/index.js';
|
|
36
36
|
import { FontFamily, FontFamilyMap, FontStyle, FontWeight, } from '../../affine-model/index.js';
|
|
37
|
-
import { FONT_STYLE_ITALIC, FONT_WEIGHT_LIGHT, FONT_WEIGHT_REGULAR, FONT_WEIGHT_SEMIBOLD, translateKey, } from '../../affine-shared/services/index.js';
|
|
37
|
+
import { FONT_STYLE_ITALIC, FONT_WEIGHT_BOLD, FONT_WEIGHT_LIGHT, FONT_WEIGHT_REGULAR, FONT_WEIGHT_SEMIBOLD, translateKey, } from '../../affine-shared/services/index.js';
|
|
38
38
|
import { DoneIcon } from '@blocksuite/icons/lit';
|
|
39
39
|
import { css, html, LitElement, nothing } from 'lit';
|
|
40
40
|
import { property } from 'lit/decorators.js';
|
|
41
41
|
import { join } from 'lit/directives/join.js';
|
|
42
42
|
import { repeat } from 'lit/directives/repeat.js';
|
|
43
|
+
/**
|
|
44
|
+
* How each weight is named. The panel does not offer this list: it offers the
|
|
45
|
+
* faces the current family actually has loaded, and only borrows the wording
|
|
46
|
+
* from here — so a family that ships no 700 file simply never draws a Bold
|
|
47
|
+
* row.
|
|
48
|
+
*/
|
|
43
49
|
const FONT_WEIGHT_CHOOSE = [
|
|
44
50
|
[FontWeight.Light, FONT_WEIGHT_LIGHT],
|
|
45
51
|
[FontWeight.Regular, FONT_WEIGHT_REGULAR],
|
|
46
52
|
[FontWeight.SemiBold, FONT_WEIGHT_SEMIBOLD],
|
|
53
|
+
[FontWeight.Bold, FONT_WEIGHT_BOLD],
|
|
47
54
|
];
|
|
48
55
|
let EdgelessFontWeightAndStylePanel = (() => {
|
|
49
56
|
let _classSuper = LitElement;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { type RoughCanvas, ToolOverlay } from '../../affine-block-surface/index.js';
|
|
2
|
+
import type { Bound } from '../../global/gfx/index.js';
|
|
3
|
+
import type { GfxController, GfxPrimitiveElementModel } from '../../std/gfx/index.js';
|
|
4
|
+
/**
|
|
5
|
+
* The ghost an armed {@link ArtefactPlacementTool} leaves under the cursor: the
|
|
6
|
+
* artefact itself, painted by the very renderers that will paint it once it is
|
|
7
|
+
* placed, at full opacity (PO decision, 2026-09-16).
|
|
8
|
+
*
|
|
9
|
+
* The elements are DETACHED models (`createDetachedElement`), built once by the
|
|
10
|
+
* tool from the recording of the command — never per frame, and never in the
|
|
11
|
+
* document. Each frame only runs the renderers, in paint order.
|
|
12
|
+
*
|
|
13
|
+
* When nothing could be built — the recording threw, or recorded nothing the
|
|
14
|
+
* surface can build — the ghost falls back to what the tool can still promise:
|
|
15
|
+
* a dashed footprint and the command's label under it. A real preview carries
|
|
16
|
+
* its own words, so it gets no label.
|
|
17
|
+
*
|
|
18
|
+
* Like `ShapeOverlay`, everything is positioned from {@link ToolOverlay.x} /
|
|
19
|
+
* {@link ToolOverlay.y} — the cursor in model coordinates — and the recorded
|
|
20
|
+
* boxes are offsets around it, because the recording ran against a viewport
|
|
21
|
+
* whose centre was the origin. The same offset is what the placement re-applies
|
|
22
|
+
* for real.
|
|
23
|
+
*/
|
|
24
|
+
export declare class ArtefactGhostOverlay extends ToolOverlay {
|
|
25
|
+
/** The footprint, relative to the cursor. */
|
|
26
|
+
bound: Bound;
|
|
27
|
+
/** What the command is called, in the reader's language. */
|
|
28
|
+
label: string;
|
|
29
|
+
/** The artefact's drawable elements, in paint order, with their renderer. */
|
|
30
|
+
private readonly _preview;
|
|
31
|
+
constructor(gfx: GfxController, bound: Bound, label: string, models?: GfxPrimitiveElementModel[]);
|
|
32
|
+
/** Whether the artefact itself is drawn, rather than the fallback box. */
|
|
33
|
+
get drawsArtefact(): boolean;
|
|
34
|
+
render(ctx: CanvasRenderingContext2D, rc: RoughCanvas): void;
|
|
35
|
+
/**
|
|
36
|
+
* What the surface's render loop does per element, with the cursor in place
|
|
37
|
+
* of the element's position: the context is already in model coordinates
|
|
38
|
+
* here, so the element's matrix is that transform moved to cursor + offset.
|
|
39
|
+
*/
|
|
40
|
+
private _renderArtefact;
|
|
41
|
+
private _renderFootprint;
|
|
42
|
+
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { CanvasRenderer, ElementRendererIdentifier, ToolOverlay, } from '../../affine-block-surface/index.js';
|
|
2
|
+
import { ThemeProvider } from '../../affine-shared/services/index.js';
|
|
3
|
+
/** Gap between the bottom of the footprint and the baseline of the label. */
|
|
4
|
+
const LABEL_GAP = 16;
|
|
5
|
+
/** Label size in SCREEN pixels; divided by the zoom before it is drawn. */
|
|
6
|
+
const LABEL_SIZE = 12;
|
|
7
|
+
/**
|
|
8
|
+
* The ghost an armed {@link ArtefactPlacementTool} leaves under the cursor: the
|
|
9
|
+
* artefact itself, painted by the very renderers that will paint it once it is
|
|
10
|
+
* placed, at full opacity (PO decision, 2026-09-16).
|
|
11
|
+
*
|
|
12
|
+
* The elements are DETACHED models (`createDetachedElement`), built once by the
|
|
13
|
+
* tool from the recording of the command — never per frame, and never in the
|
|
14
|
+
* document. Each frame only runs the renderers, in paint order.
|
|
15
|
+
*
|
|
16
|
+
* When nothing could be built — the recording threw, or recorded nothing the
|
|
17
|
+
* surface can build — the ghost falls back to what the tool can still promise:
|
|
18
|
+
* a dashed footprint and the command's label under it. A real preview carries
|
|
19
|
+
* its own words, so it gets no label.
|
|
20
|
+
*
|
|
21
|
+
* Like `ShapeOverlay`, everything is positioned from {@link ToolOverlay.x} /
|
|
22
|
+
* {@link ToolOverlay.y} — the cursor in model coordinates — and the recorded
|
|
23
|
+
* boxes are offsets around it, because the recording ran against a viewport
|
|
24
|
+
* whose centre was the origin. The same offset is what the placement re-applies
|
|
25
|
+
* for real.
|
|
26
|
+
*/
|
|
27
|
+
export class ArtefactGhostOverlay extends ToolOverlay {
|
|
28
|
+
constructor(gfx, bound, label, models = []) {
|
|
29
|
+
super(gfx);
|
|
30
|
+
this.bound = bound;
|
|
31
|
+
this.label = label;
|
|
32
|
+
// Resolved once: a type without a canvas renderer is skipped silently, as
|
|
33
|
+
// the surface's own render loop skips it.
|
|
34
|
+
this._preview = models.flatMap(model => {
|
|
35
|
+
const render = gfx.std.getOptional(ElementRendererIdentifier(model.type));
|
|
36
|
+
return render ? [{ model, render }] : [];
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
/** Whether the artefact itself is drawn, rather than the fallback box. */
|
|
40
|
+
get drawsArtefact() {
|
|
41
|
+
return this._preview.length > 0;
|
|
42
|
+
}
|
|
43
|
+
render(ctx, rc) {
|
|
44
|
+
ctx.globalAlpha = this.globalAlpha;
|
|
45
|
+
if (this.globalAlpha === 0)
|
|
46
|
+
return;
|
|
47
|
+
const renderer = this.gfx.surfaceComponent
|
|
48
|
+
?.renderer;
|
|
49
|
+
if (this.drawsArtefact && renderer instanceof CanvasRenderer) {
|
|
50
|
+
this._renderArtefact(ctx, rc, renderer);
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
this._renderFootprint(ctx);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* What the surface's render loop does per element, with the cursor in place
|
|
58
|
+
* of the element's position: the context is already in model coordinates
|
|
59
|
+
* here, so the element's matrix is that transform moved to cursor + offset.
|
|
60
|
+
*/
|
|
61
|
+
_renderArtefact(ctx, rc, renderer) {
|
|
62
|
+
const base = ctx.getTransform();
|
|
63
|
+
const viewportBound = this.gfx.viewport.viewportBounds;
|
|
64
|
+
for (const { model, render } of this._preview) {
|
|
65
|
+
const [x, y] = model.deserializedXYWH;
|
|
66
|
+
ctx.save();
|
|
67
|
+
ctx.globalAlpha = model.opacity ?? 1;
|
|
68
|
+
render(model, ctx, base.translate(this.x + x, this.y + y), renderer, rc, viewportBound);
|
|
69
|
+
ctx.restore();
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
_renderFootprint(ctx) {
|
|
73
|
+
const theme = this.gfx.std.get(ThemeProvider);
|
|
74
|
+
const stroke = theme.getCssVariableColor('--affine-primary-color');
|
|
75
|
+
const text = theme.getCssVariableColor('--affine-text-secondary-color');
|
|
76
|
+
// Chrome, not content: the outline and the label keep their size on screen
|
|
77
|
+
// whatever the zoom, the way the polygon tool's own indicators do.
|
|
78
|
+
const zoom = this.gfx.viewport.zoom;
|
|
79
|
+
const { bound } = this;
|
|
80
|
+
const x = this.x + bound.x;
|
|
81
|
+
const y = this.y + bound.y;
|
|
82
|
+
const radius = Math.min(8 / zoom, bound.w / 4, bound.h / 4);
|
|
83
|
+
ctx.save();
|
|
84
|
+
ctx.beginPath();
|
|
85
|
+
ctx.roundRect(x, y, bound.w, bound.h, radius);
|
|
86
|
+
ctx.strokeStyle = stroke;
|
|
87
|
+
ctx.lineWidth = 1.5 / zoom;
|
|
88
|
+
ctx.setLineDash([6 / zoom, 4 / zoom]);
|
|
89
|
+
ctx.stroke();
|
|
90
|
+
if (this.label) {
|
|
91
|
+
ctx.setLineDash([]);
|
|
92
|
+
ctx.font = `${LABEL_SIZE / zoom}px var(--affine-font-family, sans-serif)`;
|
|
93
|
+
ctx.fillStyle = text;
|
|
94
|
+
ctx.textAlign = 'center';
|
|
95
|
+
ctx.textBaseline = 'top';
|
|
96
|
+
ctx.fillText(this.label, x + bound.w / 2, y + bound.h + LABEL_GAP / zoom - LABEL_SIZE / zoom);
|
|
97
|
+
}
|
|
98
|
+
ctx.restore();
|
|
99
|
+
}
|
|
100
|
+
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { type AnyCommandDescriptor, type BlockStdScope, type CommandOwner, type PointerEventState } from '../../std/index.js';
|
|
2
|
+
import { BaseTool, type GfxController } from '../../std/gfx/index.js';
|
|
3
|
+
export type ArtefactPlacementOption = {
|
|
4
|
+
/** Whose senior menu armed this, and therefore whose row Shift+S walks. */
|
|
5
|
+
owner: CommandOwner;
|
|
6
|
+
command: AnyCommandDescriptor;
|
|
7
|
+
};
|
|
8
|
+
/**
|
|
9
|
+
* ONE tool for every framework's artefacts: pick one from a senior menu and it
|
|
10
|
+
* is not created, it is ARMED — a ghost follows the cursor and the click says
|
|
11
|
+
* where (PO decision, 2026-09-16).
|
|
12
|
+
*
|
|
13
|
+
* The shape tool has always worked this way, and a framework artefact is a
|
|
14
|
+
* shape the framework named. Before this, an artefact landed at the viewport
|
|
15
|
+
* centre whatever the author was looking at, and putting it where they meant it
|
|
16
|
+
* to go was a second gesture with a mouse held down.
|
|
17
|
+
*
|
|
18
|
+
* It is generic on purpose. Nothing here knows what a Wardley component or a
|
|
19
|
+
* BPMN gateway is: the armed {@link CommandDescriptor} carries its own label,
|
|
20
|
+
* its own creation body and its own telemetry, and the footprint is MEASURED by
|
|
21
|
+
* running that body against the recording fake (`recordAction`) rather than
|
|
22
|
+
* declared a second time. A ninth framework arms this tool by existing.
|
|
23
|
+
*
|
|
24
|
+
* What it deliberately does not do:
|
|
25
|
+
*
|
|
26
|
+
* - **Telemetry.** Arming and cycling emit nothing and record no usage, exactly
|
|
27
|
+
* as choosing a shape variant does. The one emission still happens where it
|
|
28
|
+
* always did — inside {@link runCommand}, at placement — so the numbers a
|
|
29
|
+
* framework already reports are unchanged, and a user who arms an artefact
|
|
30
|
+
* and changes their mind has not "used" it.
|
|
31
|
+
* - **Drag to size.** A framework artefact has a size its framework chose; the
|
|
32
|
+
* click places that size. Out of scope, deliberately.
|
|
33
|
+
*/
|
|
34
|
+
export declare class ArtefactPlacementTool extends BaseTool<ArtefactPlacementOption> {
|
|
35
|
+
static toolName: string;
|
|
36
|
+
private _ghost;
|
|
37
|
+
private get _surfaceComponent();
|
|
38
|
+
activate(): void;
|
|
39
|
+
deactivate(): void;
|
|
40
|
+
clearOverlay(): void;
|
|
41
|
+
/**
|
|
42
|
+
* Record the armed command once, and hang its ghost off the cursor.
|
|
43
|
+
*
|
|
44
|
+
* Once per arming and per cycle, never per pointer move: the recording runs
|
|
45
|
+
* the command's whole creation body against a fake and the preview builds a
|
|
46
|
+
* model per element, which is cheap but not free — and neither can change
|
|
47
|
+
* between two mouse positions.
|
|
48
|
+
*
|
|
49
|
+
* An artefact made of connectors only gets no ghost at all: a connector is
|
|
50
|
+
* not previewed (PO decision, 2026-09-16), and the crosshair alone says the
|
|
51
|
+
* next click places something.
|
|
52
|
+
*/
|
|
53
|
+
createOverlay(): void;
|
|
54
|
+
/**
|
|
55
|
+
* Place the artefact under the cursor.
|
|
56
|
+
*
|
|
57
|
+
* The command is not asked WHERE to create — every one of them creates around
|
|
58
|
+
* the viewport centre, and teaching eight frameworks' worth of actions to take
|
|
59
|
+
* a point would be the per-framework code this tool exists to avoid. So the
|
|
60
|
+
* command runs as it always has, and what it created is moved by the offset
|
|
61
|
+
* between the centre it aimed at and the point the user clicked. That offset
|
|
62
|
+
* is read BEFORE the run, because a command may move the viewport.
|
|
63
|
+
*/
|
|
64
|
+
click(e: PointerEventState): void;
|
|
65
|
+
pointerMove(e: PointerEventState): void;
|
|
66
|
+
pointerOut(e: PointerEventState): void;
|
|
67
|
+
/** A framework artefact keeps the size its framework chose; a drag is a click. */
|
|
68
|
+
dragStart(_e: PointerEventState): void;
|
|
69
|
+
dragMove(_e: PointerEventState): void;
|
|
70
|
+
dragEnd(_e: PointerEventState): void;
|
|
71
|
+
}
|
|
72
|
+
/** The armed artefact, or `null` when the editor is on any other tool. */
|
|
73
|
+
export declare function armedArtefact(gfx: GfxController): ArtefactPlacementOption | null;
|
|
74
|
+
/** Arm `command`; the ghost appears with the next pointer move. */
|
|
75
|
+
export declare function armArtefact(gfx: GfxController, owner: CommandOwner, command: AnyCommandDescriptor): void;
|
|
76
|
+
/**
|
|
77
|
+
* The artefacts of one owner, in the order its senior menu shows them.
|
|
78
|
+
*
|
|
79
|
+
* The MENU's row and not the whole catalogue: cycling is a keyboard walk along
|
|
80
|
+
* a row of buttons the user is looking at, and a Shift+S that stepped onto an
|
|
81
|
+
* artefact filed away in the sidepanel would move the ghost with nothing on
|
|
82
|
+
* screen to explain it. An owner past the fourteen-slot cap therefore cycles
|
|
83
|
+
* through its thirteen ranked artefacts; the rest stay one catalogue away.
|
|
84
|
+
*
|
|
85
|
+
* `kind` is what decides, not the owner: an entry of kind `'tool'` — a link
|
|
86
|
+
* tool, the evolution arrow, the Wardley area polygon — arms a gesture of its
|
|
87
|
+
* own and has no footprint to ghost, so it is never armed here and never
|
|
88
|
+
* stepped onto.
|
|
89
|
+
*/
|
|
90
|
+
export declare function artefactCommandsFor(std: BlockStdScope, owner: CommandOwner): AnyCommandDescriptor[];
|
|
91
|
+
/**
|
|
92
|
+
* Arm the artefact `dir` steps along the owner's row, wrapping at both ends.
|
|
93
|
+
* Returns false when nothing is armed, so a caller can fall through to whatever
|
|
94
|
+
* the keystroke means otherwise.
|
|
95
|
+
*
|
|
96
|
+
* An artefact armed from the catalogue is not in the row: a backwards step then
|
|
97
|
+
* enters on the row's last entry, a forwards one on its first — the same "enter
|
|
98
|
+
* from nothing" the open menu's highlight gives.
|
|
99
|
+
*/
|
|
100
|
+
export declare function cycleArmedArtefact(gfx: GfxController, dir: 1 | -1): boolean;
|
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
import { DefaultTool, EXCLUDING_MOUSE_OUT_CLASS_LIST, recordAction, sortIndex, } from '../../affine-block-surface/index.js';
|
|
2
|
+
import { translateKey } from '../../affine-shared/services/index.js';
|
|
3
|
+
import { hasClassNameInList } from '../../affine-shared/utils/index.js';
|
|
4
|
+
import { Bound } from '../../global/gfx/index.js';
|
|
5
|
+
import { runCommand, } from '../../std/index.js';
|
|
6
|
+
import { BaseTool, GfxGroupLikeElementModel, } from '../../std/gfx/index.js';
|
|
7
|
+
import { seniorMenuSelection } from '../menu/senior-menu-selection.js';
|
|
8
|
+
import { ArtefactGhostOverlay } from './artefact-ghost-overlay.js';
|
|
9
|
+
import { collectCreated, translateCreated } from './translate-created.js';
|
|
10
|
+
/** The ghost of an artefact nobody could measure. */
|
|
11
|
+
const FALLBACK_FOOTPRINT = new Bound(-60, -30, 120, 60);
|
|
12
|
+
/**
|
|
13
|
+
* ONE tool for every framework's artefacts: pick one from a senior menu and it
|
|
14
|
+
* is not created, it is ARMED — a ghost follows the cursor and the click says
|
|
15
|
+
* where (PO decision, 2026-09-16).
|
|
16
|
+
*
|
|
17
|
+
* The shape tool has always worked this way, and a framework artefact is a
|
|
18
|
+
* shape the framework named. Before this, an artefact landed at the viewport
|
|
19
|
+
* centre whatever the author was looking at, and putting it where they meant it
|
|
20
|
+
* to go was a second gesture with a mouse held down.
|
|
21
|
+
*
|
|
22
|
+
* It is generic on purpose. Nothing here knows what a Wardley component or a
|
|
23
|
+
* BPMN gateway is: the armed {@link CommandDescriptor} carries its own label,
|
|
24
|
+
* its own creation body and its own telemetry, and the footprint is MEASURED by
|
|
25
|
+
* running that body against the recording fake (`recordAction`) rather than
|
|
26
|
+
* declared a second time. A ninth framework arms this tool by existing.
|
|
27
|
+
*
|
|
28
|
+
* What it deliberately does not do:
|
|
29
|
+
*
|
|
30
|
+
* - **Telemetry.** Arming and cycling emit nothing and record no usage, exactly
|
|
31
|
+
* as choosing a shape variant does. The one emission still happens where it
|
|
32
|
+
* always did — inside {@link runCommand}, at placement — so the numbers a
|
|
33
|
+
* framework already reports are unchanged, and a user who arms an artefact
|
|
34
|
+
* and changes their mind has not "used" it.
|
|
35
|
+
* - **Drag to size.** A framework artefact has a size its framework chose; the
|
|
36
|
+
* click places that size. Out of scope, deliberately.
|
|
37
|
+
*/
|
|
38
|
+
export class ArtefactPlacementTool extends BaseTool {
|
|
39
|
+
constructor() {
|
|
40
|
+
super(...arguments);
|
|
41
|
+
this._ghost = null;
|
|
42
|
+
}
|
|
43
|
+
static { this.toolName = 'artefact-placement'; }
|
|
44
|
+
get _surfaceComponent() {
|
|
45
|
+
return this.gfx.surfaceComponent;
|
|
46
|
+
}
|
|
47
|
+
activate() {
|
|
48
|
+
this.createOverlay();
|
|
49
|
+
}
|
|
50
|
+
deactivate() {
|
|
51
|
+
this.clearOverlay();
|
|
52
|
+
}
|
|
53
|
+
clearOverlay() {
|
|
54
|
+
if (!this._ghost)
|
|
55
|
+
return;
|
|
56
|
+
this._ghost.dispose();
|
|
57
|
+
this._surfaceComponent?.renderer.removeOverlay(this._ghost);
|
|
58
|
+
this._ghost = null;
|
|
59
|
+
this._surfaceComponent?.renderer.refresh();
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Record the armed command once, and hang its ghost off the cursor.
|
|
63
|
+
*
|
|
64
|
+
* Once per arming and per cycle, never per pointer move: the recording runs
|
|
65
|
+
* the command's whole creation body against a fake and the preview builds a
|
|
66
|
+
* model per element, which is cheap but not free — and neither can change
|
|
67
|
+
* between two mouse positions.
|
|
68
|
+
*
|
|
69
|
+
* An artefact made of connectors only gets no ghost at all: a connector is
|
|
70
|
+
* not previewed (PO decision, 2026-09-16), and the crosshair alone says the
|
|
71
|
+
* next click places something.
|
|
72
|
+
*/
|
|
73
|
+
createOverlay() {
|
|
74
|
+
this.clearOverlay();
|
|
75
|
+
const { command } = this.activatedOption;
|
|
76
|
+
if (!command)
|
|
77
|
+
return;
|
|
78
|
+
const preview = previewOf(this.gfx, command);
|
|
79
|
+
if (!preview)
|
|
80
|
+
return;
|
|
81
|
+
this._ghost = new ArtefactGhostOverlay(this.gfx, preview.bound, translateKey(this.std, command.labelKey, command.labelFallback), preview.models);
|
|
82
|
+
this._surfaceComponent?.renderer.addOverlay(this._ghost);
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Place the artefact under the cursor.
|
|
86
|
+
*
|
|
87
|
+
* The command is not asked WHERE to create — every one of them creates around
|
|
88
|
+
* the viewport centre, and teaching eight frameworks' worth of actions to take
|
|
89
|
+
* a point would be the per-framework code this tool exists to avoid. So the
|
|
90
|
+
* command runs as it always has, and what it created is moved by the offset
|
|
91
|
+
* between the centre it aimed at and the point the user clicked. That offset
|
|
92
|
+
* is read BEFORE the run, because a command may move the viewport.
|
|
93
|
+
*/
|
|
94
|
+
click(e) {
|
|
95
|
+
const { command } = this.activatedOption;
|
|
96
|
+
this.clearOverlay();
|
|
97
|
+
if (!command)
|
|
98
|
+
return;
|
|
99
|
+
const { viewport } = this.gfx;
|
|
100
|
+
const [x, y] = viewport.toModelCoord(e.point.x, e.point.y);
|
|
101
|
+
const dx = x - viewport.centerX;
|
|
102
|
+
const dy = y - viewport.centerY;
|
|
103
|
+
this.doc.captureSync();
|
|
104
|
+
// THE bottleneck, not a shortcut past it: the placement is an invocation
|
|
105
|
+
// like any other, so `FrameworkElementAdded` and the usage measure are
|
|
106
|
+
// emitted exactly where they were before the tool existed.
|
|
107
|
+
const created = collectCreated(this.gfx, () => {
|
|
108
|
+
runCommand(this.std, command, {
|
|
109
|
+
surface: 'senior-menu',
|
|
110
|
+
source: 'toolbar:general',
|
|
111
|
+
});
|
|
112
|
+
});
|
|
113
|
+
const placed = translateCreated(this.gfx, created, dx, dy);
|
|
114
|
+
// `setTool` clears the selection, so the selection goes after it.
|
|
115
|
+
this.gfx.tool.setTool(DefaultTool);
|
|
116
|
+
if (placed.length) {
|
|
117
|
+
this.gfx.selection.set({ elements: placed, editing: false });
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
pointerMove(e) {
|
|
121
|
+
if (!this._ghost)
|
|
122
|
+
return;
|
|
123
|
+
if (this._ghost.globalAlpha === 0)
|
|
124
|
+
this._ghost.globalAlpha = 1;
|
|
125
|
+
const [x, y] = this.gfx.viewport.toModelCoord(e.x, e.y);
|
|
126
|
+
this._ghost.x = x;
|
|
127
|
+
this._ghost.y = y;
|
|
128
|
+
this._surfaceComponent?.refresh();
|
|
129
|
+
}
|
|
130
|
+
pointerOut(e) {
|
|
131
|
+
if (e.raw.relatedTarget &&
|
|
132
|
+
hasClassNameInList(e.raw.relatedTarget, EXCLUDING_MOUSE_OUT_CLASS_LIST))
|
|
133
|
+
return;
|
|
134
|
+
if (!this._ghost)
|
|
135
|
+
return;
|
|
136
|
+
this._ghost.globalAlpha = 0;
|
|
137
|
+
this._surfaceComponent?.refresh();
|
|
138
|
+
}
|
|
139
|
+
/** A framework artefact keeps the size its framework chose; a drag is a click. */
|
|
140
|
+
dragStart(_e) { }
|
|
141
|
+
dragMove(_e) { }
|
|
142
|
+
dragEnd(_e) { }
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* What the command would draw, recorded and BUILT by running it against
|
|
146
|
+
* nothing: its footprint, and a detached model per drawable element, in paint
|
|
147
|
+
* order. `null` when there is nothing to show but the crosshair.
|
|
148
|
+
*
|
|
149
|
+
* The recording's viewport centre is the origin, so every recorded box is
|
|
150
|
+
* already the offset around a real centre — and therefore around the cursor.
|
|
151
|
+
* The records go to `createDetachedElement` as they were handed to the CRUD,
|
|
152
|
+
* so a seed string becomes its `Y.Text` through the element's own `propsToY`,
|
|
153
|
+
* exactly as it will at insertion; the host's `TranslationProvider` makes the
|
|
154
|
+
* seeds come out in the author's language, as they will once placed.
|
|
155
|
+
*
|
|
156
|
+
* Skipped: connectors (never previewed) and group-likes, whose renderers draw
|
|
157
|
+
* selection chrome and look their children up in the document — the children
|
|
158
|
+
* are drawn on their own. A record the surface cannot build is skipped too.
|
|
159
|
+
*
|
|
160
|
+
* A command the fake cannot serve throws by design (it answers only the
|
|
161
|
+
* members creation actions touch); that is not an error worth a console line
|
|
162
|
+
* here, it just means the ghost falls back to a plain box rather than the tool
|
|
163
|
+
* refusing to arm. So does a recording in which nothing could be built.
|
|
164
|
+
*/
|
|
165
|
+
function previewOf(gfx, command) {
|
|
166
|
+
let recorded;
|
|
167
|
+
try {
|
|
168
|
+
recorded = recordAction((std) => {
|
|
169
|
+
// An async body records nothing it does after its first `await`, and
|
|
170
|
+
// then fails on the fake: that late failure is the same "cannot
|
|
171
|
+
// preview", not an unhandled rejection in the console.
|
|
172
|
+
Promise.resolve(command.run(std, { surface: 'senior-menu', source: 'internal' })).catch(() => { });
|
|
173
|
+
}, { host: gfx.std });
|
|
174
|
+
}
|
|
175
|
+
catch {
|
|
176
|
+
return { bound: FALLBACK_FOOTPRINT, models: [] };
|
|
177
|
+
}
|
|
178
|
+
const { records } = recorded;
|
|
179
|
+
if (records.length > 0 && records.every(r => r['type'] === 'connector')) {
|
|
180
|
+
return null;
|
|
181
|
+
}
|
|
182
|
+
// Paint order as the surface derives it: a group's children sort under the
|
|
183
|
+
// group's own index, even though the group itself is not drawn.
|
|
184
|
+
const groupIndexMap = new Map();
|
|
185
|
+
for (const record of records) {
|
|
186
|
+
const children = record['children'];
|
|
187
|
+
if (record['type'] !== 'group' || typeof children !== 'object')
|
|
188
|
+
continue;
|
|
189
|
+
const group = { id: String(record['id']), index: String(record['index']) };
|
|
190
|
+
for (const childId of Object.keys(children ?? {})) {
|
|
191
|
+
groupIndexMap.set(childId, group);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
const ordered = records
|
|
195
|
+
.map(record => ({
|
|
196
|
+
record,
|
|
197
|
+
id: String(record['id']),
|
|
198
|
+
index: String(record['index']),
|
|
199
|
+
}))
|
|
200
|
+
.sort((a, b) => sortIndex(a, b, groupIndexMap));
|
|
201
|
+
const { surface } = gfx;
|
|
202
|
+
const models = [];
|
|
203
|
+
for (const { record, id } of ordered) {
|
|
204
|
+
const type = String(record['type']);
|
|
205
|
+
const Ctor = surface?.getConstructor(type);
|
|
206
|
+
if (!surface ||
|
|
207
|
+
!Ctor ||
|
|
208
|
+
type === 'connector' ||
|
|
209
|
+
Ctor.prototype instanceof GfxGroupLikeElementModel) {
|
|
210
|
+
continue;
|
|
211
|
+
}
|
|
212
|
+
try {
|
|
213
|
+
models.push(surface.createDetachedElement({ ...record, type, id }));
|
|
214
|
+
}
|
|
215
|
+
catch {
|
|
216
|
+
// Unbuildable here means unpaintable here; the rest still draws.
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
return { bound: recorded.bound ?? FALLBACK_FOOTPRINT, models };
|
|
220
|
+
}
|
|
221
|
+
/** The armed artefact, or `null` when the editor is on any other tool. */
|
|
222
|
+
export function armedArtefact(gfx) {
|
|
223
|
+
const { toolType, options } = gfx.tool.currentToolOption$.value ?? {};
|
|
224
|
+
if (toolType?.toolName !== ArtefactPlacementTool.toolName)
|
|
225
|
+
return null;
|
|
226
|
+
const armed = options;
|
|
227
|
+
return armed?.command ? armed : null;
|
|
228
|
+
}
|
|
229
|
+
/** Arm `command`; the ghost appears with the next pointer move. */
|
|
230
|
+
export function armArtefact(gfx, owner, command) {
|
|
231
|
+
gfx.tool.setTool(ArtefactPlacementTool, { owner, command });
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* The artefacts of one owner, in the order its senior menu shows them.
|
|
235
|
+
*
|
|
236
|
+
* The MENU's row and not the whole catalogue: cycling is a keyboard walk along
|
|
237
|
+
* a row of buttons the user is looking at, and a Shift+S that stepped onto an
|
|
238
|
+
* artefact filed away in the sidepanel would move the ghost with nothing on
|
|
239
|
+
* screen to explain it. An owner past the fourteen-slot cap therefore cycles
|
|
240
|
+
* through its thirteen ranked artefacts; the rest stay one catalogue away.
|
|
241
|
+
*
|
|
242
|
+
* `kind` is what decides, not the owner: an entry of kind `'tool'` — a link
|
|
243
|
+
* tool, the evolution arrow, the Wardley area polygon — arms a gesture of its
|
|
244
|
+
* own and has no footprint to ghost, so it is never armed here and never
|
|
245
|
+
* stepped onto.
|
|
246
|
+
*/
|
|
247
|
+
export function artefactCommandsFor(std, owner) {
|
|
248
|
+
return seniorMenuSelection(std, owner).commands.filter(command => command.kind === 'artefact');
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Arm the artefact `dir` steps along the owner's row, wrapping at both ends.
|
|
252
|
+
* Returns false when nothing is armed, so a caller can fall through to whatever
|
|
253
|
+
* the keystroke means otherwise.
|
|
254
|
+
*
|
|
255
|
+
* An artefact armed from the catalogue is not in the row: a backwards step then
|
|
256
|
+
* enters on the row's last entry, a forwards one on its first — the same "enter
|
|
257
|
+
* from nothing" the open menu's highlight gives.
|
|
258
|
+
*/
|
|
259
|
+
export function cycleArmedArtefact(gfx, dir) {
|
|
260
|
+
const armed = armedArtefact(gfx);
|
|
261
|
+
if (!armed)
|
|
262
|
+
return false;
|
|
263
|
+
const commands = artefactCommandsFor(gfx.std, armed.owner);
|
|
264
|
+
if (commands.length === 0)
|
|
265
|
+
return false;
|
|
266
|
+
const current = commands.findIndex(command => command.id === armed.command.id);
|
|
267
|
+
const next = current < 0
|
|
268
|
+
? dir === 1
|
|
269
|
+
? 0
|
|
270
|
+
: commands.length - 1
|
|
271
|
+
: (current + dir + commands.length) % commands.length;
|
|
272
|
+
armArtefact(gfx, armed.owner, commands[next]);
|
|
273
|
+
return true;
|
|
274
|
+
}
|