@formicoidea/labre-core 0.41.0 → 0.42.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/LICENSE +384 -0
- package/dist/_pkgs/affine-block-bookmark/bookmark-block.js +2 -2
- package/dist/_pkgs/affine-block-edgeless-text/edgeless-toolbar/config.js +7 -1
- package/dist/_pkgs/affine-block-embed/embed-figma-block/embed-figma-block.js +2 -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/consts.d.ts +2 -0
- package/dist/_pkgs/affine-block-embed/embed-iframe-block/consts.js +5 -0
- package/dist/_pkgs/affine-block-embed/embed-iframe-block/embed-iframe-block.d.ts +1 -0
- package/dist/_pkgs/affine-block-embed/embed-iframe-block/embed-iframe-block.js +30 -8
- 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 +2 -1
- package/dist/_pkgs/affine-block-embed/embed-youtube-block/embed-youtube-block.js +2 -1
- package/dist/_pkgs/affine-block-frame/frame-manager.js +1 -1
- 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-note/note-keymap.js +7 -1
- package/dist/_pkgs/affine-block-paragraph/paragraph-keymap.js +7 -1
- 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/keyboard/keymap.js +1 -16
- 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 +241 -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 +136 -0
- package/dist/_pkgs/affine-block-surface/extensions/legend.js +439 -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/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/index.d.ts +1 -0
- package/dist/_pkgs/affine-block-surface/framework-background/index.js +1 -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/view.js +8 -1
- package/dist/_pkgs/affine-block-surface-ref/configs/slash-menu.js +1 -1
- 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 +440 -0
- 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/resource/resource.js +29 -16
- 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-gfx-brush/element-renderer.js +2 -2
- 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/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 +216 -54
- 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 +72 -4
- 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/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/templates/index.js +1 -1
- package/dist/_pkgs/affine-gfx-mindmap/toolbar/basket-elements.js +1 -1
- package/dist/_pkgs/affine-gfx-mindmap/toolbar/utils/import-mindmap.js +2 -2
- package/dist/_pkgs/affine-gfx-mindmap/translations.d.ts +1 -1
- package/dist/_pkgs/affine-gfx-mindmap/translations.js +1 -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 +6 -1
- package/dist/_pkgs/affine-gfx-shape/toolbar/palette-color-action.js +11 -1
- package/dist/_pkgs/affine-gfx-template/builtin/other.js +1 -1
- package/dist/_pkgs/affine-gfx-template/snapshot-from-action.js +32 -119
- package/dist/_pkgs/affine-gfx-template/toolbar/template-type.d.ts +1 -1
- 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 +57 -2
- package/dist/_pkgs/affine-gfx-text/toolbar/actions.d.ts +8 -1
- package/dist/_pkgs/affine-gfx-text/toolbar/actions.js +12 -2
- package/dist/_pkgs/affine-gfx-text/translations.d.ts +1 -0
- package/dist/_pkgs/affine-gfx-text/translations.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/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 +7 -0
- package/dist/_pkgs/affine-shared/services/font-loader/config.js +43 -0
- 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/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 +77 -7
- package/dist/_pkgs/affine-shared/services/translation-service/chrome.js +97 -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-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/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-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/view.js +5 -0
- 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/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 +8 -1
- package/dist/frameworks.d.ts +9 -0
- package/dist/frameworks.js +19 -0
- package/dist/translations.js +16 -0
- package/package.json +9 -4
- package/dist/_pkgs/affine-gfx-group/group-watcher.d.ts +0 -1
- package/dist/_pkgs/affine-gfx-group/group-watcher.js +0 -20
|
@@ -2,6 +2,13 @@ export function serializeXYWH(x, y, w, h) {
|
|
|
2
2
|
return `[${x},${y},${w},${h}]`;
|
|
3
3
|
}
|
|
4
4
|
export function deserializeXYWH(xywh) {
|
|
5
|
+
// An ABSENT value is not a parse failure: a document whose Yjs state has
|
|
6
|
+
// pending structs can hand us an element whose `xywh` key is simply missing.
|
|
7
|
+
// Say nothing here — this getter runs several times per frame per element,
|
|
8
|
+
// and the surface already reports the damaged element once, at mount.
|
|
9
|
+
if (xywh === null || xywh === undefined) {
|
|
10
|
+
return [0, 0, 0, 0];
|
|
11
|
+
}
|
|
5
12
|
try {
|
|
6
13
|
return JSON.parse(xywh);
|
|
7
14
|
}
|
|
@@ -2,6 +2,7 @@ import type { ExtensionType } from '../../store/index.js';
|
|
|
2
2
|
import type { TemplateResult } from 'lit';
|
|
3
3
|
import type { z } from 'zod';
|
|
4
4
|
import type { BlockStdScope } from '../scope/index.js';
|
|
5
|
+
import type { RoleId } from '../gfx/model/surface/role.js';
|
|
5
6
|
import { type ShortcutDescriptor, type ShortcutScope } from './shortcut.js';
|
|
6
7
|
/**
|
|
7
8
|
* Where an element/tool creation was triggered from. Historically declared in
|
|
@@ -20,9 +21,25 @@ export type ElementCreationSource = 'shortcut' | 'toolbar:general' | 'toolbar:dn
|
|
|
20
21
|
* `ddd-aggregate` is deliberately absent: it ships DDD *templates* only — no
|
|
21
22
|
* senior button, no commands — so it is a packaging bundle, not a framework.
|
|
22
23
|
*/
|
|
23
|
-
export declare const FRAMEWORK_IDS: readonly ["wardley", "edgy", "cynefin-estuarine", "bpmn", "c4", "ddd-event-storming", "ddd-core-domain", "ddd-context-map"];
|
|
24
|
+
export declare const FRAMEWORK_IDS: readonly ["wardley", "edgy", "cynefin-estuarine", "bpmn", "c4", "ddd-event-storming", "ddd-core-domain", "ddd-context-map", "uml"];
|
|
24
25
|
export type FrameworkId = (typeof FRAMEWORK_IDS)[number];
|
|
25
26
|
export type CommandOwner = 'core' | FrameworkId;
|
|
27
|
+
/**
|
|
28
|
+
* `'wardley:component'` → `'wardley'`, when that names a real framework.
|
|
29
|
+
*
|
|
30
|
+
* A role id is namespaced by its framework (`<framework>:<role>`, see
|
|
31
|
+
* `gfx/model/surface/role.ts`), so the namespace IS the framework — for every
|
|
32
|
+
* element that carries one, board included (`wardley:map`, `edgy:board`…).
|
|
33
|
+
* Anything else — a neutral element, a namespace no framework claims — answers
|
|
34
|
+
* `undefined`, which is what "this element belongs to no framework" means
|
|
35
|
+
* everywhere this is read.
|
|
36
|
+
*
|
|
37
|
+
* Lives here, beside {@link FRAMEWORK_IDS}, because it is the only knowledge it
|
|
38
|
+
* needs and because four call sites had each copied it: the materiality
|
|
39
|
+
* publisher, the pivot and tag commands, and now the colour pickers' palette
|
|
40
|
+
* carousel.
|
|
41
|
+
*/
|
|
42
|
+
export declare function frameworkOfRole(role: string | undefined): FrameworkId | undefined;
|
|
26
43
|
/**
|
|
27
44
|
* Serializable precondition. Closed union; extended only by an amendment to
|
|
28
45
|
* `docs/adr/0008`. `'always'` is the default when omitted.
|
|
@@ -130,6 +147,28 @@ export interface CommandDescriptor<P = void> {
|
|
|
130
147
|
* it as the `role` dimension.
|
|
131
148
|
*/
|
|
132
149
|
telemetry?: CommandTelemetry;
|
|
150
|
+
/**
|
|
151
|
+
* The legend row (or rows) this command's artefact puts in its board's
|
|
152
|
+
* legend — `docs/adr/0009`'s sibling for the legend: a framework subscribes
|
|
153
|
+
* its notation instead of maintaining a second table of it.
|
|
154
|
+
*
|
|
155
|
+
* Declared on the command that DRAWS the thing, so the row and the gesture
|
|
156
|
+
* cannot drift: renaming the role renames the row, restyling the preset
|
|
157
|
+
* restyles the swatch. The board's own command declares {@link legendBox}
|
|
158
|
+
* instead — it is the sheet the legend is drawn on, not an artefact on it.
|
|
159
|
+
*
|
|
160
|
+
* A LIST because one command may put several rows down: EDGY's twelve
|
|
161
|
+
* official elements are all stamped by one template command, and no "add a
|
|
162
|
+
* Content" gesture exists to hang them off individually.
|
|
163
|
+
*/
|
|
164
|
+
legend?: CommandLegendEntry | readonly CommandLegendEntry[];
|
|
165
|
+
/**
|
|
166
|
+
* How the legend BOX of this framework's board is laid out, and what it adds
|
|
167
|
+
* beyond the rows. Declared on the board command (`telemetry.board`) and
|
|
168
|
+
* read by nothing else — a framework whose rows are 16-unit chips declares
|
|
169
|
+
* none of it.
|
|
170
|
+
*/
|
|
171
|
+
legendBox?: CommandLegendBox;
|
|
133
172
|
}
|
|
134
173
|
/** See {@link CommandDescriptor.telemetry}. */
|
|
135
174
|
export interface CommandTelemetry {
|
|
@@ -137,6 +176,124 @@ export interface CommandTelemetry {
|
|
|
137
176
|
element: string;
|
|
138
177
|
board?: true;
|
|
139
178
|
}
|
|
179
|
+
/**
|
|
180
|
+
* What a legend SWATCH is, without its label: the command already carries a
|
|
181
|
+
* wording, and the role it stamps carries one too, so a table that restated the
|
|
182
|
+
* text would be a third spelling of the same word.
|
|
183
|
+
*/
|
|
184
|
+
export interface CommandLegendRow {
|
|
185
|
+
swatch: 'dot' | 'square' | 'line' | 'glyph' | 'edge' | 'custom';
|
|
186
|
+
color: string;
|
|
187
|
+
/** `square` swatches: the letter drawn inside it (Team Topologies' C/X/F). */
|
|
188
|
+
letter?: string;
|
|
189
|
+
/** `line` swatches: draw the sample as two segments, so a dash reads as one. */
|
|
190
|
+
dashed?: boolean;
|
|
191
|
+
/**
|
|
192
|
+
* `glyph` / `edge` swatches: the props of the REAL element to draw in the
|
|
193
|
+
* swatch box, geometry excluded — the layout fills in `xywh` (a glyph) or the
|
|
194
|
+
* two endpoint positions (an edge).
|
|
195
|
+
*
|
|
196
|
+
* A `role` here is stripped by the drawing side and must not be declared: a
|
|
197
|
+
* legend is drawn ON the board it describes and the scan detects by role, so
|
|
198
|
+
* a swatch carrying one would list itself the next time a legend is
|
|
199
|
+
* generated — and would be counted by every validation rule.
|
|
200
|
+
*/
|
|
201
|
+
props?: Record<string, unknown>;
|
|
202
|
+
/** `glyph` swatches: the artefact's aspect ratio, fitted inside the box. */
|
|
203
|
+
aspect?: number;
|
|
204
|
+
/**
|
|
205
|
+
* `glyph` swatches: an explicit size in model units, which SHORT-CIRCUITS the
|
|
206
|
+
* fit-to-box. Wardley's gradation (component 16 < method 18 < ecosystem 20 <
|
|
207
|
+
* market 22) is notation rather than decoration, and fitting every pastille
|
|
208
|
+
* to the same box would erase it.
|
|
209
|
+
*/
|
|
210
|
+
size?: readonly [width: number, height: number];
|
|
211
|
+
/**
|
|
212
|
+
* `custom` swatches: draw the sample yourself and return the ids created.
|
|
213
|
+
*
|
|
214
|
+
* The escape hatch for a COMPOSITE glyph — Wardley's market (a circle, three
|
|
215
|
+
* dots and three connectors), its pipeline (a body and a handle), its Porter
|
|
216
|
+
* rose (a circle, four derived arrows and a letter). Their geometry is
|
|
217
|
+
* derived rather than literal, and a table of static rectangles would re-fix
|
|
218
|
+
* what the framework computes.
|
|
219
|
+
*/
|
|
220
|
+
draw?: (surface: CommandLegendSurface, box: {
|
|
221
|
+
x: number;
|
|
222
|
+
y: number;
|
|
223
|
+
w: number;
|
|
224
|
+
h: number;
|
|
225
|
+
}, std: BlockStdScope) => string[];
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Where a `custom` swatch (and a {@link CommandLegendExtra}) puts what it
|
|
229
|
+
* draws. Structural on purpose: `std` declares WHAT a framework may say, and
|
|
230
|
+
* the surface block that receives it is what knows how to draw — importing it
|
|
231
|
+
* here would point this layer at one of its own consumers.
|
|
232
|
+
*/
|
|
233
|
+
export interface CommandLegendSurface {
|
|
234
|
+
addElement(props: Record<string, unknown>): string;
|
|
235
|
+
}
|
|
236
|
+
/** See {@link CommandDescriptor.legend}. */
|
|
237
|
+
export interface CommandLegendEntry {
|
|
238
|
+
/**
|
|
239
|
+
* The role this row stands for — usually the one the command stamps, but not
|
|
240
|
+
* always: C4 writes ONE "Boundary" row on the parent `c4:boundary` for its
|
|
241
|
+
* two boundary commands, and the second declares nothing.
|
|
242
|
+
*/
|
|
243
|
+
role: RoleId;
|
|
244
|
+
row: CommandLegendRow;
|
|
245
|
+
/**
|
|
246
|
+
* Match `role` and `role` ALONE, without the specialisation walk. Reach for
|
|
247
|
+
* it when the parent row would be a lie on a board carrying only children —
|
|
248
|
+
* EDGY's bare "Object", BPMN's blank "Task".
|
|
249
|
+
*/
|
|
250
|
+
exact?: boolean;
|
|
251
|
+
/** Static prefix kept in front of the resolved wording ("PS — Partnership"). */
|
|
252
|
+
labelPrefix?: string;
|
|
253
|
+
/**
|
|
254
|
+
* The row's OWN wording, ahead of the role's. Wardley's rows explain the
|
|
255
|
+
* notation ("Need / capability (activity, practice, data…)") where the role
|
|
256
|
+
* merely names it ("Component"); without this the legend would lose its prose.
|
|
257
|
+
*/
|
|
258
|
+
labelWording?: readonly [key: string, fallback: string];
|
|
259
|
+
/**
|
|
260
|
+
* The sub-title this row files itself under, ahead of the command's
|
|
261
|
+
* `category`. Three of the DDD frameworks put every command in ONE category
|
|
262
|
+
* and still show two or three sub-titles, and EDGY's twelve elements come
|
|
263
|
+
* from one command and span four.
|
|
264
|
+
*/
|
|
265
|
+
section?: readonly [key: string, fallback: string];
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
* A block of the legend box that is not a row: Wardley's evolution gradient,
|
|
269
|
+
* its Porter panel. `height` is a VALUE rather than a second callback because
|
|
270
|
+
* the box has to be measured before it is placed.
|
|
271
|
+
*/
|
|
272
|
+
export interface CommandLegendExtra {
|
|
273
|
+
/** Total height in model units, separator included. Known BEFORE drawing. */
|
|
274
|
+
height: number;
|
|
275
|
+
draw(surface: CommandLegendSurface, std: BlockStdScope, x: number, y: number, width: number): string[];
|
|
276
|
+
}
|
|
277
|
+
/** See {@link CommandLegendBox.extras}. */
|
|
278
|
+
export type CommandLegendExtras = (ctx: {
|
|
279
|
+
std: BlockStdScope;
|
|
280
|
+
/** The board the legend describes. Cast by whoever needs more than its box. */
|
|
281
|
+
board: {
|
|
282
|
+
xywh: string;
|
|
283
|
+
};
|
|
284
|
+
present: ReadonlySet<RoleId>;
|
|
285
|
+
}) => CommandLegendExtra[];
|
|
286
|
+
/** See {@link CommandDescriptor.legendBox}. */
|
|
287
|
+
export interface CommandLegendBox {
|
|
288
|
+
/** Box title; every board that has one says "Legend" and omits this. */
|
|
289
|
+
titleWording?: readonly [key: string, fallback: string];
|
|
290
|
+
width?: number;
|
|
291
|
+
/** Row pitch; the swatch is drawn centred in it. */
|
|
292
|
+
rowHeight?: number;
|
|
293
|
+
swatchWidth?: number;
|
|
294
|
+
swatchHeight?: number;
|
|
295
|
+
extras?: CommandLegendExtras;
|
|
296
|
+
}
|
|
140
297
|
/**
|
|
141
298
|
* A command with its parameter contract erased — what the REGISTRY holds.
|
|
142
299
|
*
|
|
@@ -19,7 +19,29 @@ export const FRAMEWORK_IDS = [
|
|
|
19
19
|
'ddd-event-storming',
|
|
20
20
|
'ddd-core-domain',
|
|
21
21
|
'ddd-context-map',
|
|
22
|
+
'uml',
|
|
22
23
|
];
|
|
24
|
+
/**
|
|
25
|
+
* `'wardley:component'` → `'wardley'`, when that names a real framework.
|
|
26
|
+
*
|
|
27
|
+
* A role id is namespaced by its framework (`<framework>:<role>`, see
|
|
28
|
+
* `gfx/model/surface/role.ts`), so the namespace IS the framework — for every
|
|
29
|
+
* element that carries one, board included (`wardley:map`, `edgy:board`…).
|
|
30
|
+
* Anything else — a neutral element, a namespace no framework claims — answers
|
|
31
|
+
* `undefined`, which is what "this element belongs to no framework" means
|
|
32
|
+
* everywhere this is read.
|
|
33
|
+
*
|
|
34
|
+
* Lives here, beside {@link FRAMEWORK_IDS}, because it is the only knowledge it
|
|
35
|
+
* needs and because four call sites had each copied it: the materiality
|
|
36
|
+
* publisher, the pivot and tag commands, and now the colour pickers' palette
|
|
37
|
+
* carousel.
|
|
38
|
+
*/
|
|
39
|
+
export function frameworkOfRole(role) {
|
|
40
|
+
const namespace = role?.split(':')[0];
|
|
41
|
+
return FRAMEWORK_IDS.includes(namespace ?? '')
|
|
42
|
+
? namespace
|
|
43
|
+
: undefined;
|
|
44
|
+
}
|
|
23
45
|
/** Multi-instance: one registered {@link CommandDescriptor} per impl. */
|
|
24
46
|
export const CommandDescriptorIdentifier = createIdentifier('CommandDescriptor');
|
|
25
47
|
/** Multi-instance: one `iconKey → template` table per contributing package. */
|
|
@@ -20,7 +20,7 @@ export { GfxLocalElementModel, prop, } from './model/surface/local-element-model
|
|
|
20
20
|
export { collectPivotOccurrences, isPivotBound, type PivotBoundElement, type PivotOccurrence, resolvePivotBinding, } from './model/surface/pivot.js';
|
|
21
21
|
export { type EdgeDirectionDef, findRoleDef, isTypedEdgeRole, type RoleDef, type RoleDefs, type RoleId, roleIsA, type RoleKind, RoleVocabularyExtension, RoleVocabularyIdentifier, } from './model/surface/role.js';
|
|
22
22
|
export { ELEMENT_TAGS_FIELD, type ElementTags, elementTagValues, hasElementTagValue, readElementTags, setElementTag, tagsPropToY, } from './model/surface/tags.js';
|
|
23
|
-
export { type ElementUpdatedData, SURFACE_TEXT_UNIQ_IDENTIFIER, SURFACE_YMAP_UNIQ_IDENTIFIER, SurfaceBlockModel, type SurfaceBlockProps, type SurfaceMiddleware, } from './model/surface/surface-model.js';
|
|
23
|
+
export { type ElementUpdatedData, SURFACE_TEXT_UNIQ_IDENTIFIER, SURFACE_YMAP_UNIQ_IDENTIFIER, SurfaceBlockModel, type SurfaceBlockProps, type SurfaceDamageReason, type SurfaceElementDamage, type SurfaceElementDamageReport, type SurfaceMiddleware, } from './model/surface/surface-model.js';
|
|
24
24
|
export { measureOperation } from './perf.js';
|
|
25
25
|
export { GfxSelectionManager } from './selection.js';
|
|
26
26
|
export { SurfaceMiddlewareBuilder, SurfaceMiddlewareExtension, } from './surface-middleware.js';
|
|
@@ -59,6 +59,18 @@ export declare class GfxViewEventManager {
|
|
|
59
59
|
* cannot see.
|
|
60
60
|
*/
|
|
61
61
|
private _answersAt;
|
|
62
|
+
/**
|
|
63
|
+
* Whether ANY view answers at a model point — "is this spot taken?" asked of
|
|
64
|
+
* the view layer rather than of the models.
|
|
65
|
+
*
|
|
66
|
+
* The two layers do not answer the same thing (see {@link _answersAt}), so
|
|
67
|
+
* whoever treats a point as empty canvas has to ask both: the model says
|
|
68
|
+
* "select me?", the view says "is this mine?". A framework background is the
|
|
69
|
+
* case that forced this out — it is picked by its border alone, yet its
|
|
70
|
+
* labels answer the double-click that renames them, so the model calls their
|
|
71
|
+
* zone empty while the view is about to use it.
|
|
72
|
+
*/
|
|
73
|
+
hasViewAt(x: number, y: number): boolean;
|
|
62
74
|
/**
|
|
63
75
|
* The views under a MODEL point, in PAINT ORDER — the topmost last.
|
|
64
76
|
*
|
|
@@ -71,7 +71,12 @@ export class GfxViewEventManager {
|
|
|
71
71
|
if (this._draggingElement) {
|
|
72
72
|
this._draggingElement.dispatch('dragend', _evt);
|
|
73
73
|
}
|
|
74
|
-
|
|
74
|
+
// The same re-pick by point a click makes, and for the same reason: a
|
|
75
|
+
// stack only `pointermove` rebuilds is stale whenever the pointer
|
|
76
|
+
// arrived without one — after a toolbar action that rewrote what is
|
|
77
|
+
// under it, for instance — and a drag would then be handed to the view
|
|
78
|
+
// that USED to be there.
|
|
79
|
+
this._draggingElement = this._targetOf(_evt);
|
|
75
80
|
return this._draggingElement?.dispatch('dragstart', _evt) ?? false;
|
|
76
81
|
}
|
|
77
82
|
case 'dragmove': {
|
|
@@ -109,6 +114,20 @@ export class GfxViewEventManager {
|
|
|
109
114
|
? (model.externalBound?.isPointInBound([x, y]) ?? false)
|
|
110
115
|
: false));
|
|
111
116
|
}
|
|
117
|
+
/**
|
|
118
|
+
* Whether ANY view answers at a model point — "is this spot taken?" asked of
|
|
119
|
+
* the view layer rather than of the models.
|
|
120
|
+
*
|
|
121
|
+
* The two layers do not answer the same thing (see {@link _answersAt}), so
|
|
122
|
+
* whoever treats a point as empty canvas has to ask both: the model says
|
|
123
|
+
* "select me?", the view says "is this mine?". A framework background is the
|
|
124
|
+
* case that forced this out — it is picked by its border alone, yet its
|
|
125
|
+
* labels answer the double-click that renames them, so the model calls their
|
|
126
|
+
* zone empty while the view is about to use it.
|
|
127
|
+
*/
|
|
128
|
+
hasViewAt(x, y) {
|
|
129
|
+
return this._viewsAt(x, y).length > 0;
|
|
130
|
+
}
|
|
112
131
|
/**
|
|
113
132
|
* The views under a MODEL point, in PAINT ORDER — the topmost last.
|
|
114
133
|
*
|
|
@@ -45,6 +45,16 @@ export declare class InteractivityManager extends GfxExtension {
|
|
|
45
45
|
preventDefaultState: boolean;
|
|
46
46
|
handledByView: boolean;
|
|
47
47
|
} | undefined;
|
|
48
|
+
/**
|
|
49
|
+
* Whether a view claims the model point — the answer the pointer router will
|
|
50
|
+
* give this coordinate, made available BEFORE the router runs.
|
|
51
|
+
*
|
|
52
|
+
* `dispatchEvent` emits to the extensions first and to the views second, so
|
|
53
|
+
* an extension that wants to know whether the point is free (rather than
|
|
54
|
+
* react after the fact) has no `handledByView` to read yet. This is that
|
|
55
|
+
* answer, asked ahead of time.
|
|
56
|
+
*/
|
|
57
|
+
hasViewAt(x: number, y: number): boolean;
|
|
48
58
|
private _getSelectionConfig;
|
|
49
59
|
private _getSuggestedTarget;
|
|
50
60
|
/**
|
|
@@ -78,6 +78,18 @@ export class InteractivityManager extends GfxExtension {
|
|
|
78
78
|
handledByView,
|
|
79
79
|
};
|
|
80
80
|
}
|
|
81
|
+
/**
|
|
82
|
+
* Whether a view claims the model point — the answer the pointer router will
|
|
83
|
+
* give this coordinate, made available BEFORE the router runs.
|
|
84
|
+
*
|
|
85
|
+
* `dispatchEvent` emits to the extensions first and to the views second, so
|
|
86
|
+
* an extension that wants to know whether the point is free (rather than
|
|
87
|
+
* react after the fact) has no `handledByView` to read yet. This is that
|
|
88
|
+
* answer, asked ahead of time.
|
|
89
|
+
*/
|
|
90
|
+
hasViewAt(x, y) {
|
|
91
|
+
return this.canvasEventHandler.hasViewAt(x, y);
|
|
92
|
+
}
|
|
81
93
|
_getSelectionConfig(models) {
|
|
82
94
|
const selectionConfigMap = new Map();
|
|
83
95
|
models.forEach(model => {
|
|
@@ -45,20 +45,25 @@ import { convertProps, field, getDerivedProps, getFieldPropsSet, hasObserveMeta,
|
|
|
45
45
|
/**
|
|
46
46
|
* Declared `@field()`s that {@link GfxPrimitiveElementModel.clearField} refuses
|
|
47
47
|
* to remove, because they have no meaningful ABSENT state: every one of them is
|
|
48
|
-
* read unconditionally
|
|
48
|
+
* read unconditionally by code that has no way to cope with its absence.
|
|
49
49
|
*
|
|
50
50
|
* - `index` — the fractional z-order key. Gone, the element's stacking is
|
|
51
51
|
* `undefined` and the layer manager sorts it nowhere, silently.
|
|
52
|
-
* - `xywh` — gone,
|
|
53
|
-
*
|
|
52
|
+
* - `xywh` — gone, the element reads `[0,0,0,0]` (its declared fallback, so it
|
|
53
|
+
* draws nothing rather than a phantom shape at the origin) and the surface
|
|
54
|
+
* reports it once, at mount. A zero-size element is unusable, not optional,
|
|
55
|
+
* so it stays here: nothing may CLEAR a bound on purpose.
|
|
54
56
|
* - `seed` — the roughness seed; gone, the hand-drawn renderers produce a
|
|
55
57
|
* different shape on every repaint.
|
|
56
58
|
*
|
|
57
59
|
* An optional field is exactly one whose accessor declares a usable default (or
|
|
58
|
-
* `undefined`), and those stay clearable.
|
|
59
|
-
*
|
|
60
|
-
*
|
|
61
|
-
*
|
|
60
|
+
* `undefined`), and those stay clearable. A read fallback is not the same thing
|
|
61
|
+
* as a usable default: `xywh` now falls back to `[0,0,0,0]` so a damaged
|
|
62
|
+
* document keeps painting, which is damage control, not an optional state.
|
|
63
|
+
*
|
|
64
|
+
* This list is the short answer to "which declared fields are not optional"; it
|
|
65
|
+
* is a deny-list on purpose, so a new optional field needs no ceremony and a
|
|
66
|
+
* new structural one is a deliberate addition here.
|
|
62
67
|
*/
|
|
63
68
|
const UNCLEARABLE_ELEMENT_FIELDS = new Set(['index', 'seed', 'xywh']);
|
|
64
69
|
/**
|
|
@@ -32,6 +32,17 @@ export type MiddlewareCtx = {
|
|
|
32
32
|
};
|
|
33
33
|
};
|
|
34
34
|
export type SurfaceMiddleware = (ctx: MiddlewareCtx) => void;
|
|
35
|
+
/** Why an element is considered damaged. One reason so far. */
|
|
36
|
+
export type SurfaceDamageReason = 'missing-xywh';
|
|
37
|
+
/** What the surface knows about one damaged element. */
|
|
38
|
+
export type SurfaceElementDamage = {
|
|
39
|
+
type: string;
|
|
40
|
+
reason: SurfaceDamageReason;
|
|
41
|
+
};
|
|
42
|
+
/** The same fact, pushed as it happens. */
|
|
43
|
+
export type SurfaceElementDamageReport = SurfaceElementDamage & {
|
|
44
|
+
id: string;
|
|
45
|
+
};
|
|
35
46
|
export declare class SurfaceBlockModel extends BlockModel<SurfaceBlockProps> {
|
|
36
47
|
/**
|
|
37
48
|
* The props that are known to move the bound of the containing group, so a
|
|
@@ -73,6 +84,12 @@ export declare class SurfaceBlockModel extends BlockModel<SurfaceBlockProps> {
|
|
|
73
84
|
local: boolean;
|
|
74
85
|
}>;
|
|
75
86
|
elementUpdated: Subject<ElementUpdatedData>;
|
|
87
|
+
/**
|
|
88
|
+
* An element was found damaged — see {@link damagedElements}. Pushed at the
|
|
89
|
+
* same moment the console line is written, so a subscriber that arrives
|
|
90
|
+
* later reads the map instead and misses nothing.
|
|
91
|
+
*/
|
|
92
|
+
elementDamaged: Subject<SurfaceElementDamageReport>;
|
|
76
93
|
localElementAdded: Subject<GfxLocalElementModel>;
|
|
77
94
|
localElementDeleted: Subject<GfxLocalElementModel>;
|
|
78
95
|
localElementUpdated: Subject<{
|
|
@@ -81,6 +98,20 @@ export declare class SurfaceBlockModel extends BlockModel<SurfaceBlockProps> {
|
|
|
81
98
|
oldValues: Record<string, unknown>;
|
|
82
99
|
}>;
|
|
83
100
|
private readonly _isEmpty$;
|
|
101
|
+
private readonly _damagedElements;
|
|
102
|
+
/**
|
|
103
|
+
* The elements this surface built from a Y.Map that was missing a key it
|
|
104
|
+
* declares — today only `xywh`, the bound without which the element paints
|
|
105
|
+
* nothing (see {@link _createElementFromYMap}).
|
|
106
|
+
*
|
|
107
|
+
* **State, not just a signal.** The element models are built when the block
|
|
108
|
+
* model is created, before any view or `LifeCycleWatcher` is mounted, so a
|
|
109
|
+
* subscriber to {@link elementDamaged} would always be too late for the
|
|
110
|
+
* elements the document opened with. Whoever wants to count damaged
|
|
111
|
+
* documents reads this map at mount, then subscribes for what sync brings
|
|
112
|
+
* afterwards.
|
|
113
|
+
*/
|
|
114
|
+
get damagedElements(): ReadonlyMap<string, SurfaceElementDamage>;
|
|
84
115
|
get elementModels(): GfxPrimitiveElementModel<import("./element-model.js").BaseElementProps>[];
|
|
85
116
|
get elements(): Boxed<Y.Map<Y.Map<unknown>>>;
|
|
86
117
|
get localElementModels(): Set<GfxLocalElementModel>;
|
|
@@ -166,6 +197,31 @@ export declare class SurfaceBlockModel extends BlockModel<SurfaceBlockProps> {
|
|
|
166
197
|
addElement<T extends object = Record<string, unknown>>(props: Partial<T> & {
|
|
167
198
|
type: string;
|
|
168
199
|
}): string;
|
|
200
|
+
/**
|
|
201
|
+
* Build the element `addElement` would build from `props`, and stop there:
|
|
202
|
+
* FOR PREVIEWS ONLY — the model never enters the document.
|
|
203
|
+
*
|
|
204
|
+
* The props take the insertion path up to the moment the Y.Map would be
|
|
205
|
+
* attached — the `beforeAdd` middlewares (the author's last-used style), the
|
|
206
|
+
* class's `propsToY` (a string `text` becomes a `Y.Text`), the declared-prop
|
|
207
|
+
* routing — so a preview paints exactly what the placed element will. What
|
|
208
|
+
* `addElement` does next is skipped: the model is not registered (no
|
|
209
|
+
* `getElementById`, no `elementModels`), is never mounted (no observers, no
|
|
210
|
+
* `onChange`), emits no `elementAdded`, and opens no transaction.
|
|
211
|
+
*
|
|
212
|
+
* Its Y.Map is then parked in a throwaway `Y.Doc` of its own, because the
|
|
213
|
+
* values of a map that belongs to no document cannot be read (a `Y.Text`
|
|
214
|
+
* reads empty) — and a renderer needs to read them. That doc is not the
|
|
215
|
+
* store's; a renderer that WROTE to the model would still reach the store's
|
|
216
|
+
* `transact`, which is why a preview must only ever be rendered.
|
|
217
|
+
*
|
|
218
|
+
* `props.id` is required and is the caller's: nothing checks it against the
|
|
219
|
+
* document, since nothing is added to it.
|
|
220
|
+
*/
|
|
221
|
+
createDetachedElement(props: Record<string, unknown> & {
|
|
222
|
+
type: string;
|
|
223
|
+
id: string;
|
|
224
|
+
}): GfxPrimitiveElementModel;
|
|
169
225
|
addLocalElement(elem: GfxLocalElementModel): void;
|
|
170
226
|
applyMiddlewares(middlewares: SurfaceMiddleware[]): void;
|
|
171
227
|
deleteElement(id: string): void;
|
|
@@ -189,6 +189,21 @@ export class SurfaceBlockModel extends BlockModel {
|
|
|
189
189
|
'rotate',
|
|
190
190
|
'hidden',
|
|
191
191
|
]); }
|
|
192
|
+
/**
|
|
193
|
+
* The elements this surface built from a Y.Map that was missing a key it
|
|
194
|
+
* declares — today only `xywh`, the bound without which the element paints
|
|
195
|
+
* nothing (see {@link _createElementFromYMap}).
|
|
196
|
+
*
|
|
197
|
+
* **State, not just a signal.** The element models are built when the block
|
|
198
|
+
* model is created, before any view or `LifeCycleWatcher` is mounted, so a
|
|
199
|
+
* subscriber to {@link elementDamaged} would always be too late for the
|
|
200
|
+
* elements the document opened with. Whoever wants to count damaged
|
|
201
|
+
* documents reads this map at mount, then subscribes for what sync brings
|
|
202
|
+
* afterwards.
|
|
203
|
+
*/
|
|
204
|
+
get damagedElements() {
|
|
205
|
+
return this._damagedElements;
|
|
206
|
+
}
|
|
192
207
|
get elementModels() {
|
|
193
208
|
const models = [];
|
|
194
209
|
this._elementModels.forEach(model => models.push(model.model));
|
|
@@ -219,10 +234,17 @@ export class SurfaceBlockModel extends BlockModel {
|
|
|
219
234
|
this.elementAdded = new Subject();
|
|
220
235
|
this.elementRemoved = new Subject();
|
|
221
236
|
this.elementUpdated = new Subject();
|
|
237
|
+
/**
|
|
238
|
+
* An element was found damaged — see {@link damagedElements}. Pushed at the
|
|
239
|
+
* same moment the console line is written, so a subscriber that arrives
|
|
240
|
+
* later reads the map instead and misses nothing.
|
|
241
|
+
*/
|
|
242
|
+
this.elementDamaged = new Subject();
|
|
222
243
|
this.localElementAdded = new Subject();
|
|
223
244
|
this.localElementDeleted = new Subject();
|
|
224
245
|
this.localElementUpdated = new Subject();
|
|
225
246
|
this._isEmpty$ = signal(false);
|
|
247
|
+
this._damagedElements = new Map();
|
|
226
248
|
const subscription = this.created.subscribe(() => {
|
|
227
249
|
this._init();
|
|
228
250
|
subscription.unsubscribe();
|
|
@@ -338,6 +360,27 @@ export class SurfaceBlockModel extends BlockModel {
|
|
|
338
360
|
delete Ctor['_decoratorState'];
|
|
339
361
|
state.creating = false;
|
|
340
362
|
state.skipField = false;
|
|
363
|
+
// A document whose Yjs state still has pending structs can carry an element
|
|
364
|
+
// whose `xywh` key never arrived. The element reads its `[0,0,0,0]` fallback
|
|
365
|
+
// and paints nothing instead of a phantom shape at the origin — say so ONCE
|
|
366
|
+
// here, where every element model is built from its Y.Map, and never again
|
|
367
|
+
// from a getter that runs several times per frame. Group-like elements are
|
|
368
|
+
// excluded for free: their `xywh` is a derived getter, not a declared field.
|
|
369
|
+
//
|
|
370
|
+
// Only a map that is IN the document is asked: a brand-new element is built
|
|
371
|
+
// from a detached Y.Map whose keys still sit in Yjs' preliminary content,
|
|
372
|
+
// where `has()` sees nothing (and warns about the premature read).
|
|
373
|
+
if (yMap.doc &&
|
|
374
|
+
getFieldPropsSet(elementModel).has('xywh') &&
|
|
375
|
+
!yMap.has('xywh')) {
|
|
376
|
+
// The console line stays: std runs standalone, with no telemetry bus of
|
|
377
|
+
// its own. The state and the subject below are what makes the same fact
|
|
378
|
+
// COUNTABLE by a host that has one.
|
|
379
|
+
console.warn(`[labre] surface element ${type} ${id} has no xywh: rendering it with ` +
|
|
380
|
+
`a zero-size bound; the document is damaged`);
|
|
381
|
+
this._damagedElements.set(id, { type, reason: 'missing-xywh' });
|
|
382
|
+
this.elementDamaged.next({ id, type, reason: 'missing-xywh' });
|
|
383
|
+
}
|
|
341
384
|
const unmount = () => {
|
|
342
385
|
mounted = false;
|
|
343
386
|
elementModel.onDestroyed();
|
|
@@ -458,6 +501,7 @@ export class SurfaceBlockModel extends BlockModel {
|
|
|
458
501
|
const { model, unmount } = this._elementModels.get(id);
|
|
459
502
|
removeFromType(model.type, model);
|
|
460
503
|
this._elementModels.delete(id);
|
|
504
|
+
this._damagedElements.delete(id);
|
|
461
505
|
deletedElements.push({ model, unmount });
|
|
462
506
|
}
|
|
463
507
|
break;
|
|
@@ -510,10 +554,11 @@ export class SurfaceBlockModel extends BlockModel {
|
|
|
510
554
|
if (isGfxGroupCompatibleModel(payload.model)) {
|
|
511
555
|
this._groupLikeModels.delete(payload.id);
|
|
512
556
|
}
|
|
513
|
-
// Same rule as `_watchGroupRelationChange`:
|
|
557
|
+
// Same rule as `_watchGroupRelationChange`: cascade only on a local
|
|
558
|
+
// edit, and only if the store is writeable. The author already
|
|
514
559
|
// dropped the block from its group, and `removeChild` is a raw
|
|
515
560
|
// `transact` — on a readonly viewer it would be a silent write.
|
|
516
|
-
if (payload.isLocal) {
|
|
561
|
+
if (payload.isLocal && !this.store.readonly) {
|
|
517
562
|
const group = this.getGroup(payload.id);
|
|
518
563
|
if (group) {
|
|
519
564
|
// oxlint-disable-next-line unicorn/prefer-dom-node-remove
|
|
@@ -572,7 +617,10 @@ export class SurfaceBlockModel extends BlockModel {
|
|
|
572
617
|
// the same sync. Reacting to a REMOTE update with a local write is
|
|
573
618
|
// redundant on a writeable peer and, on a readonly viewer, the
|
|
574
619
|
// production exception `Cannot remove element in readonly mode`.
|
|
575
|
-
|
|
620
|
+
// A readonly peer never cascades either, whatever the provenance of
|
|
621
|
+
// the update: it may not write at all, and a lingering empty group is
|
|
622
|
+
// harmless — the author's own cascade arrives through sync.
|
|
623
|
+
if (!local || this.store.readonly)
|
|
576
624
|
return;
|
|
577
625
|
const element = this.getElementById(id);
|
|
578
626
|
if (isGroup(element) &&
|
|
@@ -640,6 +688,37 @@ export class SurfaceBlockModel extends BlockModel {
|
|
|
640
688
|
});
|
|
641
689
|
return id;
|
|
642
690
|
}
|
|
691
|
+
/**
|
|
692
|
+
* Build the element `addElement` would build from `props`, and stop there:
|
|
693
|
+
* FOR PREVIEWS ONLY — the model never enters the document.
|
|
694
|
+
*
|
|
695
|
+
* The props take the insertion path up to the moment the Y.Map would be
|
|
696
|
+
* attached — the `beforeAdd` middlewares (the author's last-used style), the
|
|
697
|
+
* class's `propsToY` (a string `text` becomes a `Y.Text`), the declared-prop
|
|
698
|
+
* routing — so a preview paints exactly what the placed element will. What
|
|
699
|
+
* `addElement` does next is skipped: the model is not registered (no
|
|
700
|
+
* `getElementById`, no `elementModels`), is never mounted (no observers, no
|
|
701
|
+
* `onChange`), emits no `elementAdded`, and opens no transaction.
|
|
702
|
+
*
|
|
703
|
+
* Its Y.Map is then parked in a throwaway `Y.Doc` of its own, because the
|
|
704
|
+
* values of a map that belongs to no document cannot be read (a `Y.Text`
|
|
705
|
+
* reads empty) — and a renderer needs to read them. That doc is not the
|
|
706
|
+
* store's; a renderer that WROTE to the model would still reach the store's
|
|
707
|
+
* `transact`, which is why a preview must only ever be rendered.
|
|
708
|
+
*
|
|
709
|
+
* `props.id` is required and is the caller's: nothing checks it against the
|
|
710
|
+
* document, since nothing is added to it.
|
|
711
|
+
*/
|
|
712
|
+
createDetachedElement(props) {
|
|
713
|
+
const middlewareCtx = {
|
|
714
|
+
type: 'beforeAdd',
|
|
715
|
+
payload: { type: props.type, props: { ...props } },
|
|
716
|
+
};
|
|
717
|
+
this._middlewares.forEach(mid => mid(middlewareCtx));
|
|
718
|
+
const { model } = this._createElementFromProps({ ...middlewareCtx.payload.props, id: props.id }, { onChange: () => { } });
|
|
719
|
+
new Y.Doc().getMap('preview').set(props.id, model.yMap);
|
|
720
|
+
return model;
|
|
721
|
+
}
|
|
643
722
|
addLocalElement(elem) {
|
|
644
723
|
this.localElements.add(elem);
|
|
645
724
|
this.localElementAdded.next(elem);
|
|
@@ -682,8 +761,10 @@ export class SurfaceBlockModel extends BlockModel {
|
|
|
682
761
|
this.elementAdded.complete();
|
|
683
762
|
this.elementRemoved.complete();
|
|
684
763
|
this.elementUpdated.complete();
|
|
764
|
+
this.elementDamaged.complete();
|
|
685
765
|
this._elementModels.forEach(({ unmount }) => unmount());
|
|
686
766
|
this._elementModels.clear();
|
|
767
|
+
this._damagedElements.clear();
|
|
687
768
|
}
|
|
688
769
|
getElementById(id) {
|
|
689
770
|
return this._elementModels.get(id)?.model ?? null;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type Container } from '../../../global/di/index.js';
|
|
2
2
|
import { DisposableGroup } from '../../../global/disposable/index.js';
|
|
3
|
-
import {
|
|
3
|
+
import { Bound, type IVec } from '../../../global/gfx/index.js';
|
|
4
4
|
import type { Extension } from '../../../store/index.js';
|
|
5
5
|
import type { PointerEventState } from '../../event/index.js';
|
|
6
6
|
import type { EditorHost } from '../../view/index.js';
|
|
@@ -57,7 +57,16 @@ export declare class GfxElementModelView<T extends GfxLocalElementModel | GfxPri
|
|
|
57
57
|
onDragStart(_: DragStartContext): void;
|
|
58
58
|
onDragEnd(_: DragEndContext): void;
|
|
59
59
|
onDragMove({ dx, dy, currentBound }: DragMoveContext): void;
|
|
60
|
-
|
|
60
|
+
/**
|
|
61
|
+
* Whether a box (marquee) selection takes this element. `false` keeps it
|
|
62
|
+
* out; anything else keeps the default (any overlap selects).
|
|
63
|
+
*
|
|
64
|
+
* A model may carry its own answer as `boxSelectable(box)` — a framework
|
|
65
|
+
* background does, to join a marquee only when the marquee contains it —
|
|
66
|
+
* and the default view defers to it, so every view of such a model gets the
|
|
67
|
+
* rule without restating it.
|
|
68
|
+
*/
|
|
69
|
+
onBoxSelected(context: BoxSelectionContext): boolean | void;
|
|
61
70
|
/**
|
|
62
71
|
* Called when the view is destroyed.
|
|
63
72
|
* Override this method requires calling `super.onDestroyed()`.
|