@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
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
*/
|
|
25
25
|
|
|
26
26
|
import { Decoration } from "prosemirror-view";
|
|
27
|
-
import type { RuntimePageGraph } from "../../
|
|
27
|
+
import type { RuntimePageGraph } from "../../api/public-types.ts";
|
|
28
28
|
import { resolvePageFieldDisplayText } from "../../runtime/layout/resolve-page-fields.ts";
|
|
29
29
|
|
|
30
30
|
export const PAGE_CHROME_DEFAULTS = {
|
|
@@ -12,7 +12,7 @@ import type {
|
|
|
12
12
|
import { shouldRenderAbsoluteFloatingImageInPageOverlay } from "../page-stack/floating-image-overlay-model.ts";
|
|
13
13
|
import { editorSchema } from "./pm-schema";
|
|
14
14
|
import { buildPositionMap, type PositionMap } from "./pm-position-map";
|
|
15
|
-
import {
|
|
15
|
+
import { getChartModel } from "../../api/v3/runtime/chart.ts";
|
|
16
16
|
|
|
17
17
|
export interface PMStateResult {
|
|
18
18
|
state: EditorState;
|
|
@@ -783,7 +783,7 @@ function buildOpaqueInlineOrComplexAtom(
|
|
|
783
783
|
let widthPx: number | null = null;
|
|
784
784
|
let heightPx: number | null = null;
|
|
785
785
|
if (parsedChartId) {
|
|
786
|
-
const entry =
|
|
786
|
+
const entry = getChartModel(parsedChartId);
|
|
787
787
|
if (entry) {
|
|
788
788
|
widthPx = entry.widthPx;
|
|
789
789
|
heightPx = entry.heightPx;
|
|
@@ -857,7 +857,7 @@ function buildOpaqueBlock(
|
|
|
857
857
|
): PMNode {
|
|
858
858
|
// Viewport-culled placeholder: emit a single paragraph with ZWSP text so
|
|
859
859
|
// PM position math matches the original block span.
|
|
860
|
-
// See
|
|
860
|
+
// See CLAUDE.md (lane status table) Task 2.2.3.
|
|
861
861
|
const placeholderSize = block.placeholderSize ?? null;
|
|
862
862
|
if (placeholderSize !== null) {
|
|
863
863
|
const targetSize = placeholderSize as number;
|
|
@@ -2,7 +2,7 @@ import type {
|
|
|
2
2
|
EditorSurfaceSnapshot,
|
|
3
3
|
SurfaceBlockSnapshot,
|
|
4
4
|
} from "../../api/public-types.ts";
|
|
5
|
-
import type { ScopeTagRegistry } from "../../
|
|
5
|
+
import type { ScopeTagRegistry } from "../../api/public-types.ts";
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Pre-flight check the FastTextEditLane consults before applying a predicted
|
|
@@ -5,12 +5,12 @@ import type { EditorView } from "prosemirror-view";
|
|
|
5
5
|
import type { Awareness } from "y-protocols/awareness";
|
|
6
6
|
|
|
7
7
|
import type { EditorStoryTarget } from "../../api/public-types";
|
|
8
|
-
import { storyTargetsEqual } from "../../
|
|
8
|
+
import { storyTargetsEqual } from "../../api/public-types";
|
|
9
9
|
import type { PositionMap } from "./pm-position-map";
|
|
10
10
|
import {
|
|
11
11
|
getRemoteCursorStates,
|
|
12
12
|
type RemoteCursorState,
|
|
13
|
-
} from "../../runtime/collab
|
|
13
|
+
} from "../../api/v3/runtime/collab";
|
|
14
14
|
|
|
15
15
|
/**
|
|
16
16
|
* Remote `cursor.color` comes straight off Yjs Awareness — another peer
|
|
@@ -8,11 +8,18 @@
|
|
|
8
8
|
* boundary in page mode.
|
|
9
9
|
*
|
|
10
10
|
* The anchor is keyed on `data-block-id` rather than pixel offset so
|
|
11
|
-
* it survives arbitrary height changes across the toggle.
|
|
12
|
-
*
|
|
13
|
-
*
|
|
11
|
+
* it survives arbitrary height changes across the toggle.
|
|
12
|
+
*
|
|
13
|
+
* Refactor/05 Slice 3b (2026-04-22) rewires these helpers to read block
|
|
14
|
+
* rects through `GeometryFacet.getBlock(blockId)` in the steady-state
|
|
15
|
+
* (warm) path. The DOM-measurement path is preserved as the cold-open
|
|
16
|
+
* seam for the window before the render kernel has emitted its first
|
|
17
|
+
* frame — per architecture 05 Slice 3 exit criteria, a single narrow
|
|
18
|
+
* DOM fallback branch is permitted here.
|
|
14
19
|
*/
|
|
15
20
|
|
|
21
|
+
import type { GeometryFacet } from "../../api/public-types.ts";
|
|
22
|
+
|
|
16
23
|
export interface ScrollAnchor {
|
|
17
24
|
/** `data-block-id` of the topmost block straddling or below scrollTop. */
|
|
18
25
|
blockId: string;
|
|
@@ -24,24 +31,79 @@ export interface ScrollAnchor {
|
|
|
24
31
|
offsetWithinBlock: number;
|
|
25
32
|
}
|
|
26
33
|
|
|
34
|
+
export interface FindScrollAnchorOptions {
|
|
35
|
+
/**
|
|
36
|
+
* Geometry facet — when provided and its `getBlock(blockId)` resolves,
|
|
37
|
+
* the anchor is computed from the kernel's frame coordinates instead
|
|
38
|
+
* of the DOM. The DOM path runs only on cold-open (no kernel frame
|
|
39
|
+
* yet) or when explicitly requested via `prepaintFallback: true`.
|
|
40
|
+
*/
|
|
41
|
+
geometryFacet?: GeometryFacet;
|
|
42
|
+
/**
|
|
43
|
+
* Opt-in DOM fallback for callers that want to force the pre-paint
|
|
44
|
+
* path (e.g. a mode toggle that fires before the first render frame
|
|
45
|
+
* of the destination mode). When `false` (default) and a
|
|
46
|
+
* `geometryFacet` is provided, the helper tries the facet first and
|
|
47
|
+
* only falls through to DOM when no block resolves.
|
|
48
|
+
*/
|
|
49
|
+
prepaintFallback?: boolean;
|
|
50
|
+
}
|
|
51
|
+
|
|
27
52
|
/**
|
|
28
53
|
* Find the scroll anchor for `root` — the scroll container whose
|
|
29
|
-
* `scrollTop`
|
|
54
|
+
* `scrollTop` defines the viewport origin for the anchor.
|
|
55
|
+
*
|
|
56
|
+
* Resolution order:
|
|
57
|
+
* 1. `geometryFacet` provided + `prepaintFallback !== true`: walk
|
|
58
|
+
* block ids from the DOM in document order, query the facet's
|
|
59
|
+
* `getBlock` for each, pick the first whose rect's bottom is
|
|
60
|
+
* >= the scroll-root-relative viewport top (rects are frame-local
|
|
61
|
+
* pixels). The root's scroll offset supplies the viewport-top.
|
|
62
|
+
* 2. Otherwise: the legacy DOM path via `getBoundingClientRect` —
|
|
63
|
+
* this is the cold-open fallback architecture 05 Slice 3 exit
|
|
64
|
+
* criteria explicitly keep.
|
|
30
65
|
*
|
|
31
66
|
* Returns `null` when the root has no `[data-block-id]` descendants or
|
|
32
67
|
* when the root itself has zero height (e.g. disconnected during the
|
|
33
68
|
* toggle).
|
|
34
69
|
*/
|
|
35
|
-
export function findScrollAnchor(
|
|
70
|
+
export function findScrollAnchor(
|
|
71
|
+
root: HTMLElement | null,
|
|
72
|
+
options?: FindScrollAnchorOptions,
|
|
73
|
+
): ScrollAnchor | null {
|
|
36
74
|
if (!root) return null;
|
|
37
75
|
const blocks = root.querySelectorAll<HTMLElement>("[data-block-id]");
|
|
38
76
|
if (blocks.length === 0) return null;
|
|
77
|
+
|
|
78
|
+
// Slice 3b warm path — read block rects from the kernel frame.
|
|
79
|
+
// `viewportTopFramePx` is "what frame-local y-coordinate is currently
|
|
80
|
+
// visible at the top of the scroll-root viewport?" For the overlay's
|
|
81
|
+
// wiring (overlay root = frame root), that's simply `scrollTop`.
|
|
82
|
+
if (options?.geometryFacet && !options.prepaintFallback) {
|
|
83
|
+
const viewportTopFramePx = root.scrollTop;
|
|
84
|
+
for (const block of blocks) {
|
|
85
|
+
const blockId = block.getAttribute("data-block-id");
|
|
86
|
+
if (!blockId) continue;
|
|
87
|
+
const geometry = options.geometryFacet.getBlock(blockId);
|
|
88
|
+
if (!geometry || geometry.rects.length === 0) continue;
|
|
89
|
+
const rect = geometry.rects[0]!;
|
|
90
|
+
const blockTop = rect.topPx;
|
|
91
|
+
const blockBottom = rect.topPx + rect.heightPx;
|
|
92
|
+
if (blockBottom < viewportTopFramePx) continue;
|
|
93
|
+
return {
|
|
94
|
+
blockId,
|
|
95
|
+
offsetWithinBlock: viewportTopFramePx - blockTop,
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
// No block matched via the facet — fall through to the DOM path so
|
|
99
|
+
// cold-open (pre-first-frame) callers still produce an anchor.
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Cold-open / pre-paint fallback — the single permitted DOM-origin
|
|
103
|
+
// branch under `src/ui-tailwind/editor-surface/scroll-anchor.ts` per
|
|
104
|
+
// the Slice-3 plan.
|
|
39
105
|
const rootRect = root.getBoundingClientRect();
|
|
40
106
|
const rootTop = rootRect.top;
|
|
41
|
-
// Walk blocks in document order; pick the first one whose bottom is
|
|
42
|
-
// >= the scroll root's top edge. That's the topmost block at least
|
|
43
|
-
// partially visible (or the one just below when the viewport sits in
|
|
44
|
-
// a gap between blocks).
|
|
45
107
|
for (const block of blocks) {
|
|
46
108
|
const rect = block.getBoundingClientRect();
|
|
47
109
|
if (rect.bottom < rootTop) continue;
|
|
@@ -60,14 +122,34 @@ export function findScrollAnchor(root: HTMLElement | null): ScrollAnchor | null
|
|
|
60
122
|
* `root` and adjusting `scrollTop` so the block's leading edge sits at
|
|
61
123
|
* the same offset relative to the viewport.
|
|
62
124
|
*
|
|
125
|
+
* When a `geometryFacet` is supplied and resolves the block, the
|
|
126
|
+
* translation runs on kernel-frame coordinates (no DOM measurement).
|
|
127
|
+
* Otherwise the DOM path is used as the cold-open fallback.
|
|
128
|
+
*
|
|
63
129
|
* Graceful no-op when the anchor's block no longer exists (deletion
|
|
64
130
|
* mid-toggle, doc swap) or when the new root is empty.
|
|
65
131
|
*/
|
|
66
132
|
export function restoreScrollAnchor(
|
|
67
133
|
root: HTMLElement | null,
|
|
68
134
|
anchor: ScrollAnchor | null,
|
|
135
|
+
options?: FindScrollAnchorOptions,
|
|
69
136
|
): void {
|
|
70
137
|
if (!root || !anchor) return;
|
|
138
|
+
|
|
139
|
+
if (options?.geometryFacet && !options.prepaintFallback) {
|
|
140
|
+
const geometry = options.geometryFacet.getBlock(anchor.blockId);
|
|
141
|
+
if (geometry && geometry.rects.length > 0) {
|
|
142
|
+
const rect = geometry.rects[0]!;
|
|
143
|
+
// We want, post-restore, the frame-local y of the block's top to
|
|
144
|
+
// land at `scrollTop + offsetWithinBlock`-below-viewport-top.
|
|
145
|
+
// Equivalently, set scrollTop so that the block's top is
|
|
146
|
+
// `offsetWithinBlock` above it.
|
|
147
|
+
root.scrollTop = rect.topPx - anchor.offsetWithinBlock;
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
// No block match through facet; fall through to DOM path.
|
|
151
|
+
}
|
|
152
|
+
|
|
71
153
|
const selector = `[data-block-id="${cssEscape(anchor.blockId)}"]`;
|
|
72
154
|
const block = root.querySelector<HTMLElement>(selector);
|
|
73
155
|
if (!block) return;
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
* fill; `noLine: true` → `stroke: "none"`.
|
|
18
18
|
*/
|
|
19
19
|
|
|
20
|
-
import { EMU_PER_PX, ROTATION_UNITS_PER_DEGREE } from "../../
|
|
20
|
+
import { EMU_PER_PX, ROTATION_UNITS_PER_DEGREE } from "../../api/public-types";
|
|
21
21
|
|
|
22
22
|
const SUPPORTED_GEOMETRIES = new Set(["rect", "ellipse", "roundRect"]);
|
|
23
23
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* R.4 SurfaceLayer — named shell for the outermost input surface layer.
|
|
3
|
-
* See `
|
|
3
|
+
* See `CLAUDE.md (lane status table)` §R.4.
|
|
4
4
|
*
|
|
5
5
|
* Analogous to LibreOffice `SwWrtShell`. Owns: keyboard resolution, paste/drop
|
|
6
6
|
* routing decisions, composition state. Does NOT own: PM view construction,
|
|
@@ -18,7 +18,7 @@ export function TwOpaqueBlock(props: TwOpaqueBlockProps) {
|
|
|
18
18
|
const selected = selectionTouchesRange(selection, block.from, block.to);
|
|
19
19
|
|
|
20
20
|
return (
|
|
21
|
-
<div className="group relative">
|
|
21
|
+
<div className="group relative" data-block-kind="opaque">
|
|
22
22
|
<div className="absolute -left-10 top-1 flex flex-col items-end gap-0 select-none w-8 text-right">
|
|
23
23
|
<div className="flex items-center gap-0.5">
|
|
24
24
|
<span className="text-[10px] text-tertiary/60 font-medium">Lock</span>
|
|
@@ -4,7 +4,7 @@ import type {
|
|
|
4
4
|
SurfaceBlockSnapshot,
|
|
5
5
|
SurfaceTextMark,
|
|
6
6
|
} from "../../api/public-types.ts";
|
|
7
|
-
import type { CanonicalRunFormatting } from "../../
|
|
7
|
+
import type { CanonicalRunFormatting } from "../../api/public-types.ts";
|
|
8
8
|
|
|
9
9
|
// ---------------------------------------------------------------------------
|
|
10
10
|
// Pure helpers shared by `tw-page-block-view` (body) and `tw-region-block-
|
|
@@ -122,15 +122,32 @@ export function buildParagraphStyle(
|
|
|
122
122
|
style.minHeight = `${lineSpacing / 20}pt`;
|
|
123
123
|
}
|
|
124
124
|
|
|
125
|
-
// Indentation
|
|
125
|
+
// Indentation — ECMA-376 §17.9.6: numbering-level pPr/ind overrides
|
|
126
|
+
// direct paragraph ind, which overrides style-chain ind. Mirror the PM
|
|
127
|
+
// path resolver at pm-state-from-snapshot.ts:453-456 so this static
|
|
128
|
+
// render path (pages 2+, non-PM) composes the same marker-lane +
|
|
129
|
+
// hanging-indent geometry as PM (page 1). Without the resolvedNumbering
|
|
130
|
+
// fallback, CCEP numbered paragraphs whose indent lives only on the
|
|
131
|
+
// numbering level (e.g. "X.1" lane openers) get paddingLeft=undefined
|
|
132
|
+
// while the marker span still applies marginLeft: -markerWidth —
|
|
133
|
+
// marker slides off the body frame.
|
|
134
|
+
const numberingInd = block.resolvedNumbering?.geometry.indentation;
|
|
126
135
|
const indentLeft =
|
|
127
|
-
|
|
136
|
+
numberingInd?.left ??
|
|
137
|
+
block.indentation?.left ??
|
|
138
|
+
block.resolvedParagraphFormatting?.indentation?.left;
|
|
128
139
|
const indentRight =
|
|
129
|
-
|
|
140
|
+
numberingInd?.right ??
|
|
141
|
+
block.indentation?.right ??
|
|
142
|
+
block.resolvedParagraphFormatting?.indentation?.right;
|
|
130
143
|
const indentFirstLine =
|
|
131
|
-
|
|
144
|
+
numberingInd?.firstLine ??
|
|
145
|
+
block.indentation?.firstLine ??
|
|
146
|
+
block.resolvedParagraphFormatting?.indentation?.firstLine;
|
|
132
147
|
const indentHanging =
|
|
133
|
-
|
|
148
|
+
numberingInd?.hanging ??
|
|
149
|
+
block.indentation?.hanging ??
|
|
150
|
+
block.resolvedParagraphFormatting?.indentation?.hanging;
|
|
134
151
|
|
|
135
152
|
if (indentLeft) style.paddingLeft = `${indentLeft / 20}pt`;
|
|
136
153
|
if (indentRight) style.paddingRight = `${indentRight / 20}pt`;
|
|
@@ -11,6 +11,7 @@ import { EditorView } from "prosemirror-view";
|
|
|
11
11
|
|
|
12
12
|
import type {
|
|
13
13
|
DocumentNavigationSnapshot,
|
|
14
|
+
EditorStoryTarget,
|
|
14
15
|
EditorUser,
|
|
15
16
|
RuntimeRenderSnapshot,
|
|
16
17
|
SearchOptions,
|
|
@@ -22,17 +23,23 @@ import type {
|
|
|
22
23
|
WorkflowMetadataMarkup,
|
|
23
24
|
WorkflowScope,
|
|
24
25
|
} from "../../api/public-types";
|
|
25
|
-
import type { CanonicalDocumentEnvelope } from "../../
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
26
|
+
import type { CanonicalDocumentEnvelope } from "../../api/public-types.ts";
|
|
27
|
+
// §4.8 · refactor/11 — search + table descriptor access moved to the
|
|
28
|
+
// Runtime API v3 seam (`runtime.search.searchDocument` +
|
|
29
|
+
// `runtime.table.getSelectionDescriptor`, both shipped in react-refactor
|
|
30
|
+
// `eb98ae06`). The PM surface receives them as host-supplied callbacks
|
|
31
|
+
// instead of importing from `src/runtime/**` directly. `TableSelectionDescriptor`
|
|
32
|
+
// is re-exported from the v3 table family so consumers don't peek into
|
|
33
|
+
// `src/runtime/table-commands.ts` for the type either.
|
|
34
|
+
import { type TableSelectionDescriptor } from "../../api/v3/runtime/table.ts";
|
|
31
35
|
import {
|
|
32
36
|
createCommentDecorationModel,
|
|
33
37
|
type MarkupDisplay,
|
|
34
38
|
} from "../../ui/headless/comment-decoration-model";
|
|
35
|
-
import {
|
|
39
|
+
import {
|
|
40
|
+
createRevisionDecorationModel,
|
|
41
|
+
type RevisionDisplayFlags,
|
|
42
|
+
} from "../../ui/headless/revision-decoration-model";
|
|
36
43
|
import {
|
|
37
44
|
createPMSelectionFromSnapshot,
|
|
38
45
|
createPMStateFromSnapshot,
|
|
@@ -45,7 +52,7 @@ import {
|
|
|
45
52
|
import { buildDecorations } from "./pm-decorations";
|
|
46
53
|
import { buildPageBreakDecorations } from "./pm-page-break-decorations";
|
|
47
54
|
import { DecorationSet } from "prosemirror-view";
|
|
48
|
-
import type { WordReviewEditorLayoutFacet } from "../../
|
|
55
|
+
import type { WordReviewEditorLayoutFacet } from "../../api/public-types.ts";
|
|
49
56
|
import { buildPagePreviewMaps } from "../../runtime/layout/resolve-page-previews";
|
|
50
57
|
import { createContextualInteractionPlugin } from "./pm-contextual-ui";
|
|
51
58
|
import {
|
|
@@ -58,7 +65,7 @@ import { buildPositionMap, type PositionMap } from "./pm-position-map";
|
|
|
58
65
|
import { createLocalEditSessionState } from "./local-edit-session-state";
|
|
59
66
|
import { createFastTextEditLane } from "./fast-text-edit-lane";
|
|
60
67
|
import { createPredictedTxGate } from "./predicted-tx-gate";
|
|
61
|
-
import { createScopeTagRegistry } from "../../runtime/scope-tag-registry";
|
|
68
|
+
import { createScopeTagRegistry } from "../../runtime/workflow/scope-tag-registry";
|
|
62
69
|
import { hasBailIfCrossedTagInRange } from "./predicted-tag-preflight";
|
|
63
70
|
import {
|
|
64
71
|
clearSearch as clearSearchPlugin,
|
|
@@ -89,11 +96,13 @@ import type { MediaPreviewDescriptor } from "./pm-state-from-snapshot";
|
|
|
89
96
|
* between adjacent blocks.
|
|
90
97
|
*/
|
|
91
98
|
function buildPageBreakDecorationsFromProps(
|
|
92
|
-
|
|
99
|
+
geometryFacet:
|
|
100
|
+
| import("../../runtime/geometry/index.ts").GeometryFacet
|
|
101
|
+
| undefined,
|
|
93
102
|
isMainStory: boolean,
|
|
94
103
|
positionMap: PositionMap,
|
|
95
104
|
posture: "canvas" | "page",
|
|
96
|
-
canonicalDocument:
|
|
105
|
+
canonicalDocument: CanonicalDocumentEnvelope,
|
|
97
106
|
dimensions: {
|
|
98
107
|
headerBandPx?: number;
|
|
99
108
|
footerBandPx?: number;
|
|
@@ -101,9 +110,8 @@ function buildPageBreakDecorationsFromProps(
|
|
|
101
110
|
} = {},
|
|
102
111
|
surfaceBlocks?: readonly import("../../api/public-types.ts").SurfaceBlockSnapshot[],
|
|
103
112
|
): ReturnType<typeof buildPageBreakDecorations> {
|
|
104
|
-
if (!
|
|
105
|
-
|
|
106
|
-
const frame = facet.getRenderFrame();
|
|
113
|
+
if (!geometryFacet || !isMainStory) return [];
|
|
114
|
+
const frame = geometryFacet.getRenderFrame();
|
|
107
115
|
if (!frame || frame.pages.length < 2) return [];
|
|
108
116
|
const fakeGraph = {
|
|
109
117
|
revision: frame.revision,
|
|
@@ -226,6 +234,37 @@ export interface TwProseMirrorSurfaceProps {
|
|
|
226
234
|
onUndo?: () => void;
|
|
227
235
|
onRedo?: () => void;
|
|
228
236
|
onBlockedInput?: (command: "paste" | "drop", message: string) => void;
|
|
237
|
+
/**
|
|
238
|
+
* refactor/11 Slice 5 — host-supplied adapter for rich clipboard
|
|
239
|
+
* parsing (WordML + HTML). Forwarded to `createCommandBridgePlugins`
|
|
240
|
+
* so the PM bridge no longer reaches into `src/io/paste/**`. When
|
|
241
|
+
* omitted, rich paste falls through to plain-text (identical to
|
|
242
|
+
* pre-Slice-5 behavior when `onPasteFragment` was not wired).
|
|
243
|
+
*/
|
|
244
|
+
pasteFragmentParser?: import("./pm-command-bridge.ts").PasteFragmentParserAdapter;
|
|
245
|
+
/**
|
|
246
|
+
* §4.8 — host-supplied compound-search callback. Threaded from
|
|
247
|
+
* `api.runtime.search.searchDocument` at the WordReviewEditor mount;
|
|
248
|
+
* tests / headless callers that exercise search supply their own
|
|
249
|
+
* closure. Replaces the pre-slice direct import from
|
|
250
|
+
* `src/runtime/document-search.ts`.
|
|
251
|
+
*/
|
|
252
|
+
runtimeSearchDocument?: (
|
|
253
|
+
document: CanonicalDocumentEnvelope,
|
|
254
|
+
selection: SelectionSnapshot,
|
|
255
|
+
activeStory: EditorStoryTarget,
|
|
256
|
+
navigation: DocumentNavigationSnapshot,
|
|
257
|
+
query: string,
|
|
258
|
+
options?: SearchOptions,
|
|
259
|
+
) => SearchResultSnapshot[];
|
|
260
|
+
/**
|
|
261
|
+
* §4.8 — host-supplied table-selection descriptor reader. Threaded
|
|
262
|
+
* from `api.runtime.table.getSelectionDescriptor`; callers without a
|
|
263
|
+
* live runtime (test harnesses) pass the helper directly.
|
|
264
|
+
*/
|
|
265
|
+
runtimeGetTableSelectionDescriptor?: (
|
|
266
|
+
state: import("prosemirror-state").EditorState,
|
|
267
|
+
) => TableSelectionDescriptor | null;
|
|
229
268
|
onPasteApplied?: (meta: {
|
|
230
269
|
segmentCount: number;
|
|
231
270
|
charCount: number;
|
|
@@ -252,13 +291,21 @@ export interface TwProseMirrorSurfaceProps {
|
|
|
252
291
|
command: import("./fast-text-edit-lane").LaneRuntimeCommand,
|
|
253
292
|
) => import("../../api/public-types").TextCommandAck;
|
|
254
293
|
/**
|
|
255
|
-
* Optional layout facet.
|
|
256
|
-
*
|
|
257
|
-
*
|
|
258
|
-
*
|
|
259
|
-
* with PM content without any absolute overlay.
|
|
294
|
+
* Optional layout facet. Retained as a legacy pass-through; no longer
|
|
295
|
+
* read by this surface after the refactor/05 cross-lane-coord §8.4
|
|
296
|
+
* migration. Parents should pass `geometryFacet` instead for the
|
|
297
|
+
* page-break decoration build path.
|
|
260
298
|
*/
|
|
261
299
|
layoutFacet?: WordReviewEditorLayoutFacet;
|
|
300
|
+
/**
|
|
301
|
+
* Geometry facet (`runtime.geometry`). When supplied and the active
|
|
302
|
+
* story is `main`, the surface injects widget decorations at every
|
|
303
|
+
* page boundary. Migrated from `layoutFacet` in the Slice-6 UI
|
|
304
|
+
* migration pass — geometry is the canonical source of
|
|
305
|
+
* render-frame access; layout-facet's `getRenderFrame` is being
|
|
306
|
+
* deleted.
|
|
307
|
+
*/
|
|
308
|
+
geometryFacet?: import("../../runtime/geometry/index.ts").GeometryFacet;
|
|
262
309
|
/** Height in px of each page's header band. Default 32. */
|
|
263
310
|
pageChromeHeaderBandPx?: number;
|
|
264
311
|
/** Height in px of each page's footer band. Default 32. */
|
|
@@ -276,6 +323,28 @@ export interface TwProseMirrorSurfaceProps {
|
|
|
276
323
|
*/
|
|
277
324
|
onOpenHeaderStoryForPage?: (pageIndex: number) => void;
|
|
278
325
|
onOpenFooterStoryForPage?: (pageIndex: number) => void;
|
|
326
|
+
/**
|
|
327
|
+
* Phase D.1 — right-click composition hook.
|
|
328
|
+
*
|
|
329
|
+
* When wired, the surface forwards `contextmenu` DOM events to this
|
|
330
|
+
* callback with the event coordinates + target; the PM command
|
|
331
|
+
* bridge suppresses the browser-native menu so the host can mount
|
|
332
|
+
* `TwContextMenu` at the returned coordinates.
|
|
333
|
+
*
|
|
334
|
+
* Hosts typically wire this to
|
|
335
|
+
* `chromeControllerRef.current?.handleContextMenuRequest(event)` —
|
|
336
|
+
* the workspace's `TwWorkspaceChromeHost` (Phase C.γ.3) owns the
|
|
337
|
+
* menu state + portal mount.
|
|
338
|
+
*
|
|
339
|
+
* When NOT wired, the bridge leaves the native menu alone so
|
|
340
|
+
* integrators that haven't opted in retain browser-default
|
|
341
|
+
* behavior (back-compat).
|
|
342
|
+
*/
|
|
343
|
+
onContextMenuRequested?: (event: {
|
|
344
|
+
clientX: number;
|
|
345
|
+
clientY: number;
|
|
346
|
+
target: EventTarget | null;
|
|
347
|
+
}) => void;
|
|
279
348
|
}
|
|
280
349
|
|
|
281
350
|
export interface TwProseMirrorSurfaceRef {
|
|
@@ -296,6 +365,32 @@ export const TwProseMirrorSurface = forwardRef<
|
|
|
296
365
|
onBlur,
|
|
297
366
|
} = props;
|
|
298
367
|
const surface = snapshot.surface;
|
|
368
|
+
|
|
369
|
+
// §4.3 — Track B integration. Pre-compute offset → revisionDisplay flags
|
|
370
|
+
// from the live surface-segment stream once per surface update; the
|
|
371
|
+
// decoration builder reads from L03's authoritative flags when an entry
|
|
372
|
+
// is present, otherwise falls through to the review-store side channel.
|
|
373
|
+
// Keyed by `segment.from` — L03 segments the plain text at revision
|
|
374
|
+
// boundaries, so `rev.from` aligns with a segment start whenever the
|
|
375
|
+
// segment carries `revisionDisplay`.
|
|
376
|
+
const revisionDisplayByOffset = useMemo<
|
|
377
|
+
ReadonlyMap<number, RevisionDisplayFlags> | undefined
|
|
378
|
+
>(() => {
|
|
379
|
+
if (!surface) return undefined;
|
|
380
|
+
let map: Map<number, RevisionDisplayFlags> | undefined;
|
|
381
|
+
for (const block of surface.blocks) {
|
|
382
|
+
if (block.kind !== "paragraph") continue;
|
|
383
|
+
for (const segment of block.segments) {
|
|
384
|
+
if (segment.kind !== "text") continue;
|
|
385
|
+
const flags = segment.revisionDisplay;
|
|
386
|
+
if (!flags) continue;
|
|
387
|
+
if (!map) map = new Map();
|
|
388
|
+
map.set(segment.from, flags);
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
return map;
|
|
392
|
+
}, [surface]);
|
|
393
|
+
|
|
299
394
|
const mediaPreviewKey = useMemo(
|
|
300
395
|
() =>
|
|
301
396
|
Object.entries(props.mediaPreviews ?? {})
|
|
@@ -377,6 +472,12 @@ export const TwProseMirrorSurface = forwardRef<
|
|
|
377
472
|
},
|
|
378
473
|
getPositionMap: () => positionMapRef.current,
|
|
379
474
|
isSelectionSyncSuppressed: () => suppressSelectionEchoRef.current,
|
|
475
|
+
// Phase D.1 — forward contextmenu events to the host-supplied
|
|
476
|
+
// chrome controller. Delegates through a ref-indirect so handler
|
|
477
|
+
// identity stays stable for the lifetime of the PM plugin.
|
|
478
|
+
onContextMenuRequested: (event) => {
|
|
479
|
+
props.onContextMenuRequested?.(event);
|
|
480
|
+
},
|
|
380
481
|
};
|
|
381
482
|
|
|
382
483
|
// Comment/revision decoration models
|
|
@@ -505,6 +606,10 @@ export const TwProseMirrorSurface = forwardRef<
|
|
|
505
606
|
onCompositionChange: (composing) => {
|
|
506
607
|
sessionRef.current?.setComposing(composing);
|
|
507
608
|
},
|
|
609
|
+
}, {
|
|
610
|
+
...(props.pasteFragmentParser
|
|
611
|
+
? { pasteFragmentParser: props.pasteFragmentParser }
|
|
612
|
+
: {}),
|
|
508
613
|
});
|
|
509
614
|
|
|
510
615
|
return [
|
|
@@ -545,9 +650,10 @@ export const TwProseMirrorSurface = forwardRef<
|
|
|
545
650
|
props.activeWorkflowWorkItemId,
|
|
546
651
|
props.activeWorkflowScopeIds,
|
|
547
652
|
props.workflowMetadata,
|
|
653
|
+
revisionDisplayByOffset,
|
|
548
654
|
);
|
|
549
655
|
const pageBreakDecos = buildPageBreakDecorationsFromProps(
|
|
550
|
-
props.
|
|
656
|
+
props.geometryFacet,
|
|
551
657
|
snapshot.activeStory.kind === "main",
|
|
552
658
|
positionMap,
|
|
553
659
|
props.isPageWorkspace ? "page" : "canvas",
|
|
@@ -585,6 +691,7 @@ export const TwProseMirrorSurface = forwardRef<
|
|
|
585
691
|
props.workflowMetadata,
|
|
586
692
|
props.workflowCandidates,
|
|
587
693
|
props.workflowScopes,
|
|
694
|
+
revisionDisplayByOffset,
|
|
588
695
|
revisionModel,
|
|
589
696
|
showTrackedChanges,
|
|
590
697
|
suggestionsEnabled,
|
|
@@ -744,6 +851,7 @@ export const TwProseMirrorSurface = forwardRef<
|
|
|
744
851
|
props.activeWorkflowWorkItemId,
|
|
745
852
|
props.activeWorkflowScopeIds,
|
|
746
853
|
props.workflowMetadata,
|
|
854
|
+
revisionDisplayByOffset,
|
|
747
855
|
);
|
|
748
856
|
recordPerfSample("pm.rebuild");
|
|
749
857
|
incrementInvalidationCounter("pm.laneA.rebuilds");
|
|
@@ -897,7 +1005,8 @@ export const TwProseMirrorSurface = forwardRef<
|
|
|
897
1005
|
if (!view) {
|
|
898
1006
|
return null;
|
|
899
1007
|
}
|
|
900
|
-
|
|
1008
|
+
if (!props.runtimeGetTableSelectionDescriptor) return null;
|
|
1009
|
+
return props.runtimeGetTableSelectionDescriptor(view.state);
|
|
901
1010
|
},
|
|
902
1011
|
}),
|
|
903
1012
|
[
|
|
@@ -956,8 +1065,9 @@ export const TwProseMirrorSurface = forwardRef<
|
|
|
956
1065
|
);
|
|
957
1066
|
}
|
|
958
1067
|
|
|
1068
|
+
if (!props.runtimeSearchDocument) return [];
|
|
959
1069
|
return filterHiddenDeletionSearchResults(
|
|
960
|
-
|
|
1070
|
+
props.runtimeSearchDocument(
|
|
961
1071
|
props.canonicalDocument,
|
|
962
1072
|
snapshot.selection,
|
|
963
1073
|
snapshot.activeStory,
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
|
|
11
11
|
import type { Node as PMNode } from "prosemirror-model";
|
|
12
12
|
import type { NodeViewConstructor, ViewMutationRecord } from "prosemirror-view";
|
|
13
|
-
import { PERCENTAGE_PARTS } from "../../
|
|
13
|
+
import { PERCENTAGE_PARTS } from "../../api/public-types.ts";
|
|
14
14
|
|
|
15
15
|
// R2c: band class styles live in ./tw-table-bands.module.css. Consumers import
|
|
16
16
|
// that stylesheet through their build pipeline (same pattern as editor-theme.css).
|
package/src/ui-tailwind/index.ts
CHANGED
|
@@ -51,11 +51,6 @@ export { TwStatusBar } from "./status/tw-status-bar";
|
|
|
51
51
|
// Chrome
|
|
52
52
|
export { TwAlertBanner } from "./chrome/tw-alert-banner";
|
|
53
53
|
export { TwSelectionToolbar } from "./chrome/tw-selection-toolbar";
|
|
54
|
-
export {
|
|
55
|
-
TwModeDock,
|
|
56
|
-
type TwModeDockAction,
|
|
57
|
-
type TwModeDockProps,
|
|
58
|
-
} from "./chrome/tw-mode-dock";
|
|
59
54
|
export {
|
|
60
55
|
TwPasteDropToast,
|
|
61
56
|
type TwPasteDropToastProps,
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OverlayAnchorBridgeContext — React context for publishing the shell's
|
|
3
|
+
* overlay-anchor bridge to deep presentation hooks without prop
|
|
4
|
+
* drilling.
|
|
5
|
+
*
|
|
6
|
+
* Pairs with `src/shell/overlay-anchor-bridge.ts` (bridge type) and
|
|
7
|
+
* `src/ui/ui-controller-factory.ts` (factory that reads the bridge).
|
|
8
|
+
* See DS-C1 in the close list / designsystem.md §8.8.1 "Selection
|
|
9
|
+
* toolbar" row.
|
|
10
|
+
*
|
|
11
|
+
* Only hooks that *write* to the bridge — publishing a current
|
|
12
|
+
* selection-anchor resolver — need this context. Readers go through
|
|
13
|
+
* `useUiApi().overlays.getAnchor(...)`; the bridge is a shell-private
|
|
14
|
+
* implementation detail of how that read resolves for
|
|
15
|
+
* `kind: "selection"`.
|
|
16
|
+
*
|
|
17
|
+
* Returns `null` when no bridge provider is mounted (headless path or
|
|
18
|
+
* pre-provider render) — writers skip publication silently, and
|
|
19
|
+
* `ui.overlays.getAnchor({ kind: "selection" })` honors U4 by returning
|
|
20
|
+
* `null` at the API layer.
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
import { createContext, useContext } from "react";
|
|
24
|
+
|
|
25
|
+
import type { ShellOverlayAnchorBridge } from "../shell/overlay-anchor-bridge.ts";
|
|
26
|
+
|
|
27
|
+
const OverlayAnchorBridgeContext = createContext<ShellOverlayAnchorBridge | null>(null);
|
|
28
|
+
|
|
29
|
+
export const OverlayAnchorBridgeProvider = OverlayAnchorBridgeContext.Provider;
|
|
30
|
+
|
|
31
|
+
export function useOverlayAnchorBridge(): ShellOverlayAnchorBridge | null {
|
|
32
|
+
return useContext(OverlayAnchorBridgeContext);
|
|
33
|
+
}
|