@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,364 @@
1
+ /**
2
+ * Layer 05 — Geometry facet.
3
+ *
4
+ * The `GeometryFacet` is the runtime-internal surface for concrete visual
5
+ * geometry. Per `docs/architecture/05-geometry-projection.md`, this surface
6
+ * owns rects, hit-tests, carets, anchors, and replacement envelopes; it is
7
+ * consumed by layer 07 (Runtime API) and chrome overlays.
8
+ *
9
+ * Slice 1: scaffold as a thin proxy over the layout facet.
10
+ * Slice 2a: direct path — `hitTest` / `getAnchorRects` call the moved
11
+ * pure helpers (`resolveHitTest` / `resolveAnchorRects`) against the
12
+ * render kernel's current frame.
13
+ * Slice 3: viewport becomes DOM-backed; chrome overlays subscribe.
14
+ * Slice 4: caret geometry.
15
+ * Slice 5: replacement envelope + object handles.
16
+ * Slice 6 (2026-04-22 wrapper-deletion pass): the layout-facet
17
+ * `hitTest` + `getAnchorRects` wrappers were deleted, along with the
18
+ * geometry-facet's layout-facet fallback paths. `hitTest` /
19
+ * `getAnchorRects` now return null / [] when no kernel is wired
20
+ * (headless tests, pre-paint); production always wires the kernel
21
+ * via `document-runtime.ts`.
22
+ */
23
+
24
+ import type { EditorStoryTarget } from "../../api/public-types";
25
+ import type { CanonicalDocument } from "../../model/canonical-document.ts";
26
+ import type { CanonicalDocumentEnvelope } from "../../core/state/editor-state.ts";
27
+ import type {
28
+ PublicLineBox,
29
+ PublicPageRegion,
30
+ WordReviewEditorLayoutFacet,
31
+ } from "../layout/public-facet.ts";
32
+ import type { RenderKernel } from "../render/index.ts";
33
+ import { resolveScope } from "../workflow/scope-resolver.ts";
34
+ import type { ScopeRailSegment } from "../workflow/rail/compose.ts";
35
+ import type {
36
+ AnchorQuery,
37
+ BlockGeometry,
38
+ CaretGeometry,
39
+ EnvelopeBundle,
40
+ GeometryRect,
41
+ HitTestPoint,
42
+ HitTestResult,
43
+ PageGeometry,
44
+ Viewport,
45
+ ViewportListener,
46
+ } from "./geometry-types.ts";
47
+ import {
48
+ resolveCaretGeometry,
49
+ resolveSelectionRects,
50
+ } from "./caret-geometry.ts";
51
+ import { resolveHitTest } from "./hit-test.ts";
52
+ import { resolveObjectHandles } from "./object-handles.ts";
53
+ import { resolveAnchorRects } from "./project-anchors.ts";
54
+ import {
55
+ resolveReplacementEnvelope,
56
+ type ReplacementScope,
57
+ } from "./replacement-envelope.ts";
58
+ import {
59
+ getBlockGeometryFromFrame,
60
+ getBlockRectsFromFrame,
61
+ getPageFromFrame,
62
+ } from "./project-fragments.ts";
63
+ import { createViewport, type ViewportHandle } from "./viewport.ts";
64
+
65
+ // ---------------------------------------------------------------------------
66
+ // Public surface
67
+ // ---------------------------------------------------------------------------
68
+
69
+ export interface GeometryFacet {
70
+ // Hit-test -------------------------------------------------------------
71
+ /**
72
+ * Resolve a point in the shell's overlay coordinate space to a canonical
73
+ * position. Routes directly to the render-kernel frame via
74
+ * `resolveHitTest`. Returns null when no kernel is wired (headless
75
+ * tests, pre-paint). The layout-facet fallback was deleted in the
76
+ * refactor/05 Slice 6 wrapper-deletion pass (2026-04-22).
77
+ */
78
+ hitTest(point: HitTestPoint): HitTestResult | null;
79
+
80
+ // Anchors --------------------------------------------------------------
81
+ /**
82
+ * Rect bundle for an anchor query (selection range, block id, scope id,
83
+ * etc.). Resolves directly via `resolveAnchorRects` against the render
84
+ * frame. Returns [] when no kernel is wired.
85
+ */
86
+ getAnchorRects(query: AnchorQuery): readonly GeometryRect[];
87
+
88
+ /**
89
+ * Convenience single-rect read — returns the first rect, or the union on
90
+ * spanning selections where the layout facet has already reduced it.
91
+ */
92
+ getAnchor(query: AnchorQuery): GeometryRect | null;
93
+
94
+ // Fragment projection (Slice 2b) ---------------------------------------
95
+ /**
96
+ * Rects (one per page-fragment) for a block, tagged `space: "frame"`.
97
+ * Resolves through the render kernel's frame — a multi-page block yields
98
+ * multiple rects in page order. Returns `[]` when no kernel is wired or
99
+ * the block has no fragments.
100
+ *
101
+ * New in Slice 2b. Slice 5 promotes `v3 runtime.geometry.getBlockRects`
102
+ * from `mock` to `live-with-adapter` against this method.
103
+ */
104
+ getBlockRects(blockId: string): readonly GeometryRect[];
105
+
106
+ /**
107
+ * Resolve a page by index or id. Returns the `PageGeometry` read from
108
+ * the kernel's current frame, or `null` when no kernel is wired or the
109
+ * target page is not in the frame. New in Slice 3a — the substrate
110
+ * chrome overlays consume in place of `getBoundingClientRect` on the
111
+ * overlay root.
112
+ *
113
+ * Dispatch: `typeof target === "number"` resolves as a 0-based page
114
+ * index; any other value is resolved as a `pageId` string match.
115
+ * Numeric-looking strings (e.g. `"0"`) are treated as pageIds, not
116
+ * indices — match the runtime's `RuntimePageNode.pageId` shape.
117
+ */
118
+ getPage(target: number | string): PageGeometry | null;
119
+
120
+ /**
121
+ * Resolve a block to its `BlockGeometry` (rects per page the block
122
+ * spans). Returns `null` when no kernel is wired or the block has no
123
+ * fragments. New in Slice 3a — the substrate `scroll-anchor` consumes
124
+ * in place of the `offsetTop` / `offsetParent` chain.
125
+ */
126
+ getBlock(blockId: string): BlockGeometry | null;
127
+
128
+ /**
129
+ * Per-region line boxes for a page — delegates to the layout facet's
130
+ * `getLineBoxes` since body line boxes are measured by the paginator and
131
+ * header/footer/column/footnote-area lines are synthesized from
132
+ * fragment heights (see
133
+ * `src/runtime/geometry/project-fragments.ts::collectLineBoxesForRegion`,
134
+ * moved from the layout facet in Slice 2b).
135
+ */
136
+ getLineBoxes(
137
+ pageIndex: number,
138
+ options?: { region?: PublicPageRegion["kind"]; columnIndex?: number },
139
+ ): readonly PublicLineBox[];
140
+
141
+ // Workflow-scope rail methods removed by Layer-06 Slice 4. Consume
142
+ // via `runtime.workflow.getRailSegments(pageIndex)` /
143
+ // `runtime.workflow.getAllRailSegments()`. Layer-05 geometry now
144
+ // only exposes page/anchor/caret primitives; workflow composition
145
+ // is Layer-06's responsibility.
146
+
147
+ // Caret + selection (Slice 4) -----------------------------------------
148
+ getCaret(offset: number, story?: EditorStoryTarget): CaretGeometry | null;
149
+ getSelectionRects(range: {
150
+ from: number;
151
+ to: number;
152
+ story?: EditorStoryTarget;
153
+ }): readonly GeometryRect[];
154
+
155
+ // Replacement envelope + object handles (Slice 5) ---------------------
156
+ getReplacementEnvelope(scopeId: string): EnvelopeBundle | null;
157
+ /**
158
+ * Resolve the handle points for an object. Slice-5 substrate
159
+ * addresses objects by `blockId` via `frame.anchorIndex.byBlockId`
160
+ * — so an inline image embedded in a paragraph resolves to the
161
+ * enclosing paragraph's rect, not the image's own rect. Callers
162
+ * that need per-object (not per-block) bboxes should consult the
163
+ * deferred-items list in the refactor/05 closure note: an object-
164
+ * specific anchor index is part of a later slice.
165
+ */
166
+ getObjectHandles(objectId: string): readonly GeometryRect[];
167
+
168
+ // Render-kernel passthroughs (migration target for Layer 04's
169
+ // deprecated `layoutFacet.getRenderFrame` / `.getRenderZoom`;
170
+ // tracked in `docs/plans/cross-layer-coord-05.md` §8).
171
+ //
172
+ // These return the kernel's primitive types (`RenderFrame`,
173
+ // `RenderZoom`) rather than geometry-projected types — callers that
174
+ // only need a projection should use `getPage` / `getAnchorRects` /
175
+ // `getCaret` instead. The passthroughs exist specifically so UI
176
+ // consumers (selection-anchor resolver, table-grip layer,
177
+ // scope-rail layer, object-selection overlay, PM surface) can flip
178
+ // their `layoutFacet.getRenderFrame?.()` reads onto the geometry
179
+ // facet before the layout-facet versions are deleted.
180
+ getRenderFrame(
181
+ options?: import("../render/index.ts").RenderFrameQueryOptions,
182
+ ): import("../render/index.ts").RenderFrame | null;
183
+ getRenderZoom(): import("../render/index.ts").RenderZoom | null;
184
+
185
+ // Viewport (Slice 3 wires real DOM reads) ------------------------------
186
+ getViewport(): Viewport;
187
+ subscribeViewport(listener: ViewportListener): () => void;
188
+ }
189
+
190
+ export interface CreateGeometryFacetInput {
191
+ layoutFacet: WordReviewEditorLayoutFacet;
192
+ /**
193
+ * Render-kernel getter. Geometry resolves through `resolveHitTest` /
194
+ * `resolveAnchorRects` against the kernel's current frame. When omitted
195
+ * (headless tests, pre-paint), `hitTest` returns null and
196
+ * `getAnchorRects` returns []. The layout-facet fallback was deleted in
197
+ * the refactor/05 Slice 6 wrapper-deletion pass (2026-04-22).
198
+ */
199
+ renderKernel?: () => RenderKernel | null;
200
+ /**
201
+ * Canonical document getter. Required for `getReplacementEnvelope` to
202
+ * resolve scope ids to runtime offset ranges (via `resolveScope`).
203
+ * When omitted, `getReplacementEnvelope` returns `null` — same
204
+ * fall-through used when no renderKernel is wired. Slice 5 added.
205
+ */
206
+ getCanonicalDocument?: () =>
207
+ | CanonicalDocument
208
+ | CanonicalDocumentEnvelope
209
+ | null
210
+ | undefined;
211
+ /**
212
+ * Optional viewport handle. When omitted, Slice 1's in-memory stub is
213
+ * used. Slice 3 installs a DOM-backed handle from `editor-surface`.
214
+ */
215
+ viewport?: ViewportHandle;
216
+ }
217
+
218
+ // ---------------------------------------------------------------------------
219
+ // Factory
220
+ // ---------------------------------------------------------------------------
221
+
222
+ export function createGeometryFacet(
223
+ input: CreateGeometryFacetInput,
224
+ ): GeometryFacet {
225
+ const { layoutFacet } = input;
226
+ const viewport = input.viewport ?? createViewport();
227
+
228
+ return {
229
+ hitTest(point) {
230
+ // Slice 6 wrapper-deletion (2026-04-22): the layout-facet fallback
231
+ // was deleted. `hitTest` now resolves only through the render-kernel
232
+ // frame; returns null when no kernel is wired (headless tests,
233
+ // pre-paint).
234
+ const kernel = input.renderKernel?.();
235
+ if (!kernel) return null;
236
+ const frame = kernel.getRenderFrame();
237
+ const raw = resolveHitTest(frame, { xPx: point.xPx, yPx: point.yPx });
238
+ if (!raw) return null;
239
+ return {
240
+ pageIndex: raw.pageIndex,
241
+ regionKind: raw.regionKind,
242
+ blockId: raw.blockId,
243
+ fragmentId: raw.fragmentId,
244
+ lineIndex: raw.lineIndex,
245
+ runtimeOffset: raw.runtimeOffset,
246
+ };
247
+ },
248
+
249
+ getAnchorRects(query) {
250
+ // Slice 6 wrapper-deletion: kernel-only resolution; [] when no kernel.
251
+ const kernel = input.renderKernel?.();
252
+ if (!kernel) return [];
253
+ const frame = kernel.getRenderFrame();
254
+ const raw = resolveAnchorRects(frame, {
255
+ kind: query.kind,
256
+ value: query.value,
257
+ story: query.story,
258
+ });
259
+ if (raw.length === 0) return [];
260
+ return raw.map(
261
+ (r): GeometryRect => ({
262
+ leftPx: r.leftPx,
263
+ topPx: r.topPx,
264
+ widthPx: r.widthPx,
265
+ heightPx: r.heightPx,
266
+ space: "frame",
267
+ }),
268
+ );
269
+ },
270
+
271
+ getAnchor(query) {
272
+ const rects = this.getAnchorRects(query);
273
+ return rects[0] ?? null;
274
+ },
275
+
276
+ getBlockRects(blockId) {
277
+ const kernel = input.renderKernel?.();
278
+ if (!kernel) return [];
279
+ return getBlockRectsFromFrame(kernel.getRenderFrame(), blockId);
280
+ },
281
+
282
+ getPage(target) {
283
+ const kernel = input.renderKernel?.();
284
+ if (!kernel) return null;
285
+ return getPageFromFrame(kernel.getRenderFrame(), target);
286
+ },
287
+
288
+ getBlock(blockId) {
289
+ const kernel = input.renderKernel?.();
290
+ if (!kernel) return null;
291
+ return getBlockGeometryFromFrame(kernel.getRenderFrame(), blockId);
292
+ },
293
+
294
+ getLineBoxes(pageIndex, options) {
295
+ return layoutFacet.getLineBoxes(pageIndex, options);
296
+ },
297
+
298
+ getCaret(offset, story) {
299
+ const kernel = input.renderKernel?.();
300
+ if (!kernel) return null;
301
+ return resolveCaretGeometry(kernel.getRenderFrame(), offset, story);
302
+ },
303
+
304
+ getSelectionRects(range) {
305
+ const kernel = input.renderKernel?.();
306
+ if (!kernel) return [];
307
+ return resolveSelectionRects(kernel.getRenderFrame(), range);
308
+ },
309
+
310
+ getReplacementEnvelope(scopeId) {
311
+ const kernel = input.renderKernel?.();
312
+ if (!kernel) return null;
313
+ const document = input.getCanonicalDocument?.();
314
+ if (!document) return null;
315
+ const anchor = resolveScope(document, scopeId);
316
+ if (!anchor) return null;
317
+ let scope: ReplacementScope;
318
+ if (anchor.kind === "range") {
319
+ scope = { kind: "range", from: anchor.from, to: anchor.to };
320
+ } else if (anchor.kind === "detached") {
321
+ scope = {
322
+ kind: "detached",
323
+ lastKnownRange: {
324
+ from: anchor.lastKnownRange.from,
325
+ to: anchor.lastKnownRange.to,
326
+ },
327
+ };
328
+ } else {
329
+ // node-anchor kind — not a replaceable range; caller wanted a
330
+ // range resolution. Future slice may add node-based envelopes.
331
+ return null;
332
+ }
333
+ return resolveReplacementEnvelope(kernel.getRenderFrame(), scope);
334
+ },
335
+
336
+ getObjectHandles(objectId) {
337
+ const kernel = input.renderKernel?.();
338
+ if (!kernel) return [];
339
+ return resolveObjectHandles(kernel.getRenderFrame(), objectId);
340
+ },
341
+
342
+ // Render-kernel passthroughs (migration target for layout-facet
343
+ // deprecated `getRenderFrame` / `getRenderZoom`).
344
+ getRenderFrame(options) {
345
+ const kernel = input.renderKernel?.();
346
+ if (!kernel) return null;
347
+ return kernel.getRenderFrame(options);
348
+ },
349
+
350
+ getRenderZoom() {
351
+ const kernel = input.renderKernel?.();
352
+ if (!kernel) return null;
353
+ return kernel.getZoom();
354
+ },
355
+
356
+ getViewport() {
357
+ return viewport.getViewport();
358
+ },
359
+
360
+ subscribeViewport(listener) {
361
+ return viewport.subscribe(listener);
362
+ },
363
+ };
364
+ }
@@ -0,0 +1,256 @@
1
+ /**
2
+ * Layer 05 — Geometry Projection — type surface.
3
+ *
4
+ * Per `docs/architecture/05-geometry-projection.md`, layer 05 owns concrete
5
+ * visual geometry (rects, hit-tests, carets, envelopes, anchors). This module
6
+ * defines the public type surface consumed by the `GeometryFacet` and by
7
+ * consumers through layer 07.
8
+ *
9
+ * Slice 1 (this slice) reserves the directory and publishes these types while
10
+ * the `GeometryFacet` delegates to the existing `layout/public-facet.ts` +
11
+ * `render/render-kernel.ts` sites — so the Slice-1 shapes intentionally
12
+ * mirror `RenderFrameRect`, `RenderHitResult`, and `RenderAnchorQuery` from
13
+ * `../render/render-frame-types.ts`. Slices 2+ migrate the implementations
14
+ * here and may evolve the types independently of the render-kernel shapes.
15
+ *
16
+ * Contract references (architecture 05):
17
+ * G1 — geometry is a projection of truth, not truth
18
+ * G2 — no DOM reads as document-structure authority
19
+ * G3 — all layout reads in callbacks coalesce via rAF
20
+ * G4 — invalidation is bounded by layout invalidation
21
+ * G5 — geometry coordinates are explicit (space + unit)
22
+ * G6 — hit-test, caret, and envelope are first-class operations
23
+ * G7 — replacement envelopes are stable under edits at the same scope
24
+ */
25
+
26
+ import type { EditorStoryTarget } from "../../api/public-types";
27
+ import type { PublicPageRegion } from "../layout/public-facet.ts";
28
+
29
+ // ---------------------------------------------------------------------------
30
+ // G5 · Coordinate space tags
31
+ // ---------------------------------------------------------------------------
32
+
33
+ /**
34
+ * Every `GeometryRect` carries an explicit coordinate space. Consumers choose;
35
+ * the geometry layer never silently converts.
36
+ *
37
+ * - `twips` — document-relative semantic units. Zoom-independent. The
38
+ * representation the oracle compares against.
39
+ * - `frame` — frame-local pixels, post-zoom, origin at the frame root.
40
+ * This is what the render kernel emits today.
41
+ * - `overlay`— overlay-local pixels, origin at the overlay root (for
42
+ * chrome surfaces that read rects projected through
43
+ * `chrome-overlay-projector`).
44
+ */
45
+ export type GeometrySpace = "twips" | "frame" | "overlay";
46
+
47
+ // ---------------------------------------------------------------------------
48
+ // Precision discriminator (refactor/05 Slice 7b · 2026-04-22)
49
+ // ---------------------------------------------------------------------------
50
+
51
+ /**
52
+ * Precision tag carried on geometry results so callers can tell exact
53
+ * projections from substrate placeholders.
54
+ *
55
+ * - `"exact"` — value comes from a real per-run / per-line
56
+ * projection and should be consumed as ground
57
+ * truth. Consumers may render with pixel-level
58
+ * confidence.
59
+ * - `"within-tolerance"` — value comes from a real projection but was
60
+ * widened to a conservative bound (e.g. union
61
+ * rect across a wrapped range). Safe for visual
62
+ * chrome; may overshoot by one line.
63
+ * - `"heuristic"` — value comes from a substrate placeholder:
64
+ * hardcoded direction, baseline derived from a
65
+ * height ratio, object handles derived from
66
+ * enclosing-block bbox, etc. Consumers that need
67
+ * correctness (not just visual) should fall back
68
+ * or gate.
69
+ *
70
+ * Fields are optional on existing result types for backward-compat; treat
71
+ * a missing `precision` as `"exact"` when derived from the render kernel's
72
+ * frame/anchor index, and as `"heuristic"` when the value is known to be a
73
+ * substrate placeholder (caller-side convention — the method JSDoc names
74
+ * which).
75
+ */
76
+ export type GeometryPrecision = "exact" | "within-tolerance" | "heuristic";
77
+
78
+ // ---------------------------------------------------------------------------
79
+ // Core rect shape
80
+ // ---------------------------------------------------------------------------
81
+
82
+ /**
83
+ * Rect carrying its coordinate space. Pixel-valued in `frame` / `overlay`;
84
+ * twip-valued in `twips`. Consumers read `space` before interpreting the
85
+ * numeric fields.
86
+ *
87
+ * `precision` is optional; rects emitted from exact frame/anchor projections
88
+ * omit it (implicitly exact), while rects derived from substrate placeholders
89
+ * (union-rect selection, block-bbox object handle, etc.) tag themselves so
90
+ * callers can discriminate.
91
+ */
92
+ export interface GeometryRect {
93
+ leftPx: number;
94
+ topPx: number;
95
+ widthPx: number;
96
+ heightPx: number;
97
+ space: GeometrySpace;
98
+ precision?: GeometryPrecision;
99
+ }
100
+
101
+ // ---------------------------------------------------------------------------
102
+ // Per-granularity geometry nodes (read models; Slice 2+ populates them)
103
+ // ---------------------------------------------------------------------------
104
+
105
+ export interface PageGeometry {
106
+ pageId: string;
107
+ pageIndex: number;
108
+ frame: GeometryRect;
109
+ }
110
+
111
+ export interface BlockGeometry {
112
+ blockId: string;
113
+ rects: readonly GeometryRect[];
114
+ }
115
+
116
+ export interface LineGeometry {
117
+ fragmentId: string;
118
+ lineIndex: number;
119
+ rect: GeometryRect;
120
+ /** Baseline offset from the line rect's top, in the rect's unit. */
121
+ baseline: number;
122
+ }
123
+
124
+ export interface RunGeometry {
125
+ runId: string;
126
+ rect: GeometryRect;
127
+ }
128
+
129
+ // ---------------------------------------------------------------------------
130
+ // Caret + selection (Slice 4)
131
+ // ---------------------------------------------------------------------------
132
+
133
+ export interface CaretGeometry {
134
+ rect: GeometryRect;
135
+ /** Baseline offset from `rect.topPx`, in the rect's unit. */
136
+ baseline: number;
137
+ /** Caret height in the rect's unit. */
138
+ height: number;
139
+ /** Writing direction at the caret position. */
140
+ direction: "ltr" | "rtl";
141
+ /**
142
+ * Precision tag. Substrate caret today hardcodes `direction: "ltr"`
143
+ * and derives `baseline` from a `0.8 * height` heuristic — both
144
+ * fields are flagged `"heuristic"` until the render-kernel's per-run
145
+ * anchors ship. Rect position itself comes from `byRuntimeOffset` on
146
+ * the anchor index and is `"exact"` for unwrapped paragraphs,
147
+ * `"within-tolerance"` inside wrapped paragraphs. The coarsest tag
148
+ * wins — so today `precision` is always `"heuristic"`.
149
+ */
150
+ precision?: GeometryPrecision;
151
+ }
152
+
153
+ // ---------------------------------------------------------------------------
154
+ // Hit-test (Slice 2 owns the real implementation)
155
+ // ---------------------------------------------------------------------------
156
+
157
+ export interface HitTestPoint {
158
+ xPx: number;
159
+ yPx: number;
160
+ space: GeometrySpace;
161
+ }
162
+
163
+ export interface HitTestResult {
164
+ pageIndex: number;
165
+ regionKind: PublicPageRegion["kind"];
166
+ blockId: string;
167
+ fragmentId: string;
168
+ lineIndex: number;
169
+ runtimeOffset: number;
170
+ /**
171
+ * Caret association relative to the resolved offset — reserved for Slice 4
172
+ * when caret geometry lands. Slice 1 proxy sets this to "after" to mirror
173
+ * the render-kernel's implicit association.
174
+ */
175
+ assoc?: "before" | "after";
176
+ }
177
+
178
+ // ---------------------------------------------------------------------------
179
+ // Anchor queries (Slice 2 migrates real implementation)
180
+ // ---------------------------------------------------------------------------
181
+
182
+ export type AnchorQueryKind =
183
+ | "runtime-offset"
184
+ | "block-id"
185
+ | "fragment-id"
186
+ | "scope-id"
187
+ | "comment-id"
188
+ | "revision-id"
189
+ | "page-index";
190
+
191
+ export interface AnchorQuery {
192
+ kind: AnchorQueryKind;
193
+ value: string | number;
194
+ story?: EditorStoryTarget;
195
+ }
196
+
197
+ // ---------------------------------------------------------------------------
198
+ // Replacement envelopes + object handles (Slice 5)
199
+ // ---------------------------------------------------------------------------
200
+
201
+ export type EnvelopeConfidence = "exact" | "medium" | "detached";
202
+
203
+ export interface EnvelopeBundle {
204
+ /**
205
+ * Rect coverage for the resolved scope. Slice-5 substrate produces
206
+ * **one** union rect for any non-collapsed range (mirrors the
207
+ * Slice-4 `resolveSelectionRects` contract); when the render kernel
208
+ * grows per-run anchors, this field upgrades to one-rect-per-line
209
+ * automatically. Consumers that need per-line enumeration TODAY
210
+ * should check `scopeRects.length` and fall back to their own line
211
+ * walk if the count is lower than expected.
212
+ */
213
+ scopeRects: readonly GeometryRect[];
214
+ /** Anchor point consumers attach chrome to (top-left of first rect). */
215
+ attachPoint: { xPx: number; yPx: number; space: GeometrySpace };
216
+ /**
217
+ * How confident the envelope is. `"detached"` means the scope's markers
218
+ * were removed; `lastKnownRange` describes the last observed rects.
219
+ */
220
+ confidence: EnvelopeConfidence;
221
+ /**
222
+ * Number of entries in `scopeRects` — NOT the number of line boxes
223
+ * the scope covers in the source document. Under the Slice-5
224
+ * substrate this is always `1` for non-collapsed ranges; the field
225
+ * becomes a true line-count once per-run anchors land. Renaming to
226
+ * `scopeRectCount` is tracked in the deferred-items list for the
227
+ * layer-05 closure.
228
+ */
229
+ linesCrossed: number;
230
+ /**
231
+ * Precision tag. `"exact"` when the envelope collapsed to a caret rect
232
+ * (single anchor position); `"within-tolerance"` when the envelope is
233
+ * a single union rect over a wrapped range (substrate default — may
234
+ * overshoot by up to one line of trailing whitespace); `"heuristic"`
235
+ * when the markers were detached and the envelope uses a last-known
236
+ * fallback. Consumers should gate per-line chrome work on
237
+ * `precision === "exact"`.
238
+ */
239
+ precision?: GeometryPrecision;
240
+ }
241
+
242
+ // ---------------------------------------------------------------------------
243
+ // Viewport (Slice 3 wires the real DOM read path)
244
+ // ---------------------------------------------------------------------------
245
+
246
+ export interface Viewport {
247
+ /** Scroll position of the editor root, in CSS pixels. */
248
+ scrollLeftPx: number;
249
+ scrollTopPx: number;
250
+ /** Device-pixel-ratio snapshot at read time. */
251
+ dpr: number;
252
+ /** Current zoom pxPerTwip (mirrors `RenderZoom.pxPerTwip`). */
253
+ pxPerTwip: number;
254
+ }
255
+
256
+ export type ViewportListener = (viewport: Viewport) => void;