@beyondwork/docx-react-component 1.0.67 → 1.0.70
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 -932
- 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 -4797
- 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
package/README.md
CHANGED
|
@@ -11,993 +11,136 @@ canonical: true
|
|
|
11
11
|
|
|
12
12
|
[](https://github.com/bwllaming/React-OOXML-Office/actions/workflows/ci.yml)
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
Embeddable backoffice components for the [Beyond Work](https://beyondwork.ai) runtime. This repository ships **`@beyondwork/docx-react-component`** — a fidelity-first React `.docx` editor for legal review, contract negotiation, and any workflow where documents round-trip through Microsoft Word without damage.
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
**Design principle — human-AI parity.** Every capability in the UI has an equivalent, structured API. The agent and the user operate on the same runtime, the same commands, the same read models. There is no "agent-only" shortcut and no "human-only" feature.
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
- confirming what is shipped today
|
|
21
|
-
- installing the package
|
|
22
|
-
- finding the right documentation lane quickly
|
|
23
|
-
|
|
24
|
-
Do not use this README as the full package contract. The canonical consumer path starts in `docs/README.md`, [`docs/reference/public-api.md`](docs/reference/public-api.md), and [`docs/reference/integration-guide.md`](docs/reference/integration-guide.md).
|
|
25
|
-
|
|
26
|
-
## Components
|
|
27
|
-
|
|
28
|
-
### Document Editor (`@beyondwork/docx-react-component`)
|
|
29
|
-
|
|
30
|
-
A fidelity-first React `.docx` editor centered on `WordReviewEditor`. Built for legal review, contract negotiation, and any workflow where documents need to survive a round-trip through Microsoft Word without damage.
|
|
31
|
-
|
|
32
|
-
**Capabilities:**
|
|
33
|
-
- Full tracked-change and comment support (add, resolve, accept, reject)
|
|
34
|
-
- Suggesting mode where every edit automatically becomes a tracked change
|
|
35
|
-
- Round-trip OOXML preservation — open, edit, export, reopen in Word without repair prompts
|
|
36
|
-
- Workflow overlays with scope-based editing constraints
|
|
37
|
-
- Runtime-backed read models for document structure, review state, selection, compatibility, and fields
|
|
38
|
-
- Document comparison with LCS-based diffing and redline export
|
|
39
|
-
- Legal document analysis (bookmarks, cross-references, defined terms, signature blocks)
|
|
40
|
-
- Real-time collaboration via Yjs
|
|
41
|
-
|
|
42
|
-
**Human-AI parity in practice:**
|
|
43
|
-
- The human clicks "Add Comment" on selected text; the agent calls `addComment({ anchor, body })` on the same selection
|
|
44
|
-
- The human reviews tracked changes in the sidebar; the agent reads `getTrackedChanges()` and makes the same accept/reject decisions
|
|
45
|
-
- The human exports via toolbar; the agent calls `exportDocx()` after the same `getCompatibilityReport()` check
|
|
46
|
-
- Workflow overlays constrain both humans and agents identically — `getInteractionGuardSnapshot()` is the single source of posture truth
|
|
47
|
-
- The AI action policy module gates 37 discrete agent operations with risk classification and context validation
|
|
48
|
-
|
|
49
|
-
### Workblocks
|
|
50
|
-
|
|
51
|
-
Composable task modules that automate business processes. Each workblock is a self-contained package of Python backend logic, React UI components, and a declarative task graph defined in `manifest.yaml`. They execute on the Beyond Work platform via Temporal workflows.
|
|
52
|
-
|
|
53
|
-
**Categories:**
|
|
54
|
-
- **Document processing** — invoice extraction, PDF template OCR, bulk processing, email-to-action
|
|
55
|
-
- **AI agents** — explore, flow debugging, data querying, task launching, authoring
|
|
56
|
-
- **Analytics** — execution history, company insights, timeline queries
|
|
57
|
-
- **Learning** — human correction capture, learning set curation, embedding management
|
|
58
|
-
- **Infrastructure** — registry, health checks, credential management (9 types)
|
|
59
|
-
|
|
60
|
-
**Human-AI parity in practice:**
|
|
61
|
-
- Users create workblocks through VS Code Studio with prompts and visual editing; authoring agents create them through the same manifest schema and file tools
|
|
62
|
-
- Users validate invoice fields in a React form; agents validate the same fields through typed task inputs/outputs
|
|
63
|
-
- Both humans and agents operate within the same workblock execution engine — same task graph, same data flow, same error handling
|
|
64
|
-
|
|
65
|
-
## The Beyond Work Runtime
|
|
66
|
-
|
|
67
|
-
These components plug into a four-layer platform:
|
|
68
|
-
|
|
69
|
-
```
|
|
70
|
-
User-Facing (Layer 4)
|
|
71
|
-
neui (Next.js 15), bport (BFF), MCP server, VS Code extension
|
|
72
|
-
|
|
|
73
|
-
Workblocks (Layer 3)
|
|
74
|
-
20+ composable task modules: agents, data processing, credentials
|
|
75
|
-
|
|
|
76
|
-
Platform Services (Layer 2)
|
|
77
|
-
bworker (Go), modelproxy (LiteLLM), registry, pythonworker, Temporal
|
|
78
|
-
|
|
|
79
|
-
AWS Infrastructure (Layer 1)
|
|
80
|
-
EKS, Crossplane, Terraform, PostgreSQL, Redis, Qdrant, S3, SQS
|
|
81
|
-
```
|
|
82
|
-
|
|
83
|
-
The document editor lives at Layer 4 as an embeddable surface. Workblocks live at Layer 3 and are orchestrated by the platform. Both expose their capabilities symmetrically to human UIs and agent APIs.
|
|
84
|
-
|
|
85
|
-
## Current Package Reality
|
|
86
|
-
|
|
87
|
-
The shipped contract today is docx-first:
|
|
88
|
-
|
|
89
|
-
- `docx` is the only implemented and shipped runtime contract
|
|
90
|
-
- `xlsx` is planned work, not part of the current package contract
|
|
91
|
-
- `pdf` remains future work outside the current package boundary
|
|
18
|
+
---
|
|
92
19
|
|
|
93
20
|
## Install
|
|
94
21
|
|
|
95
22
|
```bash
|
|
96
|
-
pnpm add @beyondwork/docx-react-component
|
|
97
|
-
prosemirror-commands prosemirror-keymap prosemirror-model \
|
|
98
|
-
prosemirror-state prosemirror-tables prosemirror-transform prosemirror-view
|
|
99
|
-
```
|
|
100
|
-
|
|
101
|
-
Current packaging truth:
|
|
102
|
-
|
|
103
|
-
- the package is ESM-only
|
|
104
|
-
- exports point at shipped TypeScript source entry points
|
|
105
|
-
- `types` and subpath `types` entries resolve to the shipped source-backed TypeScript contracts
|
|
106
|
-
- consumers need a bundler or runtime that can resolve `.ts` and `.tsx` ESM imports
|
|
107
|
-
- consumers should import `@beyondwork/docx-react-component/ui-tailwind/theme/editor-theme.css` once and provide a Tailwind v4 CSS pipeline for it
|
|
108
|
-
- package and source identifiers remain docx-first until a deliberate rename lands
|
|
109
|
-
|
|
110
|
-
## Shipped Product
|
|
111
|
-
|
|
112
|
-
The primary shipped surface is:
|
|
113
|
-
|
|
114
|
-
```tsx
|
|
115
|
-
import { WordReviewEditor } from "@beyondwork/docx-react-component";
|
|
116
|
-
|
|
117
|
-
<WordReviewEditor />
|
|
118
|
-
```
|
|
119
|
-
|
|
120
|
-
`WordReviewEditor` remains uncontrolled by default:
|
|
121
|
-
|
|
122
|
-
- host passes `initialDocx`, `initialSessionState`, or `initialSnapshot`, or provides `hostAdapter.load()` / `datastore.load()`
|
|
123
|
-
- runtime owns the live working session
|
|
124
|
-
- host receives events, warnings, errors, session state, compatibility snapshots, and exported artifacts
|
|
125
|
-
|
|
126
|
-
Persistence direction:
|
|
127
|
-
|
|
128
|
-
- `EditorSessionState` is the canonical host-facing live-session contract
|
|
129
|
-
- `EditorHostAdapter` is the preferred persistence boundary for `load`, `saveSession`, `saveExport`, and telemetry
|
|
130
|
-
- `EditorDatastoreAdapter` remains the legacy snapshot bridge for hosts that still persist `PersistedEditorSnapshot`
|
|
131
|
-
|
|
132
|
-
Snapshot/export note:
|
|
133
|
-
|
|
134
|
-
- when a session starts from a real `.docx`, persisted snapshots now carry embedded source-package provenance so later snapshot-origin `.docx` export can use the same package-backed exporter
|
|
135
|
-
- legacy snapshots without that provenance still load, but `.docx` export is intentionally blocked rather than falling back to a lossy minimal package
|
|
136
|
-
|
|
137
|
-
The current shipped ESM exports include:
|
|
138
|
-
|
|
139
|
-
- stable default entrypoints:
|
|
140
|
-
- `@beyondwork/docx-react-component`
|
|
141
|
-
- `@beyondwork/docx-react-component/public-types`
|
|
142
|
-
- `@beyondwork/docx-react-component/ui-tailwind`
|
|
143
|
-
- `@beyondwork/docx-react-component/legal`
|
|
144
|
-
- `@beyondwork/docx-react-component/compare`
|
|
145
|
-
- `@beyondwork/docx-react-component/ui-tailwind/theme/editor-theme.css`
|
|
146
|
-
- advanced-supported subpaths for wrapper teams and package-adjacent integrations:
|
|
147
|
-
- `@beyondwork/docx-react-component/runtime/document-runtime`
|
|
148
|
-
- `@beyondwork/docx-react-component/io/docx-session`
|
|
149
|
-
- `@beyondwork/docx-react-component/core/commands/*`
|
|
150
|
-
- `@beyondwork/docx-react-component/core/selection/mapping`
|
|
151
|
-
- `@beyondwork/docx-react-component/core/state/editor-state`
|
|
152
|
-
- `@beyondwork/docx-react-component/ui-tailwind/editor-surface/search-plugin`
|
|
153
|
-
- alias subpaths:
|
|
154
|
-
- `@beyondwork/docx-react-component/tailwind`
|
|
155
|
-
- `@beyondwork/docx-react-component/api/public-types`
|
|
156
|
-
|
|
157
|
-
Use [`docs/reference/public-api.md`](docs/reference/public-api.md) and `docs/reference/public-api.manifest.json` for the current contract inventory and stability guidance.
|
|
158
|
-
|
|
159
|
-
## Product Contract
|
|
160
|
-
|
|
161
|
-
For every component this repo ships, the standard is:
|
|
162
|
-
|
|
163
|
-
> Open -> edit -> save -> reopen in the host application without damage.
|
|
164
|
-
|
|
165
|
-
For the current shipped `docx` implementation, that specifically means:
|
|
166
|
-
|
|
167
|
-
- open in recent Microsoft Word without repair prompts
|
|
168
|
-
- preserve supported content and review structures
|
|
169
|
-
- preserve unsupported but preservable OOXML
|
|
170
|
-
- remain editable in Word after export
|
|
171
|
-
|
|
172
|
-
For the normative API and host contract, use:
|
|
173
|
-
|
|
174
|
-
- [`docs/reference/public-api.md`](docs/reference/public-api.md)
|
|
175
|
-
- [`docs/reference/integration-guide.md`](docs/reference/integration-guide.md)
|
|
176
|
-
- [`docs/reference/ooxml-compliance.md`](docs/reference/ooxml-compliance.md)
|
|
177
|
-
|
|
178
|
-
## Documentation Map
|
|
179
|
-
|
|
180
|
-
### Start Here
|
|
181
|
-
|
|
182
|
-
- [`docs/README.md`](docs/README.md)
|
|
183
|
-
|
|
184
|
-
### Main Consumer Path
|
|
185
|
-
|
|
186
|
-
- [`docs/reference/quick-start.md`](docs/reference/quick-start.md)
|
|
187
|
-
- [`docs/reference/consumer-matrix.md`](docs/reference/consumer-matrix.md)
|
|
188
|
-
- [`docs/reference/public-api.md`](docs/reference/public-api.md)
|
|
189
|
-
- [`docs/reference/integration-guide.md`](docs/reference/integration-guide.md)
|
|
190
|
-
- [`docs/reference/glossary.md`](docs/reference/glossary.md)
|
|
191
|
-
|
|
192
|
-
### Wrapper And Agent Path
|
|
193
|
-
|
|
194
|
-
- [`docs/reference/consumer-matrix.md`](docs/reference/consumer-matrix.md)
|
|
195
|
-
- [`docs/reference/agent-integration-guide.md`](docs/reference/agent-integration-guide.md)
|
|
196
|
-
- [`docs/reference/public-api.md`](docs/reference/public-api.md)
|
|
197
|
-
- [`docs/reference/service-wrapper-guidance.md`](docs/reference/service-wrapper-guidance.md)
|
|
198
|
-
- [`docs/reference/agent-capability-map.md`](docs/reference/agent-capability-map.md)
|
|
199
|
-
- [`docs/reference/agent-read-models-and-snapshots.md`](docs/reference/agent-read-models-and-snapshots.md)
|
|
200
|
-
- [`docs/reference/agent-workflow-and-suggestions.md`](docs/reference/agent-workflow-and-suggestions.md)
|
|
201
|
-
- [`docs/reference/scope-aware-selection-tooling.md`](docs/reference/scope-aware-selection-tooling.md)
|
|
202
|
-
- [`docs/reference/glossary.md`](docs/reference/glossary.md)
|
|
203
|
-
- [`docs/reference/editor-integration-style.md`](docs/reference/editor-integration-style.md)
|
|
204
|
-
- [`docs/reference/ui-theming-and-styling.md`](docs/reference/ui-theming-and-styling.md)
|
|
205
|
-
- [`docs/reference/beyondwork-runtime-environment.md`](docs/reference/beyondwork-runtime-environment.md)
|
|
206
|
-
|
|
207
|
-
Wrapper and agent docs stay on `main`, but they are downstream integration guidance rather than the canonical package contract.
|
|
208
|
-
|
|
209
|
-
Current integration honesty:
|
|
210
|
-
|
|
211
|
-
- the shipped React host surface is still `WordReviewEditor`
|
|
212
|
-
- `showReviewPanel={false}` only hides the bundled review rail
|
|
213
|
-
- a distinct public chromeless React surface is not yet shipped
|
|
214
|
-
|
|
215
|
-
### Maintainer Path
|
|
216
|
-
|
|
217
|
-
- [`docs/maintainers/README.md`](docs/maintainers/README.md)
|
|
218
|
-
- [`docs/ccep-contract-templates/README.md`](docs/ccep-contract-templates/README.md)
|
|
219
|
-
- [`docs/plans/README.md`](docs/plans/README.md) — active development lanes + open-issues register
|
|
220
|
-
|
|
221
|
-
The CCEP corpus is kept on `main` as a maintainer-safe smoke-doc source set for agreement-heavy validation and wrapper or agent benchmarking.
|
|
222
|
-
|
|
223
|
-
### Active Development Lanes
|
|
224
|
-
|
|
225
|
-
Engineering work is organized into 9 lanes (5 active now + 2 later polish + 2 final) — full plan index, status, and worktree map at [`docs/plans/README.md`](docs/plans/README.md). Each lane has a single self-contained doc at `docs/plans/lane-N-<name>.md`:
|
|
226
|
-
|
|
227
|
-
**Progress snapshot — 2026-04-19 (post PR #189 + #190 + #191 + #192 merged to `main`; Lane 3 split into 3a + 3b on 2026-04-19 deep evening):**
|
|
228
|
-
|
|
229
|
-
| # | Lane | % to goal | Status summary |
|
|
230
|
-
|---|---|---|---|
|
|
231
|
-
| 1 | [**Editing Foundation**](docs/plans/lane-1-editing-foundation.md) | **65%** | I1–I6 + I3 widening + I4 + S1 + X3 + I8 shipped; I2B / I7 / R.1–R.5 backlog |
|
|
232
|
-
| 2 | [**Render Performance**](docs/plans/lane-2-render-performance.md) | **85%** | All Phases 1.x + 2.2 + 2.4b + 2.5 (A+B) + 2.9 shipped; Tasks 2.1 / 2.3 left |
|
|
233
|
-
| 3a | [**Layout & Render Engine**](docs/plans/lane-3a-layout-render-engine.md) | **45%** | P1–P6 + P8 + P14.a/b/e shipped; P9 (now unblocked) + P10 + P11 + P12 + P14.c/d backlog |
|
|
234
|
-
| 3b | [**OOXML Fidelity & Round-Trip**](docs/plans/lane-3b-ooxml-fidelity.md) | **55%** | V1 + O3 + O4 + O2 (all 4 slices) + V7 closed; 🚨 O8 + L2.c + V6 + V2a/b/c + R3–R5 backlog |
|
|
235
|
-
| 4 | [**Collab + CLM/Vallor**](docs/plans/lane-4-collab-clm-vallor.md) | **80%** | P1–P14 + all P11 sub-bullets + P12 + perf-parity + P13 A/B/C shipped; P15 / P16 / P17 left |
|
|
236
|
-
| 5 | [**Charts (independent)**](docs/plans/lane-5-charts.md) | **30%** | Stages 0–2 shipped (parsers + theme); Stages 3–7 (SVG renderers + pixel-diff) left |
|
|
237
|
-
| 6a | [**Tokens & Theme Foundation**](docs/plans/lane-6a-tokens-theme-foundation.md) | **~25%** | Active (no gate) — canonical token substrate: brand-accent flip, semantic families, scope-tint tokens, chart palette, hex eviction, density + reduced-motion plumbing |
|
|
238
|
-
| 6b | [**Shell & Workspace Chrome**](docs/plans/lane-6b-shell-workspace-chrome.md) | **~15%** | Gated on 6a.S1+S2 — shell header + toolbar + status + alert banner + unsaved modal + collab chrome restyle; mode-dock decommission; TwCommandPalette |
|
|
239
|
-
| 6c | [**Context & Review Surfaces**](docs/plans/lane-6c-context-review-surfaces.md) | **~15%** | Gated on 6a.S1+S2 — selection toolbar + suggestion card + rail + scope + context toolbars + health panel restyle; TwCommentPreview / TwEmptyState / TwShortcutHint |
|
|
240
|
-
| 6d | [**Visual Fidelity**](docs/plans/lane-6d-visual-fidelity.md) | **~20%** | Gated on 6a.S1+S2 + external-lane deps — L8 A/B/C shipped; L8 Phase D + P11 overlays + P7 + P12 + P14 next |
|
|
241
|
-
| 7a | [**Visual Fidelity Register**](docs/plans/lane-7a-visual-fidelity-register.md) | **0%** | LATER (gated on 6a–6d) — V5 covers, V6 REF/PAGEREF, V7 cascade audit |
|
|
242
|
-
| 7b | [**Revision & Redline Completion**](docs/plans/lane-prompts/lane-7b-revision-redline-completion.md) | **✅ CLOSED** | Phases A–N shipped on `lane-7b-revision-redline` (17 commits) — full X4.a parse (container + range markers), X4.b complete (cellIns accept + reject + row-ins/row-del accept + reject), move-promotion (linked-pair atomic accept/reject). Trigger-gated: X4.c + X5 + nested-table row-insertion scope limit. Validator pass handed off to coordinator |
|
|
243
|
-
| 7c | [**Preservation & Format Coverage**](docs/plans/lane-7c-preservation-format-coverage.md) | **0%** | LATER (gated on 6a–6d) — O6 Strict, OLE preserve-only, picture-SDT, w14/kern/VML defer |
|
|
244
|
-
| 7d | [**Platform Hardening & Hygiene**](docs/plans/lane-7d-platform-hardening-hygiene.md) | **0%** | LATER (gated on 6a–6d) — harness-crash-hardening, fastload activation, worktree consolidation |
|
|
245
|
-
| 8 | [**API Ergonomics / Errors / BC**](docs/plans/lane-8-api-ergonomics.md) | **40%** | LATER — Tracks A+C shipped (error catalog + ergonomics fixes); Tracks B+D+E + public-api.md end-to-end refactor remain |
|
|
246
|
-
| 9 | [**Shipping (v2.0.0)**](docs/plans/lane-9-shipping.md) | **0%** | FINAL — API freeze, semver discipline, changelog, telemetry, customer migration guides, doc completeness audit |
|
|
247
|
-
|
|
248
|
-
**Aggregate v2.0.0 readiness:** ~70% — long poles are Lane 3 O8 + P9/P10, Lane 4 P15/P16/P17, Lane 1 R.1–R.5, Lane 5 Stage 4 SVG renderers (Lane 5 ships on independent v2.x cadence). Detailed task-completeness factor + per-lane backlog inventory in [`docs/plans/coordination-prompt.md`](docs/plans/coordination-prompt.md).
|
|
249
|
-
|
|
250
|
-
### Technical Wiki
|
|
251
|
-
|
|
252
|
-
- [`docs/wiki/`](docs/wiki/) — Feature-by-feature technical documentation (25+ topics covering OOXML, ProseMirror, runtime, and platform)
|
|
253
|
-
|
|
254
|
-
## Agent Integration
|
|
255
|
-
|
|
256
|
-
Agents consume the editor through a consistent pipeline:
|
|
257
|
-
|
|
258
|
-
```
|
|
259
|
-
inspect --> locate --> mutate --> validate --> export
|
|
260
|
-
```
|
|
261
|
-
|
|
262
|
-
Beyond Work platform agents extend this with propose/approve gates:
|
|
263
|
-
|
|
264
|
-
```
|
|
265
|
-
inspect --> locate --> propose --> approve --> mutate --> validate --> export
|
|
23
|
+
pnpm add @beyondwork/docx-react-component
|
|
266
24
|
```
|
|
267
25
|
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
| Read model | Getter | Purpose |
|
|
271
|
-
|---|---|---|
|
|
272
|
-
| Document surface | `getRenderSnapshot()` | Structure, blocks, text, selection |
|
|
273
|
-
| Comments | `getComments()` | Thread state, resolution, anchors |
|
|
274
|
-
| Tracked changes | `getTrackedChanges()` | Revision inventory, actionability |
|
|
275
|
-
| Workflow scope | `getWorkflowScopeSnapshot()` | Scope boundaries, work items, mode |
|
|
276
|
-
| Interaction guard | `getInteractionGuardSnapshot()` | Effective mode, blocked reasons |
|
|
277
|
-
| Compatibility | `getCompatibilityReport()` | Export risk assessment |
|
|
278
|
-
| Warnings | `getWarnings()` | Active fidelity or mutation warnings |
|
|
279
|
-
| Fields | `getFieldSnapshot()` | Field posture and refresh state |
|
|
280
|
-
|
|
281
|
-
Agents should read the narrow snapshot that answers the next question, not pull the full render snapshot for every decision.
|
|
282
|
-
|
|
283
|
-
## Packaging And Release
|
|
284
|
-
|
|
285
|
-
- `.github/workflows/publish.yml` publishes on `v*` tags after verifying the tag matches `package.json`
|
|
286
|
-
- `pnpm pack --dry-run` is the baseline package proof
|
|
287
|
-
- npm provenance is enabled in `publishConfig` and in the publish workflow invocation
|
|
288
|
-
- the published package currently ships source ESM entry points plus TypeScript source-backed `types` exports
|
|
289
|
-
- the Microsoft Open XML SDK remains CI/internal-service only, never part of the shipped browser runtime
|
|
290
|
-
|
|
291
|
-
## Contribution Rules
|
|
292
|
-
|
|
293
|
-
- respect the runtime-owned state model
|
|
294
|
-
- do not bypass commands and transactions
|
|
295
|
-
- do not treat the DOM as canonical state
|
|
296
|
-
- do not silently drop unknown OOXML
|
|
297
|
-
- keep docs honest about shipped versus planned behavior
|
|
298
|
-
- add or extend fixtures for compatibility-critical changes
|
|
299
|
-
- `bash scripts/validate-fixtures.sh` now uses the Railway validator service and requires `OPENXML_VALIDATOR_AUTH_TOKEN` when hitting the public domain
|
|
300
|
-
- `node scripts/validate-docs-navigation.mjs` enforces the core docs catalog, required indexes, and frontmatter contract
|
|
301
|
-
|
|
302
|
-
## Guiding Principle
|
|
303
|
-
|
|
304
|
-
This repo builds backoffice work components where humans and AI agents are first-class peers. Every capability is designed for both audiences from the start — not bolted on for one after the other. The result is tools that are powerful enough for complex enterprise workflows and structured enough that an agent can operate them safely and predictably.
|
|
305
|
-
|
|
306
|
-
## Using the package
|
|
307
|
-
|
|
308
|
-
### WordReviewEditor
|
|
309
|
-
|
|
310
|
-
`WordReviewEditor` is a React component for loading, editing, and exporting `.docx` files with full comment and tracked-change (redline) support. It is exported from `@beyondwork/docx-react-component`.
|
|
311
|
-
|
|
312
|
-
### Installation
|
|
313
|
-
|
|
314
|
-
```tsx
|
|
315
|
-
import {
|
|
316
|
-
WordReviewEditor,
|
|
317
|
-
type WordReviewEditorRef,
|
|
318
|
-
type WordReviewEditorProps,
|
|
319
|
-
type WordReviewEditorEvent,
|
|
320
|
-
} from "@beyondwork/docx-react-component";
|
|
321
|
-
```
|
|
26
|
+
Peer dependencies: `react` ≥ 19.2, `react-dom` ≥ 19.2, the ProseMirror family (`prosemirror-state`, `prosemirror-view`, `prosemirror-model`, `prosemirror-transform`, `prosemirror-keymap`, `prosemirror-commands`, `prosemirror-schema-basic`), `tailwindcss` ≥ 4.2, and `yjs` + `y-protocols` for collaboration. See `package.json > peerDependencies`.
|
|
322
27
|
|
|
323
|
-
|
|
28
|
+
## Quick start — mount the editor
|
|
324
29
|
|
|
325
30
|
```tsx
|
|
326
|
-
import {
|
|
327
|
-
import
|
|
328
|
-
|
|
329
|
-
export function MyEditor({ docxBytes }: { docxBytes: Uint8Array }) {
|
|
330
|
-
const editorRef = useRef<WordReviewEditorRef>(null);
|
|
31
|
+
import { WordReviewEditor } from "@beyondwork/docx-react-component/ui-tailwind";
|
|
32
|
+
import "@beyondwork/docx-react-component/ui-tailwind/theme/editor-theme.css";
|
|
331
33
|
|
|
34
|
+
export function App() {
|
|
332
35
|
return (
|
|
333
36
|
<WordReviewEditor
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
currentUser={{ userId: "u1", displayName: "Alice" }}
|
|
337
|
-
initialDocx={docxBytes}
|
|
338
|
-
onEvent={(event) => console.log(event)}
|
|
37
|
+
initialDocument={docxBytes}
|
|
38
|
+
onExport={(bytes) => /* persist */}
|
|
339
39
|
/>
|
|
340
40
|
);
|
|
341
41
|
}
|
|
342
42
|
```
|
|
343
43
|
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
### Props reference
|
|
347
|
-
|
|
348
|
-
| Prop | Type | Description |
|
|
349
|
-
|---|---|---|
|
|
350
|
-
| `documentId` | `string` | **Required.** Stable identifier for this document. |
|
|
351
|
-
| `currentUser` | `EditorUser` | **Required.** The user performing edits and adding comments. |
|
|
352
|
-
| `initialDocx` | `Uint8Array \| ArrayBuffer` | Raw `.docx` bytes to load on first mount. |
|
|
353
|
-
| `initialSessionState` | `EditorSessionState` | Previously saved session state to restore. |
|
|
354
|
-
| `initialSnapshot` | `PersistedEditorSnapshot` | Previously saved snapshot to restore. |
|
|
355
|
-
| `externalDocSource` | `ExternalDocumentSource` | Alternative source with explicit `kind` (`"docx"`, `"session"`, `"snapshot"`). |
|
|
356
|
-
| `readOnly` | `boolean` | When `true`, all editing commands are disabled. |
|
|
357
|
-
| `reviewMode` | `"editing" \| "review"` | Shell layout hint — affects toolbar/panel arrangement but not editing authority. |
|
|
358
|
-
| `markupDisplay` | `"clean" \| "simple" \| "all"` | Controls tracked-change visibility. |
|
|
359
|
-
| `showReviewPanel` | `boolean` | Shows or hides the right-side comment and tracked-change panel. |
|
|
360
|
-
| `autosave` | `AutosaveConfig` | Enables automatic saving. |
|
|
361
|
-
| `hostAdapter` | `EditorHostAdapter` | Callbacks for `load`, `saveSession`, `saveExport`. |
|
|
362
|
-
| `datastore` | `EditorDatastoreAdapter` | Alternative persistence adapter with `load`, `saveSnapshot`. |
|
|
363
|
-
| `onEvent` | `(event: WordReviewEditorEvent) => void` | Unified event handler (see [Events](#events)). |
|
|
364
|
-
| `onWarning` | `(warning: EditorWarning) => void` | Fired for non-fatal warnings. |
|
|
365
|
-
| `onError` | `(error: EditorError) => void` | Fired for fatal errors. |
|
|
366
|
-
|
|
367
|
-
#### EditorUser
|
|
368
|
-
|
|
369
|
-
```ts
|
|
370
|
-
interface EditorUser {
|
|
371
|
-
userId: string;
|
|
372
|
-
displayName: string;
|
|
373
|
-
email?: string;
|
|
374
|
-
avatarUrl?: string;
|
|
375
|
-
}
|
|
376
|
-
```
|
|
377
|
-
|
|
378
|
-
#### AutosaveConfig
|
|
44
|
+
## Quick start — headless / stateless service
|
|
379
45
|
|
|
380
46
|
```ts
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
debounceMs?: number; // default: 2000
|
|
384
|
-
}
|
|
385
|
-
```
|
|
386
|
-
|
|
387
|
-
---
|
|
388
|
-
|
|
389
|
-
### Show / hide UI regions
|
|
390
|
-
|
|
391
|
-
#### Review panel
|
|
392
|
-
|
|
393
|
-
The right-side panel lists comment threads and tracked changes.
|
|
394
|
-
|
|
395
|
-
```tsx
|
|
396
|
-
<WordReviewEditor showReviewPanel={false} ... /> // hide panel
|
|
397
|
-
<WordReviewEditor showReviewPanel={true} ... /> // show panel (default)
|
|
398
|
-
```
|
|
399
|
-
|
|
400
|
-
#### Tracked-change display mode
|
|
401
|
-
|
|
402
|
-
`markupDisplay` controls how tracked changes appear in the document body.
|
|
403
|
-
|
|
404
|
-
| Value | Behaviour |
|
|
405
|
-
|---|---|
|
|
406
|
-
| `"clean"` | Show the accepted version — insertions visible, deletions hidden. |
|
|
407
|
-
| `"simple"` | Show a simplified view of changes without inline markup. |
|
|
408
|
-
| `"all"` | Show all insertion and deletion marks inline (Word's "Show Markup" mode). |
|
|
409
|
-
|
|
410
|
-
```tsx
|
|
411
|
-
<WordReviewEditor markupDisplay="clean" ... />
|
|
412
|
-
```
|
|
413
|
-
|
|
414
|
-
You can also change the display mode at runtime:
|
|
415
|
-
|
|
416
|
-
```ts
|
|
417
|
-
// no ref method for markupDisplay — pass as a prop; React re-renders propagate the change.
|
|
418
|
-
```
|
|
419
|
-
|
|
420
|
-
#### Document mode
|
|
421
|
-
|
|
422
|
-
`DocumentMode` controls editing authority, not just appearance.
|
|
423
|
-
|
|
424
|
-
| Mode | Effect |
|
|
425
|
-
|---|---|
|
|
426
|
-
| `"editing"` | Edits are applied directly (no tracking). |
|
|
427
|
-
| `"suggesting"` | Every edit is automatically wrapped in a tracked change. |
|
|
428
|
-
| `"viewing"` | Document is read-only regardless of the `readOnly` prop. |
|
|
429
|
-
|
|
430
|
-
Set via ref:
|
|
431
|
-
|
|
432
|
-
```ts
|
|
433
|
-
editorRef.current.setDocumentMode("suggesting");
|
|
434
|
-
```
|
|
435
|
-
|
|
436
|
-
Or pass `reviewMode="review"` as a prop to start in a review-friendly shell layout (the component internally maps this to `"suggesting"` document mode).
|
|
437
|
-
|
|
438
|
-
#### Read-only mode
|
|
439
|
-
|
|
440
|
-
```tsx
|
|
441
|
-
<WordReviewEditor readOnly={true} ... />
|
|
442
|
-
```
|
|
443
|
-
|
|
444
|
-
All editing, commenting, and tracked-change commands are blocked. The toolbar is still rendered but all buttons are disabled.
|
|
47
|
+
import { DocxSession } from "@beyondwork/docx-react-component/session";
|
|
48
|
+
import { createApiV3 } from "@beyondwork/docx-react-component/api/v3";
|
|
445
49
|
|
|
446
|
-
|
|
50
|
+
const session = await DocxSession.open(docxBytes);
|
|
51
|
+
const api = createApiV3(session.runtime);
|
|
447
52
|
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
53
|
+
const outline = await api.runtime.document.getOutline();
|
|
54
|
+
const issues = await api.runtime.review.getChanges();
|
|
55
|
+
const bytes = await api.runtime.document.export();
|
|
451
56
|
```
|
|
452
57
|
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
### Imperative ref
|
|
456
|
-
|
|
457
|
-
Obtain the ref via `useRef<WordReviewEditorRef>()`:
|
|
458
|
-
|
|
459
|
-
```tsx
|
|
460
|
-
const editorRef = useRef<WordReviewEditorRef>(null);
|
|
461
|
-
<WordReviewEditor ref={editorRef} ... />
|
|
462
|
-
|
|
463
|
-
// then:
|
|
464
|
-
editorRef.current?.addComment({ body: "Needs revision" });
|
|
465
|
-
```
|
|
58
|
+
See [`examples/headless-service/`](examples/headless-service/) for a full stateless consumer.
|
|
466
59
|
|
|
467
60
|
---
|
|
468
61
|
|
|
469
|
-
|
|
62
|
+
## What's shipped
|
|
470
63
|
|
|
471
|
-
|
|
64
|
+
**Editing & review**
|
|
65
|
+
- Tracked changes (add, accept, reject, resolve) incl. container + range markers and move-promotion
|
|
66
|
+
- Suggesting mode — every edit automatically becomes a tracked change
|
|
67
|
+
- Comments — anchored, threaded, mention-aware, with presentation/negotiation layer
|
|
68
|
+
- Workflow overlays and scope-based editing guards
|
|
69
|
+
- Document comparison (LCS-backed diffing + redline export)
|
|
472
70
|
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
71
|
+
**Fidelity**
|
|
72
|
+
- OOXML round-trip — open, edit, export, reopen in Word without repair prompts
|
|
73
|
+
- Preserve-first handling for unknown fragments (opaque preservation)
|
|
74
|
+
- Layout engine — **97.77 %** external layout-structure truth and **96.34 %** rendered-word geometry on the CCEP contract corpus
|
|
75
|
+
- Charts v1 — native SVG renderer for 7 chart families, progressive time-sliced
|
|
477
76
|
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
body?: string;
|
|
482
|
-
authorId?: string; // defaults to currentUser.userId
|
|
483
|
-
}
|
|
484
|
-
```
|
|
485
|
-
|
|
486
|
-
**Important**: if you want the comment to land on a specific text selection, capture the anchor *before* opening any draft UI (e.g. a modal or popover), because opening a modal typically collapses the editor selection.
|
|
487
|
-
|
|
488
|
-
```ts
|
|
489
|
-
// 1. Capture anchor while text is still selected
|
|
490
|
-
const snapshot = editorRef.current.getRenderSnapshot();
|
|
491
|
-
const anchor = snapshot.selection.activeRange;
|
|
77
|
+
**Collaboration**
|
|
78
|
+
- Yjs transport with HMAC-signed awareness, tamper-gating, external-custody round-trip
|
|
79
|
+
- Prerender cache (`prerenderDocument()`) for cold-open parity
|
|
492
80
|
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
81
|
+
**Automation surface**
|
|
82
|
+
- **V1/V2 ref-method API** — stable React imperative surface on `WordReviewEditorRef`
|
|
83
|
+
- **V3 stateless API** — `createApiV3(runtime)` exposes Runtime + AI families under a `live` / `live-with-adapter` / `partial` / `mock` taxonomy
|
|
84
|
+
- AI action policy — risk-classified gating for 37 discrete agent operations
|
|
85
|
+
- Every `uiVisible` V3 function emits exactly one `UxResponse` on the `api` telemetry channel — the stream the debug surfaces consume
|
|
497
86
|
|
|
498
|
-
|
|
87
|
+
**Accessibility**
|
|
88
|
+
- Keyboard-first, reduced-motion respected, WCAG-audited (audit harness lives outside the shipping snapshot)
|
|
499
89
|
|
|
500
|
-
|
|
501
|
-
editorRef.current.resolveComment(commentId);
|
|
502
|
-
```
|
|
503
|
-
|
|
504
|
-
Marks the thread as resolved. The comment remains in the document and can be exported; it is moved to the resolved list in the sidebar.
|
|
505
|
-
|
|
506
|
-
#### Reopen a resolved comment
|
|
507
|
-
|
|
508
|
-
```ts
|
|
509
|
-
editorRef.current.reopenComment(commentId);
|
|
510
|
-
```
|
|
511
|
-
|
|
512
|
-
#### Delete a comment permanently
|
|
513
|
-
|
|
514
|
-
```ts
|
|
515
|
-
editorRef.current.deleteComment(commentId);
|
|
516
|
-
```
|
|
517
|
-
|
|
518
|
-
Removes the comment entirely. Use this to clean up failed or unwanted drafts.
|
|
519
|
-
|
|
520
|
-
#### Add a reply to an existing thread
|
|
521
|
-
|
|
522
|
-
```ts
|
|
523
|
-
editorRef.current.addCommentReply(commentId, "Reply text here");
|
|
524
|
-
```
|
|
525
|
-
|
|
526
|
-
#### Edit a comment body
|
|
527
|
-
|
|
528
|
-
```ts
|
|
529
|
-
editorRef.current.editCommentBody(commentId, "Updated text");
|
|
530
|
-
```
|
|
531
|
-
|
|
532
|
-
#### Scroll to a comment
|
|
533
|
-
|
|
534
|
-
```ts
|
|
535
|
-
editorRef.current.scrollToComment(commentId);
|
|
536
|
-
```
|
|
537
|
-
|
|
538
|
-
#### Open (focus) a comment in the sidebar
|
|
539
|
-
|
|
540
|
-
```ts
|
|
541
|
-
editorRef.current.openComment(commentId);
|
|
542
|
-
```
|
|
543
|
-
|
|
544
|
-
#### Get all comments
|
|
545
|
-
|
|
546
|
-
```ts
|
|
547
|
-
const sidebar: CommentSidebarSnapshot = editorRef.current.getComments();
|
|
548
|
-
```
|
|
549
|
-
|
|
550
|
-
```ts
|
|
551
|
-
interface CommentSidebarSnapshot {
|
|
552
|
-
activeCommentId?: string;
|
|
553
|
-
openCommentIds: string[];
|
|
554
|
-
resolvedCommentIds: string[];
|
|
555
|
-
detachedCommentIds: string[];
|
|
556
|
-
totalCount: number;
|
|
557
|
-
threads: CommentSidebarThreadSnapshot[];
|
|
558
|
-
}
|
|
559
|
-
|
|
560
|
-
interface CommentSidebarThreadSnapshot {
|
|
561
|
-
commentId: string;
|
|
562
|
-
status: "open" | "resolved" | "detached";
|
|
563
|
-
anchor: EditorAnchorProjection;
|
|
564
|
-
excerpt: string; // the anchored text snippet
|
|
565
|
-
entries: CommentSidebarThreadEntrySnapshot[];
|
|
566
|
-
entryCount: number;
|
|
567
|
-
createdAt: string; // ISO 8601
|
|
568
|
-
createdBy: string; // userId
|
|
569
|
-
resolvedAt?: string;
|
|
570
|
-
resolvedBy?: string;
|
|
571
|
-
}
|
|
572
|
-
```
|
|
573
|
-
|
|
574
|
-
#### Detached comments
|
|
575
|
-
|
|
576
|
-
A comment becomes **detached** when the text it was anchored to is deleted. Detached comments:
|
|
577
|
-
|
|
578
|
-
- Still appear in `sidebar.detachedCommentIds` and have `status: "detached"`.
|
|
579
|
-
- Have `anchor.kind === "detached"` with a `lastKnownRange` and a `reason` (`"deleted"`, `"invalidatedByStructureChange"`, or `"importAmbiguity"`).
|
|
580
|
-
- Do **not** block DOCX export.
|
|
581
|
-
- Can be resolved, reopened, or deleted via the same methods above.
|
|
90
|
+
Feature-level status + known gaps: [`KNOWN-ISSUES.md`](KNOWN-ISSUES.md), [`KNOWN_ISSUES.md`](KNOWN_ISSUES.md), [`KNOWN-ISSUES-VISUAL.md`](KNOWN-ISSUES-VISUAL.md).
|
|
582
91
|
|
|
583
92
|
---
|
|
584
93
|
|
|
585
|
-
|
|
94
|
+
## Architecture
|
|
586
95
|
|
|
587
|
-
|
|
96
|
+
The editor runs ProseMirror in an **inverted model**: PM is a view surface, the runtime owns every mutation, and the canonical truth order is
|
|
588
97
|
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
98
|
+
1. OOXML package bytes
|
|
99
|
+
2. `CanonicalDocument`
|
|
100
|
+
3. `DocumentRuntime` derived state (formatting, layout, geometry, scopes, review)
|
|
101
|
+
4. `EditorSurfaceSnapshot` + PM state + DOM
|
|
592
102
|
|
|
593
|
-
|
|
594
|
-
interface TrackedChangesSnapshot {
|
|
595
|
-
pendingChangeIds: string[];
|
|
596
|
-
acceptedChangeIds: string[];
|
|
597
|
-
rejectedChangeIds: string[];
|
|
598
|
-
detachedChangeIds: string[];
|
|
599
|
-
actionableChangeIds: string[];
|
|
600
|
-
preserveOnlyChangeIds: string[];
|
|
601
|
-
totalCount: number;
|
|
602
|
-
revisions: TrackedChangeEntrySnapshot[];
|
|
603
|
-
}
|
|
103
|
+
Higher layers are projections of lower layers. Reading the DOM or PM state as truth is a bug.
|
|
604
104
|
|
|
605
|
-
|
|
606
|
-
revisionId: string;
|
|
607
|
-
kind: "insertion" | "deletion" | "formatting" | "move" | "property-change";
|
|
608
|
-
status: "active" | "accepted" | "rejected" | "detached";
|
|
609
|
-
actionability: "actionable" | "preserve-only";
|
|
610
|
-
canAccept: boolean;
|
|
611
|
-
canReject: boolean;
|
|
612
|
-
anchor: EditorAnchorProjection;
|
|
613
|
-
anchorLabel: string;
|
|
614
|
-
excerpt?: string;
|
|
615
|
-
detail?: string;
|
|
616
|
-
authorId: string;
|
|
617
|
-
createdAt: string;
|
|
618
|
-
}
|
|
619
|
-
```
|
|
620
|
-
|
|
621
|
-
`preserve-only` revisions (`formatting`, `move`) can be displayed but cannot be individually accepted or rejected through the API.
|
|
622
|
-
|
|
623
|
-
#### Accept a single change
|
|
624
|
-
|
|
625
|
-
```ts
|
|
626
|
-
editorRef.current.acceptChange(revisionId);
|
|
627
|
-
```
|
|
628
|
-
|
|
629
|
-
#### Reject a single change
|
|
630
|
-
|
|
631
|
-
```ts
|
|
632
|
-
editorRef.current.rejectChange(revisionId);
|
|
633
|
-
```
|
|
634
|
-
|
|
635
|
-
#### Accept all pending changes
|
|
636
|
-
|
|
637
|
-
```ts
|
|
638
|
-
editorRef.current.acceptAllChanges();
|
|
639
|
-
```
|
|
640
|
-
|
|
641
|
-
#### Reject all pending changes
|
|
642
|
-
|
|
643
|
-
```ts
|
|
644
|
-
editorRef.current.rejectAllChanges();
|
|
645
|
-
```
|
|
646
|
-
|
|
647
|
-
#### Scroll to a tracked change
|
|
648
|
-
|
|
649
|
-
```ts
|
|
650
|
-
editorRef.current.scrollToRevision(revisionId);
|
|
651
|
-
```
|
|
105
|
+
The 11-layer target architecture — session, canonical document, formatting, layout, geometry, workflow, runtime API, semantic scope compiler, AI API, UI API, presentation — is documented in [`docs/architecture/00-overview.md`](docs/architecture/00-overview.md), with per-layer canonical specs in [`docs/architecture/01-package-session.md`](docs/architecture/01-package-session.md) … [`11-presentation-surfaces.md`](docs/architecture/11-presentation-surfaces.md).
|
|
652
106
|
|
|
653
107
|
---
|
|
654
108
|
|
|
655
|
-
|
|
109
|
+
## Documentation lanes
|
|
656
110
|
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
111
|
+
| Lane | Path | When to start here |
|
|
112
|
+
|---|---|---|
|
|
113
|
+
| Router | [`docs/README.md`](docs/README.md) | Any time — triage into the right lane |
|
|
114
|
+
| Architecture | [`docs/architecture/00-overview.md`](docs/architecture/00-overview.md) | Canonical per-layer target design for the 11-layer stack |
|
|
115
|
+
| Wiki (feature deep-dives) | [`docs/wiki/`](docs/wiki/) | Topic-organized narrative connecting OOXML + PM + implementation + testing |
|
|
116
|
+
| Migration | [`MIGRATION.md`](MIGRATION.md) | Upgrading across major versions |
|
|
117
|
+
| Known issues | [`KNOWN-ISSUES.md`](KNOWN-ISSUES.md), [`KNOWN_ISSUES.md`](KNOWN_ISSUES.md), [`KNOWN-ISSUES-VISUAL.md`](KNOWN-ISSUES-VISUAL.md) | Preview caveats + visual-fidelity gap inventory |
|
|
118
|
+
| Changelog | [`CHANGELOG.md`](CHANGELOG.md) | Release notes |
|
|
663
119
|
|
|
664
120
|
---
|
|
665
121
|
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
All events are dispatched through the single `onEvent` prop. The `type` discriminator narrows the payload.
|
|
122
|
+
## Development
|
|
669
123
|
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
}
|
|
676
|
-
}}
|
|
677
|
-
/>
|
|
678
|
-
```
|
|
679
|
-
|
|
680
|
-
#### `ready`
|
|
681
|
-
|
|
682
|
-
Fired once after the document finishes loading and the editor is interactive.
|
|
683
|
-
|
|
684
|
-
```ts
|
|
685
|
-
{
|
|
686
|
-
type: "ready";
|
|
687
|
-
documentId: string;
|
|
688
|
-
sessionId: string;
|
|
689
|
-
source: "docx" | "session" | "snapshot";
|
|
690
|
-
stats: DocumentStats; // storyLength, commentCount, revisionCount
|
|
691
|
-
compatibility: CompatibilityReport;
|
|
692
|
-
comments: CommentSidebarSnapshot;
|
|
693
|
-
trackedChanges: TrackedChangesSnapshot;
|
|
694
|
-
}
|
|
695
|
-
```
|
|
696
|
-
|
|
697
|
-
#### `comment_added`
|
|
698
|
-
|
|
699
|
-
Fired when a new comment thread is created (via `addComment` or the toolbar).
|
|
700
|
-
|
|
701
|
-
```ts
|
|
702
|
-
{
|
|
703
|
-
type: "comment_added";
|
|
704
|
-
documentId: string;
|
|
705
|
-
commentId: string;
|
|
706
|
-
anchor: EditorAnchorProjection;
|
|
707
|
-
}
|
|
708
|
-
```
|
|
709
|
-
|
|
710
|
-
#### `comment_resolved`
|
|
711
|
-
|
|
712
|
-
Fired when a comment is resolved (via `resolveComment` or the sidebar).
|
|
713
|
-
|
|
714
|
-
```ts
|
|
715
|
-
{
|
|
716
|
-
type: "comment_resolved";
|
|
717
|
-
documentId: string;
|
|
718
|
-
commentId: string;
|
|
719
|
-
}
|
|
720
|
-
```
|
|
721
|
-
|
|
722
|
-
For a general-purpose "something about comments changed" signal (covering deletions, reply appends, body edits, reopen, and every other mutation — including Yjs-driven mutations that route through the editor's imperative ref), subscribe to `comments_changed`.
|
|
723
|
-
|
|
724
|
-
#### `comments_changed`
|
|
725
|
-
|
|
726
|
-
Fired once per commit whenever the runtime's comment snapshot differs from the previous commit. Use this when you render comments in a sibling component and need to know when to re-fetch via `editorRef.current.getComments()`.
|
|
727
|
-
|
|
728
|
-
```ts
|
|
729
|
-
{
|
|
730
|
-
type: "comments_changed";
|
|
731
|
-
documentId: string;
|
|
732
|
-
changedCommentIds: string[]; // always non-empty
|
|
733
|
-
}
|
|
734
|
-
```
|
|
735
|
-
|
|
736
|
-
Covers: `addComment`, `deleteComment`, `resolveComment`, `reopenComment`, `addCommentReply`, `editCommentBody`, and any remote-origin mutation that funnels through the same runtime APIs. Does NOT fire on selection/focus changes.
|
|
737
|
-
|
|
738
|
-
#### `change_accepted`
|
|
739
|
-
|
|
740
|
-
Fired when a tracked change is accepted.
|
|
741
|
-
|
|
742
|
-
```ts
|
|
743
|
-
{
|
|
744
|
-
type: "change_accepted";
|
|
745
|
-
documentId: string;
|
|
746
|
-
changeId: string;
|
|
747
|
-
}
|
|
748
|
-
```
|
|
749
|
-
|
|
750
|
-
#### `change_rejected`
|
|
751
|
-
|
|
752
|
-
Fired when a tracked change is rejected.
|
|
753
|
-
|
|
754
|
-
```ts
|
|
755
|
-
{
|
|
756
|
-
type: "change_rejected";
|
|
757
|
-
documentId: string;
|
|
758
|
-
changeId: string;
|
|
759
|
-
}
|
|
760
|
-
```
|
|
761
|
-
|
|
762
|
-
#### `selection_changed`
|
|
763
|
-
|
|
764
|
-
Fired whenever the editor cursor or selection changes.
|
|
765
|
-
|
|
766
|
-
```ts
|
|
767
|
-
{
|
|
768
|
-
type: "selection_changed";
|
|
769
|
-
documentId: string;
|
|
770
|
-
selection: SelectionSnapshot;
|
|
771
|
-
}
|
|
772
|
-
|
|
773
|
-
interface SelectionSnapshot {
|
|
774
|
-
anchor: number;
|
|
775
|
-
head: number;
|
|
776
|
-
isCollapsed: boolean;
|
|
777
|
-
activeRange: EditorAnchorProjection;
|
|
778
|
-
storyTarget?: EditorStoryTarget;
|
|
779
|
-
}
|
|
780
|
-
```
|
|
781
|
-
|
|
782
|
-
Use `selection.activeRange` as the `anchor` argument to `addComment` — but capture it *before* opening any modal UI.
|
|
783
|
-
|
|
784
|
-
#### `dirty_changed`
|
|
785
|
-
|
|
786
|
-
Fired when the document transitions between clean and dirty (unsaved) states.
|
|
787
|
-
|
|
788
|
-
```ts
|
|
789
|
-
{
|
|
790
|
-
type: "dirty_changed";
|
|
791
|
-
documentId: string;
|
|
792
|
-
isDirty: boolean;
|
|
793
|
-
}
|
|
794
|
-
```
|
|
795
|
-
|
|
796
|
-
#### `story_changed`
|
|
797
|
-
|
|
798
|
-
Fired when the user navigates between document stories (e.g. main body -> header/footer).
|
|
799
|
-
|
|
800
|
-
```ts
|
|
801
|
-
{
|
|
802
|
-
type: "story_changed";
|
|
803
|
-
documentId: string;
|
|
804
|
-
activeStory: EditorStoryTarget;
|
|
805
|
-
}
|
|
806
|
-
```
|
|
807
|
-
|
|
808
|
-
#### `export_completed`
|
|
809
|
-
|
|
810
|
-
Fired after a successful `exportDocx` call, after the host `saveExport` callback (if any) has resolved.
|
|
811
|
-
|
|
812
|
-
```ts
|
|
813
|
-
{
|
|
814
|
-
type: "export_completed";
|
|
815
|
-
documentId: string;
|
|
816
|
-
result: ExportResult; // result.bytes, result.fileName, result.mimeType
|
|
817
|
-
}
|
|
818
|
-
```
|
|
819
|
-
|
|
820
|
-
#### `session_saved`
|
|
821
|
-
|
|
822
|
-
Fired after the host `saveSession` callback resolves.
|
|
823
|
-
|
|
824
|
-
```ts
|
|
825
|
-
{
|
|
826
|
-
type: "session_saved";
|
|
827
|
-
documentId: string;
|
|
828
|
-
sessionState: EditorSessionState;
|
|
829
|
-
savedAt: string;
|
|
830
|
-
isAutosave: boolean;
|
|
831
|
-
}
|
|
832
|
-
```
|
|
833
|
-
|
|
834
|
-
#### `snapshot_saved`
|
|
835
|
-
|
|
836
|
-
Fired after the datastore `saveSnapshot` callback resolves.
|
|
837
|
-
|
|
838
|
-
```ts
|
|
839
|
-
{
|
|
840
|
-
type: "snapshot_saved";
|
|
841
|
-
documentId: string;
|
|
842
|
-
snapshot: PersistedEditorSnapshot;
|
|
843
|
-
isAutosave: boolean;
|
|
844
|
-
}
|
|
845
|
-
```
|
|
846
|
-
|
|
847
|
-
#### `autosave_state`
|
|
848
|
-
|
|
849
|
-
Fired when the autosave lifecycle transitions.
|
|
850
|
-
|
|
851
|
-
```ts
|
|
852
|
-
{
|
|
853
|
-
type: "autosave_state";
|
|
854
|
-
documentId: string;
|
|
855
|
-
state: "idle" | "pending" | "saving" | "saved" | "error";
|
|
856
|
-
}
|
|
857
|
-
```
|
|
858
|
-
|
|
859
|
-
#### `warning_added` / `warning_cleared`
|
|
860
|
-
|
|
861
|
-
Non-fatal import or rendering warnings.
|
|
862
|
-
|
|
863
|
-
```ts
|
|
864
|
-
{ type: "warning_added"; documentId: string; warning: EditorWarning; }
|
|
865
|
-
{ type: "warning_cleared"; documentId: string; warningId: string; code: EditorWarningCode; }
|
|
866
|
-
```
|
|
867
|
-
|
|
868
|
-
#### `error`
|
|
869
|
-
|
|
870
|
-
Fatal editor error. The editor may be in an unrecoverable state after this event.
|
|
871
|
-
|
|
872
|
-
```ts
|
|
873
|
-
{
|
|
874
|
-
type: "error";
|
|
875
|
-
documentId: string;
|
|
876
|
-
error: EditorError; // error.code, error.message, error.isFatal
|
|
877
|
-
}
|
|
878
|
-
```
|
|
879
|
-
|
|
880
|
-
#### Workflow events
|
|
881
|
-
|
|
882
|
-
These events relate to the optional workflow overlay feature.
|
|
124
|
+
| Command | Purpose |
|
|
125
|
+
|---|---|
|
|
126
|
+
| `pnpm run lint:tsgo` | TypeScript type check |
|
|
127
|
+
| `pnpm test:repo` | Contract + validation test suite |
|
|
128
|
+
| `pnpm run build` | Build the shipped package |
|
|
883
129
|
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
{ type: "command_blocked"; documentId: string; command: string; reasons: WorkflowBlockedCommandReason[]; }
|
|
888
|
-
```
|
|
130
|
+
Agent onboarding: [`CLAUDE.md`](CLAUDE.md), [`AGENTS.md`](AGENTS.md).
|
|
131
|
+
Product charters: [`DESIGN-EDITOR.md`](DESIGN-EDITOR.md), [`DESIGN-WORKBLOCK.md`](DESIGN-WORKBLOCK.md).
|
|
132
|
+
Findings log: [`SHIP-LOG.md`](SHIP-LOG.md).
|
|
889
133
|
|
|
890
134
|
---
|
|
891
135
|
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
#### EditorAnchorProjection
|
|
895
|
-
|
|
896
|
-
Describes a position or range in the document. Returned by `selection.activeRange` and stored on comments/revisions.
|
|
897
|
-
|
|
898
|
-
```ts
|
|
899
|
-
type EditorAnchorProjection =
|
|
900
|
-
| { kind: "range"; from: number; to: number; assoc: { start: -1|1; end: -1|1 } }
|
|
901
|
-
| { kind: "node"; at: number; assoc: -1|1 }
|
|
902
|
-
| { kind: "detached"; lastKnownRange: { from: number; to: number };
|
|
903
|
-
reason: "deleted" | "invalidatedByStructureChange" | "importAmbiguity" };
|
|
904
|
-
```
|
|
905
|
-
|
|
906
|
-
A `"range"` anchor is required for `addComment` if the document contains tables or the selection spans multiple characters. The `from`/`to` positions are in the editor's internal runtime coordinate space — always capture them from `getRenderSnapshot().selection.activeRange`, never construct them manually.
|
|
907
|
-
|
|
908
|
-
#### DocumentMode
|
|
909
|
-
|
|
910
|
-
```ts
|
|
911
|
-
type DocumentMode = "editing" | "suggesting" | "viewing";
|
|
912
|
-
```
|
|
913
|
-
|
|
914
|
-
#### WorkspaceMode
|
|
136
|
+
## Browser / runtime support
|
|
915
137
|
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
138
|
+
- Modern evergreen browsers (Chrome, Firefox, Safari, Edge)
|
|
139
|
+
- React 19.2+, Node 22+ for server-side usage
|
|
140
|
+
- No web workers — all time-slicing via `scheduler.yield` / `requestIdleCallback` on the main thread
|
|
919
141
|
|
|
920
142
|
---
|
|
921
143
|
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
#### Full add-comment flow with custom UI
|
|
925
|
-
|
|
926
|
-
```tsx
|
|
927
|
-
function CommentButton({ editorRef }: { editorRef: React.RefObject<WordReviewEditorRef> }) {
|
|
928
|
-
const [draft, setDraft] = useState<{ anchor: EditorAnchorProjection; text: string } | null>(null);
|
|
929
|
-
|
|
930
|
-
function openDraft() {
|
|
931
|
-
// Capture anchor BEFORE the modal steals focus from the editor
|
|
932
|
-
const snapshot = editorRef.current?.getRenderSnapshot();
|
|
933
|
-
if (!snapshot) return;
|
|
934
|
-
const anchor = snapshot.selection.activeRange;
|
|
935
|
-
if (anchor.kind !== "range" || anchor.from === anchor.to) return;
|
|
936
|
-
setDraft({ anchor, text: "" });
|
|
937
|
-
}
|
|
938
|
-
|
|
939
|
-
function submit() {
|
|
940
|
-
if (!draft) return;
|
|
941
|
-
editorRef.current?.addComment({ anchor: draft.anchor, body: draft.text });
|
|
942
|
-
setDraft(null);
|
|
943
|
-
}
|
|
944
|
-
|
|
945
|
-
return (
|
|
946
|
-
<>
|
|
947
|
-
<button onClick={openDraft}>Comment</button>
|
|
948
|
-
{draft && (
|
|
949
|
-
<dialog open>
|
|
950
|
-
<textarea value={draft.text} onChange={(e) => setDraft({ ...draft, text: e.target.value })} />
|
|
951
|
-
<button onClick={submit}>Add</button>
|
|
952
|
-
<button onClick={() => setDraft(null)}>Cancel</button>
|
|
953
|
-
</dialog>
|
|
954
|
-
)}
|
|
955
|
-
</>
|
|
956
|
-
);
|
|
957
|
-
}
|
|
958
|
-
```
|
|
959
|
-
|
|
960
|
-
#### Listen for comment and review-change events
|
|
144
|
+
## License
|
|
961
145
|
|
|
962
|
-
|
|
963
|
-
<WordReviewEditor
|
|
964
|
-
onEvent={(event) => {
|
|
965
|
-
switch (event.type) {
|
|
966
|
-
case "comment_added":
|
|
967
|
-
console.log("comment added:", event.commentId, event.anchor);
|
|
968
|
-
break;
|
|
969
|
-
case "comment_resolved":
|
|
970
|
-
console.log("comment resolved:", event.commentId);
|
|
971
|
-
break;
|
|
972
|
-
case "comments_changed":
|
|
973
|
-
console.log("comments changed:", event.changedCommentIds);
|
|
974
|
-
break;
|
|
975
|
-
case "change_accepted":
|
|
976
|
-
console.log("change accepted:", event.changeId);
|
|
977
|
-
break;
|
|
978
|
-
case "change_rejected":
|
|
979
|
-
console.log("change rejected:", event.changeId);
|
|
980
|
-
break;
|
|
981
|
-
}
|
|
982
|
-
}}
|
|
983
|
-
/>
|
|
984
|
-
```
|
|
985
|
-
|
|
986
|
-
#### Resolve all open comments programmatically
|
|
987
|
-
|
|
988
|
-
```ts
|
|
989
|
-
const { threads } = editorRef.current.getComments();
|
|
990
|
-
for (const thread of threads) {
|
|
991
|
-
if (thread.status === "open") {
|
|
992
|
-
editorRef.current.resolveComment(thread.commentId);
|
|
993
|
-
}
|
|
994
|
-
}
|
|
995
|
-
```
|
|
996
|
-
|
|
997
|
-
#### Accept or reject all actionable changes
|
|
998
|
-
|
|
999
|
-
```ts
|
|
1000
|
-
editorRef.current.acceptAllChanges();
|
|
1001
|
-
// or
|
|
1002
|
-
editorRef.current.rejectAllChanges();
|
|
1003
|
-
```
|
|
146
|
+
See [`LICENSE.md`](LICENSE.md). The package is published under the Beyond Work license for use inside the Beyond Work platform and its authorized integrations.
|