@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,520 @@
1
+ /**
2
+ * @endStateApi v3 — UI API types.
3
+ *
4
+ * The UI API (layer 10 per `docs/architecture/10-ui-api.md`) is the
5
+ * first-class public face of the runtime for mounted-surface consumption —
6
+ * session binding, selection/viewport hooks, geometry-backed overlay
7
+ * primitives, chrome posture composition, debug-service attachment.
8
+ *
9
+ * Slice 1 reserves the type surface + entry shells. The shells throw
10
+ * `NOT_IMPLEMENTED` until Slices 2–5 wire them through `RuntimeApiHandle`
11
+ * (runtime reads) + `GeometryFacet` (overlay anchors) + `InteractionGuardSnapshot`
12
+ * (chrome posture) + `runtime.debug` (debug attachment).
13
+ *
14
+ * Contracts (per architecture 10):
15
+ * U1 — no DOM or PM truth reads. UI API consumes runtime state through
16
+ * RuntimeApiHandle + Geometry + Workflow/Review.
17
+ * U2 — bound to a controller, not React internals.
18
+ * U3 — selection + viewport are the only bidirectional channels.
19
+ * U4 — overlays derive anchors from geometry, never DOM.
20
+ * U5 — chrome posture composed once per read.
21
+ * U6 — debug attachment opt-in; gated by `debugMode` prop, default "off".
22
+ * U7 — subscribers fire on runtime state changes + coalesced rAF.
23
+ * U8 — no access to internal controllers.
24
+ */
25
+
26
+ import type {
27
+ OverlayKind,
28
+ ScopeBundle,
29
+ SelectionSnapshot,
30
+ WorkflowMarkupMode,
31
+ } from "../../public-types.ts";
32
+ import type { GeometryRect } from "../../../runtime/geometry/geometry-types.ts";
33
+ import type {
34
+ ChromeComposition,
35
+ ChromeCompositionInput,
36
+ EditorRailTab,
37
+ } from "./chrome-composition.ts";
38
+
39
+ /**
40
+ * Re-export the layer-05 GeometryRect so UI API consumers can type overlay
41
+ * returns without importing from `src/runtime/geometry/**` themselves.
42
+ */
43
+ export type { GeometryRect };
44
+
45
+ /**
46
+ * Re-export the class-A `OverlayKind` closed union from public-types so
47
+ * U9 consumers can import everything they need from the UI API barrel.
48
+ * The canonical definition lives at `src/api/public-types.ts` because
49
+ * layer-06 policies also key off it.
50
+ */
51
+ export type { OverlayKind };
52
+
53
+ /**
54
+ * Re-export the class-A `WorkflowMarkupMode` closed union from
55
+ * public-types so X5 consumers can import everything they need from the
56
+ * UI API barrel. Composed with the class-C local preference in
57
+ * `ui.viewport.getEffectiveMarkupMode()`.
58
+ */
59
+ export type { WorkflowMarkupMode };
60
+
61
+ /* ================================================================== */
62
+ /* Session binding */
63
+ /* ================================================================== */
64
+
65
+ /**
66
+ * Opaque controller handle. The UI API does not care whether a React
67
+ * component, a Playwright test, or a remote debug session is driving it —
68
+ * only that the caller is responsible for the lifecycle.
69
+ */
70
+ export type UiControllerKind = "runtime-direct" | "window-debug" | "playwright";
71
+
72
+ /**
73
+ * Opaque controller handle. Three dispatch hooks (all optional) let the
74
+ * bind-side wire concrete host behavior for the bidirectional channels in
75
+ * U3 — selection + viewport/scroll. Missing hooks cause the matching UI
76
+ * API methods to throw rather than silently no-op, so consumers notice
77
+ * misconfigured bindings immediately.
78
+ *
79
+ * - `runtime-direct` — a React editor mount binds a controller whose
80
+ * `dispatchSelection` routes through the command bridge and whose
81
+ * `dispatchScroll` calls `scrollIntoView` on the geometry target.
82
+ * - `window-debug` — the debug service binds a controller that RPCs to
83
+ * the editor instance via `window.__debug`.
84
+ * - `playwright` — a Playwright test driver binds a controller whose
85
+ * hooks enqueue events for the test runner to observe.
86
+ */
87
+ export interface UiController {
88
+ readonly kind: UiControllerKind;
89
+ readonly id: string;
90
+ /**
91
+ * Bidirectional channel U3 — UI → runtime selection dispatch. Called by
92
+ * `ui.surface.setSelection`. Throwing here (or omitting the hook) is a
93
+ * configuration bug; the UI API surfaces the error verbatim.
94
+ */
95
+ readonly dispatchSelection?: (range: SelectionRangeInput) => void;
96
+ /**
97
+ * Bidirectional channel U3 — UI → runtime/viewport scroll dispatch.
98
+ * Called by `ui.surface.scrollTo`. Returns a promise that resolves when
99
+ * the scroll settles (or immediately for `behavior: "instant"`).
100
+ */
101
+ readonly dispatchScroll?: (target: ScrollTarget) => Promise<void>;
102
+ /**
103
+ * Viewport provider. Optional. Slice 2 reads viewport through this when
104
+ * present; a geometry-backed path lands when `RuntimeApiHandle` gains a
105
+ * `geometry` accessor (tracked on `refactor/runtime-api`).
106
+ */
107
+ readonly getViewport?: () => ViewportState;
108
+ /**
109
+ * Viewport subscription — rAF-coalesced updates for scroll / zoom / DPR
110
+ * changes. `ui.viewport.subscribe` delegates here; the bind-side is
111
+ * responsible for producing one event per rAF tick (U7). Omitting the
112
+ * hook causes `ui.viewport.subscribe` to throw a configuration-clear
113
+ * error rather than silently no-op.
114
+ */
115
+ readonly subscribeViewport?: (listener: UiListener<ViewportState>) => UiUnsubscribe;
116
+ /**
117
+ * Overlay invalidation subscription. Fires when geometry invalidation
118
+ * ranges overlap attached overlay queries (U7). `ui.overlays.subscribe`
119
+ * delegates here; bind-side wires the runtime's layout-invalidation
120
+ * events to this hook.
121
+ */
122
+ readonly subscribeOverlays?: (
123
+ listener: UiListener<OverlayAnchorQuery>,
124
+ ) => UiUnsubscribe;
125
+ /**
126
+ * Overlay anchor resolver. Expected to be a direct projection of the
127
+ * geometry facet (U4 — overlays derive from geometry, not DOM). Returns
128
+ * null when geometry is unavailable or the query does not resolve. The
129
+ * bind-side wires this to `GeometryFacet.getAnchor` with the appropriate
130
+ * OverlayAnchorQuery → AnchorQuery translation.
131
+ *
132
+ * This controller hook exists as a seam until `RuntimeApiHandle` gains
133
+ * a `geometry` accessor (tracked on `refactor/runtime-api`); at that
134
+ * point `ui.overlays.getAnchor` can call through the handle directly
135
+ * and downgrade this hook to a fallback.
136
+ */
137
+ readonly getOverlayAnchor?: (query: OverlayAnchorQuery) => GeometryRect | null;
138
+ /**
139
+ * Overlay multi-rect resolver. Used for scope envelopes and spanning
140
+ * selections (U4). Returns the empty array when geometry is unavailable
141
+ * or the query does not resolve.
142
+ */
143
+ readonly getOverlayRects?: (query: OverlayAnchorQuery) => readonly GeometryRect[];
144
+ /**
145
+ * Host-provided chrome posture slice — the fields that live outside the
146
+ * runtime (host props like reviewMode / markupDisplay / debugMode /
147
+ * chromePreset). `ui.chrome.getPosture` composes this with the runtime's
148
+ * guard snapshot + session/render state into the final ChromePosture.
149
+ *
150
+ * Default values when the hook is missing or returns undefined:
151
+ * reviewMode — "observer"
152
+ * markupDisplay — "final"
153
+ * debugMode — "off" (gated per U6; default MUST remain "off")
154
+ * chromePreset — undefined
155
+ */
156
+ readonly getHostPosture?: () => ChromeHostPosture | undefined;
157
+ /**
158
+ * Pinned-surface enumeration. The bind-side wraps the existing
159
+ * `chrome-preset-model` logic and returns the current list. When the
160
+ * hook is absent, `ui.chrome.getPinnedSurfaces()` returns [].
161
+ */
162
+ readonly getPinnedSurfaces?: () => readonly ChromeSurface[];
163
+ /**
164
+ * Posture change subscription. Fires on guard snapshot change, session
165
+ * state change, or host posture change (U7). `ui.chrome.subscribe`
166
+ * delegates here.
167
+ */
168
+ readonly subscribeChrome?: (
169
+ listener: UiListener<ChromePosture>,
170
+ ) => UiUnsubscribe;
171
+ /**
172
+ * Debug attachment. The bind-side wires the runtime's telemetry bus and
173
+ * projector to the mounted debug surface (Phase Q — see
174
+ * `src/ui-tailwind/debug/`). Returns a cleanup function. Omitting the
175
+ * hook causes `ui.debug.attach` to throw rather than silently ignoring
176
+ * the request.
177
+ */
178
+ readonly attachDebug?: (session: DebugSession) => () => void;
179
+ }
180
+
181
+ /**
182
+ * Factory signature consumed by `createUiApi(handle, factory)` and by
183
+ * `createApiV3(handle, { ui: factory })` (refactor/07 Slice 2 wiring per the
184
+ * staircase in master plan §2).
185
+ *
186
+ * The factory receives the `RuntimeApiHandle` the UI API will operate
187
+ * against; the returned `UiController` provides the mounted-surface
188
+ * dispatch + subscription hooks. Passing `RuntimeApiHandle` (not
189
+ * `unknown`) means bind-side code gets the same typed seam v3 family
190
+ * modules use — no ad-hoc casts to reach the runtime shape.
191
+ */
192
+ export type UiControllerFactory = (handle: import("../_runtime-handle.ts").RuntimeApiHandle) => UiController;
193
+
194
+ export interface UiBinding {
195
+ readonly controller: UiController;
196
+ /**
197
+ * Release this specific binding. Idempotent — subsequent calls are no-ops.
198
+ * If the UI API has since been bound to a different controller, releasing
199
+ * an older binding does not affect the newer one.
200
+ */
201
+ readonly release: () => void;
202
+ }
203
+
204
+ /* ================================================================== */
205
+ /* Surface — selection + viewport (bidirectional, U3) */
206
+ /* ================================================================== */
207
+
208
+ export interface ViewportState {
209
+ readonly scrollTop: number;
210
+ readonly scrollLeft: number;
211
+ readonly width: number;
212
+ readonly height: number;
213
+ /**
214
+ * Physical pixel density — pixels per OOXML twip (the geometry facet's
215
+ * `pxPerTwip`). NOT a 1.0-is-100% zoom ratio. Review M1 (2026-04-22)
216
+ * flagged the naming as misleading: when the first semantic consumer
217
+ * reads this field, either (a) rename to `pxPerTwip`, or (b) divide
218
+ * by a known baseline at the composition site so `zoom: 1.0 = 100%`.
219
+ * No consumer reads this semantically today — keep the name for now
220
+ * because renaming is a breaking surface change.
221
+ */
222
+ readonly zoom: number;
223
+ readonly devicePixelRatio: number;
224
+ }
225
+
226
+ export type ScrollTargetBehavior = "auto" | "smooth" | "instant";
227
+
228
+ export type ScrollTarget =
229
+ | { kind: "offset"; value: number; behavior?: ScrollTargetBehavior }
230
+ | { kind: "block"; value: string; behavior?: ScrollTargetBehavior }
231
+ | { kind: "scope"; value: string; behavior?: ScrollTargetBehavior }
232
+ | { kind: "comment"; value: string; behavior?: ScrollTargetBehavior }
233
+ | { kind: "revision"; value: string; behavior?: ScrollTargetBehavior }
234
+ | { kind: "page"; value: number; behavior?: ScrollTargetBehavior };
235
+
236
+ export interface SelectionRangeInput {
237
+ readonly anchor: number;
238
+ readonly head: number;
239
+ readonly storyTarget?: SelectionSnapshot["storyTarget"];
240
+ }
241
+
242
+ /* ================================================================== */
243
+ /* Overlays — U4: anchor derivation from geometry */
244
+ /* ================================================================== */
245
+
246
+ export type OverlayAnchorQuery =
247
+ | { kind: "block"; value: string }
248
+ | { kind: "scope"; value: string }
249
+ | { kind: "comment"; value: string }
250
+ | { kind: "revision"; value: string }
251
+ | { kind: "page"; value: number }
252
+ | { kind: "selection" };
253
+
254
+ /* ================================================================== */
255
+ /* Overlay visibility — U9 (state-classes X3) */
256
+ /* ================================================================== */
257
+
258
+ /**
259
+ * Composed overlay visibility per `OverlayKind`. Returned by
260
+ * `ui.overlays.getVisibility(kind)` after merging:
261
+ * - class-A policy → `handle.getVisibilityPolicy(kind)` (L06)
262
+ * - class-C local pref → per-mounted-session preference (L10)
263
+ *
264
+ * Four discriminated states:
265
+ * - `"visible"` / `"hidden"` — policy ceded to preference (or defaulted).
266
+ * `reason` carries whether it was the authored default or the user's
267
+ * explicit preference.
268
+ * - `"forced-on"` / `"forced-off"` — policy enforcement won; local
269
+ * preference has no effect. `reason` is always `"policy-enforcement"`.
270
+ *
271
+ * The closed union makes it impossible for a consumer to render a toggle
272
+ * that would silently fail — `forced-*` states communicate "your click
273
+ * won't change this" before the user clicks.
274
+ */
275
+ export type OverlayVisibility =
276
+ | { readonly state: "visible"; readonly reason: "policy-default" | "user-preference" }
277
+ | { readonly state: "hidden"; readonly reason: "policy-default" | "user-preference" }
278
+ | { readonly state: "forced-on"; readonly reason: "policy-enforcement" }
279
+ | { readonly state: "forced-off"; readonly reason: "policy-enforcement" };
280
+
281
+ /* ================================================================== */
282
+ /* Chrome posture — U5 */
283
+ /* ================================================================== */
284
+
285
+ export type ChromeDocumentMode = "edit" | "suggest" | "comment" | "view";
286
+ export type ChromeMarkupDisplay = "final" | "markup" | "original";
287
+ export type ChromeReviewMode = "author" | "reviewer" | "observer";
288
+ export type ChromeDebugMode = "off" | "top-bar" | "full";
289
+
290
+ export interface ChromePosture {
291
+ readonly effectiveMode: ChromeDocumentMode | "blocked";
292
+ readonly documentMode: ChromeDocumentMode;
293
+ readonly readOnly: boolean;
294
+ readonly reviewMode: ChromeReviewMode;
295
+ readonly markupDisplay: ChromeMarkupDisplay;
296
+ readonly debugMode: ChromeDebugMode;
297
+ readonly chromePreset?: string;
298
+ readonly blockedReasons: readonly string[];
299
+ }
300
+
301
+ export type ChromeSurfaceKind =
302
+ | "toolbar"
303
+ | "rail"
304
+ | "sidebar"
305
+ | "command-palette"
306
+ | "context-menu"
307
+ | "top-nav";
308
+
309
+ export interface ChromeSurface {
310
+ readonly kind: ChromeSurfaceKind;
311
+ readonly id: string;
312
+ readonly visible: boolean;
313
+ readonly pinned: boolean;
314
+ }
315
+
316
+ /**
317
+ * Host-provided slice of ChromePosture. Returned by the bind-side through
318
+ * `UiController.getHostPosture`. The runtime-sourced fields (effectiveMode,
319
+ * documentMode, readOnly, blockedReasons) come from the handle; these fields
320
+ * are the host's responsibility.
321
+ */
322
+ export interface ChromeHostPosture {
323
+ readonly reviewMode?: ChromeReviewMode;
324
+ readonly markupDisplay?: ChromeMarkupDisplay;
325
+ /** MUST default to "off" at the caller level (U6); see CLAUDE.md Protected Invariants. */
326
+ readonly debugMode?: ChromeDebugMode;
327
+ readonly chromePreset?: string;
328
+ }
329
+
330
+ /* ================================================================== */
331
+ /* Debug attachment — U6 */
332
+ /* ================================================================== */
333
+
334
+ export interface DebugSession {
335
+ readonly id: string;
336
+ readonly channels: readonly string[];
337
+ }
338
+
339
+ export interface DebugAttachment {
340
+ readonly session: DebugSession;
341
+ readonly detach: () => void;
342
+ }
343
+
344
+ /* ================================================================== */
345
+ /* Subscription */
346
+ /* ================================================================== */
347
+
348
+ export type UiUnsubscribe = () => void;
349
+ export type UiListener<T> = (value: T) => void;
350
+
351
+ /* ================================================================== */
352
+ /* Namespace shape */
353
+ /* ================================================================== */
354
+
355
+ export interface ApiV3UiSession {
356
+ bind(controller: UiController): UiBinding;
357
+ getController(): UiController | null;
358
+ release(): void;
359
+ }
360
+
361
+ export interface ApiV3UiSurface {
362
+ getSelection(): SelectionSnapshot | null;
363
+ setSelection(range: SelectionRangeInput): void;
364
+ getViewport(): ViewportState;
365
+ scrollTo(target: ScrollTarget): Promise<void>;
366
+ }
367
+
368
+ export interface ApiV3UiViewport {
369
+ get(): ViewportState;
370
+ subscribe(listener: UiListener<ViewportState>): UiUnsubscribe;
371
+
372
+ /**
373
+ * X5 · Composed effective markup mode. Merges L06's class-A
374
+ * `WorkflowMarkupModePolicy` (via `handle.getMarkupModePolicy()`)
375
+ * with this instance's class-C local preference.
376
+ *
377
+ * Composition rules (parallels U9 overlay visibility):
378
+ * - `policy.enforcement === "always"` → the policy's mode wins.
379
+ * - `"authored-default"` cedes to the local preference; when none
380
+ * is set, `policy.mode` is the default.
381
+ * - No policy yet authored → `"all"` (intrinsic default: show all
382
+ * markup so a user who hasn't toggled anything sees changes).
383
+ */
384
+ getEffectiveMarkupMode(): WorkflowMarkupMode;
385
+ /** Set the per-session local preference (class C). */
386
+ setLocalMarkupMode(mode: WorkflowMarkupMode): void;
387
+ /** Clear the local preference; subsequent reads fall back to policy. */
388
+ resetLocalMarkupMode(): void;
389
+ /**
390
+ * Subscribe to effective-markup-mode changes. Fires on local-pref
391
+ * mutation AND on L06 policy-change (chained through
392
+ * `handle.subscribeMarkupModePolicy`). Returns unsubscribe.
393
+ */
394
+ subscribeEffectiveMarkupMode(
395
+ listener: UiListener<WorkflowMarkupMode>,
396
+ ): UiUnsubscribe;
397
+ }
398
+
399
+ export interface ApiV3UiOverlays {
400
+ /** Returns null when geometry is unavailable — never falls back to DOM (U4). */
401
+ getAnchor(query: OverlayAnchorQuery): GeometryRect | null;
402
+ /** Multi-rect coverage for scope envelopes. Empty array when unavailable. */
403
+ getRects(query: OverlayAnchorQuery): readonly GeometryRect[];
404
+ subscribe(listener: UiListener<OverlayAnchorQuery>): UiUnsubscribe;
405
+
406
+ /**
407
+ * U9 · Composed overlay visibility. Merges the class-A policy from
408
+ * `handle.getVisibilityPolicy(kind)` with the class-C local preference
409
+ * stored per UI API instance. `"debug-panel"` has an extra gate:
410
+ * local preference is ignored when `ChromePosture.debugMode === "off"`
411
+ * (CLAUDE.md Protected Invariant).
412
+ */
413
+ getVisibility(kind: OverlayKind): OverlayVisibility;
414
+ /** Set the per-session local preference (class C). */
415
+ setLocalPreference(kind: OverlayKind, visible: boolean): void;
416
+ /** Clear the local preference; subsequent reads fall back to policy. */
417
+ resetLocalPreference(kind: OverlayKind): void;
418
+ /**
419
+ * Subscribe to visibility changes for a specific `OverlayKind`. Fires
420
+ * when the local preference for that kind changes (via
421
+ * `setLocalPreference` / `resetLocalPreference`). Policy changes and
422
+ * `debugMode` changes are not fanned out in this slice — consumers
423
+ * that need those should re-read on their own cadence. Returns an
424
+ * unsubscribe function.
425
+ */
426
+ subscribeVisibility(
427
+ kind: OverlayKind,
428
+ listener: UiListener<OverlayVisibility>,
429
+ ): UiUnsubscribe;
430
+ }
431
+
432
+ export interface ApiV3UiChrome {
433
+ /**
434
+ * Runtime-sourced chrome posture (U5.a). Narrow slice — effectiveMode,
435
+ * documentMode, readOnly, blocked reasons, plus the host-provided
436
+ * reviewMode / markupDisplay / debugMode / chromePreset.
437
+ */
438
+ getPosture(): ChromePosture;
439
+ /**
440
+ * Full presentation-shaped chrome composition (U5.b). Takes a host-
441
+ * supplied `ChromeCompositionInput` and returns the single
442
+ * `ChromeComposition` every chrome surface reads.
443
+ *
444
+ * Rail state (`activeRailTab`, `pinnedRailTabs`) is read from the UI
445
+ * API's class-C local state when the caller omits those fields; if
446
+ * the caller supplies them, they override. That means chrome consumers
447
+ * can call `getComposition({ chromePreset, chromeOptions, reviewMode,
448
+ * role })` without re-tracking rail state — the UI API owns it.
449
+ *
450
+ * Pure under equal inputs + rail state — memoize at the caller
451
+ * boundary against whatever inputs change per render, plus the
452
+ * result of `getActiveRailTab()` / `getPinnedRailTabs()` if those
453
+ * feed into the render.
454
+ */
455
+ getComposition(input: ChromeCompositionInput): ChromeComposition;
456
+ getPinnedSurfaces(): readonly ChromeSurface[];
457
+ subscribe(listener: UiListener<ChromePosture>): UiUnsubscribe;
458
+
459
+ /**
460
+ * Class-C local rail state — which rail tab is active. Null means
461
+ * "no tab is active" (rail closed or preset suppresses rail). The UI
462
+ * API owns this state; consumers that set it expect composition
463
+ * reads to reflect the change on next call.
464
+ */
465
+ getActiveRailTab(): EditorRailTab | null;
466
+ /**
467
+ * Explicitly set the active rail tab. `null` closes the rail (no
468
+ * active tab). Subsequent `getComposition()` calls reflect this
469
+ * unless the caller supplies an explicit `activeRailTab` override.
470
+ */
471
+ setActiveRailTab(tab: EditorRailTab | null): void;
472
+
473
+ /** Snapshot of currently-pinned rail tabs (class C). */
474
+ getPinnedRailTabs(): ReadonlySet<EditorRailTab>;
475
+ /** Pin a rail tab so it stays visible even when empty. Idempotent. */
476
+ pinRailTab(tab: EditorRailTab): void;
477
+ /** Unpin a rail tab. Idempotent. */
478
+ unpinRailTab(tab: EditorRailTab): void;
479
+
480
+ /**
481
+ * Subscribe to rail-state changes (active tab or pinned set). Fires
482
+ * after every `setActiveRailTab` / `pinRailTab` / `unpinRailTab` call
483
+ * that actually mutated state. Payload is the new active tab; consumers
484
+ * that need the pinned set read via `getPinnedRailTabs()`.
485
+ */
486
+ subscribeRailState(
487
+ listener: UiListener<EditorRailTab | null>,
488
+ ): UiUnsubscribe;
489
+ }
490
+
491
+ export interface ApiV3UiDebug {
492
+ attach(session: DebugSession): DebugAttachment;
493
+ detach(): void;
494
+ }
495
+
496
+ /**
497
+ * Scope seam — mounted-path scope-bundle reads. MVP surface unblocked
498
+ * by L07's `compileScopeBundleById` handle primitive (2026-04-23).
499
+ */
500
+ export interface ApiV3UiScope {
501
+ /**
502
+ * Read the full `ScopeBundle` for a scope by id. Returns `null` when
503
+ * the scope does not enumerate today (handle drift, synthetic scope,
504
+ * marker-backed scope on a different story target, etc.). Ergonomic
505
+ * single-call wrapper — callers that need replay-deterministic
506
+ * `generatedAtUtc` use `api.ai.getScopeBundle` directly with an
507
+ * explicit clock.
508
+ */
509
+ getBundle(scopeId: string): ScopeBundle | null;
510
+ }
511
+
512
+ export interface ApiV3Ui {
513
+ readonly session: ApiV3UiSession;
514
+ readonly surface: ApiV3UiSurface;
515
+ readonly viewport: ApiV3UiViewport;
516
+ readonly overlays: ApiV3UiOverlays;
517
+ readonly chrome: ApiV3UiChrome;
518
+ readonly debug: ApiV3UiDebug;
519
+ readonly scope: ApiV3UiScope;
520
+ }