@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.
Files changed (384) hide show
  1. package/README.md +75 -931
  2. package/package.json +26 -27
  3. package/src/api/anchor-conversion.ts +43 -0
  4. package/src/api/editor-state-types.ts +2 -1
  5. package/src/api/public-types.ts +504 -101
  6. package/src/api/session-state.ts +4 -0
  7. package/src/api/v3/README.md +91 -0
  8. package/src/api/v3/_create.ts +146 -0
  9. package/src/api/v3/_layer-metadata.ts +362 -0
  10. package/src/api/v3/_mocks.ts +84 -0
  11. package/src/api/v3/_runtime-handle.ts +162 -0
  12. package/src/api/v3/_ux-response.ts +73 -0
  13. package/src/api/v3/ai/_metadata-audit.ts +225 -0
  14. package/src/api/v3/ai/attach.ts +235 -0
  15. package/src/api/v3/ai/bundle.ts +132 -0
  16. package/src/api/v3/ai/explain.ts +144 -0
  17. package/src/api/v3/ai/export.ts +54 -0
  18. package/src/api/v3/ai/inspect.ts +118 -0
  19. package/src/api/v3/ai/policy.ts +77 -0
  20. package/src/api/v3/ai/replacement.ts +341 -0
  21. package/src/api/v3/ai/resolve.ts +133 -0
  22. package/src/api/v3/index.ts +79 -0
  23. package/src/api/v3/runtime/chart.ts +310 -0
  24. package/src/api/v3/runtime/clipboard.ts +81 -0
  25. package/src/api/v3/runtime/collab.ts +331 -0
  26. package/src/api/v3/runtime/content.ts +236 -0
  27. package/src/api/v3/runtime/document.ts +282 -0
  28. package/src/api/v3/runtime/formatting.ts +186 -0
  29. package/src/api/v3/runtime/geometry.ts +349 -0
  30. package/src/api/v3/runtime/layout.ts +108 -0
  31. package/src/api/v3/runtime/review.ts +129 -0
  32. package/src/api/v3/runtime/search.ts +74 -0
  33. package/src/api/v3/runtime/table.ts +63 -0
  34. package/src/api/v3/runtime/workflow.ts +434 -0
  35. package/src/api/v3/ui/_context.ts +86 -0
  36. package/src/api/v3/ui/_create.ts +65 -0
  37. package/src/api/v3/ui/_types.ts +520 -0
  38. package/src/api/v3/ui/chrome-composition.ts +342 -0
  39. package/src/{ui-tailwind/chrome → api/v3/ui}/chrome-preset-model.ts +11 -1
  40. package/src/api/v3/ui/chrome.ts +476 -0
  41. package/src/api/v3/ui/debug.ts +124 -0
  42. package/src/api/v3/ui/index.ts +64 -0
  43. package/src/api/v3/ui/overlays-visibility.ts +170 -0
  44. package/src/api/v3/ui/overlays.ts +427 -0
  45. package/src/api/v3/ui/scope.ts +71 -0
  46. package/src/api/v3/ui/session.ts +100 -0
  47. package/src/api/v3/ui/surface.ts +170 -0
  48. package/src/api/v3/ui/viewport.ts +303 -0
  49. package/src/core/commands/index.ts +28 -6
  50. package/src/core/commands/list-commands.ts +3 -2
  51. package/src/core/commands/section-layout-commands.ts +9 -8
  52. package/src/core/schema/text-schema.ts +16 -0
  53. package/src/core/selection/mapping.ts +33 -72
  54. package/src/core/state/editor-state.ts +96 -189
  55. package/src/index.ts +23 -4
  56. package/src/io/chart-preview-resolver.ts +1 -1
  57. package/src/io/docx-session.ts +36 -4795
  58. package/src/io/export/build-app-properties-xml.ts +1 -1
  59. package/src/io/export/serialize-comments.ts +1 -1
  60. package/src/io/export/serialize-headers-footers.ts +6 -1
  61. package/src/io/export/serialize-main-document.ts +45 -0
  62. package/src/io/export/serialize-run-formatting.ts +17 -2
  63. package/src/io/export/twip.ts +1 -1
  64. package/src/io/normalize/normalize-text.ts +27 -20
  65. package/src/io/ooxml/chart/parse-series.ts +1 -1
  66. package/src/io/ooxml/chart/resolve-color.ts +2 -2
  67. package/src/io/ooxml/chart/types.ts +1 -1
  68. package/src/io/ooxml/classify-embedding.ts +83 -33
  69. package/src/io/ooxml/parse-fill.ts +1 -1
  70. package/src/io/ooxml/parse-main-document.ts +71 -1
  71. package/src/io/ooxml/parse-object.ts +14 -10
  72. package/src/io/ooxml/parse-run-formatting.ts +47 -1
  73. package/src/io/ooxml/property-grab-bag.ts +2 -2
  74. package/src/io/ooxml/units.ts +11 -0
  75. package/src/io/ooxml/workflow-payload.ts +282 -7
  76. package/src/model/anchor.ts +85 -0
  77. package/src/model/canonical-document.ts +351 -15
  78. package/src/model/chart-types.ts +1 -1
  79. package/src/model/layout/index.ts +83 -0
  80. package/src/model/layout/page-graph-types.ts +181 -0
  81. package/src/model/layout/page-layout-snapshot.ts +105 -0
  82. package/src/model/layout/resolved-layout-types.ts +47 -0
  83. package/src/model/layout/runtime-page-graph-types.ts +102 -0
  84. package/src/model/paragraph-scope-ids.ts +72 -0
  85. package/src/model/review/comment-types.ts +112 -0
  86. package/src/model/review/index.ts +2 -0
  87. package/src/model/review/revision-types.ts +215 -0
  88. package/src/model/snapshot.ts +32 -0
  89. package/src/review/store/comment-store.ts +21 -47
  90. package/src/review/store/revision-types.ts +40 -198
  91. package/src/runtime/collab/base-doc-fingerprint.ts +6 -1
  92. package/src/runtime/collab/runtime-collab-sync.ts +13 -3
  93. package/src/runtime/collab-session.ts +1 -1
  94. package/src/runtime/debug/build-debug-inspector-snapshot.ts +686 -0
  95. package/src/runtime/debug/event-ring-buffer.ts +64 -0
  96. package/src/runtime/debug/probability-sampler.ts +18 -0
  97. package/src/runtime/debug/runtime-debug-facet.ts +67 -0
  98. package/src/runtime/debug/stage-tokens.ts +31 -0
  99. package/src/runtime/debug/telemetry-bus.ts +271 -0
  100. package/src/runtime/debug/types.ts +275 -0
  101. package/src/runtime/debug/wrap-ref-for-telemetry.ts +118 -0
  102. package/src/runtime/document-layout.ts +8 -6
  103. package/src/runtime/document-runtime.ts +843 -1141
  104. package/src/runtime/document-search.ts +1 -1
  105. package/src/runtime/edit-ops/index.ts +1 -1
  106. package/src/runtime/external-send-runtime.ts +1 -1
  107. package/src/runtime/formatting/document-lookup.ts +235 -0
  108. package/src/runtime/formatting/field/registry.ts +41 -0
  109. package/src/runtime/{field-resolver.ts → formatting/field/resolver.ts} +27 -2
  110. package/src/runtime/formatting/font-resolution.ts +83 -0
  111. package/src/runtime/formatting/formatting-context.ts +903 -0
  112. package/src/runtime/formatting/formatting-types.ts +157 -0
  113. package/src/runtime/{hyperlink-color-resolver.ts → formatting/hyperlink-color.ts} +2 -2
  114. package/src/runtime/formatting/index.ts +125 -0
  115. package/src/runtime/{resolved-numbering-geometry.ts → formatting/numbering/geometry.ts} +1 -1
  116. package/src/runtime/{numbering-prefix.ts → formatting/numbering/prefix.ts} +170 -3
  117. package/src/runtime/formatting/paragraph-style-resolver.ts +92 -0
  118. package/src/runtime/formatting/projector.ts +75 -0
  119. package/src/runtime/formatting/resolve-effective.ts +407 -0
  120. package/src/runtime/formatting/revision-display.ts +105 -0
  121. package/src/runtime/{paragraph-style-resolver.ts → formatting/style-cascade.ts} +84 -141
  122. package/src/runtime/{table-style-resolver.ts → formatting/table-style-resolver.ts} +1 -1
  123. package/src/runtime/formatting/telemetry-bridge.ts +106 -0
  124. package/src/runtime/{theme-color-resolver.ts → formatting/theme-color.ts} +2 -30
  125. package/src/runtime/geometry/caret-geometry.ts +164 -0
  126. package/src/runtime/geometry/geometry-facet.ts +364 -0
  127. package/src/runtime/geometry/geometry-types.ts +256 -0
  128. package/src/runtime/geometry/hit-test.ts +125 -0
  129. package/src/runtime/geometry/index.ts +71 -0
  130. package/src/runtime/geometry/inert-geometry-facet.ts +43 -0
  131. package/src/runtime/geometry/invalidation.ts +35 -0
  132. package/src/runtime/geometry/object-handles.ts +77 -0
  133. package/src/runtime/geometry/overlay-rects.ts +85 -0
  134. package/src/runtime/geometry/project-anchors.ts +100 -0
  135. package/src/runtime/geometry/project-fragments.ts +216 -0
  136. package/src/runtime/geometry/projector.ts +129 -0
  137. package/src/runtime/geometry/replacement-envelope.ts +130 -0
  138. package/src/runtime/geometry/viewport.ts +218 -0
  139. package/src/runtime/layout/compat-input-ledger.ts +211 -0
  140. package/src/runtime/layout/index.ts +6 -1
  141. package/src/runtime/layout/inert-layout-facet.ts +12 -7
  142. package/src/runtime/layout/layout-engine-instance.ts +189 -11
  143. package/src/runtime/layout/layout-engine-version.ts +450 -1
  144. package/src/runtime/layout/layout-facet-types.ts +60 -0
  145. package/src/runtime/layout/layout-measurement-provider.ts +13 -0
  146. package/src/runtime/layout/measurement-backend-canvas.ts +14 -2
  147. package/src/runtime/layout/measurement-backend-empirical.ts +23 -4
  148. package/src/runtime/layout/page-graph.ts +62 -209
  149. package/src/runtime/layout/page-story-resolver.ts +7 -12
  150. package/src/runtime/layout/paginated-layout-engine.ts +186 -11
  151. package/src/runtime/layout/project-block-fragments.ts +11 -0
  152. package/src/runtime/layout/projector.ts +90 -0
  153. package/src/runtime/layout/public-facet.ts +187 -442
  154. package/src/runtime/layout/resolved-formatting-state.ts +158 -26
  155. package/src/runtime/layout/table-render-plan.ts +1 -1
  156. package/src/runtime/prerender/cache-envelope.ts +6 -1
  157. package/src/runtime/prerender/prerender-document.ts +18 -23
  158. package/src/runtime/render/decoration-resolver.ts +1 -1
  159. package/src/runtime/render/render-frame-types.ts +20 -0
  160. package/src/runtime/render/render-kernel.ts +94 -25
  161. package/src/runtime/scopes/_formatting-seam.ts +262 -0
  162. package/src/runtime/scopes/_scope-dependencies.ts +49 -0
  163. package/src/runtime/scopes/action-validation.ts +356 -0
  164. package/src/runtime/scopes/attach-explanation.ts +102 -0
  165. package/src/runtime/scopes/audit-bundle.ts +71 -0
  166. package/src/runtime/scopes/compile-scope-bundle.ts +163 -0
  167. package/src/runtime/scopes/compile-scope.ts +262 -0
  168. package/src/runtime/scopes/compiler-service.ts +431 -0
  169. package/src/runtime/scopes/create-issue.ts +107 -0
  170. package/src/runtime/scopes/enumerate-scopes.ts +543 -0
  171. package/src/runtime/scopes/evidence.ts +233 -0
  172. package/src/runtime/scopes/index.ts +150 -0
  173. package/src/runtime/scopes/position-map.ts +214 -0
  174. package/src/runtime/scopes/preservation-boundary.ts +91 -0
  175. package/src/runtime/scopes/projector.ts +49 -0
  176. package/src/runtime/scopes/replaceability.ts +87 -0
  177. package/src/runtime/scopes/replacement/apply.ts +228 -0
  178. package/src/runtime/scopes/replacement/compile.ts +59 -0
  179. package/src/runtime/scopes/replacement/propose.ts +42 -0
  180. package/src/runtime/scopes/resolve-reference.ts +347 -0
  181. package/src/runtime/scopes/review-bundle.ts +141 -0
  182. package/src/runtime/scopes/scope-kinds/_paragraph-text.ts +57 -0
  183. package/src/runtime/scopes/scope-kinds/_table-text.ts +42 -0
  184. package/src/runtime/scopes/scope-kinds/comment-thread.ts +59 -0
  185. package/src/runtime/scopes/scope-kinds/field.ts +65 -0
  186. package/src/runtime/scopes/scope-kinds/heading.ts +84 -0
  187. package/src/runtime/scopes/scope-kinds/list-item.ts +77 -0
  188. package/src/runtime/scopes/scope-kinds/paragraph.ts +182 -0
  189. package/src/runtime/scopes/scope-kinds/revision.ts +62 -0
  190. package/src/runtime/scopes/scope-kinds/table-cell.ts +57 -0
  191. package/src/runtime/scopes/scope-kinds/table-row.ts +61 -0
  192. package/src/runtime/scopes/scope-kinds/table.ts +55 -0
  193. package/src/runtime/scopes/scope-range.ts +208 -0
  194. package/src/runtime/scopes/semantic-scope-types.ts +454 -0
  195. package/src/runtime/scopes/workflow-overlap.ts +92 -0
  196. package/src/runtime/selection/index.ts +1 -1
  197. package/src/runtime/structure-ops/fragment-insert.ts +1 -1
  198. package/src/runtime/structure-ops/index.ts +1 -1
  199. package/src/runtime/surface-projection.ts +232 -262
  200. package/src/runtime/units.ts +4 -2
  201. package/src/runtime/workflow/coordinator.ts +1348 -0
  202. package/src/runtime/workflow/derived-scope-resolver.ts +125 -0
  203. package/src/runtime/workflow/index.ts +25 -0
  204. package/src/runtime/workflow/markup-mode-policy.ts +98 -0
  205. package/src/runtime/{workflow-markup.ts → workflow/markup.ts} +6 -6
  206. package/src/runtime/workflow/metadata-persistence.ts +306 -0
  207. package/src/runtime/workflow/metadata-writer.ts +123 -0
  208. package/src/runtime/workflow/overlay-store.ts +690 -0
  209. package/src/runtime/workflow/projector.ts +127 -0
  210. package/src/runtime/{query-scopes.ts → workflow/query-scopes.ts} +3 -3
  211. package/src/runtime/{workflow-rail-segments.ts → workflow/rail/compose.ts} +60 -165
  212. package/src/runtime/workflow/rail/types.ts +198 -0
  213. package/src/runtime/workflow/scope-rail-composer.ts +39 -0
  214. package/src/runtime/{scope-resolver.ts → workflow/scope-resolver.ts} +3 -3
  215. package/src/runtime/workflow/scope-writer.ts +188 -0
  216. package/src/runtime/{tamper-gate.ts → workflow/tamper-gate.ts} +1 -1
  217. package/src/runtime/workflow/visibility-policy.ts +129 -0
  218. package/src/session/_sync-legacy.ts +66 -0
  219. package/src/session/export/embedded-reconstitute.ts +104 -0
  220. package/src/session/export/export-diagnostics.ts +85 -0
  221. package/src/session/export/export-validation.ts +110 -0
  222. package/src/session/export/index.ts +34 -0
  223. package/src/session/export/preservation-reattach.ts +30 -0
  224. package/src/session/export/serialize-dispatch.ts +165 -0
  225. package/src/session/export/stateful-export-pipeline.ts +432 -0
  226. package/src/session/export/stateful-export.ts +684 -0
  227. package/src/session/import/canonical-assembly.ts +227 -0
  228. package/src/session/import/diagnostics-session.ts +54 -0
  229. package/src/session/import/embedded-discovery.ts +225 -0
  230. package/src/session/import/embedded-offload.ts +337 -0
  231. package/src/session/import/import-diagnostics.ts +69 -0
  232. package/src/session/import/loader-types.ts +313 -0
  233. package/src/session/import/loader.ts +1834 -0
  234. package/src/session/import/normalize.ts +195 -0
  235. package/src/session/import/package-parts.ts +217 -0
  236. package/src/session/import/package-read.ts +195 -0
  237. package/src/session/import/parse-orchestration.ts +105 -0
  238. package/src/session/import/part-constants.ts +70 -0
  239. package/src/session/import/part-discovery.ts +94 -0
  240. package/src/session/import/preservation-index.ts +46 -0
  241. package/src/{runtime/read-only-diagnostics-runtime.ts → session/import/read-only-diagnostics.ts} +24 -3
  242. package/src/session/import/review-import.ts +508 -0
  243. package/src/session/import/styles-consolidation.ts +281 -0
  244. package/src/session/import/workflow-scope-import.ts +256 -0
  245. package/src/session/index.ts +37 -0
  246. package/src/session/session-state.ts +69 -0
  247. package/src/session/session.ts +532 -0
  248. package/src/session/shared/protection.ts +228 -0
  249. package/src/session/shared/session-utils.ts +82 -0
  250. package/src/session/types.ts +499 -0
  251. package/src/shell/chart-snapshots.ts +96 -0
  252. package/src/shell/media-previews.ts +85 -0
  253. package/src/shell/overlay-anchor-bridge.ts +53 -0
  254. package/src/shell/paste-adapter.ts +23 -0
  255. package/src/shell/ref-commands.ts +1697 -0
  256. package/src/shell/ref-utilities.ts +48 -0
  257. package/src/shell/search.ts +51 -0
  258. package/src/{ui/editor-runtime-boundary.ts → shell/session-bootstrap.ts} +243 -67
  259. package/src/shell/ui-subscriber-channels.ts +81 -0
  260. package/src/shell/use-collab-sync.ts +116 -0
  261. package/src/ui/WordReviewEditor.tsx +496 -2051
  262. package/src/ui/editor-shell-view.tsx +30 -1
  263. package/src/ui/editor-surface-controller.tsx +49 -1
  264. package/src/ui/headless/revision-decoration-model.ts +83 -0
  265. package/src/{ui-tailwind/chrome → ui/headless}/role-action-sets.ts +1 -1
  266. package/src/ui/headless/scoped-chrome-policy.ts +2 -2
  267. package/src/ui/headless/selection-tool-context.ts +1 -1
  268. package/src/ui/headless/selection-tool-resolver.ts +1 -1
  269. package/src/ui/runtime-shortcut-dispatch.ts +46 -1
  270. package/src/ui/ui-controller-factory.ts +221 -0
  271. package/src/ui-tailwind/chart/ChartSurface.tsx +2 -2
  272. package/src/ui-tailwind/chart/layout/legend-layout.ts +1 -1
  273. package/src/ui-tailwind/chart/layout/plot-area.ts +2 -2
  274. package/src/ui-tailwind/chart/layout/title-layout.ts +1 -1
  275. package/src/ui-tailwind/chart/render/area.tsx +3 -3
  276. package/src/ui-tailwind/chart/render/bar-column.tsx +3 -3
  277. package/src/ui-tailwind/chart/render/bubble.tsx +3 -3
  278. package/src/ui-tailwind/chart/render/combo.tsx +2 -2
  279. package/src/ui-tailwind/chart/render/data-labels.tsx +2 -2
  280. package/src/ui-tailwind/chart/render/font-metrics.ts +2 -2
  281. package/src/ui-tailwind/chart/render/line.tsx +3 -3
  282. package/src/ui-tailwind/chart/render/pie.tsx +6 -6
  283. package/src/ui-tailwind/chart/render/scatter.tsx +3 -3
  284. package/src/ui-tailwind/chart/render/svg-primitives.ts +3 -3
  285. package/src/ui-tailwind/chart/render/unsupported.tsx +2 -2
  286. package/src/ui-tailwind/chrome/build-context-menu-entries.ts +88 -0
  287. package/src/ui-tailwind/chrome/chrome-preset-toolbar.tsx +1 -1
  288. package/src/ui-tailwind/chrome/collab-send-to-supplier-button.tsx +1 -1
  289. package/src/ui-tailwind/chrome/collab-tamper-banner.tsx +1 -1
  290. package/src/ui-tailwind/chrome/collab-top-nav-container.tsx +1 -1
  291. package/src/ui-tailwind/chrome/editor-action-registry.ts +553 -0
  292. package/src/ui-tailwind/chrome/editor-actions-to-palette.ts +182 -0
  293. package/src/ui-tailwind/chrome/local-surface-arbiter.ts +534 -0
  294. package/src/ui-tailwind/chrome/resolve-target-kind.ts +226 -0
  295. package/src/ui-tailwind/chrome/tw-alert-banner.tsx +38 -4
  296. package/src/ui-tailwind/chrome/tw-context-band.tsx +125 -0
  297. package/src/ui-tailwind/chrome/tw-context-menu-portal.tsx +248 -0
  298. package/src/ui-tailwind/chrome/tw-image-context-toolbar.tsx +42 -1
  299. package/src/ui-tailwind/chrome/tw-selection-anchor-resolver.ts +8 -7
  300. package/src/ui-tailwind/chrome/tw-selection-tool-blocked.tsx +38 -4
  301. package/src/ui-tailwind/chrome/tw-selection-tool-comment.tsx +104 -6
  302. package/src/ui-tailwind/chrome/tw-selection-tool-host.tsx +66 -7
  303. package/src/ui-tailwind/chrome/tw-selection-tool-workflow.tsx +54 -8
  304. package/src/ui-tailwind/chrome/tw-shortcut-hint.tsx +7 -1
  305. package/src/ui-tailwind/chrome/tw-suggestion-card.tsx +33 -0
  306. package/src/ui-tailwind/chrome/tw-table-context-toolbar.tsx +78 -1
  307. package/src/ui-tailwind/chrome/tw-table-grip-layer.tsx +16 -8
  308. package/src/ui-tailwind/chrome/tw-workspace-chrome-host.tsx +276 -0
  309. package/src/ui-tailwind/chrome/use-context-menu-controller.ts +201 -0
  310. package/src/ui-tailwind/chrome-overlay/chrome-overlay-projector.ts +1 -1
  311. package/src/ui-tailwind/chrome-overlay/tw-chrome-overlay.tsx +22 -4
  312. package/src/ui-tailwind/chrome-overlay/tw-comment-balloon-layer.tsx +1 -1
  313. package/src/ui-tailwind/chrome-overlay/tw-locked-block-layer.tsx +1 -1
  314. package/src/ui-tailwind/chrome-overlay/tw-object-selection-overlay.tsx +11 -5
  315. package/src/ui-tailwind/chrome-overlay/tw-page-stack-overlay-layer.tsx +197 -3
  316. package/src/ui-tailwind/chrome-overlay/tw-revision-margin-bar-layer.tsx +1 -1
  317. package/src/ui-tailwind/chrome-overlay/tw-scope-card-layer.tsx +35 -6
  318. package/src/ui-tailwind/chrome-overlay/tw-scope-rail-layer.tsx +24 -16
  319. package/src/ui-tailwind/chrome-overlay/tw-table-continuation-header.tsx +1 -1
  320. package/src/ui-tailwind/debug/README.md +57 -0
  321. package/src/ui-tailwind/debug/index.ts +3 -0
  322. package/src/ui-tailwind/debug/tw-debug-overlay.tsx +186 -0
  323. package/src/ui-tailwind/debug/tw-debug-presentation.tsx +80 -0
  324. package/src/ui-tailwind/debug/tw-debug-top-bar.tsx +83 -0
  325. package/src/ui-tailwind/editor-surface/chart-node-view.tsx +2 -2
  326. package/src/ui-tailwind/editor-surface/float-wrap-resolver.ts +1 -1
  327. package/src/ui-tailwind/editor-surface/pm-command-bridge.ts +135 -10
  328. package/src/ui-tailwind/editor-surface/pm-decorations.ts +40 -13
  329. package/src/ui-tailwind/editor-surface/pm-page-break-decorations.ts +1 -1
  330. package/src/ui-tailwind/editor-surface/pm-schema.ts +1 -1
  331. package/src/ui-tailwind/editor-surface/pm-state-from-snapshot.ts +3 -3
  332. package/src/ui-tailwind/editor-surface/predicted-tag-preflight.ts +1 -1
  333. package/src/ui-tailwind/editor-surface/remote-cursor-plugin.ts +2 -2
  334. package/src/ui-tailwind/editor-surface/scroll-anchor.ts +91 -9
  335. package/src/ui-tailwind/editor-surface/shape-renderer.ts +1 -1
  336. package/src/ui-tailwind/editor-surface/surface-layer.ts +1 -1
  337. package/src/ui-tailwind/editor-surface/tw-opaque-block.tsx +1 -1
  338. package/src/ui-tailwind/editor-surface/tw-page-block-view.helpers.ts +23 -6
  339. package/src/ui-tailwind/editor-surface/tw-prosemirror-surface.tsx +132 -22
  340. package/src/ui-tailwind/editor-surface/tw-table-node-view.tsx +1 -1
  341. package/src/ui-tailwind/index.ts +0 -5
  342. package/src/ui-tailwind/overlay-anchor-bridge-context.tsx +33 -0
  343. package/src/ui-tailwind/page-stack/floating-image-overlay-model.ts +66 -29
  344. package/src/ui-tailwind/page-stack/tw-floating-image-layer.tsx +25 -2
  345. package/src/ui-tailwind/review/comment-markdown-renderer.tsx +15 -0
  346. package/src/ui-tailwind/review/tw-review-rail.tsx +92 -4
  347. package/src/ui-tailwind/review/tw-workflow-tab.tsx +1 -1
  348. package/src/ui-tailwind/review-workspace/page-chrome.ts +210 -0
  349. package/src/ui-tailwind/review-workspace/page-shell-metrics.ts +101 -0
  350. package/src/ui-tailwind/review-workspace/paragraph-layout.ts +115 -0
  351. package/src/ui-tailwind/review-workspace/selection-toolbar-placement.ts +97 -0
  352. package/src/ui-tailwind/review-workspace/tw-review-workspace-navigator.tsx +130 -0
  353. package/src/ui-tailwind/review-workspace/tw-review-workspace-page-toolbar.tsx +240 -0
  354. package/src/ui-tailwind/review-workspace/tw-review-workspace-rail.tsx +59 -0
  355. package/src/ui-tailwind/review-workspace/types.ts +408 -0
  356. package/src/ui-tailwind/review-workspace/use-chrome-policy.ts +104 -0
  357. package/src/ui-tailwind/review-workspace/use-derived-view-state.ts +151 -0
  358. package/src/ui-tailwind/review-workspace/use-diagnostics-signal.ts +70 -0
  359. package/src/ui-tailwind/review-workspace/use-grabbed-segment-offsets.ts +40 -0
  360. package/src/ui-tailwind/review-workspace/use-layout-facet-render-signal.ts +55 -0
  361. package/src/ui-tailwind/review-workspace/use-page-markers.ts +130 -0
  362. package/src/ui-tailwind/review-workspace/use-pm-surface-capture.ts +60 -0
  363. package/src/ui-tailwind/review-workspace/use-review-rail-state.ts +63 -0
  364. package/src/ui-tailwind/review-workspace/use-scope-card-state.ts +170 -0
  365. package/src/ui-tailwind/review-workspace/use-scroll-root-capture.ts +28 -0
  366. package/src/ui-tailwind/review-workspace/use-selection-toolbar-placement.ts +113 -0
  367. package/src/ui-tailwind/review-workspace/use-shell-selection-anchor-bridge.ts +120 -0
  368. package/src/ui-tailwind/review-workspace/use-status-bar-page-facts.ts +55 -0
  369. package/src/ui-tailwind/review-workspace/use-viewport-dimensions.ts +43 -0
  370. package/src/ui-tailwind/review-workspace/use-workspace-arbiter.ts +25 -0
  371. package/src/ui-tailwind/review-workspace/use-workspace-composition.ts +86 -0
  372. package/src/ui-tailwind/review-workspace/use-workspace-side-effects.ts +150 -0
  373. package/src/ui-tailwind/theme/editor-theme.css +25 -0
  374. package/src/ui-tailwind/toolbar/tw-role-action-region.tsx +2 -2
  375. package/src/ui-tailwind/toolbar/tw-toolbar.tsx +61 -98
  376. package/src/ui-tailwind/tw-review-workspace.tsx +521 -1802
  377. package/src/ui-tailwind/ui-api-context.tsx +43 -0
  378. package/src/ui-tailwind/ui-shell-channels-context.tsx +49 -0
  379. package/src/validation/compatibility-engine.ts +6 -6
  380. package/src/runtime/styles-cascade.ts +0 -33
  381. package/src/ui-tailwind/chrome/tw-mode-dock.tsx +0 -85
  382. /package/src/runtime/{page-number-format.ts → formatting/field/page-number-format.ts} +0 -0
  383. /package/src/runtime/{ai-action-policy.ts → workflow/ai-action-policy.ts} +0 -0
  384. /package/src/runtime/{scope-tag-registry.ts → workflow/scope-tag-registry.ts} +0 -0
