@beyondwork/docx-react-component 1.0.67 → 1.0.70

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (384) hide show
  1. package/README.md +75 -932
  2. package/package.json +26 -27
  3. package/src/api/anchor-conversion.ts +43 -0
  4. package/src/api/editor-state-types.ts +2 -1
  5. package/src/api/public-types.ts +504 -101
  6. package/src/api/session-state.ts +4 -0
  7. package/src/api/v3/README.md +91 -0
  8. package/src/api/v3/_create.ts +146 -0
  9. package/src/api/v3/_layer-metadata.ts +362 -0
  10. package/src/api/v3/_mocks.ts +84 -0
  11. package/src/api/v3/_runtime-handle.ts +162 -0
  12. package/src/api/v3/_ux-response.ts +73 -0
  13. package/src/api/v3/ai/_metadata-audit.ts +225 -0
  14. package/src/api/v3/ai/attach.ts +235 -0
  15. package/src/api/v3/ai/bundle.ts +132 -0
  16. package/src/api/v3/ai/explain.ts +144 -0
  17. package/src/api/v3/ai/export.ts +54 -0
  18. package/src/api/v3/ai/inspect.ts +118 -0
  19. package/src/api/v3/ai/policy.ts +77 -0
  20. package/src/api/v3/ai/replacement.ts +341 -0
  21. package/src/api/v3/ai/resolve.ts +133 -0
  22. package/src/api/v3/index.ts +79 -0
  23. package/src/api/v3/runtime/chart.ts +310 -0
  24. package/src/api/v3/runtime/clipboard.ts +81 -0
  25. package/src/api/v3/runtime/collab.ts +331 -0
  26. package/src/api/v3/runtime/content.ts +236 -0
  27. package/src/api/v3/runtime/document.ts +282 -0
  28. package/src/api/v3/runtime/formatting.ts +186 -0
  29. package/src/api/v3/runtime/geometry.ts +349 -0
  30. package/src/api/v3/runtime/layout.ts +108 -0
  31. package/src/api/v3/runtime/review.ts +129 -0
  32. package/src/api/v3/runtime/search.ts +74 -0
  33. package/src/api/v3/runtime/table.ts +63 -0
  34. package/src/api/v3/runtime/workflow.ts +434 -0
  35. package/src/api/v3/ui/_context.ts +86 -0
  36. package/src/api/v3/ui/_create.ts +65 -0
  37. package/src/api/v3/ui/_types.ts +520 -0
  38. package/src/api/v3/ui/chrome-composition.ts +342 -0
  39. package/src/{ui-tailwind/chrome → api/v3/ui}/chrome-preset-model.ts +11 -1
  40. package/src/api/v3/ui/chrome.ts +476 -0
  41. package/src/api/v3/ui/debug.ts +124 -0
  42. package/src/api/v3/ui/index.ts +64 -0
  43. package/src/api/v3/ui/overlays-visibility.ts +170 -0
  44. package/src/api/v3/ui/overlays.ts +427 -0
  45. package/src/api/v3/ui/scope.ts +71 -0
  46. package/src/api/v3/ui/session.ts +100 -0
  47. package/src/api/v3/ui/surface.ts +170 -0
  48. package/src/api/v3/ui/viewport.ts +303 -0
  49. package/src/core/commands/index.ts +28 -6
  50. package/src/core/commands/list-commands.ts +3 -2
  51. package/src/core/commands/section-layout-commands.ts +9 -8
  52. package/src/core/schema/text-schema.ts +16 -0
  53. package/src/core/selection/mapping.ts +33 -72
  54. package/src/core/state/editor-state.ts +96 -189
  55. package/src/index.ts +23 -4
  56. package/src/io/chart-preview-resolver.ts +1 -1
  57. package/src/io/docx-session.ts +36 -4797
  58. package/src/io/export/build-app-properties-xml.ts +1 -1
  59. package/src/io/export/serialize-comments.ts +1 -1
  60. package/src/io/export/serialize-headers-footers.ts +6 -1
  61. package/src/io/export/serialize-main-document.ts +45 -0
  62. package/src/io/export/serialize-run-formatting.ts +17 -2
  63. package/src/io/export/twip.ts +1 -1
  64. package/src/io/normalize/normalize-text.ts +27 -20
  65. package/src/io/ooxml/chart/parse-series.ts +1 -1
  66. package/src/io/ooxml/chart/resolve-color.ts +2 -2
  67. package/src/io/ooxml/chart/types.ts +1 -1
  68. package/src/io/ooxml/classify-embedding.ts +83 -33
  69. package/src/io/ooxml/parse-fill.ts +1 -1
  70. package/src/io/ooxml/parse-main-document.ts +71 -1
  71. package/src/io/ooxml/parse-object.ts +14 -10
  72. package/src/io/ooxml/parse-run-formatting.ts +47 -1
  73. package/src/io/ooxml/property-grab-bag.ts +2 -2
  74. package/src/io/ooxml/units.ts +11 -0
  75. package/src/io/ooxml/workflow-payload.ts +282 -7
  76. package/src/model/anchor.ts +85 -0
  77. package/src/model/canonical-document.ts +351 -15
  78. package/src/model/chart-types.ts +1 -1
  79. package/src/model/layout/index.ts +83 -0
  80. package/src/model/layout/page-graph-types.ts +181 -0
  81. package/src/model/layout/page-layout-snapshot.ts +105 -0
  82. package/src/model/layout/resolved-layout-types.ts +47 -0
  83. package/src/model/layout/runtime-page-graph-types.ts +102 -0
  84. package/src/model/paragraph-scope-ids.ts +72 -0
  85. package/src/model/review/comment-types.ts +112 -0
  86. package/src/model/review/index.ts +2 -0
  87. package/src/model/review/revision-types.ts +215 -0
  88. package/src/model/snapshot.ts +32 -0
  89. package/src/review/store/comment-store.ts +21 -47
  90. package/src/review/store/revision-types.ts +40 -198
  91. package/src/runtime/collab/base-doc-fingerprint.ts +6 -1
  92. package/src/runtime/collab/runtime-collab-sync.ts +13 -3
  93. package/src/runtime/collab-session.ts +1 -1
  94. package/src/runtime/debug/build-debug-inspector-snapshot.ts +686 -0
  95. package/src/runtime/debug/event-ring-buffer.ts +64 -0
  96. package/src/runtime/debug/probability-sampler.ts +18 -0
  97. package/src/runtime/debug/runtime-debug-facet.ts +67 -0
  98. package/src/runtime/debug/stage-tokens.ts +31 -0
  99. package/src/runtime/debug/telemetry-bus.ts +271 -0
  100. package/src/runtime/debug/types.ts +275 -0
  101. package/src/runtime/debug/wrap-ref-for-telemetry.ts +118 -0
  102. package/src/runtime/document-layout.ts +8 -6
  103. package/src/runtime/document-runtime.ts +843 -1141
  104. package/src/runtime/document-search.ts +1 -1
  105. package/src/runtime/edit-ops/index.ts +1 -1
  106. package/src/runtime/external-send-runtime.ts +1 -1
  107. package/src/runtime/formatting/document-lookup.ts +235 -0
  108. package/src/runtime/formatting/field/registry.ts +41 -0
  109. package/src/runtime/{field-resolver.ts → formatting/field/resolver.ts} +27 -2
  110. package/src/runtime/formatting/font-resolution.ts +83 -0
  111. package/src/runtime/formatting/formatting-context.ts +903 -0
  112. package/src/runtime/formatting/formatting-types.ts +157 -0
  113. package/src/runtime/{hyperlink-color-resolver.ts → formatting/hyperlink-color.ts} +2 -2
  114. package/src/runtime/formatting/index.ts +125 -0
  115. package/src/runtime/{resolved-numbering-geometry.ts → formatting/numbering/geometry.ts} +1 -1
  116. package/src/runtime/{numbering-prefix.ts → formatting/numbering/prefix.ts} +170 -3
  117. package/src/runtime/formatting/paragraph-style-resolver.ts +92 -0
  118. package/src/runtime/formatting/projector.ts +75 -0
  119. package/src/runtime/formatting/resolve-effective.ts +407 -0
  120. package/src/runtime/formatting/revision-display.ts +105 -0
  121. package/src/runtime/{paragraph-style-resolver.ts → formatting/style-cascade.ts} +84 -141
  122. package/src/runtime/{table-style-resolver.ts → formatting/table-style-resolver.ts} +1 -1
  123. package/src/runtime/formatting/telemetry-bridge.ts +106 -0
  124. package/src/runtime/{theme-color-resolver.ts → formatting/theme-color.ts} +2 -30
  125. package/src/runtime/geometry/caret-geometry.ts +164 -0
  126. package/src/runtime/geometry/geometry-facet.ts +364 -0
  127. package/src/runtime/geometry/geometry-types.ts +256 -0
  128. package/src/runtime/geometry/hit-test.ts +125 -0
  129. package/src/runtime/geometry/index.ts +71 -0
  130. package/src/runtime/geometry/inert-geometry-facet.ts +43 -0
  131. package/src/runtime/geometry/invalidation.ts +35 -0
  132. package/src/runtime/geometry/object-handles.ts +77 -0
  133. package/src/runtime/geometry/overlay-rects.ts +85 -0
  134. package/src/runtime/geometry/project-anchors.ts +100 -0
  135. package/src/runtime/geometry/project-fragments.ts +216 -0
  136. package/src/runtime/geometry/projector.ts +129 -0
  137. package/src/runtime/geometry/replacement-envelope.ts +130 -0
  138. package/src/runtime/geometry/viewport.ts +218 -0
  139. package/src/runtime/layout/compat-input-ledger.ts +211 -0
  140. package/src/runtime/layout/index.ts +6 -1
  141. package/src/runtime/layout/inert-layout-facet.ts +12 -7
  142. package/src/runtime/layout/layout-engine-instance.ts +189 -11
  143. package/src/runtime/layout/layout-engine-version.ts +450 -1
  144. package/src/runtime/layout/layout-facet-types.ts +60 -0
  145. package/src/runtime/layout/layout-measurement-provider.ts +13 -0
  146. package/src/runtime/layout/measurement-backend-canvas.ts +14 -2
  147. package/src/runtime/layout/measurement-backend-empirical.ts +23 -4
  148. package/src/runtime/layout/page-graph.ts +62 -209
  149. package/src/runtime/layout/page-story-resolver.ts +7 -12
  150. package/src/runtime/layout/paginated-layout-engine.ts +186 -11
  151. package/src/runtime/layout/project-block-fragments.ts +11 -0
  152. package/src/runtime/layout/projector.ts +90 -0
  153. package/src/runtime/layout/public-facet.ts +187 -442
  154. package/src/runtime/layout/resolved-formatting-state.ts +158 -26
  155. package/src/runtime/layout/table-render-plan.ts +1 -1
  156. package/src/runtime/prerender/cache-envelope.ts +6 -1
  157. package/src/runtime/prerender/prerender-document.ts +18 -23
  158. package/src/runtime/render/decoration-resolver.ts +1 -1
  159. package/src/runtime/render/render-frame-types.ts +20 -0
  160. package/src/runtime/render/render-kernel.ts +94 -25
  161. package/src/runtime/scopes/_formatting-seam.ts +262 -0
  162. package/src/runtime/scopes/_scope-dependencies.ts +49 -0
  163. package/src/runtime/scopes/action-validation.ts +356 -0
  164. package/src/runtime/scopes/attach-explanation.ts +102 -0
  165. package/src/runtime/scopes/audit-bundle.ts +71 -0
  166. package/src/runtime/scopes/compile-scope-bundle.ts +163 -0
  167. package/src/runtime/scopes/compile-scope.ts +262 -0
  168. package/src/runtime/scopes/compiler-service.ts +431 -0
  169. package/src/runtime/scopes/create-issue.ts +107 -0
  170. package/src/runtime/scopes/enumerate-scopes.ts +543 -0
  171. package/src/runtime/scopes/evidence.ts +233 -0
  172. package/src/runtime/scopes/index.ts +150 -0
  173. package/src/runtime/scopes/position-map.ts +214 -0
  174. package/src/runtime/scopes/preservation-boundary.ts +91 -0
  175. package/src/runtime/scopes/projector.ts +49 -0
  176. package/src/runtime/scopes/replaceability.ts +87 -0
  177. package/src/runtime/scopes/replacement/apply.ts +228 -0
  178. package/src/runtime/scopes/replacement/compile.ts +59 -0
  179. package/src/runtime/scopes/replacement/propose.ts +42 -0
  180. package/src/runtime/scopes/resolve-reference.ts +347 -0
  181. package/src/runtime/scopes/review-bundle.ts +141 -0
  182. package/src/runtime/scopes/scope-kinds/_paragraph-text.ts +57 -0
  183. package/src/runtime/scopes/scope-kinds/_table-text.ts +42 -0
  184. package/src/runtime/scopes/scope-kinds/comment-thread.ts +59 -0
  185. package/src/runtime/scopes/scope-kinds/field.ts +65 -0
  186. package/src/runtime/scopes/scope-kinds/heading.ts +84 -0
  187. package/src/runtime/scopes/scope-kinds/list-item.ts +77 -0
  188. package/src/runtime/scopes/scope-kinds/paragraph.ts +182 -0
  189. package/src/runtime/scopes/scope-kinds/revision.ts +62 -0
  190. package/src/runtime/scopes/scope-kinds/table-cell.ts +57 -0
  191. package/src/runtime/scopes/scope-kinds/table-row.ts +61 -0
  192. package/src/runtime/scopes/scope-kinds/table.ts +55 -0
  193. package/src/runtime/scopes/scope-range.ts +208 -0
  194. package/src/runtime/scopes/semantic-scope-types.ts +454 -0
  195. package/src/runtime/scopes/workflow-overlap.ts +92 -0
  196. package/src/runtime/selection/index.ts +1 -1
  197. package/src/runtime/structure-ops/fragment-insert.ts +1 -1
  198. package/src/runtime/structure-ops/index.ts +1 -1
  199. package/src/runtime/surface-projection.ts +232 -262
  200. package/src/runtime/units.ts +4 -2
  201. package/src/runtime/workflow/coordinator.ts +1348 -0
  202. package/src/runtime/workflow/derived-scope-resolver.ts +125 -0
  203. package/src/runtime/workflow/index.ts +25 -0
  204. package/src/runtime/workflow/markup-mode-policy.ts +98 -0
  205. package/src/runtime/{workflow-markup.ts → workflow/markup.ts} +6 -6
  206. package/src/runtime/workflow/metadata-persistence.ts +306 -0
  207. package/src/runtime/workflow/metadata-writer.ts +123 -0
  208. package/src/runtime/workflow/overlay-store.ts +690 -0
  209. package/src/runtime/workflow/projector.ts +127 -0
  210. package/src/runtime/{query-scopes.ts → workflow/query-scopes.ts} +3 -3
  211. package/src/runtime/{workflow-rail-segments.ts → workflow/rail/compose.ts} +60 -165
  212. package/src/runtime/workflow/rail/types.ts +198 -0
  213. package/src/runtime/workflow/scope-rail-composer.ts +39 -0
  214. package/src/runtime/{scope-resolver.ts → workflow/scope-resolver.ts} +3 -3
  215. package/src/runtime/workflow/scope-writer.ts +188 -0
  216. package/src/runtime/{tamper-gate.ts → workflow/tamper-gate.ts} +1 -1
  217. package/src/runtime/workflow/visibility-policy.ts +129 -0
  218. package/src/session/_sync-legacy.ts +66 -0
  219. package/src/session/export/embedded-reconstitute.ts +104 -0
  220. package/src/session/export/export-diagnostics.ts +85 -0
  221. package/src/session/export/export-validation.ts +110 -0
  222. package/src/session/export/index.ts +34 -0
  223. package/src/session/export/preservation-reattach.ts +30 -0
  224. package/src/session/export/serialize-dispatch.ts +165 -0
  225. package/src/session/export/stateful-export-pipeline.ts +432 -0
  226. package/src/session/export/stateful-export.ts +684 -0
  227. package/src/session/import/canonical-assembly.ts +227 -0
  228. package/src/session/import/diagnostics-session.ts +54 -0
  229. package/src/session/import/embedded-discovery.ts +225 -0
  230. package/src/session/import/embedded-offload.ts +337 -0
  231. package/src/session/import/import-diagnostics.ts +69 -0
  232. package/src/session/import/loader-types.ts +313 -0
  233. package/src/session/import/loader.ts +1834 -0
  234. package/src/session/import/normalize.ts +195 -0
  235. package/src/session/import/package-parts.ts +217 -0
  236. package/src/session/import/package-read.ts +195 -0
  237. package/src/session/import/parse-orchestration.ts +105 -0
  238. package/src/session/import/part-constants.ts +70 -0
  239. package/src/session/import/part-discovery.ts +94 -0
  240. package/src/session/import/preservation-index.ts +46 -0
  241. package/src/{runtime/read-only-diagnostics-runtime.ts → session/import/read-only-diagnostics.ts} +24 -3
  242. package/src/session/import/review-import.ts +508 -0
  243. package/src/session/import/styles-consolidation.ts +281 -0
  244. package/src/session/import/workflow-scope-import.ts +256 -0
  245. package/src/session/index.ts +37 -0
  246. package/src/session/session-state.ts +69 -0
  247. package/src/session/session.ts +532 -0
  248. package/src/session/shared/protection.ts +228 -0
  249. package/src/session/shared/session-utils.ts +82 -0
  250. package/src/session/types.ts +499 -0
  251. package/src/shell/chart-snapshots.ts +96 -0
  252. package/src/shell/media-previews.ts +85 -0
  253. package/src/shell/overlay-anchor-bridge.ts +53 -0
  254. package/src/shell/paste-adapter.ts +23 -0
  255. package/src/shell/ref-commands.ts +1697 -0
  256. package/src/shell/ref-utilities.ts +48 -0
  257. package/src/shell/search.ts +51 -0
  258. package/src/{ui/editor-runtime-boundary.ts → shell/session-bootstrap.ts} +243 -67
  259. package/src/shell/ui-subscriber-channels.ts +81 -0
  260. package/src/shell/use-collab-sync.ts +116 -0
  261. package/src/ui/WordReviewEditor.tsx +496 -2051
  262. package/src/ui/editor-shell-view.tsx +30 -1
  263. package/src/ui/editor-surface-controller.tsx +49 -1
  264. package/src/ui/headless/revision-decoration-model.ts +83 -0
  265. package/src/{ui-tailwind/chrome → ui/headless}/role-action-sets.ts +1 -1
  266. package/src/ui/headless/scoped-chrome-policy.ts +2 -2
  267. package/src/ui/headless/selection-tool-context.ts +1 -1
  268. package/src/ui/headless/selection-tool-resolver.ts +1 -1
  269. package/src/ui/runtime-shortcut-dispatch.ts +46 -1
  270. package/src/ui/ui-controller-factory.ts +221 -0
  271. package/src/ui-tailwind/chart/ChartSurface.tsx +2 -2
  272. package/src/ui-tailwind/chart/layout/legend-layout.ts +1 -1
  273. package/src/ui-tailwind/chart/layout/plot-area.ts +2 -2
  274. package/src/ui-tailwind/chart/layout/title-layout.ts +1 -1
  275. package/src/ui-tailwind/chart/render/area.tsx +3 -3
  276. package/src/ui-tailwind/chart/render/bar-column.tsx +3 -3
  277. package/src/ui-tailwind/chart/render/bubble.tsx +3 -3
  278. package/src/ui-tailwind/chart/render/combo.tsx +2 -2
  279. package/src/ui-tailwind/chart/render/data-labels.tsx +2 -2
  280. package/src/ui-tailwind/chart/render/font-metrics.ts +2 -2
  281. package/src/ui-tailwind/chart/render/line.tsx +3 -3
  282. package/src/ui-tailwind/chart/render/pie.tsx +6 -6
  283. package/src/ui-tailwind/chart/render/scatter.tsx +3 -3
  284. package/src/ui-tailwind/chart/render/svg-primitives.ts +3 -3
  285. package/src/ui-tailwind/chart/render/unsupported.tsx +2 -2
  286. package/src/ui-tailwind/chrome/build-context-menu-entries.ts +88 -0
  287. package/src/ui-tailwind/chrome/chrome-preset-toolbar.tsx +1 -1
  288. package/src/ui-tailwind/chrome/collab-send-to-supplier-button.tsx +1 -1
  289. package/src/ui-tailwind/chrome/collab-tamper-banner.tsx +1 -1
  290. package/src/ui-tailwind/chrome/collab-top-nav-container.tsx +1 -1
  291. package/src/ui-tailwind/chrome/editor-action-registry.ts +553 -0
  292. package/src/ui-tailwind/chrome/editor-actions-to-palette.ts +182 -0
  293. package/src/ui-tailwind/chrome/local-surface-arbiter.ts +534 -0
  294. package/src/ui-tailwind/chrome/resolve-target-kind.ts +226 -0
  295. package/src/ui-tailwind/chrome/tw-alert-banner.tsx +38 -4
  296. package/src/ui-tailwind/chrome/tw-context-band.tsx +125 -0
  297. package/src/ui-tailwind/chrome/tw-context-menu-portal.tsx +248 -0
  298. package/src/ui-tailwind/chrome/tw-image-context-toolbar.tsx +42 -1
  299. package/src/ui-tailwind/chrome/tw-selection-anchor-resolver.ts +8 -7
  300. package/src/ui-tailwind/chrome/tw-selection-tool-blocked.tsx +38 -4
  301. package/src/ui-tailwind/chrome/tw-selection-tool-comment.tsx +104 -6
  302. package/src/ui-tailwind/chrome/tw-selection-tool-host.tsx +66 -7
  303. package/src/ui-tailwind/chrome/tw-selection-tool-workflow.tsx +54 -8
  304. package/src/ui-tailwind/chrome/tw-shortcut-hint.tsx +7 -1
  305. package/src/ui-tailwind/chrome/tw-suggestion-card.tsx +33 -0
  306. package/src/ui-tailwind/chrome/tw-table-context-toolbar.tsx +78 -1
  307. package/src/ui-tailwind/chrome/tw-table-grip-layer.tsx +16 -8
  308. package/src/ui-tailwind/chrome/tw-workspace-chrome-host.tsx +276 -0
  309. package/src/ui-tailwind/chrome/use-context-menu-controller.ts +201 -0
  310. package/src/ui-tailwind/chrome-overlay/chrome-overlay-projector.ts +1 -1
  311. package/src/ui-tailwind/chrome-overlay/tw-chrome-overlay.tsx +22 -4
  312. package/src/ui-tailwind/chrome-overlay/tw-comment-balloon-layer.tsx +1 -1
  313. package/src/ui-tailwind/chrome-overlay/tw-locked-block-layer.tsx +1 -1
  314. package/src/ui-tailwind/chrome-overlay/tw-object-selection-overlay.tsx +11 -5
  315. package/src/ui-tailwind/chrome-overlay/tw-page-stack-overlay-layer.tsx +197 -3
  316. package/src/ui-tailwind/chrome-overlay/tw-revision-margin-bar-layer.tsx +1 -1
  317. package/src/ui-tailwind/chrome-overlay/tw-scope-card-layer.tsx +35 -6
  318. package/src/ui-tailwind/chrome-overlay/tw-scope-rail-layer.tsx +24 -16
  319. package/src/ui-tailwind/chrome-overlay/tw-table-continuation-header.tsx +1 -1
  320. package/src/ui-tailwind/debug/README.md +57 -0
  321. package/src/ui-tailwind/debug/index.ts +3 -0
  322. package/src/ui-tailwind/debug/tw-debug-overlay.tsx +186 -0
  323. package/src/ui-tailwind/debug/tw-debug-presentation.tsx +80 -0
  324. package/src/ui-tailwind/debug/tw-debug-top-bar.tsx +83 -0
  325. package/src/ui-tailwind/editor-surface/chart-node-view.tsx +2 -2
  326. package/src/ui-tailwind/editor-surface/float-wrap-resolver.ts +1 -1
  327. package/src/ui-tailwind/editor-surface/pm-command-bridge.ts +135 -10
  328. package/src/ui-tailwind/editor-surface/pm-decorations.ts +40 -13
  329. package/src/ui-tailwind/editor-surface/pm-page-break-decorations.ts +1 -1
  330. package/src/ui-tailwind/editor-surface/pm-schema.ts +1 -1
  331. package/src/ui-tailwind/editor-surface/pm-state-from-snapshot.ts +3 -3
  332. package/src/ui-tailwind/editor-surface/predicted-tag-preflight.ts +1 -1
  333. package/src/ui-tailwind/editor-surface/remote-cursor-plugin.ts +2 -2
  334. package/src/ui-tailwind/editor-surface/scroll-anchor.ts +91 -9
  335. package/src/ui-tailwind/editor-surface/shape-renderer.ts +1 -1
  336. package/src/ui-tailwind/editor-surface/surface-layer.ts +1 -1
  337. package/src/ui-tailwind/editor-surface/tw-opaque-block.tsx +1 -1
  338. package/src/ui-tailwind/editor-surface/tw-page-block-view.helpers.ts +23 -6
  339. package/src/ui-tailwind/editor-surface/tw-prosemirror-surface.tsx +132 -22
  340. package/src/ui-tailwind/editor-surface/tw-table-node-view.tsx +1 -1
  341. package/src/ui-tailwind/index.ts +0 -5
  342. package/src/ui-tailwind/overlay-anchor-bridge-context.tsx +33 -0
  343. package/src/ui-tailwind/page-stack/floating-image-overlay-model.ts +66 -29
  344. package/src/ui-tailwind/page-stack/tw-floating-image-layer.tsx +25 -2
  345. package/src/ui-tailwind/review/comment-markdown-renderer.tsx +15 -0
  346. package/src/ui-tailwind/review/tw-review-rail.tsx +92 -4
  347. package/src/ui-tailwind/review/tw-workflow-tab.tsx +1 -1
  348. package/src/ui-tailwind/review-workspace/page-chrome.ts +210 -0
  349. package/src/ui-tailwind/review-workspace/page-shell-metrics.ts +101 -0
  350. package/src/ui-tailwind/review-workspace/paragraph-layout.ts +115 -0
  351. package/src/ui-tailwind/review-workspace/selection-toolbar-placement.ts +97 -0
  352. package/src/ui-tailwind/review-workspace/tw-review-workspace-navigator.tsx +130 -0
  353. package/src/ui-tailwind/review-workspace/tw-review-workspace-page-toolbar.tsx +240 -0
  354. package/src/ui-tailwind/review-workspace/tw-review-workspace-rail.tsx +59 -0
  355. package/src/ui-tailwind/review-workspace/types.ts +408 -0
  356. package/src/ui-tailwind/review-workspace/use-chrome-policy.ts +104 -0
  357. package/src/ui-tailwind/review-workspace/use-derived-view-state.ts +151 -0
  358. package/src/ui-tailwind/review-workspace/use-diagnostics-signal.ts +70 -0
  359. package/src/ui-tailwind/review-workspace/use-grabbed-segment-offsets.ts +40 -0
  360. package/src/ui-tailwind/review-workspace/use-layout-facet-render-signal.ts +55 -0
  361. package/src/ui-tailwind/review-workspace/use-page-markers.ts +130 -0
  362. package/src/ui-tailwind/review-workspace/use-pm-surface-capture.ts +60 -0
  363. package/src/ui-tailwind/review-workspace/use-review-rail-state.ts +63 -0
  364. package/src/ui-tailwind/review-workspace/use-scope-card-state.ts +170 -0
  365. package/src/ui-tailwind/review-workspace/use-scroll-root-capture.ts +28 -0
  366. package/src/ui-tailwind/review-workspace/use-selection-toolbar-placement.ts +113 -0
  367. package/src/ui-tailwind/review-workspace/use-shell-selection-anchor-bridge.ts +120 -0
  368. package/src/ui-tailwind/review-workspace/use-status-bar-page-facts.ts +55 -0
  369. package/src/ui-tailwind/review-workspace/use-viewport-dimensions.ts +43 -0
  370. package/src/ui-tailwind/review-workspace/use-workspace-arbiter.ts +25 -0
  371. package/src/ui-tailwind/review-workspace/use-workspace-composition.ts +86 -0
  372. package/src/ui-tailwind/review-workspace/use-workspace-side-effects.ts +150 -0
  373. package/src/ui-tailwind/theme/editor-theme.css +25 -0
  374. package/src/ui-tailwind/toolbar/tw-role-action-region.tsx +2 -2
  375. package/src/ui-tailwind/toolbar/tw-toolbar.tsx +61 -98
  376. package/src/ui-tailwind/tw-review-workspace.tsx +521 -1802
  377. package/src/ui-tailwind/ui-api-context.tsx +43 -0
  378. package/src/ui-tailwind/ui-shell-channels-context.tsx +49 -0
  379. package/src/validation/compatibility-engine.ts +6 -6
  380. package/src/runtime/styles-cascade.ts +0 -33
  381. package/src/ui-tailwind/chrome/tw-mode-dock.tsx +0 -85
  382. /package/src/runtime/{page-number-format.ts → formatting/field/page-number-format.ts} +0 -0
  383. /package/src/runtime/{ai-action-policy.ts → workflow/ai-action-policy.ts} +0 -0
  384. /package/src/runtime/{scope-tag-registry.ts → workflow/scope-tag-registry.ts} +0 -0
