@beyondwork/docx-react-component 1.0.29 → 1.0.30

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 (381) hide show
  1. package/package.json +65 -96
  2. package/src/README.md +85 -0
  3. package/src/api/README.md +26 -0
  4. package/src/api/public-types.ts +1952 -0
  5. package/src/api/session-state.ts +62 -0
  6. package/src/compare/diff-engine.ts +623 -0
  7. package/src/compare/export-redlines.ts +280 -0
  8. package/src/compare/index.ts +25 -0
  9. package/src/compare/snapshot.ts +97 -0
  10. package/src/component-inventory.md +99 -0
  11. package/src/core/README.md +10 -0
  12. package/src/core/commands/README.md +3 -0
  13. package/{dist/chunk-TJBP2K4T.js → src/core/commands/formatting-commands.ts} +536 -196
  14. package/src/core/commands/image-commands.ts +373 -0
  15. package/src/core/commands/index.ts +1879 -0
  16. package/src/core/commands/list-commands.ts +565 -0
  17. package/src/core/commands/paragraph-layout-commands.ts +339 -0
  18. package/src/core/commands/review-commands.ts +108 -0
  19. package/{dist/core/commands/section-layout-commands.cjs → src/core/commands/section-layout-commands.ts} +340 -137
  20. package/src/core/commands/structural-helpers.ts +309 -0
  21. package/{dist/core/commands/style-commands.cjs → src/core/commands/style-commands.ts} +113 -65
  22. package/src/core/commands/table-structure-commands.ts +854 -0
  23. package/{dist/chunk-UZXBISGO.js → src/core/commands/text-commands.ts} +142 -86
  24. package/src/core/schema/README.md +3 -0
  25. package/src/core/schema/text-schema.ts +516 -0
  26. package/src/core/search/search-text.ts +357 -0
  27. package/src/core/selection/README.md +3 -0
  28. package/src/core/selection/mapping.ts +289 -0
  29. package/src/core/selection/review-anchors.ts +183 -0
  30. package/src/core/state/README.md +3 -0
  31. package/src/core/state/editor-state.ts +892 -0
  32. package/src/core/state/text-transaction.ts +869 -0
  33. package/src/formats/xlsx/io/parse-shared-strings.ts +41 -0
  34. package/src/formats/xlsx/io/parse-sheet.ts +459 -0
  35. package/src/formats/xlsx/io/parse-styles.ts +59 -0
  36. package/src/formats/xlsx/io/parse-workbook.ts +75 -0
  37. package/src/formats/xlsx/io/serialize-shared-strings.ts +72 -0
  38. package/src/formats/xlsx/io/serialize-sheet.ts +333 -0
  39. package/src/formats/xlsx/io/serialize-styles.ts +98 -0
  40. package/src/formats/xlsx/io/serialize-workbook.ts +429 -0
  41. package/src/formats/xlsx/io/xlsx-session.ts +314 -0
  42. package/src/formats/xlsx/model/cell.ts +189 -0
  43. package/src/formats/xlsx/model/sheet.ts +326 -0
  44. package/src/formats/xlsx/model/styles.ts +118 -0
  45. package/src/formats/xlsx/model/workbook.ts +453 -0
  46. package/src/formats/xlsx/runtime/cell-commands.ts +567 -0
  47. package/src/formats/xlsx/runtime/sheet-commands.ts +206 -0
  48. package/src/formats/xlsx/runtime/workbook-runtime.ts +177 -0
  49. package/src/formats/xlsx/runtime/workbook-transaction.ts +822 -0
  50. package/src/index.ts +142 -0
  51. package/src/io/README.md +10 -0
  52. package/src/io/docx-session.ts +3175 -0
  53. package/src/io/export/README.md +3 -0
  54. package/src/io/export/export-session.ts +220 -0
  55. package/src/io/export/minimal-docx.ts +115 -0
  56. package/src/io/export/reattach-preserved-parts.ts +54 -0
  57. package/src/io/export/serialize-comments.ts +947 -0
  58. package/src/io/export/serialize-footnotes.ts +394 -0
  59. package/src/io/export/serialize-headers-footers.ts +368 -0
  60. package/src/io/export/serialize-main-document.ts +1342 -0
  61. package/src/io/export/serialize-numbering.ts +218 -0
  62. package/src/io/export/serialize-revisions.ts +389 -0
  63. package/src/io/export/serialize-runtime-revisions.ts +463 -0
  64. package/src/io/export/serialize-tables.ts +174 -0
  65. package/src/io/export/split-review-boundaries.ts +356 -0
  66. package/src/io/export/split-story-blocks-for-runtime-revisions.ts +252 -0
  67. package/src/io/export/table-properties-xml.ts +318 -0
  68. package/src/io/normalize/README.md +3 -0
  69. package/src/io/normalize/normalize-text.ts +670 -0
  70. package/src/io/ooxml/README.md +3 -0
  71. package/src/io/ooxml/highlight-colors.ts +39 -0
  72. package/src/io/ooxml/numbering-sentinels.ts +44 -0
  73. package/src/io/ooxml/parse-comments.ts +852 -0
  74. package/src/io/ooxml/parse-complex-content.ts +287 -0
  75. package/src/io/ooxml/parse-fields.ts +834 -0
  76. package/src/io/ooxml/parse-footnotes.ts +952 -0
  77. package/src/io/ooxml/parse-headers-footers.ts +1212 -0
  78. package/src/io/ooxml/parse-inline-media.ts +461 -0
  79. package/src/io/ooxml/parse-main-document.ts +2947 -0
  80. package/src/io/ooxml/parse-numbering.ts +747 -0
  81. package/src/io/ooxml/parse-revisions.ts +1045 -0
  82. package/src/io/ooxml/parse-settings.ts +184 -0
  83. package/src/io/ooxml/parse-shapes.ts +296 -0
  84. package/src/io/ooxml/parse-styles.ts +639 -0
  85. package/src/io/ooxml/parse-tables.ts +627 -0
  86. package/src/io/ooxml/parse-theme.ts +346 -0
  87. package/src/io/ooxml/part-manifest.ts +136 -0
  88. package/src/io/ooxml/revision-boundaries.ts +475 -0
  89. package/src/io/ooxml/workflow-payload.ts +544 -0
  90. package/src/io/opc/README.md +3 -0
  91. package/src/io/opc/corrupt-package.ts +166 -0
  92. package/src/io/opc/docx-package.ts +74 -0
  93. package/src/io/opc/package-reader.ts +325 -0
  94. package/src/io/opc/package-writer.ts +273 -0
  95. package/src/io/source-package-provenance.ts +241 -0
  96. package/{dist/chunk-RMH72RZI.js → src/legal/bookmarks.ts} +130 -44
  97. package/src/legal/cross-references.ts +414 -0
  98. package/src/legal/defined-terms.ts +203 -0
  99. package/src/legal/index.ts +32 -0
  100. package/src/legal/signature-blocks.ts +259 -0
  101. package/src/model/README.md +3 -0
  102. package/src/model/canonical-document.ts +2722 -0
  103. package/src/model/cds-1.0.0.ts +212 -0
  104. package/src/model/snapshot.ts +760 -0
  105. package/src/preservation/README.md +3 -0
  106. package/src/preservation/markup-compatibility.ts +48 -0
  107. package/src/preservation/opaque-fragment-store.ts +89 -0
  108. package/src/preservation/opaque-region.ts +233 -0
  109. package/src/preservation/package-preservation.ts +113 -0
  110. package/src/preservation/preserved-part-manifest.ts +56 -0
  111. package/src/preservation/relationship-retention.ts +57 -0
  112. package/src/preservation/store.ts +255 -0
  113. package/src/review/README.md +16 -0
  114. package/src/review/store/README.md +3 -0
  115. package/src/review/store/comment-anchors.ts +70 -0
  116. package/src/review/store/comment-remapping.ts +154 -0
  117. package/src/review/store/comment-store.ts +349 -0
  118. package/src/review/store/comment-thread.ts +109 -0
  119. package/src/review/store/revision-actions.ts +423 -0
  120. package/src/review/store/revision-store.ts +323 -0
  121. package/src/review/store/revision-types.ts +182 -0
  122. package/src/review/store/runtime-comment-store.ts +43 -0
  123. package/src/runtime/README.md +3 -0
  124. package/src/runtime/ai-action-policy.ts +764 -0
  125. package/src/runtime/context-analytics.ts +824 -0
  126. package/src/runtime/document-layout.ts +332 -0
  127. package/src/runtime/document-locations.ts +521 -0
  128. package/src/runtime/document-navigation.ts +616 -0
  129. package/src/runtime/document-outline.ts +440 -0
  130. package/src/runtime/document-runtime.ts +4055 -0
  131. package/src/runtime/document-search.ts +145 -0
  132. package/src/runtime/event-refresh-hints.ts +137 -0
  133. package/src/runtime/numbering-prefix.ts +244 -0
  134. package/src/runtime/page-layout-estimation.ts +305 -0
  135. package/src/runtime/read-only-diagnostics-runtime.ts +241 -0
  136. package/src/runtime/resolved-numbering-geometry.ts +293 -0
  137. package/src/runtime/review-runtime.ts +44 -0
  138. package/src/runtime/revision-runtime.ts +107 -0
  139. package/src/runtime/session-capabilities.ts +192 -0
  140. package/src/runtime/story-context.ts +164 -0
  141. package/src/runtime/story-targeting.ts +162 -0
  142. package/src/runtime/suggestions-snapshot.ts +137 -0
  143. package/src/runtime/surface-projection.ts +1553 -0
  144. package/src/runtime/table-commands.ts +173 -0
  145. package/src/runtime/table-schema.ts +309 -0
  146. package/src/runtime/table-style-resolver.ts +409 -0
  147. package/src/runtime/view-state.ts +493 -0
  148. package/src/runtime/virtualized-rendering.ts +258 -0
  149. package/src/runtime/workflow-markup.ts +393 -0
  150. package/src/ui/README.md +30 -0
  151. package/src/ui/WordReviewEditor.tsx +5268 -0
  152. package/src/ui/browser-export.ts +52 -0
  153. package/src/ui/comments/README.md +3 -0
  154. package/src/ui/compatibility/README.md +3 -0
  155. package/src/ui/editor-command-bag.ts +127 -0
  156. package/src/ui/editor-runtime-boundary.ts +1558 -0
  157. package/src/ui/editor-shell-view.tsx +144 -0
  158. package/src/ui/editor-surface/README.md +3 -0
  159. package/src/ui/editor-surface-controller.tsx +66 -0
  160. package/src/ui/headless/comment-decoration-model.ts +124 -0
  161. package/src/ui/headless/preserve-editor-selection.ts +5 -0
  162. package/src/ui/headless/revision-decoration-model.ts +128 -0
  163. package/src/ui/headless/selection-helpers.ts +54 -0
  164. package/src/ui/headless/selection-tool-context.ts +19 -0
  165. package/src/ui/headless/selection-tool-resolver.ts +752 -0
  166. package/src/ui/headless/selection-tool-types.ts +129 -0
  167. package/src/ui/headless/selection-toolbar-model.ts +11 -0
  168. package/src/ui/headless/use-editor-keyboard.ts +103 -0
  169. package/src/ui/review/README.md +3 -0
  170. package/src/ui/runtime-shortcut-dispatch.ts +365 -0
  171. package/src/ui/runtime-snapshot-selectors.ts +197 -0
  172. package/src/ui/shared/revision-filters.ts +31 -0
  173. package/src/ui/status/README.md +3 -0
  174. package/src/ui/theme/README.md +3 -0
  175. package/src/ui/toolbar/README.md +3 -0
  176. package/src/ui/workflow-surface-blocked-rails.ts +94 -0
  177. package/src/ui-tailwind/chrome/chrome-preset-model.ts +107 -0
  178. package/src/ui-tailwind/chrome/chrome-preset-toolbar.tsx +15 -0
  179. package/src/ui-tailwind/chrome/review-queue-bar.tsx +97 -0
  180. package/src/ui-tailwind/chrome/tw-alert-banner.tsx +64 -0
  181. package/src/ui-tailwind/chrome/tw-context-analytics-summary.tsx +122 -0
  182. package/src/ui-tailwind/chrome/tw-image-context-toolbar.tsx +121 -0
  183. package/src/ui-tailwind/chrome/tw-layout-panel.tsx +114 -0
  184. package/src/ui-tailwind/chrome/tw-object-context-toolbar.tsx +30 -0
  185. package/src/ui-tailwind/chrome/tw-page-ruler.tsx +365 -0
  186. package/src/ui-tailwind/chrome/tw-selection-tool-blocked.tsx +23 -0
  187. package/src/ui-tailwind/chrome/tw-selection-tool-comment.tsx +35 -0
  188. package/src/ui-tailwind/chrome/tw-selection-tool-formatting.tsx +37 -0
  189. package/src/ui-tailwind/chrome/tw-selection-tool-host.tsx +298 -0
  190. package/src/ui-tailwind/chrome/tw-selection-tool-structure.tsx +116 -0
  191. package/src/ui-tailwind/chrome/tw-selection-tool-suggestion.tsx +29 -0
  192. package/src/ui-tailwind/chrome/tw-selection-tool-workflow.tsx +27 -0
  193. package/src/ui-tailwind/chrome/tw-selection-toolbar.tsx +186 -0
  194. package/src/ui-tailwind/chrome/tw-suggestion-card.tsx +139 -0
  195. package/src/ui-tailwind/chrome/tw-table-context-toolbar.tsx +200 -0
  196. package/src/ui-tailwind/chrome/tw-unsaved-modal.tsx +58 -0
  197. package/src/ui-tailwind/chrome/use-before-unload.ts +20 -0
  198. package/src/ui-tailwind/editor-surface/perf-probe.ts +179 -0
  199. package/src/ui-tailwind/editor-surface/pm-command-bridge.ts +189 -0
  200. package/src/ui-tailwind/editor-surface/pm-contextual-ui.ts +31 -0
  201. package/src/ui-tailwind/editor-surface/pm-decorations.ts +411 -0
  202. package/src/ui-tailwind/editor-surface/pm-position-map.ts +123 -0
  203. package/src/ui-tailwind/editor-surface/pm-schema.ts +927 -0
  204. package/src/ui-tailwind/editor-surface/pm-state-from-snapshot.ts +567 -0
  205. package/src/ui-tailwind/editor-surface/search-plugin.ts +168 -0
  206. package/src/ui-tailwind/editor-surface/surface-build-keys.ts +65 -0
  207. package/src/ui-tailwind/editor-surface/tw-caret.tsx +12 -0
  208. package/src/ui-tailwind/editor-surface/tw-editor-surface.tsx +150 -0
  209. package/src/ui-tailwind/editor-surface/tw-inline-token.tsx +129 -0
  210. package/src/ui-tailwind/editor-surface/tw-opaque-block.tsx +58 -0
  211. package/src/ui-tailwind/editor-surface/tw-paragraph-block.tsx +151 -0
  212. package/src/ui-tailwind/editor-surface/tw-prosemirror-surface.tsx +1047 -0
  213. package/src/ui-tailwind/editor-surface/tw-segment-view.tsx +111 -0
  214. package/src/ui-tailwind/editor-surface/tw-table-node-view.tsx +503 -0
  215. package/src/ui-tailwind/index.ts +62 -0
  216. package/src/ui-tailwind/page-chrome-model.ts +27 -0
  217. package/src/ui-tailwind/review/tw-comment-sidebar.tsx +406 -0
  218. package/src/ui-tailwind/review/tw-health-panel.tsx +149 -0
  219. package/src/ui-tailwind/review/tw-review-rail.tsx +122 -0
  220. package/src/ui-tailwind/review/tw-revision-sidebar.tsx +164 -0
  221. package/src/ui-tailwind/status/tw-status-bar.tsx +65 -0
  222. package/{dist → src}/ui-tailwind/theme/editor-theme.css +58 -40
  223. package/src/ui-tailwind/toolbar/tw-toolbar-icon-button.tsx +52 -0
  224. package/src/ui-tailwind/toolbar/tw-toolbar.tsx +1133 -0
  225. package/src/ui-tailwind/tw-review-workspace.tsx +1460 -0
  226. package/src/validation/README.md +3 -0
  227. package/src/validation/compatibility-engine.ts +878 -0
  228. package/src/validation/compatibility-report.ts +161 -0
  229. package/src/validation/diagnostics.ts +204 -0
  230. package/src/validation/docx-comment-proof.ts +720 -0
  231. package/src/validation/import-diagnostics.ts +128 -0
  232. package/src/validation/low-priority-word-surfaces.ts +373 -0
  233. package/dist/canonical-document-BLEbzL2J.d.cts +0 -844
  234. package/dist/canonical-document-BLEbzL2J.d.ts +0 -844
  235. package/dist/chunk-2FJS5GZM.js +0 -763
  236. package/dist/chunk-2FJS5GZM.js.map +0 -1
  237. package/dist/chunk-2OQBZS3F.js +0 -446
  238. package/dist/chunk-2OQBZS3F.js.map +0 -1
  239. package/dist/chunk-2S7W4KFO.js +0 -127
  240. package/dist/chunk-2S7W4KFO.js.map +0 -1
  241. package/dist/chunk-2TG72QSW.js +0 -3874
  242. package/dist/chunk-2TG72QSW.js.map +0 -1
  243. package/dist/chunk-36QNIZBO.js +0 -532
  244. package/dist/chunk-36QNIZBO.js.map +0 -1
  245. package/dist/chunk-4AQOYAW4.js +0 -3069
  246. package/dist/chunk-4AQOYAW4.js.map +0 -1
  247. package/dist/chunk-4D5EWJ3P.js +0 -77
  248. package/dist/chunk-4D5EWJ3P.js.map +0 -1
  249. package/dist/chunk-5FN54NDH.js +0 -2257
  250. package/dist/chunk-5FN54NDH.js.map +0 -1
  251. package/dist/chunk-BOYGQYRQ.js +0 -7306
  252. package/dist/chunk-BOYGQYRQ.js.map +0 -1
  253. package/dist/chunk-CN3XMECL.js +0 -212
  254. package/dist/chunk-CN3XMECL.js.map +0 -1
  255. package/dist/chunk-EBI3BX6U.js +0 -164
  256. package/dist/chunk-EBI3BX6U.js.map +0 -1
  257. package/dist/chunk-EILUG3VB.js +0 -1275
  258. package/dist/chunk-EILUG3VB.js.map +0 -1
  259. package/dist/chunk-FUDY333O.js +0 -70
  260. package/dist/chunk-FUDY333O.js.map +0 -1
  261. package/dist/chunk-GBVOWFIK.js +0 -1237
  262. package/dist/chunk-GBVOWFIK.js.map +0 -1
  263. package/dist/chunk-H4TQ3H3Y.js +0 -262
  264. package/dist/chunk-H4TQ3H3Y.js.map +0 -1
  265. package/dist/chunk-JGB3IXZO.js +0 -189
  266. package/dist/chunk-JGB3IXZO.js.map +0 -1
  267. package/dist/chunk-KD2QRQPY.js +0 -4342
  268. package/dist/chunk-KD2QRQPY.js.map +0 -1
  269. package/dist/chunk-KLMXQVYK.js +0 -369
  270. package/dist/chunk-KLMXQVYK.js.map +0 -1
  271. package/dist/chunk-KZUG5KFQ.js +0 -214
  272. package/dist/chunk-KZUG5KFQ.js.map +0 -1
  273. package/dist/chunk-QDAQ4CJU.js +0 -345
  274. package/dist/chunk-QDAQ4CJU.js.map +0 -1
  275. package/dist/chunk-RMH72RZI.js.map +0 -1
  276. package/dist/chunk-SWKWQZXM.js +0 -117
  277. package/dist/chunk-SWKWQZXM.js.map +0 -1
  278. package/dist/chunk-TJBP2K4T.js.map +0 -1
  279. package/dist/chunk-TLCEAQDQ.js +0 -542
  280. package/dist/chunk-TLCEAQDQ.js.map +0 -1
  281. package/dist/chunk-UZXBISGO.js.map +0 -1
  282. package/dist/chunk-WGBAKP3Q.js +0 -3220
  283. package/dist/chunk-WGBAKP3Q.js.map +0 -1
  284. package/dist/compare/index.cjs +0 -5475
  285. package/dist/compare/index.cjs.map +0 -1
  286. package/dist/compare/index.d.cts +0 -114
  287. package/dist/compare/index.d.ts +0 -114
  288. package/dist/compare/index.js +0 -731
  289. package/dist/compare/index.js.map +0 -1
  290. package/dist/core/commands/formatting-commands.cjs +0 -828
  291. package/dist/core/commands/formatting-commands.cjs.map +0 -1
  292. package/dist/core/commands/formatting-commands.d.cts +0 -63
  293. package/dist/core/commands/formatting-commands.d.ts +0 -63
  294. package/dist/core/commands/formatting-commands.js +0 -37
  295. package/dist/core/commands/formatting-commands.js.map +0 -1
  296. package/dist/core/commands/image-commands.cjs +0 -2023
  297. package/dist/core/commands/image-commands.cjs.map +0 -1
  298. package/dist/core/commands/image-commands.d.cts +0 -58
  299. package/dist/core/commands/image-commands.d.ts +0 -58
  300. package/dist/core/commands/image-commands.js +0 -18
  301. package/dist/core/commands/image-commands.js.map +0 -1
  302. package/dist/core/commands/section-layout-commands.cjs.map +0 -1
  303. package/dist/core/commands/section-layout-commands.d.cts +0 -62
  304. package/dist/core/commands/section-layout-commands.d.ts +0 -62
  305. package/dist/core/commands/section-layout-commands.js +0 -21
  306. package/dist/core/commands/section-layout-commands.js.map +0 -1
  307. package/dist/core/commands/style-commands.cjs.map +0 -1
  308. package/dist/core/commands/style-commands.d.cts +0 -13
  309. package/dist/core/commands/style-commands.d.ts +0 -13
  310. package/dist/core/commands/style-commands.js +0 -9
  311. package/dist/core/commands/style-commands.js.map +0 -1
  312. package/dist/core/commands/table-structure-commands.cjs +0 -1883
  313. package/dist/core/commands/table-structure-commands.cjs.map +0 -1
  314. package/dist/core/commands/table-structure-commands.d.cts +0 -59
  315. package/dist/core/commands/table-structure-commands.d.ts +0 -59
  316. package/dist/core/commands/table-structure-commands.js +0 -12
  317. package/dist/core/commands/table-structure-commands.js.map +0 -1
  318. package/dist/core/commands/text-commands.cjs +0 -2391
  319. package/dist/core/commands/text-commands.cjs.map +0 -1
  320. package/dist/core/commands/text-commands.d.cts +0 -24
  321. package/dist/core/commands/text-commands.d.ts +0 -24
  322. package/dist/core/commands/text-commands.js +0 -28
  323. package/dist/core/commands/text-commands.js.map +0 -1
  324. package/dist/core/selection/mapping.cjs +0 -200
  325. package/dist/core/selection/mapping.cjs.map +0 -1
  326. package/dist/core/selection/mapping.d.cts +0 -2
  327. package/dist/core/selection/mapping.d.ts +0 -2
  328. package/dist/core/selection/mapping.js +0 -31
  329. package/dist/core/selection/mapping.js.map +0 -1
  330. package/dist/core/state/editor-state.cjs +0 -2278
  331. package/dist/core/state/editor-state.cjs.map +0 -1
  332. package/dist/core/state/editor-state.d.cts +0 -2
  333. package/dist/core/state/editor-state.d.ts +0 -2
  334. package/dist/core/state/editor-state.js +0 -26
  335. package/dist/core/state/editor-state.js.map +0 -1
  336. package/dist/index.cjs +0 -38553
  337. package/dist/index.cjs.map +0 -1
  338. package/dist/index.d.cts +0 -15
  339. package/dist/index.d.ts +0 -15
  340. package/dist/index.js +0 -7856
  341. package/dist/index.js.map +0 -1
  342. package/dist/io/docx-session.cjs +0 -16236
  343. package/dist/io/docx-session.cjs.map +0 -1
  344. package/dist/io/docx-session.d.cts +0 -21
  345. package/dist/io/docx-session.d.ts +0 -21
  346. package/dist/io/docx-session.js +0 -18
  347. package/dist/io/docx-session.js.map +0 -1
  348. package/dist/legal/index.cjs +0 -3900
  349. package/dist/legal/index.cjs.map +0 -1
  350. package/dist/legal/index.d.cts +0 -86
  351. package/dist/legal/index.d.ts +0 -86
  352. package/dist/legal/index.js +0 -616
  353. package/dist/legal/index.js.map +0 -1
  354. package/dist/public-types-7ZL_94cz.d.ts +0 -1573
  355. package/dist/public-types-CeMaDueh.d.cts +0 -1573
  356. package/dist/public-types.cjs +0 -19
  357. package/dist/public-types.cjs.map +0 -1
  358. package/dist/public-types.d.cts +0 -2
  359. package/dist/public-types.d.ts +0 -2
  360. package/dist/public-types.js +0 -1
  361. package/dist/public-types.js.map +0 -1
  362. package/dist/runtime/document-runtime.cjs +0 -11140
  363. package/dist/runtime/document-runtime.cjs.map +0 -1
  364. package/dist/runtime/document-runtime.d.cts +0 -231
  365. package/dist/runtime/document-runtime.d.ts +0 -231
  366. package/dist/runtime/document-runtime.js +0 -21
  367. package/dist/runtime/document-runtime.js.map +0 -1
  368. package/dist/structural-helpers-CilgOVhh.d.cts +0 -10
  369. package/dist/structural-helpers-q0Gd-eBN.d.ts +0 -10
  370. package/dist/ui-tailwind/editor-surface/search-plugin.cjs +0 -313
  371. package/dist/ui-tailwind/editor-surface/search-plugin.cjs.map +0 -1
  372. package/dist/ui-tailwind/editor-surface/search-plugin.d.cts +0 -67
  373. package/dist/ui-tailwind/editor-surface/search-plugin.d.ts +0 -67
  374. package/dist/ui-tailwind/editor-surface/search-plugin.js +0 -23
  375. package/dist/ui-tailwind/editor-surface/search-plugin.js.map +0 -1
  376. package/dist/ui-tailwind/index.cjs +0 -4833
  377. package/dist/ui-tailwind/index.cjs.map +0 -1
  378. package/dist/ui-tailwind/index.d.cts +0 -617
  379. package/dist/ui-tailwind/index.d.ts +0 -617
  380. package/dist/ui-tailwind/index.js +0 -575
  381. package/dist/ui-tailwind/index.js.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/ui-tailwind/index.ts","../../src/ui-tailwind/tw-review-workspace.tsx","../../src/core/selection/mapping.ts","../../src/runtime/page-layout-estimation.ts","../../src/runtime/document-navigation.ts","../../src/ui-tailwind/editor-surface/perf-probe.ts","../../src/ui-tailwind/page-chrome-model.ts","../../src/ui/headless/preserve-editor-selection.ts","../../src/ui-tailwind/chrome/tw-alert-banner.tsx","../../src/ui-tailwind/chrome/tw-image-context-toolbar.tsx","../../src/ui-tailwind/chrome/tw-layout-panel.tsx","../../src/ui-tailwind/chrome/tw-object-context-toolbar.tsx","../../src/ui-tailwind/chrome/tw-page-ruler.tsx","../../src/ui-tailwind/chrome/tw-selection-toolbar.tsx","../../src/ui-tailwind/chrome/tw-suggestion-card.tsx","../../src/ui-tailwind/chrome/tw-table-context-toolbar.tsx","../../src/ui-tailwind/review/tw-review-rail.tsx","../../src/ui-tailwind/review/tw-comment-sidebar.tsx","../../src/ui-tailwind/review/tw-revision-sidebar.tsx","../../src/ui/shared/revision-filters.ts","../../src/ui-tailwind/status/tw-status-bar.tsx","../../src/ui-tailwind/toolbar/tw-toolbar.tsx","../../src/ui-tailwind/review/tw-health-panel.tsx","../../src/ui-tailwind/toolbar/tw-toolbar-icon-button.tsx","../../src/ui-tailwind/editor-surface/tw-editor-surface.tsx","../../src/ui/headless/comment-decoration-model.ts","../../src/ui/headless/revision-decoration-model.ts","../../src/ui/headless/selection-helpers.ts","../../src/ui/headless/use-editor-keyboard.ts","../../src/ui-tailwind/editor-surface/tw-opaque-block.tsx","../../src/ui-tailwind/editor-surface/tw-caret.tsx","../../src/ui-tailwind/editor-surface/tw-inline-token.tsx","../../src/ui-tailwind/editor-surface/tw-segment-view.tsx","../../src/ui-tailwind/editor-surface/tw-paragraph-block.tsx","../../src/core/schema/text-schema.ts","../../src/core/selection/review-anchors.ts","../../src/runtime/session-capabilities.ts"],"sourcesContent":["// Workspace shell\nexport { TwReviewWorkspace, type TwReviewWorkspaceProps } from \"./tw-review-workspace\";\n\n// Editor surface\nexport { TwEditorSurface, type TwEditorSurfaceProps } from \"./editor-surface/tw-editor-surface\";\nexport { TwParagraphBlock } from \"./editor-surface/tw-paragraph-block\";\nexport { TwOpaqueBlock } from \"./editor-surface/tw-opaque-block\";\nexport { TwSegmentView } from \"./editor-surface/tw-segment-view\";\nexport { TwInlineToken } from \"./editor-surface/tw-inline-token\";\nexport { renderTwCaret } from \"./editor-surface/tw-caret\";\n\n// Review rail\nexport { TwReviewRail, type TwReviewRailProps, type ReviewRailTab } from \"./review/tw-review-rail\";\nexport { TwCommentSidebar } from \"./review/tw-comment-sidebar\";\nexport { TwRevisionSidebar } from \"./review/tw-revision-sidebar\";\nexport { TwHealthPanel } from \"./review/tw-health-panel\";\n\n// Toolbar\nexport { TwToolbar, type TwToolbarProps } from \"./toolbar/tw-toolbar\";\nexport { TwToolbarIconButton } from \"./toolbar/tw-toolbar-icon-button\";\nexport type { WorkspaceMode, ZoomLevel } from \"../api/public-types\";\n\n// Status\nexport { TwStatusBar } from \"./status/tw-status-bar\";\n\n// Chrome\nexport { TwAlertBanner } from \"./chrome/tw-alert-banner\";\nexport { TwSelectionToolbar } from \"./chrome/tw-selection-toolbar\";\n\n// Session capabilities\nexport {\n deriveCapabilities,\n type SessionCapabilities,\n} from \"../runtime/session-capabilities\";\n\n// Headless (re-export for convenience)\nexport {\n createCommentDecorationModel,\n getCommentHighlightClass,\n getCommentRangeState,\n type CommentDecorationModel,\n type MarkupDisplay,\n} from \"../ui/headless/comment-decoration-model\";\n\nexport {\n createRevisionDecorationModel,\n getRevisionHighlightClass,\n getRevisionRangeState,\n shouldHideInCleanMode,\n type RevisionDecorationModel,\n} from \"../ui/headless/revision-decoration-model\";\n\nexport {\n createEditorKeyboardHandler,\n type EditorKeyboardCallbacks,\n type EditorKeyboardContext,\n} from \"../ui/headless/use-editor-keyboard\";\n\nexport {\n createSelectionSnapshot,\n selectionTouchesRange,\n} from \"../ui/headless/selection-helpers\";\n","import React, {\n type CSSProperties,\n type FocusEventHandler,\n type ReactNode,\n type Ref,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\n\nimport * as Tooltip from \"@radix-ui/react-tooltip\";\nimport { ChevronLeft, ChevronRight, List } from \"lucide-react\";\n\nimport type {\n CommentSidebarThreadSnapshot,\n DocumentNavigationSnapshot,\n EditorViewStateSnapshot,\n FormattingStateSnapshot,\n FormattingAlignment,\n HeaderFooterLinkPatch,\n InteractionGuardSnapshot,\n InsertImageOptions,\n RuntimeRenderSnapshot,\n SectionPageNumberingPatch,\n SectionBreakType,\n StyleCatalogSnapshot,\n SurfaceBlockSnapshot,\n TrackedChangeEntrySnapshot,\n WordReviewEditorChromeVisibility,\n WorkflowScopeSnapshot,\n WorkspaceMode,\n ZoomLevel,\n} from \"../api/public-types\";\nimport { findPageForOffset } from \"../runtime/document-navigation.ts\";\nimport {\n DEFAULT_PAGE_ESTIMATE_PX_PER_TWIP,\n estimateBlockHeight,\n estimateParagraphLineCount,\n estimateParagraphLineHeight,\n getUsableColumnWidth,\n} from \"../runtime/page-layout-estimation.ts\";\nimport {\n incrementInvalidationCounter,\n recordPerfSample,\n} from \"./editor-surface/perf-probe.ts\";\nimport { computeLineMarkersIfEnabled } from \"./page-chrome-model.ts\";\nimport type { SessionCapabilities } from \"../runtime/session-capabilities\";\nimport type {\n SelectionToolbarAnchor,\n SelectionToolbarModel,\n SuggestionCardModel,\n} from \"../ui/headless/selection-toolbar-model\";\nimport type { MarkupDisplay } from \"../ui/headless/comment-decoration-model\";\nimport type { EditorCommandBag } from \"../ui/editor-command-bag.ts\";\nimport { preserveEditorSelectionMouseDown } from \"../ui/headless/preserve-editor-selection\";\nimport { TwAlertBanner } from \"./chrome/tw-alert-banner\";\nimport { TwImageContextToolbar, type ActiveImageContext } from \"./chrome/tw-image-context-toolbar\";\nimport { TwLayoutPanel } from \"./chrome/tw-layout-panel\";\nimport { TwObjectContextToolbar, type ActiveObjectContext } from \"./chrome/tw-object-context-toolbar\";\nimport { TwPageRuler } from \"./chrome/tw-page-ruler\";\nimport { TwSelectionToolbar } from \"./chrome/tw-selection-toolbar\";\nimport { TwSuggestionCard } from \"./chrome/tw-suggestion-card\";\nimport { TwTableContextToolbar } from \"./chrome/tw-table-context-toolbar\";\nimport { TwReviewRail, type ReviewRailTab } from \"./review/tw-review-rail\";\nimport { TwStatusBar } from \"./status/tw-status-bar\";\nimport { TwToolbar, type ToolbarInteractionPolicy } from \"./toolbar/tw-toolbar\";\n\nexport type ReviewWorkspaceChromeVisibility = WordReviewEditorChromeVisibility;\n\nexport interface TwReviewWorkspaceProps {\n snapshot: RuntimeRenderSnapshot;\n viewState: EditorViewStateSnapshot;\n markupDisplay: MarkupDisplay;\n currentUserId?: string;\n capabilities?: SessionCapabilities;\n reviewMode?: \"editing\" | \"review\";\n document: ReactNode;\n workspaceMode: WorkspaceMode;\n zoomLevel?: ZoomLevel;\n formattingState?: FormattingStateSnapshot;\n styleCatalog?: StyleCatalogSnapshot;\n activeRailTab: ReviewRailTab;\n activeCommentId?: string;\n activeRevisionId?: string;\n showTrackedChanges: boolean;\n workflowScopeSnapshot?: WorkflowScopeSnapshot | null;\n interactionGuardSnapshot?: InteractionGuardSnapshot;\n commands: EditorCommandBag;\n selectionToolbar?: SelectionToolbarModel | null;\n suggestionCard?: SuggestionCardModel | null;\n selectionToolbarAnchor?: SelectionToolbarAnchor | null;\n documentNavigation?: DocumentNavigationSnapshot;\n onWorkspaceModeChange?: (value: WorkspaceMode) => void;\n onZoomChange?: (level: ZoomLevel) => void;\n onActiveRailTabChange?: (value: ReviewRailTab) => void;\n onShowTrackedChangesChange?: (show: boolean) => void;\n onUndo?: () => void;\n onRedo?: () => void;\n onSetParagraphStyle?: (styleId: string) => void;\n onToggleBold?: () => void;\n onToggleItalic?: () => void;\n onToggleUnderline?: () => void;\n onSetSelectionTextColor?: (color: string) => void;\n onSetSelectionHighlightColor?: (color: string | null) => void;\n onToggleStrikethrough?: () => void;\n onToggleSuperscript?: () => void;\n onToggleSubscript?: () => void;\n onSetFontFamily?: (fontFamily: string) => void;\n onSetFontSize?: (fontSize: number) => void;\n onSetTextColor?: (color: string) => void;\n onSetHighlightColor?: (color: string | null) => void;\n onSetAlignment?: (alignment: FormattingAlignment) => void;\n onOutdent?: () => void;\n onIndent?: () => void;\n onAddComment?: () => void;\n onInsertPageBreak?: () => void;\n onInsertTable?: () => void;\n onInsertSectionBreak?: (type: SectionBreakType) => void;\n onInsertImage?: (options: InsertImageOptions) => void;\n onSetTableStyle?: (styleId: string) => void;\n onAddRowBefore?: () => void;\n onAddRowAfter?: () => void;\n onAddColumnBefore?: () => void;\n onAddColumnAfter?: () => void;\n onDeleteRow?: () => void;\n onDeleteColumn?: () => void;\n onDeleteTable?: () => void;\n onMergeCells?: () => void;\n onSplitCell?: () => void;\n onSetCellBackground?: (color: string) => void;\n activeImageContext?: ActiveImageContext | null;\n activeObjectContext?: ActiveObjectContext | null;\n onSetImageLayout?: (\n mediaId: string,\n dimensions: { widthEmu: number; heightEmu: number },\n ) => void;\n onSetImageFrame?: (\n mediaId: string,\n offsets: { horizontalOffsetEmu?: number; verticalOffsetEmu?: number },\n ) => void;\n onDeleteSectionBreak?: (sectionIndex: number) => void;\n onUpdateSectionLayout?: (\n sectionIndex: number,\n patch: {\n pageSize?: { width?: number; height?: number; orientation?: \"portrait\" | \"landscape\" };\n pageMargins?: {\n top?: number;\n right?: number;\n bottom?: number;\n left?: number;\n header?: number;\n footer?: number;\n gutter?: number;\n };\n columns?: {\n count?: number;\n space?: number;\n equalWidth?: boolean;\n columns?: Array<{ width: number; space?: number }>;\n separator?: boolean;\n };\n titlePage?: boolean;\n sectionType?: SectionBreakType;\n },\n ) => void;\n onSetSectionPageNumbering?: (\n sectionIndex: number,\n patch: SectionPageNumberingPatch | null,\n ) => void;\n onSetHeaderFooterLink?: (\n sectionIndex: number,\n patch: HeaderFooterLinkPatch,\n ) => void;\n onAddCommentFromSelection?: () => void;\n onExport?: () => void;\n onDismissSelectionToolbar?: () => void;\n onAcceptSuggestion?: () => void;\n onRejectSuggestion?: () => void;\n onEditSuggestion?: () => void;\n onAddCommentFromSuggestion?: () => void;\n onSelectionToolbarFocusCapture?: FocusEventHandler<HTMLDivElement>;\n onSelectionToolbarBlurCapture?: FocusEventHandler<HTMLDivElement>;\n selectionToolbarRef?: Ref<HTMLDivElement>;\n onOpenComment?: (thread: CommentSidebarThreadSnapshot) => void;\n onResolveComment?: (commentId: string) => void;\n onReopenComment?: (commentId: string) => void;\n onAddReply?: (commentId: string, body: string) => void;\n onEditBody?: (commentId: string, body: string) => void;\n onOpenRevision?: (revision: TrackedChangeEntrySnapshot) => void;\n onAcceptRevision?: (revisionId: string) => void;\n onRejectRevision?: (revisionId: string) => void;\n onAcceptAllChanges?: () => void;\n onRejectAllChanges?: () => void;\n onCloseStory?: () => void;\n onOpenHeaderStory?: () => void;\n onOpenFooterStory?: () => void;\n onSetParagraphIndentation?: (indentation: {\n left?: number;\n right?: number;\n firstLine?: number;\n hanging?: number;\n }) => void;\n onSetParagraphTabStops?: (tabStops: Array<{ pos: number; val?: string; leader?: string }>) => void;\n onRestartNumbering?: () => void;\n onContinueNumbering?: () => void;\n onNavigateHeading?: (headingId: string) => void;\n chromeVisibility?: Partial<ReviewWorkspaceChromeVisibility>;\n}\n\nexport function TwReviewWorkspace(inputProps: TwReviewWorkspaceProps) {\n const props = {\n ...inputProps,\n ...inputProps.commands,\n } as TwReviewWorkspaceProps & EditorCommandBag;\n const { snapshot, viewState } = props;\n const selectionToolbarRootRef = useRef<HTMLDivElement>(null);\n const caps = props.capabilities;\n const isPageWorkspace = props.workspaceMode === \"page\";\n const markupDisplay = props.markupDisplay;\n const [navOpen, setNavOpen] = useState(false);\n const [layoutToolsOpen, setLayoutToolsOpen] = useState(false);\n const zoomLevel = props.zoomLevel ?? 100;\n const zoomScale = typeof zoomLevel === \"number\" ? zoomLevel / 100 : 1;\n const preserveOnlyCount = caps?.preserveOnlyCount ??\n snapshot.compatibility.featureEntries.filter(\n (entry) => entry.featureClass === \"preserve-only\",\n ).length;\n const blockedReasons =\n props.interactionGuardSnapshot?.blockedReasons ??\n props.workflowScopeSnapshot?.blockedReasons ??\n [];\n const chromeVisibility: ReviewWorkspaceChromeVisibility = {\n toolbar: true,\n alerts: true,\n selectionOverlay: true,\n contextToolbars: true,\n pageChrome: true,\n statusBar: true,\n reviewRail: true,\n ...props.chromeVisibility,\n };\n const showReviewRail = chromeVisibility.reviewRail && (caps?.reviewRailVisible ?? true);\n const headings = props.documentNavigation?.headings ?? [];\n const headerVariant = snapshot.pageLayout?.headerVariants[0]?.variant ?? \"default\";\n const footerVariant = snapshot.pageLayout?.footerVariants[0]?.variant ?? \"default\";\n const selectionPosition =\n viewState.selection.activeRange.kind === \"node\"\n ? viewState.selection.activeRange.at\n : viewState.selection.head;\n const activeParagraphLayout = useMemo(\n () => resolveActiveParagraphLayout(snapshot.surface, selectionPosition),\n [selectionPosition, snapshot.surface],\n );\n const isTableContext = Boolean(\n props.formattingState?.breadcrumb.some((item) => item.kind === \"table\" || item.kind === \"table_cell\" || item.kind === \"table_row\"),\n );\n const contextualSurface =\n props.activeImageContext\n ? \"image\"\n : props.activeObjectContext\n ? \"object\"\n : isTableContext\n ? \"table\"\n : null;\n const pageChromeModel = useMemo(\n () =>\n buildPageChromeModel(\n snapshot.surface,\n snapshot.pageLayout,\n props.documentNavigation,\n snapshot.activeStory,\n ),\n [props.documentNavigation, snapshot.activeStory, snapshot.pageLayout, snapshot.surface],\n );\n const selectionToolbarPlacement = resolveSelectionToolbarPlacement(\n props.selectionToolbarAnchor,\n selectionToolbarRootRef.current,\n zoomScale,\n );\n const activePage = props.documentNavigation?.pages[props.documentNavigation.activePageIndex] ?? null;\n const pageShellMetrics = useMemo(\n () => buildPageShellMetrics(snapshot.pageLayout),\n [snapshot.pageLayout],\n );\n const hidePageBorderForActiveEditing =\n isPageWorkspace &&\n snapshot.activeStory.kind === \"main\" &&\n shouldHidePageBorderForSelection(viewState.selection);\n const effectiveSelectionMode = props.interactionGuardSnapshot?.effectiveMode ?? \"edit\";\n const allowLocalChromeMutations = Boolean(caps?.canEdit) && effectiveSelectionMode === \"edit\";\n const pageChromeReadOnly =\n snapshot.readOnly ||\n snapshot.activeStory.kind !== \"main\" ||\n effectiveSelectionMode !== \"edit\";\n const toolbarInteractionPolicy: ToolbarInteractionPolicy | undefined = caps\n ? {\n mode: effectiveSelectionMode,\n canFormatText: caps.canEdit && effectiveSelectionMode === \"edit\",\n canInsertStructural: caps.canEdit && effectiveSelectionMode === \"edit\",\n canAddComment:\n caps.canAddComment &&\n effectiveSelectionMode !== \"view\" &&\n effectiveSelectionMode !== \"blocked\",\n }\n : undefined;\n\n useEffect(() => {\n recordPerfSample(\"workspace.chrome\");\n incrementInvalidationCounter(\"workspace.chrome.recomputes\");\n }, [activeParagraphLayout, pageChromeModel, pageShellMetrics]);\n\n useEffect(() => {\n if (isPageWorkspace && snapshot.activeStory.kind !== \"main\") {\n setLayoutToolsOpen(true);\n }\n }, [isPageWorkspace, snapshot.activeStory.kind]);\n\n const dismissSelectionToolbar = useCallback(() => {\n props.onDismissSelectionToolbar?.();\n }, [props.onDismissSelectionToolbar]);\n\n const runWithSelectionToolbarDismiss = useCallback(\n (action?: () => void) => () => {\n dismissSelectionToolbar();\n action?.();\n },\n [dismissSelectionToolbar],\n );\n\n return (\n <Tooltip.Provider delayDuration={400}>\n <div className=\"flex h-full flex-col bg-canvas text-primary\">\n {chromeVisibility.toolbar ? <TwToolbar\n sourceLabel={snapshot.sourceLabel}\n capabilities={caps}\n compatibility={snapshot.compatibility}\n warnings={snapshot.warnings}\n interactionPolicy={toolbarInteractionPolicy}\n workspaceMode={props.workspaceMode}\n zoomLevel={props.zoomLevel}\n formattingState={props.formattingState}\n styleCatalog={props.styleCatalog}\n showTrackedChanges={props.showTrackedChanges}\n onUndo={runWithSelectionToolbarDismiss(props.onUndo)}\n onRedo={runWithSelectionToolbarDismiss(props.onRedo)}\n onSetParagraphStyle={props.onSetParagraphStyle\n ? (styleId) => {\n dismissSelectionToolbar();\n props.onSetParagraphStyle?.(styleId);\n }\n : undefined}\n onToggleBold={runWithSelectionToolbarDismiss(props.onToggleBold)}\n onToggleItalic={runWithSelectionToolbarDismiss(props.onToggleItalic)}\n onToggleUnderline={runWithSelectionToolbarDismiss(props.onToggleUnderline)}\n onToggleStrikethrough={runWithSelectionToolbarDismiss(props.onToggleStrikethrough)}\n onToggleSuperscript={runWithSelectionToolbarDismiss(props.onToggleSuperscript)}\n onToggleSubscript={runWithSelectionToolbarDismiss(props.onToggleSubscript)}\n onSetFontFamily={props.onSetFontFamily\n ? (fontFamily) => {\n dismissSelectionToolbar();\n props.onSetFontFamily?.(fontFamily);\n }\n : undefined}\n onSetFontSize={props.onSetFontSize\n ? (fontSize) => {\n dismissSelectionToolbar();\n props.onSetFontSize?.(fontSize);\n }\n : undefined}\n onSetTextColor={props.onSetTextColor\n ? (color) => {\n dismissSelectionToolbar();\n props.onSetTextColor?.(color);\n }\n : undefined}\n onSetHighlightColor={props.onSetHighlightColor\n ? (color) => {\n dismissSelectionToolbar();\n props.onSetHighlightColor?.(color);\n }\n : undefined}\n onSetAlignment={props.onSetAlignment\n ? (alignment) => {\n dismissSelectionToolbar();\n props.onSetAlignment?.(alignment);\n }\n : undefined}\n onOutdent={runWithSelectionToolbarDismiss(props.onOutdent)}\n onIndent={runWithSelectionToolbarDismiss(props.onIndent)}\n onAddComment={runWithSelectionToolbarDismiss(props.onAddComment)}\n onInsertPageBreak={runWithSelectionToolbarDismiss(props.onInsertPageBreak)}\n onInsertTable={runWithSelectionToolbarDismiss(props.onInsertTable)}\n onInsertSectionBreak={props.onInsertSectionBreak\n ? (type) => {\n dismissSelectionToolbar();\n props.onInsertSectionBreak?.(type);\n }\n : undefined}\n onInsertImage={props.onInsertImage\n ? (options) => {\n dismissSelectionToolbar();\n props.onInsertImage?.(options);\n }\n : undefined}\n onExport={runWithSelectionToolbarDismiss(props.onExport)}\n activeStory={snapshot.activeStory}\n onCloseStory={props.onCloseStory\n ? runWithSelectionToolbarDismiss(props.onCloseStory)\n : undefined}\n onWorkspaceModeChange={(value) => {\n dismissSelectionToolbar();\n props.onWorkspaceModeChange(value);\n }}\n onZoomChange={props.onZoomChange\n ? (level) => {\n dismissSelectionToolbar();\n props.onZoomChange?.(level);\n }\n : undefined}\n onShowTrackedChangesChange={(show) => {\n dismissSelectionToolbar();\n props.onShowTrackedChangesChange(show);\n }}\n blockedReasons={blockedReasons}\n /> : null}\n\n {chromeVisibility.alerts ? <TwAlertBanner\n snapshot={snapshot}\n preserveOnlyCount={preserveOnlyCount}\n workflowBlockedReasons={blockedReasons}\n /> : null}\n\n <div className=\"flex flex-1 min-h-0\">\n {/* Collapsible document navigator — page mode only */}\n {isPageWorkspace && chromeVisibility.pageChrome ? (\n <aside\n aria-label=\"Document navigator\"\n className={`shrink-0 border-r border-border bg-surface transition-[width] duration-200 ${\n navOpen ? \"w-48\" : \"w-0\"\n } overflow-hidden`}\n >\n {navOpen ? (\n <div className=\"flex h-full flex-col\">\n <div className=\"flex items-center justify-between px-3 py-2 border-b border-border\">\n <span className=\"text-xs font-medium text-secondary uppercase tracking-wider\">Navigator</span>\n <Tooltip.Root>\n <Tooltip.Trigger asChild>\n <button\n type=\"button\"\n aria-label=\"Collapse navigator\"\n onMouseDown={preserveEditorSelectionMouseDown}\n onClick={() => {\n dismissSelectionToolbar();\n setNavOpen(false);\n }}\n className=\"inline-flex h-6 w-6 items-center justify-center rounded-md text-secondary hover:bg-surface-hover transition-colors\"\n >\n <ChevronLeft className=\"h-3.5 w-3.5\" />\n </button>\n </Tooltip.Trigger>\n <Tooltip.Portal>\n <Tooltip.Content className=\"rounded-md bg-primary px-2 py-1 text-xs text-white shadow-md z-50\" sideOffset={6}>\n Collapse navigator\n </Tooltip.Content>\n </Tooltip.Portal>\n </Tooltip.Root>\n </div>\n <nav className=\"flex-1 overflow-y-auto px-2 py-2\" aria-label=\"Document headings\">\n {headings.length > 0 ? (\n <ul className=\"space-y-0.5\">\n {headings.map((entry) => (\n <li key={entry.headingId}>\n <button\n type=\"button\"\n className=\"block w-full truncate rounded-md px-2 py-1 text-left text-xs text-primary hover:bg-surface-hover\"\n style={{ paddingLeft: `${8 + (entry.level - 1) * 12}px` }}\n onMouseDown={preserveEditorSelectionMouseDown}\n onClick={() => {\n dismissSelectionToolbar();\n props.onNavigateHeading?.(entry.headingId);\n setNavOpen(false);\n }}\n >\n {entry.text}\n </button>\n </li>\n ))}\n </ul>\n ) : (\n <p className=\"px-2 py-4 text-xs text-tertiary\">No headings found.</p>\n )}\n </nav>\n </div>\n ) : null}\n </aside>\n ) : null}\n\n {/* Navigator expand toggle — page mode only when collapsed */}\n {isPageWorkspace && chromeVisibility.pageChrome && !navOpen ? (\n <div className=\"shrink-0 flex items-start pt-2 pl-1\">\n <Tooltip.Root>\n <Tooltip.Trigger asChild>\n <button\n type=\"button\"\n aria-label=\"Open document navigator\"\n onMouseDown={preserveEditorSelectionMouseDown}\n onClick={() => {\n dismissSelectionToolbar();\n setNavOpen(true);\n }}\n className=\"inline-flex h-7 w-7 items-center justify-center rounded-md text-secondary hover:bg-surface-hover transition-colors\"\n >\n <List className=\"h-3.5 w-3.5\" />\n </button>\n </Tooltip.Trigger>\n <Tooltip.Portal>\n <Tooltip.Content className=\"rounded-md bg-primary px-2 py-1 text-xs text-white shadow-md z-50\" sideOffset={6}>\n Open document navigator\n </Tooltip.Content>\n </Tooltip.Portal>\n </Tooltip.Root>\n </div>\n ) : null}\n\n {/* Document column */}\n <div className=\"flex flex-1 flex-col min-w-0\">\n <div\n className={`flex-1 overflow-y-auto ${isPageWorkspace ? \"bg-surface\" : \"bg-canvas\"}`}\n data-wre-scroll-root=\"true\"\n >\n <div\n ref={selectionToolbarRootRef}\n className={`mx-auto min-h-full ${\n isPageWorkspace\n ? \"wre-page-chrome wre-page-surface relative max-w-[840px] my-8 overflow-hidden\"\n : \"wre-canvas-surface relative bg-canvas\"\n }`}\n style={isPageWorkspace && zoomScale !== 1 ? { transform: `scale(${zoomScale})`, transformOrigin: \"top center\" } : undefined}\n >\n {isPageWorkspace && chromeVisibility.pageChrome && snapshot.pageLayout ? (\n <div className=\"border-b border-border/70 bg-surface/65 px-5 py-3\" data-testid=\"page-context-summary\">\n <div className=\"flex flex-wrap items-center justify-between gap-2\">\n <div className=\"flex flex-wrap items-center gap-2 text-xs text-secondary\">\n <span className=\"rounded-full bg-canvas px-2 py-1 font-medium text-primary\">\n {activePage\n ? `Page ${activePage.pageIndex + 1} of ${props.documentNavigation?.pageCount ?? 1}`\n : \"Page workspace\"}\n </span>\n <span>{`Section ${snapshot.pageLayout.sectionIndex + 1}`}</span>\n <span className=\"uppercase tracking-[0.12em] text-tertiary\">\n {snapshot.pageLayout.orientation}\n </span>\n </div>\n <div className=\"flex items-center gap-2\">\n {snapshot.activeStory.kind !== \"main\" ? (\n <button\n type=\"button\"\n aria-label=\"Return to document body\"\n onMouseDown={preserveEditorSelectionMouseDown}\n onClick={runWithSelectionToolbarDismiss(props.onCloseStory)}\n className=\"inline-flex items-center gap-1 rounded-md border border-border bg-canvas px-2 py-1 text-xs font-medium text-primary transition-colors hover:bg-surface\"\n >\n Body\n </button>\n ) : null}\n {snapshot.activeStory.kind === \"main\" && snapshot.pageLayout.sectionIndex > 0 ? (\n <>\n <button\n type=\"button\"\n aria-label=\"Link header to previous\"\n disabled={!props.onSetHeaderFooterLink || !allowLocalChromeMutations}\n onMouseDown={preserveEditorSelectionMouseDown}\n onClick={() => {\n dismissSelectionToolbar();\n props.onSetHeaderFooterLink?.(snapshot.pageLayout!.sectionIndex, {\n kind: \"header\",\n variant: headerVariant,\n linkToPrevious: true,\n });\n }}\n className=\"inline-flex items-center gap-1 rounded-md border border-border bg-canvas px-2 py-1 text-xs font-medium text-primary transition-colors hover:bg-surface disabled:cursor-not-allowed disabled:opacity-40\"\n >\n Link header\n </button>\n <button\n type=\"button\"\n aria-label=\"Link footer to previous\"\n disabled={!props.onSetHeaderFooterLink || !allowLocalChromeMutations}\n onMouseDown={preserveEditorSelectionMouseDown}\n onClick={() => {\n dismissSelectionToolbar();\n props.onSetHeaderFooterLink?.(snapshot.pageLayout!.sectionIndex, {\n kind: \"footer\",\n variant: footerVariant,\n linkToPrevious: true,\n });\n }}\n className=\"inline-flex items-center gap-1 rounded-md border border-border bg-canvas px-2 py-1 text-xs font-medium text-primary transition-colors hover:bg-surface disabled:cursor-not-allowed disabled:opacity-40\"\n >\n Link footer\n </button>\n </>\n ) : null}\n <button\n type=\"button\"\n aria-label=\"Toggle layout tools\"\n aria-expanded={layoutToolsOpen}\n onMouseDown={preserveEditorSelectionMouseDown}\n onClick={() => {\n dismissSelectionToolbar();\n setLayoutToolsOpen((open) => !open);\n }}\n className=\"inline-flex items-center gap-1 rounded-md border border-border bg-canvas px-2 py-1 text-xs font-medium text-primary transition-colors hover:bg-surface\"\n >\n <ChevronRight className={`h-3.5 w-3.5 transition-transform ${layoutToolsOpen ? \"rotate-90\" : \"\"}`} />\n Layout tools\n </button>\n </div>\n </div>\n </div>\n ) : null}\n {isPageWorkspace && chromeVisibility.pageChrome && snapshot.pageLayout && layoutToolsOpen ? (\n <div className=\"px-5 pt-3\">\n <TwPageRuler\n pageLayout={snapshot.pageLayout}\n viewState={viewState}\n paragraphLayout={activeParagraphLayout}\n readOnly={pageChromeReadOnly}\n onReturnToBody={props.onCloseStory\n ? runWithSelectionToolbarDismiss(props.onCloseStory)\n : () => undefined}\n onOpenHeader={props.onOpenHeaderStory\n ? runWithSelectionToolbarDismiss(props.onOpenHeaderStory)\n : undefined}\n onOpenFooter={props.onOpenFooterStory\n ? runWithSelectionToolbarDismiss(props.onOpenFooterStory)\n : undefined}\n onSetIndentation={props.onSetParagraphIndentation\n ? (indentation) => {\n dismissSelectionToolbar();\n props.onSetParagraphIndentation?.(indentation);\n }\n : undefined}\n onSetTabStops={props.onSetParagraphTabStops\n ? (tabStops) => {\n dismissSelectionToolbar();\n props.onSetParagraphTabStops?.(tabStops);\n }\n : undefined}\n onRestartNumbering={props.onRestartNumbering\n ? runWithSelectionToolbarDismiss(props.onRestartNumbering)\n : undefined}\n onContinueNumbering={props.onContinueNumbering\n ? runWithSelectionToolbarDismiss(props.onContinueNumbering)\n : undefined}\n />\n <TwLayoutPanel\n pageLayout={snapshot.pageLayout}\n readOnly={pageChromeReadOnly}\n onInsertSectionBreak={props.onInsertSectionBreak\n ? (type) => {\n dismissSelectionToolbar();\n props.onInsertSectionBreak?.(type);\n }\n : undefined}\n onDeleteSectionBreak={props.onDeleteSectionBreak\n ? (sectionIndex) => {\n dismissSelectionToolbar();\n props.onDeleteSectionBreak?.(sectionIndex);\n }\n : undefined}\n onUpdateSectionLayout={props.onUpdateSectionLayout\n ? (sectionIndex, patch) => {\n dismissSelectionToolbar();\n props.onUpdateSectionLayout?.(sectionIndex, patch);\n }\n : undefined}\n onSetSectionPageNumbering={props.onSetSectionPageNumbering\n ? (sectionIndex, patch) => {\n dismissSelectionToolbar();\n props.onSetSectionPageNumbering?.(sectionIndex, patch);\n }\n : undefined}\n />\n </div>\n ) : null}\n {chromeVisibility.contextToolbars && contextualSurface ? (\n <div className=\"px-5 pt-3 space-y-3\">\n {contextualSurface === \"table\" ? (\n <TwTableContextToolbar\n disabled={!allowLocalChromeMutations}\n tableStyles={props.styleCatalog?.tables ?? []}\n onSetTableStyle={props.onSetTableStyle\n ? (styleId) => {\n dismissSelectionToolbar();\n props.onSetTableStyle?.(styleId);\n }\n : undefined}\n onAddRowBefore={runWithSelectionToolbarDismiss(props.onAddRowBefore)}\n onAddRowAfter={runWithSelectionToolbarDismiss(props.onAddRowAfter)}\n onAddColumnBefore={runWithSelectionToolbarDismiss(props.onAddColumnBefore)}\n onAddColumnAfter={runWithSelectionToolbarDismiss(props.onAddColumnAfter)}\n onDeleteRow={runWithSelectionToolbarDismiss(props.onDeleteRow)}\n onDeleteColumn={runWithSelectionToolbarDismiss(props.onDeleteColumn)}\n onDeleteTable={runWithSelectionToolbarDismiss(props.onDeleteTable)}\n onMergeCells={runWithSelectionToolbarDismiss(props.onMergeCells)}\n onSplitCell={runWithSelectionToolbarDismiss(props.onSplitCell)}\n onSetCellBackground={props.onSetCellBackground\n ? (color) => {\n dismissSelectionToolbar();\n props.onSetCellBackground?.(color);\n }\n : undefined}\n />\n ) : null}\n {contextualSurface === \"image\" && props.activeImageContext ? (\n <TwImageContextToolbar\n activeImage={props.activeImageContext}\n disabled={!allowLocalChromeMutations}\n onSetImageLayout={props.onSetImageLayout\n ? (mediaId, dimensions) => {\n dismissSelectionToolbar();\n props.onSetImageLayout?.(mediaId, dimensions);\n }\n : undefined}\n onSetImageFrame={props.onSetImageFrame\n ? (mediaId, offsets) => {\n dismissSelectionToolbar();\n props.onSetImageFrame?.(mediaId, offsets);\n }\n : undefined}\n />\n ) : null}\n {contextualSurface === \"object\" && props.activeObjectContext ? (\n <TwObjectContextToolbar activeObject={props.activeObjectContext} />\n ) : null}\n </div>\n ) : null}\n {chromeVisibility.selectionOverlay && props.suggestionCard && selectionToolbarPlacement ? (\n <div className=\"pointer-events-none absolute inset-0 z-20\" data-testid=\"suggestion-card-overlay\">\n <div\n className=\"pointer-events-auto absolute\"\n data-placement={selectionToolbarPlacement.placement}\n style={selectionToolbarPlacement.style}\n >\n <TwSuggestionCard\n model={props.suggestionCard}\n onFocusCapture={props.onSelectionToolbarFocusCapture}\n onBlurCapture={props.onSelectionToolbarBlurCapture}\n onAccept={props.onAcceptSuggestion}\n onReject={props.onRejectSuggestion}\n onEditSuggestion={props.onEditSuggestion}\n onAddComment={props.onAddCommentFromSuggestion ?? props.onAddComment}\n />\n </div>\n </div>\n ) : null}\n {chromeVisibility.selectionOverlay && props.suggestionCard && !selectionToolbarPlacement ? (\n <div\n className=\"pointer-events-none absolute inset-x-0 top-0 z-20 flex justify-center px-4 pt-3\"\n data-testid=\"suggestion-card-fallback\"\n >\n <div className=\"pointer-events-auto\" data-placement=\"fallback\">\n <TwSuggestionCard\n model={props.suggestionCard}\n onFocusCapture={props.onSelectionToolbarFocusCapture}\n onBlurCapture={props.onSelectionToolbarBlurCapture}\n onAccept={props.onAcceptSuggestion}\n onReject={props.onRejectSuggestion}\n onEditSuggestion={props.onEditSuggestion}\n onAddComment={props.onAddCommentFromSuggestion ?? props.onAddComment}\n />\n </div>\n </div>\n ) : null}\n {chromeVisibility.selectionOverlay && props.selectionToolbar && !props.suggestionCard && selectionToolbarPlacement ? (\n <div className=\"pointer-events-none absolute inset-0 z-20\" data-testid=\"selection-toolbar-overlay\">\n <div\n className=\"pointer-events-auto absolute\"\n data-placement={selectionToolbarPlacement.placement}\n style={selectionToolbarPlacement.style}\n >\n <TwSelectionToolbar\n ref={props.selectionToolbarRef}\n model={props.selectionToolbar}\n disabledReason={props.selectionToolbar.disabledReason}\n onFocusCapture={props.onSelectionToolbarFocusCapture}\n onBlurCapture={props.onSelectionToolbarBlurCapture}\n onToggleBold={props.onToggleBold}\n onToggleItalic={props.onToggleItalic}\n onToggleUnderline={props.onToggleUnderline}\n onSetTextColor={props.onSetSelectionTextColor}\n onSetHighlightColor={props.onSetSelectionHighlightColor}\n onAddComment={props.onAddCommentFromSelection ?? props.onAddComment}\n />\n </div>\n </div>\n ) : null}\n {chromeVisibility.selectionOverlay && props.selectionToolbar && !props.suggestionCard && !selectionToolbarPlacement ? (\n <div\n className=\"pointer-events-none absolute inset-x-0 top-0 z-20 flex justify-center px-4 pt-3\"\n data-testid=\"selection-toolbar-fallback\"\n >\n <div className=\"pointer-events-auto\" data-placement=\"fallback\">\n <TwSelectionToolbar\n ref={props.selectionToolbarRef}\n model={props.selectionToolbar}\n disabledReason={props.selectionToolbar.disabledReason}\n onFocusCapture={props.onSelectionToolbarFocusCapture}\n onBlurCapture={props.onSelectionToolbarBlurCapture}\n onToggleBold={props.onToggleBold}\n onToggleItalic={props.onToggleItalic}\n onToggleUnderline={props.onToggleUnderline}\n onSetTextColor={props.onSetSelectionTextColor}\n onSetHighlightColor={props.onSetSelectionHighlightColor}\n onAddComment={props.onAddCommentFromSelection ?? props.onAddComment}\n />\n </div>\n </div>\n ) : null}\n <div\n className={isPageWorkspace ? \"relative\" : undefined}\n data-line-numbering={pageChromeModel.lineNumberingEnabled ? \"enabled\" : \"disabled\"}\n >\n {isPageWorkspace && chromeVisibility.pageChrome && pageChromeModel.lineNumberingEnabled ? (\n <div\n aria-hidden=\"true\"\n className=\"pointer-events-none absolute inset-y-0 left-0 z-10\"\n data-testid=\"page-line-number-gutter\"\n style={{ width: `${pageChromeModel.gutterWidthPx}px` }}\n >\n {pageChromeModel.lineMarkers.map((marker) => (\n <span\n key={marker.id}\n className=\"absolute right-2 font-[family-name:var(--font-legal-sans)] text-[10px] font-medium tabular-nums tracking-[0.12em] text-tertiary/80\"\n style={{ top: `${marker.topPx}px` }}\n >\n {marker.label}\n </span>\n ))}\n </div>\n ) : null}\n <div\n className={isPageWorkspace && chromeVisibility.pageChrome && pageChromeModel.lineNumberingEnabled ? \"pl-12\" : undefined}\n style={isPageWorkspace ? pageShellMetrics.contentInsetStyle : undefined}\n >\n <div\n className={isPageWorkspace ? \"relative\" : undefined}\n data-document-grid={pageChromeModel.documentGridType}\n data-page-border-display={pageChromeModel.pageBorderDisplay}\n style={isPageWorkspace\n ? {\n ...pageChromeModel.documentGridStyle,\n ...pageShellMetrics.pageFrameStyle,\n }\n : pageChromeModel.documentGridStyle}\n >\n {isPageWorkspace && chromeVisibility.pageChrome ? (\n <div\n data-testid=\"page-header-band\"\n className=\"relative z-10 flex items-center justify-between border-b border-dashed border-border/60 px-4 text-[11px] text-secondary\"\n style={pageShellMetrics.headerBandStyle}\n >\n <span className=\"uppercase tracking-[0.12em] text-tertiary\">Header</span>\n {snapshot.pageLayout?.headerVariants[0] ? (\n <button\n type=\"button\"\n aria-label=\"Open header story\"\n onClick={props.onOpenHeaderStory}\n className=\"rounded-md px-2 py-1 text-xs font-medium text-primary transition-colors hover:bg-surface\"\n >\n Edit header\n </button>\n ) : null}\n </div>\n ) : null}\n {isPageWorkspace && chromeVisibility.pageChrome && pageChromeModel.showPageBorder && !hidePageBorderForActiveEditing ? (\n <div\n aria-hidden=\"true\"\n className=\"pointer-events-none absolute inset-0 z-0 rounded-[2px]\"\n data-testid=\"page-border-overlay\"\n style={pageChromeModel.pageBorderStyle}\n />\n ) : null}\n <div className={isPageWorkspace ? \"relative z-10\" : undefined}>\n {props.document}\n </div>\n {isPageWorkspace && chromeVisibility.pageChrome ? (\n <div\n data-testid=\"page-footer-band\"\n className=\"relative z-10 flex items-center justify-between border-t border-dashed border-border/60 px-4 text-[11px] text-secondary\"\n style={pageShellMetrics.footerBandStyle}\n >\n <span className=\"uppercase tracking-[0.12em] text-tertiary\">Footer</span>\n {snapshot.pageLayout?.footerVariants[0] ? (\n <button\n type=\"button\"\n aria-label=\"Open footer story\"\n onClick={props.onOpenFooterStory}\n className=\"rounded-md px-2 py-1 text-xs font-medium text-primary transition-colors hover:bg-surface\"\n >\n Edit footer\n </button>\n ) : null}\n </div>\n ) : null}\n </div>\n </div>\n </div>\n </div>\n </div>\n\n {chromeVisibility.statusBar ? (\n <TwStatusBar\n isDirty={snapshot.isDirty}\n isExportBlocked={snapshot.compatibility.blockExport}\n preserveOnlyCount={preserveOnlyCount}\n commentCount={snapshot.comments.totalCount}\n changeCount={snapshot.trackedChanges.totalCount}\n sessionId={snapshot.sessionId}\n />\n ) : null}\n </div>\n\n {/* Review rail — hidden in editing mode unless toggled */}\n {showReviewRail ? <TwReviewRail\n activeTab={props.activeRailTab}\n currentUserId={props.currentUserId}\n comments={snapshot.comments}\n trackedChanges={snapshot.trackedChanges}\n compatibility={snapshot.compatibility}\n warnings={snapshot.warnings}\n markupDisplay={markupDisplay}\n activeCommentId={props.activeCommentId}\n activeRevisionId={props.activeRevisionId}\n onActiveTabChange={props.onActiveRailTabChange}\n onOpenComment={props.onOpenComment}\n onResolveComment={props.onResolveComment}\n onReopenComment={props.onReopenComment}\n onAddReply={props.onAddReply}\n onEditBody={props.onEditBody}\n onOpenRevision={props.onOpenRevision}\n onAcceptRevision={props.onAcceptRevision}\n onRejectRevision={props.onRejectRevision}\n onAcceptAllChanges={props.onAcceptAllChanges}\n onRejectAllChanges={props.onRejectAllChanges}\n /> : null}\n </div>\n </div>\n </Tooltip.Provider>\n );\n}\n\nfunction shouldHidePageBorderForSelection(\n selection: EditorViewStateSnapshot[\"selection\"],\n): boolean {\n if (selection.isCollapsed) {\n return false;\n }\n\n return selection.activeRange.kind === \"range\";\n}\n\nfunction resolveActiveParagraphLayout(\n surface: RuntimeRenderSnapshot[\"surface\"],\n position: number,\n): {\n leftIndent: number;\n rightIndent: number;\n firstLineOffset: number;\n tabStops: Array<{ pos: number; val?: string; leader?: string }>;\n} | null {\n const paragraph = surface ? findActiveParagraph(surface.blocks, position) : null;\n if (!paragraph) {\n return null;\n }\n\n return {\n leftIndent: paragraph.indentation?.left ?? 0,\n rightIndent: paragraph.indentation?.right ?? 0,\n firstLineOffset:\n paragraph.indentation?.firstLine ??\n (paragraph.indentation?.hanging ? -paragraph.indentation.hanging : 0),\n tabStops: paragraph.tabStops ? [...paragraph.tabStops] : [],\n };\n}\n\nfunction findActiveParagraph(\n blocks: readonly SurfaceBlockSnapshot[],\n position: number,\n): Extract<SurfaceBlockSnapshot, { kind: \"paragraph\" }> | null {\n for (const block of blocks) {\n if (block.kind === \"paragraph\" && position >= block.from && position <= block.to) {\n return block;\n }\n if (block.kind === \"table\") {\n for (const row of block.rows) {\n for (const cell of row.cells) {\n const paragraph = findActiveParagraph(cell.content, position);\n if (paragraph) {\n return paragraph;\n }\n }\n }\n }\n if (block.kind === \"sdt_block\") {\n const paragraph = findActiveParagraph(block.children, position);\n if (paragraph) {\n return paragraph;\n }\n }\n }\n return null;\n}\n\ninterface PageChromeModel {\n lineNumberingEnabled: boolean;\n gutterWidthPx: number;\n lineMarkers: Array<{ id: string; label: string; topPx: number }>;\n showPageBorder: boolean;\n pageBorderDisplay: string;\n pageBorderStyle: CSSProperties | undefined;\n documentGridType: string;\n documentGridStyle: CSSProperties | undefined;\n}\n\nconst EMPTY_PAGE_CHROME_MODEL: PageChromeModel = {\n lineNumberingEnabled: false,\n gutterWidthPx: 0,\n lineMarkers: [],\n showPageBorder: false,\n pageBorderDisplay: \"none\",\n pageBorderStyle: undefined,\n documentGridType: \"none\",\n documentGridStyle: undefined,\n};\n\nconst DOCUMENT_CONTENT_TOP_PADDING_PX = 40;\n\ninterface PageShellMetrics {\n contentInsetStyle: CSSProperties;\n pageFrameStyle: CSSProperties;\n headerBandStyle: CSSProperties;\n footerBandStyle: CSSProperties;\n}\n\nfunction buildPageChromeModel(\n surface: RuntimeRenderSnapshot[\"surface\"] | undefined,\n pageLayout: RuntimeRenderSnapshot[\"pageLayout\"] | undefined,\n navigation: DocumentNavigationSnapshot | undefined,\n activeStory: RuntimeRenderSnapshot[\"activeStory\"],\n): PageChromeModel {\n if (!surface || !pageLayout || !navigation || activeStory.kind !== \"main\") {\n return EMPTY_PAGE_CHROME_MODEL;\n }\n\n const lineMarkers = computeLineMarkersIfEnabled({\n pageLayout,\n surfaceBlocks: surface.blocks,\n pages: navigation.pages,\n buildLineNumberMarkers,\n });\n const lineNumberingEnabled =\n Boolean(pageLayout.lineNumbering) && lineMarkers.length > 0;\n const distance = pageLayout.lineNumbering?.distance ?? 0;\n const gutterWidthPx = lineNumberingEnabled\n ? Math.max(40, Math.min(88, 24 + Math.round(distance * DEFAULT_PAGE_ESTIMATE_PX_PER_TWIP)))\n : 0;\n const showPageBorder = shouldRenderPageBorder(pageLayout, navigation.pages, navigation.activePageIndex);\n\n return {\n lineNumberingEnabled,\n gutterWidthPx,\n lineMarkers,\n showPageBorder,\n pageBorderDisplay: pageLayout.pageBorders?.display ?? \"none\",\n pageBorderStyle: showPageBorder ? buildPageBorderStyle(pageLayout) : undefined,\n documentGridType: pageLayout.documentGrid?.type ?? \"none\",\n documentGridStyle: buildDocumentGridStyle(pageLayout.documentGrid),\n };\n}\n\nfunction buildPageShellMetrics(\n pageLayout: RuntimeRenderSnapshot[\"pageLayout\"] | undefined,\n): PageShellMetrics {\n if (!pageLayout) {\n return {\n contentInsetStyle: {},\n pageFrameStyle: {},\n headerBandStyle: {},\n footerBandStyle: {},\n };\n }\n\n const horizontalInsetPx = Math.max(\n 24,\n Math.min(120, Math.round(pageLayout.marginLeft * DEFAULT_PAGE_ESTIMATE_PX_PER_TWIP)),\n );\n const verticalInsetPx = Math.max(\n 24,\n Math.min(140, Math.round(pageLayout.marginTop * DEFAULT_PAGE_ESTIMATE_PX_PER_TWIP)),\n );\n const headerBandHeightPx = Math.max(\n 40,\n Math.min(96, Math.round(pageLayout.headerMargin * DEFAULT_PAGE_ESTIMATE_PX_PER_TWIP + 16)),\n );\n const footerBandHeightPx = Math.max(\n 40,\n Math.min(96, Math.round(pageLayout.footerMargin * DEFAULT_PAGE_ESTIMATE_PX_PER_TWIP + 16)),\n );\n\n return {\n contentInsetStyle: {\n paddingLeft: `${horizontalInsetPx}px`,\n paddingRight: `${horizontalInsetPx}px`,\n paddingTop: `${Math.max(20, verticalInsetPx - 12)}px`,\n paddingBottom: `${Math.max(20, Math.round(pageLayout.marginBottom * DEFAULT_PAGE_ESTIMATE_PX_PER_TWIP) - 12)}px`,\n },\n pageFrameStyle: {\n backgroundColor: \"var(--color-page-bg)\",\n },\n headerBandStyle: {\n minHeight: `${headerBandHeightPx}px`,\n },\n footerBandStyle: {\n minHeight: `${footerBandHeightPx}px`,\n },\n };\n}\n\nfunction buildLineNumberMarkers(\n blocks: readonly SurfaceBlockSnapshot[],\n pages: ReadonlyArray<DocumentNavigationSnapshot[\"pages\"][number]>,\n): Array<{ id: string; label: string; topPx: number }> {\n const markers: Array<{ id: string; label: string; topPx: number }> = [];\n if (pages.length === 0) {\n return markers;\n }\n\n let currentTopTwips = 0;\n let lineNumber = 1;\n let lastPageIndex = -1;\n let lastSectionIndex = -1;\n\n for (const block of blocks) {\n const pageIndex = findPageForOffset(pages, block.from);\n const page = pages[pageIndex];\n if (!page) {\n continue;\n }\n\n const lineNumbering = page.layout.lineNumbering;\n const restartMode = lineNumbering?.restart ?? \"newPage\";\n const restartStart = lineNumbering?.start ?? 1;\n const countBy = Math.max(1, lineNumbering?.countBy ?? 1);\n const columnWidth = getUsableColumnWidth(page.layout);\n\n if (pageIndex !== lastPageIndex) {\n if (restartMode === \"newPage\" || lastPageIndex === -1) {\n lineNumber = restartStart;\n }\n lastPageIndex = pageIndex;\n }\n if (page.sectionIndex !== lastSectionIndex) {\n if (restartMode === \"newSection\" || lastSectionIndex === -1) {\n lineNumber = restartStart;\n }\n lastSectionIndex = page.sectionIndex;\n }\n\n if (block.kind === \"paragraph\" && lineNumbering) {\n const lineCount = estimateParagraphLineCount(block, columnWidth);\n const lineHeight = estimateParagraphLineHeight(block);\n const suppress = block.suppressLineNumbers === true;\n for (let lineIndex = 0; lineIndex < lineCount; lineIndex += 1) {\n if (!suppress && (lineNumber - restartStart) % countBy === 0) {\n markers.push({\n id: `${block.blockId}-${lineIndex}`,\n label: String(lineNumber),\n topPx:\n DOCUMENT_CONTENT_TOP_PADDING_PX +\n (currentTopTwips + lineIndex * lineHeight) * DEFAULT_PAGE_ESTIMATE_PX_PER_TWIP,\n });\n }\n if (!suppress) {\n lineNumber += 1;\n }\n }\n }\n\n currentTopTwips += estimateBlockHeight(block, columnWidth);\n }\n\n return markers;\n}\n\nfunction shouldRenderPageBorder(\n pageLayout: RuntimeRenderSnapshot[\"pageLayout\"],\n pages: ReadonlyArray<DocumentNavigationSnapshot[\"pages\"][number]>,\n activePageIndex: number,\n): boolean {\n const display = pageLayout?.pageBorders?.display ?? \"allPages\";\n const activePage = pages[activePageIndex];\n if (!pageLayout?.pageBorders || !activePage) {\n return false;\n }\n\n switch (display) {\n case \"firstPage\":\n return activePage.pageInSection === 0;\n case \"notFirstPage\":\n return activePage.pageInSection > 0;\n default:\n return true;\n }\n}\n\nfunction buildPageBorderStyle(\n pageLayout: NonNullable<RuntimeRenderSnapshot[\"pageLayout\"]>,\n): CSSProperties | undefined {\n const pageBorders = pageLayout.pageBorders;\n if (!pageBorders) {\n return undefined;\n }\n\n const leftInset = createInsetValue(\n pageBorders.left?.space,\n pageBorders.offsetFrom === \"text\"\n ? (pageLayout.marginLeft / Math.max(1, pageLayout.pageWidth)) * 100\n : 1.25,\n );\n const rightInset = createInsetValue(\n pageBorders.right?.space,\n pageBorders.offsetFrom === \"text\"\n ? (pageLayout.marginRight / Math.max(1, pageLayout.pageWidth)) * 100\n : 1.25,\n );\n const topInset = createInsetValue(\n pageBorders.top?.space,\n pageBorders.offsetFrom === \"text\"\n ? (pageLayout.marginTop / Math.max(1, pageLayout.pageHeight)) * 100\n : 1.5,\n );\n const bottomInset = createInsetValue(\n pageBorders.bottom?.space,\n pageBorders.offsetFrom === \"text\"\n ? (pageLayout.marginBottom / Math.max(1, pageLayout.pageHeight)) * 100\n : 1.5,\n );\n\n return {\n top: topInset,\n right: rightInset,\n bottom: bottomInset,\n left: leftInset,\n borderTop: toBorderCss(pageBorders.top),\n borderRight: toBorderCss(pageBorders.right),\n borderBottom: toBorderCss(pageBorders.bottom),\n borderLeft: toBorderCss(pageBorders.left),\n boxSizing: \"border-box\",\n mixBlendMode: pageBorders.zOrder === \"back\" ? \"multiply\" : undefined,\n };\n}\n\nfunction buildDocumentGridStyle(\n documentGrid: NonNullable<RuntimeRenderSnapshot[\"pageLayout\"]>[\"documentGrid\"] | undefined,\n): CSSProperties | undefined {\n if (!documentGrid || !documentGrid.type || documentGrid.type === \"default\") {\n return undefined;\n }\n\n const linePitchPx = Math.max(\n 18,\n Math.round((documentGrid.linePitch ?? 360) * DEFAULT_PAGE_ESTIMATE_PX_PER_TWIP),\n );\n const charSpacePx = Math.max(\n 12,\n Math.round((documentGrid.charSpace ?? 204) * DEFAULT_PAGE_ESTIMATE_PX_PER_TWIP),\n );\n const gridColor = \"rgba(15, 23, 42, 0.06)\";\n const backgrounds: string[] = [];\n\n if (\n documentGrid.type === \"lines\" ||\n documentGrid.type === \"linesAndChars\" ||\n documentGrid.type === \"snapToChars\"\n ) {\n backgrounds.push(\n `repeating-linear-gradient(to bottom, ${gridColor} 0, ${gridColor} 1px, transparent 1px, transparent ${linePitchPx}px)`,\n );\n }\n if (\n documentGrid.type === \"linesAndChars\" ||\n documentGrid.type === \"snapToChars\"\n ) {\n backgrounds.push(\n `repeating-linear-gradient(to right, rgba(15, 23, 42, 0.04) 0, rgba(15, 23, 42, 0.04) 1px, transparent 1px, transparent ${charSpacePx}px)`,\n );\n }\n\n if (backgrounds.length === 0) {\n return undefined;\n }\n\n return {\n backgroundImage: backgrounds.join(\", \"),\n backgroundOrigin: \"content-box\",\n };\n}\n\nfunction createInsetValue(spaceTwips: number | undefined, percent: number): string {\n const spacingPx = Math.max(0, Math.round((spaceTwips ?? 0) * DEFAULT_PAGE_ESTIMATE_PX_PER_TWIP));\n return `calc(${percent.toFixed(2)}% + ${spacingPx}px)`;\n}\n\nfunction resolveSelectionToolbarPlacement(\n anchor: SelectionToolbarAnchor | null | undefined,\n root: HTMLDivElement | null,\n zoomScale: number,\n): { placement: \"right\" | \"left\" | \"above\" | \"below\"; style: CSSProperties } | null {\n if (!anchor || !root) {\n return null;\n }\n\n const rootRect = root.getBoundingClientRect();\n if (rootRect.width <= 0 || rootRect.height <= 0 || zoomScale <= 0) {\n return null;\n }\n\n const centerX = (anchor.left + anchor.right) / 2;\n const centerY = (anchor.top + anchor.bottom) / 2;\n const localLeftEdge = (anchor.left - rootRect.left) / zoomScale;\n const localRightEdge = (anchor.right - rootRect.left) / zoomScale;\n const localLeft = (centerX - rootRect.left) / zoomScale;\n const localCenterY = (centerY - rootRect.top) / zoomScale;\n const localTop = (anchor.top - rootRect.top) / zoomScale;\n const localBottom = (anchor.bottom - rootRect.top) / zoomScale;\n const edgePadding = 16 / zoomScale;\n const containerWidth = rootRect.width / zoomScale;\n const containerHeight = rootRect.height / zoomScale;\n const gapPx = 12 / zoomScale;\n const estimatedToolbarWidth = Math.min(260 / zoomScale, Math.max(168 / zoomScale, containerWidth * 0.32));\n const estimatedToolbarHeight = 44 / zoomScale;\n const clampedCenterLeft = Math.max(\n edgePadding,\n Math.min(localLeft, Math.max(edgePadding, containerWidth - edgePadding)),\n );\n const clampedCenterY = Math.max(\n edgePadding + estimatedToolbarHeight / 2,\n Math.min(localCenterY, Math.max(edgePadding + estimatedToolbarHeight / 2, containerHeight - edgePadding - estimatedToolbarHeight / 2)),\n );\n const rightClearance = containerWidth - localRightEdge - gapPx - edgePadding;\n const leftClearance = localLeftEdge - gapPx - edgePadding;\n\n if (rightClearance >= estimatedToolbarWidth) {\n return {\n placement: \"right\",\n style: {\n left: `${localRightEdge}px`,\n top: `${clampedCenterY}px`,\n maxWidth: `${Math.max(220, containerWidth - edgePadding * 2)}px`,\n transform: `translate(${gapPx}px, -50%)`,\n },\n };\n }\n\n if (leftClearance >= estimatedToolbarWidth) {\n return {\n placement: \"left\",\n style: {\n left: `${localLeftEdge}px`,\n top: `${clampedCenterY}px`,\n maxWidth: `${Math.max(220, containerWidth - edgePadding * 2)}px`,\n transform: `translate(calc(-100% - ${gapPx}px), -50%)`,\n },\n };\n }\n\n const placement = localTop < estimatedToolbarHeight + gapPx + edgePadding ? \"below\" : \"above\";\n\n return {\n placement,\n style: {\n left: `${clampedCenterLeft}px`,\n top: `${placement === \"above\" ? localTop : localBottom}px`,\n maxWidth: `${Math.max(220, containerWidth - edgePadding * 2)}px`,\n transform:\n placement === \"above\"\n ? `translate(-50%, calc(-100% - ${gapPx}px))`\n : `translate(-50%, ${gapPx}px)`,\n },\n };\n}\n\nfunction toBorderCss(\n border:\n | NonNullable<NonNullable<RuntimeRenderSnapshot[\"pageLayout\"]>[\"pageBorders\"]>[\"top\"]\n | undefined,\n): string | undefined {\n if (!border || border.value === \"none\" || border.value === \"nil\") {\n return undefined;\n }\n\n const width = border.size ? `${Math.max(1, Math.round(border.size / 8))}px` : \"1px\";\n const style =\n border.value === \"double\"\n ? \"double\"\n : border.value === \"dotted\"\n ? \"dotted\"\n : border.value === \"dashed\" || border.value === \"dashSmallGap\"\n ? \"dashed\"\n : \"solid\";\n const color = border.color && border.color !== \"auto\" ? `#${border.color}` : \"rgba(31, 31, 31, 0.28)\";\n return `${width} ${style} ${color}`;\n}\n","import type { EditorStoryTarget } from \"../../api/public-types\";\n\nexport type Position = number;\nexport type Assoc = -1 | 1;\n\nexport interface DocRange {\n from: Position;\n to: Position;\n}\n\nexport interface BoundaryAssoc {\n start: Assoc;\n end: Assoc;\n}\n\nexport interface RangeAnchor {\n kind: \"range\";\n range: DocRange;\n assoc: BoundaryAssoc;\n}\n\nexport interface NodeAnchor {\n kind: \"node\";\n at: Position;\n assoc: Assoc;\n}\n\nexport interface DetachedAnchor {\n kind: \"detached\";\n lastKnownRange: DocRange;\n reason: \"deleted\" | \"invalidatedByStructureChange\" | \"importAmbiguity\";\n}\n\nexport type EditorAnchorProjection = RangeAnchor | NodeAnchor | DetachedAnchor;\n\nexport interface MappingStep {\n from: Position;\n to: Position;\n insertSize: number;\n}\n\nexport interface MappingResult {\n position: Position;\n deleted: boolean;\n}\n\nexport interface TransactionMapping {\n steps: MappingStep[];\n metadata?: {\n invalidatesStructures?: boolean;\n affectsComments?: boolean;\n affectsRevisions?: boolean;\n affectsOpaqueFragments?: boolean;\n [key: string]: unknown;\n };\n}\n\nexport const DEFAULT_BOUNDARY_ASSOC: BoundaryAssoc = {\n start: 1,\n end: -1,\n};\n\nexport function createRangeAnchor(\n from: Position,\n to = from,\n assoc: BoundaryAssoc = DEFAULT_BOUNDARY_ASSOC,\n): RangeAnchor {\n return {\n kind: \"range\",\n range: normalizeRange({ from, to }),\n assoc,\n };\n}\n\nexport function createNodeAnchor(at: Position, assoc: Assoc = 1): NodeAnchor {\n return {\n kind: \"node\",\n at,\n assoc,\n };\n}\n\nexport function createDetachedAnchor(\n lastKnownRange: DocRange,\n reason: DetachedAnchor[\"reason\"],\n): DetachedAnchor {\n return {\n kind: \"detached\",\n lastKnownRange: normalizeRange(lastKnownRange),\n reason,\n };\n}\n\nexport function createEmptyMapping(): TransactionMapping {\n return {\n steps: [],\n };\n}\n\nexport function normalizeRange(range: DocRange): DocRange {\n return range.from <= range.to\n ? { from: range.from, to: range.to }\n : { from: range.to, to: range.from };\n}\n\nexport function getEffectiveRange(anchor: EditorAnchorProjection): DocRange {\n if (anchor.kind === \"range\") {\n return anchor.range;\n }\n if (anchor.kind === \"node\") {\n return { from: anchor.at, to: anchor.at };\n }\n return anchor.lastKnownRange;\n}\n\nexport function mapPosition(\n position: Position,\n assoc: Assoc,\n mapping: TransactionMapping,\n): MappingResult {\n let mappedPosition = position;\n let deleted = false;\n\n for (const step of mapping.steps) {\n const next = mapPositionThroughStep(mappedPosition, assoc, step);\n mappedPosition = next.position;\n deleted = deleted || next.deleted;\n }\n\n return {\n position: mappedPosition,\n deleted,\n };\n}\n\nexport function mapAnchor(\n anchor: EditorAnchorProjection,\n mapping: TransactionMapping,\n): EditorAnchorProjection {\n if (anchor.kind === \"detached\") {\n return anchor;\n }\n\n if (anchor.kind === \"node\") {\n const mapped = mapPosition(anchor.at, anchor.assoc, mapping);\n\n if (mapped.deleted) {\n return createDetachedAnchor(\n { from: anchor.at, to: anchor.at + 1 },\n mapping.metadata?.invalidatesStructures\n ? \"invalidatedByStructureChange\"\n : \"deleted\",\n );\n }\n\n return createNodeAnchor(mapped.position, anchor.assoc);\n }\n\n const from = mapPosition(anchor.range.from, anchor.assoc.start, mapping);\n const to = mapPosition(anchor.range.to, anchor.assoc.end, mapping);\n const mappedRange = normalizeRange({ from: from.position, to: to.position });\n\n if (from.deleted && to.deleted && mappedRange.from === mappedRange.to) {\n return createDetachedAnchor(\n anchor.range,\n mapping.metadata?.invalidatesStructures\n ? \"invalidatedByStructureChange\"\n : \"deleted\",\n );\n }\n\n return createRangeAnchor(mappedRange.from, mappedRange.to, anchor.assoc);\n}\n\nexport function mapRange(\n range: DocRange,\n assoc: BoundaryAssoc,\n mapping: TransactionMapping,\n): RangeAnchor | DetachedAnchor {\n const mapped = mapAnchor(createRangeAnchor(range.from, range.to, assoc), mapping);\n return mapped.kind === \"node\" ? createRangeAnchor(mapped.at, mapped.at, assoc) : mapped;\n}\n\nexport function areAnchorsEqual(\n left: EditorAnchorProjection,\n right: EditorAnchorProjection,\n): boolean {\n if (left.kind !== right.kind) {\n return false;\n }\n\n if (left.kind === \"detached\" && right.kind === \"detached\") {\n return (\n left.reason === right.reason &&\n left.lastKnownRange.from === right.lastKnownRange.from &&\n left.lastKnownRange.to === right.lastKnownRange.to\n );\n }\n\n if (left.kind === \"node\" && right.kind === \"node\") {\n return left.at === right.at && left.assoc === right.assoc;\n }\n\n if (left.kind === \"range\" && right.kind === \"range\") {\n return (\n left.range.from === right.range.from &&\n left.range.to === right.range.to &&\n left.assoc.start === right.assoc.start &&\n left.assoc.end === right.assoc.end\n );\n }\n\n return false;\n}\n\nexport function storyTargetsEqual(\n left: EditorStoryTarget | undefined,\n right: EditorStoryTarget | undefined,\n): boolean {\n if (left === right) return true;\n if (!left || !right) return left === right;\n if (left.kind !== right.kind) return false;\n if (left.kind === \"main\") return true;\n if (left.kind === \"header\" && right.kind === \"header\") {\n return (\n left.relationshipId === right.relationshipId &&\n left.variant === right.variant &&\n (left.sectionIndex === undefined ||\n right.sectionIndex === undefined\n ? true\n : left.sectionIndex === right.sectionIndex)\n );\n }\n if (left.kind === \"footer\" && right.kind === \"footer\") {\n return (\n left.relationshipId === right.relationshipId &&\n left.variant === right.variant &&\n (left.sectionIndex === undefined ||\n right.sectionIndex === undefined\n ? true\n : left.sectionIndex === right.sectionIndex)\n );\n }\n if (left.kind === \"footnote\" && right.kind === \"footnote\") {\n return left.noteId === right.noteId;\n }\n if (left.kind === \"endnote\" && right.kind === \"endnote\") {\n return left.noteId === right.noteId;\n }\n return false;\n}\n\nexport const MAIN_STORY_TARGET: EditorStoryTarget = { kind: \"main\" };\n\nfunction mapPositionThroughStep(\n position: Position,\n assoc: Assoc,\n step: MappingStep,\n): MappingResult {\n if (position < step.from) {\n return { position, deleted: false };\n }\n\n if (position > step.to) {\n return {\n position: position + step.insertSize - (step.to - step.from),\n deleted: false,\n };\n }\n\n if (position === step.from) {\n return {\n position: assoc < 0 ? step.from : step.from + step.insertSize,\n deleted: false,\n };\n }\n\n if (position === step.to) {\n return {\n position: assoc < 0 ? step.from : step.from + step.insertSize,\n deleted: false,\n };\n }\n\n return {\n position: assoc < 0 ? step.from : step.from + step.insertSize,\n deleted: true,\n };\n}\n","import type {\n PageLayoutSnapshot,\n SurfaceBlockSnapshot,\n SurfaceInlineSegment,\n} from \"../api/public-types\";\n\nconst DEFAULT_FONT_SIZE_POINTS = 12;\nconst DEFAULT_LINE_HEIGHT_TWIPS = 280;\nconst MIN_BLOCK_HEIGHT_TWIPS = 240;\nconst TABLE_ROW_PADDING_TWIPS = 120;\n\nexport const DEFAULT_PAGE_ESTIMATE_PX_PER_TWIP = 1 / 15;\n\nexport function estimateBlockHeight(\n block: SurfaceBlockSnapshot | undefined,\n columnWidth: number,\n): number {\n if (!block) {\n return 0;\n }\n\n switch (block.kind) {\n case \"paragraph\":\n return estimateParagraphHeight(block, columnWidth);\n case \"table\":\n return estimateTableHeight(block, columnWidth);\n case \"sdt_block\":\n return Math.max(\n MIN_BLOCK_HEIGHT_TWIPS,\n block.children.reduce((total, child) => total + estimateBlockHeight(child, columnWidth), 0),\n );\n case \"opaque_block\":\n return block.label === \"Section break\" ? 0 : MIN_BLOCK_HEIGHT_TWIPS;\n }\n}\n\nexport function estimateParagraphHeight(\n block: Extract<SurfaceBlockSnapshot, { kind: \"paragraph\" }>,\n columnWidth: number,\n): number {\n const lineHeight = estimateParagraphLineHeight(block);\n const lineCount = estimateParagraphLineCount(block, columnWidth);\n const spacingBefore = block.spacing?.before ?? 0;\n const spacingAfter = block.spacing?.after ?? 0;\n return Math.max(\n MIN_BLOCK_HEIGHT_TWIPS,\n lineHeight * lineCount + spacingBefore + spacingAfter,\n );\n}\n\nexport function estimateParagraphLineHeight(\n block: Extract<SurfaceBlockSnapshot, { kind: \"paragraph\" }>,\n): number {\n const explicitLine = block.spacing?.line;\n if (typeof explicitLine === \"number\" && explicitLine > 0) {\n return explicitLine;\n }\n\n const fontSizeHalfPoints = block.segments.find(\n (segment): segment is Extract<SurfaceInlineSegment, { kind: \"text\" }> =>\n segment.kind === \"text\" && typeof segment.markAttrs?.fontSize === \"number\",\n )?.markAttrs?.fontSize;\n const fontSizePoints =\n typeof fontSizeHalfPoints === \"number\"\n ? fontSizeHalfPoints / 2\n : DEFAULT_FONT_SIZE_POINTS;\n return Math.max(\n DEFAULT_LINE_HEIGHT_TWIPS,\n Math.round(fontSizePoints * 20 * 1.35),\n );\n}\n\nexport function estimateParagraphLineCount(\n block: Extract<SurfaceBlockSnapshot, { kind: \"paragraph\" }>,\n columnWidth: number,\n): number {\n const averageCharWidth = estimateAverageCharWidth(block);\n const charsPerLine = Math.max(12, Math.floor(columnWidth / averageCharWidth));\n let lineCount = 1;\n let currentLineChars = estimatedPrefixLength(block);\n\n for (const segment of block.segments) {\n switch (segment.kind) {\n case \"text\":\n currentLineChars += Array.from(segment.text).length;\n while (currentLineChars > charsPerLine) {\n lineCount += 1;\n currentLineChars -= charsPerLine;\n }\n break;\n case \"tab\":\n currentLineChars += 4;\n break;\n case \"hard_break\":\n lineCount += 1;\n currentLineChars = 0;\n break;\n case \"image\":\n lineCount += Math.max(1, Math.round(segment.display === \"floating\" ? 2 : 1));\n currentLineChars = 0;\n break;\n case \"note_ref\":\n currentLineChars += 1;\n break;\n case \"opaque_inline\":\n if (segment.presentation !== \"quiet-marker\") {\n currentLineChars += segment.label.length > 0 ? 1 : 0;\n }\n break;\n }\n }\n\n return Math.max(1, lineCount);\n}\n\nexport function getUsablePageHeight(layout: PageLayoutSnapshot): number {\n return Math.max(\n 1440,\n layout.pageHeight - layout.marginTop - layout.marginBottom,\n );\n}\n\nexport interface PageColumnMetric {\n width: number;\n space: number;\n}\n\nexport function getUsableColumnMetrics(\n layout: PageLayoutSnapshot,\n): PageColumnMetric[] {\n const usableWidth = Math.max(\n 1440,\n layout.pageWidth - layout.marginLeft - layout.marginRight - layout.gutter,\n );\n const columnCount = Math.max(1, layout.columns);\n if (\n !layout.equalWidthColumns &&\n layout.columnDefinitions.length > 0\n ) {\n return layout.columnDefinitions.map((column, index) => ({\n width: Math.max(720, column.width),\n space:\n index < layout.columnDefinitions.length - 1\n ? Math.max(0, column.space ?? 0)\n : 0,\n }));\n }\n\n const width = columnCount <= 1\n ? usableWidth\n : Math.max(720, Math.floor(usableWidth / columnCount));\n return Array.from({ length: columnCount }, () => ({\n width,\n space: 0,\n }));\n}\n\nexport function getUsableColumnWidth(layout: PageLayoutSnapshot): number {\n return getUsableColumnMetrics(layout)[0]?.width ?? 1440;\n}\n\nfunction estimateTableHeight(\n block: Extract<SurfaceBlockSnapshot, { kind: \"table\" }>,\n columnWidth: number,\n): number {\n let totalHeight = 0;\n for (const row of block.rows) {\n const explicitHeight = row.height ?? 0;\n if (explicitHeight > 0) {\n totalHeight += explicitHeight;\n continue;\n }\n\n let rowHeight = MIN_BLOCK_HEIGHT_TWIPS;\n for (const cell of row.cells) {\n const cellHeight = cell.content.reduce(\n (total, child) => total + estimateBlockHeight(child, columnWidth),\n 0,\n );\n rowHeight = Math.max(rowHeight, cellHeight + TABLE_ROW_PADDING_TWIPS);\n }\n totalHeight += rowHeight;\n }\n return Math.max(MIN_BLOCK_HEIGHT_TWIPS, totalHeight);\n}\n\nfunction estimateAverageCharWidth(\n block: Extract<SurfaceBlockSnapshot, { kind: \"paragraph\" }>,\n): number {\n const fontSizeHalfPoints = block.segments.find(\n (segment): segment is Extract<SurfaceInlineSegment, { kind: \"text\" }> =>\n segment.kind === \"text\" && typeof segment.markAttrs?.fontSize === \"number\",\n )?.markAttrs?.fontSize;\n const fontSizePoints =\n typeof fontSizeHalfPoints === \"number\"\n ? fontSizeHalfPoints / 2\n : DEFAULT_FONT_SIZE_POINTS;\n return Math.max(96, Math.round(fontSizePoints * 12));\n}\n\nfunction estimatedPrefixLength(\n block: Extract<SurfaceBlockSnapshot, { kind: \"paragraph\" }>,\n): number {\n const prefix = block.numberingPrefix ?? \"\";\n const suffix =\n block.numberingSuffix === \"space\"\n ? 1\n : block.numberingSuffix === \"tab\"\n ? 4\n : 0;\n return prefix.length + suffix;\n}\n","/**\n * Runtime-owned document navigation model.\n *\n * Derives the page stack, heading outline, and navigation context entirely\n * from canonical document state and section properties. DOM scroll position,\n * CSS layout, and shell-local state are never consulted — the runtime is the\n * source of pagination truth.\n *\n * This module owns read models only. Section authoring commands live in\n * `src/core/commands/section-layout-commands.ts` (owned by A3).\n */\n\nimport type {\n DocumentHeadingSnapshot,\n DocumentNavigationSnapshot,\n DocumentPageSnapshot,\n EditorStoryTarget,\n EditorSurfaceSnapshot,\n SurfaceBlockSnapshot,\n SurfaceInlineSegment,\n} from \"../api/public-types\";\nimport type {\n FootnoteCollection,\n} from \"../model/canonical-document.ts\";\nimport type { CanonicalDocumentEnvelope } from \"../core/state/editor-state.ts\";\nimport { createSelectionSnapshot } from \"../core/state/editor-state.ts\";\nimport { MAIN_STORY_TARGET } from \"../core/selection/mapping.ts\";\nimport { createEditorSurfaceSnapshot } from \"./surface-projection.ts\";\nimport {\n estimateBlockHeight,\n estimateParagraphHeight,\n getUsableColumnMetrics,\n getUsableColumnWidth,\n getUsablePageHeight,\n} from \"./page-layout-estimation.ts\";\nimport {\n buildPageLayoutSnapshot,\n buildResolvedSections,\n findSectionForPosition as resolveSectionForPosition,\n resolveSectionForStoryTarget,\n type ResolvedDocumentSection,\n} from \"./document-layout.ts\";\nimport { findNoteReferencePosition } from \"./view-state.ts\";\n\nconst MIN_BLOCK_HEIGHT_TWIPS = 240;\nconst FOOTNOTE_REFERENCE_RESERVATION_TWIPS = 180;\n\ninterface NavigationBaseSnapshot {\n mainSurface: EditorSurfaceSnapshot;\n sections: ResolvedDocumentSection[];\n pages: DocumentPageSnapshot[];\n headings: DocumentHeadingSnapshot[];\n}\n\nconst navigationBaseCache = new WeakMap<\n CanonicalDocumentEnvelope[\"content\"],\n NavigationBaseSnapshot & {\n styles: CanonicalDocumentEnvelope[\"styles\"];\n subParts: CanonicalDocumentEnvelope[\"subParts\"];\n }\n>();\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Build the full document navigation snapshot from canonical state.\n *\n * The page stack is derived from structured block layout, section geometry,\n * and bounded pagination rules. DOM scroll position and CSS layout are never\n * consulted.\n */\nexport function createDocumentNavigationSnapshot(\n document: CanonicalDocumentEnvelope,\n selectionHead: number,\n activeStory: EditorStoryTarget,\n): DocumentNavigationSnapshot {\n const base = getNavigationBaseSnapshot(document);\n const navigationContext = resolveActiveNavigationContext(\n document,\n base.pages,\n base.sections,\n base.mainSurface,\n selectionHead,\n activeStory,\n );\n\n return {\n pageCount: base.pages.length,\n pages: base.pages,\n headings: base.headings,\n activePageIndex: navigationContext.activePageIndex,\n activeSectionIndex: navigationContext.activeSectionIndex,\n };\n}\n\nfunction getNavigationBaseSnapshot(\n document: CanonicalDocumentEnvelope,\n): NavigationBaseSnapshot {\n const cached = navigationBaseCache.get(document.content);\n if (\n cached &&\n cached.styles === document.styles &&\n cached.subParts === document.subParts\n ) {\n return cached;\n }\n\n const mainSurface = createEditorSurfaceSnapshot(\n document,\n createSelectionSnapshot(0, 0),\n MAIN_STORY_TARGET,\n );\n const sections = buildResolvedSections(document);\n const pages = buildPageStack(document, sections, mainSurface);\n const headings = buildHeadingOutline(document, mainSurface, sections, pages);\n const next = {\n mainSurface,\n sections,\n pages,\n headings,\n styles: document.styles,\n subParts: document.subParts,\n };\n navigationBaseCache.set(document.content, next);\n return next;\n}\n\n/**\n * Find the page index that contains a given main-story character offset.\n */\nexport function findPageForOffset(\n pages: readonly DocumentPageSnapshot[],\n offset: number,\n): number {\n for (let i = 0; i < pages.length; i++) {\n if (offset < pages[i]!.endOffset) {\n return i;\n }\n }\n return Math.max(0, pages.length - 1);\n}\n\n/**\n * Find the section index that contains a given main-story character offset.\n */\nexport function findSectionForOffset(\n sections: readonly ResolvedDocumentSection[],\n offset: number,\n): number {\n return sections.length > 0 ? resolveSectionForPosition(sections, offset).index : 0;\n}\n\nfunction buildPageStack(\n document: CanonicalDocumentEnvelope,\n sections: ResolvedDocumentSection[],\n mainSurface: EditorSurfaceSnapshot,\n): DocumentPageSnapshot[] {\n const pages: DocumentPageSnapshot[] = [];\n let globalPageIndex = 0;\n\n for (const section of sections) {\n const layout = buildPageLayoutSnapshot(\n section.index,\n section.properties ?? document.subParts?.finalSectionProperties,\n document.subParts,\n );\n const sectionBlocks = collectSectionBlocks(mainSurface.blocks, section.start, section.end);\n const paginated = paginateSectionBlocks(\n section,\n sectionBlocks,\n layout,\n document.subParts?.footnoteCollection,\n );\n\n for (const page of paginated) {\n pages.push({\n ...page,\n pageIndex: globalPageIndex,\n });\n globalPageIndex += 1;\n }\n }\n\n // Guarantee at least one page\n if (pages.length === 0) {\n pages.push({\n pageIndex: 0,\n sectionIndex: 0,\n pageInSection: 0,\n startOffset: 0,\n endOffset: mainSurface.storySize,\n layout: buildPageLayoutSnapshot(\n 0,\n document.subParts?.finalSectionProperties,\n document.subParts,\n ),\n });\n }\n\n return pages;\n}\n\nfunction collectSectionBlocks(\n blocks: readonly SurfaceBlockSnapshot[],\n start: number,\n end: number,\n): SurfaceBlockSnapshot[] {\n return blocks.filter((block) => block.to > start && block.from < end);\n}\n\nfunction paginateSectionBlocks(\n section: ResolvedDocumentSection,\n blocks: readonly SurfaceBlockSnapshot[],\n layout: DocumentPageSnapshot[\"layout\"],\n footnotes: FootnoteCollection | undefined,\n): Omit<DocumentPageSnapshot, \"pageIndex\">[] {\n if (blocks.length === 0) {\n return [\n {\n sectionIndex: section.index,\n pageInSection: 0,\n startOffset: section.start,\n endOffset: section.end,\n layout,\n },\n ];\n }\n\n const pages: Omit<DocumentPageSnapshot, \"pageIndex\">[] = [];\n const usableHeight = getUsablePageHeight(layout);\n const columnMetrics = getUsableColumnMetrics(layout);\n const maxColumns = Math.max(1, columnMetrics.length);\n let pageStart = section.start;\n let columnHeight = 0;\n let columnIndex = 0;\n let pageInSection = 0;\n let reservedNoteHeight = 0;\n const reservedNotes = new Set<string>();\n\n const pushPage = (endOffset: number): void => {\n const boundedEnd = Math.max(pageStart, Math.min(endOffset, section.end));\n if (boundedEnd === pageStart && pages.length > 0) {\n return;\n }\n pages.push({\n sectionIndex: section.index,\n pageInSection,\n startOffset: pageStart,\n endOffset: boundedEnd,\n layout,\n });\n pageInSection += 1;\n pageStart = boundedEnd;\n columnHeight = 0;\n columnIndex = 0;\n reservedNoteHeight = 0;\n reservedNotes.clear();\n };\n\n for (let index = 0; index < blocks.length; index += 1) {\n const block = blocks[index]!;\n const nextBoundary = blocks[index + 1]?.from ?? section.end;\n while (true) {\n const columnWidth =\n columnMetrics[Math.min(columnIndex, columnMetrics.length - 1)]?.width ??\n getUsableColumnWidth(layout);\n const baseHeight = estimateBlockHeight(block, columnWidth);\n const keepWithNextHeight =\n block.kind === \"paragraph\" && block.keepNext\n ? baseHeight + estimateBlockHeight(blocks[index + 1], columnWidth)\n : baseHeight;\n const noteHeight = estimateFootnoteReservation(block, footnotes, columnWidth, reservedNotes);\n const projectedHeight = columnHeight + keepWithNextHeight + reservedNoteHeight + noteHeight;\n\n if (block.kind === \"paragraph\" && block.pageBreakBefore && pageStart < block.from) {\n pushPage(block.from);\n continue;\n }\n if (projectedHeight > usableHeight && pageStart < block.from) {\n if (columnIndex < maxColumns - 1) {\n columnIndex += 1;\n columnHeight = 0;\n reservedNoteHeight = 0;\n reservedNotes.clear();\n continue;\n }\n pushPage(block.from);\n continue;\n }\n\n const effectiveNoteHeight = estimateFootnoteReservation(\n block,\n footnotes,\n columnWidth,\n reservedNotes,\n );\n columnHeight += baseHeight;\n reservedNoteHeight += effectiveNoteHeight;\n currentPageNoteIds(block).forEach((noteKey) => reservedNotes.add(noteKey));\n\n if (hasColumnBreak(block)) {\n if (columnIndex < maxColumns - 1) {\n columnIndex += 1;\n columnHeight = 0;\n reservedNoteHeight = 0;\n reservedNotes.clear();\n } else {\n pushPage(nextBoundary);\n }\n break;\n }\n\n if (index === blocks.length - 1) {\n pushPage(section.end);\n }\n break;\n }\n }\n\n return pages.length > 0\n ? pages\n : [\n {\n sectionIndex: section.index,\n pageInSection: 0,\n startOffset: section.start,\n endOffset: section.end,\n layout,\n },\n ];\n}\n\nfunction resolveActiveNavigationContext(\n document: CanonicalDocumentEnvelope,\n pages: readonly DocumentPageSnapshot[],\n sections: readonly ResolvedDocumentSection[],\n mainSurface: EditorSurfaceSnapshot,\n selectionHead: number,\n activeStory: EditorStoryTarget,\n): { activePageIndex: number; activeSectionIndex: number } {\n if (activeStory.kind === \"main\") {\n const activePageIndex = findPageForOffset(pages, selectionHead);\n return {\n activePageIndex,\n activeSectionIndex: pages[activePageIndex]?.sectionIndex ?? 0,\n };\n }\n\n if (activeStory.kind === \"header\" || activeStory.kind === \"footer\") {\n const section = resolveSectionForStoryTarget(document, sections, activeStory);\n if (section) {\n return {\n activePageIndex: findFirstPageIndexForSection(pages, section.index),\n activeSectionIndex: section.index,\n };\n }\n }\n\n if (activeStory.kind === \"footnote\" || activeStory.kind === \"endnote\") {\n const referencePosition = findNoteReferencePosition(mainSurface, activeStory);\n const activePageIndex = findPageForOffset(pages, referencePosition);\n return {\n activePageIndex,\n activeSectionIndex:\n pages[activePageIndex]?.sectionIndex ??\n findSectionForOffset(sections, referencePosition),\n };\n }\n\n return {\n activePageIndex: 0,\n activeSectionIndex: 0,\n };\n}\n\nfunction findFirstPageIndexForSection(\n pages: readonly DocumentPageSnapshot[],\n sectionIndex: number,\n): number {\n const match = pages.findIndex((page) => page.sectionIndex === sectionIndex);\n return match >= 0 ? match : 0;\n}\n\nfunction estimateFootnoteReservation(\n block: SurfaceBlockSnapshot,\n footnotes: FootnoteCollection | undefined,\n columnWidth: number,\n reservedNotes: ReadonlySet<string>,\n): number {\n if (!footnotes || block.kind !== \"paragraph\") {\n return 0;\n }\n\n let reservation = 0;\n for (const noteKey of currentPageNoteIds(block)) {\n if (reservedNotes.has(noteKey)) {\n continue;\n }\n\n const [noteKind, noteId] = noteKey.split(\":\");\n const noteCollection =\n noteKind === \"endnote\" ? footnotes.endnotes : footnotes.footnotes;\n const note = noteCollection[noteId];\n reservation += FOOTNOTE_REFERENCE_RESERVATION_TWIPS;\n if (note) {\n reservation += note.blocks.reduce(\n (total, child) => total + estimateCanonicalNoteBlockHeight(child, columnWidth),\n 0,\n );\n }\n }\n\n return reservation;\n}\n\nfunction estimateCanonicalNoteBlockHeight(\n block: FootnoteCollection[\"footnotes\"][string][\"blocks\"][number],\n columnWidth: number,\n): number {\n switch (block.type) {\n case \"paragraph\":\n return estimateParagraphHeight(\n {\n blockId: \"note\",\n kind: \"paragraph\",\n from: 0,\n to: 0,\n ...(block.styleId ? { styleId: block.styleId } : {}),\n segments: createEstimatedNoteSegments(block.children),\n },\n columnWidth,\n );\n case \"table\":\n return MIN_BLOCK_HEIGHT_TWIPS * Math.max(1, block.rows.length);\n default:\n return MIN_BLOCK_HEIGHT_TWIPS;\n }\n}\n\nfunction createEstimatedNoteSegments(\n children: Extract<FootnoteCollection[\"footnotes\"][string][\"blocks\"][number], { type: \"paragraph\" }>[\"children\"],\n): SurfaceInlineSegment[] {\n const segments: SurfaceInlineSegment[] = [];\n\n children.forEach((child, index) => {\n if (child.type === \"text\") {\n segments.push({\n segmentId: `note-${index}`,\n kind: \"text\",\n from: 0,\n to: Array.from(child.text).length,\n text: child.text,\n });\n return;\n }\n\n if (child.type === \"hard_break\" || child.type === \"tab\") {\n segments.push({\n segmentId: `note-${index}`,\n kind: child.type,\n from: 0,\n to: 1,\n });\n }\n });\n\n return segments;\n}\n\nfunction currentPageNoteIds(\n block: SurfaceBlockSnapshot,\n): Set<string> {\n const notes = new Set<string>();\n if (block.kind !== \"paragraph\") {\n return notes;\n }\n\n for (const segment of block.segments) {\n if (segment.kind === \"note_ref\" && segment.noteId) {\n notes.add(`${segment.noteKind}:${segment.noteId}`);\n }\n }\n return notes;\n}\n\nfunction hasColumnBreak(block: SurfaceBlockSnapshot): boolean {\n return block.kind === \"paragraph\" && block.segments.some(\n (segment) =>\n segment.kind === \"opaque_inline\" &&\n segment.label === \"Column break\",\n );\n}\n\n// ---------------------------------------------------------------------------\n// Heading outline\n// ---------------------------------------------------------------------------\n\n/** Style IDs that map to heading levels by convention. */\nconst HEADING_STYLE_PATTERN = /^heading\\s*(\\d+)$/i;\n\nfunction headingLevelFromStyleId(styleId?: string): number | null {\n if (!styleId) return null;\n const match = HEADING_STYLE_PATTERN.exec(styleId);\n if (match) {\n const level = parseInt(match[1]!, 10);\n return level >= 1 && level <= 9 ? level : null;\n }\n return null;\n}\n\nfunction buildHeadingOutline(\n document: CanonicalDocumentEnvelope,\n mainSurface: EditorSurfaceSnapshot,\n sections: ResolvedDocumentSection[],\n pages: DocumentPageSnapshot[],\n): DocumentHeadingSnapshot[] {\n const headings: DocumentHeadingSnapshot[] = [];\n\n for (const block of mainSurface.blocks) {\n if (block.kind !== \"paragraph\") continue;\n\n // Check explicit outlineLevel first, then style-based heading detection\n const outlineLevel = block.outlineLevel;\n const styleLevel = resolveHeadingLevelFromStyle(document, block.styleId);\n const level =\n outlineLevel !== undefined && outlineLevel >= 0\n ? outlineLevel + 1\n : styleLevel;\n\n if (level === null) continue;\n\n const text = extractParagraphText(block);\n if (!text.trim()) continue;\n\n const offset = block.from;\n const pageIndex = findPageForOffset(pages, offset);\n const sectionIndex = findSectionForOffset(sections, offset);\n\n headings.push({\n headingId: `heading-${block.blockId}-${offset}`,\n level,\n text: text.trim(),\n offset,\n pageIndex,\n sectionIndex,\n });\n }\n\n return headings;\n}\n\nfunction resolveHeadingLevelFromStyle(\n document: CanonicalDocumentEnvelope,\n styleId?: string,\n): number | null {\n if (!styleId) {\n return null;\n }\n\n const visited = new Set<string>();\n let currentStyleId: string | undefined = styleId;\n while (currentStyleId && !visited.has(currentStyleId)) {\n visited.add(currentStyleId);\n const style:\n | { outlineLevel?: number; basedOn?: string }\n | undefined = document.styles.paragraphs[currentStyleId];\n if (!style) {\n break;\n }\n if (\n typeof style.outlineLevel === \"number\" &&\n style.outlineLevel >= 0 &&\n style.outlineLevel <= 8\n ) {\n return style.outlineLevel + 1;\n }\n currentStyleId = style.basedOn;\n }\n\n return headingLevelFromStyleId(styleId);\n}\n\nfunction extractParagraphText(\n block: Extract<SurfaceBlockSnapshot, { kind: \"paragraph\" }>,\n): string {\n let text = \"\";\n for (const segment of block.segments) {\n switch (segment.kind) {\n case \"text\":\n text += segment.text;\n break;\n case \"tab\":\n text += \"\\t\";\n break;\n case \"hard_break\":\n text += \"\\n\";\n break;\n }\n }\n return text;\n}\n","export type PerfProbeKind =\n | \"typing\"\n | \"selection\"\n | \"runtime.create\"\n | \"snapshot.surface\"\n | \"snapshot.compatibility\"\n | \"snapshot.navigation\"\n | \"pm.rebuild\"\n | \"pm.decorations\"\n | \"pm.mount\"\n | \"shell.render\"\n | \"workspace.chrome\"\n | \"selection.sync\";\n\nexport interface PerfProbeSample {\n token: string;\n kind: PerfProbeKind;\n durationMs: number;\n recordedAt: number;\n}\n\ninterface PendingProbe {\n kind: PerfProbeKind;\n startedAt: number;\n}\n\ninterface PerfProbeState {\n enabled?: boolean;\n nextToken?: number;\n pending?: Record<string, PendingProbe>;\n samples?: PerfProbeSample[];\n maxSamples?: number;\n invalidationCounts?: Record<string, number>;\n}\n\nexport interface PerfProbeSummary {\n samples: PerfProbeSample[];\n latest: Partial<Record<PerfProbeKind, PerfProbeSample | null>>;\n invalidationCounts: Record<string, number>;\n}\n\ndeclare global {\n interface Window {\n __DOCX_REACT_PERF_PROBE__?: PerfProbeState;\n }\n}\n\nexport function startPerfProbe(kind: PerfProbeKind): string | null {\n const state = getEnabledState();\n if (!state) {\n return null;\n }\n\n const token = `${kind}-${state.nextToken ?? 0}`;\n state.nextToken = (state.nextToken ?? 0) + 1;\n state.pending ??= {};\n state.pending[token] = {\n kind,\n startedAt: performance.now(),\n };\n return token;\n}\n\nexport function finishPerfProbe(token: string | null | undefined): PerfProbeSample | null {\n if (!token) {\n return null;\n }\n const state = getEnabledState();\n if (!state?.pending?.[token]) {\n return null;\n }\n\n const pending = state.pending[token];\n delete state.pending[token];\n\n const sample: PerfProbeSample = {\n token,\n kind: pending.kind,\n durationMs: performance.now() - pending.startedAt,\n recordedAt: Date.now(),\n };\n\n pushSample(state, sample);\n\n return sample;\n}\n\nexport function recordPerfSample(\n kind: PerfProbeKind,\n durationMs = 0,\n): PerfProbeSample | null {\n const state = getEnabledState();\n if (!state) {\n return null;\n }\n\n const token = `${kind}-${state.nextToken ?? 0}`;\n state.nextToken = (state.nextToken ?? 0) + 1;\n const sample: PerfProbeSample = {\n token,\n kind,\n durationMs,\n recordedAt: Date.now(),\n };\n pushSample(state, sample);\n return sample;\n}\n\nexport function incrementInvalidationCounter(\n counter: string,\n amount = 1,\n): number {\n const state = getEnabledState();\n if (!state) {\n return 0;\n }\n\n state.invalidationCounts ??= {};\n state.invalidationCounts[counter] =\n (state.invalidationCounts[counter] ?? 0) + amount;\n return state.invalidationCounts[counter]!;\n}\n\nexport function getLatestPerfSummary(): PerfProbeSummary | null {\n const state = getEnabledState();\n const samples = state?.samples ?? [];\n if (!state || samples.length === 0) {\n return null;\n }\n\n return {\n samples: [...samples],\n latest: buildLatestSampleMap(samples),\n invalidationCounts: { ...(state.invalidationCounts ?? {}) },\n };\n}\n\nexport function resetPerfProbeState(): void {\n const state = getEnabledState();\n if (!state) {\n return;\n }\n state.nextToken = 0;\n state.pending = {};\n state.samples = [];\n state.invalidationCounts = {};\n}\n\nfunction getEnabledState(): PerfProbeState | null {\n if (typeof window === \"undefined\") {\n return null;\n }\n const state = window.__DOCX_REACT_PERF_PROBE__;\n if (!state?.enabled) {\n return null;\n }\n return state;\n}\n\nfunction pushSample(state: PerfProbeState, sample: PerfProbeSample): void {\n state.samples ??= [];\n state.samples.push(sample);\n const maxSamples = state.maxSamples ?? 20;\n if (state.samples.length > maxSamples) {\n state.samples.splice(0, state.samples.length - maxSamples);\n }\n}\n\nfunction buildLatestSampleMap(\n samples: PerfProbeSample[],\n): Partial<Record<PerfProbeKind, PerfProbeSample | null>> {\n const latest: Partial<Record<PerfProbeKind, PerfProbeSample | null>> = {};\n for (const sample of [...samples].reverse()) {\n if (latest[sample.kind] === undefined) {\n latest[sample.kind] = sample;\n }\n }\n return latest;\n}\n","import type {\n DocumentNavigationSnapshot,\n PageLayoutSnapshot,\n SurfaceBlockSnapshot,\n} from \"../api/public-types.ts\";\n\nexport interface LineMarker {\n id: string;\n label: string;\n topPx: number;\n}\n\nexport function computeLineMarkersIfEnabled(input: {\n pageLayout: PageLayoutSnapshot | undefined;\n surfaceBlocks: readonly SurfaceBlockSnapshot[];\n pages: ReadonlyArray<DocumentNavigationSnapshot[\"pages\"][number]>;\n buildLineNumberMarkers: (\n blocks: readonly SurfaceBlockSnapshot[],\n pages: ReadonlyArray<DocumentNavigationSnapshot[\"pages\"][number]>,\n ) => LineMarker[];\n}): LineMarker[] {\n if (!input.pageLayout?.lineNumbering) {\n return [];\n }\n\n return input.buildLineNumberMarkers(input.surfaceBlocks, input.pages);\n}\n","import type { MouseEvent } from \"react\";\n\nexport function preserveEditorSelectionMouseDown(event: MouseEvent<HTMLElement>): void {\n event.preventDefault();\n}\n","import React from \"react\";\nimport { AlertTriangle, XCircle } from \"lucide-react\";\n\nimport type { RuntimeRenderSnapshot, WorkflowBlockedCommandReason } from \"../../api/public-types\";\n\nexport interface TwAlertBannerProps {\n snapshot: RuntimeRenderSnapshot;\n preserveOnlyCount: number;\n workflowBlockedReasons?: WorkflowBlockedCommandReason[];\n}\n\nexport function TwAlertBanner(props: TwAlertBannerProps) {\n const { snapshot, preserveOnlyCount, workflowBlockedReasons = [] } = props;\n\n if (snapshot.fatalError) {\n return (\n <div className=\"flex items-center gap-2 px-3 py-1.5 bg-danger-soft text-danger text-xs\">\n <XCircle className=\"h-3.5 w-3.5 shrink-0\" />\n <span>{snapshot.fatalError.message}</span>\n </div>\n );\n }\n\n if (snapshot.compatibility.blockExport) {\n return (\n <div className=\"flex items-center gap-2 px-3 py-1.5 bg-danger-soft text-danger text-xs\">\n <XCircle className=\"h-3.5 w-3.5 shrink-0\" />\n <span>\n Export blocked &mdash;{\" \"}\n {snapshot.compatibility.blockExportReasons[0] ?? \"unsupported content\"}\n </span>\n </div>\n );\n }\n\n if (preserveOnlyCount > 0) {\n return (\n <div className=\"flex items-center gap-2 px-3 py-1.5 bg-warning-soft text-comment text-xs\">\n <AlertTriangle className=\"h-3.5 w-3.5 shrink-0\" />\n <span>\n {preserveOnlyCount} preserve-only feature\n {preserveOnlyCount !== 1 ? \"s\" : \"\"} detected\n </span>\n </div>\n );\n }\n\n if (workflowBlockedReasons.length > 0) {\n const firstReason = workflowBlockedReasons[0];\n return (\n <div className=\"flex items-center gap-2 px-3 py-1.5 bg-amber-50 text-amber-700 text-xs\">\n <AlertTriangle className=\"h-3.5 w-3.5 shrink-0\" />\n <span>\n {firstReason.message}\n {workflowBlockedReasons.length > 1\n ? ` (+${workflowBlockedReasons.length - 1} more)`\n : \"\"}\n </span>\n </div>\n );\n }\n\n return null;\n}\n","import React from \"react\";\n\nimport { preserveEditorSelectionMouseDown } from \"../../ui/headless/preserve-editor-selection\";\n\nexport interface ActiveImageContext {\n mediaId: string;\n display: \"inline\" | \"floating\";\n widthEmu?: number;\n heightEmu?: number;\n horizontalOffsetEmu?: number;\n verticalOffsetEmu?: number;\n}\n\nexport interface TwImageContextToolbarProps {\n activeImage: ActiveImageContext;\n disabled: boolean;\n onSetImageLayout?: (\n mediaId: string,\n dimensions: { widthEmu: number; heightEmu: number },\n ) => void;\n onSetImageFrame?: (\n mediaId: string,\n offsets: { horizontalOffsetEmu?: number; verticalOffsetEmu?: number },\n ) => void;\n}\n\nconst IMAGE_SIZE_PRESETS = [\n { label: \"Small image\", widthEmu: 1828800, heightEmu: 914400 },\n { label: \"Medium image\", widthEmu: 2743200, heightEmu: 1371600 },\n { label: \"Large image\", widthEmu: 3657600, heightEmu: 1828800 },\n] as const;\n\nconst NUDGE_EMU = 228600;\n\nexport function TwImageContextToolbar(props: TwImageContextToolbarProps) {\n const { activeImage } = props;\n\n return (\n <div\n data-testid=\"image-context-toolbar\"\n className=\"flex flex-wrap items-center gap-2 rounded-xl border border-border bg-canvas px-3 py-2 shadow-sm\"\n >\n <span className=\"text-[10px] font-semibold uppercase tracking-[0.12em] text-tertiary\">\n Image\n </span>\n <span className=\"rounded-full bg-surface px-2 py-1 text-[10px] font-medium uppercase tracking-[0.1em] text-secondary\">\n {activeImage.display}\n </span>\n {IMAGE_SIZE_PRESETS.map((preset) => (\n <ToolbarButton\n key={preset.label}\n ariaLabel={preset.label}\n disabled={props.disabled || !props.onSetImageLayout}\n onClick={() =>\n props.onSetImageLayout?.(activeImage.mediaId, {\n widthEmu: preset.widthEmu,\n heightEmu: preset.heightEmu,\n })}\n >\n {preset.label.replace(\" image\", \"\")}\n </ToolbarButton>\n ))}\n {activeImage.display === \"floating\" ? (\n <>\n <ToolbarButton\n ariaLabel=\"Nudge image left\"\n disabled={props.disabled || !props.onSetImageFrame}\n onClick={() =>\n props.onSetImageFrame?.(activeImage.mediaId, {\n horizontalOffsetEmu: (activeImage.horizontalOffsetEmu ?? 0) - NUDGE_EMU,\n })}\n >\n Left\n </ToolbarButton>\n <ToolbarButton\n ariaLabel=\"Nudge image right\"\n disabled={props.disabled || !props.onSetImageFrame}\n onClick={() =>\n props.onSetImageFrame?.(activeImage.mediaId, {\n horizontalOffsetEmu: (activeImage.horizontalOffsetEmu ?? 0) + NUDGE_EMU,\n })}\n >\n Right\n </ToolbarButton>\n <ToolbarButton\n ariaLabel=\"Nudge image up\"\n disabled={props.disabled || !props.onSetImageFrame}\n onClick={() =>\n props.onSetImageFrame?.(activeImage.mediaId, {\n verticalOffsetEmu: (activeImage.verticalOffsetEmu ?? 0) - NUDGE_EMU,\n })}\n >\n Up\n </ToolbarButton>\n <ToolbarButton\n ariaLabel=\"Nudge image down\"\n disabled={props.disabled || !props.onSetImageFrame}\n onClick={() =>\n props.onSetImageFrame?.(activeImage.mediaId, {\n verticalOffsetEmu: (activeImage.verticalOffsetEmu ?? 0) + NUDGE_EMU,\n })}\n >\n Down\n </ToolbarButton>\n </>\n ) : null}\n </div>\n );\n}\n\nfunction ToolbarButton(props: {\n ariaLabel: string;\n children: React.ReactNode;\n disabled: boolean;\n onClick?: () => void;\n}) {\n return (\n <button\n type=\"button\"\n aria-label={props.ariaLabel}\n disabled={props.disabled}\n onMouseDown={preserveEditorSelectionMouseDown}\n onClick={props.onClick}\n className=\"inline-flex h-8 items-center rounded-md px-2 text-xs font-medium text-primary transition-colors hover:bg-surface disabled:cursor-not-allowed disabled:opacity-40\"\n >\n {props.children}\n </button>\n );\n}\n","import React from \"react\";\n\nimport type {\n PageLayoutSnapshot,\n SectionPageNumberingPatch,\n SectionBreakType,\n SectionLayoutPatch,\n} from \"../../api/public-types\";\nimport { preserveEditorSelectionMouseDown } from \"../../ui/headless/preserve-editor-selection\";\n\nexport interface TwLayoutPanelProps {\n pageLayout: PageLayoutSnapshot;\n readOnly: boolean;\n onInsertSectionBreak?: (type: SectionBreakType) => void;\n onDeleteSectionBreak?: (sectionIndex: number) => void;\n onUpdateSectionLayout?: (sectionIndex: number, patch: SectionLayoutPatch) => void;\n onSetSectionPageNumbering?: (\n sectionIndex: number,\n patch: SectionPageNumberingPatch | null,\n ) => void;\n}\n\nexport function TwLayoutPanel(props: TwLayoutPanelProps) {\n const nextOrientation = props.pageLayout.orientation === \"portrait\" ? \"landscape\" : \"portrait\";\n const titlePageEnabled = props.pageLayout.differentFirstPage;\n\n return (\n <div className=\"mt-3 flex flex-wrap items-center gap-2 rounded-xl border border-border bg-canvas px-3 py-2 shadow-sm\">\n <span className=\"text-[10px] font-semibold uppercase tracking-[0.12em] text-tertiary\">\n Section\n </span>\n <ToolbarButton\n ariaLabel=\"Insert next-page section break\"\n disabled={props.readOnly || !props.onInsertSectionBreak}\n onClick={() => props.onInsertSectionBreak?.(\"nextPage\")}\n >\n Next-page break\n </ToolbarButton>\n <ToolbarButton\n ariaLabel={`Switch section to ${nextOrientation}`}\n disabled={props.readOnly || !props.onUpdateSectionLayout}\n onClick={() =>\n props.onUpdateSectionLayout?.(props.pageLayout.sectionIndex, {\n pageSize: {\n orientation: nextOrientation,\n width: props.pageLayout.pageHeight,\n height: props.pageLayout.pageWidth,\n },\n })}\n >\n {nextOrientation === \"landscape\" ? \"Landscape\" : \"Portrait\"}\n </ToolbarButton>\n <ToolbarButton\n ariaLabel=\"Delete current section break\"\n disabled={props.readOnly || props.pageLayout.sectionIndex === 0 || !props.onDeleteSectionBreak}\n onClick={() => props.onDeleteSectionBreak?.(props.pageLayout.sectionIndex)}\n >\n Delete break\n </ToolbarButton>\n <ToolbarButton\n ariaLabel=\"Restart page numbering at 1\"\n disabled={props.readOnly || !props.onSetSectionPageNumbering}\n onClick={() =>\n props.onSetSectionPageNumbering?.(props.pageLayout.sectionIndex, {\n ...(props.pageLayout.pageNumbering ?? {}),\n start: 1,\n })}\n >\n Restart numbering\n </ToolbarButton>\n <ToolbarButton\n ariaLabel=\"Use roman page numbering\"\n disabled={props.readOnly || !props.onSetSectionPageNumbering}\n onClick={() =>\n props.onSetSectionPageNumbering?.(props.pageLayout.sectionIndex, {\n ...(props.pageLayout.pageNumbering ?? {}),\n format: \"roman\",\n })}\n >\n Roman numerals\n </ToolbarButton>\n <ToolbarButton\n ariaLabel=\"Toggle different first page\"\n disabled={props.readOnly || !props.onUpdateSectionLayout}\n onClick={() =>\n props.onUpdateSectionLayout?.(props.pageLayout.sectionIndex, {\n titlePage: !titlePageEnabled,\n })}\n >\n {titlePageEnabled ? \"Same first page\" : \"Different first page\"}\n </ToolbarButton>\n </div>\n );\n}\n\nfunction ToolbarButton(props: {\n ariaLabel: string;\n children: React.ReactNode;\n disabled: boolean;\n onClick?: () => void;\n}) {\n return (\n <button\n type=\"button\"\n aria-label={props.ariaLabel}\n disabled={props.disabled}\n onMouseDown={preserveEditorSelectionMouseDown}\n onClick={props.onClick}\n className=\"inline-flex h-8 items-center rounded-md px-2 text-xs font-medium text-primary transition-colors hover:bg-surface disabled:cursor-not-allowed disabled:opacity-40\"\n >\n {props.children}\n </button>\n );\n}\n","import React from \"react\";\n\nexport interface ActiveObjectContext {\n kind: \"textbox\" | \"shape\";\n display: \"inline\" | \"floating\";\n}\n\nexport interface TwObjectContextToolbarProps {\n activeObject: ActiveObjectContext;\n}\n\nexport function TwObjectContextToolbar(props: TwObjectContextToolbarProps) {\n const label = props.activeObject.kind === \"textbox\" ? \"Text box\" : \"Shape\";\n\n return (\n <div\n data-testid=\"object-context-toolbar\"\n className=\"flex flex-wrap items-center gap-2 rounded-xl border border-border bg-canvas px-3 py-2 shadow-sm\"\n >\n <span className=\"text-[10px] font-semibold uppercase tracking-[0.12em] text-tertiary\">\n Object\n </span>\n <span className=\"rounded-full bg-surface px-2 py-1 text-[10px] font-medium uppercase tracking-[0.1em] text-secondary\">\n {label}\n </span>\n <span className=\"rounded-full bg-surface px-2 py-1 text-[10px] font-medium uppercase tracking-[0.1em] text-secondary\">\n {props.activeObject.display}\n </span>\n <span className=\"text-xs text-secondary\">\n Object selection is active.\n </span>\n </div>\n );\n}\n","import React, { useEffect, useMemo, useRef, useState } from \"react\";\n\nimport type {\n EditorViewStateSnapshot,\n PageLayoutSnapshot,\n} from \"../../api/public-types\";\n\ninterface ActiveParagraphLayout {\n leftIndent: number;\n rightIndent: number;\n firstLineOffset: number;\n tabStops: Array<{ pos: number; val?: string; leader?: string }>;\n}\n\nexport interface TwPageRulerProps {\n pageLayout: PageLayoutSnapshot;\n viewState: EditorViewStateSnapshot;\n paragraphLayout: ActiveParagraphLayout | null;\n readOnly: boolean;\n onReturnToBody: () => void;\n onOpenHeader?: () => void;\n onOpenFooter?: () => void;\n onSetIndentation?: (indentation: {\n left?: number;\n right?: number;\n firstLine?: number;\n hanging?: number;\n }) => void;\n onSetTabStops?: (tabStops: Array<{ pos: number; val?: string; leader?: string }>) => void;\n onRestartNumbering?: () => void;\n onContinueNumbering?: () => void;\n}\n\ntype DragKind = \"left-indent\" | \"first-line\";\n\nconst MIN_HANDLE_TWIPS = 0;\nconst HANDLE_OVERLAP_THRESHOLD_PERCENT = 1.4;\nconst HANDLE_OFFSET_PERCENT = 0.9;\nconst MARKER_HALF_PX = 8;\n\nexport function TwPageRuler(props: TwPageRulerProps) {\n const trackRef = useRef<HTMLDivElement | null>(null);\n const dragCleanupRef = useRef<(() => void) | null>(null);\n const [, setDragState] = useState<{\n kind: DragKind;\n startClientX: number;\n startLeftIndent: number;\n startFirstLineOffset: number;\n } | null>(null);\n const [previewLayout, setPreviewLayout] = useState<ActiveParagraphLayout | null>(null);\n\n const effectiveLayout = previewLayout ?? props.paragraphLayout;\n const activeRegion = props.viewState.activePageRegion?.region ?? \"body\";\n const isBodyParagraphContext =\n activeRegion === \"body\" && Boolean(props.paragraphLayout);\n const availableHeader = props.pageLayout.headerVariants[0];\n const availableFooter = props.pageLayout.footerVariants[0];\n\n const usablePageWidth = Math.max(\n 1440,\n props.pageLayout.pageWidth - props.pageLayout.marginLeft - props.pageLayout.marginRight,\n );\n\n useEffect(() => {\n return () => {\n dragCleanupRef.current?.();\n };\n }, []);\n\n function beginDrag(kind: DragKind, clientX: number): void {\n if (!isBodyParagraphContext || !props.paragraphLayout || props.readOnly) {\n return;\n }\n\n dragCleanupRef.current?.();\n const activeDrag = {\n kind,\n startClientX: clientX,\n startLeftIndent: props.paragraphLayout.leftIndent,\n startFirstLineOffset: props.paragraphLayout.firstLineOffset,\n };\n setDragState(activeDrag);\n\n const handleMouseMove = (event: MouseEvent): void => {\n const track = trackRef.current;\n if (!track) {\n return;\n }\n const rect = track.getBoundingClientRect();\n const deltaPx = event.clientX - activeDrag.startClientX;\n const deltaTwips = pxToTwips(deltaPx, rect.width, usablePageWidth);\n\n if (activeDrag.kind === \"left-indent\") {\n setPreviewLayout({\n ...props.paragraphLayout!,\n leftIndent: clampTwips(activeDrag.startLeftIndent + deltaTwips),\n firstLineOffset: activeDrag.startFirstLineOffset,\n });\n return;\n }\n\n setPreviewLayout({\n ...props.paragraphLayout!,\n leftIndent: activeDrag.startLeftIndent,\n firstLineOffset: activeDrag.startFirstLineOffset + deltaTwips,\n });\n };\n\n const handleMouseUp = (event: MouseEvent): void => {\n const track = trackRef.current;\n if (!track || !props.onSetIndentation) {\n cleanupDrag();\n setDragState(null);\n setPreviewLayout(null);\n return;\n }\n\n const rect = track.getBoundingClientRect();\n const deltaPx = event.clientX - activeDrag.startClientX;\n const deltaTwips = pxToTwips(deltaPx, rect.width, usablePageWidth);\n const leftIndent =\n activeDrag.kind === \"left-indent\"\n ? clampTwips(activeDrag.startLeftIndent + deltaTwips)\n : activeDrag.startLeftIndent;\n const firstLineOffset =\n activeDrag.kind === \"first-line\"\n ? activeDrag.startFirstLineOffset + deltaTwips\n : activeDrag.startFirstLineOffset;\n\n cleanupDrag();\n props.onSetIndentation(\n composeIndentation(leftIndent, effectiveLayout?.rightIndent ?? props.paragraphLayout?.rightIndent ?? 0, firstLineOffset),\n );\n setDragState(null);\n setPreviewLayout(null);\n };\n\n const cleanupDrag = (): void => {\n window.removeEventListener(\"mousemove\", handleMouseMove);\n window.removeEventListener(\"mouseup\", handleMouseUp);\n if (dragCleanupRef.current === cleanupDrag) {\n dragCleanupRef.current = null;\n }\n };\n\n dragCleanupRef.current = cleanupDrag;\n window.addEventListener(\"mousemove\", handleMouseMove);\n window.addEventListener(\"mouseup\", handleMouseUp);\n }\n\n const markerLayout = useMemo(() => {\n if (!effectiveLayout || !isBodyParagraphContext) {\n return null;\n }\n return {\n leftIndent: twipsToPercent(effectiveLayout.leftIndent, usablePageWidth),\n firstLine: twipsToPercent(\n Math.max(MIN_HANDLE_TWIPS, effectiveLayout.leftIndent + effectiveLayout.firstLineOffset),\n usablePageWidth,\n ),\n tabStops: effectiveLayout.tabStops.map((tabStop, index) => ({\n id: `${tabStop.pos}-${index}`,\n left: twipsToPercent(tabStop.pos, usablePageWidth),\n })),\n };\n }, [effectiveLayout, isBodyParagraphContext, usablePageWidth]);\n const handlesOverlap = markerLayout\n ? Math.abs(markerLayout.leftIndent - markerLayout.firstLine) < HANDLE_OVERLAP_THRESHOLD_PERCENT\n : false;\n const leftIndentHandleLeft = markerLayout\n ? offsetHandlePercent(markerLayout.leftIndent, handlesOverlap ? -HANDLE_OFFSET_PERCENT : 0)\n : 0;\n const firstLineHandleLeft = markerLayout\n ? offsetHandlePercent(markerLayout.firstLine, handlesOverlap ? HANDLE_OFFSET_PERCENT : 0)\n : 0;\n\n return (\n <div\n aria-label=\"Page ruler\"\n className=\"mb-4 rounded-2xl border border-border bg-surface/80 px-4 py-3 shadow-sm\"\n >\n <div className=\"mb-3 flex flex-wrap items-center gap-2\">\n <button\n type=\"button\"\n aria-label=\"Return to document body\"\n title=\"Return to document body\"\n onClick={props.onReturnToBody}\n className={regionButtonClass(activeRegion === \"body\")}\n >\n Body\n </button>\n {availableHeader ? (\n <button\n type=\"button\"\n aria-label=\"Open header story\"\n title=\"Open header story\"\n onClick={props.onOpenHeader}\n className={regionButtonClass(activeRegion === \"header\")}\n >\n Header\n </button>\n ) : null}\n {availableFooter ? (\n <button\n type=\"button\"\n aria-label=\"Open footer story\"\n title=\"Open footer story\"\n onClick={props.onOpenFooter}\n className={regionButtonClass(activeRegion === \"footer\")}\n >\n Footer\n </button>\n ) : null}\n {props.viewState.activeListContext ? (\n <>\n <div className=\"h-4 w-px bg-border\" />\n <button\n type=\"button\"\n aria-label=\"Continue numbering\"\n title=\"Continue numbering from previous list\"\n disabled={props.readOnly}\n onClick={props.onContinueNumbering}\n className={controlButtonClass}\n >\n Continue\n </button>\n <button\n type=\"button\"\n aria-label=\"Restart numbering\"\n title=\"Restart numbering at 1\"\n disabled={props.readOnly}\n onClick={props.onRestartNumbering}\n className={controlButtonClass}\n >\n Restart\n </button>\n </>\n ) : null}\n </div>\n\n <div\n className=\"mb-2 flex items-center justify-between\"\n aria-label={`Section ${props.pageLayout.sectionIndex + 1}, ${props.pageLayout.orientation}`}\n title={`Section ${props.pageLayout.sectionIndex + 1} · ${props.pageLayout.orientation}`}\n >\n <span className=\"sr-only\">Page ruler</span>\n </div>\n\n <div\n ref={trackRef}\n aria-label=\"Page ruler track\"\n className=\"relative h-14 overflow-hidden rounded-xl border border-border bg-canvas\"\n onClick={(event) => {\n if (\n props.readOnly ||\n !isBodyParagraphContext ||\n !props.paragraphLayout ||\n !props.onSetTabStops\n ) {\n return;\n }\n if ((event.target as HTMLElement).dataset.handle === \"true\") {\n return;\n }\n const rect = event.currentTarget.getBoundingClientRect();\n const nextPos = clampTwips(pxToTwips(event.clientX - rect.left, rect.width, usablePageWidth));\n props.onSetTabStops(\n [...props.paragraphLayout.tabStops, { pos: nextPos, val: \"left\" }]\n .sort((left, right) => left.pos - right.pos),\n );\n }}\n >\n <div className=\"absolute inset-x-4 top-2 h-px bg-border\" />\n <div className=\"absolute inset-x-4 top-7 h-px bg-border/70\" />\n {Array.from({ length: 8 }, (_, index) => (\n <div\n key={`tick-${index}`}\n className=\"absolute top-1 h-3 w-px bg-border/80\"\n style={{ left: `${12 + index * 12}%` }}\n />\n ))}\n\n {markerLayout ? (\n <>\n <button\n type=\"button\"\n data-handle=\"true\"\n aria-label=\"Left indent handle\"\n title={`Left indent: ${effectiveLayout?.leftIndent ?? 0} twips`}\n disabled={props.readOnly}\n className={`absolute top-8 h-4 w-4 -translate-x-1/2 rounded-[5px] border border-accent/40 bg-accent-soft shadow-sm transition-opacity ${\n handlesOverlap ? \"opacity-80 z-10\" : \"\"\n }`}\n style={{ left: markerLeftStyle(leftIndentHandleLeft) }}\n onMouseDown={(event) => {\n event.preventDefault();\n beginDrag(\"left-indent\", event.clientX);\n }}\n />\n <button\n type=\"button\"\n data-handle=\"true\"\n aria-label=\"First line indent handle\"\n title={`First line offset: ${effectiveLayout?.firstLineOffset ?? 0} twips`}\n disabled={props.readOnly}\n className={`absolute top-1 h-4 w-4 -translate-x-1/2 rotate-45 rounded-[4px] border border-primary/30 bg-surface-raised shadow-sm transition-opacity ${\n handlesOverlap ? \"opacity-80 z-20\" : \"\"\n }`}\n style={{ left: markerLeftStyle(firstLineHandleLeft) }}\n onMouseDown={(event) => {\n event.preventDefault();\n beginDrag(\"first-line\", event.clientX);\n }}\n />\n {markerLayout.tabStops.map((tabStop) => (\n <div\n key={tabStop.id}\n data-handle=\"true\"\n aria-label={`Tab stop at ${tabStop.left.toFixed(0)}%`}\n title={`Tab stop`}\n className=\"absolute top-5 h-4 w-4 -translate-x-1/2 rounded-sm border border-border bg-surface-raised shadow-sm\"\n style={{ left: markerLeftStyle(tabStop.left) }}\n />\n ))}\n </>\n ) : null}\n </div>\n </div>\n );\n}\n\nfunction composeIndentation(leftIndent: number, rightIndent: number, firstLineOffset: number) {\n const indentation: {\n left?: number;\n right?: number;\n firstLine?: number;\n hanging?: number;\n } = {};\n if (leftIndent > 0) {\n indentation.left = leftIndent;\n }\n if (rightIndent > 0) {\n indentation.right = rightIndent;\n }\n if (firstLineOffset > 0) {\n indentation.firstLine = Math.round(firstLineOffset);\n } else if (firstLineOffset < 0) {\n indentation.hanging = Math.round(Math.abs(firstLineOffset));\n }\n return indentation;\n}\n\nfunction regionButtonClass(active: boolean): string {\n return `inline-flex items-center rounded-full border px-3 py-1 text-xs transition-colors ${\n active\n ? \"border-accent/30 bg-accent-soft text-accent\"\n : \"border-border bg-canvas text-secondary hover:bg-surface\"\n }`;\n}\n\nconst controlButtonClass =\n \"inline-flex items-center rounded-full border border-border bg-canvas px-3 py-1 text-xs text-secondary transition-colors hover:bg-surface disabled:cursor-not-allowed disabled:opacity-50\";\n\nfunction twipsToPercent(value: number, usablePageWidth: number): number {\n return Math.max(0, Math.min(100, (value / usablePageWidth) * 100));\n}\n\nfunction pxToTwips(px: number, width: number, usablePageWidth: number): number {\n if (width <= 0) {\n return 0;\n }\n return Math.round((px / width) * usablePageWidth);\n}\n\nfunction clampTwips(value: number): number {\n return Math.max(MIN_HANDLE_TWIPS, Math.round(value));\n}\n\nfunction offsetHandlePercent(value: number, offset: number): number {\n return Math.max(0, Math.min(100, value + offset));\n}\n\nfunction markerLeftStyle(value: number): string {\n const clamped = Math.max(0, Math.min(100, value));\n return `clamp(${MARKER_HALF_PX}px, ${clamped}%, calc(100% - ${MARKER_HALF_PX}px))`;\n}\n","import React, { forwardRef } from \"react\";\nimport type { FocusEventHandler } from \"react\";\nimport * as Tooltip from \"@radix-ui/react-tooltip\";\nimport { Baseline, Bold, Highlighter, Italic, MessageSquare, Underline } from \"lucide-react\";\n\nimport type { SelectionToolbarModel } from \"../../ui/headless/selection-toolbar-model\";\nimport { preserveEditorSelectionMouseDown } from \"../../ui/headless/preserve-editor-selection\";\n\nexport interface TwSelectionToolbarProps {\n model: SelectionToolbarModel;\n disabledReason?: string;\n onFocusCapture?: FocusEventHandler<HTMLDivElement>;\n onBlurCapture?: FocusEventHandler<HTMLDivElement>;\n onToggleBold?: () => void;\n onToggleItalic?: () => void;\n onToggleUnderline?: () => void;\n onSetTextColor?: (color: string) => void;\n onSetHighlightColor?: (color: string | null) => void;\n onAddComment?: () => void;\n}\n\nconst focusRingClass =\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-2 focus-visible:ring-offset-canvas\";\n\nexport const TwSelectionToolbar = forwardRef<HTMLDivElement, TwSelectionToolbarProps>(function TwSelectionToolbar(props, ref) {\n const { model } = props;\n const addCommentDisabled = !model.canAddComment;\n const formattingDisabled = !model.canToggleFormatting;\n const contextLabel = summarizeSelectionContext(model);\n const tooltipLabel = addCommentDisabled\n ? props.disabledReason ?? \"Select text within one paragraph to add a DOCX comment\"\n : \"Add comment\";\n\n return (\n <div\n ref={ref}\n data-testid=\"selection-toolbar\"\n className=\"inline-flex max-w-[min(24rem,calc(100vw-2rem))] items-center gap-1.5 rounded-xl border border-border/80 bg-canvas px-1.5 py-1.5 shadow-lg ring-1 ring-border/80\"\n role=\"toolbar\"\n aria-label=\"Selection actions\"\n onFocusCapture={props.onFocusCapture}\n onBlurCapture={props.onBlurCapture}\n >\n <ToolbarActionButton\n icon={<Bold className=\"h-3.5 w-3.5\" />}\n label=\"Bold selection\"\n pressed={model.boldActive}\n disabled={formattingDisabled}\n onClick={props.onToggleBold}\n />\n <ToolbarActionButton\n icon={<Italic className=\"h-3.5 w-3.5\" />}\n label=\"Italic selection\"\n pressed={model.italicActive}\n disabled={formattingDisabled}\n onClick={props.onToggleItalic}\n />\n <ToolbarActionButton\n icon={<Underline className=\"h-3.5 w-3.5\" />}\n label=\"Underline selection\"\n pressed={model.underlineActive}\n disabled={formattingDisabled}\n onClick={props.onToggleUnderline}\n />\n <ToolbarActionButton\n icon={<Baseline className=\"h-3.5 w-3.5\" />}\n label=\"Text color blue\"\n pressed={false}\n disabled={formattingDisabled}\n onClick={() => props.onSetTextColor?.(\"#1660a8\")}\n />\n <ToolbarActionButton\n icon={<Highlighter className=\"h-3.5 w-3.5\" />}\n label=\"Highlight yellow\"\n pressed={false}\n disabled={formattingDisabled}\n onClick={() => props.onSetHighlightColor?.(\"#ffff00\")}\n />\n\n <div className=\"mx-0.5 h-4 w-px bg-border\" />\n\n <Tooltip.Root>\n <Tooltip.Trigger asChild>\n <button\n type=\"button\"\n aria-label=\"Add comment from selection\"\n disabled={addCommentDisabled}\n onMouseDown={preserveEditorSelectionMouseDown}\n onClick={props.onAddComment}\n className={`inline-flex h-7 w-7 items-center justify-center rounded-md transition-colors text-accent hover:bg-accent-soft disabled:cursor-not-allowed disabled:opacity-30 ${focusRingClass}`}\n >\n <MessageSquare className=\"h-3.5 w-3.5\" />\n </button>\n </Tooltip.Trigger>\n <Tooltip.Portal>\n <Tooltip.Content\n className=\"rounded-md bg-primary px-2 py-1 text-xs text-white shadow-md z-50\"\n sideOffset={6}\n >\n {tooltipLabel}\n </Tooltip.Content>\n </Tooltip.Portal>\n </Tooltip.Root>\n\n {model.previewText ? (\n <>\n <div className=\"mx-0.5 h-4 w-px bg-border\" />\n <span className=\"max-w-[8rem] truncate text-[11px] text-secondary\">\n {model.previewText}\n </span>\n </>\n ) : null}\n\n {contextLabel ? (\n <>\n {!model.previewText ? <div className=\"mx-0.5 h-4 w-px bg-border\" /> : null}\n <span\n className={`min-w-0 max-w-[11rem] truncate rounded-full px-2 py-0.5 text-[10px] font-medium tracking-[0.08em] ${\n model.badges.some((badge) => badge.tone === \"accent\")\n ? \"bg-accent-soft text-accent\"\n : \"bg-surface text-tertiary\"\n }`}\n >\n {contextLabel}\n </span>\n </>\n ) : null}\n </div>\n );\n});\n\nfunction summarizeSelectionContext(model: SelectionToolbarModel): string | null {\n if (model.badges.length === 0) {\n return null;\n }\n\n const accentBadges = model.badges.filter((badge) => badge.tone === \"accent\");\n const source = accentBadges.length > 0 ? accentBadges : model.badges;\n const labels = source.slice(0, 2).map((badge) => badge.label.trim()).filter(Boolean);\n if (labels.length === 0) {\n return null;\n }\n\n const summary = labels.join(\" · \");\n return summary.length > 30 ? `${summary.slice(0, 27)}...` : summary;\n}\n\ninterface ToolbarActionButtonProps {\n icon: React.ReactNode;\n label: string;\n pressed: boolean;\n disabled: boolean;\n onClick?: () => void;\n}\n\nfunction ToolbarActionButton(props: ToolbarActionButtonProps) {\n return (\n <Tooltip.Root>\n <Tooltip.Trigger asChild>\n <button\n type=\"button\"\n aria-label={props.label}\n aria-pressed={props.pressed}\n disabled={props.disabled}\n onMouseDown={preserveEditorSelectionMouseDown}\n onClick={props.onClick}\n className={`inline-flex h-7 w-7 items-center justify-center rounded-md transition-colors disabled:cursor-not-allowed disabled:opacity-30 ${\n props.pressed\n ? \"bg-accent-soft text-accent\"\n : \"text-secondary hover:bg-surface\"\n } ${focusRingClass}`}\n >\n {props.icon}\n </button>\n </Tooltip.Trigger>\n <Tooltip.Portal>\n <Tooltip.Content\n className=\"rounded-md bg-primary px-2 py-1 text-xs text-white shadow-md z-50\"\n sideOffset={6}\n >\n {props.label}\n </Tooltip.Content>\n </Tooltip.Portal>\n </Tooltip.Root>\n );\n}\n","import React from \"react\";\nimport type { FocusEventHandler } from \"react\";\nimport * as Tooltip from \"@radix-ui/react-tooltip\";\nimport { Check, MessageSquare, Pencil, X } from \"lucide-react\";\n\nimport type { SuggestionCardModel } from \"../../ui/headless/selection-toolbar-model\";\nimport { preserveEditorSelectionMouseDown } from \"../../ui/headless/preserve-editor-selection\";\n\nexport interface TwSuggestionCardProps {\n model: SuggestionCardModel;\n onFocusCapture?: FocusEventHandler<HTMLDivElement>;\n onBlurCapture?: FocusEventHandler<HTMLDivElement>;\n onAccept?: () => void;\n onReject?: () => void;\n onEditSuggestion?: () => void;\n onAddComment?: () => void;\n}\n\nconst focusRingClass =\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-2 focus-visible:ring-offset-canvas\";\n\nexport function TwSuggestionCard(props: TwSuggestionCardProps) {\n const contextLabel = summarizeSuggestionContext(props.model);\n const commentDisabled = !props.model.canAddComment;\n const tooltipLabel = commentDisabled\n ? props.model.disabledReason ?? \"Commenting is unavailable for this selection\"\n : \"Comment on suggestion\";\n\n return (\n <div\n data-testid=\"suggestion-card\"\n className=\"inline-flex max-w-[min(28rem,calc(100vw-2rem))] flex-col gap-2 rounded-2xl border border-border/80 bg-canvas px-3 py-2 shadow-xl ring-1 ring-border/80\"\n onFocusCapture={props.onFocusCapture}\n onBlurCapture={props.onBlurCapture}\n role=\"group\"\n aria-label=\"Suggestion actions\"\n >\n <div className=\"flex items-start justify-between gap-3\">\n <div className=\"min-w-0\">\n <div className=\"text-[11px] font-semibold uppercase tracking-[0.12em] text-warning\">\n {props.model.kindLabel}\n </div>\n <div className=\"mt-1 max-w-[16rem] truncate text-sm text-primary\">\n {props.model.previewText}\n </div>\n </div>\n {contextLabel ? (\n <div className=\"shrink-0 rounded-full bg-accent-soft px-2 py-0.5 text-[10px] font-medium uppercase tracking-[0.08em] text-accent\">\n {contextLabel}\n </div>\n ) : null}\n </div>\n\n <div className=\"flex flex-wrap items-center gap-1.5\">\n <SuggestionActionButton\n icon={<Check className=\"h-3.5 w-3.5\" />}\n label=\"Accept suggestion\"\n disabled={!props.model.canAccept}\n tone=\"accept\"\n onClick={props.onAccept}\n />\n <SuggestionActionButton\n icon={<X className=\"h-3.5 w-3.5\" />}\n label=\"Reject suggestion\"\n disabled={!props.model.canReject}\n tone=\"reject\"\n onClick={props.onReject}\n />\n <SuggestionActionButton\n icon={<Pencil className=\"h-3.5 w-3.5\" />}\n label=\"Edit suggestion\"\n disabled={!props.model.canEditSuggestion}\n tone=\"neutral\"\n onClick={props.onEditSuggestion}\n />\n <Tooltip.Root>\n <Tooltip.Trigger asChild>\n <button\n type=\"button\"\n aria-label=\"Comment on suggestion\"\n disabled={commentDisabled}\n onMouseDown={preserveEditorSelectionMouseDown}\n onClick={props.onAddComment}\n className={`inline-flex h-8 items-center gap-1 rounded-lg border border-border px-2.5 text-xs font-medium text-secondary transition-colors hover:bg-surface disabled:cursor-not-allowed disabled:opacity-40 ${focusRingClass}`}\n >\n <MessageSquare className=\"h-3.5 w-3.5\" />\n Comment\n </button>\n </Tooltip.Trigger>\n <Tooltip.Portal>\n <Tooltip.Content\n className=\"rounded-md bg-primary px-2 py-1 text-xs text-white shadow-md z-50\"\n sideOffset={6}\n >\n {tooltipLabel}\n </Tooltip.Content>\n </Tooltip.Portal>\n </Tooltip.Root>\n </div>\n </div>\n );\n}\n\nfunction summarizeSuggestionContext(model: SuggestionCardModel): string | null {\n const labels = model.badges.map((badge) => badge.label.trim()).filter(Boolean);\n if (labels.length === 0) {\n return null;\n }\n const summary = labels.slice(0, 2).join(\" · \");\n return summary.length > 36 ? `${summary.slice(0, 33)}...` : summary;\n}\n\nfunction SuggestionActionButton(props: {\n icon: React.ReactNode;\n label: string;\n disabled: boolean;\n tone: \"accept\" | \"reject\" | \"neutral\";\n onClick?: () => void;\n}) {\n const toneClass = props.tone === \"accept\"\n ? \"border-emerald-500/30 bg-emerald-500/10 text-emerald-700 hover:bg-emerald-500/15 dark:text-emerald-300\"\n : props.tone === \"reject\"\n ? \"border-rose-500/30 bg-rose-500/10 text-rose-700 hover:bg-rose-500/15 dark:text-rose-300\"\n : \"border-border text-secondary hover:bg-surface\";\n\n return (\n <button\n type=\"button\"\n aria-label={props.label}\n disabled={props.disabled}\n onMouseDown={preserveEditorSelectionMouseDown}\n onClick={props.onClick}\n className={`inline-flex h-8 items-center gap-1 rounded-lg border px-2.5 text-xs font-medium transition-colors disabled:cursor-not-allowed disabled:opacity-40 ${toneClass} ${focusRingClass}`}\n >\n {props.icon}\n {props.label.replace(\" suggestion\", \"\").replace(\" on suggestion\", \"\")}\n </button>\n );\n}\n","import React from \"react\";\n\nimport type { StyleCatalogSnapshot } from \"../../api/public-types\";\nimport { preserveEditorSelectionMouseDown } from \"../../ui/headless/preserve-editor-selection\";\n\nexport interface TwTableContextToolbarProps {\n disabled: boolean;\n tableStyles: StyleCatalogSnapshot[\"tables\"];\n onSetTableStyle?: (styleId: string) => void;\n onAddRowBefore?: () => void;\n onAddRowAfter?: () => void;\n onAddColumnBefore?: () => void;\n onAddColumnAfter?: () => void;\n onDeleteRow?: () => void;\n onDeleteColumn?: () => void;\n onMergeCells?: () => void;\n onSplitCell?: () => void;\n onSetCellBackground?: (color: string) => void;\n onDeleteTable?: () => void;\n}\n\nconst CELL_COLORS = [\n \"#ffffff\",\n \"#f0f0ee\",\n \"#dbeafe\",\n \"#fef3c7\",\n \"#dcfce7\",\n \"#fce7f3\",\n] as const;\n\nexport function TwTableContextToolbar(props: TwTableContextToolbarProps) {\n return (\n <div\n data-testid=\"table-context-toolbar\"\n className=\"flex flex-wrap items-center gap-2 rounded-xl border border-border bg-canvas px-3 py-2 shadow-sm\"\n >\n <span className=\"text-[10px] font-semibold uppercase tracking-[0.12em] text-tertiary\">\n Table\n </span>\n\n <select\n aria-label=\"Table style\"\n className=\"h-8 rounded-md border border-border bg-canvas px-2 text-xs text-primary disabled:opacity-40\"\n disabled={props.disabled || props.tableStyles.length === 0 || !props.onSetTableStyle}\n onMouseDown={preserveEditorSelectionMouseDown}\n onChange={(event) => props.onSetTableStyle?.(event.target.value)}\n defaultValue=\"\"\n >\n <option value=\"\" disabled>Table style</option>\n {props.tableStyles.map((style) => (\n <option key={style.styleId} value={style.styleId}>\n {style.displayName}\n </option>\n ))}\n </select>\n\n <ToolbarButton ariaLabel=\"Add row above\" disabled={props.disabled} onClick={props.onAddRowBefore}>\n Row above\n </ToolbarButton>\n <ToolbarButton ariaLabel=\"Add row below\" disabled={props.disabled} onClick={props.onAddRowAfter}>\n Row below\n </ToolbarButton>\n <ToolbarButton ariaLabel=\"Delete row\" disabled={props.disabled} onClick={props.onDeleteRow}>\n Delete row\n </ToolbarButton>\n <ToolbarButton ariaLabel=\"Add column left\" disabled={props.disabled} onClick={props.onAddColumnBefore}>\n Column left\n </ToolbarButton>\n <ToolbarButton ariaLabel=\"Add column right\" disabled={props.disabled} onClick={props.onAddColumnAfter}>\n Column right\n </ToolbarButton>\n <ToolbarButton ariaLabel=\"Delete column\" disabled={props.disabled} onClick={props.onDeleteColumn}>\n Delete column\n </ToolbarButton>\n <ToolbarButton ariaLabel=\"Merge cells\" disabled={props.disabled} onClick={props.onMergeCells}>\n Merge\n </ToolbarButton>\n <ToolbarButton ariaLabel=\"Split cell\" disabled={props.disabled} onClick={props.onSplitCell}>\n Split\n </ToolbarButton>\n\n <div className=\"flex items-center gap-1\">\n <span className=\"text-[11px] text-secondary\">Fill</span>\n {CELL_COLORS.map((color) => (\n <button\n key={color}\n type=\"button\"\n aria-label={`Set cell fill ${color}`}\n disabled={props.disabled || !props.onSetCellBackground}\n onMouseDown={preserveEditorSelectionMouseDown}\n onClick={() => props.onSetCellBackground?.(color)}\n className=\"h-6 w-6 rounded border border-border disabled:opacity-40\"\n style={{ backgroundColor: color }}\n />\n ))}\n </div>\n\n <ToolbarButton ariaLabel=\"Delete table\" danger disabled={props.disabled} onClick={props.onDeleteTable}>\n Delete table\n </ToolbarButton>\n </div>\n );\n}\n\nfunction ToolbarButton(props: {\n ariaLabel: string;\n children: React.ReactNode;\n danger?: boolean;\n disabled: boolean;\n onClick?: () => void;\n}) {\n return (\n <button\n type=\"button\"\n aria-label={props.ariaLabel}\n disabled={props.disabled || !props.onClick}\n onMouseDown={preserveEditorSelectionMouseDown}\n onClick={props.onClick}\n className={`inline-flex h-8 items-center rounded-md px-2 text-xs font-medium transition-colors disabled:cursor-not-allowed disabled:opacity-40 ${\n props.danger\n ? \"text-danger hover:bg-danger/10\"\n : \"text-primary hover:bg-surface\"\n }`}\n >\n {props.children}\n </button>\n );\n}\n","import React from \"react\";\n\nimport * as Tabs from \"@radix-ui/react-tabs\";\nimport * as ScrollArea from \"@radix-ui/react-scroll-area\";\n\nimport type {\n CommentSidebarSnapshot,\n CommentSidebarThreadSnapshot,\n CompatibilityPanelSnapshot,\n EditorWarning,\n TrackedChangesSnapshot,\n TrackedChangeEntrySnapshot,\n} from \"../../api/public-types\";\nimport type { MarkupDisplay } from \"../../ui/headless/comment-decoration-model\";\nimport { TwCommentSidebar } from \"./tw-comment-sidebar\";\nimport { TwRevisionSidebar } from \"./tw-revision-sidebar\";\nimport { TwHealthPanel } from \"./tw-health-panel\";\n\nexport type ReviewRailTab = \"comments\" | \"changes\";\n\nexport interface TwReviewRailProps {\n activeTab: ReviewRailTab;\n currentUserId?: string;\n comments: CommentSidebarSnapshot;\n trackedChanges: TrackedChangesSnapshot;\n compatibility: CompatibilityPanelSnapshot;\n warnings: EditorWarning[];\n markupDisplay: MarkupDisplay;\n activeCommentId?: string;\n activeRevisionId?: string;\n onActiveTabChange: (tab: ReviewRailTab) => void;\n onOpenComment?: (thread: CommentSidebarThreadSnapshot) => void;\n onResolveComment?: (commentId: string) => void;\n onReopenComment?: (commentId: string) => void;\n onAddReply?: (commentId: string, body: string) => void;\n onEditBody?: (commentId: string, body: string) => void;\n onOpenRevision?: (revision: TrackedChangeEntrySnapshot) => void;\n onAcceptRevision?: (revisionId: string) => void;\n onRejectRevision?: (revisionId: string) => void;\n onAcceptAllChanges?: () => void;\n onRejectAllChanges?: () => void;\n}\n\nconst focusRingClass =\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-2 focus-visible:ring-offset-canvas\";\n\nexport function TwReviewRail(props: TwReviewRailProps) {\n const warningCount = props.compatibility.featureEntries.filter(\n (e) => e.featureClass !== \"supported-roundtrip\",\n ).length + props.warnings.length;\n\n return (\n <aside\n aria-label=\"Review rail\"\n className=\"flex w-[304px] shrink-0 flex-col border-l border-border bg-canvas\"\n >\n <Tabs.Root\n value={props.activeTab}\n onValueChange={(v: string) => props.onActiveTabChange(v as ReviewRailTab)}\n className=\"flex flex-1 flex-col min-h-0\"\n >\n <Tabs.List className=\"flex shrink-0 border-b border-border px-2\">\n <Tabs.Trigger\n value=\"comments\"\n className={`flex-1 py-2 text-xs text-tertiary font-medium transition-colors data-[state=active]:text-primary data-[state=active]:font-semibold data-[state=active]:shadow-[inset_0_-2px_0_var(--color-accent)] outline-none ${focusRingClass}`}\n >\n Comments{\" \"}\n <span className=\"ml-1 inline-flex min-w-[14px] items-center justify-center rounded-full bg-subtle px-1.5 py-px text-[10px] font-medium text-tertiary\">{props.comments.totalCount}</span>\n </Tabs.Trigger>\n <Tabs.Trigger\n value=\"changes\"\n className={`flex-1 py-2 text-xs text-tertiary font-medium transition-colors data-[state=active]:text-primary data-[state=active]:font-semibold data-[state=active]:shadow-[inset_0_-2px_0_var(--color-accent)] outline-none ${focusRingClass}`}\n >\n Changes{\" \"}\n <span className=\"ml-1 inline-flex min-w-[14px] items-center justify-center rounded-full bg-subtle px-1.5 py-px text-[10px] font-medium text-tertiary\">{props.trackedChanges.totalCount}</span>\n </Tabs.Trigger>\n {/* Health moved to toolbar popover */}\n </Tabs.List>\n\n <ScrollArea.Root className=\"flex-1 min-h-0\">\n <ScrollArea.Viewport className=\"h-full w-full\">\n <Tabs.Content value=\"comments\" className=\"p-2.5 outline-none\">\n <TwCommentSidebar\n currentUserId={props.currentUserId}\n comments={props.comments}\n activeCommentId={props.activeCommentId}\n onOpenComment={props.onOpenComment}\n onResolveComment={props.onResolveComment}\n onReopenComment={props.onReopenComment}\n onAddReply={props.onAddReply}\n onEditBody={props.onEditBody}\n />\n </Tabs.Content>\n\n <Tabs.Content value=\"changes\" className=\"p-2.5 outline-none\">\n <TwRevisionSidebar\n trackedChanges={props.trackedChanges}\n markupDisplay={props.markupDisplay}\n activeRevisionId={props.activeRevisionId}\n onOpenRevision={props.onOpenRevision}\n onAcceptRevision={props.onAcceptRevision}\n onRejectRevision={props.onRejectRevision}\n onAcceptAllChanges={props.onAcceptAllChanges}\n onRejectAllChanges={props.onRejectAllChanges}\n />\n </Tabs.Content>\n\n {/* Health panel moved to toolbar popover */}\n </ScrollArea.Viewport>\n <ScrollArea.Scrollbar\n orientation=\"vertical\"\n className=\"flex w-1.5 touch-none select-none p-0.5\"\n >\n <ScrollArea.Thumb className=\"relative flex-1 rounded-full bg-black/[0.12]\" />\n </ScrollArea.Scrollbar>\n </ScrollArea.Root>\n </Tabs.Root>\n </aside>\n );\n}\n","import React, { useCallback, useEffect, useRef, useState } from \"react\";\nimport { Check, CornerDownRight, RotateCcw } from \"lucide-react\";\n\nimport type { CommentSidebarSnapshot, CommentSidebarThreadSnapshot } from \"../../api/public-types\";\n\nexport interface TwCommentSidebarProps {\n comments: CommentSidebarSnapshot;\n activeCommentId?: string;\n currentUserId?: string;\n onOpenComment?: (thread: CommentSidebarThreadSnapshot) => void;\n onResolveComment?: (commentId: string) => void;\n onReopenComment?: (commentId: string) => void;\n onAddReply?: (commentId: string, body: string) => void;\n onEditBody?: (commentId: string, body: string) => void;\n}\n\nconst focusRingClass =\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-2 focus-visible:ring-offset-canvas\";\n\nexport function TwCommentSidebar(props: TwCommentSidebarProps) {\n const { comments, activeCommentId, currentUserId } = props;\n\n return (\n <div className=\"outline-none\">\n <div className=\"mb-2 flex items-center gap-2 text-[10px] text-tertiary\">\n <span>{comments.openCommentIds.length} open</span>\n <span className=\"text-border\">·</span>\n <span>{comments.resolvedCommentIds.length} resolved</span>\n {comments.detachedCommentIds.length > 0 && (\n <>\n <span className=\"text-border\">·</span>\n <span>{comments.detachedCommentIds.length} detached</span>\n </>\n )}\n </div>\n {comments.threads.length > 0 ? (\n <div className=\"space-y-1.5\">\n {comments.threads.map((thread) => (\n <CommentThreadCard\n key={thread.commentId}\n thread={thread}\n isActive={activeCommentId === thread.commentId}\n currentUserId={currentUserId}\n onOpenComment={props.onOpenComment}\n onResolveComment={props.onResolveComment}\n onReopenComment={props.onReopenComment}\n onAddReply={props.onAddReply}\n onEditBody={props.onEditBody}\n />\n ))}\n </div>\n ) : (\n <div className=\"rounded-lg border border-dashed border-border bg-surface/60 px-2.5 py-3 text-[10px] leading-4 text-tertiary\">\n No comment threads yet. Select text and add one from the toolbar.\n </div>\n )}\n </div>\n );\n}\n\nfunction CommentThreadCard(props: {\n thread: CommentSidebarThreadSnapshot;\n isActive: boolean;\n currentUserId?: string;\n onOpenComment?: (thread: CommentSidebarThreadSnapshot) => void;\n onResolveComment?: (commentId: string) => void;\n onReopenComment?: (commentId: string) => void;\n onAddReply?: (commentId: string, body: string) => void;\n onEditBody?: (commentId: string, body: string) => void;\n}) {\n const { thread, isActive } = props;\n const leadEntry = thread.entries[0];\n const isDraftThread = thread.status === \"open\" && thread.entryCount === 1 && isEmptyCommentBody(leadEntry?.body);\n const isOwnComment = props.currentUserId != null && leadEntry?.authorId === props.currentUserId;\n const canEdit = isOwnComment && thread.status === \"open\" && props.onEditBody != null;\n const hasNoBody = isEmptyCommentBody(leadEntry?.body);\n const showExcerpt = Boolean(thread.excerpt) && !isDraftThread && thread.excerpt !== \"Empty thread\";\n\n const scrollRef = useCallback(\n (node: HTMLDivElement | null) => {\n if (node && isActive && typeof node.scrollIntoView === \"function\") {\n node.scrollIntoView({ behavior: \"smooth\", block: \"nearest\" });\n }\n },\n [isActive],\n );\n\n return (\n <div\n ref={scrollRef}\n data-comment-thread-id={thread.commentId}\n data-comment-thread-status={thread.status}\n role=\"button\"\n tabIndex={0}\n className={[\n \"cursor-pointer rounded-lg border px-2 py-1.5 transition-colors\",\n focusRingClass,\n isActive\n ? \"border-accent/25 bg-accent-soft/35\"\n : \"border-border bg-canvas hover:border-border-strong hover:bg-surface/70\",\n thread.status === \"detached\" ? \"opacity-70\" : \"\",\n ].join(\" \")}\n onClick={() => props.onOpenComment?.(thread)}\n onKeyDown={(event) => {\n if (event.key === \"Enter\" || event.key === \" \") {\n event.preventDefault();\n props.onOpenComment?.(thread);\n }\n }}\n >\n {/* Header row: avatar + author + date + status */}\n <div className=\"mb-1 flex items-center gap-1.5\">\n <span className=\"inline-flex h-4 w-4 shrink-0 items-center justify-center rounded-full bg-accent/10 text-[8px] font-semibold text-accent\">\n {thread.createdBy.charAt(0).toUpperCase()}\n </span>\n <span className=\"truncate text-[10px] font-medium text-primary\">{thread.createdBy}</span>\n <span data-comment-thread-created-at=\"true\" className=\"text-[9px] text-tertiary\">\n {formatCommentDate(thread.createdAt)}\n </span>\n <span className=\"flex-1\" />\n {isDraftThread ? <StatusBadge label=\"draft\" tone=\"draft\" /> : null}\n {thread.status === \"resolved\" ? <StatusBadge label=\"resolved\" tone=\"resolved\" /> : null}\n {thread.status === \"detached\" ? <StatusBadge label=\"detached\" tone=\"detached\" /> : null}\n </div>\n\n {/* Excerpt — anchored text from document */}\n {showExcerpt ? (\n <p className=\"mb-1 rounded-md border-l-2 border-comment/25 bg-comment-soft/30 px-2 py-1 text-[9px] leading-4 text-comment/80 italic whitespace-pre-wrap break-words line-clamp-2\">\n {thread.excerpt}\n </p>\n ) : null}\n\n {/* Comment body */}\n {canEdit && (isActive || hasNoBody) ? (\n <InlineEditableBody\n body={leadEntry?.body ?? \"\"}\n autoFocus={isActive && hasNoBody}\n onSave={(newBody) => props.onEditBody?.(thread.commentId, newBody)}\n label={isDraftThread ? \"New comment\" : undefined}\n />\n ) : leadEntry?.body ? (\n <p\n className=\"text-[10px] leading-[1.1rem] text-secondary whitespace-pre-wrap break-words line-clamp-4\"\n data-comment-thread-body=\"true\"\n >\n {leadEntry.body}\n </p>\n ) : canEdit ? (\n <p\n className=\"cursor-text text-[10px] italic text-tertiary\"\n onClick={(e) => {\n e.stopPropagation();\n props.onOpenComment?.(thread);\n }}\n >\n New comment\n </p>\n ) : null}\n\n {/* Reply entries (compact) */}\n {thread.entries.slice(1).map((entry) => (\n <div key={entry.entryId} className=\"mt-1.5 ml-4 border-l border-border/50 pl-2.5\">\n <div className=\"mb-0.5 flex items-center gap-1\">\n <span className=\"text-[9px] font-medium text-secondary\">{entry.authorId}</span>\n <span className=\"text-[9px] text-tertiary\">{formatCommentDate(entry.createdAt)}</span>\n </div>\n <p\n className=\"text-[10px] leading-4 text-secondary whitespace-pre-wrap break-words line-clamp-3\"\n data-comment-reply-body=\"true\"\n >\n {entry.body}\n </p>\n </div>\n ))}\n\n {thread.entryCount > thread.entries.length ? (\n <p className=\"mt-1 text-[9px] text-tertiary\">\n +{thread.entryCount - thread.entries.length} more\n </p>\n ) : null}\n\n {/* Inline actions — compact, horizontal */}\n <div className=\"mt-1 flex items-center gap-0.5\">\n {thread.status === \"open\" && (\n <>\n <button\n type=\"button\"\n className=\"inline-flex items-center gap-0.5 rounded px-1 py-0.5 text-[9px] font-medium text-insert hover:bg-insert-soft transition-colors\"\n onClick={(e) => { e.stopPropagation(); props.onResolveComment?.(thread.commentId); }}\n >\n <Check className=\"h-2 w-2\" /> Resolve\n </button>\n {props.onAddReply && (\n <ReplyInput commentId={thread.commentId} onAddReply={props.onAddReply} />\n )}\n </>\n )}\n {thread.status === \"resolved\" && (\n <button\n type=\"button\"\n className=\"inline-flex items-center gap-0.5 rounded px-1 py-0.5 text-[9px] font-medium text-secondary hover:bg-surface transition-colors\"\n data-comment-thread-action=\"reopen\"\n onClick={(e) => { e.stopPropagation(); props.onReopenComment?.(thread.commentId); }}\n >\n <RotateCcw className=\"h-2 w-2\" /> Reopen\n </button>\n )}\n {thread.status === \"detached\" && (\n <span className=\"text-[9px] text-comment\">Detached</span>\n )}\n </div>\n </div>\n );\n}\n\nfunction InlineEditableBody(props: {\n body: string;\n autoFocus?: boolean;\n label?: string;\n onSave: (newBody: string) => void;\n}) {\n const [isEditing, setIsEditing] = useState(props.autoFocus || props.body === \"\");\n const [draft, setDraft] = useState(props.body);\n const textareaRef = useRef<HTMLTextAreaElement>(null);\n\n useEffect(() => {\n if (isEditing && textareaRef.current) {\n textareaRef.current.focus();\n textareaRef.current.setSelectionRange(draft.length, draft.length);\n }\n }, [isEditing]);\n\n if (!isEditing) {\n return (\n <p\n className={`cursor-text rounded px-1 text-[10px] leading-[1.15rem] -mx-1 transition-colors hover:bg-surface ${props.body ? \"text-secondary\" : \"text-tertiary italic\"}`}\n onClick={(e) => {\n e.stopPropagation();\n setDraft(props.body);\n setIsEditing(true);\n }}\n title=\"Click to edit\"\n >\n {props.body || \"Click to add comment\\u2026\"}\n </p>\n );\n }\n\n return (\n <div className=\"space-y-1\">\n {props.label ? (\n <span className=\"block text-[10px] font-medium uppercase tracking-[0.08em] text-tertiary\">\n {props.label}\n </span>\n ) : null}\n <textarea\n ref={textareaRef}\n className=\"w-full resize-none rounded-md border border-border bg-surface px-2 py-1.5 text-[10px] leading-4 text-primary placeholder:text-tertiary focus:outline-none focus:ring-1 focus:ring-accent\"\n rows={2}\n value={draft}\n placeholder=\"Type your comment...\"\n onClick={(e) => e.stopPropagation()}\n onChange={(e) => setDraft(e.target.value)}\n onBlur={() => {\n if (draft.trim() && draft.trim() !== props.body) {\n props.onSave(draft.trim());\n }\n setIsEditing(false);\n }}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" && !e.shiftKey) {\n e.preventDefault();\n if (draft.trim() && draft.trim() !== props.body) {\n props.onSave(draft.trim());\n }\n setIsEditing(false);\n }\n if (e.key === \"Escape\") {\n setDraft(props.body);\n setIsEditing(false);\n }\n e.stopPropagation();\n }}\n />\n </div>\n );\n}\n\nfunction ReplyInput(props: { commentId: string; onAddReply: (commentId: string, body: string) => void }) {\n const [body, setBody] = useState(\"\");\n const [isOpen, setIsOpen] = useState(false);\n const inputRef = useRef<HTMLTextAreaElement>(null);\n\n useEffect(() => {\n if (isOpen && inputRef.current) {\n inputRef.current.focus();\n }\n }, [isOpen]);\n\n if (!isOpen) {\n return (\n <button\n type=\"button\"\n className=\"inline-flex items-center gap-0.5 rounded px-1.5 py-0.5 text-[10px] font-medium text-tertiary hover:text-secondary hover:bg-surface transition-colors\"\n onClick={(e) => {\n e.stopPropagation();\n setIsOpen(true);\n }}\n >\n <CornerDownRight className=\"h-2.5 w-2.5\" /> Reply\n </button>\n );\n }\n\n return (\n <div className=\"w-full mt-1.5\" onClick={(e) => e.stopPropagation()}>\n <textarea\n ref={inputRef}\n className=\"w-full rounded border border-border bg-surface px-2 py-1 text-[11px] text-primary placeholder:text-tertiary resize-none focus:outline-none focus:ring-1 focus:ring-accent\"\n rows={2}\n placeholder=\"Reply...\"\n value={body}\n onChange={(e) => setBody(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" && !e.shiftKey && body.trim()) {\n e.preventDefault();\n props.onAddReply(props.commentId, body.trim());\n setBody(\"\");\n setIsOpen(false);\n }\n if (e.key === \"Escape\") {\n setBody(\"\");\n setIsOpen(false);\n }\n e.stopPropagation();\n }}\n />\n <div className=\"flex gap-1 mt-0.5\">\n <button\n type=\"button\"\n disabled={!body.trim()}\n className=\"rounded px-1.5 py-0.5 text-[10px] font-medium text-accent hover:bg-accent-soft transition-colors disabled:opacity-40\"\n onClick={() => {\n if (body.trim()) {\n props.onAddReply(props.commentId, body.trim());\n setBody(\"\");\n setIsOpen(false);\n }\n }}\n >\n Send\n </button>\n <button\n type=\"button\"\n className=\"rounded px-1.5 py-0.5 text-[10px] text-tertiary hover:bg-surface transition-colors\"\n onClick={() => { setBody(\"\"); setIsOpen(false); }}\n >\n Cancel\n </button>\n </div>\n </div>\n );\n}\n\nfunction formatCommentDate(raw: string): string {\n try {\n const date = new Date(raw);\n if (Number.isNaN(date.getTime())) return raw;\n const now = new Date();\n const diffMs = now.getTime() - date.getTime();\n const diffMin = Math.floor(diffMs / 60000);\n if (diffMin < 1) return \"just now\";\n if (diffMin < 60) return `${diffMin}m ago`;\n const diffHours = Math.floor(diffMin / 60);\n if (diffHours < 24) return `${diffHours}h ago`;\n const diffDays = Math.floor(diffHours / 24);\n if (diffDays < 7) return `${diffDays}d ago`;\n return new Intl.DateTimeFormat(\"en-US\", {\n month: \"short\",\n day: \"numeric\",\n year: date.getFullYear() !== now.getFullYear() ? \"numeric\" : undefined,\n }).format(date);\n } catch {\n return raw;\n }\n}\n\nfunction StatusBadge(props: { label: string; tone: \"resolved\" | \"detached\" | \"draft\" }) {\n const styles: Record<string, string> = {\n resolved: \"text-insert bg-insert-soft\",\n detached: \"text-comment bg-warning-soft\",\n draft: \"text-secondary bg-subtle\",\n };\n return (\n <span\n className={`shrink-0 rounded px-1 py-px text-[8px] font-medium uppercase tracking-[0.08em] ${styles[props.tone] ?? \"text-secondary bg-subtle\"}`}\n data-comment-thread-badge={props.tone}\n >\n {props.label}\n </span>\n );\n}\n\nfunction isEmptyCommentBody(body: string | undefined): boolean {\n return !body || body.trim() === \"\";\n}\n","import React from \"react\";\nimport { Check, X } from \"lucide-react\";\n\nimport type { TrackedChangesSnapshot, TrackedChangeEntrySnapshot } from \"../../api/public-types\";\nimport { selectVisibleRevisions } from \"../../ui/shared/revision-filters\";\nimport type { MarkupDisplay } from \"../../ui/headless/comment-decoration-model\";\n\nexport interface TwRevisionSidebarProps {\n trackedChanges: TrackedChangesSnapshot;\n markupDisplay: MarkupDisplay;\n activeRevisionId?: string;\n onOpenRevision?: (revision: TrackedChangeEntrySnapshot) => void;\n onAcceptRevision?: (revisionId: string) => void;\n onRejectRevision?: (revisionId: string) => void;\n onAcceptAllChanges?: () => void;\n onRejectAllChanges?: () => void;\n}\n\nconst focusRingClass =\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-2 focus-visible:ring-offset-canvas\";\n\nexport function TwRevisionSidebar(props: TwRevisionSidebarProps) {\n const { trackedChanges, markupDisplay, activeRevisionId } = props;\n const visibleRevisions = selectVisibleRevisions(trackedChanges.revisions, markupDisplay);\n const actionablePendingCount = trackedChanges.revisions.filter(\n (r) => r.status === \"active\" && r.actionability === \"actionable\",\n ).length;\n\n return (\n <div className=\"outline-none\">\n <p className=\"mb-2 text-[10px] text-tertiary\">\n {trackedChanges.pendingChangeIds.length} active · {trackedChanges.acceptedChangeIds.length} accepted · {trackedChanges.preserveOnlyChangeIds.length} preserve-only\n </p>\n\n {/* Bulk actions */}\n <div className=\"mb-2 flex gap-1\">\n <button\n type=\"button\"\n disabled={actionablePendingCount === 0}\n className=\"inline-flex items-center gap-1 rounded-md px-2 py-1 text-[10px] font-semibold text-accent hover:bg-accent-soft transition-colors disabled:opacity-30 disabled:cursor-not-allowed\"\n onClick={props.onAcceptAllChanges}\n >\n Accept all ({actionablePendingCount})\n </button>\n <button\n type=\"button\"\n disabled={actionablePendingCount === 0}\n className=\"inline-flex items-center gap-1 rounded-md px-2 py-1 text-[10px] text-secondary hover:bg-surface transition-colors disabled:opacity-30 disabled:cursor-not-allowed\"\n onClick={props.onRejectAllChanges}\n >\n Reject all\n </button>\n </div>\n\n {visibleRevisions.length > 0 ? (\n <div className=\"space-y-1\">\n {visibleRevisions.map((rev) => {\n const isActive = activeRevisionId === rev.revisionId;\n\n return (\n <div\n key={rev.revisionId}\n role=\"button\"\n tabIndex={0}\n className={`flex rounded-lg transition-colors cursor-pointer ${focusRingClass} ${isActive ? \"bg-accent-soft\" : \"hover:bg-surface\"}`}\n onClick={() => props.onOpenRevision?.(rev)}\n onKeyDown={(event) => {\n if (event.key === \"Enter\" || event.key === \" \") {\n event.preventDefault();\n props.onOpenRevision?.(rev);\n }\n }}\n >\n <div className={`w-0.5 shrink-0 rounded-l-lg ${\n rev.kind === \"insertion\" ? \"bg-insert\"\n : rev.kind === \"deletion\" ? \"bg-danger\"\n : \"bg-tertiary\"\n }`} />\n <div className=\"p-2 flex-1 min-w-0\">\n <div className=\"mb-0.5 flex items-start justify-between gap-2\">\n <span className=\"text-[11px] font-medium text-primary\">{rev.anchorLabel}</span>\n <RevisionBadge status={rev.status} actionability={rev.actionability} />\n </div>\n <p className=\"mb-1 text-[10px] text-tertiary\">{rev.authorId} · {rev.createdAt}</p>\n {rev.excerpt ? (\n <p className={`text-[11px] ${\n rev.kind === \"insertion\" ? \"text-insert\"\n : rev.kind === \"deletion\" ? \"text-danger line-through\"\n : \"text-secondary\"\n }`}>\n {rev.excerpt}\n </p>\n ) : (\n <p className=\"text-[11px] text-secondary\">{rev.label}</p>\n )}\n {rev.detail ? (\n <p className=\"mt-1 text-[10px] text-secondary\">{rev.detail}</p>\n ) : null}\n <div className=\"mt-1.5 flex gap-1\">\n {rev.actionability === \"actionable\" ? (\n <>\n <button\n type=\"button\"\n disabled={!rev.canAccept || rev.status === \"accepted\"}\n className=\"inline-flex items-center gap-1 rounded-md px-1.5 py-0.5 text-[10px] text-insert hover:bg-insert-soft transition-colors disabled:opacity-30 disabled:cursor-not-allowed\"\n onClick={(e) => {\n e.stopPropagation();\n props.onAcceptRevision?.(rev.revisionId);\n }}\n >\n <Check className=\"h-3 w-3\" /> Accept\n </button>\n <button\n type=\"button\"\n disabled={!rev.canReject || rev.status === \"rejected\"}\n className=\"inline-flex items-center gap-1 rounded-md px-1.5 py-0.5 text-[10px] text-danger hover:bg-delete-soft transition-colors disabled:opacity-30 disabled:cursor-not-allowed\"\n onClick={(e) => {\n e.stopPropagation();\n props.onRejectRevision?.(rev.revisionId);\n }}\n >\n <X className=\"h-3 w-3\" /> Reject\n </button>\n </>\n ) : (\n <span className=\"px-1.5 py-0.5 text-[10px] text-tertiary\">Preserve-only</span>\n )}\n </div>\n </div>\n </div>\n );\n })}\n </div>\n ) : (\n <p className=\"text-xs text-tertiary py-4\">\n {trackedChanges.totalCount > 0\n ? \"Switch to Full markup to see all tracked changes.\"\n : \"Tracked change cards will appear here when present.\"}\n </p>\n )}\n </div>\n );\n}\n\nfunction RevisionBadge(props: { status: string; actionability: string }) {\n if (props.actionability === \"preserve-only\") {\n return (\n <span className=\"inline-flex items-center rounded px-1.5 py-0.5 text-[10px] font-medium text-comment bg-warning-soft\">\n preserve-only\n </span>\n );\n }\n const styles: Record<string, string> = {\n active: \"text-secondary bg-subtle\",\n accepted: \"text-insert bg-insert-soft\",\n rejected: \"text-danger bg-delete-soft\",\n detached: \"text-comment bg-warning-soft\",\n };\n return (\n <span className={`inline-flex items-center rounded px-1.5 py-0.5 text-[10px] font-medium ${styles[props.status] ?? \"text-secondary bg-subtle\"}`}>\n {props.status}\n </span>\n );\n}\n","import type { RuntimeRenderSnapshot } from \"../../api/public-types\";\n\ntype Revision = RuntimeRenderSnapshot[\"trackedChanges\"][\"revisions\"][number];\ntype MarkupDisplay = \"clean\" | \"simple\" | \"all\";\n\nexport function selectVisibleRevisions(\n revisions: readonly Revision[],\n markupDisplay: MarkupDisplay,\n): Revision[] {\n switch (markupDisplay) {\n case \"clean\":\n case \"simple\":\n return revisions.filter(\n (revision) =>\n revision.status === \"active\" && revision.actionability === \"actionable\",\n );\n case \"all\":\n return [...revisions];\n }\n}\n\nexport function describeEmptyRevisionState(\n markupDisplay: MarkupDisplay,\n totalCount: number,\n): string {\n if ((markupDisplay === \"clean\" || markupDisplay === \"simple\") && totalCount > 0) {\n return \"Simple markup keeps the rail focused on actionable live changes. Switch to All to inspect preserve-only or historical revision records.\";\n }\n\n return \"Runtime-backed change cards will appear here when tracked changes are present.\";\n}\n","import React from \"react\";\n\nexport interface TwStatusBarProps {\n isDirty: boolean;\n isExportBlocked: boolean;\n preserveOnlyCount: number;\n commentCount: number;\n changeCount: number;\n sessionId: string;\n}\n\nexport function TwStatusBar(props: TwStatusBarProps) {\n const saveState = props.isExportBlocked\n ? \"Read-only\"\n : props.isDirty\n ? \"Unsaved\"\n : \"Ready\";\n const exportState = props.isExportBlocked\n ? \"Blocked\"\n : props.preserveOnlyCount > 0\n ? \"Warnings\"\n : \"Ready\";\n\n return (\n <footer\n data-testid=\"status-bar\"\n className=\"flex h-7 shrink-0 items-center gap-4 border-t border-border px-3 text-xs text-tertiary\"\n >\n <span className=\"flex items-center gap-1.5\">\n <span\n className={`inline-block h-1.5 w-1.5 rounded-full ${\n props.isExportBlocked\n ? \"bg-danger\"\n : props.isDirty\n ? \"bg-comment\"\n : \"bg-insert\"\n }`}\n />\n {saveState}\n </span>\n <span className=\"flex items-center gap-1.5\">\n <span\n className={`inline-block h-1.5 w-1.5 rounded-full ${\n props.isExportBlocked\n ? \"bg-danger\"\n : props.preserveOnlyCount > 0\n ? \"bg-comment\"\n : \"bg-insert\"\n }`}\n />\n Export {exportState.toLowerCase()}\n </span>\n <span>\n {props.commentCount} comment{props.commentCount !== 1 ? \"s\" : \"\"} ·{\" \"}\n {props.changeCount} change{props.changeCount !== 1 ? \"s\" : \"\"}\n </span>\n <span className=\"flex-1\" />\n <span>{props.sessionId}</span>\n </footer>\n );\n}\n","import React from \"react\";\n\nimport * as Popover from \"@radix-ui/react-popover\";\nimport * as Select from \"@radix-ui/react-select\";\nimport * as Toggle from \"@radix-ui/react-toggle\";\nimport * as ToggleGroup from \"@radix-ui/react-toggle-group\";\nimport * as Tooltip from \"@radix-ui/react-tooltip\";\nimport {\n AlignCenter,\n AlignJustify,\n AlignLeft,\n AlignRight,\n Baseline,\n Bold,\n ChevronDown,\n Download,\n Eye,\n EyeOff,\n FileText,\n Highlighter,\n ImagePlus,\n Indent,\n Italic,\n MessageSquare,\n Minus,\n Monitor,\n MoreHorizontal,\n Outdent,\n Plus,\n Redo2,\n Rows3,\n Strikethrough,\n Subscript,\n Superscript,\n ShieldAlert,\n ShieldCheck,\n Underline,\n Undo2,\n} from \"lucide-react\";\n\nimport type {\n CompatibilityPanelSnapshot,\n EditorStoryTarget,\n EditorWarning,\n FormattingStateSnapshot,\n FormattingAlignment,\n InsertImageOptions,\n SectionBreakType,\n StyleCatalogSnapshot,\n WorkflowBlockedCommandReason,\n WorkspaceMode,\n ZoomLevel,\n} from \"../../api/public-types\";\nimport type { SessionCapabilities } from \"../../runtime/session-capabilities\";\nimport { preserveEditorSelectionMouseDown } from \"../../ui/headless/preserve-editor-selection\";\nimport { TwHealthPanel } from \"../review/tw-health-panel\";\nimport { TwToolbarIconButton } from \"./tw-toolbar-icon-button\";\n\nexport interface TwToolbarProps {\n sourceLabel?: string;\n capabilities?: SessionCapabilities;\n compatibility?: CompatibilityPanelSnapshot;\n warnings?: EditorWarning[];\n blockedReasons?: WorkflowBlockedCommandReason[];\n interactionPolicy?: ToolbarInteractionPolicy;\n workspaceMode: WorkspaceMode;\n zoomLevel?: ZoomLevel;\n formattingState?: FormattingStateSnapshot;\n styleCatalog?: StyleCatalogSnapshot;\n /** Display toggle for tracked change decorations (not a runtime mutation toggle). */\n showTrackedChanges: boolean;\n /** Active story target — shows a breadcrumb when editing a secondary story. */\n activeStory?: EditorStoryTarget;\n /** Called when the user clicks the story breadcrumb to return to main body. */\n onCloseStory?: () => void;\n onUndo: () => void;\n onRedo: () => void;\n onSetParagraphStyle?: (styleId: string) => void;\n onToggleBold?: () => void;\n onToggleItalic?: () => void;\n onToggleUnderline?: () => void;\n onToggleStrikethrough?: () => void;\n onToggleSuperscript?: () => void;\n onToggleSubscript?: () => void;\n onSetFontFamily?: (fontFamily: string) => void;\n onSetFontSize?: (fontSize: number) => void;\n onSetTextColor?: (color: string) => void;\n onSetHighlightColor?: (color: string | null) => void;\n onSetAlignment?: (alignment: FormattingAlignment) => void;\n onOutdent?: () => void;\n onIndent?: () => void;\n onAddComment: () => void;\n onInsertPageBreak?: () => void;\n onInsertTable?: () => void;\n onInsertSectionBreak?: (type: SectionBreakType) => void;\n onInsertImage?: (options: InsertImageOptions) => void;\n onExport: () => void;\n onWorkspaceModeChange: (value: WorkspaceMode) => void;\n onZoomChange?: (level: ZoomLevel) => void;\n onShowTrackedChangesChange: (show: boolean) => void;\n}\n\nexport interface ToolbarInteractionPolicy {\n mode: \"edit\" | \"suggest\" | \"comment\" | \"view\" | \"blocked\";\n canFormatText: boolean;\n canInsertStructural: boolean;\n canAddComment: boolean;\n}\n\nexport function getSupportedZoomPresets(): ReadonlyArray<number> {\n return [75, 100, 125, 150];\n}\n\nconst focusRingClass =\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-2 focus-visible:ring-offset-canvas\";\n\nconst FONT_FAMILIES = [\"Arial\", \"Times New Roman\", \"Calibri\", \"Cambria\", \"Georgia\", \"Verdana\"];\nconst FONT_SIZES = [8, 9, 10, 11, 12, 14, 16, 18, 20, 24, 28, 36];\nconst TEXT_COLORS = [\"#000000\", \"#434343\", \"#1660a8\", \"#1a7f37\", \"#cf222e\", \"#7a4f00\"];\nconst HIGHLIGHT_COLORS = [\n { value: \"#ffff00\", label: \"Yellow\" },\n { value: \"#00ff00\", label: \"Green\" },\n { value: \"#00ffff\", label: \"Cyan\" },\n { value: \"#ff69b4\", label: \"Pink\" },\n { value: null, label: \"None\" },\n] as const;\n\nexport function TwToolbar(props: TwToolbarProps) {\n const caps = props.capabilities;\n const workspaceMode = props.workspaceMode;\n const isPageMode = workspaceMode === \"page\";\n const paragraphStyles = props.styleCatalog?.paragraphs ?? [];\n const zoomLevel = props.zoomLevel ?? 100;\n const canEdit = props.interactionPolicy?.canFormatText ?? (caps ? caps.canEdit : false);\n const canInsertStructural = props.interactionPolicy?.canInsertStructural ?? canEdit;\n const canAddComment = props.interactionPolicy?.canAddComment ?? (caps ? caps.canAddComment : false);\n const zoomLabel =\n typeof zoomLevel === \"number\"\n ? `${zoomLevel}%`\n : zoomLevel === \"pageWidth\"\n ? \"Fit width\"\n : \"Fit page\";\n\n return (\n <header className=\"flex h-10 shrink-0 items-center gap-1 border-b border-border px-2\">\n {/* Left cluster: undo/redo + formatting */}\n <div className=\"flex items-center gap-0.5\">\n <TwToolbarIconButton\n icon={Undo2}\n label=\"Undo\"\n disabled={caps ? !caps.canUndo : true}\n onClick={props.onUndo}\n />\n <TwToolbarIconButton\n icon={Redo2}\n label=\"Redo\"\n disabled={caps ? !caps.canRedo : true}\n onClick={props.onRedo}\n />\n <div className=\"mx-1 h-4 w-px bg-border\" />\n\n <ToolbarParagraphStyleSelect\n disabled={!canEdit || paragraphStyles.length === 0 || !props.onSetParagraphStyle}\n styles={paragraphStyles}\n value={props.formattingState?.paragraphStyleId}\n onValueChange={props.onSetParagraphStyle}\n />\n\n <ToolbarFontFamilySelect\n disabled={!canEdit || !props.onSetFontFamily}\n value={props.formattingState?.fontFamily}\n onValueChange={props.onSetFontFamily}\n />\n <ToolbarFontSizeSelect\n disabled={!canEdit || !props.onSetFontSize}\n value={props.formattingState?.fontSize}\n onValueChange={props.onSetFontSize}\n />\n\n <div className=\"mx-1 h-4 w-px bg-border\" />\n\n <TwToolbarIconButton\n icon={Bold}\n label=\"Bold\"\n active={props.formattingState?.bold ?? false}\n disabled={!canEdit}\n onClick={props.onToggleBold}\n />\n <TwToolbarIconButton\n icon={Italic}\n label=\"Italic\"\n active={props.formattingState?.italic ?? false}\n disabled={!canEdit}\n onClick={props.onToggleItalic}\n />\n <TwToolbarIconButton\n icon={Underline}\n label=\"Underline\"\n active={props.formattingState?.underline ?? false}\n disabled={!canEdit}\n onClick={props.onToggleUnderline}\n />\n <ToolbarFormattingOverflow\n disabled={!canEdit}\n formattingState={props.formattingState}\n onToggleStrikethrough={props.onToggleStrikethrough}\n onToggleSuperscript={props.onToggleSuperscript}\n onToggleSubscript={props.onToggleSubscript}\n />\n <ToolbarColorPopover\n ariaLabel=\"Text color\"\n colors={TEXT_COLORS.map((value) => ({ value, label: value }))}\n disabled={!canEdit || !props.onSetTextColor}\n icon={<Baseline className=\"h-3.5 w-3.5\" />}\n onSelect={(value) => {\n if (value) {\n props.onSetTextColor?.(value);\n }\n }}\n title=\"Text color\"\n />\n <ToolbarColorPopover\n ariaLabel=\"Highlight color\"\n colors={HIGHLIGHT_COLORS.map((entry) => ({ value: entry.value, label: entry.label }))}\n disabled={!canEdit || !props.onSetHighlightColor}\n icon={<Highlighter className=\"h-3.5 w-3.5\" />}\n onSelect={(value) => props.onSetHighlightColor?.(value)}\n title=\"Highlight color\"\n />\n <ToolbarAlignmentPopover\n activeAlignment={props.formattingState?.alignment}\n disabled={!canEdit || !props.onSetAlignment}\n onSelect={(alignment) => props.onSetAlignment?.(alignment)}\n />\n\n <div className=\"mx-1 h-4 w-px bg-border\" />\n\n <TwToolbarIconButton\n icon={Outdent}\n label=\"Outdent\"\n disabled={!canEdit}\n onClick={props.onOutdent}\n />\n <TwToolbarIconButton\n icon={Indent}\n label=\"Indent\"\n disabled={!canEdit}\n onClick={props.onIndent}\n />\n <ToolbarInsertMenu\n disabled={!canInsertStructural}\n onInsertImage={props.onInsertImage}\n onInsertPageBreak={props.onInsertPageBreak}\n onInsertSectionBreak={props.onInsertSectionBreak}\n onInsertTable={props.onInsertTable}\n />\n\n {/* Story focus breadcrumb — visible when editing a secondary story */}\n {props.activeStory && props.activeStory.kind !== \"main\" ? (\n <>\n <div className=\"mx-1 h-4 w-px bg-border\" />\n <button\n type=\"button\"\n onClick={props.onCloseStory}\n onMouseDown={preserveEditorSelectionMouseDown}\n className={`inline-flex items-center gap-1 rounded-md px-1.5 py-0.5 text-xs font-medium text-accent hover:bg-accent-soft transition-colors outline-none ${focusRingClass}`}\n aria-label={`Editing ${storyLabel(props.activeStory)} — click to return to main body`}\n >\n <span className=\"text-secondary\">&larr;</span>\n {storyLabel(props.activeStory)}\n </button>\n </>\n ) : null}\n </div>\n\n {/* Center: document title */}\n <div className=\"flex-1 text-center min-w-0\">\n <span className=\"text-sm font-medium truncate block\">\n {props.sourceLabel ?? \"Untitled\"}\n </span>\n </div>\n\n {/* Right cluster: comment, track changes, markup, view, export */}\n <div className=\"flex items-center gap-0.5\">\n <TwToolbarIconButton\n icon={MessageSquare}\n label=\"Add comment\"\n disabled={!canAddComment}\n emphasis\n onClick={props.onAddComment}\n />\n\n <Tooltip.Root>\n <Tooltip.Trigger asChild>\n <Toggle.Root\n pressed={props.showTrackedChanges}\n onPressedChange={props.onShowTrackedChangesChange}\n disabled={caps ? !caps.trackChangesSupported : false}\n onMouseDown={preserveEditorSelectionMouseDown}\n className={`inline-flex h-7 w-7 items-center justify-center rounded-md text-secondary transition-colors hover:bg-surface data-[state=on]:bg-accent-soft data-[state=on]:text-accent outline-none disabled:opacity-40 ${focusRingClass}`}\n >\n {props.showTrackedChanges ? <Eye className=\"h-4 w-4\" /> : <EyeOff className=\"h-4 w-4\" />}\n </Toggle.Root>\n </Tooltip.Trigger>\n <Tooltip.Portal>\n <Tooltip.Content\n className=\"rounded-md bg-primary px-2 py-1 text-xs text-white shadow-md z-50\"\n sideOffset={6}\n >\n {props.showTrackedChanges ? \"Hide tracked changes\" : \"Show tracked changes\"}\n </Tooltip.Content>\n </Tooltip.Portal>\n </Tooltip.Root>\n\n <div className=\"mx-1 h-4 w-px bg-border\" />\n\n {/* View mode toggle group: Canvas (clean, flowing) / Page (layout-sensitive) */}\n <ToggleGroup.Root\n type=\"single\"\n value={workspaceMode}\n onValueChange={(v: string) => {\n if (v) props.onWorkspaceModeChange(v as WorkspaceMode);\n }}\n className=\"flex items-center gap-0.5\"\n >\n <Tooltip.Root>\n <Tooltip.Trigger asChild>\n <ToggleGroup.Item\n value=\"canvas\"\n aria-label=\"Canvas workspace\"\n onMouseDown={preserveEditorSelectionMouseDown}\n className={`inline-flex h-7 w-7 items-center justify-center rounded-md text-secondary transition-colors hover:bg-surface data-[state=on]:bg-accent-soft data-[state=on]:text-accent outline-none ${focusRingClass}`}\n >\n <Monitor className=\"h-3.5 w-3.5\" />\n </ToggleGroup.Item>\n </Tooltip.Trigger>\n <Tooltip.Portal>\n <Tooltip.Content className=\"rounded-md bg-primary px-2 py-1 text-xs text-white shadow-md z-50\" sideOffset={6}>\n Canvas — clean flowing text\n </Tooltip.Content>\n </Tooltip.Portal>\n </Tooltip.Root>\n <Tooltip.Root>\n <Tooltip.Trigger asChild>\n <ToggleGroup.Item\n value=\"page\"\n aria-label=\"Page workspace\"\n onMouseDown={preserveEditorSelectionMouseDown}\n className={`inline-flex h-7 w-7 items-center justify-center rounded-md text-secondary transition-colors hover:bg-surface data-[state=on]:bg-accent-soft data-[state=on]:text-accent outline-none ${focusRingClass}`}\n >\n <FileText className=\"h-3.5 w-3.5\" />\n </ToggleGroup.Item>\n </Tooltip.Trigger>\n <Tooltip.Portal>\n <Tooltip.Content className=\"rounded-md bg-primary px-2 py-1 text-xs text-white shadow-md z-50\" sideOffset={6}>\n Page — layout-sensitive view\n </Tooltip.Content>\n </Tooltip.Portal>\n </Tooltip.Root>\n </ToggleGroup.Root>\n\n {/* Zoom controls — visible in page mode */}\n {isPageMode && props.onZoomChange ? (\n <>\n <div className=\"mx-1 h-4 w-px bg-border\" />\n <div className=\"flex items-center gap-0.5\">\n <Tooltip.Root>\n <Tooltip.Trigger asChild>\n <button\n type=\"button\"\n aria-label=\"Zoom out\"\n className={`inline-flex h-7 w-7 items-center justify-center rounded-md text-secondary transition-colors hover:bg-surface outline-none ${focusRingClass}`}\n disabled={typeof zoomLevel === \"number\" && zoomLevel <= 50}\n onMouseDown={preserveEditorSelectionMouseDown}\n onClick={() => {\n const current = typeof zoomLevel === \"number\" ? zoomLevel : 100;\n props.onZoomChange!(Math.max(50, current - 10));\n }}\n >\n <Minus className=\"h-3 w-3\" />\n </button>\n </Tooltip.Trigger>\n <Tooltip.Portal>\n <Tooltip.Content className=\"rounded-md bg-primary px-2 py-1 text-xs text-white shadow-md z-50\" sideOffset={6}>\n Zoom out\n </Tooltip.Content>\n </Tooltip.Portal>\n </Tooltip.Root>\n\n <Popover.Root>\n <Tooltip.Root>\n <Tooltip.Trigger asChild>\n <Popover.Trigger asChild>\n <button\n type=\"button\"\n aria-label={`Zoom: ${zoomLabel}`}\n onMouseDown={preserveEditorSelectionMouseDown}\n className={`inline-flex h-7 items-center justify-center rounded-md px-1.5 text-[11px] font-medium text-secondary transition-colors hover:bg-surface outline-none ${focusRingClass}`}\n >\n {zoomLabel}\n </button>\n </Popover.Trigger>\n </Tooltip.Trigger>\n <Tooltip.Portal>\n <Tooltip.Content className=\"rounded-md bg-primary px-2 py-1 text-xs text-white shadow-md z-50\" sideOffset={6}>\n Zoom level\n </Tooltip.Content>\n </Tooltip.Portal>\n </Tooltip.Root>\n <Popover.Portal>\n <Popover.Content\n className=\"w-[140px] rounded-lg bg-canvas shadow-lg ring-1 ring-border p-1 z-50\"\n sideOffset={8}\n align=\"center\"\n >\n {getSupportedZoomPresets().map((preset) => {\n const label = `${preset}%`;\n return (\n <Popover.Close key={preset} asChild>\n <button\n type=\"button\"\n onMouseDown={preserveEditorSelectionMouseDown}\n className={`w-full rounded-md px-3 py-1.5 text-left text-xs transition-colors hover:bg-surface ${\n zoomLevel === preset ? \"font-semibold text-accent\" : \"text-primary\"\n }`}\n onClick={() => props.onZoomChange!(preset)}\n >\n {label}\n </button>\n </Popover.Close>\n );\n })}\n </Popover.Content>\n </Popover.Portal>\n </Popover.Root>\n\n <Tooltip.Root>\n <Tooltip.Trigger asChild>\n <button\n type=\"button\"\n aria-label=\"Zoom in\"\n className={`inline-flex h-7 w-7 items-center justify-center rounded-md text-secondary transition-colors hover:bg-surface outline-none ${focusRingClass}`}\n disabled={typeof zoomLevel === \"number\" && zoomLevel >= 200}\n onMouseDown={preserveEditorSelectionMouseDown}\n onClick={() => {\n const current = typeof zoomLevel === \"number\" ? zoomLevel : 100;\n props.onZoomChange!(Math.min(200, current + 10));\n }}\n >\n <Plus className=\"h-3 w-3\" />\n </button>\n </Tooltip.Trigger>\n <Tooltip.Portal>\n <Tooltip.Content className=\"rounded-md bg-primary px-2 py-1 text-xs text-white shadow-md z-50\" sideOffset={6}>\n Zoom in\n </Tooltip.Content>\n </Tooltip.Portal>\n </Tooltip.Root>\n </div>\n </>\n ) : null}\n\n {/* Health indicator */}\n {props.compatibility && props.warnings ? (\n <Popover.Root>\n <Tooltip.Root>\n <Tooltip.Trigger asChild>\n <Popover.Trigger asChild>\n <button\n type=\"button\"\n onMouseDown={preserveEditorSelectionMouseDown}\n className={`relative inline-flex h-7 w-7 items-center justify-center rounded-md transition-colors hover:bg-surface hover:text-primary outline-none ${focusRingClass} ${\n (caps?.healthIssueCount ?? 0) > 0 ? \"text-secondary\" : \"text-secondary\"\n }`}\n >\n {(caps?.healthIssueCount ?? 0) > 0\n ? <ShieldAlert className=\"h-4 w-4\" />\n : <ShieldCheck className=\"h-4 w-4\" />\n }\n {(caps?.healthIssueCount ?? 0) > 0 ? (\n <span className=\"absolute -top-0.5 -right-0.5 flex h-3 min-w-[12px] items-center justify-center rounded-full bg-tertiary text-[8px] font-medium text-white\">\n {caps?.healthIssueCount}\n </span>\n ) : null}\n </button>\n </Popover.Trigger>\n </Tooltip.Trigger>\n <Tooltip.Portal>\n <Tooltip.Content className=\"rounded-md bg-primary px-2 py-1 text-xs text-white shadow-md z-50\" sideOffset={6}>\n {(caps?.healthIssueCount ?? 0) > 0\n ? `Document health — ${caps?.healthIssueCount} issue${(caps?.healthIssueCount ?? 0) !== 1 ? \"s\" : \"\"}`\n : \"Document health — no issues\"\n }\n </Tooltip.Content>\n </Tooltip.Portal>\n </Tooltip.Root>\n <Popover.Portal>\n <Popover.Content\n className=\"w-[360px] max-h-[480px] overflow-y-auto rounded-lg bg-canvas shadow-lg ring-1 ring-border p-3 z-50\"\n sideOffset={8}\n align=\"end\"\n >\n <TwHealthPanel\n blockedReasons={props.blockedReasons}\n compatibility={props.compatibility}\n warnings={props.warnings}\n />\n </Popover.Content>\n </Popover.Portal>\n </Popover.Root>\n ) : null}\n\n <div className=\"mx-1 h-4 w-px bg-border\" />\n\n {/* Export button */}\n <Tooltip.Root>\n <Tooltip.Trigger asChild>\n <button\n type=\"button\"\n disabled={caps ? !caps.canExport : true}\n onMouseDown={preserveEditorSelectionMouseDown}\n className={[\n \"inline-flex h-7 items-center gap-1.5 rounded-md px-2.5 text-xs font-semibold transition-colors outline-none\",\n focusRingClass,\n caps?.exportBlocked\n ? \"cursor-not-allowed text-danger opacity-50\"\n : \"text-accent hover:bg-accent-soft\",\n ].join(\" \")}\n onClick={props.onExport}\n >\n <Download className=\"h-3.5 w-3.5\" />\n Export .docx\n </button>\n </Tooltip.Trigger>\n <Tooltip.Portal>\n <Tooltip.Content className=\"rounded-md bg-primary px-2 py-1 text-xs text-white shadow-md z-50\" sideOffset={6}>\n {caps?.exportBlocked\n ? \"Export blocked by unsupported content\"\n : \"Export document\"}\n </Tooltip.Content>\n </Tooltip.Portal>\n </Tooltip.Root>\n </div>\n </header>\n );\n}\n\nfunction ToolbarParagraphStyleSelect(props: {\n styles: StyleCatalogSnapshot[\"paragraphs\"];\n value?: string;\n disabled: boolean;\n onValueChange?: (styleId: string) => void;\n}) {\n const resolvedValue =\n props.value && props.styles.some((style) => style.styleId === props.value)\n ? props.value\n : \"\";\n\n return (\n <Select.Root\n disabled={props.disabled}\n onValueChange={(value) => props.onValueChange?.(value)}\n value={resolvedValue}\n >\n <Select.Trigger\n aria-label=\"Paragraph style\"\n aria-disabled={props.disabled || undefined}\n data-disabled={props.disabled ? \"\" : undefined}\n onMouseDown={preserveEditorSelectionMouseDown}\n className={`inline-flex h-7 min-w-[8.5rem] items-center justify-between gap-2 rounded-md border border-border bg-canvas px-2.5 text-xs font-medium text-primary transition-colors hover:bg-surface outline-none disabled:cursor-not-allowed disabled:opacity-40 ${focusRingClass}`}\n >\n <Select.Value placeholder=\"Style\" />\n <Select.Icon>\n <ChevronDown className=\"h-3.5 w-3.5 text-tertiary\" />\n </Select.Icon>\n </Select.Trigger>\n <Select.Portal>\n <Select.Content\n align=\"start\"\n className=\"z-50 overflow-hidden rounded-lg bg-canvas shadow-lg ring-1 ring-border\"\n position=\"popper\"\n sideOffset={8}\n >\n <Select.Viewport className=\"p-1\">\n {props.styles.map((style) => (\n <Select.Item\n className={`flex cursor-pointer items-center rounded-md px-2.5 py-1.5 text-xs text-primary outline-none data-[highlighted]:bg-surface data-[state=checked]:bg-accent-soft data-[state=checked]:text-accent ${focusRingClass}`}\n key={style.styleId}\n value={style.styleId}\n >\n <Select.ItemText>{style.displayName}</Select.ItemText>\n </Select.Item>\n ))}\n </Select.Viewport>\n </Select.Content>\n </Select.Portal>\n </Select.Root>\n );\n}\n\nfunction ToolbarFontFamilySelect(props: {\n value?: string;\n disabled: boolean;\n onValueChange?: (fontFamily: string) => void;\n}) {\n const resolvedValue = props.value && FONT_FAMILIES.includes(props.value) ? props.value : \"\";\n\n return (\n <Select.Root\n disabled={props.disabled}\n onValueChange={(value) => props.onValueChange?.(value)}\n value={resolvedValue}\n >\n <Select.Trigger\n aria-label=\"Font family\"\n aria-disabled={props.disabled || undefined}\n data-disabled={props.disabled ? \"\" : undefined}\n onMouseDown={preserveEditorSelectionMouseDown}\n className={`inline-flex h-7 min-w-[7rem] items-center justify-between gap-2 rounded-md border border-border bg-canvas px-2 text-xs font-medium text-primary transition-colors hover:bg-surface outline-none disabled:cursor-not-allowed disabled:opacity-40 ${focusRingClass}`}\n >\n <Select.Value placeholder=\"Font\" />\n <Select.Icon>\n <ChevronDown className=\"h-3.5 w-3.5 text-tertiary\" />\n </Select.Icon>\n </Select.Trigger>\n <Select.Portal>\n <Select.Content\n align=\"start\"\n className=\"z-50 overflow-hidden rounded-lg bg-canvas shadow-lg ring-1 ring-border\"\n position=\"popper\"\n sideOffset={8}\n >\n <Select.Viewport className=\"p-1\">\n {FONT_FAMILIES.map((font) => (\n <Select.Item\n className={`flex cursor-pointer items-center rounded-md px-2.5 py-1.5 text-xs text-primary outline-none data-[highlighted]:bg-surface data-[state=checked]:bg-accent-soft data-[state=checked]:text-accent ${focusRingClass}`}\n key={font}\n value={font}\n >\n <Select.ItemText>{font}</Select.ItemText>\n </Select.Item>\n ))}\n </Select.Viewport>\n </Select.Content>\n </Select.Portal>\n </Select.Root>\n );\n}\n\nfunction ToolbarFontSizeSelect(props: {\n value?: number;\n disabled: boolean;\n onValueChange?: (fontSize: number) => void;\n}) {\n const resolvedValue =\n typeof props.value === \"number\" && FONT_SIZES.includes(props.value) ? String(props.value) : \"\";\n\n return (\n <Select.Root\n disabled={props.disabled}\n onValueChange={(value) => props.onValueChange?.(Number(value))}\n value={resolvedValue}\n >\n <Select.Trigger\n aria-label=\"Font size\"\n aria-disabled={props.disabled || undefined}\n data-disabled={props.disabled ? \"\" : undefined}\n onMouseDown={preserveEditorSelectionMouseDown}\n className={`inline-flex h-7 min-w-[4rem] items-center justify-between gap-2 rounded-md border border-border bg-canvas px-2 text-xs font-medium text-primary transition-colors hover:bg-surface outline-none disabled:cursor-not-allowed disabled:opacity-40 ${focusRingClass}`}\n >\n <Select.Value placeholder=\"Size\" />\n <Select.Icon>\n <ChevronDown className=\"h-3.5 w-3.5 text-tertiary\" />\n </Select.Icon>\n </Select.Trigger>\n <Select.Portal>\n <Select.Content\n align=\"start\"\n className=\"z-50 overflow-hidden rounded-lg bg-canvas shadow-lg ring-1 ring-border\"\n position=\"popper\"\n sideOffset={8}\n >\n <Select.Viewport className=\"p-1\">\n {FONT_SIZES.map((size) => (\n <Select.Item\n className={`flex cursor-pointer items-center rounded-md px-2.5 py-1.5 text-xs text-primary outline-none data-[highlighted]:bg-surface data-[state=checked]:bg-accent-soft data-[state=checked]:text-accent ${focusRingClass}`}\n key={size}\n value={String(size)}\n >\n <Select.ItemText>{size}</Select.ItemText>\n </Select.Item>\n ))}\n </Select.Viewport>\n </Select.Content>\n </Select.Portal>\n </Select.Root>\n );\n}\n\nfunction ToolbarFormattingOverflow(props: {\n disabled: boolean;\n formattingState?: FormattingStateSnapshot;\n onToggleStrikethrough?: () => void;\n onToggleSuperscript?: () => void;\n onToggleSubscript?: () => void;\n}) {\n const [open, setOpen] = React.useState(false);\n\n return (\n <div className=\"relative\">\n <Tooltip.Root>\n <Tooltip.Trigger asChild>\n <button\n type=\"button\"\n aria-label=\"More text formatting\"\n aria-expanded={open}\n disabled={props.disabled}\n onMouseDown={preserveEditorSelectionMouseDown}\n onClick={() => setOpen((value) => !value)}\n className={`inline-flex h-7 w-7 items-center justify-center rounded-md text-secondary transition-colors hover:bg-surface outline-none disabled:cursor-not-allowed disabled:opacity-40 ${focusRingClass}`}\n >\n <MoreHorizontal className=\"h-3.5 w-3.5\" />\n </button>\n </Tooltip.Trigger>\n <Tooltip.Portal>\n <Tooltip.Content className=\"rounded-md bg-primary px-2 py-1 text-xs text-white shadow-md z-50\" sideOffset={6}>\n More text formatting\n </Tooltip.Content>\n </Tooltip.Portal>\n </Tooltip.Root>\n {open ? (\n <div className=\"absolute left-0 top-9 z-50 w-[220px] rounded-lg bg-canvas p-2 shadow-lg ring-1 ring-border\">\n <div className=\"mb-1 px-1 text-[10px] font-semibold uppercase tracking-[0.12em] text-tertiary\">\n Text styling\n </div>\n <div className=\"grid grid-cols-3 gap-1\">\n <ToolbarPopoverActionButton\n active={props.formattingState?.strikethrough ?? false}\n ariaLabel=\"Strikethrough\"\n disabled={props.disabled}\n icon={<Strikethrough className=\"h-3.5 w-3.5\" />}\n onClick={() => {\n props.onToggleStrikethrough?.();\n setOpen(false);\n }}\n />\n <ToolbarPopoverActionButton\n active={props.formattingState?.superscript ?? false}\n ariaLabel=\"Superscript\"\n disabled={props.disabled}\n icon={<Superscript className=\"h-3.5 w-3.5\" />}\n onClick={() => {\n props.onToggleSuperscript?.();\n setOpen(false);\n }}\n />\n <ToolbarPopoverActionButton\n active={props.formattingState?.subscript ?? false}\n ariaLabel=\"Subscript\"\n disabled={props.disabled}\n icon={<Subscript className=\"h-3.5 w-3.5\" />}\n onClick={() => {\n props.onToggleSubscript?.();\n setOpen(false);\n }}\n />\n </div>\n </div>\n ) : null}\n </div>\n );\n}\n\nfunction ToolbarColorPopover(props: {\n ariaLabel: string;\n colors: ReadonlyArray<{ value: string | null; label: string }>;\n disabled: boolean;\n icon: React.ReactNode;\n title: string;\n onSelect: (value: string | null) => void;\n}) {\n const [open, setOpen] = React.useState(false);\n\n return (\n <div className=\"relative\">\n <Tooltip.Root>\n <Tooltip.Trigger asChild>\n <button\n type=\"button\"\n aria-label={props.ariaLabel}\n aria-expanded={open}\n disabled={props.disabled}\n onMouseDown={preserveEditorSelectionMouseDown}\n onClick={() => setOpen((value) => !value)}\n className={`inline-flex h-7 w-7 items-center justify-center rounded-md text-secondary transition-colors hover:bg-surface outline-none disabled:cursor-not-allowed disabled:opacity-40 ${focusRingClass}`}\n >\n {props.icon}\n </button>\n </Tooltip.Trigger>\n <Tooltip.Portal>\n <Tooltip.Content className=\"rounded-md bg-primary px-2 py-1 text-xs text-white shadow-md z-50\" sideOffset={6}>\n {props.title}\n </Tooltip.Content>\n </Tooltip.Portal>\n </Tooltip.Root>\n {open ? (\n <div className=\"absolute left-0 top-9 z-50 w-[180px] rounded-lg bg-canvas p-2 shadow-lg ring-1 ring-border\">\n <div className=\"mb-1 px-1 text-[10px] font-semibold uppercase tracking-[0.12em] text-tertiary\">\n {props.title}\n </div>\n <div className=\"grid grid-cols-3 gap-1\">\n {props.colors.map((color) => (\n <button\n key={`${props.ariaLabel}-${color.label}`}\n type=\"button\"\n aria-label={`${props.title} ${color.label}`}\n disabled={props.disabled}\n onMouseDown={preserveEditorSelectionMouseDown}\n onClick={() => {\n props.onSelect(color.value);\n setOpen(false);\n }}\n className={`inline-flex h-8 items-center justify-center rounded-md border border-border text-[10px] font-medium text-primary transition-transform hover:scale-[1.04] disabled:cursor-not-allowed disabled:opacity-40 ${\n color.value ? \"\" : \"bg-surface\"\n } ${focusRingClass}`}\n style={color.value ? { backgroundColor: color.value } : undefined}\n >\n {color.value ? <span className=\"sr-only\">{color.label}</span> : \"None\"}\n </button>\n ))}\n </div>\n </div>\n ) : null}\n </div>\n );\n}\n\nfunction ToolbarAlignmentPopover(props: {\n activeAlignment?: FormattingAlignment;\n disabled: boolean;\n onSelect: (alignment: FormattingAlignment) => void;\n}) {\n const [open, setOpen] = React.useState(false);\n const alignments = [\n { value: \"left\" as const, label: \"Align left\", icon: <AlignLeft className=\"h-3.5 w-3.5\" /> },\n { value: \"center\" as const, label: \"Align center\", icon: <AlignCenter className=\"h-3.5 w-3.5\" /> },\n { value: \"right\" as const, label: \"Align right\", icon: <AlignRight className=\"h-3.5 w-3.5\" /> },\n { value: \"justify\" as const, label: \"Align justify\", icon: <AlignJustify className=\"h-3.5 w-3.5\" /> },\n ];\n\n return (\n <div className=\"relative\">\n <Tooltip.Root>\n <Tooltip.Trigger asChild>\n <button\n type=\"button\"\n aria-label=\"Paragraph alignment\"\n aria-expanded={open}\n disabled={props.disabled}\n onMouseDown={preserveEditorSelectionMouseDown}\n onClick={() => setOpen((value) => !value)}\n className={`inline-flex h-7 w-7 items-center justify-center rounded-md text-secondary transition-colors hover:bg-surface outline-none disabled:cursor-not-allowed disabled:opacity-40 ${focusRingClass}`}\n >\n {(alignments.find((entry) => entry.value === props.activeAlignment) ?? alignments[0])?.icon}\n </button>\n </Tooltip.Trigger>\n <Tooltip.Portal>\n <Tooltip.Content className=\"rounded-md bg-primary px-2 py-1 text-xs text-white shadow-md z-50\" sideOffset={6}>\n Paragraph alignment\n </Tooltip.Content>\n </Tooltip.Portal>\n </Tooltip.Root>\n {open ? (\n <div className=\"absolute left-0 top-9 z-50 w-[220px] rounded-lg bg-canvas p-2 shadow-lg ring-1 ring-border\">\n <div className=\"mb-1 px-1 text-[10px] font-semibold uppercase tracking-[0.12em] text-tertiary\">\n Paragraph alignment\n </div>\n <div className=\"grid grid-cols-2 gap-1\">\n {alignments.map((entry) => (\n <ToolbarPopoverActionButton\n key={entry.value}\n active={props.activeAlignment === entry.value}\n ariaLabel={entry.label}\n disabled={props.disabled}\n icon={entry.icon}\n onClick={() => {\n props.onSelect(entry.value);\n setOpen(false);\n }}\n />\n ))}\n </div>\n </div>\n ) : null}\n </div>\n );\n}\n\nfunction ToolbarInsertMenu(props: {\n disabled: boolean;\n onInsertPageBreak?: () => void;\n onInsertTable?: () => void;\n onInsertSectionBreak?: (type: SectionBreakType) => void;\n onInsertImage?: (options: InsertImageOptions) => void;\n}) {\n const [open, setOpen] = React.useState(false);\n\n async function handleImageChange(event: React.ChangeEvent<HTMLInputElement>): Promise<void> {\n const file = event.target.files?.[0];\n if (!file || props.disabled || !props.onInsertImage) {\n event.target.value = \"\";\n return;\n }\n const data = new Uint8Array(await file.arrayBuffer());\n props.onInsertImage({\n data,\n mimeType: file.type || \"image/png\",\n altText: file.name,\n });\n setOpen(false);\n event.target.value = \"\";\n }\n\n return (\n <div className=\"relative\">\n <Tooltip.Root>\n <Tooltip.Trigger asChild>\n <button\n type=\"button\"\n aria-label=\"Insert\"\n aria-expanded={open}\n disabled={props.disabled}\n onMouseDown={preserveEditorSelectionMouseDown}\n onClick={() => setOpen((value) => !value)}\n className={`inline-flex h-7 items-center gap-1 rounded-md border border-border bg-canvas px-2 text-xs font-medium text-primary transition-colors hover:bg-surface outline-none disabled:cursor-not-allowed disabled:opacity-40 ${focusRingClass}`}\n >\n Insert\n <ChevronDown className=\"h-3.5 w-3.5 text-tertiary\" />\n </button>\n </Tooltip.Trigger>\n <Tooltip.Portal>\n <Tooltip.Content className=\"rounded-md bg-primary px-2 py-1 text-xs text-white shadow-md z-50\" sideOffset={6}>\n Insert\n </Tooltip.Content>\n </Tooltip.Portal>\n </Tooltip.Root>\n {open ? (\n <div className=\"absolute left-0 top-9 z-50 w-[220px] rounded-lg bg-canvas p-2 shadow-lg ring-1 ring-border\">\n <div className=\"space-y-1\">\n <ToolbarMenuButton\n ariaLabel=\"Insert page break\"\n disabled={props.disabled || !props.onInsertPageBreak}\n icon={<Minus className=\"h-3.5 w-3.5\" />}\n label=\"Page break\"\n onClick={() => {\n props.onInsertPageBreak?.();\n setOpen(false);\n }}\n />\n <ToolbarMenuButton\n ariaLabel=\"Insert table\"\n disabled={props.disabled || !props.onInsertTable}\n icon={<Rows3 className=\"h-3.5 w-3.5\" />}\n label=\"Table\"\n onClick={() => {\n props.onInsertTable?.();\n setOpen(false);\n }}\n />\n <label\n className={`flex h-8 cursor-pointer items-center gap-2 rounded-md px-2 text-xs font-medium text-primary transition-colors hover:bg-surface ${\n props.disabled || !props.onInsertImage ? \"pointer-events-none opacity-40\" : \"\"\n }`}\n >\n <ImagePlus className=\"h-3.5 w-3.5 text-secondary\" />\n <span>Image</span>\n <input\n accept=\"image/png,image/jpeg,image/gif\"\n aria-label=\"Insert image\"\n className=\"sr-only\"\n disabled={props.disabled || !props.onInsertImage}\n type=\"file\"\n onChange={(event) => {\n void handleImageChange(event);\n }}\n />\n </label>\n <ToolbarMenuButton\n ariaLabel=\"Insert next-page section break\"\n disabled={props.disabled || !props.onInsertSectionBreak}\n icon={<FileText className=\"h-3.5 w-3.5\" />}\n label=\"Next-page section break\"\n onClick={() => {\n props.onInsertSectionBreak?.(\"nextPage\");\n setOpen(false);\n }}\n />\n </div>\n </div>\n ) : null}\n </div>\n );\n}\n\nfunction ToolbarPopoverActionButton(props: {\n active: boolean;\n ariaLabel: string;\n disabled: boolean;\n icon: React.ReactNode;\n onClick?: () => void;\n}) {\n return (\n <button\n type=\"button\"\n aria-label={props.ariaLabel}\n aria-pressed={props.active}\n disabled={props.disabled}\n onMouseDown={preserveEditorSelectionMouseDown}\n onClick={props.onClick}\n className={`inline-flex h-8 items-center justify-center rounded-md border border-border transition-colors disabled:cursor-not-allowed disabled:opacity-40 ${\n props.active ? \"bg-accent-soft text-accent\" : \"bg-canvas text-secondary hover:bg-surface\"\n } ${focusRingClass}`}\n >\n {props.icon}\n </button>\n );\n}\n\nfunction ToolbarMenuButton(props: {\n ariaLabel: string;\n disabled: boolean;\n icon: React.ReactNode;\n label: string;\n onClick?: () => void;\n}) {\n return (\n <button\n type=\"button\"\n aria-label={props.ariaLabel}\n disabled={props.disabled}\n onMouseDown={preserveEditorSelectionMouseDown}\n onClick={props.onClick}\n className={`flex h-8 w-full items-center gap-2 rounded-md px-2 text-left text-xs font-medium text-primary transition-colors hover:bg-surface disabled:cursor-not-allowed disabled:opacity-40 ${focusRingClass}`}\n >\n <span className=\"text-secondary\">{props.icon}</span>\n <span>{props.label}</span>\n </button>\n );\n}\n\nfunction storyLabel(target: EditorStoryTarget): string {\n switch (target.kind) {\n case \"header\":\n return `Header (${target.variant})`;\n case \"footer\":\n return `Footer (${target.variant})`;\n case \"footnote\":\n return \"Footnote\";\n case \"endnote\":\n return \"Endnote\";\n default:\n return \"Document\";\n }\n}\n","import React from \"react\";\nimport { AlertTriangle, Info, Shield, ShieldAlert, ShieldCheck } from \"lucide-react\";\n\nimport type {\n CompatibilityFeatureEntry,\n CompatibilityPanelSnapshot,\n EditorWarning,\n WorkflowBlockedCommandReason,\n} from \"../../api/public-types\";\n\nexport interface TwHealthPanelProps {\n compatibility: CompatibilityPanelSnapshot;\n warnings: EditorWarning[];\n blockedReasons?: WorkflowBlockedCommandReason[];\n}\n\nexport function TwHealthPanel(props: TwHealthPanelProps) {\n const { compatibility, warnings, blockedReasons = [] } = props;\n const supportedCount = compatibility.featureEntries.filter(\n (e) => e.featureClass === \"supported-roundtrip\",\n ).length;\n const preserveOnlyCount = compatibility.featureEntries.filter(\n (e) => e.featureClass === \"preserve-only\",\n ).length;\n const blockedCount = compatibility.featureEntries.filter(\n (e) => e.featureClass === \"unsupported-fatal\",\n ).length;\n\n return (\n <div className=\"outline-none\">\n <p className=\"text-xs text-tertiary mb-3\">\n {supportedCount} supported · {preserveOnlyCount} preserve-only · {blockedCount} blocked\n {warnings.length > 0 ? ` · ${warnings.length} warning${warnings.length !== 1 ? \"s\" : \"\"}` : \"\"}\n </p>\n\n <div className=\"space-y-1\">\n {compatibility.featureEntries.map((entry) => (\n <div key={entry.featureEntryId} className=\"flex rounded-lg transition-colors hover:bg-surface\">\n {entry.featureClass !== \"supported-roundtrip\" ? (\n <div className={`w-0.5 shrink-0 rounded-l-lg ${\n entry.featureClass === \"unsupported-fatal\" ? \"bg-danger\" : \"bg-comment\"\n }`} />\n ) : null}\n <div className=\"flex items-start gap-2 p-2.5 flex-1\">\n <HealthIcon featureClass={entry.featureClass} />\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex items-start justify-between gap-2\">\n <span className=\"text-sm font-medium text-primary\">{entry.message}</span>\n <FeatureClassBadge featureClass={entry.featureClass} />\n </div>\n <p className=\"text-xs text-tertiary mt-0.5\">{entry.featureKey}</p>\n </div>\n </div>\n </div>\n ))}\n\n {warnings.map((warning) => (\n <div key={warning.warningId} className=\"flex rounded-lg transition-colors hover:bg-surface\">\n <div className={`w-0.5 shrink-0 rounded-l-lg ${\n warning.severity === \"warning\" ? \"bg-comment\" : \"bg-accent\"\n }`} />\n <div className=\"flex items-start gap-2 p-2.5 flex-1\">\n {warning.severity === \"warning\" ? (\n <AlertTriangle className=\"h-4 w-4 text-comment shrink-0 mt-0.5\" />\n ) : (\n <Info className=\"h-4 w-4 text-accent shrink-0 mt-0.5\" />\n )}\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex items-start justify-between gap-2\">\n <span className=\"text-sm font-medium text-primary\">{warning.message}</span>\n <span className={`inline-flex items-center rounded px-1.5 py-0.5 text-[10px] font-medium ${\n warning.severity === \"warning\"\n ? \"text-comment bg-warning-soft\"\n : \"text-accent bg-accent-soft\"\n }`}>\n {warning.code.replace(/_/g, \" \")}\n </span>\n </div>\n <p className=\"text-xs text-tertiary mt-0.5\">{warning.source}</p>\n </div>\n </div>\n </div>\n ))}\n\n {blockedReasons.length > 0 ? (\n <>\n <div className=\"border-t border-border mt-2 pt-2\">\n <p className=\"text-xs font-medium text-tertiary mb-1\">Workflow blocked reasons</p>\n </div>\n {blockedReasons.map((reason, index) => (\n <div key={`blocked-${index}`} className=\"flex rounded-lg transition-colors hover:bg-surface\">\n <div className=\"w-0.5 shrink-0 rounded-l-lg bg-amber-400\" />\n <div className=\"flex items-start gap-2 p-2.5 flex-1\">\n <ShieldAlert className=\"h-4 w-4 text-amber-500 shrink-0 mt-0.5\" />\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex items-start justify-between gap-2\">\n <span className=\"text-sm font-medium text-primary\">{reason.message}</span>\n <span className=\"inline-flex items-center rounded px-1.5 py-0.5 text-[10px] font-medium text-amber-700 bg-amber-100\">\n {reason.code.replace(/_/g, \" \")}\n </span>\n </div>\n {reason.scopeId ? (\n <p className=\"text-xs text-tertiary mt-0.5\">scope: {reason.scopeId}</p>\n ) : null}\n </div>\n </div>\n </div>\n ))}\n </>\n ) : null}\n\n {compatibility.featureEntries.length === 0 && warnings.length === 0 && blockedReasons.length === 0 ? (\n <p className=\"text-xs text-tertiary py-4\">\n No compatibility entries or warnings to display.\n </p>\n ) : null}\n </div>\n </div>\n );\n}\n\nfunction HealthIcon(props: { featureClass: CompatibilityFeatureEntry[\"featureClass\"] }) {\n switch (props.featureClass) {\n case \"supported-roundtrip\":\n return <ShieldCheck className=\"h-4 w-4 text-insert shrink-0 mt-0.5\" />;\n case \"preserve-only\":\n return <Shield className=\"h-4 w-4 text-comment shrink-0 mt-0.5\" />;\n case \"unsupported-fatal\":\n return <ShieldAlert className=\"h-4 w-4 text-danger shrink-0 mt-0.5\" />;\n }\n}\n\nfunction FeatureClassBadge(props: { featureClass: CompatibilityFeatureEntry[\"featureClass\"] }) {\n const styles: Record<string, string> = {\n \"supported-roundtrip\": \"text-insert bg-insert-soft\",\n \"preserve-only\": \"text-comment bg-warning-soft\",\n \"unsupported-fatal\": \"text-danger bg-delete-soft\",\n };\n const labels: Record<string, string> = {\n \"supported-roundtrip\": \"supported\",\n \"preserve-only\": \"preserve-only\",\n \"unsupported-fatal\": \"blocked\",\n };\n return (\n <span className={`inline-flex items-center rounded px-1.5 py-0.5 text-[10px] font-medium ${styles[props.featureClass]}`}>\n {labels[props.featureClass]}\n </span>\n );\n}\n","import React from \"react\";\nimport * as Tooltip from \"@radix-ui/react-tooltip\";\n\nimport { preserveEditorSelectionMouseDown } from \"../../ui/headless/preserve-editor-selection\";\n\nexport interface TwToolbarIconButtonProps {\n icon: React.ComponentType<{ className?: string }>;\n label: string;\n disabled?: boolean;\n active?: boolean;\n emphasis?: boolean;\n onClick?: () => void;\n}\n\nconst focusRingClass =\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-2 focus-visible:ring-offset-canvas\";\n\nexport function TwToolbarIconButton(props: TwToolbarIconButtonProps) {\n return (\n <Tooltip.Root>\n <Tooltip.Trigger asChild>\n <button\n type=\"button\"\n aria-label={props.label}\n disabled={props.disabled}\n onMouseDown={preserveEditorSelectionMouseDown}\n onClick={props.onClick}\n className={[\n \"inline-flex h-7 w-7 items-center justify-center rounded-md transition-colors outline-none\",\n \"disabled:opacity-30 disabled:cursor-not-allowed\",\n props.emphasis\n ? \"text-accent hover:bg-accent-soft\"\n : props.active\n ? \"bg-accent-soft text-accent\"\n : \"text-secondary hover:bg-surface hover:text-primary\",\n focusRingClass,\n ].join(\" \")}\n >\n <props.icon className=\"h-4 w-4\" />\n </button>\n </Tooltip.Trigger>\n <Tooltip.Portal>\n <Tooltip.Content\n className=\"rounded-md bg-primary px-2 py-1 text-xs text-white shadow-md z-50\"\n sideOffset={6}\n >\n {props.label}\n </Tooltip.Content>\n </Tooltip.Portal>\n </Tooltip.Root>\n );\n}\n","import React, { type FocusEventHandler, useMemo } from \"react\";\n\nimport type {\n EditorUser,\n RuntimeRenderSnapshot,\n SelectionSnapshot,\n} from \"../../api/public-types\";\nimport {\n createCommentDecorationModel,\n type MarkupDisplay,\n} from \"../../ui/headless/comment-decoration-model\";\nimport { createRevisionDecorationModel } from \"../../ui/headless/revision-decoration-model\";\nimport { createEditorKeyboardHandler } from \"../../ui/headless/use-editor-keyboard\";\nimport { TwOpaqueBlock } from \"./tw-opaque-block\";\nimport { TwParagraphBlock } from \"./tw-paragraph-block\";\n\nexport interface TwEditorSurfaceProps {\n currentUser: EditorUser;\n snapshot: RuntimeRenderSnapshot;\n reviewMode: \"editing\" | \"review\";\n markupDisplay: MarkupDisplay;\n activeRevisionId?: string;\n /** When false, revision decorations are suppressed in the document surface. */\n showTrackedChanges?: boolean;\n onFocus: FocusEventHandler<HTMLDivElement>;\n onBlur: FocusEventHandler<HTMLDivElement>;\n onSelectionChange?: (selection: SelectionSnapshot) => void;\n onInsertText?: (text: string) => void;\n onDeleteBackward?: () => void;\n onDeleteForward?: () => void;\n onInsertTab?: () => void;\n onInsertHardBreak?: () => void;\n onSplitParagraph?: () => void;\n onCommentActivated?: (commentId: string) => void;\n onRevisionActivated?: (revisionId: string) => void;\n}\n\nexport function TwEditorSurface(props: TwEditorSurfaceProps) {\n const { currentUser, markupDisplay, onBlur, onFocus, snapshot } = props;\n const surface = snapshot.surface;\n\n const canEdit = Boolean(\n surface && snapshot.isReady && !snapshot.readOnly && !snapshot.fatalError,\n );\n\n const commentDecorations = useMemo(\n () => createCommentDecorationModel(snapshot.comments),\n [snapshot.comments],\n );\n\n const showTrackedChanges = props.showTrackedChanges !== false;\n const revisionDecorations = useMemo(\n () => showTrackedChanges\n ? createRevisionDecorationModel(snapshot.trackedChanges, props.activeRevisionId)\n : undefined,\n [snapshot.trackedChanges, props.activeRevisionId, showTrackedChanges],\n );\n\n const handleKeyDown = useMemo(() => {\n if (!surface) return undefined;\n return createEditorKeyboardHandler(\n {\n selection: snapshot.selection,\n storySize: surface.storySize,\n canEdit,\n },\n {\n onSelectionChange: props.onSelectionChange,\n onInsertText: props.onInsertText,\n onDeleteBackward: props.onDeleteBackward,\n onDeleteForward: props.onDeleteForward,\n onInsertTab: props.onInsertTab,\n onInsertHardBreak: props.onInsertHardBreak,\n onSplitParagraph: props.onSplitParagraph,\n },\n );\n }, [surface, snapshot.selection, canEdit, props]);\n\n const fontClass = markupDisplay === \"clean\"\n ? \"font-[family-name:var(--font-legal-sans)]\"\n : \"font-[family-name:var(--font-legal-serif)]\";\n\n return (\n <section aria-label=\"Document canvas\" className=\"min-w-0\">\n <div\n aria-label=\"Document surface\"\n aria-multiline=\"true\"\n role=\"textbox\"\n tabIndex={0}\n onFocus={onFocus}\n onBlur={onBlur}\n onKeyDown={handleKeyDown}\n className={`bg-transparent border-none px-12 py-10 outline-offset-1 ${fontClass}`}\n >\n {/* Document header */}\n <div className=\"flex justify-between gap-4 items-start mb-5\">\n <div>\n <h1 className=\"font-[family-name:var(--font-legal-serif)] text-2xl leading-tight text-primary\">\n {snapshot.sourceLabel ?? \"Document draft\"}\n </h1>\n <p className=\"text-xs text-secondary mt-2\">\n {snapshot.sessionId} · {snapshot.documentStats.storyLength} chars\n </p>\n </div>\n <span className=\"text-xs text-secondary whitespace-nowrap\">\n Reviewer {currentUser.displayName}\n </span>\n </div>\n\n {/* Document blocks */}\n <div className=\"space-y-4 pl-10 relative\">\n {surface ? (\n surface.blocks.map((block) =>\n block.kind === \"paragraph\" ? (\n <TwParagraphBlock\n key={block.blockId}\n block={block}\n selection={snapshot.selection}\n markupDisplay={markupDisplay}\n commentDecorations={commentDecorations}\n revisionDecorations={revisionDecorations}\n onSelectionChange={props.onSelectionChange}\n onCommentActivated={props.onCommentActivated}\n onRevisionActivated={props.onRevisionActivated}\n />\n ) : block.kind === \"opaque_block\" ? (\n <TwOpaqueBlock\n key={block.blockId}\n block={block}\n selection={snapshot.selection}\n onSelectionChange={props.onSelectionChange}\n />\n ) : null,\n )\n ) : (\n <p className=\"text-sm text-secondary leading-relaxed\">\n Loading the review surface. Compatibility cues and edit actions appear here once\n the runtime snapshot is ready.\n </p>\n )}\n {snapshot.fatalError ? (\n <p className=\"text-sm text-danger\">\n Fatal runtime error: {snapshot.fatalError.message}\n </p>\n ) : null}\n </div>\n </div>\n </section>\n );\n}\n","import type { CommentSidebarSnapshot } from \"../../api/public-types\";\n\nexport interface CommentDecorationModel {\n threads: CommentDecorationThread[];\n activeCommentId?: string;\n}\n\nexport interface CommentDecorationThread {\n commentId: string;\n from: number;\n to: number;\n status: CommentSidebarSnapshot[\"threads\"][number][\"status\"];\n isActive: boolean;\n}\n\nexport interface CommentRangeState {\n hasComments: boolean;\n hasOpen: boolean;\n hasResolved: boolean;\n hasActive: boolean;\n count: number;\n overlapping: CommentDecorationThread[];\n}\n\nexport function createCommentDecorationModel(\n snapshot?: CommentSidebarSnapshot,\n): CommentDecorationModel | undefined {\n if (!snapshot) {\n return undefined;\n }\n\n return {\n activeCommentId: snapshot.activeCommentId,\n threads: snapshot.threads\n .filter((thread) => thread.anchor.kind !== \"detached\")\n .map((thread) => {\n const anchor = thread.anchor;\n const from = anchor.kind === \"range\" ? anchor.from : anchor.kind === \"node\" ? anchor.at : 0;\n const to = anchor.kind === \"range\" ? anchor.to : anchor.kind === \"node\" ? anchor.at : 0;\n return {\n commentId: thread.commentId,\n from,\n to,\n status: thread.status,\n isActive: thread.isActive,\n };\n }),\n };\n}\n\nexport function getCommentRangeState(\n model: CommentDecorationModel | undefined,\n from: number,\n to: number,\n): CommentRangeState {\n if (!model) {\n return {\n hasComments: false,\n hasOpen: false,\n hasResolved: false,\n hasActive: false,\n count: 0,\n overlapping: [],\n };\n }\n\n const overlapping = model.threads.filter((thread) =>\n rangesOverlap(thread.from, thread.to, from, to),\n );\n return {\n hasComments: overlapping.length > 0,\n hasOpen: overlapping.some((thread) => thread.status === \"open\"),\n hasResolved: overlapping.some((thread) => thread.status === \"resolved\"),\n hasActive: overlapping.some((thread) => thread.isActive),\n count: overlapping.length,\n overlapping,\n };\n}\n\nexport type MarkupDisplay = \"clean\" | \"simple\" | \"all\";\n\nexport function getCommentHighlightClass(\n model: CommentDecorationModel | undefined,\n from: number,\n to: number,\n markupDisplay: MarkupDisplay = \"all\",\n): string {\n const state = getCommentRangeState(model, from, to);\n if (!state.hasComments) {\n return \"\";\n }\n\n switch (markupDisplay) {\n case \"clean\":\n return state.hasActive ? \"bg-comment-soft\" : \"\";\n case \"simple\":\n if (state.hasActive) {\n return \"underline decoration-comment decoration-2 underline-offset-4\";\n }\n if (state.hasOpen) {\n return \"underline decoration-comment/60 decoration-1 underline-offset-4\";\n }\n return \"underline decoration-comment/40 decoration-1 underline-offset-4\";\n case \"all\":\n if (state.hasActive) {\n return \"bg-comment-strong\";\n }\n if (state.hasOpen) {\n return \"bg-comment-soft\";\n }\n return \"bg-comment-soft opacity-60\";\n }\n}\n\nexport function rangesOverlap(\n leftFrom: number,\n leftTo: number,\n rightFrom: number,\n rightTo: number,\n): boolean {\n const leftEnd = Math.max(leftFrom, leftTo);\n const rightEnd = Math.max(rightFrom, rightTo);\n return leftFrom < rightEnd && rightFrom < leftEnd;\n}\n","import type { TrackedChangesSnapshot, TrackedChangeEntrySnapshot } from \"../../api/public-types\";\nimport { rangesOverlap, type MarkupDisplay } from \"./comment-decoration-model\";\n\nexport interface RevisionDecorationModel {\n revisions: RevisionDecorationEntry[];\n}\n\nexport interface RevisionDecorationEntry {\n revisionId: string;\n from: number;\n to: number;\n kind: TrackedChangeEntrySnapshot[\"kind\"];\n status: TrackedChangeEntrySnapshot[\"status\"];\n actionability: TrackedChangeEntrySnapshot[\"actionability\"];\n isActive: boolean;\n}\n\nexport interface RevisionRangeState {\n hasChanges: boolean;\n hasInsertions: boolean;\n hasDeletions: boolean;\n hasActive: boolean;\n count: number;\n overlapping: RevisionDecorationEntry[];\n}\n\nexport function createRevisionDecorationModel(\n snapshot?: TrackedChangesSnapshot,\n activeRevisionId?: string,\n): RevisionDecorationModel | undefined {\n if (!snapshot) {\n return undefined;\n }\n\n return {\n revisions: snapshot.revisions\n .filter((rev) => rev.anchor.kind !== \"detached\" && rev.status === \"active\")\n .map((rev) => {\n const anchor = rev.anchor;\n const from = anchor.kind === \"range\" ? anchor.from : anchor.kind === \"node\" ? anchor.at : 0;\n const to = anchor.kind === \"range\" ? anchor.to : anchor.kind === \"node\" ? anchor.at : 0;\n return {\n revisionId: rev.revisionId,\n from,\n to,\n kind: rev.kind,\n status: rev.status,\n actionability: rev.actionability,\n isActive: rev.revisionId === activeRevisionId,\n };\n }),\n };\n}\n\nexport function getRevisionRangeState(\n model: RevisionDecorationModel | undefined,\n from: number,\n to: number,\n): RevisionRangeState {\n if (!model) {\n return {\n hasChanges: false,\n hasInsertions: false,\n hasDeletions: false,\n hasActive: false,\n count: 0,\n overlapping: [],\n };\n }\n\n const overlapping = model.revisions.filter((rev) =>\n rangesOverlap(rev.from, rev.to, from, to),\n );\n return {\n hasChanges: overlapping.length > 0,\n hasInsertions: overlapping.some((rev) => rev.kind === \"insertion\"),\n hasDeletions: overlapping.some((rev) => rev.kind === \"deletion\"),\n hasActive: overlapping.some((rev) => rev.isActive),\n count: overlapping.length,\n overlapping,\n };\n}\n\nexport function getRevisionHighlightClass(\n model: RevisionDecorationModel | undefined,\n from: number,\n to: number,\n markupDisplay: MarkupDisplay = \"all\",\n): string {\n const state = getRevisionRangeState(model, from, to);\n if (!state.hasChanges) {\n return \"\";\n }\n\n const activeRing = state.hasActive ? \" ring-1 ring-accent/30\" : \"\";\n\n switch (markupDisplay) {\n case \"clean\":\n // In clean mode, deletions are hidden entirely (caller should not render).\n // Insertions render as normal text with no decoration.\n return \"\";\n case \"simple\":\n if (state.hasInsertions) {\n return `underline decoration-insert/60 decoration-1 underline-offset-2 text-primary${activeRing}`;\n }\n if (state.hasDeletions) {\n return `text-secondary line-through decoration-danger/70 decoration-1${activeRing}`;\n }\n return activeRing;\n case \"all\":\n if (state.hasInsertions) {\n return `text-primary bg-insert-soft/80 ring-1 ring-insert/20${activeRing}`;\n }\n if (state.hasDeletions) {\n return `text-danger line-through decoration-danger/80 decoration-1 bg-delete-soft/70${activeRing}`;\n }\n return activeRing;\n }\n}\n\nexport function shouldHideInCleanMode(\n model: RevisionDecorationModel | undefined,\n from: number,\n to: number,\n): boolean {\n const state = getRevisionRangeState(model, from, to);\n return state.hasDeletions;\n}\n","import type { SelectionSnapshot } from \"../../api/public-types\";\n\nexport function createSelectionSnapshot(anchor: number, head = anchor): SelectionSnapshot {\n const from = Math.min(anchor, head);\n const to = Math.max(anchor, head);\n return {\n anchor,\n head,\n isCollapsed: anchor === head,\n activeRange: {\n kind: \"range\",\n from,\n to,\n assoc: {\n start: -1,\n end: 1,\n },\n },\n };\n}\n\nexport function createNodeSelectionSnapshot(at: number, assoc: -1 | 1 = 1): SelectionSnapshot {\n return {\n anchor: at,\n head: at,\n isCollapsed: true,\n activeRange: {\n kind: \"node\",\n at,\n assoc,\n },\n };\n}\n\nexport function isCollapsedAtBlockStart(\n selection: SelectionSnapshot,\n blockFrom: number,\n): boolean {\n return selection.isCollapsed && selection.head === blockFrom;\n}\n\nexport function selectionTouchesRange(\n selection: SelectionSnapshot,\n from: number,\n to: number,\n): boolean {\n if (selection.isCollapsed) {\n return false;\n }\n\n const selectionFrom = Math.min(selection.anchor, selection.head);\n const selectionTo = Math.max(selection.anchor, selection.head);\n return selectionFrom < to && from < selectionTo;\n}\n","import type { KeyboardEvent } from \"react\";\n\nimport type { SelectionSnapshot } from \"../../api/public-types\";\nimport { createSelectionSnapshot } from \"./selection-helpers\";\n\nexport interface EditorKeyboardCallbacks {\n onSelectionChange?: (selection: SelectionSnapshot) => void;\n onInsertText?: (text: string) => void;\n onDeleteBackward?: () => void;\n onDeleteForward?: () => void;\n onInsertTab?: () => void;\n onOutdentTab?: () => void;\n onInsertHardBreak?: () => void;\n onSplitParagraph?: () => void;\n}\n\nexport interface EditorKeyboardContext {\n selection: SelectionSnapshot;\n storySize: number;\n canEdit: boolean;\n}\n\nexport function createEditorKeyboardHandler(\n context: EditorKeyboardContext,\n callbacks: EditorKeyboardCallbacks,\n): (event: KeyboardEvent<HTMLDivElement>) => void {\n return function handleKeyDown(event: KeyboardEvent<HTMLDivElement>): void {\n const { selection, storySize, canEdit } = context;\n\n if (event.key === \"ArrowLeft\") {\n event.preventDefault();\n moveSelection(selection.anchor, selection.head - 1, event.shiftKey, storySize, callbacks);\n return;\n }\n\n if (event.key === \"ArrowRight\") {\n event.preventDefault();\n moveSelection(selection.anchor, selection.head + 1, event.shiftKey, storySize, callbacks);\n return;\n }\n\n if (event.key === \"Home\") {\n event.preventDefault();\n moveSelection(selection.anchor, 0, event.shiftKey, storySize, callbacks);\n return;\n }\n\n if (event.key === \"End\") {\n event.preventDefault();\n moveSelection(selection.anchor, storySize, event.shiftKey, storySize, callbacks);\n return;\n }\n\n if (!canEdit || event.metaKey || event.ctrlKey || event.altKey) {\n return;\n }\n\n switch (event.key) {\n case \"Backspace\":\n event.preventDefault();\n callbacks.onDeleteBackward?.();\n return;\n case \"Delete\":\n event.preventDefault();\n callbacks.onDeleteForward?.();\n return;\n case \"Tab\":\n event.preventDefault();\n if (event.shiftKey) {\n callbacks.onOutdentTab?.();\n } else {\n callbacks.onInsertTab?.();\n }\n return;\n case \"Enter\":\n event.preventDefault();\n if (event.shiftKey) {\n callbacks.onInsertHardBreak?.();\n } else {\n callbacks.onSplitParagraph?.();\n }\n return;\n default:\n if (event.key.length === 1) {\n event.preventDefault();\n callbacks.onInsertText?.(event.key);\n }\n }\n };\n}\n\nfunction moveSelection(\n anchor: number,\n nextHead: number,\n extend: boolean,\n storySize: number,\n callbacks: EditorKeyboardCallbacks,\n): void {\n const clampedHead = Math.max(0, Math.min(storySize, nextHead));\n callbacks.onSelectionChange?.(\n createSelectionSnapshot(extend ? anchor : clampedHead, clampedHead),\n );\n}\n","import React from \"react\";\n\nimport type { SelectionSnapshot, SurfaceBlockSnapshot } from \"../../api/public-types\";\nimport { selectionTouchesRange, createSelectionSnapshot } from \"../../ui/headless/selection-helpers\";\n\nexport interface TwOpaqueBlockProps {\n block: Extract<SurfaceBlockSnapshot, { kind: \"opaque_block\" }>;\n selection: SelectionSnapshot;\n onSelectionChange?: (selection: SelectionSnapshot) => void;\n workflowTargeted?: boolean;\n}\n\nconst focusRingClass =\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-2 focus-visible:ring-offset-canvas\";\n\nexport function TwOpaqueBlock(props: TwOpaqueBlockProps) {\n const { block, selection, workflowTargeted } = props;\n const selected = selectionTouchesRange(selection, block.from, block.to);\n\n return (\n <div className=\"group relative\">\n <div className=\"absolute -left-10 top-1 flex flex-col items-end gap-0 select-none w-8 text-right\">\n <div className=\"flex items-center gap-0.5\">\n <span className=\"text-[10px] text-tertiary/60 font-medium\">Lock</span>\n <span className=\"inline-block h-1 w-1 rounded-full\" style={{ backgroundColor: \"var(--color-comment)\" }} />\n </div>\n </div>\n <button\n type=\"button\"\n tabIndex={-1}\n onMouseDown={(e) => {\n e.preventDefault();\n props.onSelectionChange?.(createSelectionSnapshot(block.from, block.to));\n }}\n className={[\n \"w-full text-left border-l-2 border-dashed border-warning/30 pl-4 py-2 rounded-r bg-warning-soft/20\",\n \"cursor-pointer transition-colors\",\n selected ? \"ring-1 ring-accent/30 bg-warning-soft/40\" : \"hover:bg-warning-soft/30\",\n focusRingClass,\n ].join(\" \")}\n >\n <div className=\"flex items-center gap-1.5 text-xs text-tertiary mb-1\">\n <span>🔒</span>\n <span>{block.label}</span>\n <span className=\"inline-flex items-center px-1.5 py-0.5 rounded-full text-[10px] font-semibold text-comment bg-warning-soft\">\n preserve-only\n </span>\n {workflowTargeted && (\n <span className=\"inline-flex items-center px-1.5 py-0.5 rounded-full text-[10px] font-semibold text-amber-700 bg-amber-100\">\n workflow-targeted\n </span>\n )}\n </div>\n <p className=\"text-sm text-secondary\">{block.detail}</p>\n </button>\n </div>\n );\n}\n","import React from \"react\";\n\nimport type { SelectionSnapshot } from \"../../api/public-types\";\n\nexport function renderTwCaret(selection: SelectionSnapshot, position: number) {\n return selection.isCollapsed && selection.anchor === position ? (\n <span\n aria-hidden=\"true\"\n className=\"inline-block w-0.5 h-[1.2em] bg-accent rounded-full align-middle animate-wre-blink\"\n />\n ) : null;\n}\n","import React from \"react\";\n\nimport type { SelectionSnapshot, SurfaceInlineSegment } from \"../../api/public-types\";\nimport type { CommentDecorationModel } from \"../../ui/headless/comment-decoration-model\";\nimport { getCommentHighlightClass, type MarkupDisplay } from \"../../ui/headless/comment-decoration-model\";\nimport { createSelectionSnapshot, selectionTouchesRange } from \"../../ui/headless/selection-helpers\";\nimport { renderTwCaret } from \"./tw-caret\";\n\nexport interface TwInlineTokenProps {\n segment: SurfaceInlineSegment;\n selection: SelectionSnapshot;\n markupDisplay: MarkupDisplay;\n commentDecorations?: CommentDecorationModel;\n onSelectionChange?: (selection: SelectionSnapshot) => void;\n}\n\nconst focusRingClass =\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-2 focus-visible:ring-offset-canvas\";\n\nexport function TwInlineToken(props: TwInlineTokenProps) {\n const { segment, selection } = props;\n const selected = selectionTouchesRange(selection, segment.from, segment.to);\n const commentClass = getCommentHighlightClass(\n props.commentDecorations,\n segment.from,\n segment.to,\n props.markupDisplay,\n );\n\n const showSymbols = props.markupDisplay !== \"clean\";\n\n if (segment.kind === \"tab\") {\n return (\n <button\n type=\"button\"\n tabIndex={-1}\n onMouseDown={(e) => {\n e.preventDefault();\n props.onSelectionChange?.(createSelectionSnapshot(segment.from, segment.to));\n }}\n className={`inline-flex items-center border-none bg-transparent cursor-text ${commentClass} ${selected ? \"bg-surface-hover\" : \"\"} ${focusRingClass} ${showSymbols ? \"mx-0.5 text-tertiary/50\" : \"w-8\"}`}\n title=\"Tab character\"\n >\n {renderTwCaret(selection, segment.from)}\n {showSymbols ? <span className=\"text-xs\">→</span> : <span className=\"w-8\" />}\n {renderTwCaret(selection, segment.to)}\n </button>\n );\n }\n\n if (segment.kind === \"hard_break\") {\n return (\n <>\n <button\n type=\"button\"\n tabIndex={-1}\n onMouseDown={(e) => {\n e.preventDefault();\n props.onSelectionChange?.(createSelectionSnapshot(segment.from, segment.to));\n }}\n className={`inline-flex items-center border-none bg-transparent cursor-text ${commentClass} ${selected ? \"bg-surface-hover\" : \"\"} ${focusRingClass} ${showSymbols ? \"mx-0.5 text-tertiary/40\" : \"\"}`}\n title=\"Line break\"\n >\n {renderTwCaret(selection, segment.from)}\n {showSymbols ? <span className=\"text-xs\">↵</span> : null}\n {renderTwCaret(selection, segment.to)}\n </button>\n <br />\n </>\n );\n }\n\n if (segment.kind === \"image\") {\n const isMissing = segment.state === \"missing\";\n return (\n <button\n type=\"button\"\n tabIndex={-1}\n onMouseDown={(e) => {\n e.preventDefault();\n props.onSelectionChange?.(createSelectionSnapshot(segment.from, segment.to));\n }}\n className={`inline-flex items-center gap-1 mx-0.5 px-1.5 py-0.5 rounded text-xs border-none cursor-pointer ${commentClass} ${\n isMissing ? \"text-danger bg-delete-soft\" : \"text-secondary bg-surface\"\n } ${selected ? \"ring-1 ring-accent/30\" : \"\"} ${focusRingClass}`}\n title={segment.detail ?? segment.altText ?? \"Inline image\"}\n >\n {renderTwCaret(selection, segment.from)}\n <span>📷</span>\n {segment.altText ?? (isMissing ? \"Missing image\" : \"Image\")}\n {renderTwCaret(selection, segment.to)}\n </button>\n );\n }\n\n // opaque_inline\n if (segment.kind === \"opaque_inline\") {\n if (segment.presentation === \"quiet-marker\") {\n return (\n <span\n aria-label={segment.label}\n title={segment.detail}\n className=\"inline-block h-0 w-0 overflow-hidden align-baseline\"\n data-inline-presentation=\"quiet-marker\"\n />\n );\n }\n\n return (\n <button\n type=\"button\"\n tabIndex={-1}\n onMouseDown={(e) => {\n e.preventDefault();\n props.onSelectionChange?.(createSelectionSnapshot(segment.from, segment.to));\n }}\n className={`inline-flex items-center gap-1 mx-0.5 px-1.5 py-0.5 rounded text-xs text-comment bg-warning-soft border-none cursor-pointer ${commentClass} ${selected ? \"ring-1 ring-accent/30\" : \"\"} ${focusRingClass}`}\n title={segment.detail}\n >\n {renderTwCaret(selection, segment.from)}\n <span>🔒</span>\n {segment.label}\n {renderTwCaret(selection, segment.to)}\n </button>\n );\n }\n\n return null;\n}\n","import React from \"react\";\n\nimport type { SelectionSnapshot, SurfaceInlineSegment } from \"../../api/public-types\";\nimport type { CommentDecorationModel } from \"../../ui/headless/comment-decoration-model\";\nimport { getCommentHighlightClass, getCommentRangeState, type MarkupDisplay } from \"../../ui/headless/comment-decoration-model\";\nimport type { RevisionDecorationModel } from \"../../ui/headless/revision-decoration-model\";\nimport { getRevisionHighlightClass, shouldHideInCleanMode } from \"../../ui/headless/revision-decoration-model\";\nimport { createSelectionSnapshot, selectionTouchesRange } from \"../../ui/headless/selection-helpers\";\nimport { TwInlineToken } from \"./tw-inline-token\";\n\nexport interface TwSegmentViewProps {\n segment: SurfaceInlineSegment;\n selection: SelectionSnapshot;\n markupDisplay: MarkupDisplay;\n commentDecorations?: CommentDecorationModel;\n revisionDecorations?: RevisionDecorationModel;\n onSelectionChange?: (selection: SelectionSnapshot) => void;\n onCommentActivated?: (commentId: string) => void;\n onRevisionActivated?: (revisionId: string) => void;\n}\n\nexport function TwSegmentView(props: TwSegmentViewProps) {\n const { segment, selection, markupDisplay } = props;\n\n // Non-text segments delegate to TwInlineToken\n if (segment.kind === \"tab\" || segment.kind === \"hard_break\" || segment.kind === \"image\" || segment.kind === \"opaque_inline\") {\n return (\n <TwInlineToken\n segment={segment}\n selection={selection}\n markupDisplay={markupDisplay}\n commentDecorations={props.commentDecorations}\n onSelectionChange={props.onSelectionChange}\n />\n );\n }\n\n if (segment.kind !== \"text\") {\n return null;\n }\n\n // Text segment: render character-by-character for click-to-position editing\n const characters = Array.from(segment.text);\n\n return (\n <>\n {characters.map((character, index) => {\n const from = segment.from + index;\n const to = from + 1;\n const isSelected = selectionTouchesRange(selection, from, to);\n\n // Hide deletions in clean mode\n if (shouldHideInCleanMode(props.revisionDecorations, from, to) && markupDisplay === \"clean\") {\n return null;\n }\n\n const commentClass = getCommentHighlightClass(props.commentDecorations, from, to, markupDisplay);\n const revisionClass = getRevisionHighlightClass(props.revisionDecorations, from, to, markupDisplay);\n\n // Check if clicking this char should activate a comment or revision\n const commentState = getCommentRangeState(props.commentDecorations, from, to);\n const overlappingComment = commentState.overlapping[0];\n\n // Build mark classes\n let markClasses = \"\";\n if (segment.marks) {\n if (segment.marks.includes(\"bold\")) markClasses += \"font-bold \";\n if (segment.marks.includes(\"italic\")) markClasses += \"italic \";\n if (segment.marks.includes(\"underline\")) markClasses += \"underline \";\n if (segment.marks.includes(\"strikethrough\")) markClasses += \"line-through \";\n }\n\n const hyperlinkClass = segment.hyperlinkHref\n ? \"text-accent underline decoration-1 underline-offset-2 \"\n : \"\";\n\n return (\n <button\n key={`${segment.segmentId}-${from}`}\n type=\"button\"\n tabIndex={-1}\n onMouseDown={(event) => {\n event.preventDefault();\n props.onSelectionChange?.(createSelectionSnapshot(to));\n\n // Activate comment/revision on click if decorated\n if (overlappingComment) {\n props.onCommentActivated?.(overlappingComment.commentId);\n }\n }}\n data-comment-id={overlappingComment?.commentId}\n className={[\n \"relative inline border-none bg-transparent cursor-text whitespace-pre p-0 m-0\",\n \"text-[15px] text-primary leading-normal\",\n commentClass,\n revisionClass,\n markClasses,\n hyperlinkClass,\n isSelected ? \"bg-surface-hover rounded-[3px]\" : \"\",\n ].filter(Boolean).join(\" \")}\n >\n {character}\n {selection.isCollapsed && selection.anchor === from ? (\n <span aria-hidden=\"true\" className=\"absolute left-0 top-[0.1em] w-0.5 h-[1em] bg-accent rounded-full animate-wre-blink pointer-events-none\" />\n ) : null}\n </button>\n );\n })}\n </>\n );\n}\n","import React from \"react\";\n\nimport type { SelectionSnapshot, SurfaceBlockSnapshot, SurfaceInlineSegment } from \"../../api/public-types\";\nimport type { CommentDecorationModel } from \"../../ui/headless/comment-decoration-model\";\nimport { getCommentRangeState, type MarkupDisplay } from \"../../ui/headless/comment-decoration-model\";\nimport type { RevisionDecorationModel } from \"../../ui/headless/revision-decoration-model\";\nimport { getRevisionRangeState } from \"../../ui/headless/revision-decoration-model\";\nimport { createSelectionSnapshot } from \"../../ui/headless/selection-helpers\";\nimport { renderTwCaret } from \"./tw-caret\";\nimport { TwSegmentView } from \"./tw-segment-view\";\n\nexport interface TwParagraphBlockProps {\n block: Extract<SurfaceBlockSnapshot, { kind: \"paragraph\" }>;\n selection: SelectionSnapshot;\n markupDisplay: MarkupDisplay;\n commentDecorations?: CommentDecorationModel;\n revisionDecorations?: RevisionDecorationModel;\n onSelectionChange?: (selection: SelectionSnapshot) => void;\n onCommentActivated?: (commentId: string) => void;\n onRevisionActivated?: (revisionId: string) => void;\n}\n\nexport function TwParagraphBlock(props: TwParagraphBlockProps) {\n const { block, selection, markupDisplay } = props;\n const headingLevel = inferHeadingLevel(block.styleId);\n const hasComment = getCommentRangeState(props.commentDecorations, block.from, block.to).hasComments;\n const hasChange = getRevisionRangeState(props.revisionDecorations, block.from, block.to).hasChanges;\n\n // Margin indicator per mode\n let marginClass = \"\";\n if (markupDisplay === \"simple\" && (hasComment || hasChange)) {\n if (hasComment && hasChange) marginClass = \"border-l-2 border-l-comment/50 pl-3 \";\n else if (hasComment) marginClass = \"border-l-2 border-l-comment/40 pl-3 \";\n else marginClass = \"border-l-2 border-l-insert/40 pl-3 \";\n }\n\n // Dot markers for gutter\n const dots: string[] = [];\n if (markupDisplay === \"clean\" && hasComment) {\n dots.push(\"var(--color-comment)\");\n } else if (markupDisplay !== \"simple\") {\n if (hasComment) dots.push(\"var(--color-comment)\");\n if (hasChange) dots.push(\"var(--color-insert)\");\n }\n\n const segmentElements = (\n <>\n <CaretButton\n position={block.from}\n selection={selection}\n onSelectionChange={props.onSelectionChange}\n />\n {block.segments.length > 0 ? (\n block.segments.map((segment) => (\n <TwSegmentView\n key={segment.segmentId}\n segment={segment}\n selection={selection}\n markupDisplay={markupDisplay}\n commentDecorations={props.commentDecorations}\n revisionDecorations={props.revisionDecorations}\n onSelectionChange={props.onSelectionChange}\n onCommentActivated={props.onCommentActivated}\n onRevisionActivated={props.onRevisionActivated}\n />\n ))\n ) : (\n <span className=\"text-secondary italic\">Empty paragraph</span>\n )}\n <CaretButton\n position={block.to}\n selection={selection}\n onSelectionChange={props.onSelectionChange}\n />\n </>\n );\n\n return (\n <div className=\"group relative\">\n <BlockHint\n label={headingLevel ? `H${headingLevel}` : \"P\"}\n dots={dots.length > 0 ? dots : undefined}\n />\n {headingLevel ? (\n <div className={`${marginClass}transition-colors`}>\n <HeadingElement level={headingLevel}>{segmentElements}</HeadingElement>\n </div>\n ) : (\n <p className={`text-base leading-[1.75] text-primary ${marginClass}transition-colors`}>\n {segmentElements}\n </p>\n )}\n </div>\n );\n}\n\nfunction CaretButton(props: {\n position: number;\n selection: SelectionSnapshot;\n onSelectionChange?: (selection: SelectionSnapshot) => void;\n}) {\n const isActive = props.selection.isCollapsed && props.selection.anchor === props.position;\n return (\n <button\n type=\"button\"\n tabIndex={-1}\n onMouseDown={(e) => {\n e.preventDefault();\n props.onSelectionChange?.(createSelectionSnapshot(props.position));\n }}\n aria-label={`Set caret at ${props.position}`}\n className={`p-0 m-0 border-none bg-transparent cursor-text inline-flex items-center ${isActive ? \"min-w-[2px] h-[22px]\" : \"w-0 h-0 overflow-hidden\"}`}\n >\n {renderTwCaret(props.selection, props.position)}\n </button>\n );\n}\n\nfunction BlockHint(props: { label: string; dots?: string[] }) {\n return (\n <div className=\"absolute -left-10 top-1 flex flex-col items-end gap-0 select-none w-8 text-right\">\n <div className=\"flex items-center gap-0.5\">\n <span className=\"text-[10px] text-tertiary/60 font-medium\">{props.label}</span>\n {props.dots?.map((color, i) => (\n <span\n key={i}\n className=\"inline-block h-1 w-1 rounded-full\"\n style={{ backgroundColor: color }}\n />\n ))}\n </div>\n </div>\n );\n}\n\nfunction HeadingElement(props: { level: 1 | 2 | 3; children: React.ReactNode }) {\n switch (props.level) {\n case 1: return <h2 className=\"text-2xl font-medium text-primary leading-tight\">{props.children}</h2>;\n case 2: return <h3 className=\"text-xl font-medium text-primary leading-snug\">{props.children}</h3>;\n case 3: return <h4 className=\"text-lg font-medium text-primary leading-snug\">{props.children}</h4>;\n }\n}\n\nfunction inferHeadingLevel(styleId?: string): 1 | 2 | 3 | null {\n if (!styleId) return null;\n const lower = styleId.toLowerCase();\n if (lower === \"heading1\") return 1;\n if (lower === \"heading2\") return 2;\n if (lower === \"heading3\") return 3;\n return null;\n}\n","import type {\n DocumentRootNode,\n HyperlinkNode,\n InlineNode,\n OpaqueBlockNode,\n OpaqueInlineNode,\n ParagraphNode,\n TextMark,\n} from \"../../model/canonical-document.ts\";\n\nexport interface ParagraphProperties {\n styleId?: string;\n numbering?: ParagraphNode[\"numbering\"];\n}\n\nexport interface TextStory {\n firstParagraph: ParagraphProperties;\n units: StoryUnit[];\n size: number;\n}\n\nexport type StoryUnit =\n | TextCharacterUnit\n | TabUnit\n | HardBreakUnit\n | ImageUnit\n | OpaqueInlineUnit\n | OpaqueBlockUnit\n | ParagraphBreakUnit;\n\nexport interface TextCharacterUnit {\n kind: \"text\";\n value: string;\n marks?: TextMark[];\n hyperlinkHref?: string;\n}\n\nexport interface TabUnit {\n kind: \"tab\";\n hyperlinkHref?: string;\n}\n\nexport interface HardBreakUnit {\n kind: \"hard_break\";\n hyperlinkHref?: string;\n}\n\nexport interface ImageUnit {\n kind: \"image\";\n mediaId: string;\n altText?: string;\n}\n\nexport interface OpaqueInlineUnit {\n kind: \"opaque_inline\";\n fragmentId: string;\n warningId: string;\n}\n\nexport interface OpaqueBlockUnit {\n kind: \"opaque_block\";\n fragmentId: string;\n warningId: string;\n nextParagraph?: ParagraphProperties;\n}\n\nexport interface ParagraphBreakUnit {\n kind: \"paragraph_break\";\n nextParagraph: ParagraphProperties;\n}\n\nexport function parseTextStory(content: unknown): TextStory {\n const root = normalizeDocumentRoot(content);\n const firstParagraphNode = root.children.find(isParagraphNode);\n const firstParagraph = firstParagraphNode\n ? extractParagraphProperties(firstParagraphNode)\n : cloneParagraphProperties(EMPTY_PARAGRAPH_PROPERTIES);\n const units: StoryUnit[] = [];\n\n for (let index = 0; index < root.children.length; index += 1) {\n const block = root.children[index];\n const nextBlock = root.children[index + 1];\n\n if (isParagraphNode(block)) {\n units.push(...flattenInlineNodes(block.children));\n\n if (isParagraphNode(nextBlock)) {\n units.push({\n kind: \"paragraph_break\",\n nextParagraph: extractParagraphProperties(nextBlock),\n });\n }\n\n continue;\n }\n\n if (block.type !== \"opaque_block\") {\n continue;\n }\n\n units.push({\n kind: \"opaque_block\",\n fragmentId: block.fragmentId,\n warningId: block.warningId,\n ...(isParagraphNode(nextBlock)\n ? { nextParagraph: extractParagraphProperties(nextBlock) }\n : {}),\n });\n }\n\n return {\n firstParagraph,\n units,\n size: units.length,\n };\n}\n\nexport function serializeTextStory(story: TextStory): DocumentRootNode {\n const blocks: Array<ParagraphNode | OpaqueBlockNode> = [];\n let currentParagraph: ParagraphNode | undefined = createParagraph(story.firstParagraph);\n let currentHyperlink: HyperlinkNode | undefined;\n let activeTextBuffer:\n | {\n text: string;\n marks?: TextMark[];\n hyperlinkHref?: string;\n }\n | undefined;\n\n const ensureCurrentParagraph = () => {\n if (!currentParagraph) {\n currentParagraph = createParagraph(EMPTY_PARAGRAPH_PROPERTIES);\n }\n };\n\n const flushTextBuffer = () => {\n if (!activeTextBuffer || activeTextBuffer.text.length === 0) {\n activeTextBuffer = undefined;\n return;\n }\n\n const textNode = {\n type: \"text\" as const,\n text: activeTextBuffer.text,\n ...(activeTextBuffer.marks ? { marks: cloneMarks(activeTextBuffer.marks) } : {}),\n };\n\n ensureCurrentParagraph();\n\n if (activeTextBuffer.hyperlinkHref) {\n if (!currentHyperlink || currentHyperlink.href !== activeTextBuffer.hyperlinkHref) {\n flushHyperlink();\n currentHyperlink = {\n type: \"hyperlink\",\n href: activeTextBuffer.hyperlinkHref,\n children: [],\n };\n }\n\n currentHyperlink.children.push(textNode);\n } else {\n flushHyperlink();\n currentParagraph!.children.push(textNode);\n }\n\n activeTextBuffer = undefined;\n };\n\n const flushHyperlink = () => {\n if (currentHyperlink) {\n ensureCurrentParagraph();\n currentParagraph!.children.push(currentHyperlink);\n currentHyperlink = undefined;\n }\n };\n\n const flushParagraph = () => {\n flushTextBuffer();\n flushHyperlink();\n\n if (!currentParagraph) {\n return;\n }\n\n blocks.push(currentParagraph);\n currentParagraph = undefined;\n };\n\n const pushInlineNode = (\n node: Exclude<InlineNode, { type: \"text\" }>,\n hyperlinkHref?: string,\n ) => {\n flushTextBuffer();\n ensureCurrentParagraph();\n\n if (hyperlinkHref) {\n if (!currentHyperlink || currentHyperlink.href !== hyperlinkHref) {\n flushHyperlink();\n currentHyperlink = {\n type: \"hyperlink\",\n href: hyperlinkHref,\n children: [],\n };\n }\n\n currentHyperlink.children.push(node as HyperlinkNode[\"children\"][number]);\n return;\n }\n\n flushHyperlink();\n currentParagraph!.children.push(node);\n };\n\n for (const unit of story.units) {\n if (unit.kind === \"paragraph_break\") {\n flushParagraph();\n currentParagraph = createParagraph(unit.nextParagraph);\n continue;\n }\n\n if (unit.kind === \"opaque_block\") {\n flushParagraph();\n blocks.push({\n type: \"opaque_block\",\n fragmentId: unit.fragmentId,\n warningId: unit.warningId,\n });\n currentParagraph = unit.nextParagraph\n ? createParagraph(unit.nextParagraph)\n : undefined;\n continue;\n }\n\n if (unit.kind === \"text\") {\n const shouldExtendBuffer =\n activeTextBuffer &&\n activeTextBuffer.hyperlinkHref === unit.hyperlinkHref &&\n haveEqualMarks(activeTextBuffer.marks, unit.marks);\n\n if (shouldExtendBuffer && activeTextBuffer) {\n activeTextBuffer.text += unit.value;\n } else {\n flushTextBuffer();\n activeTextBuffer = {\n text: unit.value,\n ...(unit.marks ? { marks: cloneMarks(unit.marks) } : {}),\n ...(unit.hyperlinkHref ? { hyperlinkHref: unit.hyperlinkHref } : {}),\n };\n }\n\n continue;\n }\n\n switch (unit.kind) {\n case \"tab\":\n pushInlineNode({ type: \"tab\" }, unit.hyperlinkHref);\n break;\n case \"hard_break\":\n pushInlineNode({ type: \"hard_break\" }, unit.hyperlinkHref);\n break;\n case \"image\":\n pushInlineNode({\n type: \"image\",\n mediaId: unit.mediaId,\n ...(unit.altText ? { altText: unit.altText } : {}),\n });\n break;\n case \"opaque_inline\":\n pushInlineNode({\n type: \"opaque_inline\",\n fragmentId: unit.fragmentId,\n warningId: unit.warningId,\n });\n break;\n }\n }\n\n flushParagraph();\n\n if (blocks.length === 0) {\n blocks.push(createParagraph(story.firstParagraph));\n }\n\n return {\n type: \"doc\",\n children: blocks,\n };\n}\n\nexport function createPlainText(story: TextStory): string {\n return story.units\n .map((unit) => {\n switch (unit.kind) {\n case \"text\":\n return unit.value;\n case \"tab\":\n return \"\\t\";\n case \"hard_break\":\n return \"\\n\";\n case \"paragraph_break\":\n return \"\\n\";\n case \"image\":\n return \"\\uFFFC\";\n case \"opaque_inline\":\n return \"\\uFFF9\";\n case \"opaque_block\":\n return \"\\uFFFA\";\n }\n })\n .join(\"\");\n}\n\nexport function cloneStoryUnit(unit: StoryUnit): StoryUnit {\n switch (unit.kind) {\n case \"text\":\n return {\n kind: \"text\",\n value: unit.value,\n ...(unit.marks ? { marks: cloneMarks(unit.marks) } : {}),\n ...(unit.hyperlinkHref ? { hyperlinkHref: unit.hyperlinkHref } : {}),\n };\n case \"tab\":\n return {\n kind: \"tab\",\n ...(unit.hyperlinkHref ? { hyperlinkHref: unit.hyperlinkHref } : {}),\n };\n case \"hard_break\":\n return {\n kind: \"hard_break\",\n ...(unit.hyperlinkHref ? { hyperlinkHref: unit.hyperlinkHref } : {}),\n };\n case \"image\":\n return {\n kind: \"image\",\n mediaId: unit.mediaId,\n ...(unit.altText ? { altText: unit.altText } : {}),\n };\n case \"opaque_inline\":\n return {\n kind: \"opaque_inline\",\n fragmentId: unit.fragmentId,\n warningId: unit.warningId,\n };\n case \"opaque_block\":\n return {\n kind: \"opaque_block\",\n fragmentId: unit.fragmentId,\n warningId: unit.warningId,\n ...(unit.nextParagraph\n ? { nextParagraph: cloneParagraphProperties(unit.nextParagraph) }\n : {}),\n };\n case \"paragraph_break\":\n return {\n kind: \"paragraph_break\",\n nextParagraph: cloneParagraphProperties(unit.nextParagraph),\n };\n }\n}\n\nexport function cloneParagraphProperties(\n properties: ParagraphProperties,\n): ParagraphProperties {\n return {\n ...(properties.styleId ? { styleId: properties.styleId } : {}),\n ...(properties.numbering\n ? {\n numbering: {\n numberingInstanceId: properties.numbering.numberingInstanceId,\n level: properties.numbering.level,\n },\n }\n : {}),\n };\n}\n\nfunction normalizeDocumentRoot(content: unknown): DocumentRootNode {\n if (isDocumentRootNode(content)) {\n return content;\n }\n\n if (Array.isArray(content)) {\n return {\n type: \"doc\",\n children: content.filter(\n (block): block is DocumentRootNode[\"children\"][number] =>\n isParagraphNode(block) || isOpaqueBlockNode(block),\n ),\n };\n }\n\n return {\n type: \"doc\",\n children: [createEmptyParagraph()],\n };\n}\n\nfunction flattenInlineNodes(\n nodes: ParagraphNode[\"children\"],\n hyperlinkHref?: string,\n): StoryUnit[] {\n const units: StoryUnit[] = [];\n\n for (const node of nodes) {\n switch (node.type) {\n case \"text\":\n for (const character of Array.from(node.text)) {\n units.push({\n kind: \"text\",\n value: character,\n ...(node.marks ? { marks: cloneMarks(node.marks) } : {}),\n ...(hyperlinkHref ? { hyperlinkHref } : {}),\n });\n }\n break;\n case \"tab\":\n units.push({\n kind: \"tab\",\n ...(hyperlinkHref ? { hyperlinkHref } : {}),\n });\n break;\n case \"hard_break\":\n units.push({\n kind: \"hard_break\",\n ...(hyperlinkHref ? { hyperlinkHref } : {}),\n });\n break;\n case \"hyperlink\":\n units.push(...flattenInlineNodes(node.children, node.href));\n break;\n case \"image\":\n units.push({\n kind: \"image\",\n mediaId: node.mediaId,\n ...(node.altText ? { altText: node.altText } : {}),\n });\n break;\n case \"opaque_inline\":\n units.push({\n kind: \"opaque_inline\",\n fragmentId: node.fragmentId,\n warningId: node.warningId,\n });\n break;\n }\n }\n\n return units;\n}\n\nfunction extractParagraphProperties(paragraph: ParagraphNode): ParagraphProperties {\n return {\n ...(paragraph.styleId ? { styleId: paragraph.styleId } : {}),\n ...(paragraph.numbering\n ? {\n numbering: {\n numberingInstanceId: paragraph.numbering.numberingInstanceId,\n level: paragraph.numbering.level,\n },\n }\n : {}),\n };\n}\n\nfunction createParagraph(properties: ParagraphProperties): ParagraphNode {\n return {\n type: \"paragraph\",\n ...(properties.styleId ? { styleId: properties.styleId } : {}),\n ...(properties.numbering\n ? {\n numbering: {\n numberingInstanceId: properties.numbering.numberingInstanceId,\n level: properties.numbering.level,\n },\n }\n : {}),\n children: [],\n };\n}\n\nfunction createEmptyParagraph(): ParagraphNode {\n return {\n type: \"paragraph\",\n children: [],\n };\n}\n\nconst EMPTY_PARAGRAPH_PROPERTIES: ParagraphProperties = {};\n\nfunction cloneMarks(marks: TextMark[]): TextMark[] {\n return marks.map((mark) => ({ ...mark }));\n}\n\nfunction haveEqualMarks(left?: TextMark[], right?: TextMark[]): boolean {\n if (!left && !right) {\n return true;\n }\n\n if (!left || !right || left.length !== right.length) {\n return false;\n }\n\n return left.every((mark, index) => mark.type === right[index]?.type);\n}\n\nfunction isDocumentRootNode(value: unknown): value is DocumentRootNode {\n return Boolean(value) && typeof value === \"object\" && (value as { type?: string }).type === \"doc\";\n}\n\nfunction isParagraphNode(value: unknown): value is ParagraphNode {\n return Boolean(value) && typeof value === \"object\" && (value as { type?: string }).type === \"paragraph\";\n}\n\nfunction isOpaqueBlockNode(value: unknown): value is OpaqueBlockNode {\n return Boolean(value) && typeof value === \"object\" && (value as { type?: string }).type === \"opaque_block\";\n}\n","import { parseTextStory } from \"../schema/text-schema.ts\";\nimport {\n DEFAULT_BOUNDARY_ASSOC,\n createDetachedAnchor,\n createRangeAnchor,\n mapAnchor,\n normalizeRange,\n type BoundaryAssoc,\n type DetachedAnchor,\n type DocRange,\n type EditorAnchorProjection,\n type TransactionMapping,\n} from \"./mapping.ts\";\n\nexport type ReviewAnchor = EditorAnchorProjection;\n\nexport const COMMENT_RANGE_ASSOC: BoundaryAssoc = DEFAULT_BOUNDARY_ASSOC;\n\nexport function createCommentReviewAnchor(\n from: number,\n to = from,\n assoc: BoundaryAssoc = COMMENT_RANGE_ASSOC,\n): ReviewAnchor {\n return createRangeAnchor(from, to, assoc);\n}\n\nexport function detachReviewAnchor(\n lastKnownRange: DocRange,\n reason: DetachedAnchor[\"reason\"],\n): DetachedAnchor {\n return createDetachedAnchor(lastKnownRange, reason);\n}\n\nexport function mapReviewAnchor(\n anchor: ReviewAnchor,\n mapping: TransactionMapping,\n): ReviewAnchor {\n return mapAnchor(anchor, mapping);\n}\n\nexport function getAnchorRange(anchor: ReviewAnchor): DocRange {\n if (anchor.kind === \"range\") {\n return normalizeRange(anchor.range);\n }\n\n if (anchor.kind === \"node\") {\n return { from: anchor.at, to: anchor.at };\n }\n\n return normalizeRange(anchor.lastKnownRange);\n}\n\nexport function mappingTouchesAnchorContent(\n anchor: ReviewAnchor,\n mapping: TransactionMapping,\n): boolean {\n const range = getAnchorRange(anchor);\n\n if (range.from === range.to) {\n return mapping.steps.some(\n (step) => step.from <= range.from && step.to >= range.to,\n );\n }\n\n return mapping.steps.some(\n (step) => step.from < range.to && step.to > range.from,\n );\n}\n\nexport function rangeStaysWithinSingleParagraph(\n content: unknown,\n range: DocRange,\n): boolean {\n const normalized = normalizeRange(range);\n if (normalized.from === normalized.to) {\n return true;\n }\n\n const surfaceBlocks = readSurfaceBlocks(content);\n if (surfaceBlocks) {\n return surfaceBlocks.some(\n (block) =>\n block.kind === \"paragraph\" &&\n normalized.from >= block.from &&\n normalized.to <= block.to,\n );\n }\n\n const story = parseTextStory(content);\n const upperBound = Math.min(normalized.to, story.units.length);\n\n for (let index = Math.max(0, normalized.from); index < upperBound; index += 1) {\n const unit = story.units[index];\n if (!unit) {\n continue;\n }\n\n if (unit.kind === \"paragraph_break\" || unit.kind === \"opaque_block\") {\n return false;\n }\n }\n\n return true;\n}\n\nexport function canCreateDocxCommentAnchor(\n content: unknown,\n anchor: ReviewAnchor,\n): boolean {\n if (anchor.kind !== \"range\") {\n return false;\n }\n\n const normalized = normalizeRange(anchor.range);\n if (normalized.from === normalized.to) {\n return false;\n }\n\n return rangeStaysWithinSingleParagraph(content, normalized);\n}\n\nfunction readSurfaceBlocks(\n content: unknown,\n): Array<{ kind: string; from: number; to: number }> | undefined {\n if (!content || typeof content !== \"object\" || !(\"blocks\" in content)) {\n return undefined;\n }\n\n const blocks = (content as { blocks?: unknown }).blocks;\n if (!Array.isArray(blocks)) {\n return undefined;\n }\n\n const normalized = flattenSurfaceBlocks(blocks);\n\n return normalized.length > 0 ? normalized : undefined;\n}\n\nfunction flattenSurfaceBlocks(\n blocks: unknown[],\n): Array<{ kind: string; from: number; to: number }> {\n const flattened: Array<{ kind: string; from: number; to: number }> = [];\n\n for (const block of blocks) {\n if (\n !block ||\n typeof block !== \"object\" ||\n typeof (block as { kind?: unknown }).kind !== \"string\" ||\n typeof (block as { from?: unknown }).from !== \"number\" ||\n typeof (block as { to?: unknown }).to !== \"number\"\n ) {\n continue;\n }\n\n flattened.push({\n kind: (block as { kind: string }).kind,\n from: (block as { from: number }).from,\n to: (block as { to: number }).to,\n });\n\n if (\n (block as { kind: string }).kind === \"table\" &&\n Array.isArray((block as { rows?: unknown }).rows)\n ) {\n for (const row of (block as { rows: Array<{ cells?: unknown[] }> }).rows) {\n for (const cell of row.cells ?? []) {\n if (cell && typeof cell === \"object\" && Array.isArray((cell as { content?: unknown[] }).content)) {\n flattened.push(...flattenSurfaceBlocks((cell as { content: unknown[] }).content));\n }\n }\n }\n }\n\n if (\n (block as { kind: string }).kind === \"sdt_block\" &&\n Array.isArray((block as { children?: unknown[] }).children)\n ) {\n flattened.push(...flattenSurfaceBlocks((block as { children: unknown[] }).children));\n }\n }\n\n return flattened;\n}\n","import type { RuntimeRenderSnapshot, WorkflowScopeSnapshot } from \"../api/public-types\";\nimport {\n createDetachedAnchor,\n createNodeAnchor,\n createRangeAnchor,\n} from \"../core/selection/mapping.ts\";\nimport { canCreateDocxCommentAnchor } from \"../core/selection/review-anchors\";\n\n/**\n * Session capabilities derived from the runtime snapshot.\n *\n * All fields are computed from `RuntimeRenderSnapshot` — no local component\n * state. The UI reads these to decide what controls to enable/disable, what\n * chrome to show, and what mode the editor is in.\n */\nexport interface SessionCapabilities {\n // ── Session phase ──\n /** Current lifecycle phase of the editor session. */\n phase: \"loading\" | \"ready\" | \"diagnostics\" | \"error\";\n\n /** Effective editor mode after accounting for runtime state. */\n mode: \"editing\" | \"review\" | \"read-only-diagnostics\";\n\n // ── Document mode ──\n /** Runtime document mode — editing authority, distinct from view/workspace mode. */\n documentMode: \"editing\" | \"suggesting\" | \"viewing\";\n\n // ── Command capabilities ──\n canUndo: boolean;\n canRedo: boolean;\n canEdit: boolean;\n canAddComment: boolean;\n canExport: boolean;\n canAcceptChange: boolean;\n canRejectChange: boolean;\n canAcceptAll: boolean;\n canRejectAll: boolean;\n\n // ── Review visibility ──\n /** Whether the review rail should be visible by default. */\n reviewRailVisible: boolean;\n\n /** Whether tracked changes exist in the document (display toggle is meaningful). */\n trackChangesSupported: boolean;\n\n // ── Trust posture ──\n exportBlocked: boolean;\n preserveOnlyCount: number;\n unsupportedFatalCount: number;\n\n // ── Protection posture ──\n /** Whether the source package declares document-level protection. */\n hasDocumentProtection: boolean;\n /** Count of permission ranges from the source package. */\n protectedRangeCount: number;\n\n // ── Health ──\n /** Total count of health issues (preserve-only + unsupported-fatal + warnings). */\n healthIssueCount: number;\n\n // ── Workflow ──\n /** Whether a workflow overlay is currently applied. */\n workflowOverlayPresent: boolean;\n /** Whether the current selection is blocked by workflow scope enforcement. */\n workflowBlocked: boolean;\n\n // ── Status ──\n isDirty: boolean;\n isReady: boolean;\n hasFatalError: boolean;\n}\n\n/**\n * Derive UI capabilities from the runtime snapshot and requested review mode.\n *\n * This is a pure function with no side effects. Call it on every render to\n * get the current capability state.\n */\nexport function deriveCapabilities(\n snapshot: RuntimeRenderSnapshot,\n reviewMode: \"editing\" | \"review\",\n workflowScope?: WorkflowScopeSnapshot | null,\n): SessionCapabilities {\n const hasFatalError = Boolean(snapshot.fatalError);\n const isReady = snapshot.isReady;\n const isReadOnly = snapshot.readOnly;\n const exportBlocked = snapshot.compatibility.blockExport;\n const activeStory = snapshot.activeStory ?? { kind: \"main\" as const };\n const documentMode = snapshot.documentMode ?? \"editing\";\n\n // Phase derivation\n const phase: SessionCapabilities[\"phase\"] = !isReady\n ? \"loading\"\n : hasFatalError\n ? \"diagnostics\"\n : \"ready\";\n\n // Mode derivation: if diagnostics or read-only, override the requested mode\n const mode: SessionCapabilities[\"mode\"] =\n phase === \"diagnostics\"\n ? \"read-only-diagnostics\"\n : reviewMode;\n\n // Command capabilities — document mode \"viewing\" disables editing\n const canEdit = isReady && !isReadOnly && !hasFatalError && documentMode !== \"viewing\";\n const canUndo = snapshot.commandState.canUndo && canEdit;\n const canRedo = snapshot.commandState.canRedo && canEdit;\n const canAddComment =\n canEdit &&\n activeStory.kind === \"main\" &&\n !snapshot.selection.isCollapsed &&\n Boolean(snapshot.surface) &&\n canCreateDocxCommentAnchor(snapshot.surface, toRuntimeAnchor(snapshot.selection.activeRange));\n const canExport = isReady && !exportBlocked && !hasFatalError;\n\n // Revision capabilities\n const actionableRevisions = snapshot.trackedChanges.revisions.filter(\n (r) => r.status === \"active\" && r.actionability === \"actionable\",\n );\n const canAcceptChange = canEdit && actionableRevisions.some((r) => r.canAccept);\n const canRejectChange = canEdit && actionableRevisions.some((r) => r.canReject);\n const canAcceptAll = canEdit && actionableRevisions.length > 0;\n const canRejectAll = canEdit && actionableRevisions.length > 0;\n\n // Trust posture (computed before review visibility since it depends on these)\n const preserveOnlyCount = snapshot.compatibility.featureEntries.filter(\n (e) => e.featureClass === \"preserve-only\",\n ).length;\n const unsupportedFatalCount = snapshot.compatibility.featureEntries.filter(\n (e) => e.featureClass === \"unsupported-fatal\",\n ).length;\n const workflowOverlayPresent = workflowScope?.overlayPresent ?? false;\n const workflowBlocked = (workflowScope?.blockedReasons?.length ?? 0) > 0;\n\n // Review visibility\n const trackChangesSupported = snapshot.trackedChanges.totalCount > 0;\n // Rail visible in review/diagnostics mode always.\n // In editing mode, rail stays visible when there are trust/health concerns\n // that the user must be able to reach (per DESIGN.md: health/trust info\n // stays reachable in both modes).\n const hasTrustConcerns = exportBlocked || preserveOnlyCount > 0 || unsupportedFatalCount > 0\n || snapshot.warnings.length > 0 || hasFatalError;\n const reviewRailVisible = workflowOverlayPresent\n ? false\n : mode === \"review\" || mode === \"read-only-diagnostics\"\n || (mode === \"editing\" && hasTrustConcerns);\n\n const healthIssueCount = preserveOnlyCount + unsupportedFatalCount + snapshot.warnings.length;\n\n const protection = snapshot.protectionSnapshot;\n const hasDocumentProtection = protection?.hasDocumentProtection ?? false;\n const protectedRangeCount = protection?.ranges?.length ?? 0;\n\n return {\n phase,\n mode,\n documentMode,\n canUndo,\n canRedo,\n canEdit,\n canAddComment,\n canExport,\n canAcceptChange,\n canRejectChange,\n canAcceptAll,\n canRejectAll,\n reviewRailVisible,\n trackChangesSupported,\n exportBlocked,\n preserveOnlyCount,\n unsupportedFatalCount,\n hasDocumentProtection,\n protectedRangeCount,\n healthIssueCount,\n workflowOverlayPresent,\n workflowBlocked,\n isDirty: snapshot.isDirty,\n isReady,\n hasFatalError,\n };\n}\n\nfunction toRuntimeAnchor(anchor: RuntimeRenderSnapshot[\"selection\"][\"activeRange\"]) {\n switch (anchor.kind) {\n case \"range\":\n return createRangeAnchor(anchor.from, anchor.to, anchor.assoc);\n case \"node\":\n return createNodeAnchor(anchor.at, anchor.assoc);\n case \"detached\":\n return createDetachedAnchor(anchor.lastKnownRange, anchor.reason);\n }\n}\n"],"mappings":"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","names":["import_react","Tooltip","import_lucide_react","import_jsx_runtime","import_jsx_runtime","ToolbarButton","import_jsx_runtime","import_jsx_runtime","import_react","import_lucide_react","import_jsx_runtime","TwSelectionToolbar","Tooltip","import_lucide_react","import_jsx_runtime","focusRingClass","import_jsx_runtime","ToolbarButton","import_react","import_lucide_react","import_jsx_runtime","focusRingClass","import_lucide_react","import_jsx_runtime","focusRingClass","import_jsx_runtime","focusRingClass","import_jsx_runtime","import_react","Tooltip","import_lucide_react","import_lucide_react","import_jsx_runtime","Tooltip","import_jsx_runtime","focusRingClass","import_jsx_runtime","focusRingClass","React","import_jsx_runtime","import_react","import_jsx_runtime","focusRingClass","import_jsx_runtime","import_jsx_runtime","focusRingClass","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime"]}