@@ -0,0 +1,105 @@
1
+ /**
2
+ * Layer 02 · layout data shapes used across api / runtime / session.
3
+ *
4
+ * Pass 2 of the L04/L02 `src/model/layout/` seam (see
5
+ * `docs/plans/cross-layer-coord-04.md §1.12`). Previously these three
6
+ * types lived in `src/api/public-types.ts`; relocating them here lets
7
+ * the runtime-owned layout graph (`RuntimePageGraph`) reference them
8
+ * from a location that does not forbid transit by session / stateless
9
+ * services. `src/api/public-types.ts` continues to re-export these
10
+ * shapes so every consumer's import path remains `@beyondwork/...api`.
11
+ *
12
+ * These are pure data: no methods, no higher-layer imports. The
13
+ * acceptance rule at `src/model/layout/index.ts` applies.
14
+ */
15
+
16
+ /**
17
+ * Runtime-derived description of page layout, projected from
18
+ * `CanonicalDocument` `SectionProperties` + ambient defaults.
19
+ */
20
+ export interface PageLayoutSnapshot {
21
+ sectionIndex: number;
22
+ sectionType?: "continuous" | "nextPage" | "evenPage" | "oddPage" | "nextColumn";
23
+ pageWidth: number;
24
+ pageHeight: number;
25
+ marginTop: number;
26
+ marginBottom: number;
27
+ marginLeft: number;
28
+ marginRight: number;
29
+ headerMargin: number;
30
+ footerMargin: number;
31
+ gutter: number;
32
+ orientation: "portrait" | "landscape";
33
+ columns: number;
34
+ differentFirstPage: boolean;
35
+ differentOddEvenPages: boolean;
36
+ pageNumbering?: {
37
+ format?: string;
38
+ start?: number;
39
+ chapterStyle?: string;
40
+ chapterSeparator?: string;
41
+ };
42
+ lineNumbering?: {
43
+ countBy?: number;
44
+ start?: number;
45
+ distance?: number;
46
+ restart?: "newPage" | "newSection" | "continuous";
47
+ };
48
+ pageBorders?: {
49
+ top?: { value?: string; size?: number; space?: number; color?: string };
50
+ left?: { value?: string; size?: number; space?: number; color?: string };
51
+ bottom?: { value?: string; size?: number; space?: number; color?: string };
52
+ right?: { value?: string; size?: number; space?: number; color?: string };
53
+ offsetFrom?: "page" | "text";
54
+ display?: "allPages" | "firstPage" | "notFirstPage";
55
+ zOrder?: "front" | "back";
56
+ };
57
+ documentGrid?: {
58
+ type?: "default" | "lines" | "linesAndChars" | "snapToChars";
59
+ linePitch?: number;
60
+ charSpace?: number;
61
+ };
62
+ columnDefinitions: Array<{ width: number; space?: number }>;
63
+ equalWidthColumns: boolean;
64
+ columnSeparator: boolean;
65
+ headerVariants: Array<{ variant: "default" | "first" | "even"; relationshipId: string }>;
66
+ footerVariants: Array<{ variant: "default" | "first" | "even"; relationshipId: string }>;
67
+ }
68
+
69
+ /**
70
+ * Identifies which story / surface a read or edit addresses.
71
+ */
72
+ export type EditorStoryTarget =
73
+ | { kind: "main" }
74
+ | {
75
+ kind: "header";
76
+ relationshipId: string;
77
+ variant: "default" | "first" | "even";
78
+ sectionIndex?: number;
79
+ }
80
+ | {
81
+ kind: "footer";
82
+ relationshipId: string;
83
+ variant: "default" | "first" | "even";
84
+ sectionIndex?: number;
85
+ }
86
+ | { kind: "footnote"; noteId: string }
87
+ | { kind: "endnote"; noteId: string };
88
+
89
+ /**
90
+ * Runtime-derived descriptor for a single logical page.
91
+ */
92
+ export interface DocumentPageSnapshot {
93
+ /** Zero-based page index within the whole document. */
94
+ pageIndex: number;
95
+ /** Section that owns this page (zero-based). */
96
+ sectionIndex: number;
97
+ /** Zero-based page index within its owning section. */
98
+ pageInSection: number;
99
+ /** Estimated character offset where the page begins in the main story. */
100
+ startOffset: number;
101
+ /** Estimated character offset where the page ends in the main story. */
102
+ endOffset: number;
103
+ /** Page layout properties inherited from the section. */
104
+ layout: PageLayoutSnapshot;
105
+ }
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Layer 02 · resolved-layout data shapes.
3
+ *
4
+ * Pass 2 (2026-04-22) — these two types moved out of
5
+ * `src/runtime/layout/page-story-resolver.ts` and
6
+ * `src/runtime/document-layout.ts` respectively. Both are pure data
7
+ * shapes: no methods, no runtime-only imports. Living in the model
8
+ * tree lets `RuntimePageGraph` (next step) live here as well, which
9
+ * in turn lets `CacheEnvelope` drop its transit through
10
+ * `src/runtime/**` (per `docs/plans/cross-layer-coord-04.md §1.12`
11
+ * and Layer 01's §1 ask).
12
+ *
13
+ * The resolver function and section builder remain in their runtime
14
+ * homes; only the type definitions move, and those files continue to
15
+ * re-export them so existing consumer imports remain stable.
16
+ */
17
+
18
+ import type { SectionProperties } from "../canonical-document.ts";
19
+ import type { EditorStoryTarget } from "./page-layout-snapshot.ts";
20
+
21
+ /**
22
+ * Per-page story resolution — which header/footer variant applies on
23
+ * this page, and what the effective page number is.
24
+ */
25
+ export interface ResolvedPageStories {
26
+ /** Header story target for this page, if any. */
27
+ header?: EditorStoryTarget;
28
+ /** Footer story target for this page, if any. */
29
+ footer?: EditorStoryTarget;
30
+ /** Whether this is a "first page" in its section (title page behavior). */
31
+ isFirstPage: boolean;
32
+ /** Whether this is an even-numbered page (1-indexed for display). */
33
+ isEvenPage: boolean;
34
+ /** The effective page number for display (accounting for page numbering settings). */
35
+ displayPageNumber: number;
36
+ }
37
+
38
+ /**
39
+ * Resolved section metadata — where a section begins and ends in the
40
+ * flattened offset space, plus the section-properties payload.
41
+ */
42
+ export interface ResolvedDocumentSection {
43
+ index: number;
44
+ start: number;
45
+ end: number;
46
+ properties?: SectionProperties;
47
+ }
@@ -0,0 +1,102 @@
1
+ /**
2
+ * Layer 02 · runtime page-graph types.
3
+ *
4
+ * Pass 2 (2026-04-22) — `RuntimePageGraph`, `RuntimePageNode`, and
5
+ * `BuildPageGraphInput` moved out of `src/runtime/layout/page-graph.ts`
6
+ * per `docs/plans/cross-layer-coord-04.md §1.12`. Relocation unblocks
7
+ * Layer 01's `CacheEnvelope` transit (the type chain from
8
+ * `CacheEnvelope → RuntimePageGraph → PageLayoutSnapshot / ...` no
9
+ * longer routes through `src/runtime/**`).
10
+ *
11
+ * These are pure data shapes: no methods, no runtime-only imports.
12
+ * The graph's construction functions (`buildPageGraph`, `spliceGraph`)
13
+ * and the `graphRevision` module-local counter remain in the runtime
14
+ * layer (`src/runtime/layout/page-graph.ts`).
15
+ */
16
+
17
+ import type {
18
+ RuntimeBlockFragment,
19
+ RuntimeLineBox,
20
+ RuntimeNoteAllocation,
21
+ RuntimePageAnchor,
22
+ RuntimePageRegions,
23
+ } from "./page-graph-types.ts";
24
+ import type {
25
+ DocumentPageSnapshot,
26
+ PageLayoutSnapshot,
27
+ } from "./page-layout-snapshot.ts";
28
+ import type {
29
+ ResolvedDocumentSection,
30
+ ResolvedPageStories,
31
+ } from "./resolved-layout-types.ts";
32
+
33
+ /**
34
+ * A stable, inspectable representation of the document's paginated
35
+ * structure. Produced by the `PaginatedLayoutEngine` from canonical
36
+ * document state. External read models such as
37
+ * `DocumentNavigationSnapshot` and `PageLayoutSnapshot` are derived
38
+ * from it.
39
+ */
40
+ export interface RuntimePageGraph {
41
+ /** Monotonically increasing revision stamp. */
42
+ revision: number;
43
+ /** Ordered page nodes. */
44
+ pages: RuntimePageNode[];
45
+ /** Flat list of every block fragment produced during pagination. */
46
+ fragments: RuntimeBlockFragment[];
47
+ /** Per-offset anchor index for O(log n) lookup. */
48
+ anchors: RuntimePageAnchor[];
49
+ /** Section metadata. */
50
+ sections: ResolvedDocumentSection[];
51
+ /** Total non-blank page count. */
52
+ contentPageCount: number;
53
+ }
54
+
55
+ export interface RuntimePageNode {
56
+ pageId: string;
57
+ pageIndex: number;
58
+ sectionIndex: number;
59
+ pageInSection: number;
60
+ startOffset: number;
61
+ endOffset: number;
62
+ layout: PageLayoutSnapshot;
63
+ stories: ResolvedPageStories;
64
+ /** Sub-regions on the page. */
65
+ regions: RuntimePageRegions;
66
+ /** Line boxes rendered in the body region. */
67
+ lineBoxes: RuntimeLineBox[];
68
+ /** Footnote allocations reserved at the bottom of the page. */
69
+ noteAllocations: RuntimeNoteAllocation[];
70
+ /** Whether this page is a blank filler (from even/odd page breaks). */
71
+ isBlankFiller: boolean;
72
+ }
73
+
74
+ export interface BuildPageGraphInput {
75
+ pages: readonly DocumentPageSnapshot[];
76
+ sections: readonly ResolvedDocumentSection[];
77
+ stories: readonly ResolvedPageStories[];
78
+ /** Optional block fragments pre-computed by pagination; when omitted the
79
+ * graph produces one fragment per page spanning its entire offset range. */
80
+ fragments?: readonly RuntimeBlockFragment[];
81
+ /**
82
+ * Optional block fragments keyed by pageIndex with the `pageId` omitted.
83
+ * `buildPageGraph` fills in the pageId using the graph's fresh revision
84
+ * stamp. Use this when the caller wants to emit per-block fragments but
85
+ * cannot know the pageId in advance.
86
+ */
87
+ fragmentsByPageIndex?: ReadonlyMap<
88
+ number,
89
+ ReadonlyArray<Omit<RuntimeBlockFragment, "pageId">>
90
+ >;
91
+ /** Optional per-page line boxes. */
92
+ lineBoxes?: ReadonlyMap<string, RuntimeLineBox[]>;
93
+ /** Optional per-page note allocations keyed by graph-assigned pageId. */
94
+ noteAllocations?: ReadonlyMap<string, RuntimeNoteAllocation[]>;
95
+ /**
96
+ * P8 — per-page note allocations keyed by pageIndex (0-based).
97
+ * Parallel to `fragmentsByPageIndex`; `buildPageGraph` uses the index to
98
+ * look up allocations without requiring callers to know the graph-internal
99
+ * `page-${revision}-${index}` pageId in advance.
100
+ */
101
+ noteAllocationsByPageIndex?: ReadonlyMap<number, RuntimeNoteAllocation[]>;
102
+ }
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Paragraph scope-id minting — neutral home shared by L06 (workflow /
3
+ * metadata writer) and L08 (semantic scope enumerator).
4
+ *
5
+ * The enumerator at `src/runtime/scopes/enumerate-scopes.ts` and the
6
+ * derived-scope resolver at `src/runtime/workflow/derived-scope-resolver.ts`
7
+ * must produce identical scopeIds for the same (paragraph, blockIndex)
8
+ * pair — the enumerator mints them for the outward surface, the
9
+ * resolver matches them on the inverse path for metadata writes. Both
10
+ * lanes' files sit in W9-purity-guarded trees, so the logic lives here
11
+ * (in L02's neutral `src/model/` home) to keep both imports legal.
12
+ *
13
+ * Rules are purely shape-derived from `ParagraphNode` — no runtime,
14
+ * no overlay, no layout. Safe to import from anywhere.
15
+ */
16
+
17
+ import type { ParagraphNode } from "./canonical-document.ts";
18
+
19
+ /**
20
+ * Classify a paragraph as `paragraph` / `heading` / `list-item` using
21
+ * outlineLevel → heading style → numbering precedence. The enumerator
22
+ * and the derived-scope resolver both call this so their scopeIds
23
+ * agree on kind.
24
+ */
25
+ export function detectParagraphKind(
26
+ paragraph: ParagraphNode,
27
+ ): "paragraph" | "heading" | "list-item" {
28
+ if (
29
+ typeof paragraph.outlineLevel === "number" &&
30
+ paragraph.outlineLevel >= 0 &&
31
+ paragraph.outlineLevel <= 8
32
+ ) {
33
+ return "heading";
34
+ }
35
+ if (
36
+ typeof paragraph.styleId === "string" &&
37
+ /^heading\d$/i.test(paragraph.styleId)
38
+ ) {
39
+ return "heading";
40
+ }
41
+ if (paragraph.numbering) {
42
+ return "list-item";
43
+ }
44
+ return "paragraph";
45
+ }
46
+
47
+ /**
48
+ * Mint the derived scopeId for a paragraph. `wordExtensionIds.paraId`
49
+ * (the w14:paraId attribute) wins when present — it's stable across
50
+ * reopen but carries no kind information, so the kind prefix
51
+ * disambiguates. Kind-less bare paraIds would collide with
52
+ * marker-backed overlay scopeIds; the prefix prevents that.
53
+ */
54
+ export function buildParagraphScopeId(
55
+ kind: "paragraph" | "heading" | "list-item",
56
+ blockIndex: number,
57
+ paragraph: ParagraphNode,
58
+ ): string {
59
+ const paraId = paragraph.wordExtensionIds?.paraId;
60
+ if (kind === "heading") {
61
+ if (paraId) return `heading:${paraId}`;
62
+ return `heading:${paragraph.outlineLevel ?? 0}:${blockIndex}`;
63
+ }
64
+ if (kind === "list-item") {
65
+ if (paraId) return `li:${paraId}`;
66
+ const inst = paragraph.numbering?.numberingInstanceId ?? "u";
67
+ const lvl = paragraph.numbering?.level ?? 0;
68
+ return `li:${inst}:${lvl}:${blockIndex}`;
69
+ }
70
+ if (paraId) return `para:${paraId}`;
71
+ return `para:${blockIndex}`;
72
+ }
@@ -0,0 +1,112 @@
1
+ /**
2
+ * Pure shapes for comment threads on a CanonicalDocument.
3
+ *
4
+ * Like the revision types next door, these describe what exists on the
5
+ * document, not the store operations that mutate them. The review layer's
6
+ * `src/review/store/comment-store.ts` used to own these definitions; it
7
+ * now re-exports from here so the session layer can consume them via the
8
+ * model without crossing the P6 boundary.
9
+ *
10
+ * Store constructors (`createCommentStore`, `upsertCommentThread`, ...),
11
+ * the remap engine, and the sidebar projection all remain in
12
+ * `src/review/store/comment-store.ts` — they are runtime-state operations.
13
+ */
14
+
15
+ import type { EditorAnchorProjection } from "../anchor.ts";
16
+
17
+ export type CommentAnchor = EditorAnchorProjection;
18
+ export type CommentAnchorState = "active" | "detached";
19
+
20
+ export interface CommentAnchorSummary {
21
+ anchor: CommentAnchor;
22
+ state: CommentAnchorState;
23
+ range: import("../anchor.ts").DocRange;
24
+ }
25
+
26
+ export interface CommentEntry {
27
+ entryId: string;
28
+ authorId: string;
29
+ body: string;
30
+ createdAt: string;
31
+ metadata?: CommentEntryMetadata;
32
+ }
33
+
34
+ export interface CommentEntryMetadata {
35
+ ooxmlCommentId?: string;
36
+ paraId?: string;
37
+ parentParaId?: string;
38
+ durableId?: string;
39
+ initials?: string;
40
+ }
41
+
42
+ export interface CommentResolution {
43
+ resolvedAt: string;
44
+ resolvedBy: string;
45
+ }
46
+
47
+ export type CommentThreadStatus = "open" | "resolved" | "detached";
48
+
49
+ export interface CommentThread {
50
+ commentId: string;
51
+ anchor: CommentAnchor;
52
+ status: CommentThreadStatus;
53
+ entries: CommentEntry[];
54
+ createdBy: string;
55
+ createdAt: string;
56
+ resolution?: CommentResolution;
57
+ warningIds: string[];
58
+ metadata?: CommentThreadMetadata;
59
+ }
60
+
61
+ export interface CommentThreadMetadata {
62
+ source?: "runtime" | "import";
63
+ rootOoxmlCommentId?: string;
64
+ rootParaId?: string;
65
+ detachedReason?: "incomplete-markers" | "multi-paragraph" | "opaque-region" | "revision-overlap";
66
+ actionabilityNote?: string;
67
+ }
68
+
69
+ export interface CommentStore {
70
+ version: "comment-store/1";
71
+ threads: Record<string, CommentThread>;
72
+ }
73
+
74
+ /**
75
+ * Pure projection from the canonical-document's loose `CommentThread`
76
+ * shape (src/model/canonical-document.ts — optional entries / createdBy
77
+ * / body fields, status uncorrelated with anchor.kind) to the review-layer
78
+ * strict `CommentThread` shape defined above (required entries + status
79
+ * correlated with a detached anchor).
80
+ *
81
+ * Mirrors the runtime-comment-store `toCommentThread` defaults without
82
+ * importing from core. Session-layer code paths consume this directly so
83
+ * they can produce review-shape threads without reaching into
84
+ * `src/review/store/**`.
85
+ */
86
+ export function toReviewCommentThread(
87
+ source: import("../canonical-document.ts").CommentThread,
88
+ ): CommentThread {
89
+ const status: CommentThreadStatus =
90
+ source.anchor.kind === "detached"
91
+ ? "detached"
92
+ : source.status === "resolved"
93
+ ? "resolved"
94
+ : "open";
95
+ return {
96
+ commentId: source.commentId,
97
+ anchor: source.anchor,
98
+ status,
99
+ entries: source.entries ?? [],
100
+ createdBy: source.createdBy ?? source.authorId ?? "unknown",
101
+ createdAt: source.createdAt,
102
+ resolution: source.resolution,
103
+ warningIds: [...(source.warningIds ?? [])],
104
+ metadata: source.metadata,
105
+ };
106
+ }
107
+
108
+ export function commentRecordsToReviewThreads(
109
+ comments: Record<string, import("../canonical-document.ts").CommentThread>,
110
+ ): CommentThread[] {
111
+ return Object.values(comments).map(toReviewCommentThread);
112
+ }
@@ -0,0 +1,2 @@
1
+ export * from "./revision-types.ts";
2
+ export * from "./comment-types.ts";
@@ -0,0 +1,215 @@
1
+ /**
2
+ * Pure shapes for tracked-change revisions on a CanonicalDocument.
3
+ *
4
+ * Revisions are model-level data (what exists on the document), not
5
+ * runtime state (what the review store does with them). The review
6
+ * layer's store at `src/review/store/revision-types.ts` used to own
7
+ * these types; it now re-exports from here so the session layer (which
8
+ * cannot import from `src/review/**`) can consume the types via the
9
+ * model layer.
10
+ *
11
+ * Anchor-constructor helpers (`createRevisionRangeAnchor`, `remapRevisionAnchor`,
12
+ * etc.) + store-oriented predicates that cross into mapping mechanics
13
+ * remain in review/store. Pure classifiers (`getRevisionActionability`,
14
+ * `isRevisionActionable`, `describeRevisionKind`) live here — they only
15
+ * inspect data.
16
+ */
17
+
18
+ import type { EditorAnchorProjection } from "../anchor.ts";
19
+ import type { RevisionStoryTargetRecord } from "../canonical-document.ts";
20
+
21
+ export type RevisionAnchor = EditorAnchorProjection;
22
+
23
+ export type SupportedRevisionKind = "insertion" | "deletion" | "property-change";
24
+ export type PreserveOnlyRevisionKind = "formatting" | "move";
25
+ export type RevisionKind = SupportedRevisionKind | PreserveOnlyRevisionKind;
26
+
27
+ export type RevisionStatus = "active" | "accepted" | "rejected" | "detached";
28
+ export type RevisionActionability = "actionable" | "preserve-only";
29
+ export type RevisionAnchorState = "active" | "detached";
30
+
31
+ export interface PropertyChangeData {
32
+ xmlTag: "pPrChange" | "sectPrChange" | "tblPrChange" | "rPrChange";
33
+ beforeXml: string;
34
+ }
35
+
36
+ export interface MoveData {
37
+ moveId: string;
38
+ direction: "from" | "to";
39
+ linkedRevisionId?: string;
40
+ }
41
+
42
+ /**
43
+ * Payload for `w:cellMerge` revisions. `direction` is the `w:vMerge`
44
+ * attribute on the marker:
45
+ * `"rest"` — this cell begins a vertical merge span (restart cell).
46
+ * `"cont"` — this cell continues a vertical merge span.
47
+ *
48
+ * Accept commits `TableCellNode.verticalMerge` to the matching state;
49
+ * reject clears `verticalMerge` to undefined. No row topology changes
50
+ * (mirrors LibreOffice's treatment — vMerge is a rendering property, not
51
+ * a structural mutation).
52
+ */
53
+ export interface CellMergeData {
54
+ direction: "rest" | "cont";
55
+ }
56
+
57
+ /**
58
+ * Ordinal coordinates of a structural table revision within the canonical
59
+ * document tree.
60
+ *
61
+ * Lane 7b row-insertion revisions (`<w:trPr><w:ins/></w:trPr>`) point at an
62
+ * entire row, not a text range — the runtime anchor position alone can't
63
+ * identify which row to remove on reject. This envelope carries the table's
64
+ * ordinal (the Nth `<w:tbl>` in the body) and the row's index within that
65
+ * table, both fixed at parse time. Accept/reject resolves these to a
66
+ * canonical-document `tableBlockIndex` by walking `doc.content.children[]`
67
+ * at action time.
68
+ */
69
+ export interface TableRevisionCoordinates {
70
+ tableOrdinal: number;
71
+ rowIndex: number;
72
+ /**
73
+ * Cell index within `row.cells[]`. Present on cell-level structural
74
+ * revisions (`cellIns` / `cellDel` / `cellMerge`); `undefined` on
75
+ * row-level records (`row-ins` / `row-del`).
76
+ */
77
+ cellIndex?: number;
78
+ /**
79
+ * For revisions inside nested tables (a `<w:tbl>` inside a cell), this
80
+ * carries the full ordinal path so `resolveCanonicalTableRow` can
81
+ * tree-walk the canonical document:
82
+ * `[bodyTableOrdinal, nestedTableIndex, ...]`
83
+ * Body-level revisions omit this field and use the flat `tableOrdinal`.
84
+ * Lane 7b Phase Q.
85
+ */
86
+ tableOrdinalPath?: readonly number[];
87
+ }
88
+
89
+ export interface RevisionMetadataEnvelope {
90
+ source: "runtime" | "import";
91
+ storyTarget?: RevisionStoryTargetRecord;
92
+ preserveOnlyReason?: string;
93
+ suggestionId?: string;
94
+ semanticKind?:
95
+ | "insertion"
96
+ | "deletion"
97
+ | "replacement"
98
+ | "formatting-change"
99
+ | "paragraph-property-change"
100
+ | "structural-change"
101
+ | "object-change";
102
+ linkedRevisionIds?: string[];
103
+ predecessorSuggestionId?: string;
104
+ importedRevisionForm?:
105
+ | "run-insertion"
106
+ | "run-deletion"
107
+ | "paragraph-insertion"
108
+ | "paragraph-deletion";
109
+ originalRevisionType?: string;
110
+ ooxmlRevisionId?: string;
111
+ propertyChangeData?: PropertyChangeData;
112
+ moveData?: MoveData;
113
+ cellMergeData?: CellMergeData;
114
+ tableRevisionCoordinates?: TableRevisionCoordinates;
115
+ }
116
+
117
+ export type PropertyChangeRevision = RevisionRecord & {
118
+ kind: "property-change";
119
+ metadata: RevisionMetadataEnvelope & { propertyChangeData: PropertyChangeData };
120
+ };
121
+
122
+ export type MoveRevision = RevisionRecord & {
123
+ kind: "move";
124
+ metadata: RevisionMetadataEnvelope & { moveData: MoveData };
125
+ };
126
+
127
+ export interface RevisionRecord {
128
+ revisionId: string;
129
+ kind: RevisionKind;
130
+ anchor: RevisionAnchor;
131
+ authorId: string;
132
+ createdAt: string;
133
+ status: RevisionStatus;
134
+ warningIds: string[];
135
+ metadata: RevisionMetadataEnvelope;
136
+ }
137
+
138
+ export interface RevisionAnchorSummary {
139
+ anchor: RevisionAnchor;
140
+ state: RevisionAnchorState;
141
+ range: import("../anchor.ts").DocRange;
142
+ }
143
+
144
+ export function getRevisionActionability(
145
+ revision:
146
+ | RevisionKind
147
+ | Pick<RevisionRecord, "kind" | "metadata">,
148
+ ): RevisionActionability {
149
+ // Lane 7b promotions run BEFORE the preserveOnlyReason check on purpose:
150
+ // `createRevisionRecord` injects a default "Imported preserve-only revision."
151
+ // reason for any kind that `getRevisionActionability(kind)` returns as
152
+ // preserve-only (see revision-store.ts), which covers both `kind: "move"`
153
+ // and `kind: "formatting"`. The overrides below flip the default back to
154
+ // actionable for the specific shapes that Lane 7b promoted: cellIns
155
+ // structural-table revisions, and linked-pair move revisions. Do not add a
156
+ // `&& !preserveOnlyReason` guard here — that would re-lock these shapes
157
+ // against the injected default and regress 7b.
158
+ if (
159
+ typeof revision !== "string" &&
160
+ (revision.metadata.originalRevisionType === "cellIns" ||
161
+ revision.metadata.originalRevisionType === "cellDel" ||
162
+ revision.metadata.originalRevisionType === "cellMerge")
163
+ ) {
164
+ return "actionable";
165
+ }
166
+
167
+ if (
168
+ typeof revision !== "string" &&
169
+ revision.kind === "move" &&
170
+ typeof revision.metadata.moveData?.linkedRevisionId === "string" &&
171
+ revision.metadata.moveData.linkedRevisionId.length > 0
172
+ ) {
173
+ return "actionable";
174
+ }
175
+
176
+ if (
177
+ typeof revision !== "string" &&
178
+ typeof revision.metadata.preserveOnlyReason === "string" &&
179
+ revision.metadata.preserveOnlyReason.length > 0
180
+ ) {
181
+ return "preserve-only";
182
+ }
183
+
184
+ const kind = typeof revision === "string" ? revision : revision.kind;
185
+ switch (kind) {
186
+ case "insertion":
187
+ case "deletion":
188
+ case "property-change":
189
+ return "actionable";
190
+ case "formatting":
191
+ case "move":
192
+ return "preserve-only";
193
+ }
194
+ }
195
+
196
+ export function isRevisionActionable(
197
+ record: Pick<RevisionRecord, "kind" | "metadata" | "status">,
198
+ ): boolean {
199
+ return getRevisionActionability(record) === "actionable" && record.status === "active";
200
+ }
201
+
202
+ export function describeRevisionKind(kind: RevisionKind): string {
203
+ switch (kind) {
204
+ case "insertion":
205
+ return "Insertion";
206
+ case "deletion":
207
+ return "Deletion";
208
+ case "formatting":
209
+ return "Formatting change";
210
+ case "move":
211
+ return "Move";
212
+ case "property-change":
213
+ return "Property change";
214
+ }
215
+ }