@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,59 @@
1
+ import React from "react";
2
+
3
+ import { TwReviewRail, type TwReviewRailProps } from "../review/tw-review-rail";
4
+
5
+ /**
6
+ * Rail slot for `TwReviewWorkspace`. Three postures:
7
+ *
8
+ * - `docked` — render the rail inline as a sibling of the document
9
+ * column (standard desktop width).
10
+ * - `drawer` — render the rail behind a dismiss-overlay button so the
11
+ * narrow-viewport scrim can close it.
12
+ * - `hidden` — render nothing (the parent already decided the rail
13
+ * is off).
14
+ *
15
+ * All TwReviewRailProps except `variant` are forwarded verbatim through
16
+ * `rail`; the wrapper owns the `variant` slot so the parent doesn't have
17
+ * to branch twice on posture.
18
+ */
19
+ export type TwReviewWorkspaceRailMode = "docked" | "drawer" | "hidden";
20
+
21
+ export interface TwReviewWorkspaceRailProps {
22
+ mode: TwReviewWorkspaceRailMode;
23
+ /** Fires when the drawer scrim is clicked. Ignored in docked posture. */
24
+ onDrawerClose: () => void;
25
+ /**
26
+ * Plain rail props minus `variant` — the wrapper owns the variant
27
+ * slot so callers pass one bag regardless of posture.
28
+ */
29
+ rail: Omit<TwReviewRailProps, "variant">;
30
+ }
31
+
32
+ export function TwReviewWorkspaceRail({
33
+ mode,
34
+ onDrawerClose,
35
+ rail,
36
+ }: TwReviewWorkspaceRailProps): React.ReactElement | null {
37
+ if (mode === "hidden") return null;
38
+
39
+ if (mode === "docked") {
40
+ return <TwReviewRail {...rail} />;
41
+ }
42
+
43
+ return (
44
+ <div
45
+ className="pointer-events-none absolute inset-0 z-30 flex justify-end"
46
+ data-testid="review-rail-drawer"
47
+ >
48
+ <button
49
+ type="button"
50
+ aria-label="Close sidebar overlay"
51
+ className="pointer-events-auto absolute inset-0 border-0 bg-[color:rgba(21,26,23,0.08)] dark:bg-[color:rgba(0,0,0,0.32)]"
52
+ onClick={onDrawerClose}
53
+ />
54
+ <div className="pointer-events-auto relative h-full">
55
+ <TwReviewRail variant="drawer" {...rail} />
56
+ </div>
57
+ </div>
58
+ );
59
+ }
@@ -0,0 +1,408 @@
1
+ import type { FocusEventHandler, ReactNode, Ref } from "react";
2
+
3
+ import type {
4
+ ActiveListContext,
5
+ CommentSidebarThreadSnapshot,
6
+ DocumentNavigationSnapshot,
7
+ EditorAnchorProjection,
8
+ EditorStoryTarget,
9
+ EditorViewStateSnapshot,
10
+ FormattingStateSnapshot,
11
+ FormattingAlignment,
12
+ HeaderFooterLinkPatch,
13
+ InteractionGuardSnapshot,
14
+ InsertImageOptions,
15
+ RuntimeContextAnalyticsSnapshot,
16
+ RuntimeRenderSnapshot,
17
+ ReviewQueueSnapshot,
18
+ SectionPageNumberingPatch,
19
+ SectionBreakType,
20
+ StyleCatalogSnapshot,
21
+ TrackedChangeEntrySnapshot,
22
+ WordReviewEditorChromeOptions,
23
+ WordReviewEditorChromePreset,
24
+ WordReviewEditorChromeVisibility,
25
+ WorkflowScopeSnapshot,
26
+ WorkspaceMode,
27
+ ZoomLevel,
28
+ } from "../../api/public-types";
29
+ import type { SessionCapabilities } from "../../api/public-types";
30
+ import type {
31
+ ActiveSelectionToolModel,
32
+ SelectionToolAnchor,
33
+ } from "../../ui/headless/selection-tool-types";
34
+ import type { MarkupDisplay } from "../../ui/headless/comment-decoration-model";
35
+ import type { EditorCommandBag } from "../../ui/editor-command-bag.ts";
36
+ import type { EditorActionHostCallbacks } from "../chrome/editor-action-registry";
37
+ import type { TwWorkspaceChromeHostController } from "../chrome/tw-workspace-chrome-host";
38
+ import type { MediaPreviewDescriptor } from "../editor-surface/pm-state-from-snapshot.ts";
39
+ import type { ReviewRailTab } from "../review/tw-review-rail";
40
+
41
+ export type ReviewWorkspaceChromeVisibility = WordReviewEditorChromeVisibility;
42
+
43
+ export interface TwReviewWorkspaceProps {
44
+ snapshot: RuntimeRenderSnapshot;
45
+ viewState: EditorViewStateSnapshot;
46
+ markupDisplay: MarkupDisplay;
47
+ currentUserId?: string;
48
+ capabilities?: SessionCapabilities;
49
+ mediaPreviews?: Record<string, MediaPreviewDescriptor>;
50
+ reviewMode?: "editing" | "review";
51
+ /**
52
+ * Runtime-owned layout facet. Optional so existing tests + host apps
53
+ * continue to mount the workspace without installing a facet. When
54
+ * supplied, the ChromeOverlay plane (scope rail, workflow dock, etc.)
55
+ * renders over the document column.
56
+ */
57
+ layoutFacet?: import("../../runtime/layout/index.ts").WordReviewEditorLayoutFacet;
58
+ /**
59
+ * Layer-05 geometry facet (`runtime.geometry`). Required by chrome
60
+ * overlay layers (scope rail, object selection, table grip, page-break
61
+ * decorations) after refactor/05 cross-lane-coord §8.4 migration.
62
+ * Reads render-frame + zoom through the geometry layer instead of
63
+ * through the now-`@deprecated` `layoutFacet.getRenderFrame` /
64
+ * `.getRenderZoom` methods.
65
+ */
66
+ geometryFacet?: import("../../runtime/geometry/index.ts").GeometryFacet;
67
+ /**
68
+ * Layer-06 workflow facet — canonical source of scope rail segments
69
+ * and scope card models (`runtime.workflow`). Required by the scope
70
+ * rail + scope card chrome layers after Slice 4's seam inversion
71
+ * removed those methods from `WordReviewEditorLayoutFacet`. When
72
+ * absent, those layers render nothing.
73
+ */
74
+ workflowFacet?: import("../../runtime/workflow/rail/types.ts").WorkflowFacet;
75
+ /**
76
+ * Optional shell header override. Mounted above the formatting toolbar.
77
+ *
78
+ * Per docs/plans/chrome-composition-audit.md §2.4 the shell is always
79
+ * present in default composition. When this prop is omitted the
80
+ * workspace mounts a default `<TwShellHeader />` with the 4-mode
81
+ * switcher (edit / review / workflow / more) so mode authority is
82
+ * always visible and centralized.
83
+ *
84
+ * Hosts that need a custom brand, mode handlers, or primary CTA pass a
85
+ * pre-assembled `<TwShellHeader />` here; the custom node replaces the
86
+ * default entirely.
87
+ */
88
+ shellHeader?: ReactNode;
89
+ /**
90
+ * Phase C.γ.3 — workspace-level chrome surfaces (right-click context
91
+ * menu + Ctrl/Cmd+K command palette). When supplied, the workspace
92
+ * mounts `TwWorkspaceChromeHost` which consumes the shared
93
+ * editor-action-registry so right-click, inline "More…", and
94
+ * command-palette all dispatch the same actions
95
+ * (DESIGN-EDITOR.md §6.4).
96
+ *
97
+ * Actions without a wired callback are hidden from every surface —
98
+ * progressive disclosure per designsystem.md §2.1 principle 4.
99
+ *
100
+ * Omit to keep the pre-Phase-C workspace behavior (no right-click
101
+ * menu, no palette).
102
+ */
103
+ editorActionHost?: EditorActionHostCallbacks;
104
+ /**
105
+ * Forward ref for the workspace's chrome controller. The runtime
106
+ * boundary (`editor-runtime-boundary.ts`) wires this to the
107
+ * `onContextMenuRequested` callback on the PM command bridge so a
108
+ * native `contextmenu` event opens the menu at the click coordinates.
109
+ *
110
+ * Also consumed by Phase D's inline "More…" buttons on demoted
111
+ * floating toolbars: the toolbar calls
112
+ * `chromeControllerRef.current?.openWithKinds({ kinds: ["table-cell"], … })`
113
+ * and reuses the same registry as right-click.
114
+ */
115
+ chromeControllerRef?: React.Ref<TwWorkspaceChromeHostController>;
116
+ /**
117
+ * Suppress the global Ctrl/Cmd+K palette listener — e.g. when a
118
+ * higher-priority modal captures keyboard focus.
119
+ */
120
+ commandPaletteDisabled?: boolean;
121
+ /**
122
+ * Optional host-provided Workflow-tab override for the review rail.
123
+ * When unset the rail renders the built-in `TwWorkflowTab` sourced from
124
+ * `layoutFacet.getAllScopeRailSegments()`.
125
+ */
126
+ reviewRailWorkflowTab?: ReactNode;
127
+ reviewRailWorkflowCount?: number;
128
+ reviewRailWorkflowScopesTitle?: string;
129
+ reviewRailIntelligenceEyebrow?: string;
130
+ /** Opt in to the editorial DOCUMENT INTELLIGENCE header + underline tab chip. */
131
+ reviewRailIntelligenceHeader?: boolean;
132
+ /** Optional SEARCH / HELP utility footer at the bottom of the rail. */
133
+ reviewRailFooter?: {
134
+ onSearch?: () => void;
135
+ helpHref?: string;
136
+ searchLabel?: string;
137
+ helpLabel?: string;
138
+ };
139
+ document: ReactNode;
140
+ workspaceMode: WorkspaceMode;
141
+ zoomLevel?: ZoomLevel;
142
+ formattingState?: FormattingStateSnapshot;
143
+ activeListContext?: ActiveListContext | null;
144
+ styleCatalog?: StyleCatalogSnapshot;
145
+ activeRailTab: ReviewRailTab;
146
+ activeCommentId?: string;
147
+ activeRevisionId?: string;
148
+ showTrackedChanges: boolean;
149
+ workflowScopeSnapshot?: WorkflowScopeSnapshot | null;
150
+ interactionGuardSnapshot?: InteractionGuardSnapshot;
151
+ chromePreset?: WordReviewEditorChromePreset;
152
+ chromeOptions?: Partial<WordReviewEditorChromeOptions>;
153
+ /** P9g — live collab session for the `"collab"` chrome preset's top nav. */
154
+ collabSession?: import("../../runtime/collab-session.ts").CollabSession;
155
+ collabTransportStatus?: import("../../api/awareness-identity-types.ts").TransportStatus;
156
+ collabActorId?: string;
157
+ collabSendBaseline?: {
158
+ originDocumentId: string;
159
+ originPayloadId: string;
160
+ originContentHash: string;
161
+ payloadXml: string;
162
+ };
163
+ reviewQueue?: ReviewQueueSnapshot;
164
+ documentContextAnalytics?: RuntimeContextAnalyticsSnapshot | null;
165
+ selectionContextAnalytics?: RuntimeContextAnalyticsSnapshot | null;
166
+ currentScopeContextAnalytics?: RuntimeContextAnalyticsSnapshot | null;
167
+ commands: EditorCommandBag;
168
+ onActivateFloatingImage?: (payload: {
169
+ mediaId: string;
170
+ from: number;
171
+ to: number;
172
+ storyTarget: EditorStoryTarget;
173
+ }) => void;
174
+ /** N6 — release the grabbed image/shape. Wired to `runtime.deselectObject()` by the host. */
175
+ onDeselectObject?: () => void;
176
+ activeSelectionTool?: ActiveSelectionToolModel | null;
177
+ selectionToolAnchor?: SelectionToolAnchor | null;
178
+ documentNavigation?: DocumentNavigationSnapshot;
179
+ /**
180
+ * R2.3: chrome-pin change handler. When supplied, selection tools
181
+ * expose their detach affordance and persist pin state through to
182
+ * runtime ViewState (via the host's `setChromePin` action). When
183
+ * omitted, the detach handle is suppressed — the tool behaves as
184
+ * a non-pinnable anchored panel (pre-R2 behavior for most kinds).
185
+ */
186
+ onChromePinChange?: (
187
+ surface: import("../../api/public-types").ChromePinSurface,
188
+ pin: import("../../api/public-types").PinState | null,
189
+ ) => void;
190
+ onWorkspaceModeChange?: (value: WorkspaceMode) => void;
191
+ onZoomChange?: (level: ZoomLevel) => void;
192
+ onActiveRailTabChange?: (value: ReviewRailTab) => void;
193
+ onShowTrackedChangesChange?: (show: boolean) => void;
194
+ onUndo?: () => void;
195
+ onRedo?: () => void;
196
+ onSetParagraphStyle?: (styleId: string) => void;
197
+ onToggleBold?: () => void;
198
+ onToggleItalic?: () => void;
199
+ onToggleUnderline?: () => void;
200
+ onSetSelectionTextColor?: (color: string) => void;
201
+ onSetSelectionHighlightColor?: (color: string | null) => void;
202
+ onToggleStrikethrough?: () => void;
203
+ onToggleSuperscript?: () => void;
204
+ onToggleSubscript?: () => void;
205
+ onSetFontFamily?: (fontFamily: string) => void;
206
+ onSetFontSize?: (fontSize: number) => void;
207
+ onSetTextColor?: (color: string) => void;
208
+ onSetHighlightColor?: (color: string | null) => void;
209
+ onSetAlignment?: (alignment: FormattingAlignment) => void;
210
+ onToggleBulletedList?: () => void;
211
+ onToggleNumberedList?: () => void;
212
+ onOutdent?: () => void;
213
+ onIndent?: () => void;
214
+ onAddComment?: () => void;
215
+ onInsertPageBreak?: () => void;
216
+ onInsertTable?: () => void;
217
+ onInsertSectionBreak?: (type: SectionBreakType) => void;
218
+ onInsertImage?: (options: InsertImageOptions) => void;
219
+ onSetTableStyle?: (styleId: string) => void;
220
+ onAddRowBefore?: () => void;
221
+ onAddRowAfter?: () => void;
222
+ onAddColumnBefore?: () => void;
223
+ onAddColumnAfter?: () => void;
224
+ onDeleteRow?: () => void;
225
+ onDeleteColumn?: () => void;
226
+ onDeleteTable?: () => void;
227
+ onMergeCells?: () => void;
228
+ onSplitCell?: () => void;
229
+ onSetCellBackground?: (color: string) => void;
230
+ onSetImageLayout?: (
231
+ mediaId: string,
232
+ dimensions: { widthEmu: number; heightEmu: number },
233
+ ) => void;
234
+ onSetImageFrame?: (
235
+ mediaId: string,
236
+ offsets: { horizontalOffsetEmu?: number; verticalOffsetEmu?: number },
237
+ ) => void;
238
+ onDeleteSectionBreak?: (sectionIndex: number) => void;
239
+ onUpdateSectionLayout?: (
240
+ sectionIndex: number,
241
+ patch: {
242
+ pageSize?: { width?: number; height?: number; orientation?: "portrait" | "landscape" };
243
+ pageMargins?: {
244
+ top?: number;
245
+ right?: number;
246
+ bottom?: number;
247
+ left?: number;
248
+ header?: number;
249
+ footer?: number;
250
+ gutter?: number;
251
+ };
252
+ columns?: {
253
+ count?: number;
254
+ space?: number;
255
+ equalWidth?: boolean;
256
+ columns?: Array<{ width: number; space?: number }>;
257
+ separator?: boolean;
258
+ };
259
+ titlePage?: boolean;
260
+ sectionType?: SectionBreakType;
261
+ },
262
+ ) => void;
263
+ onSetSectionPageNumbering?: (
264
+ sectionIndex: number,
265
+ patch: SectionPageNumberingPatch | null,
266
+ ) => void;
267
+ onSetHeaderFooterLink?: (
268
+ sectionIndex: number,
269
+ patch: HeaderFooterLinkPatch,
270
+ ) => void;
271
+ onAddCommentFromSelection?: () => void;
272
+ onExport?: () => void;
273
+ onDismissSelectionToolbar?: () => void;
274
+ onAcceptSuggestion?: () => void;
275
+ onRejectSuggestion?: () => void;
276
+ onEditSuggestion?: () => void;
277
+ onAddCommentFromSuggestion?: () => void;
278
+ onSelectionToolbarFocusCapture?: FocusEventHandler<HTMLDivElement>;
279
+ onSelectionToolbarBlurCapture?: FocusEventHandler<HTMLDivElement>;
280
+ selectionToolbarRef?: Ref<HTMLDivElement>;
281
+ onOpenComment?: (thread: CommentSidebarThreadSnapshot) => void;
282
+ onResolveComment?: (commentId: string) => void;
283
+ onReopenComment?: (commentId: string) => void;
284
+ onAddReply?: (commentId: string, body: string) => void;
285
+ onEditBody?: (commentId: string, body: string) => void;
286
+ onOpenRevision?: (revision: TrackedChangeEntrySnapshot) => void;
287
+ onAcceptRevision?: (revisionId: string) => void;
288
+ onRejectRevision?: (revisionId: string) => void;
289
+ onAcceptAllChanges?: () => void;
290
+ onRejectAllChanges?: () => void;
291
+ onCloseStory?: () => void;
292
+ /**
293
+ * @deprecated P8.11 — the workspace no longer renders a workspace-level
294
+ * header band with an "Edit header" button; per-page header bands route
295
+ * clicks via `onOpenStory` / `runtime.openStory` directly. The prop
296
+ * remains optional for one release so existing hosts continue to
297
+ * compile; supplying it emits a `console.warn` on mount.
298
+ */
299
+ onOpenHeaderStory?: () => void;
300
+ /**
301
+ * @deprecated P8.11 — see `onOpenHeaderStory`. Footer variant of the
302
+ * same deprecation.
303
+ */
304
+ onOpenFooterStory?: () => void;
305
+ /**
306
+ * Open a header/footer story for a specific page. Called when the user
307
+ * double-clicks a per-page header/footer band in the page-stack chrome.
308
+ * Must resolve the correct variant for that page's section and call
309
+ * `runtime.openStory()`.
310
+ */
311
+ onOpenHeaderStoryForPage?: (pageIndex: number) => void;
312
+ onOpenFooterStoryForPage?: (pageIndex: number) => void;
313
+ /**
314
+ * P8.11 — fired when a per-page chrome band (header / footer) is
315
+ * clicked to promote it into the active editing surface. Wire to
316
+ * `runtime.openStory(target)`; the chrome layer's portal mechanism
317
+ * then reparents the PM surface into the matching band's active slot.
318
+ */
319
+ onOpenStory?: (target: EditorStoryTarget) => void;
320
+ onSetParagraphIndentation?: (indentation: {
321
+ left?: number;
322
+ right?: number;
323
+ firstLine?: number;
324
+ hanging?: number;
325
+ }) => void;
326
+ onSetParagraphTabStops?: (tabStops: Array<{ pos: number; val?: string; leader?: string }>) => void;
327
+ onRestartNumbering?: () => void;
328
+ onContinueNumbering?: () => void;
329
+ // P6: new table ops
330
+ onToggleRowHeader?: () => void;
331
+ onToggleRowCantSplit?: () => void;
332
+ onDistributeColumnsEvenly?: () => void;
333
+ onSetTableAlignment?: (alignment: "left" | "center" | "right") => void;
334
+ onSetCellVerticalAlign?: (align: "top" | "center" | "bottom") => void;
335
+ /** P6: active table context for chrome overlay grips. */
336
+ tableContext?: import("../../api/public-types").TableStructureContextSnapshot | null;
337
+ /** P6: column resize committed from overlay grip → set-column-width op. */
338
+ onSetColumnWidth?: (columnIndex: number, twips: number) => void;
339
+ /** P6: row resize committed from overlay grip → set-row-height op. */
340
+ onSetRowHeight?: (rowIndex: number, twips: number, rule: "auto" | "atLeast" | "exact") => void;
341
+ onListIndent?: () => void;
342
+ onListOutdent?: () => void;
343
+ onUpdateFields?: () => void;
344
+ onUpdateTableOfContents?: () => void;
345
+ onGoToPreviousReviewItem?: () => void;
346
+ onGoToNextReviewItem?: () => void;
347
+ onMarkSectionForReview?: () => void;
348
+ /** Optional: open sidebar to tracked-changes panel. When provided, the review role shows a sidebar-TC icon. */
349
+ onReviewSidebarTrackedChanges?: () => void;
350
+ /** Optional: open sidebar to comments panel. When provided, the review role shows a sidebar-comments icon. */
351
+ onReviewSidebarComments?: () => void;
352
+ onNavigateHeading?: (headingId: string) => void;
353
+ chromeVisibility?: Partial<ReviewWorkspaceChromeVisibility>;
354
+ /**
355
+ * Called when the shell-header mode tab changes or any chrome surface fires
356
+ * a role switch. Wire to `runtime.setEditorRole(role)` so the workspace
357
+ * re-renders with the new per-role action set.
358
+ */
359
+ onEditorRoleChange?: (role: import("../../api/public-types.ts").EditorRole) => void;
360
+ /**
361
+ * Scope card mode selector fired a mode change. Wire to the host's
362
+ * existing overlay-apply path (or an equivalent CCEP workflow
363
+ * endpoint). The card never mutates runtime state directly.
364
+ */
365
+ onScopeModeChangeRequested?: (payload: {
366
+ scopeId: string;
367
+ mode: import("../../api/public-types.ts").WorkflowScopeMode;
368
+ }) => void;
369
+ /**
370
+ * Scope card issue row fired an action (resolve/waive/escalate/
371
+ * acknowledge). Host updates the attached `IssueMetadataValue`
372
+ * state and re-pushes via `setWorkflowMetadataEntries`.
373
+ */
374
+ onScopeIssueActionRequested?: (payload: {
375
+ scopeId: string;
376
+ issueId: string;
377
+ action: import("../../api/public-types.ts").ScopeIssueAction;
378
+ }) => void;
379
+ /**
380
+ * R3 — scope card suggestion-group accept button fired. WordReview-
381
+ * Editor relays to `ref.acceptSuggestionGroup(groupId)` which fans
382
+ * out to individual `acceptChange` calls across the group members.
383
+ */
384
+ onScopeAcceptSuggestionGroup?: (payload: {
385
+ scopeId: string;
386
+ groupId: string;
387
+ }) => void;
388
+ /** R3 — scope card suggestion-group reject. */
389
+ onScopeRejectSuggestionGroup?: (payload: {
390
+ scopeId: string;
391
+ groupId: string;
392
+ }) => void;
393
+ /**
394
+ * K2 — scope card "Ask review agent" fired. WordReviewEditor emits
395
+ * `agent-on-selection-requested` via WordReviewEditorEvent.
396
+ */
397
+ onScopeAskAgent?: (payload: {
398
+ scopeId: string;
399
+ anchor?: EditorAnchorProjection;
400
+ }) => void;
401
+ /**
402
+ * P3 — optional scope-tag editor slot rendered inside the scope
403
+ * card when `editorRole === "workflow"`. Hosts pass a chip picker,
404
+ * free-text input, or whatever authoring surface they want. Unset
405
+ * in editor/review roles.
406
+ */
407
+ scopeCardScopeTagEditor?: ReactNode;
408
+ }
@@ -0,0 +1,104 @@
1
+ import { useMemo } from "react";
2
+
3
+ import type {
4
+ ActiveListContext,
5
+ EditorViewStateSnapshot,
6
+ InteractionGuardSnapshot,
7
+ WordReviewEditorChromePreset,
8
+ WorkflowScopeSnapshot,
9
+ } from "../../api/public-types";
10
+ import { resolveResponsiveChromeState } from "../chrome/responsive-chrome";
11
+ import { resolveScopedChromePolicy } from "../../ui/headless/scoped-chrome-policy";
12
+ import type { SessionCapabilities } from "../../api/public-types";
13
+ import type { ToolbarInteractionPolicy } from "../toolbar/tw-toolbar";
14
+
15
+ export interface UseChromePolicyOptions {
16
+ viewportWidth: number | undefined;
17
+ reviewRailAvailable: boolean;
18
+ reviewRailOpen: boolean;
19
+ chromePreset: WordReviewEditorChromePreset;
20
+ caps: SessionCapabilities | undefined;
21
+ interactionGuardSnapshot: InteractionGuardSnapshot | undefined;
22
+ workflowScopeSnapshot: WorkflowScopeSnapshot | null | undefined;
23
+ activeListContext: ActiveListContext | null | undefined;
24
+ role: EditorViewStateSnapshot["editorRole"];
25
+ hasSidebarPanelAccess: boolean;
26
+ effectiveSelectionMode: ToolbarInteractionPolicy["mode"];
27
+ }
28
+
29
+ export interface ChromePolicy {
30
+ responsiveChrome: ReturnType<typeof resolveResponsiveChromeState>;
31
+ scopedChromePolicy: ReturnType<typeof resolveScopedChromePolicy>;
32
+ toolbarInteractionPolicy: ToolbarInteractionPolicy | undefined;
33
+ }
34
+
35
+ /**
36
+ * Memoize the two compositional chrome-policy resolvers and derive the
37
+ * toolbar interaction policy. Bundled because `scopedChromePolicy`
38
+ * depends on `responsiveChrome.isNarrow`, and the toolbar policy depends
39
+ * on both `caps` and `effectiveSelectionMode` which flow through the
40
+ * same input set.
41
+ */
42
+ export function useChromePolicy(options: UseChromePolicyOptions): ChromePolicy {
43
+ const {
44
+ viewportWidth,
45
+ reviewRailAvailable,
46
+ reviewRailOpen,
47
+ chromePreset,
48
+ caps,
49
+ interactionGuardSnapshot,
50
+ workflowScopeSnapshot,
51
+ activeListContext,
52
+ role,
53
+ hasSidebarPanelAccess,
54
+ effectiveSelectionMode,
55
+ } = options;
56
+
57
+ const responsiveChrome = useMemo(
58
+ () =>
59
+ resolveResponsiveChromeState({
60
+ viewportWidth,
61
+ reviewRailAvailable,
62
+ reviewRailOpen,
63
+ }),
64
+ [reviewRailAvailable, reviewRailOpen, viewportWidth],
65
+ );
66
+
67
+ const scopedChromePolicy = useMemo(
68
+ () =>
69
+ resolveScopedChromePolicy({
70
+ preset: chromePreset,
71
+ compactMode: responsiveChrome.isNarrow,
72
+ capabilities: caps,
73
+ interactionGuardSnapshot,
74
+ workflowScopeSnapshot,
75
+ activeListContext,
76
+ role,
77
+ hasSidebarPanelAccess,
78
+ }),
79
+ [
80
+ caps,
81
+ chromePreset,
82
+ hasSidebarPanelAccess,
83
+ activeListContext,
84
+ interactionGuardSnapshot,
85
+ workflowScopeSnapshot,
86
+ responsiveChrome.isNarrow,
87
+ role,
88
+ ],
89
+ );
90
+
91
+ const toolbarInteractionPolicy: ToolbarInteractionPolicy | undefined = caps
92
+ ? {
93
+ mode: effectiveSelectionMode,
94
+ canFormatText: caps.canEdit && effectiveSelectionMode === "edit",
95
+ canInsertStructural: caps.canEdit && effectiveSelectionMode === "edit",
96
+ canAddComment:
97
+ caps.canAddComment &&
98
+ effectiveSelectionMode !== "view" &&
99
+ effectiveSelectionMode !== "blocked",
100
+ }
101
+ : undefined;
102
+
103
+ return { responsiveChrome, scopedChromePolicy, toolbarInteractionPolicy };
104
+ }