@@ -0,0 +1,281 @@
1
+ /**
2
+ * Styles-catalog + secondary-story media-catalog consolidation helpers.
3
+ *
4
+ * Slice 5e-6b of refactor/01 package-session. Extracted from
5
+ * `src/io/docx-session.ts`:
6
+ *
7
+ * - `buildStylesCatalog` — build the final `styles` facet from the
8
+ * parsed `styles.xml` (or a synthetic fallback) plus any referenced
9
+ * style ids the package didn't define.
10
+ * - `filterValidStyleIds` — narrow a parsed catalog to entries whose
11
+ * styleId matches the canonical model pattern.
12
+ * - `mergeSecondaryStoryMediaCatalog` — walk header / footer / footnote
13
+ * / endnote blocks and register every referenced media id into the
14
+ * media catalog (so images referenced only from a secondary story
15
+ * surface in `MediaCatalog.items`).
16
+ *
17
+ * Plus the one supporting helper these three compose over:
18
+ * `collectReferencedParagraphStyleIds`.
19
+ *
20
+ * Contract P6 clean: depends only on `src/model/**` + `src/io/**`
21
+ * type surfaces. No runtime / UI / core / review imports.
22
+ */
23
+
24
+ import type {
25
+ BlockNode,
26
+ CanonicalDocument,
27
+ FootnoteCollection,
28
+ FooterDocument,
29
+ HeaderDocument,
30
+ InlineNode,
31
+ MediaCatalog,
32
+ SubPartsCatalog,
33
+ } from "../../model/canonical-document.ts";
34
+ import type { ParseStylesResult } from "../../io/ooxml/parse-styles.ts";
35
+
36
+ /**
37
+ * Canonical model styleId validation pattern — styleIds that don't match
38
+ * are excluded from the catalog to avoid snapshot validation failures.
39
+ */
40
+ export const VALID_STYLE_ID = /^[A-Za-z_][A-Za-z0-9._-]{0,127}$/;
41
+
42
+ /** Walk the canonical content tree (and optional sub-parts) and collect
43
+ * every `styleId` referenced by a paragraph / table / structural block. */
44
+ export function collectReferencedParagraphStyleIds(
45
+ content: CanonicalDocument["content"],
46
+ subParts?: SubPartsCatalog,
47
+ ): Set<string> {
48
+ const styleIds = new Set<string>();
49
+
50
+ const visitBlocks = (blocks: ReadonlyArray<BlockNode>) => {
51
+ for (const block of blocks) {
52
+ if ("styleId" in block && typeof block.styleId === "string" && block.styleId.length > 0) {
53
+ styleIds.add(block.styleId);
54
+ }
55
+ if (block.type === "table") {
56
+ for (const row of block.rows) {
57
+ for (const cell of row.cells) {
58
+ visitBlocks(cell.children);
59
+ }
60
+ }
61
+ } else if (block.type === "sdt" || block.type === "custom_xml") {
62
+ visitBlocks(block.children);
63
+ }
64
+ }
65
+ };
66
+
67
+ visitBlocks(content.children);
68
+ if (subParts) {
69
+ for (const header of subParts.headers) {
70
+ visitBlocks(header.blocks);
71
+ }
72
+ for (const footer of subParts.footers) {
73
+ visitBlocks(footer.blocks);
74
+ }
75
+ if (subParts.footnoteCollection) {
76
+ for (const note of Object.values(subParts.footnoteCollection.footnotes)) {
77
+ visitBlocks(note.blocks);
78
+ }
79
+ for (const note of Object.values(subParts.footnoteCollection.endnotes)) {
80
+ visitBlocks(note.blocks);
81
+ }
82
+ }
83
+ }
84
+
85
+ return styleIds;
86
+ }
87
+
88
+ /** Narrow a parsed catalog to entries whose styleId matches the
89
+ * canonical model pattern. Used defensively when the package
90
+ * `styles.xml` carries legacy entries (e.g. numeric-only ids from Word). */
91
+ export function filterValidStyleIds(
92
+ catalog: CanonicalDocument["styles"],
93
+ ): CanonicalDocument["styles"] {
94
+ const filterRecord = <T extends { styleId: string }>(
95
+ record: Record<string, T>,
96
+ ): Record<string, T> => {
97
+ const result: Record<string, T> = {};
98
+ for (const [key, value] of Object.entries(record)) {
99
+ if (VALID_STYLE_ID.test(key)) {
100
+ result[key] = value;
101
+ }
102
+ }
103
+ return result;
104
+ };
105
+
106
+ return {
107
+ paragraphs: filterRecord(catalog.paragraphs),
108
+ characters: filterRecord(catalog.characters),
109
+ tables: filterRecord(catalog.tables),
110
+ ...(catalog.latentStyles ? { latentStyles: catalog.latentStyles } : {}),
111
+ ...(catalog.docDefaults ? { docDefaults: catalog.docDefaults } : {}),
112
+ ...(catalog.fromPackage !== undefined ? { fromPackage: catalog.fromPackage } : {}),
113
+ };
114
+ }
115
+
116
+ /** Build the `styles` facet. When the package shipped a `styles.xml`,
117
+ * the parsed catalog is filtered through {@link filterValidStyleIds}
118
+ * and any referenced-but-undefined style ids are synthesized as
119
+ * default entries. When there is no `styles.xml`, every referenced
120
+ * paragraph style becomes a synthetic entry. */
121
+ export function buildStylesCatalog(
122
+ parsedStyles: ParseStylesResult | undefined,
123
+ content: CanonicalDocument["content"],
124
+ subParts?: SubPartsCatalog,
125
+ ): CanonicalDocument["styles"] {
126
+ if (parsedStyles?.fromPackage) {
127
+ const catalog = filterValidStyleIds(parsedStyles.catalog);
128
+
129
+ const referencedIds = collectReferencedParagraphStyleIds(content, subParts);
130
+ for (const styleId of referencedIds) {
131
+ if (!catalog.paragraphs[styleId] && VALID_STYLE_ID.test(styleId)) {
132
+ catalog.paragraphs[styleId] = {
133
+ styleId,
134
+ displayName: styleId,
135
+ kind: "paragraph",
136
+ isDefault: styleId === "Normal",
137
+ };
138
+ }
139
+ }
140
+ return {
141
+ ...catalog,
142
+ fromPackage: true,
143
+ };
144
+ }
145
+
146
+ const paragraphStyles = Object.fromEntries(
147
+ [...collectReferencedParagraphStyleIds(content, subParts)]
148
+ .sort((left, right) => left.localeCompare(right))
149
+ .filter((styleId) => VALID_STYLE_ID.test(styleId))
150
+ .map((styleId) => [
151
+ styleId,
152
+ {
153
+ styleId,
154
+ displayName: styleId,
155
+ kind: "paragraph" as const,
156
+ isDefault: styleId === "Normal",
157
+ },
158
+ ]),
159
+ );
160
+ return {
161
+ paragraphs: paragraphStyles,
162
+ characters: {},
163
+ tables: {},
164
+ fromPackage: false,
165
+ };
166
+ }
167
+
168
+ /** Walk the secondary-story blocks (headers, footers, footnotes,
169
+ * endnotes) and register every referenced image / drawing-frame
170
+ * media id into the media catalog. Called after the primary story
171
+ * has contributed its own entries so we only ADD here — existing
172
+ * entries win. */
173
+ export function mergeSecondaryStoryMediaCatalog(
174
+ media: MediaCatalog,
175
+ input: {
176
+ headers: readonly HeaderDocument[];
177
+ footers: readonly FooterDocument[];
178
+ footnoteCollection?: FootnoteCollection;
179
+ mediaParts: ReadonlyMap<string, { path: string; contentType: string }>;
180
+ },
181
+ ): MediaCatalog {
182
+ const items = { ...media.items };
183
+ let changed = false;
184
+
185
+ const registerMediaItem = (
186
+ mediaId: string,
187
+ record: Omit<NonNullable<MediaCatalog["items"][string]>, "mediaId">,
188
+ ) => {
189
+ const existing = items[mediaId];
190
+ items[mediaId] = existing
191
+ ? {
192
+ ...existing,
193
+ ...record,
194
+ mediaId,
195
+ }
196
+ : {
197
+ mediaId,
198
+ ...record,
199
+ };
200
+ changed = true;
201
+ };
202
+
203
+ const visitInline = (node: InlineNode) => {
204
+ if (node.type === "image") {
205
+ const packagePartName = `/${node.mediaId.slice("media:".length)}`;
206
+ registerMediaItem(node.mediaId, {
207
+ contentType:
208
+ items[node.mediaId]?.contentType ??
209
+ input.mediaParts.get(packagePartName)?.contentType ??
210
+ "application/octet-stream",
211
+ filename: packagePartName.slice(packagePartName.lastIndexOf("/") + 1) || "image.bin",
212
+ packagePartName,
213
+ ...(node.altText ? { altText: node.altText } : {}),
214
+ });
215
+ return;
216
+ }
217
+ if (node.type === "drawing_frame" && node.content.type === "picture" && node.content.mediaId) {
218
+ const packagePartName =
219
+ typeof node.content.packagePartName === "string" && node.content.packagePartName.length > 0
220
+ ? node.content.packagePartName
221
+ : `/${node.content.mediaId.slice("media:".length)}`;
222
+ registerMediaItem(node.content.mediaId, {
223
+ contentType:
224
+ items[node.content.mediaId]?.contentType ??
225
+ input.mediaParts.get(packagePartName)?.contentType ??
226
+ "application/octet-stream",
227
+ filename: packagePartName.slice(packagePartName.lastIndexOf("/") + 1) || "image.bin",
228
+ packagePartName,
229
+ relationshipId: node.content.blipRef,
230
+ ...(node.anchor.docPr?.descr ? { altText: node.anchor.docPr.descr } : {}),
231
+ widthEmu: node.anchor.extent.widthEmu,
232
+ heightEmu: node.anchor.extent.heightEmu,
233
+ });
234
+ return;
235
+ }
236
+ if (node.type === "hyperlink" || node.type === "field") {
237
+ for (const child of node.children) {
238
+ visitInline(child);
239
+ }
240
+ }
241
+ };
242
+
243
+ const visitBlocks = (blocks: ReadonlyArray<BlockNode>) => {
244
+ for (const block of blocks) {
245
+ if (block.type === "paragraph") {
246
+ for (const child of block.children) {
247
+ visitInline(child);
248
+ }
249
+ continue;
250
+ }
251
+ if (block.type === "table") {
252
+ for (const row of block.rows) {
253
+ for (const cell of row.cells) {
254
+ visitBlocks(cell.children);
255
+ }
256
+ }
257
+ continue;
258
+ }
259
+ if (block.type === "sdt" || block.type === "custom_xml") {
260
+ visitBlocks(block.children);
261
+ }
262
+ }
263
+ };
264
+
265
+ for (const header of input.headers) {
266
+ visitBlocks(header.blocks);
267
+ }
268
+ for (const footer of input.footers) {
269
+ visitBlocks(footer.blocks);
270
+ }
271
+ if (input.footnoteCollection) {
272
+ for (const note of Object.values(input.footnoteCollection.footnotes)) {
273
+ visitBlocks(note.blocks);
274
+ }
275
+ for (const note of Object.values(input.footnoteCollection.endnotes)) {
276
+ visitBlocks(note.blocks);
277
+ }
278
+ }
279
+
280
+ return changed ? { ...media, items } : media;
281
+ }
@@ -0,0 +1,256 @@
1
+ /**
2
+ * CLM-workflow translation helpers extracted from `src/io/docx-session.ts`
3
+ * (slice 5e-6e). These functions lift `CLM:<TAG>:<description>` comment
4
+ * directives into workflow scopes + work items on a `WorkflowOverlay`,
5
+ * and auto-resolve the originating comment threads.
6
+ *
7
+ * P6-clean: `CommentThread` reaches through `src/model/review/`; every
8
+ * workflow type comes from `src/api/public-types.ts` (an allowed surface
9
+ * for the session layer). Anchor-shape conversion reaches through the
10
+ * shared boundary helper at `src/api/anchor-conversion.ts` (relocated in
11
+ * slice 5e-6g).
12
+ */
13
+
14
+ import { toPublicAnchorProjection } from "../../api/anchor-conversion.ts";
15
+ import type {
16
+ WorkflowMetadataSnapshot,
17
+ WorkflowOverlay,
18
+ WorkflowScope,
19
+ WorkflowScopeMetadataField,
20
+ WorkflowWorkItem,
21
+ } from "../../api/public-types.ts";
22
+ import type { CommentThread } from "../../model/review/comment-types.ts";
23
+ import {
24
+ rangesIntersect,
25
+ resolveImportedCommentThreadOnTranslation,
26
+ } from "./review-import.ts";
27
+
28
+ export function translateClmCommentsToWorkflow(input: {
29
+ comments: readonly CommentThread[];
30
+ workflowOverlay?: WorkflowOverlay;
31
+ workflowMetadata?: WorkflowMetadataSnapshot;
32
+ timestamp: string;
33
+ }): {
34
+ comments: CommentThread[];
35
+ workflowOverlay?: WorkflowOverlay;
36
+ workflowMetadata?: WorkflowMetadataSnapshot;
37
+ } {
38
+ const nextComments = input.comments.map((thread) => structuredClone(thread));
39
+ let nextOverlay = input.workflowOverlay ? structuredClone(input.workflowOverlay) : undefined;
40
+ let overlayChanged = false;
41
+
42
+ for (const [index, thread] of nextComments.entries()) {
43
+ const directive = parseClmCommentDirective(thread);
44
+ if (!directive || thread.anchor.kind !== "range") {
45
+ continue;
46
+ }
47
+
48
+ if (!nextOverlay) {
49
+ nextOverlay = {
50
+ overlayVersion: "workflow-overlay/1",
51
+ scopes: [],
52
+ };
53
+ }
54
+
55
+ const existingScope = findExistingClmScope(nextOverlay.scopes, directive);
56
+ if (!existingScope) {
57
+ const version = getNextClmScopeVersion(nextOverlay.scopes, thread.anchor);
58
+ const scopeId = `clm-scope-${thread.commentId}-v${version}`;
59
+ const workItem = directive.tag === "TASK"
60
+ ? createClmWorkflowWorkItem(thread, directive.description, scopeId)
61
+ : undefined;
62
+ const scope = createClmWorkflowScope(thread, directive, version, scopeId, workItem?.workItemId);
63
+
64
+ nextOverlay.scopes = [...nextOverlay.scopes, scope];
65
+ if (workItem) {
66
+ nextOverlay.workItems = [...(nextOverlay.workItems ?? []), workItem];
67
+ if (!nextOverlay.activeWorkItemId) {
68
+ nextOverlay.activeWorkItemId = workItem.workItemId;
69
+ }
70
+ }
71
+ overlayChanged = true;
72
+ }
73
+
74
+ nextComments[index] = resolveImportedCommentThreadOnTranslation(thread, input.timestamp);
75
+ }
76
+
77
+ return {
78
+ comments: nextComments,
79
+ workflowOverlay: overlayChanged || input.workflowOverlay ? nextOverlay : undefined,
80
+ workflowMetadata: input.workflowMetadata,
81
+ };
82
+ }
83
+
84
+ export function parseClmCommentDirective(
85
+ thread: CommentThread,
86
+ ): { tag: "TASK" | "READ" | "COMMENT" | "EDIT"; description: string; sourceCommentId: string; sourceCommentDurableId?: string; sourceCommentParaId?: string; mode: WorkflowScope["mode"] } | undefined {
87
+ if (thread.metadata?.rootParaId === undefined && thread.entries[0]?.metadata?.parentParaId) {
88
+ return undefined;
89
+ }
90
+ const firstMeaningfulLine = thread.entries
91
+ .flatMap((entry) => entry.body.split(/\r?\n/u))
92
+ .map((line) => line.trim())
93
+ .find((line) => line.length > 0);
94
+ if (!firstMeaningfulLine) {
95
+ return undefined;
96
+ }
97
+ const match = /^CLM:([A-Z]+):(.*)$/u.exec(firstMeaningfulLine);
98
+ if (!match) {
99
+ return undefined;
100
+ }
101
+ const tag = match[1] as "TASK" | "READ" | "COMMENT" | "EDIT";
102
+ const description = (match[2] ?? "").trim();
103
+ const mode = getClmWorkflowScopeMode(tag);
104
+ if (!mode || description.length === 0) {
105
+ return undefined;
106
+ }
107
+ return {
108
+ tag,
109
+ description,
110
+ sourceCommentId: thread.metadata?.rootOoxmlCommentId ?? thread.commentId,
111
+ sourceCommentDurableId: thread.entries[0]?.metadata?.durableId,
112
+ sourceCommentParaId: thread.metadata?.rootParaId ?? thread.entries[0]?.metadata?.paraId,
113
+ mode,
114
+ };
115
+ }
116
+
117
+ export function getClmWorkflowScopeMode(tag: string): WorkflowScope["mode"] | undefined {
118
+ switch (tag) {
119
+ case "TASK":
120
+ return "suggest";
121
+ case "READ":
122
+ return "view";
123
+ case "COMMENT":
124
+ return "comment";
125
+ case "EDIT":
126
+ return "edit";
127
+ default:
128
+ return undefined;
129
+ }
130
+ }
131
+
132
+ export function createClmWorkflowWorkItem(
133
+ thread: CommentThread,
134
+ description: string,
135
+ scopeId: string,
136
+ ): WorkflowWorkItem {
137
+ return {
138
+ workItemId: `clm-task-${thread.commentId}`,
139
+ title: description,
140
+ description,
141
+ status: "pending",
142
+ scopeIds: [scopeId],
143
+ };
144
+ }
145
+
146
+ export function createClmWorkflowScope(
147
+ thread: CommentThread,
148
+ directive: NonNullable<ReturnType<typeof parseClmCommentDirective>>,
149
+ version: number,
150
+ scopeId: string,
151
+ workItemId?: string,
152
+ ): WorkflowScope {
153
+ if (workItemId) {
154
+ return {
155
+ scopeId,
156
+ version,
157
+ mode: directive.mode,
158
+ anchor: toPublicAnchorProjection(thread.anchor),
159
+ storyTarget: { kind: "main" },
160
+ workItemId,
161
+ label: directive.description,
162
+ metadata: createClmScopeMetadata(directive),
163
+ };
164
+ }
165
+ return {
166
+ scopeId,
167
+ version,
168
+ mode: directive.mode,
169
+ anchor: toPublicAnchorProjection(thread.anchor),
170
+ storyTarget: { kind: "main" },
171
+ label: directive.description,
172
+ metadata: createClmScopeMetadata(directive),
173
+ };
174
+ }
175
+
176
+ export function createClmScopeMetadata(
177
+ directive: NonNullable<ReturnType<typeof parseClmCommentDirective>>,
178
+ ): WorkflowScopeMetadataField[] {
179
+ return [
180
+ {
181
+ key: "workblock.clm.tag",
182
+ valueType: "string",
183
+ value: directive.tag,
184
+ },
185
+ {
186
+ key: "workblock.clm.description",
187
+ valueType: "string",
188
+ value: directive.description,
189
+ },
190
+ {
191
+ key: "workblock.sourceCommentId",
192
+ valueType: "string",
193
+ value: directive.sourceCommentId,
194
+ },
195
+ ...(directive.sourceCommentDurableId
196
+ ? [{
197
+ key: "workblock.sourceCommentDurableId",
198
+ valueType: "string" as const,
199
+ value: directive.sourceCommentDurableId,
200
+ }]
201
+ : []),
202
+ ...(directive.sourceCommentParaId
203
+ ? [{
204
+ key: "workblock.sourceCommentParaId",
205
+ valueType: "string" as const,
206
+ value: directive.sourceCommentParaId,
207
+ }]
208
+ : []),
209
+ ];
210
+ }
211
+
212
+ export function findExistingClmScope(
213
+ scopes: readonly WorkflowScope[],
214
+ directive: NonNullable<ReturnType<typeof parseClmCommentDirective>>,
215
+ ): WorkflowScope | undefined {
216
+ return scopes.find((scope) => {
217
+ const sourceCommentId = getWorkflowScopeMetadataValue(scope.metadata, "workblock.sourceCommentId");
218
+ const sourceCommentDurableId = getWorkflowScopeMetadataValue(
219
+ scope.metadata,
220
+ "workblock.sourceCommentDurableId",
221
+ );
222
+ return (
223
+ sourceCommentId === directive.sourceCommentId ||
224
+ (directive.sourceCommentDurableId !== undefined &&
225
+ sourceCommentDurableId === directive.sourceCommentDurableId)
226
+ );
227
+ });
228
+ }
229
+
230
+ export function getWorkflowScopeMetadataValue(
231
+ metadata: WorkflowScope["metadata"] | undefined,
232
+ key: string,
233
+ ): string | undefined {
234
+ const field = metadata?.find((entry) => entry.key === key);
235
+ return typeof field?.value === "string" ? field.value : undefined;
236
+ }
237
+
238
+ export function getNextClmScopeVersion(
239
+ scopes: readonly WorkflowScope[],
240
+ anchor: Extract<CommentThread["anchor"], { kind: "range" }>,
241
+ ): number {
242
+ const anchorRange = {
243
+ from: anchor.range.from,
244
+ to: anchor.range.to,
245
+ };
246
+ const overlappingVersions = scopes.flatMap((scope) => {
247
+ if (scope.anchor.kind !== "range") {
248
+ return [];
249
+ }
250
+ return rangesIntersect(scope.anchor, anchorRange) && typeof scope.version === "number"
251
+ ? [scope.version]
252
+ : [];
253
+ });
254
+ return overlappingVersions.length > 0 ? Math.max(...overlappingVersions) + 1 : 1;
255
+ }
256
+
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Public barrel for Layer 01 (package / session).
3
+ *
4
+ * Reserved shape — matches `docs/architecture/01-package-session.md`
5
+ * § Public entry points. Consumers should import from `src/session`
6
+ * (or the `@beyondwork/docx-react-component/session` package subpath)
7
+ * rather than reaching into `src/io/docx-session.ts`. The legacy entry
8
+ * points remain exported from the root barrel for back-compat until
9
+ * Slice 5 deletes them.
10
+ */
11
+
12
+ export {
13
+ DocxSession,
14
+ SessionNotOpenError,
15
+ SessionNotWiredError,
16
+ } from "./session.ts";
17
+ export { isReopenBarrier } from "./types.ts";
18
+ export type { EditorSessionState } from "./session-state.ts";
19
+ export type {
20
+ // Reserved Layer-01 contract types.
21
+ OpenOptions,
22
+ OpenResult,
23
+ ExportOptions,
24
+ ValidateOptions,
25
+ ValidationReport,
26
+ ValidationFinding,
27
+ PreservationSnapshot,
28
+ EmbeddedDocumentManifest,
29
+ // P8 Step 7 offload surface.
30
+ ReopenBarrier,
31
+ // Transitional re-exports from the legacy IO layer.
32
+ ExportResult,
33
+ EditorHostAdapter,
34
+ ExportDocxOptions,
35
+ LoadStage,
36
+ PersistedEditorSnapshot,
37
+ } from "./types.ts";
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Canonical definition of `EditorSessionState` — the host-facing session
3
+ * contract produced by Layer 01 on open and consumed on export.
4
+ *
5
+ * Moved here from `src/api/public-types.ts` in refactor/01 slice 3f
6
+ * (F5). `src/api/public-types.ts` now re-exports for back-compat; the
7
+ * owning module is this file.
8
+ *
9
+ * P6 clean: imports only from `src/model/**` (allowed) and `src/api/**`
10
+ * (allowed; type-only to avoid runtime coupling with the presentation
11
+ * surface).
12
+ */
13
+
14
+ import type { PersistedEditorSnapshot as ModelPersistedEditorSnapshot } from "../model/snapshot.ts";
15
+ import type {
16
+ CompatibilityReport,
17
+ EditorWarning,
18
+ OverlayVisibilityPolicy,
19
+ ProtectionSnapshot,
20
+ WorkflowMarkupModePolicy,
21
+ WorkflowMetadataSnapshot,
22
+ WorkflowOverlay,
23
+ } from "../api/public-types.ts";
24
+
25
+ /**
26
+ * Durable projection of an editor session suitable for persistence and
27
+ * rehydration. The shape is versioned independently from the model
28
+ * snapshot so that host-facing fields (e.g. `editorBuild`, warning log)
29
+ * can evolve without forcing model-layer version bumps.
30
+ *
31
+ * Semantic contract:
32
+ * - `canonicalDocument` round-trips exactly through the `src/model/**`
33
+ * serializer/validator. Layer 01 does not mutate canonical fields
34
+ * during open/export.
35
+ * - `sourcePackage`, when present, carries the opaque OPC package
36
+ * reference the session opened from. Omit to materialize a session
37
+ * with no byte-source (host-authored content, test fixtures).
38
+ */
39
+ export interface EditorSessionState {
40
+ sessionVersion: "editor-session-state/1";
41
+ schemaVersion: ModelPersistedEditorSnapshot["schemaVersion"];
42
+ documentId: string;
43
+ docId: string;
44
+ createdAt: string;
45
+ updatedAt: string;
46
+ editorBuild: string;
47
+ canonicalDocument: ModelPersistedEditorSnapshot["canonicalDocument"];
48
+ compatibility: CompatibilityReport;
49
+ warningLog: EditorWarning[];
50
+ protectionSnapshot?: ProtectionSnapshot;
51
+ sourcePackage?: ModelPersistedEditorSnapshot["sourcePackage"];
52
+ workflowOverlay?: WorkflowOverlay;
53
+ workflowMetadata?: WorkflowMetadataSnapshot;
54
+ /**
55
+ * W10 — class-A overlay-visibility policies. Zero or more entries,
56
+ * at most one per `OverlayKind`. Empty array when the document
57
+ * carries no authored policy (consumers fall back to class-C local
58
+ * preference defaults). Persists via `customXml/item1.xml` under the
59
+ * `bw:overlayVisibility` namespace.
60
+ */
61
+ visibilityPolicies?: readonly OverlayVisibilityPolicy[];
62
+ /**
63
+ * X5 — class-A markup-mode policy. Single record; `undefined` when
64
+ * the document carries no authored mode (consumers fall back to the
65
+ * class-C local preference). Persists via `customXml/item1.xml`
66
+ * under the `bw:markupModePolicy` namespace.
67
+ */
68
+ markupModePolicy?: WorkflowMarkupModePolicy;
69
+ }