@beyondwork/docx-react-component 1.0.67 → 1.0.70

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