@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,543 @@
1
+ /**
2
+ * Slice 1+2 enumeration — walks the canonical document and yields one
3
+ * `EnumeratedScope` per paragraph, heading, list-item, table, table-row,
4
+ * table-cell, field, comment-thread, or revision.
5
+ *
6
+ * ## Generic substrate (post 2026-04-22 taxonomy-genericization pass)
7
+ *
8
+ * The compiler does NOT carry any vertical vocabulary in its kind
9
+ * taxonomy. A paragraph that a host has wrapped in a marker-backed
10
+ * overlay scope (for example a CLM clause marker) stays `kind:
11
+ * "paragraph"` — but its `provenance` is `"marker-backed"` and the
12
+ * compiler propagates the overlay's metadata as generic `classifications`
13
+ * on the compiled scope. Hosts read classifications to drive
14
+ * vertical behaviour (CLM legal clause treatment, compliance
15
+ * annotations, etc.) without the compiler encoding that vocabulary.
16
+ *
17
+ * See `docs/wiki/use-case-domains/clm/semantic-scope-usage.md` for the
18
+ * CLM worked example.
19
+ *
20
+ * S3 (determinism): for identical inputs this function yields an
21
+ * identical handle sequence. Handle ids derive from structural position;
22
+ * no ambient state, no timestamps, no random ids.
23
+ */
24
+
25
+ import type {
26
+ CanonicalDocument,
27
+ CommentThread,
28
+ DocumentRootNode,
29
+ FieldNode,
30
+ InlineNode,
31
+ ParagraphNode,
32
+ RevisionRecord,
33
+ TableCellNode,
34
+ TableNode,
35
+ TableRowNode,
36
+ } from "../../model/canonical-document.ts";
37
+ import {
38
+ buildParagraphScopeId,
39
+ detectParagraphKind,
40
+ } from "../../model/paragraph-scope-ids.ts";
41
+ export {
42
+ buildParagraphScopeId,
43
+ detectParagraphKind,
44
+ } from "../../model/paragraph-scope-ids.ts";
45
+ import type { CanonicalDocumentEnvelope } from "../../core/state/editor-state.ts";
46
+ import type {
47
+ WorkflowOverlay,
48
+ WorkflowScope,
49
+ WorkflowScopeMetadataField,
50
+ } from "./_scope-dependencies.ts";
51
+
52
+ import type { ScopeHandle, SemanticScopeKind } from "./semantic-scope-types.ts";
53
+
54
+ const MAIN_STORY = { kind: "main" as const };
55
+
56
+ /**
57
+ * Paragraph-bearing variant — paragraph / heading / list-item.
58
+ *
59
+ * Classifications are collected from the overlay scope the paragraph
60
+ * belongs to (if marker-backed). Empty array when no overlay match.
61
+ */
62
+ export interface ParagraphLikeEnumeratedScope {
63
+ readonly kind: "paragraph" | "heading" | "list-item";
64
+ readonly handle: ScopeHandle;
65
+ readonly paragraph: ParagraphNode;
66
+ readonly blockIndex: number;
67
+ readonly classifications: readonly string[];
68
+ }
69
+
70
+ export interface TableEnumeratedScope {
71
+ readonly kind: "table";
72
+ readonly handle: ScopeHandle;
73
+ readonly table: TableNode;
74
+ readonly blockIndex: number;
75
+ readonly classifications: readonly string[];
76
+ }
77
+
78
+ export interface TableRowEnumeratedScope {
79
+ readonly kind: "table-row";
80
+ readonly handle: ScopeHandle;
81
+ readonly row: TableRowNode;
82
+ readonly table: TableNode;
83
+ readonly blockIndex: number;
84
+ readonly rowIndex: number;
85
+ readonly classifications: readonly string[];
86
+ }
87
+
88
+ export interface TableCellEnumeratedScope {
89
+ readonly kind: "table-cell";
90
+ readonly handle: ScopeHandle;
91
+ readonly cell: TableCellNode;
92
+ readonly row: TableRowNode;
93
+ readonly table: TableNode;
94
+ readonly blockIndex: number;
95
+ readonly rowIndex: number;
96
+ readonly cellIndex: number;
97
+ readonly classifications: readonly string[];
98
+ }
99
+
100
+ export interface FieldEnumeratedScope {
101
+ readonly kind: "field";
102
+ readonly handle: ScopeHandle;
103
+ readonly field: FieldNode;
104
+ readonly paragraph: ParagraphNode;
105
+ readonly blockIndex: number;
106
+ readonly inlineIndex: number;
107
+ readonly classifications: readonly string[];
108
+ }
109
+
110
+ export interface CommentThreadEnumeratedScope {
111
+ readonly kind: "comment-thread";
112
+ readonly handle: ScopeHandle;
113
+ readonly thread: CommentThread;
114
+ readonly classifications: readonly string[];
115
+ }
116
+
117
+ export interface RevisionEnumeratedScope {
118
+ readonly kind: "revision";
119
+ readonly handle: ScopeHandle;
120
+ readonly revision: RevisionRecord;
121
+ readonly classifications: readonly string[];
122
+ }
123
+
124
+ /**
125
+ * Discriminated by `kind`. Paragraph-bearing entries carry `paragraph`;
126
+ * table-bearing entries carry the matching canonical node; field entries
127
+ * carry the inline `FieldNode` + containing paragraph; review-store
128
+ * entries carry the thread / revision record directly.
129
+ */
130
+ export type EnumeratedScope =
131
+ | ParagraphLikeEnumeratedScope
132
+ | TableEnumeratedScope
133
+ | TableRowEnumeratedScope
134
+ | TableCellEnumeratedScope
135
+ | FieldEnumeratedScope
136
+ | CommentThreadEnumeratedScope
137
+ | RevisionEnumeratedScope;
138
+
139
+ export interface EnumerateScopesInputs {
140
+ readonly overlay?: WorkflowOverlay | null;
141
+ }
142
+
143
+ function buildParagraphSemanticPath(
144
+ kind: "paragraph" | "heading" | "list-item",
145
+ blockIndex: number,
146
+ paragraph: ParagraphNode,
147
+ ): readonly string[] {
148
+ switch (kind) {
149
+ case "heading":
150
+ return [
151
+ "body",
152
+ "heading",
153
+ String(paragraph.outlineLevel ?? 0),
154
+ String(blockIndex),
155
+ ];
156
+ case "list-item":
157
+ return [
158
+ "body",
159
+ "list-item",
160
+ paragraph.numbering?.numberingInstanceId ?? "unknown",
161
+ String(paragraph.numbering?.level ?? 0),
162
+ String(blockIndex),
163
+ ];
164
+ case "paragraph":
165
+ default:
166
+ return ["body", "paragraph", String(blockIndex)];
167
+ }
168
+ }
169
+
170
+ function buildHandle(
171
+ scopeId: string,
172
+ documentId: string,
173
+ semanticPath: readonly string[],
174
+ provenance: ScopeHandle["provenance"],
175
+ rangePrecision: ScopeHandle["rangePrecision"],
176
+ parentScopeId?: string,
177
+ stableRef?: ScopeHandle["stableRef"],
178
+ ): ScopeHandle {
179
+ return {
180
+ scopeId,
181
+ documentId,
182
+ storyTarget: MAIN_STORY,
183
+ semanticPath,
184
+ ...(parentScopeId !== undefined ? { parentScopeId } : {}),
185
+ stableRef: stableRef ?? {
186
+ kind: "semantic-path",
187
+ value: semanticPath.join("/"),
188
+ },
189
+ provenance,
190
+ ...(rangePrecision ? { rangePrecision } : {}),
191
+ };
192
+ }
193
+
194
+ /**
195
+ * Collect generic classification tags from a workflow overlay scope.
196
+ * The compiler does NOT interpret these strings — it surfaces them
197
+ * verbatim. Hosts define the vocabulary: CLM hosts use `"clause"`,
198
+ * `"domain:legal"`, `"label:Liability"`; compliance hosts may use
199
+ * `"issue"`, `"severity:high"`; etc.
200
+ *
201
+ * Grammar (convention, not enforced):
202
+ * - bare strings (`"clause"`, `"issue"`) for primary classifications
203
+ * - `key:value` pairs (`"domain:legal"`, `"label:Liability"`) for
204
+ * structured metadata
205
+ *
206
+ * Order is stable: `kind` field first (if present), then `domain`,
207
+ * then `label`, then remaining metadata keys sorted alphabetically.
208
+ * This keeps classification arrays byte-stable across compiles for
209
+ * identical inputs (S3 determinism).
210
+ */
211
+ function classificationsFromOverlayScope(
212
+ scope: WorkflowScope,
213
+ ): readonly string[] {
214
+ const tags: string[] = [];
215
+ const metadata = scope.metadata ?? [];
216
+
217
+ const kindField = metadata.find(
218
+ (f: WorkflowScopeMetadataField) => f.key === "kind",
219
+ );
220
+ if (kindField && typeof kindField.value === "string") {
221
+ tags.push(kindField.value);
222
+ }
223
+ if (typeof scope.domain === "string" && scope.domain.length > 0) {
224
+ tags.push(`domain:${scope.domain}`);
225
+ }
226
+ if (typeof scope.label === "string" && scope.label.length > 0) {
227
+ tags.push(`label:${scope.label}`);
228
+ }
229
+ const remaining = metadata
230
+ .filter(
231
+ (f: WorkflowScopeMetadataField) =>
232
+ f.key !== "kind" && typeof f.value === "string",
233
+ )
234
+ .sort((a, b) => a.key.localeCompare(b.key));
235
+ for (const field of remaining) {
236
+ if (typeof field.value === "string") {
237
+ tags.push(`${field.key}:${field.value}`);
238
+ }
239
+ }
240
+ return Object.freeze(tags);
241
+ }
242
+
243
+ /**
244
+ * For each marker-backed overlay scope, map scopeId → classifications.
245
+ * Built once per enumeration; reused across every paragraph / table /
246
+ * row / cell that might be marker-backed by one of these scopes.
247
+ */
248
+ function buildClassificationIndex(
249
+ overlay: WorkflowOverlay | null | undefined,
250
+ ): Map<string, readonly string[]> {
251
+ const out = new Map<string, readonly string[]>();
252
+ if (!overlay) return out;
253
+ for (const scope of overlay.scopes as readonly WorkflowScope[]) {
254
+ out.set(scope.scopeId, classificationsFromOverlayScope(scope));
255
+ }
256
+ return out;
257
+ }
258
+
259
+ /**
260
+ * Walk paragraph children and return the first scope-marker id that
261
+ * *starts* inside the paragraph. When a paragraph carries multiple
262
+ * nested marker starts, the outermost structural interpretation is the
263
+ * first start marker — consistent with OOXML document order.
264
+ *
265
+ * Hosts that need richer multi-marker semantics should compose
266
+ * `classifications` from the matching overlay scope themselves.
267
+ */
268
+ function paragraphFirstMarkerStart(
269
+ paragraph: ParagraphNode,
270
+ knownScopeIds: ReadonlySet<string>,
271
+ ): string | null {
272
+ if (knownScopeIds.size === 0) return null;
273
+ for (const child of paragraph.children) {
274
+ if (
275
+ child.type === "scope_marker_start" &&
276
+ knownScopeIds.has(child.scopeId)
277
+ ) {
278
+ return child.scopeId;
279
+ }
280
+ }
281
+ return null;
282
+ }
283
+
284
+ function enumerateFieldsInParagraph(
285
+ paragraph: ParagraphNode,
286
+ blockIndex: number,
287
+ documentId: string,
288
+ parentScopeId: string,
289
+ ): FieldEnumeratedScope[] {
290
+ const out: FieldEnumeratedScope[] = [];
291
+ for (let i = 0; i < paragraph.children.length; i += 1) {
292
+ const child = paragraph.children[i] as InlineNode;
293
+ if (child.type !== "field") continue;
294
+ const semanticPath = [
295
+ "body",
296
+ "paragraph",
297
+ String(blockIndex),
298
+ "field",
299
+ String(i),
300
+ ];
301
+ const scopeId = `field:${blockIndex}:${i}`;
302
+ const handle: ScopeHandle = {
303
+ scopeId,
304
+ documentId,
305
+ storyTarget: MAIN_STORY,
306
+ semanticPath,
307
+ parentScopeId,
308
+ stableRef: { kind: "semantic-path", value: semanticPath.join("/") },
309
+ provenance: "derived",
310
+ rangePrecision: "canonical",
311
+ };
312
+ out.push({
313
+ kind: "field",
314
+ handle,
315
+ field: child,
316
+ paragraph,
317
+ blockIndex,
318
+ inlineIndex: i,
319
+ classifications: Object.freeze<string[]>([]),
320
+ });
321
+ }
322
+ return out;
323
+ }
324
+
325
+ function enumerateCommentThreads(
326
+ document: Pick<CanonicalDocument, "review"> | CanonicalDocumentEnvelope,
327
+ documentId: string,
328
+ ): CommentThreadEnumeratedScope[] {
329
+ const review = (document as { review?: { comments?: Record<string, CommentThread> } }).review;
330
+ const comments = review?.comments;
331
+ if (!comments) return [];
332
+ const entries = Object.values(comments);
333
+ entries.sort((a, b) => a.commentId.localeCompare(b.commentId));
334
+ return entries.map((thread) => {
335
+ const semanticPath = ["review", "comment-thread", thread.commentId];
336
+ const provenance: ScopeHandle["provenance"] =
337
+ thread.anchor.kind === "detached" ? "detached" : "marker-backed";
338
+ const handle: ScopeHandle = {
339
+ scopeId: thread.commentId,
340
+ documentId,
341
+ storyTarget: MAIN_STORY,
342
+ semanticPath,
343
+ stableRef: { kind: "scope-id", value: thread.commentId },
344
+ provenance,
345
+ rangePrecision: "marker-backed",
346
+ };
347
+ return {
348
+ kind: "comment-thread",
349
+ handle,
350
+ thread,
351
+ classifications: Object.freeze<string[]>([]),
352
+ } as CommentThreadEnumeratedScope;
353
+ });
354
+ }
355
+
356
+ function enumerateRevisions(
357
+ document: Pick<CanonicalDocument, "review"> | CanonicalDocumentEnvelope,
358
+ documentId: string,
359
+ ): RevisionEnumeratedScope[] {
360
+ const review = (document as { review?: { revisions?: Record<string, RevisionRecord> } }).review;
361
+ const revisions = review?.revisions;
362
+ if (!revisions) return [];
363
+ const entries = Object.values(revisions);
364
+ entries.sort((a, b) => a.changeId.localeCompare(b.changeId));
365
+ return entries.map((revision) => {
366
+ const semanticPath = ["review", "revision", revision.changeId];
367
+ const provenance: ScopeHandle["provenance"] =
368
+ revision.anchor.kind === "detached" ? "detached" : "marker-backed";
369
+ const handle: ScopeHandle = {
370
+ scopeId: revision.changeId,
371
+ documentId,
372
+ storyTarget: MAIN_STORY,
373
+ semanticPath,
374
+ stableRef: { kind: "scope-id", value: revision.changeId },
375
+ provenance,
376
+ rangePrecision: "marker-backed",
377
+ };
378
+ return {
379
+ kind: "revision",
380
+ handle,
381
+ revision,
382
+ classifications: Object.freeze<string[]>([]),
383
+ } as RevisionEnumeratedScope;
384
+ });
385
+ }
386
+
387
+ export function enumerateScopes(
388
+ document: Pick<CanonicalDocument, "content" | "docId" | "review"> | CanonicalDocumentEnvelope,
389
+ inputs: EnumerateScopesInputs = {},
390
+ ): EnumeratedScope[] {
391
+ const envelope = document as CanonicalDocumentEnvelope;
392
+ const root: DocumentRootNode =
393
+ "content" in envelope
394
+ ? (envelope.content as DocumentRootNode)
395
+ : (document as unknown as DocumentRootNode);
396
+ const documentId = (envelope.docId as unknown as string) ?? "";
397
+ const classificationIndex = buildClassificationIndex(inputs.overlay);
398
+ const knownOverlayScopeIds = new Set(classificationIndex.keys());
399
+
400
+ const results: EnumeratedScope[] = [];
401
+ for (let index = 0; index < root.children.length; index += 1) {
402
+ const block = root.children[index];
403
+ if (!block) continue;
404
+
405
+ if (block.type === "paragraph") {
406
+ const markerScopeId = paragraphFirstMarkerStart(
407
+ block,
408
+ knownOverlayScopeIds,
409
+ );
410
+ const kind = detectParagraphKind(block);
411
+ const semanticPath = buildParagraphSemanticPath(kind, index, block);
412
+ const scopeId =
413
+ markerScopeId !== null
414
+ ? markerScopeId
415
+ : buildParagraphScopeId(kind, index, block);
416
+ const provenance: ScopeHandle["provenance"] =
417
+ markerScopeId !== null ? "marker-backed" : "derived";
418
+ const rangePrecision: ScopeHandle["rangePrecision"] =
419
+ markerScopeId !== null ? "marker-backed" : "canonical";
420
+ const handle = buildHandle(
421
+ scopeId,
422
+ documentId,
423
+ semanticPath,
424
+ provenance,
425
+ rangePrecision,
426
+ undefined,
427
+ markerScopeId !== null
428
+ ? { kind: "scope-id", value: markerScopeId }
429
+ : undefined,
430
+ );
431
+ const classifications =
432
+ markerScopeId !== null
433
+ ? (classificationIndex.get(markerScopeId) ?? Object.freeze<string[]>([]))
434
+ : Object.freeze<string[]>([]);
435
+ results.push({
436
+ kind,
437
+ handle,
438
+ paragraph: block,
439
+ blockIndex: index,
440
+ classifications,
441
+ });
442
+ // Fields inside this paragraph carry the paragraph's real scopeId
443
+ // as their parent — NOT a hardcoded `para:${index}`, which would
444
+ // be wrong whenever the paragraph upgraded to heading / list-item.
445
+ const fields = enumerateFieldsInParagraph(block, index, documentId, scopeId);
446
+ for (const field of fields) results.push(field);
447
+ continue;
448
+ }
449
+
450
+ if (block.type === "table") {
451
+ const tableSemanticPath = ["body", "table", String(index)];
452
+ const tableScopeId = `table:${index}`;
453
+ const tableHandle = buildHandle(
454
+ tableScopeId,
455
+ documentId,
456
+ tableSemanticPath,
457
+ "derived",
458
+ "canonical",
459
+ );
460
+ results.push({
461
+ kind: "table",
462
+ handle: tableHandle,
463
+ table: block,
464
+ blockIndex: index,
465
+ classifications: Object.freeze<string[]>([]),
466
+ });
467
+
468
+ for (let rowIdx = 0; rowIdx < block.rows.length; rowIdx += 1) {
469
+ const row = block.rows[rowIdx]!;
470
+ const rowSemanticPath = [
471
+ "body",
472
+ "table",
473
+ String(index),
474
+ "row",
475
+ String(rowIdx),
476
+ ];
477
+ const rowScopeId = `row:${index}:${rowIdx}`;
478
+ const rowHandle = buildHandle(
479
+ rowScopeId,
480
+ documentId,
481
+ rowSemanticPath,
482
+ "derived",
483
+ "synthetic",
484
+ tableScopeId,
485
+ );
486
+ results.push({
487
+ kind: "table-row",
488
+ handle: rowHandle,
489
+ row,
490
+ table: block,
491
+ blockIndex: index,
492
+ rowIndex: rowIdx,
493
+ classifications: Object.freeze<string[]>([]),
494
+ });
495
+
496
+ for (let cellIdx = 0; cellIdx < row.cells.length; cellIdx += 1) {
497
+ const cell = row.cells[cellIdx]!;
498
+ const cellSemanticPath = [
499
+ "body",
500
+ "table",
501
+ String(index),
502
+ "row",
503
+ String(rowIdx),
504
+ "cell",
505
+ String(cellIdx),
506
+ ];
507
+ const cellScopeId = `cell:${index}:${rowIdx}:${cellIdx}`;
508
+ const cellHandle = buildHandle(
509
+ cellScopeId,
510
+ documentId,
511
+ cellSemanticPath,
512
+ "derived",
513
+ "synthetic",
514
+ rowScopeId,
515
+ );
516
+ results.push({
517
+ kind: "table-cell",
518
+ handle: cellHandle,
519
+ cell,
520
+ row,
521
+ table: block,
522
+ blockIndex: index,
523
+ rowIndex: rowIdx,
524
+ cellIndex: cellIdx,
525
+ classifications: Object.freeze<string[]>([]),
526
+ });
527
+ }
528
+ }
529
+ }
530
+ }
531
+
532
+ // Review-store scopes — threads + revisions — enumerate after document
533
+ // walk so their block ordering in `results` stays stable (all block scopes
534
+ // first, then review).
535
+ for (const thread of enumerateCommentThreads(document, documentId)) {
536
+ results.push(thread);
537
+ }
538
+ for (const revision of enumerateRevisions(document, documentId)) {
539
+ results.push(revision);
540
+ }
541
+
542
+ return results;
543
+ }