@beyondwork/docx-react-component 1.0.66 → 1.0.69
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +75 -931
- package/package.json +26 -27
- package/src/api/anchor-conversion.ts +43 -0
- package/src/api/editor-state-types.ts +2 -1
- package/src/api/public-types.ts +504 -101
- package/src/api/session-state.ts +4 -0
- package/src/api/v3/README.md +91 -0
- package/src/api/v3/_create.ts +146 -0
- package/src/api/v3/_layer-metadata.ts +362 -0
- package/src/api/v3/_mocks.ts +84 -0
- package/src/api/v3/_runtime-handle.ts +162 -0
- package/src/api/v3/_ux-response.ts +73 -0
- package/src/api/v3/ai/_metadata-audit.ts +225 -0
- package/src/api/v3/ai/attach.ts +235 -0
- package/src/api/v3/ai/bundle.ts +132 -0
- package/src/api/v3/ai/explain.ts +144 -0
- package/src/api/v3/ai/export.ts +54 -0
- package/src/api/v3/ai/inspect.ts +118 -0
- package/src/api/v3/ai/policy.ts +77 -0
- package/src/api/v3/ai/replacement.ts +341 -0
- package/src/api/v3/ai/resolve.ts +133 -0
- package/src/api/v3/index.ts +79 -0
- package/src/api/v3/runtime/chart.ts +310 -0
- package/src/api/v3/runtime/clipboard.ts +81 -0
- package/src/api/v3/runtime/collab.ts +331 -0
- package/src/api/v3/runtime/content.ts +236 -0
- package/src/api/v3/runtime/document.ts +282 -0
- package/src/api/v3/runtime/formatting.ts +186 -0
- package/src/api/v3/runtime/geometry.ts +349 -0
- package/src/api/v3/runtime/layout.ts +108 -0
- package/src/api/v3/runtime/review.ts +129 -0
- package/src/api/v3/runtime/search.ts +74 -0
- package/src/api/v3/runtime/table.ts +63 -0
- package/src/api/v3/runtime/workflow.ts +434 -0
- package/src/api/v3/ui/_context.ts +86 -0
- package/src/api/v3/ui/_create.ts +65 -0
- package/src/api/v3/ui/_types.ts +520 -0
- package/src/api/v3/ui/chrome-composition.ts +342 -0
- package/src/{ui-tailwind/chrome → api/v3/ui}/chrome-preset-model.ts +11 -1
- package/src/api/v3/ui/chrome.ts +476 -0
- package/src/api/v3/ui/debug.ts +124 -0
- package/src/api/v3/ui/index.ts +64 -0
- package/src/api/v3/ui/overlays-visibility.ts +170 -0
- package/src/api/v3/ui/overlays.ts +427 -0
- package/src/api/v3/ui/scope.ts +71 -0
- package/src/api/v3/ui/session.ts +100 -0
- package/src/api/v3/ui/surface.ts +170 -0
- package/src/api/v3/ui/viewport.ts +303 -0
- package/src/core/commands/index.ts +28 -6
- package/src/core/commands/list-commands.ts +3 -2
- package/src/core/commands/section-layout-commands.ts +9 -8
- package/src/core/schema/text-schema.ts +16 -0
- package/src/core/selection/mapping.ts +33 -72
- package/src/core/state/editor-state.ts +96 -189
- package/src/index.ts +23 -4
- package/src/io/chart-preview-resolver.ts +1 -1
- package/src/io/docx-session.ts +36 -4795
- package/src/io/export/build-app-properties-xml.ts +1 -1
- package/src/io/export/serialize-comments.ts +1 -1
- package/src/io/export/serialize-headers-footers.ts +6 -1
- package/src/io/export/serialize-main-document.ts +45 -0
- package/src/io/export/serialize-run-formatting.ts +17 -2
- package/src/io/export/twip.ts +1 -1
- package/src/io/normalize/normalize-text.ts +27 -20
- package/src/io/ooxml/chart/parse-series.ts +1 -1
- package/src/io/ooxml/chart/resolve-color.ts +2 -2
- package/src/io/ooxml/chart/types.ts +1 -1
- package/src/io/ooxml/classify-embedding.ts +83 -33
- package/src/io/ooxml/parse-fill.ts +1 -1
- package/src/io/ooxml/parse-main-document.ts +71 -1
- package/src/io/ooxml/parse-object.ts +14 -10
- package/src/io/ooxml/parse-run-formatting.ts +47 -1
- package/src/io/ooxml/property-grab-bag.ts +2 -2
- package/src/io/ooxml/units.ts +11 -0
- package/src/io/ooxml/workflow-payload.ts +282 -7
- package/src/model/anchor.ts +85 -0
- package/src/model/canonical-document.ts +351 -15
- package/src/model/chart-types.ts +1 -1
- package/src/model/layout/index.ts +83 -0
- package/src/model/layout/page-graph-types.ts +181 -0
- package/src/model/layout/page-layout-snapshot.ts +105 -0
- package/src/model/layout/resolved-layout-types.ts +47 -0
- package/src/model/layout/runtime-page-graph-types.ts +102 -0
- package/src/model/paragraph-scope-ids.ts +72 -0
- package/src/model/review/comment-types.ts +112 -0
- package/src/model/review/index.ts +2 -0
- package/src/model/review/revision-types.ts +215 -0
- package/src/model/snapshot.ts +32 -0
- package/src/review/store/comment-store.ts +21 -47
- package/src/review/store/revision-types.ts +40 -198
- package/src/runtime/collab/base-doc-fingerprint.ts +6 -1
- package/src/runtime/collab/runtime-collab-sync.ts +13 -3
- package/src/runtime/collab-session.ts +1 -1
- package/src/runtime/debug/build-debug-inspector-snapshot.ts +686 -0
- package/src/runtime/debug/event-ring-buffer.ts +64 -0
- package/src/runtime/debug/probability-sampler.ts +18 -0
- package/src/runtime/debug/runtime-debug-facet.ts +67 -0
- package/src/runtime/debug/stage-tokens.ts +31 -0
- package/src/runtime/debug/telemetry-bus.ts +271 -0
- package/src/runtime/debug/types.ts +275 -0
- package/src/runtime/debug/wrap-ref-for-telemetry.ts +118 -0
- package/src/runtime/document-layout.ts +8 -6
- package/src/runtime/document-runtime.ts +843 -1141
- package/src/runtime/document-search.ts +1 -1
- package/src/runtime/edit-ops/index.ts +1 -1
- package/src/runtime/external-send-runtime.ts +1 -1
- package/src/runtime/formatting/document-lookup.ts +235 -0
- package/src/runtime/formatting/field/registry.ts +41 -0
- package/src/runtime/{field-resolver.ts → formatting/field/resolver.ts} +27 -2
- package/src/runtime/formatting/font-resolution.ts +83 -0
- package/src/runtime/formatting/formatting-context.ts +903 -0
- package/src/runtime/formatting/formatting-types.ts +157 -0
- package/src/runtime/{hyperlink-color-resolver.ts → formatting/hyperlink-color.ts} +2 -2
- package/src/runtime/formatting/index.ts +125 -0
- package/src/runtime/{resolved-numbering-geometry.ts → formatting/numbering/geometry.ts} +1 -1
- package/src/runtime/{numbering-prefix.ts → formatting/numbering/prefix.ts} +170 -3
- package/src/runtime/formatting/paragraph-style-resolver.ts +92 -0
- package/src/runtime/formatting/projector.ts +75 -0
- package/src/runtime/formatting/resolve-effective.ts +407 -0
- package/src/runtime/formatting/revision-display.ts +105 -0
- package/src/runtime/{paragraph-style-resolver.ts → formatting/style-cascade.ts} +84 -141
- package/src/runtime/{table-style-resolver.ts → formatting/table-style-resolver.ts} +1 -1
- package/src/runtime/formatting/telemetry-bridge.ts +106 -0
- package/src/runtime/{theme-color-resolver.ts → formatting/theme-color.ts} +2 -30
- package/src/runtime/geometry/caret-geometry.ts +164 -0
- package/src/runtime/geometry/geometry-facet.ts +364 -0
- package/src/runtime/geometry/geometry-types.ts +256 -0
- package/src/runtime/geometry/hit-test.ts +125 -0
- package/src/runtime/geometry/index.ts +71 -0
- package/src/runtime/geometry/inert-geometry-facet.ts +43 -0
- package/src/runtime/geometry/invalidation.ts +35 -0
- package/src/runtime/geometry/object-handles.ts +77 -0
- package/src/runtime/geometry/overlay-rects.ts +85 -0
- package/src/runtime/geometry/project-anchors.ts +100 -0
- package/src/runtime/geometry/project-fragments.ts +216 -0
- package/src/runtime/geometry/projector.ts +129 -0
- package/src/runtime/geometry/replacement-envelope.ts +130 -0
- package/src/runtime/geometry/viewport.ts +218 -0
- package/src/runtime/layout/compat-input-ledger.ts +211 -0
- package/src/runtime/layout/index.ts +6 -1
- package/src/runtime/layout/inert-layout-facet.ts +12 -7
- package/src/runtime/layout/layout-engine-instance.ts +189 -11
- package/src/runtime/layout/layout-engine-version.ts +450 -1
- package/src/runtime/layout/layout-facet-types.ts +60 -0
- package/src/runtime/layout/layout-measurement-provider.ts +13 -0
- package/src/runtime/layout/measurement-backend-canvas.ts +14 -2
- package/src/runtime/layout/measurement-backend-empirical.ts +23 -4
- package/src/runtime/layout/page-graph.ts +62 -209
- package/src/runtime/layout/page-story-resolver.ts +7 -12
- package/src/runtime/layout/paginated-layout-engine.ts +186 -11
- package/src/runtime/layout/project-block-fragments.ts +11 -0
- package/src/runtime/layout/projector.ts +90 -0
- package/src/runtime/layout/public-facet.ts +187 -442
- package/src/runtime/layout/resolved-formatting-state.ts +158 -26
- package/src/runtime/layout/table-render-plan.ts +1 -1
- package/src/runtime/prerender/cache-envelope.ts +6 -1
- package/src/runtime/prerender/prerender-document.ts +18 -23
- package/src/runtime/render/decoration-resolver.ts +1 -1
- package/src/runtime/render/render-frame-types.ts +20 -0
- package/src/runtime/render/render-kernel.ts +94 -25
- package/src/runtime/scopes/_formatting-seam.ts +262 -0
- package/src/runtime/scopes/_scope-dependencies.ts +49 -0
- package/src/runtime/scopes/action-validation.ts +356 -0
- package/src/runtime/scopes/attach-explanation.ts +102 -0
- package/src/runtime/scopes/audit-bundle.ts +71 -0
- package/src/runtime/scopes/compile-scope-bundle.ts +163 -0
- package/src/runtime/scopes/compile-scope.ts +262 -0
- package/src/runtime/scopes/compiler-service.ts +431 -0
- package/src/runtime/scopes/create-issue.ts +107 -0
- package/src/runtime/scopes/enumerate-scopes.ts +543 -0
- package/src/runtime/scopes/evidence.ts +233 -0
- package/src/runtime/scopes/index.ts +150 -0
- package/src/runtime/scopes/position-map.ts +214 -0
- package/src/runtime/scopes/preservation-boundary.ts +91 -0
- package/src/runtime/scopes/projector.ts +49 -0
- package/src/runtime/scopes/replaceability.ts +87 -0
- package/src/runtime/scopes/replacement/apply.ts +228 -0
- package/src/runtime/scopes/replacement/compile.ts +59 -0
- package/src/runtime/scopes/replacement/propose.ts +42 -0
- package/src/runtime/scopes/resolve-reference.ts +347 -0
- package/src/runtime/scopes/review-bundle.ts +141 -0
- package/src/runtime/scopes/scope-kinds/_paragraph-text.ts +57 -0
- package/src/runtime/scopes/scope-kinds/_table-text.ts +42 -0
- package/src/runtime/scopes/scope-kinds/comment-thread.ts +59 -0
- package/src/runtime/scopes/scope-kinds/field.ts +65 -0
- package/src/runtime/scopes/scope-kinds/heading.ts +84 -0
- package/src/runtime/scopes/scope-kinds/list-item.ts +77 -0
- package/src/runtime/scopes/scope-kinds/paragraph.ts +182 -0
- package/src/runtime/scopes/scope-kinds/revision.ts +62 -0
- package/src/runtime/scopes/scope-kinds/table-cell.ts +57 -0
- package/src/runtime/scopes/scope-kinds/table-row.ts +61 -0
- package/src/runtime/scopes/scope-kinds/table.ts +55 -0
- package/src/runtime/scopes/scope-range.ts +208 -0
- package/src/runtime/scopes/semantic-scope-types.ts +454 -0
- package/src/runtime/scopes/workflow-overlap.ts +92 -0
- package/src/runtime/selection/index.ts +1 -1
- package/src/runtime/structure-ops/fragment-insert.ts +1 -1
- package/src/runtime/structure-ops/index.ts +1 -1
- package/src/runtime/surface-projection.ts +232 -262
- package/src/runtime/units.ts +4 -2
- package/src/runtime/workflow/coordinator.ts +1348 -0
- package/src/runtime/workflow/derived-scope-resolver.ts +125 -0
- package/src/runtime/workflow/index.ts +25 -0
- package/src/runtime/workflow/markup-mode-policy.ts +98 -0
- package/src/runtime/{workflow-markup.ts → workflow/markup.ts} +6 -6
- package/src/runtime/workflow/metadata-persistence.ts +306 -0
- package/src/runtime/workflow/metadata-writer.ts +123 -0
- package/src/runtime/workflow/overlay-store.ts +690 -0
- package/src/runtime/workflow/projector.ts +127 -0
- package/src/runtime/{query-scopes.ts → workflow/query-scopes.ts} +3 -3
- package/src/runtime/{workflow-rail-segments.ts → workflow/rail/compose.ts} +60 -165
- package/src/runtime/workflow/rail/types.ts +198 -0
- package/src/runtime/workflow/scope-rail-composer.ts +39 -0
- package/src/runtime/{scope-resolver.ts → workflow/scope-resolver.ts} +3 -3
- package/src/runtime/workflow/scope-writer.ts +188 -0
- package/src/runtime/{tamper-gate.ts → workflow/tamper-gate.ts} +1 -1
- package/src/runtime/workflow/visibility-policy.ts +129 -0
- package/src/session/_sync-legacy.ts +66 -0
- package/src/session/export/embedded-reconstitute.ts +104 -0
- package/src/session/export/export-diagnostics.ts +85 -0
- package/src/session/export/export-validation.ts +110 -0
- package/src/session/export/index.ts +34 -0
- package/src/session/export/preservation-reattach.ts +30 -0
- package/src/session/export/serialize-dispatch.ts +165 -0
- package/src/session/export/stateful-export-pipeline.ts +432 -0
- package/src/session/export/stateful-export.ts +684 -0
- package/src/session/import/canonical-assembly.ts +227 -0
- package/src/session/import/diagnostics-session.ts +54 -0
- package/src/session/import/embedded-discovery.ts +225 -0
- package/src/session/import/embedded-offload.ts +337 -0
- package/src/session/import/import-diagnostics.ts +69 -0
- package/src/session/import/loader-types.ts +313 -0
- package/src/session/import/loader.ts +1834 -0
- package/src/session/import/normalize.ts +195 -0
- package/src/session/import/package-parts.ts +217 -0
- package/src/session/import/package-read.ts +195 -0
- package/src/session/import/parse-orchestration.ts +105 -0
- package/src/session/import/part-constants.ts +70 -0
- package/src/session/import/part-discovery.ts +94 -0
- package/src/session/import/preservation-index.ts +46 -0
- package/src/{runtime/read-only-diagnostics-runtime.ts → session/import/read-only-diagnostics.ts} +24 -3
- package/src/session/import/review-import.ts +508 -0
- package/src/session/import/styles-consolidation.ts +281 -0
- package/src/session/import/workflow-scope-import.ts +256 -0
- package/src/session/index.ts +37 -0
- package/src/session/session-state.ts +69 -0
- package/src/session/session.ts +532 -0
- package/src/session/shared/protection.ts +228 -0
- package/src/session/shared/session-utils.ts +82 -0
- package/src/session/types.ts +499 -0
- package/src/shell/chart-snapshots.ts +96 -0
- package/src/shell/media-previews.ts +85 -0
- package/src/shell/overlay-anchor-bridge.ts +53 -0
- package/src/shell/paste-adapter.ts +23 -0
- package/src/shell/ref-commands.ts +1697 -0
- package/src/shell/ref-utilities.ts +48 -0
- package/src/shell/search.ts +51 -0
- package/src/{ui/editor-runtime-boundary.ts → shell/session-bootstrap.ts} +243 -67
- package/src/shell/ui-subscriber-channels.ts +81 -0
- package/src/shell/use-collab-sync.ts +116 -0
- package/src/ui/WordReviewEditor.tsx +496 -2051
- package/src/ui/editor-shell-view.tsx +30 -1
- package/src/ui/editor-surface-controller.tsx +49 -1
- package/src/ui/headless/revision-decoration-model.ts +83 -0
- package/src/{ui-tailwind/chrome → ui/headless}/role-action-sets.ts +1 -1
- package/src/ui/headless/scoped-chrome-policy.ts +2 -2
- package/src/ui/headless/selection-tool-context.ts +1 -1
- package/src/ui/headless/selection-tool-resolver.ts +1 -1
- package/src/ui/runtime-shortcut-dispatch.ts +46 -1
- package/src/ui/ui-controller-factory.ts +221 -0
- package/src/ui-tailwind/chart/ChartSurface.tsx +2 -2
- package/src/ui-tailwind/chart/layout/legend-layout.ts +1 -1
- package/src/ui-tailwind/chart/layout/plot-area.ts +2 -2
- package/src/ui-tailwind/chart/layout/title-layout.ts +1 -1
- package/src/ui-tailwind/chart/render/area.tsx +3 -3
- package/src/ui-tailwind/chart/render/bar-column.tsx +3 -3
- package/src/ui-tailwind/chart/render/bubble.tsx +3 -3
- package/src/ui-tailwind/chart/render/combo.tsx +2 -2
- package/src/ui-tailwind/chart/render/data-labels.tsx +2 -2
- package/src/ui-tailwind/chart/render/font-metrics.ts +2 -2
- package/src/ui-tailwind/chart/render/line.tsx +3 -3
- package/src/ui-tailwind/chart/render/pie.tsx +6 -6
- package/src/ui-tailwind/chart/render/scatter.tsx +3 -3
- package/src/ui-tailwind/chart/render/svg-primitives.ts +3 -3
- package/src/ui-tailwind/chart/render/unsupported.tsx +2 -2
- package/src/ui-tailwind/chrome/build-context-menu-entries.ts +88 -0
- package/src/ui-tailwind/chrome/chrome-preset-toolbar.tsx +1 -1
- package/src/ui-tailwind/chrome/collab-send-to-supplier-button.tsx +1 -1
- package/src/ui-tailwind/chrome/collab-tamper-banner.tsx +1 -1
- package/src/ui-tailwind/chrome/collab-top-nav-container.tsx +1 -1
- package/src/ui-tailwind/chrome/editor-action-registry.ts +553 -0
- package/src/ui-tailwind/chrome/editor-actions-to-palette.ts +182 -0
- package/src/ui-tailwind/chrome/local-surface-arbiter.ts +534 -0
- package/src/ui-tailwind/chrome/resolve-target-kind.ts +226 -0
- package/src/ui-tailwind/chrome/tw-alert-banner.tsx +38 -4
- package/src/ui-tailwind/chrome/tw-context-band.tsx +125 -0
- package/src/ui-tailwind/chrome/tw-context-menu-portal.tsx +248 -0
- package/src/ui-tailwind/chrome/tw-image-context-toolbar.tsx +42 -1
- package/src/ui-tailwind/chrome/tw-selection-anchor-resolver.ts +8 -7
- package/src/ui-tailwind/chrome/tw-selection-tool-blocked.tsx +38 -4
- package/src/ui-tailwind/chrome/tw-selection-tool-comment.tsx +104 -6
- package/src/ui-tailwind/chrome/tw-selection-tool-host.tsx +66 -7
- package/src/ui-tailwind/chrome/tw-selection-tool-workflow.tsx +54 -8
- package/src/ui-tailwind/chrome/tw-shortcut-hint.tsx +7 -1
- package/src/ui-tailwind/chrome/tw-suggestion-card.tsx +33 -0
- package/src/ui-tailwind/chrome/tw-table-context-toolbar.tsx +78 -1
- package/src/ui-tailwind/chrome/tw-table-grip-layer.tsx +16 -8
- package/src/ui-tailwind/chrome/tw-workspace-chrome-host.tsx +276 -0
- package/src/ui-tailwind/chrome/use-context-menu-controller.ts +201 -0
- package/src/ui-tailwind/chrome-overlay/chrome-overlay-projector.ts +1 -1
- package/src/ui-tailwind/chrome-overlay/tw-chrome-overlay.tsx +22 -4
- package/src/ui-tailwind/chrome-overlay/tw-comment-balloon-layer.tsx +1 -1
- package/src/ui-tailwind/chrome-overlay/tw-locked-block-layer.tsx +1 -1
- package/src/ui-tailwind/chrome-overlay/tw-object-selection-overlay.tsx +11 -5
- package/src/ui-tailwind/chrome-overlay/tw-page-stack-overlay-layer.tsx +197 -3
- package/src/ui-tailwind/chrome-overlay/tw-revision-margin-bar-layer.tsx +1 -1
- package/src/ui-tailwind/chrome-overlay/tw-scope-card-layer.tsx +35 -6
- package/src/ui-tailwind/chrome-overlay/tw-scope-rail-layer.tsx +24 -16
- package/src/ui-tailwind/chrome-overlay/tw-table-continuation-header.tsx +1 -1
- package/src/ui-tailwind/debug/README.md +57 -0
- package/src/ui-tailwind/debug/index.ts +3 -0
- package/src/ui-tailwind/debug/tw-debug-overlay.tsx +186 -0
- package/src/ui-tailwind/debug/tw-debug-presentation.tsx +80 -0
- package/src/ui-tailwind/debug/tw-debug-top-bar.tsx +83 -0
- package/src/ui-tailwind/editor-surface/chart-node-view.tsx +2 -2
- package/src/ui-tailwind/editor-surface/float-wrap-resolver.ts +1 -1
- package/src/ui-tailwind/editor-surface/pm-command-bridge.ts +135 -10
- package/src/ui-tailwind/editor-surface/pm-decorations.ts +40 -13
- package/src/ui-tailwind/editor-surface/pm-page-break-decorations.ts +1 -1
- package/src/ui-tailwind/editor-surface/pm-schema.ts +1 -1
- package/src/ui-tailwind/editor-surface/pm-state-from-snapshot.ts +3 -3
- package/src/ui-tailwind/editor-surface/predicted-tag-preflight.ts +1 -1
- package/src/ui-tailwind/editor-surface/remote-cursor-plugin.ts +2 -2
- package/src/ui-tailwind/editor-surface/scroll-anchor.ts +91 -9
- package/src/ui-tailwind/editor-surface/shape-renderer.ts +1 -1
- package/src/ui-tailwind/editor-surface/surface-layer.ts +1 -1
- package/src/ui-tailwind/editor-surface/tw-opaque-block.tsx +1 -1
- package/src/ui-tailwind/editor-surface/tw-page-block-view.helpers.ts +23 -6
- package/src/ui-tailwind/editor-surface/tw-prosemirror-surface.tsx +132 -22
- package/src/ui-tailwind/editor-surface/tw-table-node-view.tsx +1 -1
- package/src/ui-tailwind/index.ts +0 -5
- package/src/ui-tailwind/overlay-anchor-bridge-context.tsx +33 -0
- package/src/ui-tailwind/page-stack/floating-image-overlay-model.ts +66 -29
- package/src/ui-tailwind/page-stack/tw-floating-image-layer.tsx +25 -2
- package/src/ui-tailwind/review/comment-markdown-renderer.tsx +15 -0
- package/src/ui-tailwind/review/tw-review-rail.tsx +92 -4
- package/src/ui-tailwind/review/tw-workflow-tab.tsx +1 -1
- package/src/ui-tailwind/review-workspace/page-chrome.ts +210 -0
- package/src/ui-tailwind/review-workspace/page-shell-metrics.ts +101 -0
- package/src/ui-tailwind/review-workspace/paragraph-layout.ts +115 -0
- package/src/ui-tailwind/review-workspace/selection-toolbar-placement.ts +97 -0
- package/src/ui-tailwind/review-workspace/tw-review-workspace-navigator.tsx +130 -0
- package/src/ui-tailwind/review-workspace/tw-review-workspace-page-toolbar.tsx +240 -0
- package/src/ui-tailwind/review-workspace/tw-review-workspace-rail.tsx +59 -0
- package/src/ui-tailwind/review-workspace/types.ts +408 -0
- package/src/ui-tailwind/review-workspace/use-chrome-policy.ts +104 -0
- package/src/ui-tailwind/review-workspace/use-derived-view-state.ts +151 -0
- package/src/ui-tailwind/review-workspace/use-diagnostics-signal.ts +70 -0
- package/src/ui-tailwind/review-workspace/use-grabbed-segment-offsets.ts +40 -0
- package/src/ui-tailwind/review-workspace/use-layout-facet-render-signal.ts +55 -0
- package/src/ui-tailwind/review-workspace/use-page-markers.ts +130 -0
- package/src/ui-tailwind/review-workspace/use-pm-surface-capture.ts +60 -0
- package/src/ui-tailwind/review-workspace/use-review-rail-state.ts +63 -0
- package/src/ui-tailwind/review-workspace/use-scope-card-state.ts +170 -0
- package/src/ui-tailwind/review-workspace/use-scroll-root-capture.ts +28 -0
- package/src/ui-tailwind/review-workspace/use-selection-toolbar-placement.ts +113 -0
- package/src/ui-tailwind/review-workspace/use-shell-selection-anchor-bridge.ts +120 -0
- package/src/ui-tailwind/review-workspace/use-status-bar-page-facts.ts +55 -0
- package/src/ui-tailwind/review-workspace/use-viewport-dimensions.ts +43 -0
- package/src/ui-tailwind/review-workspace/use-workspace-arbiter.ts +25 -0
- package/src/ui-tailwind/review-workspace/use-workspace-composition.ts +86 -0
- package/src/ui-tailwind/review-workspace/use-workspace-side-effects.ts +150 -0
- package/src/ui-tailwind/theme/editor-theme.css +25 -0
- package/src/ui-tailwind/toolbar/tw-role-action-region.tsx +2 -2
- package/src/ui-tailwind/toolbar/tw-toolbar.tsx +61 -98
- package/src/ui-tailwind/tw-review-workspace.tsx +521 -1802
- package/src/ui-tailwind/ui-api-context.tsx +43 -0
- package/src/ui-tailwind/ui-shell-channels-context.tsx +49 -0
- package/src/validation/compatibility-engine.ts +6 -6
- package/src/runtime/styles-cascade.ts +0 -33
- package/src/ui-tailwind/chrome/tw-mode-dock.tsx +0 -85
- /package/src/runtime/{page-number-format.ts → formatting/field/page-number-format.ts} +0 -0
- /package/src/runtime/{ai-action-policy.ts → workflow/ai-action-policy.ts} +0 -0
- /package/src/runtime/{scope-tag-registry.ts → workflow/scope-tag-registry.ts} +0 -0
|
@@ -0,0 +1,553 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* editor-action-registry — the single source of truth for what
|
|
3
|
+
* contextual actions exist, keyed by `TargetKind`.
|
|
4
|
+
*
|
|
5
|
+
* Consumed by three access routes so DESIGN-EDITOR.md §6.4 holds by
|
|
6
|
+
* construction ("right-click cannot be richer than the floating surface;
|
|
7
|
+
* cannot duplicate command trees"):
|
|
8
|
+
*
|
|
9
|
+
* 1. Right-click context menu (via `build-context-menu-entries.ts`)
|
|
10
|
+
* 2. Inline "More…" affordance on reduced floating toolbars (Phase D)
|
|
11
|
+
* 3. Command palette groups (Phase C.δ)
|
|
12
|
+
*
|
|
13
|
+
* All three routes produce the same actions from this registry — they
|
|
14
|
+
* cannot diverge. This is the load-bearing decision that makes the
|
|
15
|
+
* floating-menu demotion legal.
|
|
16
|
+
*
|
|
17
|
+
* Perf discipline: pure data + pure filter helpers. No DOM reads, no
|
|
18
|
+
* runtime calls, no observers. Actions are dispatched through host-
|
|
19
|
+
* supplied callbacks so the registry never references the PM view or
|
|
20
|
+
* the document runtime directly.
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
import type { EditorChromeMode } from "../../api/v3/ui/chrome-composition";
|
|
24
|
+
import type { ContextMenuGroupId } from "./tw-context-menu";
|
|
25
|
+
import type { ShortcutKey } from "./tw-shortcut-hint";
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Target kinds roughly mirror DESIGN-EDITOR.md §4 "Local context" cells.
|
|
29
|
+
* A contextmenu event resolves its target to one (or more) of these
|
|
30
|
+
* kinds; the builder then asks the registry for every action whose
|
|
31
|
+
* `targetKinds` set includes at least one of the resolved kinds.
|
|
32
|
+
*/
|
|
33
|
+
export type TargetKind =
|
|
34
|
+
| "plain-text" // caret or selection in flowing body text
|
|
35
|
+
| "table-cell" // caret / selection inside a table cell (T1/T2)
|
|
36
|
+
| "table-row" // whole row selected (T3) — Chrome Closure Pass · Task 3
|
|
37
|
+
| "table-column" // whole column selected (T4b) — Chrome Closure Pass · Task 3
|
|
38
|
+
| "table-whole" // whole table selected (T5) — Chrome Closure Pass · Task 3
|
|
39
|
+
| "image" // an anchored image (inline or floating)
|
|
40
|
+
| "object" // preserved shape / textbox / OLE / SmartArt
|
|
41
|
+
| "hyperlink" // caret inside or selection over a hyperlink
|
|
42
|
+
| "comment-anchor" // caret at a comment-anchored range
|
|
43
|
+
| "suggestion" // caret at a tracked-change suggestion
|
|
44
|
+
| "opaque-block" // preserved-for-export placeholder
|
|
45
|
+
| "scope-anchor"; // caret inside a workflow scope
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Dispatch context passed to each action's `run()` function.
|
|
49
|
+
* Host callbacks + composition posture + selection state come through
|
|
50
|
+
* here so the registry's actions never reach into React / PM internals.
|
|
51
|
+
*/
|
|
52
|
+
export interface EditorActionDispatchContext {
|
|
53
|
+
readonly composition: { readonly mode: EditorChromeMode };
|
|
54
|
+
readonly host: EditorActionHostCallbacks;
|
|
55
|
+
/** Close the menu / palette after dispatching, if applicable. */
|
|
56
|
+
readonly dismiss: () => void;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Host callbacks the editor shell passes down to the registry. All
|
|
61
|
+
* fields are optional — the registry's `when()` predicates filter out
|
|
62
|
+
* actions the host hasn't wired yet so the menu never shows a row that
|
|
63
|
+
* can't fire.
|
|
64
|
+
*
|
|
65
|
+
* Phases C/D/E will wire these from the existing ref methods on
|
|
66
|
+
* `WordReviewEditorRef`; the surface is intentionally minimal now.
|
|
67
|
+
*/
|
|
68
|
+
export interface EditorActionHostCallbacks {
|
|
69
|
+
// Clipboard (always available — browser-native fallback acceptable)
|
|
70
|
+
readonly onCut?: () => void;
|
|
71
|
+
readonly onCopy?: () => void;
|
|
72
|
+
readonly onPaste?: () => void;
|
|
73
|
+
|
|
74
|
+
// Tracked-change operations (suggestion target)
|
|
75
|
+
readonly onAcceptSuggestion?: () => void;
|
|
76
|
+
readonly onRejectSuggestion?: () => void;
|
|
77
|
+
|
|
78
|
+
// Comment operations (comment-anchor target)
|
|
79
|
+
readonly onResolveComment?: () => void;
|
|
80
|
+
readonly onReplyToComment?: () => void;
|
|
81
|
+
readonly onJumpToCommentInRail?: () => void;
|
|
82
|
+
|
|
83
|
+
// Table operations (table-cell target)
|
|
84
|
+
readonly onInsertRowAbove?: () => void;
|
|
85
|
+
readonly onInsertRowBelow?: () => void;
|
|
86
|
+
readonly onInsertColumnBefore?: () => void;
|
|
87
|
+
readonly onInsertColumnAfter?: () => void;
|
|
88
|
+
readonly onDeleteRow?: () => void;
|
|
89
|
+
readonly onDeleteColumn?: () => void;
|
|
90
|
+
readonly onMergeCells?: () => void;
|
|
91
|
+
readonly onSplitCell?: () => void;
|
|
92
|
+
readonly onOpenTableProperties?: () => void;
|
|
93
|
+
readonly onOpenBorderPicker?: () => void;
|
|
94
|
+
|
|
95
|
+
// Image operations (image target)
|
|
96
|
+
readonly onReplaceImage?: () => void;
|
|
97
|
+
readonly onEditImageAltText?: () => void;
|
|
98
|
+
readonly onSetImageSize?: (preset: "small" | "medium" | "large") => void;
|
|
99
|
+
|
|
100
|
+
// Object operations (object target — read-only info by DESIGN-EDITOR.md §6.10)
|
|
101
|
+
readonly onOpenObjectInfo?: () => void;
|
|
102
|
+
|
|
103
|
+
// Hyperlink operations (hyperlink target)
|
|
104
|
+
readonly onEditHyperlink?: () => void;
|
|
105
|
+
readonly onRemoveHyperlink?: () => void;
|
|
106
|
+
readonly onOpenHyperlink?: () => void;
|
|
107
|
+
|
|
108
|
+
// Workflow (scope-anchor target)
|
|
109
|
+
readonly onJumpToScopeInRail?: () => void;
|
|
110
|
+
readonly onOpenScopeCard?: () => void;
|
|
111
|
+
readonly onMarkScopeResolved?: () => void;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export interface EditorAction {
|
|
115
|
+
readonly id: string;
|
|
116
|
+
readonly label: string;
|
|
117
|
+
readonly shortcut?: readonly ShortcutKey[];
|
|
118
|
+
readonly group: ContextMenuGroupId;
|
|
119
|
+
/** Targets for which this action is relevant. */
|
|
120
|
+
readonly targetKinds: ReadonlySet<TargetKind>;
|
|
121
|
+
/**
|
|
122
|
+
* Optional mode filter — some actions only surface in specific modes.
|
|
123
|
+
* Empty / undefined means "always in scope of its target".
|
|
124
|
+
*/
|
|
125
|
+
readonly modes?: ReadonlySet<EditorChromeMode>;
|
|
126
|
+
/**
|
|
127
|
+
* Optional availability predicate. Return `false` to hide the row;
|
|
128
|
+
* `true` to show; `"disabled"` to show as a non-interactive disabled
|
|
129
|
+
* row (DESIGN-EDITOR.md §6.4 "disabled items remain visible when
|
|
130
|
+
* explanation matters").
|
|
131
|
+
*/
|
|
132
|
+
readonly when?: (
|
|
133
|
+
ctx: EditorActionDispatchContext,
|
|
134
|
+
) => boolean | "disabled";
|
|
135
|
+
readonly run: (ctx: EditorActionDispatchContext) => void;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// ---------------------------------------------------------------------
|
|
139
|
+
// The registry itself — terse, data-driven.
|
|
140
|
+
// ---------------------------------------------------------------------
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Build a zero-argument action. The callback referenced by `opts.callback`
|
|
144
|
+
* is invoked with no arguments at dispatch. Use `mkArg()` below for
|
|
145
|
+
* callbacks that take a payload.
|
|
146
|
+
*/
|
|
147
|
+
function mk<K extends keyof EditorActionHostCallbacks>(opts: {
|
|
148
|
+
id: string;
|
|
149
|
+
label: string;
|
|
150
|
+
shortcut?: readonly ShortcutKey[];
|
|
151
|
+
group: ContextMenuGroupId;
|
|
152
|
+
targetKinds: readonly TargetKind[];
|
|
153
|
+
modes?: readonly EditorChromeMode[];
|
|
154
|
+
callback: K;
|
|
155
|
+
/** Optional extra predicate run after the callback-presence check. */
|
|
156
|
+
when?: (ctx: EditorActionDispatchContext) => boolean | "disabled";
|
|
157
|
+
}): EditorAction {
|
|
158
|
+
return {
|
|
159
|
+
id: opts.id,
|
|
160
|
+
label: opts.label,
|
|
161
|
+
...(opts.shortcut ? { shortcut: opts.shortcut } : {}),
|
|
162
|
+
group: opts.group,
|
|
163
|
+
targetKinds: new Set(opts.targetKinds),
|
|
164
|
+
...(opts.modes ? { modes: new Set(opts.modes) } : {}),
|
|
165
|
+
when: (ctx) => {
|
|
166
|
+
if (typeof ctx.host[opts.callback] !== "function") return false;
|
|
167
|
+
if (opts.when) return opts.when(ctx);
|
|
168
|
+
return true;
|
|
169
|
+
},
|
|
170
|
+
run: (ctx) => {
|
|
171
|
+
const fn = ctx.host[opts.callback] as (() => void) | undefined;
|
|
172
|
+
fn?.();
|
|
173
|
+
ctx.dismiss();
|
|
174
|
+
},
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Build a one-argument action. `payload` is the value passed to the
|
|
180
|
+
* callback at dispatch. This preserves argument-type discipline for
|
|
181
|
+
* parameterized host callbacks like
|
|
182
|
+
* `onSetImageSize(preset: "small" | "medium" | "large")`.
|
|
183
|
+
*
|
|
184
|
+
* Fixes the pre-fix bug where `mk()` cast every callback to `(() => void)`
|
|
185
|
+
* and invoked with zero arguments, leaving image-size / similar actions
|
|
186
|
+
* firing with `undefined` payloads at runtime. The `A` generic parameter
|
|
187
|
+
* MUST match the callback's argument type — callers supply it explicitly
|
|
188
|
+
* at the call site (TypeScript cannot infer from the narrow payload
|
|
189
|
+
* literal in a way that catches mismatch against the host signature).
|
|
190
|
+
*/
|
|
191
|
+
function mkArg<A, K extends keyof EditorActionHostCallbacks>(opts: {
|
|
192
|
+
id: string;
|
|
193
|
+
label: string;
|
|
194
|
+
shortcut?: readonly ShortcutKey[];
|
|
195
|
+
group: ContextMenuGroupId;
|
|
196
|
+
targetKinds: readonly TargetKind[];
|
|
197
|
+
modes?: readonly EditorChromeMode[];
|
|
198
|
+
callback: K;
|
|
199
|
+
payload: A;
|
|
200
|
+
when?: (ctx: EditorActionDispatchContext) => boolean | "disabled";
|
|
201
|
+
}): EditorAction {
|
|
202
|
+
return {
|
|
203
|
+
id: opts.id,
|
|
204
|
+
label: opts.label,
|
|
205
|
+
...(opts.shortcut ? { shortcut: opts.shortcut } : {}),
|
|
206
|
+
group: opts.group,
|
|
207
|
+
targetKinds: new Set(opts.targetKinds),
|
|
208
|
+
...(opts.modes ? { modes: new Set(opts.modes) } : {}),
|
|
209
|
+
when: (ctx) => {
|
|
210
|
+
if (typeof ctx.host[opts.callback] !== "function") return false;
|
|
211
|
+
if (opts.when) return opts.when(ctx);
|
|
212
|
+
return true;
|
|
213
|
+
},
|
|
214
|
+
run: (ctx) => {
|
|
215
|
+
const fn = ctx.host[opts.callback] as ((arg: A) => void) | undefined;
|
|
216
|
+
fn?.(opts.payload);
|
|
217
|
+
ctx.dismiss();
|
|
218
|
+
},
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
export const EDITOR_ACTION_REGISTRY: readonly EditorAction[] = [
|
|
223
|
+
// -------- Clipboard (always available across every target kind) --------
|
|
224
|
+
mk({
|
|
225
|
+
id: "cut",
|
|
226
|
+
label: "Cut",
|
|
227
|
+
shortcut: ["Mod", "X"],
|
|
228
|
+
group: "clipboard",
|
|
229
|
+
targetKinds: [
|
|
230
|
+
"plain-text",
|
|
231
|
+
"table-cell",
|
|
232
|
+
"image",
|
|
233
|
+
"hyperlink",
|
|
234
|
+
"suggestion",
|
|
235
|
+
"comment-anchor",
|
|
236
|
+
"opaque-block",
|
|
237
|
+
"scope-anchor",
|
|
238
|
+
],
|
|
239
|
+
callback: "onCut",
|
|
240
|
+
}),
|
|
241
|
+
mk({
|
|
242
|
+
id: "copy",
|
|
243
|
+
label: "Copy",
|
|
244
|
+
shortcut: ["Mod", "C"],
|
|
245
|
+
group: "clipboard",
|
|
246
|
+
targetKinds: [
|
|
247
|
+
"plain-text",
|
|
248
|
+
"table-cell",
|
|
249
|
+
"image",
|
|
250
|
+
"hyperlink",
|
|
251
|
+
"suggestion",
|
|
252
|
+
"comment-anchor",
|
|
253
|
+
"opaque-block",
|
|
254
|
+
"scope-anchor",
|
|
255
|
+
],
|
|
256
|
+
callback: "onCopy",
|
|
257
|
+
}),
|
|
258
|
+
mk({
|
|
259
|
+
id: "paste",
|
|
260
|
+
label: "Paste",
|
|
261
|
+
shortcut: ["Mod", "V"],
|
|
262
|
+
group: "clipboard",
|
|
263
|
+
targetKinds: [
|
|
264
|
+
"plain-text",
|
|
265
|
+
"table-cell",
|
|
266
|
+
"hyperlink",
|
|
267
|
+
"suggestion",
|
|
268
|
+
"comment-anchor",
|
|
269
|
+
"scope-anchor",
|
|
270
|
+
],
|
|
271
|
+
callback: "onPaste",
|
|
272
|
+
}),
|
|
273
|
+
|
|
274
|
+
// -------- Suggestion / tracked change --------
|
|
275
|
+
mk({
|
|
276
|
+
id: "accept-suggestion",
|
|
277
|
+
label: "Accept suggestion",
|
|
278
|
+
group: "suggestion",
|
|
279
|
+
targetKinds: ["suggestion"],
|
|
280
|
+
callback: "onAcceptSuggestion",
|
|
281
|
+
}),
|
|
282
|
+
mk({
|
|
283
|
+
id: "reject-suggestion",
|
|
284
|
+
label: "Reject suggestion",
|
|
285
|
+
group: "suggestion",
|
|
286
|
+
targetKinds: ["suggestion"],
|
|
287
|
+
callback: "onRejectSuggestion",
|
|
288
|
+
}),
|
|
289
|
+
|
|
290
|
+
// -------- Comment --------
|
|
291
|
+
mk({
|
|
292
|
+
id: "resolve-comment",
|
|
293
|
+
label: "Resolve comment",
|
|
294
|
+
group: "comment",
|
|
295
|
+
targetKinds: ["comment-anchor"],
|
|
296
|
+
callback: "onResolveComment",
|
|
297
|
+
}),
|
|
298
|
+
mk({
|
|
299
|
+
id: "reply-to-comment",
|
|
300
|
+
label: "Reply to comment",
|
|
301
|
+
group: "comment",
|
|
302
|
+
targetKinds: ["comment-anchor"],
|
|
303
|
+
callback: "onReplyToComment",
|
|
304
|
+
}),
|
|
305
|
+
mk({
|
|
306
|
+
id: "jump-to-comment-in-rail",
|
|
307
|
+
label: "Open in rail",
|
|
308
|
+
group: "comment",
|
|
309
|
+
targetKinds: ["comment-anchor"],
|
|
310
|
+
callback: "onJumpToCommentInRail",
|
|
311
|
+
}),
|
|
312
|
+
|
|
313
|
+
// -------- Table --------
|
|
314
|
+
// Chrome Closure Pass · Task 3 — table actions are split across the
|
|
315
|
+
// tier ladder per designsystem.md §6.9. The menu builder asks the
|
|
316
|
+
// registry for actions whose `targetKinds` overlap any of the
|
|
317
|
+
// resolved kinds (table-cell ⊂ table-row ⊂ table-column ⊂
|
|
318
|
+
// table-whole — each higher tier inherits the cell-level ops). The
|
|
319
|
+
// cell-level ops carry every table-* kind so they remain visible at
|
|
320
|
+
// every tier; the row-only / column-only / whole-table ops carry
|
|
321
|
+
// only the kinds that should expose them.
|
|
322
|
+
|
|
323
|
+
// ── Cell-level ops — visible at every tier ──
|
|
324
|
+
mk({
|
|
325
|
+
id: "table-insert-row-above",
|
|
326
|
+
label: "Insert row above",
|
|
327
|
+
group: "table",
|
|
328
|
+
targetKinds: ["table-cell", "table-row", "table-column", "table-whole"],
|
|
329
|
+
callback: "onInsertRowAbove",
|
|
330
|
+
}),
|
|
331
|
+
mk({
|
|
332
|
+
id: "table-insert-row-below",
|
|
333
|
+
label: "Insert row below",
|
|
334
|
+
group: "table",
|
|
335
|
+
targetKinds: ["table-cell", "table-row", "table-column", "table-whole"],
|
|
336
|
+
callback: "onInsertRowBelow",
|
|
337
|
+
}),
|
|
338
|
+
mk({
|
|
339
|
+
id: "table-insert-column-before",
|
|
340
|
+
label: "Insert column before",
|
|
341
|
+
group: "table",
|
|
342
|
+
targetKinds: ["table-cell", "table-row", "table-column", "table-whole"],
|
|
343
|
+
callback: "onInsertColumnBefore",
|
|
344
|
+
}),
|
|
345
|
+
mk({
|
|
346
|
+
id: "table-insert-column-after",
|
|
347
|
+
label: "Insert column after",
|
|
348
|
+
group: "table",
|
|
349
|
+
targetKinds: ["table-cell", "table-row", "table-column", "table-whole"],
|
|
350
|
+
callback: "onInsertColumnAfter",
|
|
351
|
+
}),
|
|
352
|
+
mk({
|
|
353
|
+
id: "table-merge-cells",
|
|
354
|
+
label: "Merge cells",
|
|
355
|
+
group: "table",
|
|
356
|
+
targetKinds: ["table-cell", "table-row", "table-column", "table-whole"],
|
|
357
|
+
callback: "onMergeCells",
|
|
358
|
+
}),
|
|
359
|
+
mk({
|
|
360
|
+
id: "table-split-cell",
|
|
361
|
+
label: "Split cell",
|
|
362
|
+
group: "table",
|
|
363
|
+
targetKinds: ["table-cell", "table-row", "table-column", "table-whole"],
|
|
364
|
+
callback: "onSplitCell",
|
|
365
|
+
}),
|
|
366
|
+
// ── Row-only — Delete row only when a row is selected (T3) ──
|
|
367
|
+
mk({
|
|
368
|
+
id: "table-delete-row",
|
|
369
|
+
label: "Delete row",
|
|
370
|
+
group: "table",
|
|
371
|
+
targetKinds: ["table-row", "table-whole"],
|
|
372
|
+
callback: "onDeleteRow",
|
|
373
|
+
}),
|
|
374
|
+
// ── Column-only — Delete column only when a column is selected (T4b) ──
|
|
375
|
+
mk({
|
|
376
|
+
id: "table-delete-column",
|
|
377
|
+
label: "Delete column",
|
|
378
|
+
group: "table",
|
|
379
|
+
targetKinds: ["table-column", "table-whole"],
|
|
380
|
+
callback: "onDeleteColumn",
|
|
381
|
+
}),
|
|
382
|
+
// ── Whole-table — properties / borders surface at any tier so
|
|
383
|
+
// they are reachable from a single right-click in a cell ──
|
|
384
|
+
mk({
|
|
385
|
+
id: "table-properties",
|
|
386
|
+
label: "Table properties…",
|
|
387
|
+
group: "table",
|
|
388
|
+
targetKinds: ["table-cell", "table-row", "table-column", "table-whole"],
|
|
389
|
+
callback: "onOpenTableProperties",
|
|
390
|
+
}),
|
|
391
|
+
mk({
|
|
392
|
+
id: "table-borders",
|
|
393
|
+
label: "Borders…",
|
|
394
|
+
group: "table",
|
|
395
|
+
targetKinds: ["table-cell", "table-row", "table-column", "table-whole"],
|
|
396
|
+
callback: "onOpenBorderPicker",
|
|
397
|
+
}),
|
|
398
|
+
|
|
399
|
+
// -------- Image --------
|
|
400
|
+
mk({
|
|
401
|
+
id: "image-replace",
|
|
402
|
+
label: "Replace image…",
|
|
403
|
+
group: "misc",
|
|
404
|
+
targetKinds: ["image"],
|
|
405
|
+
callback: "onReplaceImage",
|
|
406
|
+
}),
|
|
407
|
+
mk({
|
|
408
|
+
id: "image-alt-text",
|
|
409
|
+
label: "Edit alt text…",
|
|
410
|
+
group: "misc",
|
|
411
|
+
targetKinds: ["image"],
|
|
412
|
+
callback: "onEditImageAltText",
|
|
413
|
+
}),
|
|
414
|
+
mkArg<"small" | "medium" | "large", "onSetImageSize">({
|
|
415
|
+
id: "image-size-small",
|
|
416
|
+
label: "Small",
|
|
417
|
+
group: "misc",
|
|
418
|
+
targetKinds: ["image"],
|
|
419
|
+
callback: "onSetImageSize",
|
|
420
|
+
payload: "small",
|
|
421
|
+
}),
|
|
422
|
+
mkArg<"small" | "medium" | "large", "onSetImageSize">({
|
|
423
|
+
id: "image-size-medium",
|
|
424
|
+
label: "Medium",
|
|
425
|
+
group: "misc",
|
|
426
|
+
targetKinds: ["image"],
|
|
427
|
+
callback: "onSetImageSize",
|
|
428
|
+
payload: "medium",
|
|
429
|
+
}),
|
|
430
|
+
mkArg<"small" | "medium" | "large", "onSetImageSize">({
|
|
431
|
+
id: "image-size-large",
|
|
432
|
+
label: "Large",
|
|
433
|
+
group: "misc",
|
|
434
|
+
targetKinds: ["image"],
|
|
435
|
+
callback: "onSetImageSize",
|
|
436
|
+
payload: "large",
|
|
437
|
+
}),
|
|
438
|
+
|
|
439
|
+
// -------- Object (read-only info per DESIGN-EDITOR.md §6.10) --------
|
|
440
|
+
mk({
|
|
441
|
+
id: "object-info",
|
|
442
|
+
label: "Object info…",
|
|
443
|
+
group: "misc",
|
|
444
|
+
targetKinds: ["object"],
|
|
445
|
+
callback: "onOpenObjectInfo",
|
|
446
|
+
}),
|
|
447
|
+
|
|
448
|
+
// -------- Hyperlink --------
|
|
449
|
+
mk({
|
|
450
|
+
id: "hyperlink-edit",
|
|
451
|
+
label: "Edit link…",
|
|
452
|
+
group: "misc",
|
|
453
|
+
targetKinds: ["hyperlink"],
|
|
454
|
+
callback: "onEditHyperlink",
|
|
455
|
+
}),
|
|
456
|
+
mk({
|
|
457
|
+
id: "hyperlink-remove",
|
|
458
|
+
label: "Remove link",
|
|
459
|
+
group: "misc",
|
|
460
|
+
targetKinds: ["hyperlink"],
|
|
461
|
+
callback: "onRemoveHyperlink",
|
|
462
|
+
}),
|
|
463
|
+
mk({
|
|
464
|
+
id: "hyperlink-open",
|
|
465
|
+
label: "Open link",
|
|
466
|
+
group: "misc",
|
|
467
|
+
targetKinds: ["hyperlink"],
|
|
468
|
+
callback: "onOpenHyperlink",
|
|
469
|
+
}),
|
|
470
|
+
|
|
471
|
+
// -------- Workflow scope --------
|
|
472
|
+
mk({
|
|
473
|
+
id: "scope-open-card",
|
|
474
|
+
label: "Open scope card",
|
|
475
|
+
group: "misc",
|
|
476
|
+
targetKinds: ["scope-anchor"],
|
|
477
|
+
callback: "onOpenScopeCard",
|
|
478
|
+
modes: ["workflow", "review"],
|
|
479
|
+
}),
|
|
480
|
+
mk({
|
|
481
|
+
id: "scope-jump-in-rail",
|
|
482
|
+
label: "Open scope in rail",
|
|
483
|
+
group: "misc",
|
|
484
|
+
targetKinds: ["scope-anchor"],
|
|
485
|
+
callback: "onJumpToScopeInRail",
|
|
486
|
+
modes: ["workflow", "review"],
|
|
487
|
+
}),
|
|
488
|
+
mk({
|
|
489
|
+
id: "scope-mark-resolved",
|
|
490
|
+
label: "Mark scope resolved",
|
|
491
|
+
group: "misc",
|
|
492
|
+
targetKinds: ["scope-anchor"],
|
|
493
|
+
callback: "onMarkScopeResolved",
|
|
494
|
+
// Workflow-only — review posture inspects, doesn't mutate scope state.
|
|
495
|
+
modes: ["workflow"],
|
|
496
|
+
}),
|
|
497
|
+
];
|
|
498
|
+
|
|
499
|
+
/**
|
|
500
|
+
* Result row from `resolveActionsForTarget`. Carries the evaluated
|
|
501
|
+
* `when()` verdict alongside the action so callers (e.g. the context-
|
|
502
|
+
* menu builder) don't re-evaluate the predicate a second time just to
|
|
503
|
+
* detect the `"disabled"` state.
|
|
504
|
+
*/
|
|
505
|
+
export interface ResolvedEditorAction {
|
|
506
|
+
readonly action: EditorAction;
|
|
507
|
+
readonly disabled: boolean;
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
/**
|
|
511
|
+
* Query the registry for every action whose target set includes `kind`
|
|
512
|
+
* and whose mode filter (if any) matches the current composition mode.
|
|
513
|
+
* Each `when()` predicate runs once per resolution; the result includes
|
|
514
|
+
* a `disabled` flag so callers render disabled rows without a second
|
|
515
|
+
* evaluation.
|
|
516
|
+
*
|
|
517
|
+
* Pure — no side effects. The overload below preserves the legacy
|
|
518
|
+
* `readonly EditorAction[]` return shape for tests that don't need the
|
|
519
|
+
* disabled flag.
|
|
520
|
+
*/
|
|
521
|
+
export function resolveActionsForTarget(
|
|
522
|
+
kind: TargetKind,
|
|
523
|
+
mode: EditorChromeMode,
|
|
524
|
+
host: EditorActionHostCallbacks,
|
|
525
|
+
): readonly EditorAction[];
|
|
526
|
+
export function resolveActionsForTarget(
|
|
527
|
+
kind: TargetKind,
|
|
528
|
+
mode: EditorChromeMode,
|
|
529
|
+
host: EditorActionHostCallbacks,
|
|
530
|
+
options: { includeDisabled: true },
|
|
531
|
+
): readonly ResolvedEditorAction[];
|
|
532
|
+
export function resolveActionsForTarget(
|
|
533
|
+
kind: TargetKind,
|
|
534
|
+
mode: EditorChromeMode,
|
|
535
|
+
host: EditorActionHostCallbacks,
|
|
536
|
+
options?: { includeDisabled?: boolean },
|
|
537
|
+
): readonly EditorAction[] | readonly ResolvedEditorAction[] {
|
|
538
|
+
const ctx: EditorActionDispatchContext = {
|
|
539
|
+
composition: { mode },
|
|
540
|
+
host,
|
|
541
|
+
dismiss: () => {},
|
|
542
|
+
};
|
|
543
|
+
const resolved: ResolvedEditorAction[] = [];
|
|
544
|
+
for (const action of EDITOR_ACTION_REGISTRY) {
|
|
545
|
+
if (!action.targetKinds.has(kind)) continue;
|
|
546
|
+
if (action.modes && !action.modes.has(mode)) continue;
|
|
547
|
+
const verdict = action.when ? action.when(ctx) : true;
|
|
548
|
+
if (verdict === false) continue;
|
|
549
|
+
resolved.push({ action, disabled: verdict === "disabled" });
|
|
550
|
+
}
|
|
551
|
+
if (options?.includeDisabled) return resolved;
|
|
552
|
+
return resolved.map((r) => r.action);
|
|
553
|
+
}
|