@voithos-labs/aragonite 0.10.1

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 (900) hide show
  1. package/LICENSE +661 -0
  2. package/README.md +365 -0
  3. package/THIRD-PARTY-NOTICES.md +102 -0
  4. package/dist/a11y-strings.d.ts +46 -0
  5. package/dist/a11y-strings.js +62 -0
  6. package/dist/action-contracts.d.ts +301 -0
  7. package/dist/action-contracts.js +5 -0
  8. package/dist/active-editor.d.ts +16 -0
  9. package/dist/active-editor.js +67 -0
  10. package/dist/ambient/ambient-cursor.d.ts +41 -0
  11. package/dist/ambient/ambient-cursor.js +120 -0
  12. package/dist/ambient/ambient-dom.d.ts +9 -0
  13. package/dist/ambient/ambient-dom.js +102 -0
  14. package/dist/assert.d.ts +6 -0
  15. package/dist/assert.js +17 -0
  16. package/dist/block-component.d.ts +274 -0
  17. package/dist/block-component.js +43 -0
  18. package/dist/block-id.d.ts +14 -0
  19. package/dist/block-id.js +34 -0
  20. package/dist/bounded-memo.d.ts +14 -0
  21. package/dist/bounded-memo.js +32 -0
  22. package/dist/components/BlockDragHandle.svelte +66 -0
  23. package/dist/components/BlockDragHandle.svelte.d.ts +18 -0
  24. package/dist/components/BlockHost.svelte +328 -0
  25. package/dist/components/BlockHost.svelte.d.ts +15 -0
  26. package/dist/components/BlockList.svelte +114 -0
  27. package/dist/components/BlockList.svelte.d.ts +16 -0
  28. package/dist/components/DecorationOverlay.svelte +156 -0
  29. package/dist/components/DecorationOverlay.svelte.d.ts +14 -0
  30. package/dist/components/Editor.svelte +1849 -0
  31. package/dist/components/Editor.svelte.d.ts +49 -0
  32. package/dist/components/GapCaret.svelte +226 -0
  33. package/dist/components/GapCaret.svelte.d.ts +9 -0
  34. package/dist/components/SearchBar.svelte +243 -0
  35. package/dist/components/SearchBar.svelte.d.ts +7 -0
  36. package/dist/components/SelectionOverlay.svelte +171 -0
  37. package/dist/components/SelectionOverlay.svelte.d.ts +14 -0
  38. package/dist/components/block-content-selector.d.ts +12 -0
  39. package/dist/components/block-content-selector.js +12 -0
  40. package/dist/components/blocks/BlockquoteBlock.svelte +32 -0
  41. package/dist/components/blocks/BlockquoteBlock.svelte.d.ts +11 -0
  42. package/dist/components/blocks/ThematicBreakBlock.svelte +156 -0
  43. package/dist/components/blocks/ThematicBreakBlock.svelte.d.ts +17 -0
  44. package/dist/components/blocks/code/CodeBlock.svelte +726 -0
  45. package/dist/components/blocks/code/CodeBlock.svelte.d.ts +23 -0
  46. package/dist/components/blocks/code/CodeLanguageChip.svelte +127 -0
  47. package/dist/components/blocks/code/CodeLanguageChip.svelte.d.ts +14 -0
  48. package/dist/components/blocks/code/code-beforeinput.d.ts +30 -0
  49. package/dist/components/blocks/code/code-beforeinput.js +40 -0
  50. package/dist/components/blocks/code/code-bootstrap.d.ts +8 -0
  51. package/dist/components/blocks/code/code-bootstrap.js +54 -0
  52. package/dist/components/blocks/code/code-editing.d.ts +28 -0
  53. package/dist/components/blocks/code/code-editing.js +79 -0
  54. package/dist/components/blocks/code/code-enter.d.ts +22 -0
  55. package/dist/components/blocks/code/code-enter.js +19 -0
  56. package/dist/components/blocks/code/code-fence-boundary.d.ts +77 -0
  57. package/dist/components/blocks/code/code-fence-boundary.js +169 -0
  58. package/dist/components/blocks/code/code-fence-exit.d.ts +24 -0
  59. package/dist/components/blocks/code/code-fence-exit.js +36 -0
  60. package/dist/components/blocks/code/code-indent.d.ts +14 -0
  61. package/dist/components/blocks/code/code-indent.js +87 -0
  62. package/dist/components/blocks/code/code-languages.d.ts +15 -0
  63. package/dist/components/blocks/code/code-languages.js +30 -0
  64. package/dist/components/blocks/code/code-paste-surface.d.ts +6 -0
  65. package/dist/components/blocks/code/code-paste-surface.js +29 -0
  66. package/dist/components/blocks/code/code-paste.d.ts +24 -0
  67. package/dist/components/blocks/code/code-paste.js +21 -0
  68. package/dist/components/blocks/code/code-renderer.d.ts +18 -0
  69. package/dist/components/blocks/code/code-renderer.js +249 -0
  70. package/dist/components/blocks/directive/DirectiveContainerBlock.svelte +51 -0
  71. package/dist/components/blocks/directive/DirectiveContainerBlock.svelte.d.ts +11 -0
  72. package/dist/components/blocks/directive/activate-directives.d.ts +7 -0
  73. package/dist/components/blocks/directive/activate-directives.js +23 -0
  74. package/dist/components/blocks/editable-leaf.d.ts +126 -0
  75. package/dist/components/blocks/editable-leaf.js +410 -0
  76. package/dist/components/blocks/editable-surface.d.ts +209 -0
  77. package/dist/components/blocks/editable-surface.js +331 -0
  78. package/dist/components/blocks/list/ListBlock.svelte +162 -0
  79. package/dist/components/blocks/list/ListBlock.svelte.d.ts +11 -0
  80. package/dist/components/blocks/list/ListItemBlock.svelte +324 -0
  81. package/dist/components/blocks/list/ListItemBlock.svelte.d.ts +14 -0
  82. package/dist/components/blocks/list/task-checkbox.d.ts +3 -0
  83. package/dist/components/blocks/list/task-checkbox.js +33 -0
  84. package/dist/components/blocks/plain-text-backend.d.ts +21 -0
  85. package/dist/components/blocks/plain-text-backend.js +47 -0
  86. package/dist/components/blocks/surface-wiring.svelte.d.ts +18 -0
  87. package/dist/components/blocks/surface-wiring.svelte.js +68 -0
  88. package/dist/components/blocks/table/TableActionMenu.svelte +267 -0
  89. package/dist/components/blocks/table/TableActionMenu.svelte.d.ts +15 -0
  90. package/dist/components/blocks/table/TableBlock.svelte +765 -0
  91. package/dist/components/blocks/table/TableBlock.svelte.d.ts +30 -0
  92. package/dist/components/blocks/table/TableCellBlock.svelte +1075 -0
  93. package/dist/components/blocks/table/TableCellBlock.svelte.d.ts +30 -0
  94. package/dist/components/blocks/table/TableGrip.svelte +91 -0
  95. package/dist/components/blocks/table/TableGrip.svelte.d.ts +8 -0
  96. package/dist/components/blocks/table/TableRowBlock.svelte +233 -0
  97. package/dist/components/blocks/table/TableRowBlock.svelte.d.ts +34 -0
  98. package/dist/components/blocks/table/cell-clipboard.d.ts +23 -0
  99. package/dist/components/blocks/table/cell-clipboard.js +34 -0
  100. package/dist/components/blocks/table/cell-keydown-plan.d.ts +37 -0
  101. package/dist/components/blocks/table/cell-keydown-plan.js +66 -0
  102. package/dist/components/blocks/table/cell-pointer.d.ts +58 -0
  103. package/dist/components/blocks/table/cell-pointer.js +153 -0
  104. package/dist/components/blocks/table/cell-render.d.ts +51 -0
  105. package/dist/components/blocks/table/cell-render.js +98 -0
  106. package/dist/components/blocks/table/cell-table-commands.d.ts +12 -0
  107. package/dist/components/blocks/table/cell-table-commands.js +21 -0
  108. package/dist/components/blocks/table/cell-x-mapping.d.ts +6 -0
  109. package/dist/components/blocks/table/cell-x-mapping.js +16 -0
  110. package/dist/components/blocks/table/selected-cells.d.ts +19 -0
  111. package/dist/components/blocks/table/selected-cells.js +35 -0
  112. package/dist/components/blocks/table/table-caret-at-point.d.ts +8 -0
  113. package/dist/components/blocks/table/table-caret-at-point.js +35 -0
  114. package/dist/components/blocks/table/table-cell-paste.d.ts +16 -0
  115. package/dist/components/blocks/table/table-cell-paste.js +75 -0
  116. package/dist/components/blocks/table/table-drag-hit-test.d.ts +5 -0
  117. package/dist/components/blocks/table/table-drag-hit-test.js +20 -0
  118. package/dist/components/blocks/table/table-drop-target.d.ts +1 -0
  119. package/dist/components/blocks/table/table-drop-target.js +16 -0
  120. package/dist/components/blocks/table/table-menu-model.d.ts +52 -0
  121. package/dist/components/blocks/table/table-menu-model.js +78 -0
  122. package/dist/components/blocks/table/table-navigation.d.ts +8 -0
  123. package/dist/components/blocks/table/table-navigation.js +22 -0
  124. package/dist/components/blocks/table/table-reorder-drag.d.ts +78 -0
  125. package/dist/components/blocks/table/table-reorder-drag.js +97 -0
  126. package/dist/components/blocks/text/TextEditableBlock.svelte +1012 -0
  127. package/dist/components/blocks/text/TextEditableBlock.svelte.d.ts +33 -0
  128. package/dist/components/blocks/text/click-snap-guard.d.ts +8 -0
  129. package/dist/components/blocks/text/click-snap-guard.js +19 -0
  130. package/dist/components/blocks/text/composition-seat.d.ts +50 -0
  131. package/dist/components/blocks/text/composition-seat.js +65 -0
  132. package/dist/components/blocks/text/construct-edge-delete.d.ts +47 -0
  133. package/dist/components/blocks/text/construct-edge-delete.js +164 -0
  134. package/dist/components/blocks/text/construct-reveal.d.ts +39 -0
  135. package/dist/components/blocks/text/construct-reveal.js +164 -0
  136. package/dist/components/blocks/text/edge-policy-dispatch.d.ts +91 -0
  137. package/dist/components/blocks/text/edge-policy-dispatch.js +457 -0
  138. package/dist/components/blocks/text/edge-seat.d.ts +42 -0
  139. package/dist/components/blocks/text/edge-seat.js +197 -0
  140. package/dist/components/blocks/text/hidden-suffix.d.ts +10 -0
  141. package/dist/components/blocks/text/hidden-suffix.js +15 -0
  142. package/dist/components/blocks/text/link-at-point.d.ts +33 -0
  143. package/dist/components/blocks/text/link-at-point.js +47 -0
  144. package/dist/components/blocks/text/link-source-bytes.d.ts +37 -0
  145. package/dist/components/blocks/text/link-source-bytes.js +161 -0
  146. package/dist/components/blocks/text/live-join-seam.d.ts +15 -0
  147. package/dist/components/blocks/text/live-join-seam.js +327 -0
  148. package/dist/components/blocks/text/live-selection-edit.d.ts +68 -0
  149. package/dist/components/blocks/text/live-selection-edit.js +120 -0
  150. package/dist/components/blocks/text/live-split-rebalance.d.ts +56 -0
  151. package/dist/components/blocks/text/live-split-rebalance.js +239 -0
  152. package/dist/components/blocks/text/marker-completion.d.ts +18 -0
  153. package/dist/components/blocks/text/marker-completion.js +29 -0
  154. package/dist/components/blocks/text/pending-mark-insert.d.ts +37 -0
  155. package/dist/components/blocks/text/pending-mark-insert.js +188 -0
  156. package/dist/components/blocks/text/screen-diff.d.ts +20 -0
  157. package/dist/components/blocks/text/screen-diff.js +39 -0
  158. package/dist/components/blocks/text/text-clipboard.d.ts +70 -0
  159. package/dist/components/blocks/text/text-clipboard.js +131 -0
  160. package/dist/components/blocks/text/text-keydown.d.ts +39 -0
  161. package/dist/components/blocks/text/text-keydown.js +80 -0
  162. package/dist/components/blocks/text/text-render.d.ts +67 -0
  163. package/dist/components/blocks/text/text-render.js +215 -0
  164. package/dist/components/blocks/text/widget-adjacency.d.ts +30 -0
  165. package/dist/components/blocks/text/widget-adjacency.js +68 -0
  166. package/dist/components/blocks/text/widget-interaction.d.ts +90 -0
  167. package/dist/components/blocks/text/widget-interaction.js +591 -0
  168. package/dist/components/blocks/widget-portal.d.ts +54 -0
  169. package/dist/components/blocks/widget-portal.js +136 -0
  170. package/dist/components/built-in-blocks.d.ts +7 -0
  171. package/dist/components/built-in-blocks.js +77 -0
  172. package/dist/components/editor-root-clipboard.d.ts +29 -0
  173. package/dist/components/editor-root-clipboard.js +105 -0
  174. package/dist/components/editor-root-keydown.d.ts +47 -0
  175. package/dist/components/editor-root-keydown.js +88 -0
  176. package/dist/components/editor-root-listeners.d.ts +44 -0
  177. package/dist/components/editor-root-listeners.js +112 -0
  178. package/dist/components/image/ImageOverlayHost.svelte +115 -0
  179. package/dist/components/image/ImageOverlayHost.svelte.d.ts +20 -0
  180. package/dist/components/image/ImageProperties.svelte +153 -0
  181. package/dist/components/image/ImageProperties.svelte.d.ts +14 -0
  182. package/dist/components/image/ImageResizeHandles.svelte +188 -0
  183. package/dist/components/image/ImageResizeHandles.svelte.d.ts +10 -0
  184. package/dist/components/image/image-edit-commit.d.ts +38 -0
  185. package/dist/components/image/image-edit-commit.js +159 -0
  186. package/dist/components/image/image-resize.d.ts +11 -0
  187. package/dist/components/image/image-resize.js +38 -0
  188. package/dist/components/image/image-source-bytes.d.ts +15 -0
  189. package/dist/components/image/image-source-bytes.js +73 -0
  190. package/dist/components/image/image-widget-editing.d.ts +7 -0
  191. package/dist/components/image/image-widget-editing.js +41 -0
  192. package/dist/components/image/widget-dom.d.ts +11 -0
  193. package/dist/components/image/widget-dom.js +110 -0
  194. package/dist/components/image/widget-selection-state.svelte.d.ts +18 -0
  195. package/dist/components/image/widget-selection-state.svelte.js +26 -0
  196. package/dist/components/link-card/LinkCard.svelte +190 -0
  197. package/dist/components/link-card/LinkCard.svelte.d.ts +18 -0
  198. package/dist/components/link-card/LinkCardHost.svelte +181 -0
  199. package/dist/components/link-card/LinkCardHost.svelte.d.ts +25 -0
  200. package/dist/components/link-card/link-card-commit.d.ts +50 -0
  201. package/dist/components/link-card/link-card-commit.js +134 -0
  202. package/dist/components/link-card/link-card-entry.d.ts +39 -0
  203. package/dist/components/link-card/link-card-entry.js +51 -0
  204. package/dist/components/link-card/link-card-state.svelte.d.ts +44 -0
  205. package/dist/components/link-card/link-card-state.svelte.js +46 -0
  206. package/dist/components/lrd-map-gate.d.ts +18 -0
  207. package/dist/components/lrd-map-gate.js +22 -0
  208. package/dist/components/paste-image-arm.d.ts +29 -0
  209. package/dist/components/paste-image-arm.js +61 -0
  210. package/dist/components/portal.d.ts +11 -0
  211. package/dist/components/portal.js +29 -0
  212. package/dist/core/directive/activate.d.ts +8 -0
  213. package/dist/core/directive/activate.js +25 -0
  214. package/dist/core/directive/container-opener.d.ts +7 -0
  215. package/dist/core/directive/container-opener.js +162 -0
  216. package/dist/core/directive/grammar.d.ts +50 -0
  217. package/dist/core/directive/grammar.js +88 -0
  218. package/dist/core/directive/kinds.d.ts +31 -0
  219. package/dist/core/directive/kinds.js +137 -0
  220. package/dist/core/directive/registry.d.ts +39 -0
  221. package/dist/core/directive/registry.js +49 -0
  222. package/dist/core/directive/text-recognizer.d.ts +8 -0
  223. package/dist/core/directive/text-recognizer.js +87 -0
  224. package/dist/core/escapable.d.ts +6 -0
  225. package/dist/core/escapable.js +6 -0
  226. package/dist/core/inline/backticks.d.ts +16 -0
  227. package/dist/core/inline/backticks.js +62 -0
  228. package/dist/core/inline/character-refs.d.ts +7 -0
  229. package/dist/core/inline/character-refs.js +70 -0
  230. package/dist/core/inline/destination-bytes.d.ts +7 -0
  231. package/dist/core/inline/destination-bytes.js +14 -0
  232. package/dist/core/inline/entity-widget.d.ts +11 -0
  233. package/dist/core/inline/entity-widget.js +21 -0
  234. package/dist/core/inline/format-toggle.d.ts +50 -0
  235. package/dist/core/inline/format-toggle.js +533 -0
  236. package/dist/core/inline/html-entities.d.ts +8 -0
  237. package/dist/core/inline/html-entities.js +2134 -0
  238. package/dist/core/inline/html-tag-grammar.d.ts +16 -0
  239. package/dist/core/inline/html-tag-grammar.js +58 -0
  240. package/dist/core/inline/image-dimensions.d.ts +6 -0
  241. package/dist/core/inline/image-dimensions.js +42 -0
  242. package/dist/core/inline/index.d.ts +42 -0
  243. package/dist/core/inline/index.js +77 -0
  244. package/dist/core/inline/inline-cache.d.ts +20 -0
  245. package/dist/core/inline/inline-cache.js +28 -0
  246. package/dist/core/inline/inline-widgets.d.ts +124 -0
  247. package/dist/core/inline/inline-widgets.js +131 -0
  248. package/dist/core/inline/link-reference-resolver.d.ts +21 -0
  249. package/dist/core/inline/link-reference-resolver.js +46 -0
  250. package/dist/core/inline/raw-html-widget.d.ts +10 -0
  251. package/dist/core/inline/raw-html-widget.js +22 -0
  252. package/dist/core/inline/scan/autolinks.d.ts +23 -0
  253. package/dist/core/inline/scan/autolinks.js +354 -0
  254. package/dist/core/inline/scan/brackets.d.ts +11 -0
  255. package/dist/core/inline/scan/brackets.js +284 -0
  256. package/dist/core/inline/scan/code-spans.d.ts +7 -0
  257. package/dist/core/inline/scan/code-spans.js +27 -0
  258. package/dist/core/inline/scan/emphasis.d.ts +10 -0
  259. package/dist/core/inline/scan/emphasis.js +276 -0
  260. package/dist/core/inline/scan/index.d.ts +7 -0
  261. package/dist/core/inline/scan/index.js +176 -0
  262. package/dist/core/inline/scan/plugin-syntax.d.ts +62 -0
  263. package/dist/core/inline/scan/plugin-syntax.js +150 -0
  264. package/dist/core/inline/scan/scan-state.d.ts +47 -0
  265. package/dist/core/inline/scan/scan-state.js +48 -0
  266. package/dist/core/inline/scan/simple-nodes.d.ts +14 -0
  267. package/dist/core/inline/scan/simple-nodes.js +53 -0
  268. package/dist/core/inline/scan/url.d.ts +12 -0
  269. package/dist/core/inline/scan/url.js +82 -0
  270. package/dist/core/inline/transparency.d.ts +8 -0
  271. package/dist/core/inline/transparency.js +39 -0
  272. package/dist/core/inline/visibility.d.ts +81 -0
  273. package/dist/core/inline/visibility.js +144 -0
  274. package/dist/core/inline/walk.d.ts +14 -0
  275. package/dist/core/inline/walk.js +29 -0
  276. package/dist/core/inline-render.d.ts +48 -0
  277. package/dist/core/inline-render.js +322 -0
  278. package/dist/core/lines.d.ts +44 -0
  279. package/dist/core/lines.js +91 -0
  280. package/dist/core/node-views.d.ts +22 -0
  281. package/dist/core/node-views.js +8 -0
  282. package/dist/core/nodes.d.ts +297 -0
  283. package/dist/core/nodes.js +83 -0
  284. package/dist/core/parser.d.ts +68 -0
  285. package/dist/core/parser.js +189 -0
  286. package/dist/core/parsers/blockquote.d.ts +17 -0
  287. package/dist/core/parsers/blockquote.js +69 -0
  288. package/dist/core/parsers/built-in-openers.d.ts +8 -0
  289. package/dist/core/parsers/built-in-openers.js +124 -0
  290. package/dist/core/parsers/fence-syntax.d.ts +24 -0
  291. package/dist/core/parsers/fence-syntax.js +44 -0
  292. package/dist/core/parsers/fenced-code.d.ts +7 -0
  293. package/dist/core/parsers/fenced-code.js +29 -0
  294. package/dist/core/parsers/heading.d.ts +3 -0
  295. package/dist/core/parsers/heading.js +6 -0
  296. package/dist/core/parsers/html-block.d.ts +17 -0
  297. package/dist/core/parsers/html-block.js +94 -0
  298. package/dist/core/parsers/indented-code.d.ts +4 -0
  299. package/dist/core/parsers/indented-code.js +41 -0
  300. package/dist/core/parsers/link-reference.d.ts +7 -0
  301. package/dist/core/parsers/link-reference.js +152 -0
  302. package/dist/core/parsers/list.d.ts +19 -0
  303. package/dist/core/parsers/list.js +133 -0
  304. package/dist/core/parsers/paragraph.d.ts +10 -0
  305. package/dist/core/parsers/paragraph.js +42 -0
  306. package/dist/core/parsers/table-completion.d.ts +13 -0
  307. package/dist/core/parsers/table-completion.js +48 -0
  308. package/dist/core/parsers/table.d.ts +18 -0
  309. package/dist/core/parsers/table.js +110 -0
  310. package/dist/core/parsers/thematic-break.d.ts +1 -0
  311. package/dist/core/parsers/thematic-break.js +19 -0
  312. package/dist/core/serializer.d.ts +15 -0
  313. package/dist/core/serializer.js +11 -0
  314. package/dist/core/terminator-escalation.d.ts +8 -0
  315. package/dist/core/terminator-escalation.js +18 -0
  316. package/dist/core/url-policy.d.ts +14 -0
  317. package/dist/core/url-policy.js +44 -0
  318. package/dist/cursor/content-offsets.d.ts +29 -0
  319. package/dist/cursor/content-offsets.js +151 -0
  320. package/dist/cursor/coordinate-spaces.d.ts +65 -0
  321. package/dist/cursor/coordinate-spaces.js +66 -0
  322. package/dist/cursor/dom-walk.d.ts +18 -0
  323. package/dist/cursor/dom-walk.js +31 -0
  324. package/dist/cursor/edge-affinity.d.ts +44 -0
  325. package/dist/cursor/edge-affinity.js +60 -0
  326. package/dist/cursor/focused-caret.d.ts +10 -0
  327. package/dist/cursor/focused-caret.js +24 -0
  328. package/dist/cursor/height-model.d.ts +24 -0
  329. package/dist/cursor/height-model.js +72 -0
  330. package/dist/cursor/height-oracle.d.ts +24 -0
  331. package/dist/cursor/height-oracle.js +94 -0
  332. package/dist/cursor/overlay-rects.d.ts +8 -0
  333. package/dist/cursor/overlay-rects.js +19 -0
  334. package/dist/cursor/overlay-remeasure.d.ts +17 -0
  335. package/dist/cursor/overlay-remeasure.js +31 -0
  336. package/dist/cursor/pending-marks.d.ts +24 -0
  337. package/dist/cursor/pending-marks.js +36 -0
  338. package/dist/cursor/point-offset.d.ts +21 -0
  339. package/dist/cursor/point-offset.js +48 -0
  340. package/dist/cursor/reveal-anchor.d.ts +30 -0
  341. package/dist/cursor/reveal-anchor.js +31 -0
  342. package/dist/cursor/reveal-source.d.ts +35 -0
  343. package/dist/cursor/reveal-source.js +51 -0
  344. package/dist/cursor/scroll-ancestors.d.ts +28 -0
  345. package/dist/cursor/scroll-ancestors.js +89 -0
  346. package/dist/cursor/scrollport.d.ts +20 -0
  347. package/dist/cursor/scrollport.js +41 -0
  348. package/dist/cursor/sticky-column.d.ts +35 -0
  349. package/dist/cursor/sticky-column.js +64 -0
  350. package/dist/cursor/sticky-measure.d.ts +16 -0
  351. package/dist/cursor/sticky-measure.js +97 -0
  352. package/dist/cursor/typography-estimates.d.ts +21 -0
  353. package/dist/cursor/typography-estimates.js +21 -0
  354. package/dist/cursor/visual-lines.d.ts +25 -0
  355. package/dist/cursor/visual-lines.js +125 -0
  356. package/dist/cursor/widget-offset.d.ts +132 -0
  357. package/dist/cursor/widget-offset.js +543 -0
  358. package/dist/debug/diagnostics-report.d.ts +17 -0
  359. package/dist/debug/diagnostics-report.js +25 -0
  360. package/dist/debug/dump-tree.d.ts +6 -0
  361. package/dist/debug/dump-tree.js +114 -0
  362. package/dist/debug/inspect.d.ts +19 -0
  363. package/dist/debug/inspect.js +116 -0
  364. package/dist/debug/interaction-trace.d.ts +39 -0
  365. package/dist/debug/interaction-trace.js +105 -0
  366. package/dist/debug/operations-log.d.ts +14 -0
  367. package/dist/debug/operations-log.js +30 -0
  368. package/dist/decorations/buckets.d.ts +40 -0
  369. package/dist/decorations/buckets.js +87 -0
  370. package/dist/decorations/decoration-state.svelte.d.ts +20 -0
  371. package/dist/decorations/decoration-state.svelte.js +195 -0
  372. package/dist/decorations/island-dom.d.ts +35 -0
  373. package/dist/decorations/island-dom.js +148 -0
  374. package/dist/decorations/reserved-attrs.d.ts +12 -0
  375. package/dist/decorations/reserved-attrs.js +47 -0
  376. package/dist/decorations/types.d.ts +68 -0
  377. package/dist/decorations/types.js +5 -0
  378. package/dist/decorations/widget-dom.d.ts +15 -0
  379. package/dist/decorations/widget-dom.js +35 -0
  380. package/dist/dev-warn.d.ts +13 -0
  381. package/dist/dev-warn.js +28 -0
  382. package/dist/editor-actions/ancestry-folds.d.ts +32 -0
  383. package/dist/editor-actions/ancestry-folds.js +106 -0
  384. package/dist/editor-actions/block-edit-core.d.ts +29 -0
  385. package/dist/editor-actions/block-edit-core.js +277 -0
  386. package/dist/editor-actions/block-edit-scope.d.ts +79 -0
  387. package/dist/editor-actions/block-edit-scope.js +76 -0
  388. package/dist/editor-actions/block-edit.d.ts +8 -0
  389. package/dist/editor-actions/block-edit.js +111 -0
  390. package/dist/editor-actions/commit/history.d.ts +9 -0
  391. package/dist/editor-actions/commit/history.js +77 -0
  392. package/dist/editor-actions/commit/text-batch.d.ts +34 -0
  393. package/dist/editor-actions/commit/text-batch.js +61 -0
  394. package/dist/editor-actions/commit/undo-controller.d.ts +7 -0
  395. package/dist/editor-actions/commit/undo-controller.js +570 -0
  396. package/dist/editor-actions/container-block-component.d.ts +85 -0
  397. package/dist/editor-actions/container-block-component.js +228 -0
  398. package/dist/editor-actions/container-edit.d.ts +7 -0
  399. package/dist/editor-actions/container-edit.js +49 -0
  400. package/dist/editor-actions/container-exit-overrides.d.ts +16 -0
  401. package/dist/editor-actions/container-exit-overrides.js +38 -0
  402. package/dist/editor-actions/deps.d.ts +60 -0
  403. package/dist/editor-actions/deps.js +1 -0
  404. package/dist/editor-actions/enter-completion.d.ts +25 -0
  405. package/dist/editor-actions/enter-completion.js +76 -0
  406. package/dist/editor-actions/focus/focus-dispatch.d.ts +36 -0
  407. package/dist/editor-actions/focus/focus-dispatch.js +106 -0
  408. package/dist/editor-actions/focus/focus-landing.d.ts +7 -0
  409. package/dist/editor-actions/focus/focus-landing.js +39 -0
  410. package/dist/editor-actions/focus/focus.d.ts +7 -0
  411. package/dist/editor-actions/focus/focus.js +74 -0
  412. package/dist/editor-actions/index.d.ts +15 -0
  413. package/dist/editor-actions/index.js +19 -0
  414. package/dist/editor-actions/inline-range-commit.d.ts +20 -0
  415. package/dist/editor-actions/inline-range-commit.js +63 -0
  416. package/dist/editor-actions/list-context.d.ts +25 -0
  417. package/dist/editor-actions/list-context.js +285 -0
  418. package/dist/editor-actions/list-overrides.d.ts +13 -0
  419. package/dist/editor-actions/list-overrides.js +26 -0
  420. package/dist/editor-actions/merge-fallback.d.ts +19 -0
  421. package/dist/editor-actions/merge-fallback.js +27 -0
  422. package/dist/editor-actions/nested/nested-actions.d.ts +65 -0
  423. package/dist/editor-actions/nested/nested-actions.js +59 -0
  424. package/dist/editor-actions/nested/nested-block-edit.d.ts +10 -0
  425. package/dist/editor-actions/nested/nested-block-edit.js +181 -0
  426. package/dist/editor-actions/nested/nested-focus.d.ts +9 -0
  427. package/dist/editor-actions/nested/nested-focus.js +30 -0
  428. package/dist/editor-actions/paste-coordinator.d.ts +4 -0
  429. package/dist/editor-actions/paste-coordinator.js +20 -0
  430. package/dist/editor-actions/plugin/chrome-leaf.d.ts +25 -0
  431. package/dist/editor-actions/plugin/chrome-leaf.js +80 -0
  432. package/dist/editor-actions/plugin/container.d.ts +137 -0
  433. package/dist/editor-actions/plugin/container.js +351 -0
  434. package/dist/editor-actions/plugin/directive-container.d.ts +13 -0
  435. package/dist/editor-actions/plugin/directive-container.js +31 -0
  436. package/dist/editor-actions/reorder-action.d.ts +17 -0
  437. package/dist/editor-actions/reorder-action.js +104 -0
  438. package/dist/editor-actions/reorder-drag.d.ts +34 -0
  439. package/dist/editor-actions/reorder-drag.js +152 -0
  440. package/dist/editor-actions/replacement-focus.d.ts +27 -0
  441. package/dist/editor-actions/replacement-focus.js +60 -0
  442. package/dist/editor-actions/search-replace.d.ts +6 -0
  443. package/dist/editor-actions/search-replace.js +145 -0
  444. package/dist/editor-actions/table-context.d.ts +34 -0
  445. package/dist/editor-actions/table-context.js +292 -0
  446. package/dist/editor-actions/unwrap-strategies.d.ts +14 -0
  447. package/dist/editor-actions/unwrap-strategies.js +131 -0
  448. package/dist/editor-actions/whole-block-focus-surface.d.ts +51 -0
  449. package/dist/editor-actions/whole-block-focus-surface.js +171 -0
  450. package/dist/editor-events.d.ts +89 -0
  451. package/dist/editor-events.js +96 -0
  452. package/dist/editor-keys.d.ts +197 -0
  453. package/dist/editor-keys.js +40 -0
  454. package/dist/editor-props.d.ts +164 -0
  455. package/dist/editor-props.js +1 -0
  456. package/dist/editor-rects.d.ts +58 -0
  457. package/dist/editor-rects.js +114 -0
  458. package/dist/env.d.ts +12 -0
  459. package/dist/env.js +20 -0
  460. package/dist/index.d.ts +27 -0
  461. package/dist/index.js +19 -0
  462. package/dist/invariants/commit-paths.d.ts +10 -0
  463. package/dist/invariants/commit-paths.js +25 -0
  464. package/dist/invariants/commit-scope.d.ts +9 -0
  465. package/dist/invariants/commit-scope.js +16 -0
  466. package/dist/invariants/context-keys.d.ts +7 -0
  467. package/dist/invariants/context-keys.js +14 -0
  468. package/dist/invariants/descriptor.d.ts +10 -0
  469. package/dist/invariants/descriptor.js +24 -0
  470. package/dist/invariants/inline-transitions.d.ts +23 -0
  471. package/dist/invariants/inline-transitions.js +52 -0
  472. package/dist/invariants/install.d.ts +36 -0
  473. package/dist/invariants/install.js +66 -0
  474. package/dist/invariants/landable-caret.d.ts +12 -0
  475. package/dist/invariants/landable-caret.js +31 -0
  476. package/dist/invariants/marker-css-parity.d.ts +10 -0
  477. package/dist/invariants/marker-css-parity.js +87 -0
  478. package/dist/invariants/node-shape.d.ts +44 -0
  479. package/dist/invariants/node-shape.js +258 -0
  480. package/dist/invariants/registry.d.ts +126 -0
  481. package/dist/invariants/registry.js +349 -0
  482. package/dist/invariants/render-fidelity.d.ts +8 -0
  483. package/dist/invariants/render-fidelity.js +33 -0
  484. package/dist/invariants/selection-endpoints.d.ts +19 -0
  485. package/dist/invariants/selection-endpoints.js +78 -0
  486. package/dist/invariants/single-node-sink.d.ts +9 -0
  487. package/dist/invariants/single-node-sink.js +16 -0
  488. package/dist/invariants/snapshot-integrity.d.ts +17 -0
  489. package/dist/invariants/snapshot-integrity.js +24 -0
  490. package/dist/invariants/split-landing.d.ts +8 -0
  491. package/dist/invariants/split-landing.js +15 -0
  492. package/dist/invariants/structural-descriptor.d.ts +21 -0
  493. package/dist/invariants/structural-descriptor.js +50 -0
  494. package/dist/perf/instruments.d.ts +49 -0
  495. package/dist/perf/instruments.js +154 -0
  496. package/dist/perf/use-mount-gauge.svelte.d.ts +1 -0
  497. package/dist/perf/use-mount-gauge.svelte.js +15 -0
  498. package/dist/plugin.d.ts +102 -0
  499. package/dist/plugin.js +156 -0
  500. package/dist/plugins/admonitions/AdmonitionBlock.svelte +144 -0
  501. package/dist/plugins/admonitions/AdmonitionBlock.svelte.d.ts +11 -0
  502. package/dist/plugins/admonitions/admonition-kind.d.ts +8 -0
  503. package/dist/plugins/admonitions/admonition-kind.js +97 -0
  504. package/dist/plugins/admonitions/convert-document.d.ts +11 -0
  505. package/dist/plugins/admonitions/convert-document.js +39 -0
  506. package/dist/plugins/admonitions/gh-alert.d.ts +13 -0
  507. package/dist/plugins/admonitions/gh-alert.js +83 -0
  508. package/dist/plugins/admonitions/github-alert-kind.d.ts +12 -0
  509. package/dist/plugins/admonitions/github-alert-kind.js +125 -0
  510. package/dist/plugins/admonitions/index.d.ts +6 -0
  511. package/dist/plugins/admonitions/index.js +8 -0
  512. package/dist/plugins/admonitions/kinds.d.ts +26 -0
  513. package/dist/plugins/admonitions/kinds.js +18 -0
  514. package/dist/plugins/admonitions/register.d.ts +7 -0
  515. package/dist/plugins/admonitions/register.js +12 -0
  516. package/dist/plugins/details/DetailsBlock.svelte +129 -0
  517. package/dist/plugins/details/DetailsBlock.svelte.d.ts +11 -0
  518. package/dist/plugins/details/details-disclosure.svelte.d.ts +17 -0
  519. package/dist/plugins/details/details-disclosure.svelte.js +24 -0
  520. package/dist/plugins/details/details-kind.d.ts +25 -0
  521. package/dist/plugins/details/details-kind.js +237 -0
  522. package/dist/plugins/details/index.d.ts +2 -0
  523. package/dist/plugins/details/index.js +2 -0
  524. package/dist/plugins/details/register.d.ts +6 -0
  525. package/dist/plugins/details/register.js +15 -0
  526. package/dist/plugins/emoji/emoji-plugin.d.ts +2 -0
  527. package/dist/plugins/emoji/emoji-plugin.js +10 -0
  528. package/dist/plugins/emoji/emoji-recognizer.d.ts +18 -0
  529. package/dist/plugins/emoji/emoji-recognizer.js +63 -0
  530. package/dist/plugins/emoji/emoji-table.d.ts +1 -0
  531. package/dist/plugins/emoji/emoji-table.js +1919 -0
  532. package/dist/plugins/emoji/index.d.ts +3 -0
  533. package/dist/plugins/emoji/index.js +4 -0
  534. package/dist/plugins/footnotes/FootnoteDefinition.svelte +103 -0
  535. package/dist/plugins/footnotes/FootnoteDefinition.svelte.d.ts +13 -0
  536. package/dist/plugins/footnotes/FootnoteReference.svelte +50 -0
  537. package/dist/plugins/footnotes/FootnoteReference.svelte.d.ts +4 -0
  538. package/dist/plugins/footnotes/constants.d.ts +2 -0
  539. package/dist/plugins/footnotes/constants.js +4 -0
  540. package/dist/plugins/footnotes/footnote-definition.d.ts +14 -0
  541. package/dist/plugins/footnotes/footnote-definition.js +147 -0
  542. package/dist/plugins/footnotes/footnote-lookup.d.ts +9 -0
  543. package/dist/plugins/footnotes/footnote-lookup.js +33 -0
  544. package/dist/plugins/footnotes/footnote-numbering.d.ts +23 -0
  545. package/dist/plugins/footnotes/footnote-numbering.js +78 -0
  546. package/dist/plugins/footnotes/footnote-reference.d.ts +7 -0
  547. package/dist/plugins/footnotes/footnote-reference.js +54 -0
  548. package/dist/plugins/footnotes/footnotes-plugin.d.ts +7 -0
  549. package/dist/plugins/footnotes/footnotes-plugin.js +17 -0
  550. package/dist/plugins/footnotes/index.d.ts +5 -0
  551. package/dist/plugins/footnotes/index.js +6 -0
  552. package/dist/plugins/highlight-occurrences/highlight-occurrences-plugin.d.ts +17 -0
  553. package/dist/plugins/highlight-occurrences/highlight-occurrences-plugin.js +31 -0
  554. package/dist/plugins/highlight-occurrences/index.d.ts +1 -0
  555. package/dist/plugins/highlight-occurrences/index.js +1 -0
  556. package/dist/plugins/highlight-occurrences/occurrence-source.d.ts +26 -0
  557. package/dist/plugins/highlight-occurrences/occurrence-source.js +54 -0
  558. package/dist/plugins/highlight-occurrences/occurrences.d.ts +33 -0
  559. package/dist/plugins/highlight-occurrences/occurrences.js +108 -0
  560. package/dist/plugins/latex/BlockMath.svelte +119 -0
  561. package/dist/plugins/latex/BlockMath.svelte.d.ts +21 -0
  562. package/dist/plugins/latex/MathInline.svelte +28 -0
  563. package/dist/plugins/latex/MathInline.svelte.d.ts +4 -0
  564. package/dist/plugins/latex/index.d.ts +3 -0
  565. package/dist/plugins/latex/index.js +4 -0
  566. package/dist/plugins/latex/latex-kind.d.ts +17 -0
  567. package/dist/plugins/latex/latex-kind.js +224 -0
  568. package/dist/plugins/latex/math-completion.d.ts +10 -0
  569. package/dist/plugins/latex/math-completion.js +19 -0
  570. package/dist/plugins/latex/math-renderer.d.ts +26 -0
  571. package/dist/plugins/latex/math-renderer.js +42 -0
  572. package/dist/plugins/latex/register.d.ts +10 -0
  573. package/dist/plugins/latex/register.js +23 -0
  574. package/dist/plugins/latex/renderer.d.ts +13 -0
  575. package/dist/plugins/latex/renderer.js +34 -0
  576. package/dist/plugins/mermaid/MermaidBlock.svelte +572 -0
  577. package/dist/plugins/mermaid/MermaidBlock.svelte.d.ts +11 -0
  578. package/dist/plugins/mermaid/index.d.ts +3 -0
  579. package/dist/plugins/mermaid/index.js +3 -0
  580. package/dist/plugins/mermaid/mermaid-kind.d.ts +38 -0
  581. package/dist/plugins/mermaid/mermaid-kind.js +176 -0
  582. package/dist/plugins/mermaid/mermaid-renderer.d.ts +28 -0
  583. package/dist/plugins/mermaid/mermaid-renderer.js +35 -0
  584. package/dist/plugins/mermaid/register.d.ts +10 -0
  585. package/dist/plugins/mermaid/register.js +20 -0
  586. package/dist/plugins/mermaid/renderer.d.ts +11 -0
  587. package/dist/plugins/mermaid/renderer.js +53 -0
  588. package/dist/plugins/parrot/ParrotBlock.svelte +342 -0
  589. package/dist/plugins/parrot/ParrotBlock.svelte.d.ts +21 -0
  590. package/dist/plugins/parrot/index.d.ts +1 -0
  591. package/dist/plugins/parrot/index.js +2 -0
  592. package/dist/plugins/parrot/parrot-plugin.d.ts +3 -0
  593. package/dist/plugins/parrot/parrot-plugin.js +49 -0
  594. package/dist/plugins/toc/TocBlock.svelte +218 -0
  595. package/dist/plugins/toc/TocBlock.svelte.d.ts +24 -0
  596. package/dist/plugins/toc/heading-outline.d.ts +28 -0
  597. package/dist/plugins/toc/heading-outline.js +65 -0
  598. package/dist/plugins/toc/index.d.ts +2 -0
  599. package/dist/plugins/toc/index.js +2 -0
  600. package/dist/plugins/toc/navigation-queue.d.ts +12 -0
  601. package/dist/plugins/toc/navigation-queue.js +21 -0
  602. package/dist/plugins/toc/toc-plugin.d.ts +16 -0
  603. package/dist/plugins/toc/toc-plugin.js +71 -0
  604. package/dist/presentation-mode.d.ts +32 -0
  605. package/dist/presentation-mode.js +50 -0
  606. package/dist/reactivity/block-list-state.svelte.d.ts +22 -0
  607. package/dist/reactivity/block-list-state.svelte.js +46 -0
  608. package/dist/reactivity/block-window.svelte.d.ts +41 -0
  609. package/dist/reactivity/block-window.svelte.js +93 -0
  610. package/dist/reactivity/content-version.svelte.d.ts +14 -0
  611. package/dist/reactivity/content-version.svelte.js +16 -0
  612. package/dist/reactivity/list-windowing.svelte.d.ts +100 -0
  613. package/dist/reactivity/list-windowing.svelte.js +402 -0
  614. package/dist/reactivity/measure-batch.d.ts +15 -0
  615. package/dist/reactivity/measure-batch.js +18 -0
  616. package/dist/reactivity/publish-ref.svelte.d.ts +54 -0
  617. package/dist/reactivity/publish-ref.svelte.js +128 -0
  618. package/dist/reactivity/scope-geometry.d.ts +18 -0
  619. package/dist/reactivity/scope-geometry.js +29 -0
  620. package/dist/reactivity/state-registry.d.ts +10 -0
  621. package/dist/reactivity/state-registry.js +44 -0
  622. package/dist/reactivity/use-container-windowing.svelte.d.ts +35 -0
  623. package/dist/reactivity/use-container-windowing.svelte.js +95 -0
  624. package/dist/reactivity/window-slice.d.ts +11 -0
  625. package/dist/reactivity/window-slice.js +9 -0
  626. package/dist/scan-index.d.ts +11 -0
  627. package/dist/scan-index.js +27 -0
  628. package/dist/schema/block-commands.d.ts +105 -0
  629. package/dist/schema/block-commands.js +179 -0
  630. package/dist/schema/block-completions.d.ts +33 -0
  631. package/dist/schema/block-completions.js +49 -0
  632. package/dist/schema/block-component-registry.d.ts +33 -0
  633. package/dist/schema/block-component-registry.js +33 -0
  634. package/dist/schema/block-kind-descriptor.d.ts +281 -0
  635. package/dist/schema/block-kind-descriptor.js +187 -0
  636. package/dist/schema/block-openers.d.ts +94 -0
  637. package/dist/schema/block-openers.js +150 -0
  638. package/dist/schema/built-in-descriptors.d.ts +8 -0
  639. package/dist/schema/built-in-descriptors.js +560 -0
  640. package/dist/schema/child-spans.d.ts +25 -0
  641. package/dist/schema/child-spans.js +161 -0
  642. package/dist/schema/closure.d.ts +39 -0
  643. package/dist/schema/closure.js +55 -0
  644. package/dist/schema/command-id.d.ts +20 -0
  645. package/dist/schema/command-id.js +42 -0
  646. package/dist/schema/commands.d.ts +147 -0
  647. package/dist/schema/commands.js +294 -0
  648. package/dist/schema/container-raw.d.ts +21 -0
  649. package/dist/schema/container-raw.js +43 -0
  650. package/dist/schema/container-rebuilders.d.ts +32 -0
  651. package/dist/schema/container-rebuilders.js +95 -0
  652. package/dist/schema/define-plugin-block.d.ts +15 -0
  653. package/dist/schema/define-plugin-block.js +18 -0
  654. package/dist/schema/fenced-code-raw.d.ts +43 -0
  655. package/dist/schema/fenced-code-raw.js +220 -0
  656. package/dist/schema/global-commands.d.ts +11 -0
  657. package/dist/schema/global-commands.js +40 -0
  658. package/dist/schema/inline-construct-policy.d.ts +131 -0
  659. package/dist/schema/inline-construct-policy.js +96 -0
  660. package/dist/schema/keybinding-overrides.d.ts +39 -0
  661. package/dist/schema/keybinding-overrides.js +43 -0
  662. package/dist/schema/keybindings.d.ts +36 -0
  663. package/dist/schema/keybindings.js +75 -0
  664. package/dist/schema/merge-rules.d.ts +28 -0
  665. package/dist/schema/merge-rules.js +57 -0
  666. package/dist/schema/opener-priorities.d.ts +16 -0
  667. package/dist/schema/opener-priorities.js +16 -0
  668. package/dist/schema/operations.d.ts +110 -0
  669. package/dist/schema/operations.js +6 -0
  670. package/dist/schema/plugin-activation.d.ts +13 -0
  671. package/dist/schema/plugin-activation.js +18 -0
  672. package/dist/schema/plugin-editor-context.d.ts +33 -0
  673. package/dist/schema/plugin-editor-context.js +65 -0
  674. package/dist/schema/plugin-install.d.ts +58 -0
  675. package/dist/schema/plugin-install.js +132 -0
  676. package/dist/schema/plugin-kind.d.ts +21 -0
  677. package/dist/schema/plugin-kind.js +86 -0
  678. package/dist/schema/plugin-name.d.ts +1 -0
  679. package/dist/schema/plugin-name.js +7 -0
  680. package/dist/schema/register-once.d.ts +9 -0
  681. package/dist/schema/register-once.js +35 -0
  682. package/dist/schema/registration-checks.d.ts +32 -0
  683. package/dist/schema/registration-checks.js +122 -0
  684. package/dist/schema/registration-pending.d.ts +28 -0
  685. package/dist/schema/registration-pending.js +48 -0
  686. package/dist/schema/registry-reset.d.ts +7 -0
  687. package/dist/schema/registry-reset.js +30 -0
  688. package/dist/schema/registry-view.d.ts +30 -0
  689. package/dist/schema/registry-view.js +39 -0
  690. package/dist/schema/reserved-chords.d.ts +35 -0
  691. package/dist/schema/reserved-chords.js +313 -0
  692. package/dist/schema/reserved-chrome.d.ts +23 -0
  693. package/dist/schema/reserved-chrome.js +33 -0
  694. package/dist/schema/table-cell-raw.d.ts +14 -0
  695. package/dist/schema/table-cell-raw.js +30 -0
  696. package/dist/schema/whole-block-unit.d.ts +8 -0
  697. package/dist/schema/whole-block-unit.js +12 -0
  698. package/dist/search/document-scan.d.ts +22 -0
  699. package/dist/search/document-scan.js +39 -0
  700. package/dist/search/matcher.d.ts +31 -0
  701. package/dist/search/matcher.js +70 -0
  702. package/dist/search/regex-executor.d.ts +41 -0
  703. package/dist/search/regex-executor.js +165 -0
  704. package/dist/search/replace.d.ts +15 -0
  705. package/dist/search/replace.js +29 -0
  706. package/dist/search/search-state.svelte.d.ts +59 -0
  707. package/dist/search/search-state.svelte.js +231 -0
  708. package/dist/selection/autoscroll.d.ts +26 -0
  709. package/dist/selection/autoscroll.js +91 -0
  710. package/dist/selection/block-hit-test.d.ts +37 -0
  711. package/dist/selection/block-hit-test.js +59 -0
  712. package/dist/selection/caret-doors.d.ts +20 -0
  713. package/dist/selection/caret-doors.js +44 -0
  714. package/dist/selection/caret-restore.d.ts +15 -0
  715. package/dist/selection/caret-restore.js +32 -0
  716. package/dist/selection/char-endpoint-snap.d.ts +15 -0
  717. package/dist/selection/char-endpoint-snap.js +39 -0
  718. package/dist/selection/clipboard-text.d.ts +13 -0
  719. package/dist/selection/clipboard-text.js +314 -0
  720. package/dist/selection/cross-block/clipboard.d.ts +14 -0
  721. package/dist/selection/cross-block/clipboard.js +20 -0
  722. package/dist/selection/cross-block/dispatch.d.ts +78 -0
  723. package/dist/selection/cross-block/dispatch.js +57 -0
  724. package/dist/selection/cross-block/format-range.d.ts +38 -0
  725. package/dist/selection/cross-block/format-range.js +193 -0
  726. package/dist/selection/cross-block/format-toggle.d.ts +27 -0
  727. package/dist/selection/cross-block/format-toggle.js +109 -0
  728. package/dist/selection/cross-block/keydown.d.ts +11 -0
  729. package/dist/selection/cross-block/keydown.js +339 -0
  730. package/dist/selection/cross-block/ops.d.ts +56 -0
  731. package/dist/selection/cross-block/ops.js +210 -0
  732. package/dist/selection/cross-block/paste.d.ts +8 -0
  733. package/dist/selection/cross-block/paste.js +156 -0
  734. package/dist/selection/cross-block/pointer.d.ts +19 -0
  735. package/dist/selection/cross-block/pointer.js +80 -0
  736. package/dist/selection/cross-block/type-replace.d.ts +10 -0
  737. package/dist/selection/cross-block/type-replace.js +129 -0
  738. package/dist/selection/dead-space-caret.d.ts +39 -0
  739. package/dist/selection/dead-space-caret.js +173 -0
  740. package/dist/selection/drag-pointer.d.ts +22 -0
  741. package/dist/selection/drag-pointer.js +89 -0
  742. package/dist/selection/gap-caret.d.ts +47 -0
  743. package/dist/selection/gap-caret.js +72 -0
  744. package/dist/selection/keyboard-extend.d.ts +43 -0
  745. package/dist/selection/keyboard-extend.js +257 -0
  746. package/dist/selection/native-bridge.d.ts +47 -0
  747. package/dist/selection/native-bridge.js +204 -0
  748. package/dist/selection/nearest-block.d.ts +43 -0
  749. package/dist/selection/nearest-block.js +73 -0
  750. package/dist/selection/path-lookup.d.ts +32 -0
  751. package/dist/selection/path-lookup.js +132 -0
  752. package/dist/selection/path-math.d.ts +35 -0
  753. package/dist/selection/path-math.js +90 -0
  754. package/dist/selection/pointer-session.d.ts +43 -0
  755. package/dist/selection/pointer-session.js +111 -0
  756. package/dist/selection/primitives.d.ts +75 -0
  757. package/dist/selection/primitives.js +91 -0
  758. package/dist/selection/range-delete-ceremony.d.ts +85 -0
  759. package/dist/selection/range-delete-ceremony.js +197 -0
  760. package/dist/selection/range-delete-chrome.d.ts +39 -0
  761. package/dist/selection/range-delete-chrome.js +105 -0
  762. package/dist/selection/range-delete-table-coverage.d.ts +28 -0
  763. package/dist/selection/range-delete-table-coverage.js +168 -0
  764. package/dist/selection/range-delete-table.d.ts +16 -0
  765. package/dist/selection/range-delete-table.js +347 -0
  766. package/dist/selection/range-delete.d.ts +33 -0
  767. package/dist/selection/range-delete.js +121 -0
  768. package/dist/selection/selection-description.d.ts +7 -0
  769. package/dist/selection/selection-description.js +18 -0
  770. package/dist/selection/selection-restore.d.ts +46 -0
  771. package/dist/selection/selection-restore.js +66 -0
  772. package/dist/selection/selection-state.svelte.d.ts +72 -0
  773. package/dist/selection/selection-state.svelte.js +247 -0
  774. package/dist/selection/shared-keydown.d.ts +61 -0
  775. package/dist/selection/shared-keydown.js +150 -0
  776. package/dist/selection/table-endpoint-snap.d.ts +55 -0
  777. package/dist/selection/table-endpoint-snap.js +143 -0
  778. package/dist/selection/table-rect-extend.d.ts +23 -0
  779. package/dist/selection/table-rect-extend.js +46 -0
  780. package/dist/selection/widget-range-paint.d.ts +12 -0
  781. package/dist/selection/widget-range-paint.js +44 -0
  782. package/dist/styles/editor-theme.css +151 -0
  783. package/dist/styles/editor.css +585 -0
  784. package/dist/testing/conformance-core.d.ts +45 -0
  785. package/dist/testing/conformance-core.js +105 -0
  786. package/dist/testing/container-conformance.d.ts +137 -0
  787. package/dist/testing/container-conformance.js +533 -0
  788. package/dist/testing/headless-actions.d.ts +37 -0
  789. package/dist/testing/headless-actions.js +118 -0
  790. package/dist/testing/inline-conformance.d.ts +50 -0
  791. package/dist/testing/inline-conformance.js +442 -0
  792. package/dist/testing/kind-conformance.d.ts +54 -0
  793. package/dist/testing/kind-conformance.js +325 -0
  794. package/dist/testing/mount-dom-stubs.d.ts +8 -0
  795. package/dist/testing/mount-dom-stubs.js +19 -0
  796. package/dist/testing/parse-convergence.d.ts +14 -0
  797. package/dist/testing/parse-convergence.js +81 -0
  798. package/dist/testing.d.ts +20 -0
  799. package/dist/testing.js +61 -0
  800. package/dist/tree-operations/blockquote.d.ts +18 -0
  801. package/dist/tree-operations/blockquote.js +59 -0
  802. package/dist/tree-operations/children.d.ts +17 -0
  803. package/dist/tree-operations/children.js +56 -0
  804. package/dist/tree-operations/cleanup.d.ts +10 -0
  805. package/dist/tree-operations/cleanup.js +25 -0
  806. package/dist/tree-operations/clone.d.ts +5 -0
  807. package/dist/tree-operations/clone.js +43 -0
  808. package/dist/tree-operations/container-lift.d.ts +9 -0
  809. package/dist/tree-operations/container-lift.js +29 -0
  810. package/dist/tree-operations/index.d.ts +16 -0
  811. package/dist/tree-operations/index.js +14 -0
  812. package/dist/tree-operations/list/empty-check.d.ts +7 -0
  813. package/dist/tree-operations/list/empty-check.js +19 -0
  814. package/dist/tree-operations/list/exit-replacement.d.ts +13 -0
  815. package/dist/tree-operations/list/exit-replacement.js +49 -0
  816. package/dist/tree-operations/list/item-partition.d.ts +13 -0
  817. package/dist/tree-operations/list/item-partition.js +33 -0
  818. package/dist/tree-operations/list/list-builders.d.ts +44 -0
  819. package/dist/tree-operations/list/list-builders.js +129 -0
  820. package/dist/tree-operations/list/ordered-markers.d.ts +36 -0
  821. package/dist/tree-operations/list/ordered-markers.js +114 -0
  822. package/dist/tree-operations/list/reconcile-task.d.ts +12 -0
  823. package/dist/tree-operations/list/reconcile-task.js +47 -0
  824. package/dist/tree-operations/list/sublist-separator.d.ts +13 -0
  825. package/dist/tree-operations/list/sublist-separator.js +34 -0
  826. package/dist/tree-operations/list/terminator.d.ts +17 -0
  827. package/dist/tree-operations/list/terminator.js +60 -0
  828. package/dist/tree-operations/list/unwrap-merge.d.ts +29 -0
  829. package/dist/tree-operations/list/unwrap-merge.js +202 -0
  830. package/dist/tree-operations/node-ops.d.ts +296 -0
  831. package/dist/tree-operations/node-ops.js +1428 -0
  832. package/dist/tree-operations/parse-block.d.ts +3 -0
  833. package/dist/tree-operations/parse-block.js +8 -0
  834. package/dist/tree-operations/paste/apply.d.ts +12 -0
  835. package/dist/tree-operations/paste/apply.js +75 -0
  836. package/dist/tree-operations/paste/body-write.d.ts +19 -0
  837. package/dist/tree-operations/paste/body-write.js +53 -0
  838. package/dist/tree-operations/paste/container-match.d.ts +32 -0
  839. package/dist/tree-operations/paste/container-match.js +238 -0
  840. package/dist/tree-operations/paste/container-paste.d.ts +10 -0
  841. package/dist/tree-operations/paste/container-paste.js +27 -0
  842. package/dist/tree-operations/paste/dispatch.d.ts +61 -0
  843. package/dist/tree-operations/paste/dispatch.js +138 -0
  844. package/dist/tree-operations/paste/find-enclosing-list.d.ts +8 -0
  845. package/dist/tree-operations/paste/find-enclosing-list.js +30 -0
  846. package/dist/tree-operations/paste/focus-target.d.ts +27 -0
  847. package/dist/tree-operations/paste/focus-target.js +40 -0
  848. package/dist/tree-operations/paste/hooks.d.ts +17 -0
  849. package/dist/tree-operations/paste/hooks.js +80 -0
  850. package/dist/tree-operations/paste/list-absorb.d.ts +29 -0
  851. package/dist/tree-operations/paste/list-absorb.js +106 -0
  852. package/dist/tree-operations/paste/list-break-out.d.ts +42 -0
  853. package/dist/tree-operations/paste/list-break-out.js +136 -0
  854. package/dist/tree-operations/paste/parent-scope.d.ts +17 -0
  855. package/dist/tree-operations/paste/parent-scope.js +35 -0
  856. package/dist/tree-operations/paste/paste-deps.d.ts +20 -0
  857. package/dist/tree-operations/paste/paste-deps.js +6 -0
  858. package/dist/tree-operations/paste/paste-replacement.d.ts +8 -0
  859. package/dist/tree-operations/paste/paste-replacement.js +60 -0
  860. package/dist/tree-operations/paste/paste-transforms.d.ts +25 -0
  861. package/dist/tree-operations/paste/paste-transforms.js +72 -0
  862. package/dist/tree-operations/paste/replace-block-at-parent.d.ts +29 -0
  863. package/dist/tree-operations/paste/replace-block-at-parent.js +75 -0
  864. package/dist/tree-operations/paste/strategy.d.ts +9 -0
  865. package/dist/tree-operations/paste/strategy.js +20 -0
  866. package/dist/tree-operations/paste/table-slice.d.ts +10 -0
  867. package/dist/tree-operations/paste/table-slice.js +39 -0
  868. package/dist/tree-operations/paste-surfaces.d.ts +61 -0
  869. package/dist/tree-operations/paste-surfaces.js +15 -0
  870. package/dist/tree-operations/path-mutate.d.ts +12 -0
  871. package/dist/tree-operations/path-mutate.js +20 -0
  872. package/dist/tree-operations/reorder-unit.d.ts +17 -0
  873. package/dist/tree-operations/reorder-unit.js +37 -0
  874. package/dist/tree-operations/reorder.d.ts +13 -0
  875. package/dist/tree-operations/reorder.js +57 -0
  876. package/dist/tree-operations/sharing.d.ts +18 -0
  877. package/dist/tree-operations/sharing.js +14 -0
  878. package/dist/tree-operations/splice-many.d.ts +9 -0
  879. package/dist/tree-operations/splice-many.js +22 -0
  880. package/dist/tree-operations/structural-change.d.ts +65 -0
  881. package/dist/tree-operations/structural-change.js +117 -0
  882. package/dist/tree-operations/sub-table-copy.d.ts +6 -0
  883. package/dist/tree-operations/sub-table-copy.js +43 -0
  884. package/dist/tree-operations/table-mutations.d.ts +17 -0
  885. package/dist/tree-operations/table-mutations.js +101 -0
  886. package/dist/tree-operations/unshare.d.ts +101 -0
  887. package/dist/tree-operations/unshare.js +248 -0
  888. package/dist/undo/manager.d.ts +2 -0
  889. package/dist/undo/manager.js +50 -0
  890. package/dist/undo/types.d.ts +44 -0
  891. package/dist/undo/types.js +7 -0
  892. package/docs/guide/consumer-guide.md +1098 -0
  893. package/docs/guide/directives.md +223 -0
  894. package/docs/guide/plugin-api.md +329 -0
  895. package/docs/guide/plugin-guide/conspiracy.gif +0 -0
  896. package/docs/guide/plugin-guide/parrot-frames.md +209 -0
  897. package/docs/guide/plugin-guide/parrot.gif +0 -0
  898. package/docs/guide/plugin-guide.md +1693 -0
  899. package/docs/guide/plugin-testing.md +463 -0
  900. package/package.json +238 -0
@@ -0,0 +1,1849 @@
1
+ <script lang="ts">
2
+ import { setContext, tick, onMount, untrack } from 'svelte';
3
+ import '../styles/editor.css';
4
+ import type { BlockComponent } from '../block-component';
5
+ import type { AnyBlockKind, Document } from '../core/nodes';
6
+ import type { EditorProps, EditorInstance, EditorDiagnostics } from '../editor-props';
7
+ import type { EditorEvents } from '../editor-events';
8
+ import {
9
+ BLOCK_EDIT_KEY,
10
+ CONTAINER_EDIT_KEY,
11
+ EDITOR_DOC_KEY,
12
+ EDITOR_POLICIES_KEY,
13
+ EDITOR_SERVICES_KEY,
14
+ FOCUS_KEY,
15
+ HISTORY_KEY,
16
+ type BlockElLookup,
17
+ type DocumentGetter,
18
+ type EditorDoc,
19
+ type LinkReferenceResolverRef,
20
+ type EditorPolicies,
21
+ type EditorServices,
22
+ type PluginEditorLookup,
23
+ type ResolveImageUrl,
24
+ type ResolveLinkUrl
25
+ } from '../editor-keys';
26
+ import { createStickyColumnState } from '../cursor/sticky-column';
27
+ import { createEdgeAffinityState } from '../cursor/edge-affinity';
28
+ import { createPendingMarksState } from '../cursor/pending-marks';
29
+ import { createRevealAnchorState } from '../cursor/reveal-anchor';
30
+ import { createHeightOracle } from '../cursor/height-oracle';
31
+ import { ESTIMATE_BASE_FONT_SIZE, HEIGHT_ESTIMATES } from '../cursor/typography-estimates';
32
+ import {
33
+ clippingAncestors,
34
+ userScrollportFor,
35
+ type UserScrollport
36
+ } from '../cursor/scroll-ancestors';
37
+ import { createScrollport, type Scrollport } from '../cursor/scrollport';
38
+ import { createDeadSpaceCaret } from '../selection/dead-space-caret';
39
+ import { resetForPointerDown } from '../selection/cross-block/pointer';
40
+ import { createContentVersion } from '../reactivity/content-version.svelte';
41
+ import { useContainerWindowing } from '../reactivity/use-container-windowing.svelte';
42
+ import { refSlotsOver, replaceRefs, revealChildOrWait } from '../reactivity/publish-ref.svelte';
43
+ import { createSelectionState } from '../selection/selection-state.svelte';
44
+ import { createSelectionDescription } from '../selection/selection-description';
45
+ import { EDITOR_LABEL, movedBlockToPosition } from '../a11y-strings';
46
+ import type { EditorSelection } from '../selection/primitives';
47
+ import { createWidgetSelectionState } from './image/widget-selection-state.svelte';
48
+ import { bootstrapCodeLanguages } from './blocks/code/code-bootstrap';
49
+ import { assignIds } from '../block-id';
50
+ import { ensureEditableContainers, emptyParagraph } from '../tree-operations';
51
+ import { blockNodeAt, isBlockNode, nodeAt } from '../tree-operations/node-ops';
52
+ import { serialize } from '../core/serializer';
53
+ import { parse } from '../core/parser';
54
+ import { defaultLinkActivation } from '../core/url-policy';
55
+ import { advanceSignatureEpoch, lrdMapCouldChange } from './lrd-map-gate';
56
+ import {
57
+ buildLinkReferenceMap,
58
+ type LinkReferenceResolver
59
+ } from '../core/inline/link-reference-resolver';
60
+ import { createUndoManager } from '../undo/manager';
61
+ import { createSharingState } from '../tree-operations/sharing';
62
+ import { createEditorEvents, emitBlockedLinkError, emitCommandError } from '../editor-events';
63
+ import { createEditorActions, type EditorActionsDeps } from '../editor-actions';
64
+ import { createReorderAction } from '../editor-actions/reorder-action';
65
+ import { createSearchReplace } from '../editor-actions/search-replace';
66
+ import { createSearchState, type SearchState } from '../search/search-state.svelte';
67
+ import { createDecorationEngine } from '../decorations/decoration-state.svelte';
68
+ import type { DecorationRegistry } from '../decorations/types';
69
+ import { createEditorRects, type EditorRects } from '../editor-rects';
70
+ import { installReorderDrag } from '../editor-actions/reorder-drag';
71
+ import { createPasteCoordinator } from '../editor-actions/paste-coordinator';
72
+ import { createOperationsLog } from '../debug/operations-log';
73
+ import { dumpInteractionTrace, dumpOperationsLog } from '../debug/inspect';
74
+ import { buildDiagnosticsReport } from '../debug/diagnostics-report';
75
+ import {
76
+ enableInteractionTrace,
77
+ disableInteractionTrace,
78
+ isInteractionTraceEnabled,
79
+ interactionTraceSnapshot
80
+ } from '../debug/interaction-trace';
81
+ import { readCurrentSelection } from '../selection/native-bridge';
82
+ import { restoreSelection, type SelectionRestoreOutcome } from '../selection/selection-restore';
83
+ import { findSurfacePathForElement, readBlockPath } from '../selection/path-lookup';
84
+ import { createCaretRestore } from '../selection/caret-restore';
85
+ import { createCrossBlockHandlers } from '../selection/cross-block/dispatch';
86
+ import { createCrossBlockCommands } from '../selection/cross-block/format-toggle';
87
+ import { isPreviewMode } from '../presentation-mode';
88
+ import { normalizeKeybindingOverrides } from '../schema/keybinding-overrides';
89
+ import { createEditorRootKeydown } from './editor-root-keydown';
90
+ import { createEditorRootClipboard } from './editor-root-clipboard';
91
+ import {
92
+ installEditorBlurAnnouncer,
93
+ installModActiveTracker,
94
+ installSelectionChangeBridge,
95
+ installViewportHeightWatcher,
96
+ onRoot,
97
+ removeAll
98
+ } from './editor-root-listeners';
99
+ import { collectReservedChords, chordIsClaimed } from '../schema/reserved-chords';
100
+ import { portalInto } from './portal';
101
+ import {
102
+ registerEditor,
103
+ unregisterEditor,
104
+ markEditorInteracted,
105
+ releaseInteractedEditor,
106
+ isTextEntrySurface
107
+ } from '../active-editor';
108
+ import { ambientLengthOf } from '../ambient/ambient-dom';
109
+ import { toClampedRawOffset } from '../cursor/coordinate-spaces';
110
+ import { domTextOffsetAtNode } from '../cursor/widget-offset';
111
+ import {
112
+ canRunCommandById,
113
+ isCommandActiveById,
114
+ runCommandById,
115
+ type CommandDispatchContext,
116
+ type CommandErrorSink,
117
+ type KindCommandTarget
118
+ } from '../schema/block-commands';
119
+ import type { AnyCommandId } from '../schema/command-id';
120
+ import { installPlugins, normalizePluginEntries } from '../schema/plugin-install';
121
+ import {
122
+ activationFor,
123
+ everyInstalledPlugin,
124
+ kindEnablementFor
125
+ } from '../schema/plugin-activation';
126
+ import { createEditorPluginContexts, mintEditorId } from '../schema/plugin-editor-context';
127
+ import { bothEnable, createRegistryView, type KindEnablement } from '../schema/registry-view';
128
+ import BlockList from './BlockList.svelte';
129
+ import SearchBar from './SearchBar.svelte';
130
+ import ImageOverlayHost from './image/ImageOverlayHost.svelte';
131
+ import LinkCardHost from './link-card/LinkCardHost.svelte';
132
+ import { createLinkCardState } from './link-card/link-card-state.svelte';
133
+ import { LINK_ELEMENT_SELECTOR, resolveLinkAtPoint } from './blocks/text/link-at-point';
134
+ import { runStartupInvariantChecks } from '../invariants/install';
135
+ import { assertInvariant } from '../assert';
136
+ import { checkMarkerCssParity } from '../invariants/marker-css-parity';
137
+ import { checkLandableCaret } from '../invariants/landable-caret';
138
+ import { registerBuiltInBlocks } from './built-in-blocks';
139
+ import { BLOCK_CONTENT_SELECTOR } from './block-content-selector';
140
+
141
+ registerBuiltInBlocks();
142
+ bootstrapCodeLanguages();
143
+ runStartupInvariantChecks();
144
+
145
+ // `__registryEnablement` is a harness-only door; the intersection keeps it off the
146
+ // public EditorProps type.
147
+ let {
148
+ source = '',
149
+ resolveImageUrl,
150
+ resolveLinkUrl,
151
+ imageLoadPolicy = 'auto',
152
+ onLinkActivate,
153
+ onPasteImage,
154
+ header,
155
+ blockDragHandles = false,
156
+ searchBar = true,
157
+ searchBarAnchor,
158
+ keybindings,
159
+ theme = 'dark',
160
+ presentationMode = 'source',
161
+ scrollMode = 'self',
162
+ plugins,
163
+ __registryEnablement
164
+ }: EditorProps & { __registryEnablement?: KindEnablement } = $props();
165
+
166
+ // Snapshotted, not read live: set-once by contract, and a live read inside the
167
+ // windowing scopes' derived would make `scrollMode` a dependency of the hottest path.
168
+ // svelte-ignore state_referenced_locally
169
+ const hostScroll = scrollMode === 'host';
170
+
171
+ // Host mode asks two different questions one walk cannot serve (`cursor/
172
+ // scroll-ancestors` header): what a drag autoscrolls, and what bounds the visible
173
+ // region. Memoized on first read, so a host that swaps its scroller must remount.
174
+ let resolvedScrollHost: UserScrollport | null = null;
175
+ let resolvedClipBounds: HTMLElement[] = [];
176
+ let hostResolved = false;
177
+ function resolveHost(): void {
178
+ if (hostResolved || !editorEl) return;
179
+ resolvedScrollHost = userScrollportFor(editorEl);
180
+ resolvedClipBounds = clippingAncestors(editorEl);
181
+ hostResolved = true;
182
+ }
183
+ /** What a drag autoscrolls: the root in self mode, the nearest scrollable ancestor
184
+ * in host mode. Null only before the root mounts. */
185
+ function getScrollHost(): UserScrollport | null {
186
+ if (!hostScroll) return editorEl ?? null;
187
+ resolveHost();
188
+ return resolvedScrollHost;
189
+ }
190
+ /** Every clipping ancestor; their intersection with the viewport is what a reveal
191
+ * must land inside. */
192
+ function getClipBounds(): HTMLElement[] {
193
+ if (!hostScroll) return [];
194
+ resolveHost();
195
+ return resolvedClipBounds;
196
+ }
197
+
198
+ // The scrollport every windowing scope measures and writes, over the SAME scroller the
199
+ // autoscroll seam resolves — so the mode picks the target and nothing downstream branches
200
+ // on it. Memoized with that resolution.
201
+ let scrollport: Scrollport | null = null;
202
+ function getScrollport(): Scrollport | null {
203
+ if (!scrollport) {
204
+ const target = getScrollHost();
205
+ if (target) scrollport = createScrollport(target);
206
+ }
207
+ return scrollport;
208
+ }
209
+
210
+ // Install before initDocument parses `source`, so plugin openers/directives are live
211
+ // for the seed grammar. Set-once by contract — a later prop change is ignored.
212
+ // svelte-ignore state_referenced_locally
213
+ const pluginEntries = plugins?.length ? normalizePluginEntries(plugins) : undefined;
214
+ if (pluginEntries) installPlugins(pluginEntries.plugins);
215
+
216
+ // The prop IS the enablement set: this editor activates exactly what it listed. No prop
217
+ // means no restriction, so everything installed in the process stays active here.
218
+ const activePlugins = pluginEntries
219
+ ? activationFor(pluginEntries.plugins.map((p) => p.name))
220
+ : everyInstalledPlugin;
221
+
222
+ const overridesMap = $derived(normalizeKeybindingOverrides(keybindings));
223
+
224
+ // The one mode every door reports (root attribute, context getter, plugin contexts,
225
+ // events), and the seam an effective-vs-requested divergence would land in.
226
+ const effectiveMode = $derived(presentationMode);
227
+ // Replace is an edit, so it never engages in reading mode. One predicate feeds the
228
+ // write sites, the render gate, and the replace closures.
229
+ const canReplace = $derived(effectiveMode !== 'reading');
230
+
231
+ const resolveImageUrlImpl: ResolveImageUrl = (u) => (resolveImageUrl ? resolveImageUrl(u) : u);
232
+ const resolveLinkUrlImpl: ResolveLinkUrl = (u) => (resolveLinkUrl ? resolveLinkUrl(u) : u);
233
+ const activateLink = (url: string, event: MouseEvent) =>
234
+ onLinkActivate
235
+ ? onLinkActivate(url, event)
236
+ : defaultLinkActivation(url, event, (blocked) => emitBlockedLinkError(events, blocked));
237
+
238
+ // ── State ───────────────────────────────────────────────────────────
239
+
240
+ function initDocument(src: string): {
241
+ doc: Document;
242
+ resolver: LinkReferenceResolver;
243
+ signature: string;
244
+ } {
245
+ const d = parse(src, { scope: 'document' });
246
+ if (d.children.length === 0) {
247
+ // Only the empty source parses to zero blocks — a blank line is a block of its
248
+ // own — so there is no authored ending to inherit and LF is the whole answer.
249
+ d.children.push(emptyParagraph('', '\n'));
250
+ }
251
+ for (const child of d.children) {
252
+ ensureEditableContainers(child);
253
+ }
254
+ const refMap = buildLinkReferenceMap(d.children);
255
+ return { doc: d, resolver: refMap.resolve, signature: refMap.signature };
256
+ }
257
+
258
+ // doc/blockIds are mutable state structural ops write through directly, so they
259
+ // cannot be $derived: snapshot at mount, re-sync via the $effect below.
260
+ // svelte-ignore state_referenced_locally
261
+ const initial = initDocument(source);
262
+ let doc = $state<Document>(initial.doc);
263
+ // svelte-ignore state_referenced_locally
264
+ let blockIds = $state<string[]>(assignIds(doc.children));
265
+ // Bumped by every byte-writing door. Inline widgets derive on it directly, and the
266
+ // decoration engine's `editEpoch` rides it a tick later.
267
+ const contentVersion = createContentVersion();
268
+ let currentResolver = $state<LinkReferenceResolver>(initial.resolver);
269
+ let currentSignature = $state<string>(initial.signature);
270
+ // Reference-bearing render memos key on this instead of the whole (~MB) signature.
271
+ let signatureEpoch = $state<number>(0);
272
+ /** One ref for every reader — the block components through context and the action bundles
273
+ * through their deps — so a post-commit rebuild reaches both without re-binding either. */
274
+ const linkRefView: LinkReferenceResolverRef = {
275
+ get current(): LinkReferenceResolver {
276
+ return currentResolver;
277
+ },
278
+ get signature(): string {
279
+ return currentSignature;
280
+ },
281
+ get epoch(): number {
282
+ return signatureEpoch;
283
+ }
284
+ };
285
+ // Plain, not `$state`: the top-level scope's slot storage (see `refSlotsOver`).
286
+ const blockRefs: (BlockComponent | undefined)[] = [];
287
+ const blockRefSlots = refSlotsOver(blockRefs);
288
+ let editorEl: HTMLDivElement | undefined = $state();
289
+ // Inside a themed host the editor sits under no opt-in class, and the portaled search
290
+ // bar must not carry one either: the class's defaults would shadow the host tokens the
291
+ // anchor already inherits.
292
+ const inThemedScope = $derived(!!editorEl?.closest('.aragonite-editor-theme'));
293
+ let headerEl: HTMLDivElement | undefined = $state();
294
+ let typeScaleProbeEl: HTMLDivElement | undefined = $state();
295
+ const undoManager = createUndoManager();
296
+ const sharing = createSharingState();
297
+ const stickyColumn = createStickyColumnState();
298
+ // Composed, not wired seam by seam: the marks are ephemeral caret state with the affinity's
299
+ // exact lifetime, so every door that invalidates the arrival side drops them by construction.
300
+ const pendingMarks = createPendingMarksState();
301
+ const edgeAffinity = createEdgeAffinityState({ onInvalidate: pendingMarks.reset });
302
+ const revealAnchor = createRevealAnchorState();
303
+ const operationsLog = createOperationsLog();
304
+ const events = createEditorEvents();
305
+ // getSelection is function-hoisted below — callback reads the fresh snapshot each time.
306
+ const selectionState = createSelectionState({
307
+ onChange: () => {
308
+ // The other half of the mutual exclusion `onSelect` carries: a range opened while a
309
+ // widget is selected (select-all declines to the widget's own keydown) would leave
310
+ // both live, and every dispatch keyed on "a widget is selected" would answer for
311
+ // the document-wide selection the user is looking at.
312
+ if (selectionState.isCrossBlock) widgetSelection.clear();
313
+ events.emit('selectionChange', getSelection());
314
+ },
315
+ getDoc: () => doc
316
+ });
317
+ const widgetSelection = createWidgetSelectionState({
318
+ onSelect: () => {
319
+ window.getSelection()?.removeAllRanges();
320
+ // Announced like the `source` swap: dropping the native range ends the document
321
+ // caret without moving a field the clear guards on, and the native `selectionchange`
322
+ // it fires bails on the empty range before it reaches the channel.
323
+ selectionState.batch(() => {
324
+ selectionState.clear();
325
+ selectionState.announceSelection();
326
+ });
327
+ }
328
+ });
329
+
330
+ let selectionDescription = $derived(
331
+ selectionState.isCrossBlock && selectionState.anchor && selectionState.focus
332
+ ? createSelectionDescription({ anchor: selectionState.anchor, focus: selectionState.focus })
333
+ : ''
334
+ );
335
+
336
+ // Its own polite region: clobbering selectionDescription would drop the move from
337
+ // the a11y tree.
338
+ let reorderAnnouncement = $state('');
339
+
340
+ // Single elements, not per-block, so the hover/drag path adds no cost per mounted
341
+ // component.
342
+ let reorderGhost = $state<{ clientX: number; clientY: number; label: string } | null>(null);
343
+ let reorderLine = $state<{ left: number; top: number; width: number } | null>(null);
344
+
345
+ $effect(() => {
346
+ const dispose = events.on('edit', (e) => {
347
+ operationsLog.record({
348
+ op: e.op,
349
+ path: e.path,
350
+ detail: ('detail' in e ? e.detail : undefined) ?? {}
351
+ });
352
+ // The shell maintains only the LRD resolver (inline content computes lazily
353
+ // on read — core/inline/inline-cache), and hands out a fresh identity only on
354
+ // a real signature change: one per edit re-renders every block that read it.
355
+ if (lrdMapCouldChange(doc, e)) {
356
+ const newMap = buildLinkReferenceMap(doc.children);
357
+ const next = advanceSignatureEpoch(currentSignature, signatureEpoch, newMap.signature);
358
+ if (next.epoch !== signatureEpoch) {
359
+ currentResolver = newMap.resolve;
360
+ currentSignature = next.signature;
361
+ signatureEpoch = next.epoch;
362
+ }
363
+ }
364
+ });
365
+ return () => dispose();
366
+ });
367
+
368
+ // The one bump site for `editEpoch`. It rides the content version rather than the `edit`
369
+ // event, whose `input` is batched across a typing burst and would leave every source a
370
+ // pause behind the bytes; the tick keeps a source off a half-applied tree, and the
371
+ // no-source skip keeps an undecorated editor at zero keystroke work (perf:check).
372
+ let notifiedVersion = contentVersion.read();
373
+ $effect(() => {
374
+ const version = contentVersion.read();
375
+ if (version === notifiedVersion) return; // the mount run announces nothing
376
+ notifiedVersion = version;
377
+ if (decorationEngine.sourceCount > 0) void tick().then(() => decorationEngine.notifyEdit());
378
+ });
379
+
380
+ // Counts whole-document REPLACEMENTS, which the edit epoch cannot tell from a
381
+ // keystroke. Deliberately NOT $state: its readers run inside decoration `provide`,
382
+ // which must register no reactive dependency.
383
+ let documentGeneration = 0;
384
+
385
+ // `source !== lastSource` guard is load-bearing — see `docs/design/editor.md` § Reactive state plumbing.
386
+ // svelte-ignore state_referenced_locally
387
+ let lastSource = source;
388
+ $effect(() => {
389
+ if (source !== lastSource) {
390
+ // A pending typing batch addresses the OUTGOING document, so it flushes
391
+ // while its path still resolves; left armed, the timer fires note A's path
392
+ // against note B.
393
+ controller.flushDebouncedCheckpoint();
394
+ lastSource = source;
395
+ const reset = initDocument(source);
396
+ doc = reset.doc;
397
+ contentVersion.bump();
398
+ blockIds = assignIds(doc.children);
399
+ blockRefs.length = 0;
400
+ // Block ids never recur, so every measured height now keys a block that cannot
401
+ // come back: the scopes reseed from estimates exactly as they do on first load.
402
+ heightOracle.dropMeasured();
403
+ undoManager.clear();
404
+ stickyColumn.reset();
405
+ edgeAffinity.reset();
406
+ // Announced, not left to the clear: the swap usually arrives on a plain caret, which
407
+ // is native-only, so nothing editor-owned moves and subscribers would keep painting
408
+ // the outgoing document's selection. Batched, so a real range still emits once.
409
+ selectionState.batch(() => {
410
+ selectionState.clear();
411
+ selectionState.announceSelection();
412
+ });
413
+ documentGeneration++;
414
+ // The resolver refreshes unconditionally — the old one closes over the
415
+ // swapped-out doc — but the epoch bumps only on a differing LRD signature.
416
+ const next = advanceSignatureEpoch(currentSignature, signatureEpoch, reset.signature);
417
+ currentResolver = reset.resolver;
418
+ currentSignature = next.signature;
419
+ signatureEpoch = next.epoch;
420
+ }
421
+ });
422
+
423
+ /**
424
+ * The host's own chrome, mounted inside this root. Every rule meaning "this is the
425
+ * editor's own CONTENT" asks here rather than carrying its own `contains` copy,
426
+ * which is how one gets missed. The focusout guards keep using `contains` — for
427
+ * "did focus leave the whole widget", the slot IS part of the editor.
428
+ */
429
+ function isHostChrome(node: Node | null): boolean {
430
+ return !!node && !!headerEl && headerEl.contains(node);
431
+ }
432
+
433
+ // ── Dead-space caret ────────────────────────────────────────────────
434
+
435
+ // A click in the root's padding or below the last block places a caret rather than
436
+ // doing nothing. `getBlockComponent` is hoisted; the reset closure defers its reads.
437
+ const deadSpaceCaret = createDeadSpaceCaret({
438
+ getBlockComponent,
439
+ resetSelectionForClick: () =>
440
+ resetForPointerDown(selectionState, stickyColumn, edgeAffinity, false),
441
+ gapScope: {
442
+ getDoc: () => doc,
443
+ selection: selectionState,
444
+ getPresentationMode: () => effectiveMode
445
+ },
446
+ lastBlockIndex: () => doc.children.length - 1,
447
+ revealBlock: (index) => revealPath([index])
448
+ });
449
+
450
+ // ── Link card door ──────────────────────────────────────────────────
451
+
452
+ // The caret snapshot and the entry guards ride the STATE, not the callers, so entry path N+1
453
+ // cannot forget them. All three decline a cross-block range absolutely; on a same-block one
454
+ // they split by gesture: an unasked-for click must not interrupt it, the create gesture wraps
455
+ // it, and the chord has already resolved it against the construct it opens.
456
+ const linkCard = createLinkCardState({
457
+ onOpen: () => linkCardCaret.saveCurrent(),
458
+ canOpen: () => !selectionState.isCrossBlock && window.getSelection()?.isCollapsed !== false,
459
+ canEnter: () => !selectionState.isCrossBlock,
460
+ canOpenCreate: () =>
461
+ !selectionState.isCrossBlock && window.getSelection()?.isCollapsed === false
462
+ });
463
+
464
+ /** Open the card on the link `el` renders, or report that nothing there is one. The caret has
465
+ * already landed from mousedown, which is the one the state snapshots. */
466
+ function openLinkCard(el: Element): boolean {
467
+ const path = findSurfacePathForElement(el);
468
+ if (!path) return false;
469
+ const block = nodeAt(doc, path);
470
+ if (block === null || !isBlockNode(block)) return false;
471
+ const contentEl = getBlockElByPath(path);
472
+ if (!contentEl) return false;
473
+ const hit = resolveLinkAtPoint({ contentEl, block, path, linkRef: linkRefView });
474
+ if (!hit) return false;
475
+ return linkCard.open(hit.target);
476
+ }
477
+
478
+ // The card belongs to live mode alone; any other mode paints the destination bytes already.
479
+ $effect(() => {
480
+ if (effectiveMode !== 'live') linkCard.close();
481
+ });
482
+
483
+ // ── Hidden-run class probe ──────────────────────────────────────────
484
+
485
+ // Once per mode change, the probe pays the getComputedStyle the per-keystroke hidden-run
486
+ // predicate cannot afford, so the two class vocabularies cannot drift silently.
487
+ $effect(() => {
488
+ void effectiveMode;
489
+ if (!editorEl) return;
490
+ const root = editorEl;
491
+ assertInvariant('marker-css-parity', () => checkMarkerCssParity(root));
492
+ });
493
+
494
+ // ── Root gesture listeners ──────────────────────────────────────────
495
+
496
+ $effect(() => {
497
+ if (!editorEl) return;
498
+ const root = editorEl;
499
+ const handleClick = (e: MouseEvent) => {
500
+ const target = e.target as Element | null;
501
+ // Ahead of the anchor arm: a blocked-scheme link renders as a SPAN, and it is exactly
502
+ // the link a user opens the card to fix. Mod-click still activates, below.
503
+ if (effectiveMode === 'live' && !e.ctrlKey && !e.metaKey) {
504
+ const linkEl = target?.closest(LINK_ELEMENT_SELECTOR);
505
+ if (linkEl && !isHostChrome(linkEl) && openLinkCard(linkEl)) {
506
+ e.preventDefault();
507
+ return;
508
+ }
509
+ }
510
+ const anchor = target?.closest('a[href]') as HTMLAnchorElement | null;
511
+ // The helper claims only clicks whose target IS the root, so nothing the
512
+ // editor renders is touched.
513
+ if (!anchor) {
514
+ deadSpaceCaret.handleClick(root, e);
515
+ return;
516
+ }
517
+ // Host chrome follows the page's link behaviour, not plain-click-edits.
518
+ if (isHostChrome(anchor)) return;
519
+ const href = anchor.getAttribute('href');
520
+ if (!href) return;
521
+ // Reading mode has no caret for a plain click to place, so links behave as
522
+ // in a rendered document.
523
+ if (e.ctrlKey || e.metaKey || effectiveMode === 'reading') {
524
+ e.preventDefault();
525
+ activateLink(href, e);
526
+ } else {
527
+ // Suppress the browser's link navigation; cursor placement comes from
528
+ // mousedown and is unaffected.
529
+ e.preventDefault();
530
+ }
531
+ };
532
+ return removeAll(
533
+ onRoot(root, 'click', handleClick),
534
+ onRoot(root, 'mousedown', (e: MouseEvent) => deadSpaceCaret.notePress(root, e))
535
+ );
536
+ });
537
+
538
+ // Release on the next user-intent gesture, so the anchor holds only through the post-reveal
539
+ // settle. NOT on `scroll`: a programmatic correctAnchor write fires `scroll` itself and
540
+ // would self-release mid-settle. On the resolved PORT, not the root — the pin fights
541
+ // whoever scrolls the port, and in host mode that gesture lands outside the editor.
542
+ $effect(() => {
543
+ if (!editorEl) return;
544
+ const target = getScrollHost();
545
+ if (!target) return;
546
+ const release = () => revealAnchor.releaseAll();
547
+ return removeAll(
548
+ onRoot(target, 'keydown', release),
549
+ onRoot(target, 'pointerdown', release),
550
+ onRoot(target, 'wheel', release, { passive: true })
551
+ );
552
+ });
553
+
554
+ $effect(() => {
555
+ if (!editorEl) return;
556
+ const root = editorEl;
557
+ // focusout bubbles, so reset only when focus leaves the editor entirely.
558
+ return onRoot(root, 'focusout', (e: FocusEvent) => {
559
+ const next = e.relatedTarget as Node | null;
560
+ if (next && root.contains(next)) return;
561
+ stickyColumn.reset();
562
+ edgeAffinity.reset();
563
+ });
564
+ });
565
+
566
+ // Its own effect: this reads no root binding, so pairing it with the focusout one
567
+ // would make it wait for the bind and re-install on every root change.
568
+ $effect(() =>
569
+ onRoot(document, 'visibilitychange', () => {
570
+ if (document.visibilityState === 'hidden') {
571
+ stickyColumn.reset();
572
+ edgeAffinity.reset();
573
+ }
574
+ })
575
+ );
576
+
577
+ // Register as a body-chord claimant so the document-level keydown handler routes a
578
+ // body-level chord to exactly one instance: a lone editor claims unconditionally,
579
+ // among several the last-interacted one wins.
580
+ $effect(() => {
581
+ if (!editorEl) return;
582
+ const root = editorEl;
583
+ registerEditor(root);
584
+ const removeMark = onRoot(root, 'focusin', () => markEditorInteracted(root));
585
+ return () => {
586
+ removeMark();
587
+ releaseInteractedEditor(root);
588
+ unregisterEditor(root);
589
+ };
590
+ });
591
+
592
+ // ── Block element and component lookup ──────────────────────────────
593
+
594
+ // The measurement surface for cross-block caret math. Table cells carry no
595
+ // data-block-path (they render without BlockHost), so a deep cell path resolves
596
+ // the table wrapper and walks into the cell DOM.
597
+ const getBlockElByPath: BlockElLookup = (path) => {
598
+ if (!editorEl) return null;
599
+ const directWrapper = editorEl.querySelector(`[data-block-path='${JSON.stringify(path)}']`);
600
+ if (directWrapper) {
601
+ return directWrapper.querySelector(BLOCK_CONTENT_SELECTOR) as HTMLElement | null;
602
+ }
603
+ if (path.length < 3) return null;
604
+ const tablePath = path.slice(0, -2);
605
+ const rowIdx = path[path.length - 2];
606
+ const colIdx = path[path.length - 1];
607
+ const tableWrapper = editorEl.querySelector(`[data-block-path='${JSON.stringify(tablePath)}']`);
608
+ if (!tableWrapper) return null;
609
+ const tableEl = tableWrapper.querySelector(':scope > [role="table"]');
610
+ if (!tableEl) return null;
611
+ const rowEl = tableEl.querySelector(`:scope > [data-table-row-idx='${rowIdx}']`);
612
+ if (!rowEl) return null;
613
+ const cells = rowEl.querySelectorAll(':scope > [role="cell"]');
614
+ return (cells[colIdx] as HTMLElement | undefined) ?? null;
615
+ };
616
+
617
+ // The non-scrolling sibling of revealPath, and the one descent both the rect API
618
+ // and the test surface consume — a second closure would drift from it.
619
+ function getBlockComponent(path: number[]): BlockComponent | null {
620
+ if (path.length === 0) return null;
621
+ const [first, ...rest] = path;
622
+ const ref = blockRefs[first];
623
+ if (!ref) return null;
624
+ if (rest.length === 0) return ref;
625
+ return ref.getBlockComponentByPath?.(rest) ?? null;
626
+ }
627
+
628
+ // ── Action Bundles ──────────────────────────────────────────────────
629
+
630
+ // Hoisted so the deps literal below can reference it before the VR state it reads
631
+ // is declared; the body runs only at call time, post-init.
632
+ async function revealPath(path: number[]): Promise<BlockComponent | null> {
633
+ if (path.length === 0) return null;
634
+ const top = path[0];
635
+ // The shared reveal-and-wait gate skips an already-mounted block, re-checks after
636
+ // a spurious cross-level wake, and — load-bearing for VR-5 — degrades instead of
637
+ // hanging when a stale model left `top` outside the recomputed window.
638
+ await revealChildOrWait(top, {
639
+ slots: blockRefSlots,
640
+ childCount: doc.children.length,
641
+ revealChild: topWindowing.revealChild,
642
+ isInWindow: topWindowing.isInWindow
643
+ });
644
+ const ref = blockRefs[top];
645
+ if (!ref) return null;
646
+ if (path.length === 1) return ref;
647
+ return ref.revealByPath
648
+ ? await ref.revealByPath(path.slice(1))
649
+ : (ref.getBlockComponentByPath?.(path.slice(1)) ?? null);
650
+ }
651
+
652
+ // The instance's resolution over the global block definitions: an unlisted plugin's kind
653
+ // resolves no component here and its opener leaves this grammar. A prop-less editor reads
654
+ // the global registry verbatim.
655
+ // The harness door composes rather than replaces: widening past what the prop activated
656
+ // would prove a resolution the shipped path cannot reach.
657
+ // svelte-ignore state_referenced_locally
658
+ const registryView = createRegistryView({
659
+ isEnabled: bothEnable(
660
+ pluginEntries ? kindEnablementFor(activePlugins) : undefined,
661
+ __registryEnablement
662
+ )
663
+ });
664
+
665
+ const editorActionsDeps: EditorActionsDeps = {
666
+ get doc() {
667
+ return doc;
668
+ },
669
+ get blockIds() {
670
+ return blockIds;
671
+ },
672
+ get blockRefs() {
673
+ return blockRefs;
674
+ },
675
+ blockRefSlots,
676
+ setDoc: (v) => {
677
+ doc = v;
678
+ },
679
+ bumpContentVersion: contentVersion.bump,
680
+ setBlockIds: (v) => {
681
+ blockIds = v;
682
+ },
683
+ setBlockRefs: (v) => replaceRefs(blockRefs, v),
684
+ undoManager,
685
+ sharing,
686
+ stickyColumn,
687
+ edgeAffinity,
688
+ selectionState,
689
+ getBlockElByPath,
690
+ revealPath,
691
+ events,
692
+ grammar: registryView.grammar,
693
+ getPresentationMode: () => effectiveMode,
694
+ get linkRef() {
695
+ return linkRefView;
696
+ }
697
+ };
698
+ const { blockEdit, focus, history, containerEdit, controller } =
699
+ createEditorActions(editorActionsDeps);
700
+
701
+ // A getter, so block components read the live doc at keystroke time rather than
702
+ // the snapshot they mounted with.
703
+ const getDoc: DocumentGetter = () => doc;
704
+
705
+ // Ahead of the plugin contexts because the plugin door hands its registry into
706
+ // createEditorPluginContexts below.
707
+ const decorationEngine = createDecorationEngine({
708
+ getDoc,
709
+ onSourceError: (source, error) =>
710
+ events.emit('error', { origin: 'decoration', error, context: { source } })
711
+ });
712
+ const decorations: DecorationRegistry = { addSource: decorationEngine.addSource };
713
+
714
+ // Reuses revealPath/getBlockElByPath/getBlockComponent so nothing measures through
715
+ // a second closure.
716
+ const rects = createEditorRects({
717
+ getBlockElByPath,
718
+ getBlockComponentByPath: getBlockComponent,
719
+ revealPath,
720
+ getEditorRoot: () => editorEl ?? null,
721
+ isHostScroll: () => hostScroll,
722
+ getClipBounds,
723
+ isCrossBlock: () => selectionState.isCrossBlock,
724
+ isHostChrome,
725
+ revealAnchor,
726
+ // A navigation holds its pin, unlike the consumer restore door: nothing follows
727
+ // it that wants the viewport back, and the band should outlive a late decode.
728
+ landCaretAt: landCaretAtOffset
729
+ });
730
+
731
+ // After getDoc so it reuses that one live-doc closure: a second getDoc would be a
732
+ // TDZ reference here, and the rule is one getter, never a captured value.
733
+ const editorId = mintEditorId();
734
+ const pluginContexts = createEditorPluginContexts({
735
+ editorId,
736
+ getDoc,
737
+ events,
738
+ optionsFor: (name) => pluginEntries?.optionsByName.get(name),
739
+ decorations,
740
+ rects,
741
+ // The one injection point of the mode into the dispatch tiers; they read it back
742
+ // through the pluginEditor lookup they already thread.
743
+ getPresentationMode: () => effectiveMode,
744
+ getTheme: () => theme,
745
+ activation: activePlugins
746
+ });
747
+
748
+ // One definition, threaded by every dispatch tier that can reach a plugin-global
749
+ // handler, so leaf, cross-block and editor-root route identically.
750
+ const pluginEditorLookup: PluginEditorLookup = (name) => pluginContexts.get(name);
751
+ const commandErrorSink: CommandErrorSink = (report) => emitCommandError(events, report);
752
+
753
+ // onMount, NEVER a plain $effect: attachAll synchronously runs plugin callbacks that
754
+ // read reactive state, so an effect would take doc.children as a dependency and the
755
+ // first structural edit would dispose every subscription (casebook.md's re-init scar).
756
+ onMount(() => {
757
+ pluginContexts.attachAll(({ plugin, error }) =>
758
+ events.emit('error', { origin: 'subscriber', error, context: { plugin } })
759
+ );
760
+ return () => pluginContexts.dispose();
761
+ });
762
+
763
+ // Aborted on unmount; document-level listeners observe it to cancel mid-operation work.
764
+ const lifetimeController = new AbortController();
765
+ $effect(() => () => {
766
+ // Same reason as the source swap: a timer outliving the component emits into
767
+ // subscribers the host still holds, for a document that is gone.
768
+ controller.flushDebouncedCheckpoint();
769
+ lifetimeController.abort();
770
+ });
771
+
772
+ // Per-instance so two editors on one page never leak load failures into each
773
+ // other's broken-state recompute.
774
+ const brokenImageUrls = new Set<string>();
775
+
776
+ const pasteCoordinator = createPasteCoordinator(controller, revealPath);
777
+
778
+ // The document caret while chrome holds focus (selection/caret-restore.ts). One instance PER
779
+ // consumer: a card opened over an open search bar would otherwise overwrite the pre-search
780
+ // caret with its own, and closing the bar would land the user at the link.
781
+ const searchCaret = createCaretRestore(() => editorEl ?? null);
782
+ const linkCardCaret = createCaretRestore(() => editorEl ?? null);
783
+
784
+ const searchReplace = createSearchReplace(editorActionsDeps, controller);
785
+ // Find stays live in reading mode; replace is an edit and no-ops at this seam.
786
+ const gatedSearchReplace: typeof searchReplace = {
787
+ replaceOne: (match, template) =>
788
+ canReplace ? searchReplace.replaceOne(match, template) : Promise.resolve(0),
789
+ replaceAll: (matches, template) =>
790
+ canReplace ? searchReplace.replaceAll(matches, template) : Promise.resolve(0)
791
+ };
792
+ const searchState = createSearchState({
793
+ getDoc,
794
+ getDocumentGeneration: () => documentGeneration,
795
+ decorations,
796
+ replace: gatedSearchReplace,
797
+ // Rides the one public seam, which also owns the reveal anchor (top-pinned by
798
+ // default, which is what search wants), so the band's async image-decode churn
799
+ // can't clamp the reveal off the match.
800
+ reveal: (p) => rects.scrollTo(p),
801
+ onClose: searchCaret.restore
802
+ });
803
+ // Lives here, not in SearchBar, so the root Ctrl+H and the bar's chevron share one
804
+ // source of truth.
805
+ let replaceExpanded = $state(false);
806
+
807
+ const announceReorder = async (message: string) => {
808
+ // Clear first: Svelte skips the DOM write on a ===-equal assignment, which drops
809
+ // the second of two identical announcements.
810
+ reorderAnnouncement = '';
811
+ await tick();
812
+ reorderAnnouncement = message;
813
+ };
814
+ const reorder = createReorderAction(editorActionsDeps, controller, (to, total) => {
815
+ announceReorder(movedBlockToPosition(to + 1, total));
816
+ });
817
+
818
+ // ── Context provision ───────────────────────────────────────────────
819
+
820
+ // One per instance, shared by every dispatch site's gates: the chord arm, a leaf's rebound
821
+ // chord and the `runCommand` door must reach the same cross-block road.
822
+ const crossBlockCommands = createCrossBlockCommands({
823
+ selection: selectionState,
824
+ getDoc,
825
+ getBlockElByPath,
826
+ revealPath,
827
+ controller,
828
+ getPresentationMode: () => effectiveMode,
829
+ grammar: registryView.grammar,
830
+ getContentVersion: contentVersion.read
831
+ });
832
+
833
+ // The action bundles stay per-key so a container re-provides exactly what it
834
+ // overrides; HISTORY is G1.4's single-provider subject. The rest rides three facets.
835
+ setContext(BLOCK_EDIT_KEY, blockEdit);
836
+ setContext(FOCUS_KEY, focus);
837
+ setContext(HISTORY_KEY, history);
838
+ setContext(CONTAINER_EDIT_KEY, containerEdit);
839
+
840
+ setContext(EDITOR_SERVICES_KEY, {
841
+ events,
842
+ decorations: decorationEngine,
843
+ selection: selectionState,
844
+ search: searchState,
845
+ stickyColumn,
846
+ edgeAffinity,
847
+ pendingMarks,
848
+ revealAnchor,
849
+ widgetSelection,
850
+ linkCard,
851
+ controller,
852
+ pasteCoordinator,
853
+ reorder,
854
+ reorderAnnounce: announceReorder,
855
+ registryView,
856
+ activePlugins,
857
+ rects,
858
+ crossBlockCommands
859
+ } satisfies EditorServices);
860
+
861
+ setContext(EDITOR_POLICIES_KEY, {
862
+ resolveImageUrl: resolveImageUrlImpl,
863
+ resolveLinkUrl: resolveLinkUrlImpl,
864
+ imageLoadPolicy: () => imageLoadPolicy,
865
+ // Reading mode forces the affordances off through the prop's own funnel; the handle
866
+ // and the table grips all read this one getter.
867
+ blockDragHandles: () => blockDragHandles && effectiveMode !== 'reading',
868
+ presentationMode: () => effectiveMode,
869
+ theme: () => theme,
870
+ keybindingOverrides: () => overridesMap,
871
+ // An accessor, not the `onPasteImage,` shorthand: the shorthand captures the prop
872
+ // and svelte-check reports `state_referenced_locally`, which
873
+ // `svelte/no-unused-svelte-ignore` won't let us suppress.
874
+ get onPasteImage() {
875
+ return onPasteImage;
876
+ },
877
+ brokenImageUrls
878
+ } satisfies EditorPolicies);
879
+
880
+ // ── Root DOM effects ────────────────────────────────────────────────
881
+
882
+ /** The focused leaf's caret as (path, raw offset): the per-backend road while a leaf holds
883
+ * focus, else the native range a toggle click leaves behind while chrome takes focus. */
884
+ function captureFlipCaret(): { path: number[]; offset: number } | null {
885
+ if (selectionState.isCrossBlock || selectionState.gapCaret) return null;
886
+ const focused = readCurrentSelection(selectionState, blockRefs)?.focus;
887
+ if (focused) return { path: focused.path, offset: focused.offset };
888
+ const sel = window.getSelection();
889
+ if (!sel?.focusNode || !editorEl?.contains(sel.focusNode) || isHostChrome(sel.focusNode))
890
+ return null;
891
+ const node = sel.focusNode;
892
+ const el = node instanceof Element ? node : node.parentElement;
893
+ const path = findSurfacePathForElement(el);
894
+ if (!path) return null;
895
+ const contentEl = getBlockElByPath(path);
896
+ if (!contentEl?.contains(node)) return null;
897
+ const offset = toClampedRawOffset(
898
+ domTextOffsetAtNode(contentEl, node, sel.focusOffset),
899
+ ambientLengthOf(contentEl)
900
+ );
901
+ return { path, offset };
902
+ }
903
+
904
+ // The flip's PRE phase, the last moment the outgoing mode owns the DOM: past it the mode's
905
+ // render key has rebuilt every block from its own CST bytes, and the reveal's ephemeral edit
906
+ // is gone. Reading keeps its entry snapshot — no caret of its own to recapture on the way out.
907
+ let flipCaret: { path: number[]; offset: number } | null = null;
908
+ // svelte-ignore state_referenced_locally
909
+ let preFlipSeenMode = effectiveMode;
910
+ $effect.pre(() => {
911
+ const mode = effectiveMode;
912
+ if (mode === preFlipSeenMode) return;
913
+ const from = preFlipSeenMode;
914
+ preFlipSeenMode = mode;
915
+ untrack(() => {
916
+ if (from !== 'reading') flipCaret = captureFlipCaret();
917
+ // A flip is a blur-class event: a live reveal or composition folds through the existing
918
+ // blur choke point. Host chrome is exempt, or a mode toggle blurs a title field mid-edit.
919
+ const active = document.activeElement;
920
+ if (active instanceof HTMLElement && editorEl?.contains(active) && !isHostChrome(active)) {
921
+ active.blur();
922
+ // A blur the editor performs announces the selection it drops: the document listener
923
+ // only reports a range the browser still anchors in the root, and this one is gone.
924
+ events.emit('selectionChange', getSelection());
925
+ }
926
+ });
927
+ });
928
+
929
+ // svelte-ignore state_referenced_locally
930
+ let lastEffectiveMode = effectiveMode;
931
+ $effect(() => {
932
+ const mode = effectiveMode;
933
+ if (mode === lastEffectiveMode) return;
934
+ lastEffectiveMode = mode;
935
+ // Which markers paint just changed, so a side recorded against the old geometry
936
+ // no longer names the offset the user meant.
937
+ edgeAffinity.reset();
938
+ // Hidden markers re-wrap prose, so every measured height is the other mode's. Not paired
939
+ // with `widthVersion++`: the flip has blurred, so a rebuild here loses the caret pin.
940
+ heightOracle.dropMeasured();
941
+ if (mode === 'reading') {
942
+ // The gap is an editor-owned caret no DOM blur can reach, so the flip clears it
943
+ // rather than each arrival path.
944
+ selectionState.clearGapCaret();
945
+ } else if (flipCaret) {
946
+ const caret = flipCaret;
947
+ flipCaret = null;
948
+ void (async () => {
949
+ // A post-tick focus like every structural op's; the road clamps the saved offset
950
+ // into the destination mode's landable range at the door. Yielding to a focused
951
+ // text-entry surface keeps the restore from stealing a host field mid-typing.
952
+ // The reveal is the bare MOUNT: a flip is a view operation, so it re-seats the
953
+ // caret without writing the scrollport the reader chose.
954
+ await tick();
955
+ if (effectiveMode !== mode || isTextEntrySurface(document.activeElement)) return;
956
+ await restoreThroughRevealRoad(caretAt(caret.path, caret.offset), 'mount');
957
+ })();
958
+ }
959
+ events.emit('presentationModeChange', mode);
960
+ });
961
+
962
+ // A theme flip invalidates no live edit, so it only has to be announced — for
963
+ // plugins that paint their own colors and can't see the flip through CSS.
964
+ // svelte-ignore state_referenced_locally
965
+ let lastTheme = theme;
966
+ $effect(() => {
967
+ const next = theme;
968
+ if (next === lastTheme) return;
969
+ lastTheme = next;
970
+ events.emit('themeChange', next);
971
+ });
972
+
973
+ // CSS keys on `data-cross-block` to hide the native caret and selection highlight
974
+ // while the overlay paints the cross-block range. Keyed on the OVERLAY's own predicate:
975
+ // a state it declines to paint must not also lose the caret, or the screen shows neither.
976
+ $effect(() => {
977
+ if (!editorEl) return;
978
+ if (selectionState.isCustomRendered) {
979
+ editorEl.setAttribute('data-cross-block', '');
980
+ } else {
981
+ editorEl.removeAttribute('data-cross-block');
982
+ }
983
+ });
984
+
985
+ $effect(() => {
986
+ if (!editorEl) return;
987
+ return installModActiveTracker(editorEl);
988
+ });
989
+
990
+ // A delegated handle-drag on the root, torn down on unmount via the lifetime signal.
991
+ $effect(() => {
992
+ if (!editorEl) return;
993
+ const handle = installReorderDrag({
994
+ editorRoot: editorEl,
995
+ getScrollHost,
996
+ moveReorderUnit: reorder.moveReorderUnit,
997
+ overlay: {
998
+ setGhost: (g) => (reorderGhost = g),
999
+ setLine: (l) => (reorderLine = l)
1000
+ },
1001
+ lifetimeSignal: lifetimeController.signal
1002
+ });
1003
+ return () => handle.dispose();
1004
+ });
1005
+
1006
+ $effect(() => {
1007
+ if (!editorEl) return;
1008
+ return installSelectionChangeBridge({
1009
+ root: editorEl,
1010
+ isHostChrome,
1011
+ emit: () => events.emit('selectionChange', getSelection())
1012
+ });
1013
+ });
1014
+
1015
+ $effect(() => {
1016
+ if (!editorEl) return;
1017
+ return installEditorBlurAnnouncer({
1018
+ root: editorEl,
1019
+ emit: () => events.emit('selectionChange', getSelection())
1020
+ });
1021
+ });
1022
+
1023
+ // ── Editor-root keydown routing ──────────────────────────────────────
1024
+ //
1025
+ // When the caret's block windows out, focus drops to <body> and the per-block keydown handlers
1026
+ // go silent, so this editor-scope handler reuses the same cross-block composer with the root
1027
+ // and the focus path standing in for `getEl` and `getMyPath`.
1028
+ const editorCrossBlock = createCrossBlockHandlers({
1029
+ getEl: () => editorEl ?? null,
1030
+ getMyPath: () => selectionState.focus?.path ?? [],
1031
+ getIndex: () => selectionState.focus?.path?.[0] ?? 0,
1032
+ selection: selectionState,
1033
+ getDoc,
1034
+ getBlockElByPath,
1035
+ revealPath,
1036
+ getEditorRoot: () => editorEl ?? null,
1037
+ getScrollHost,
1038
+ getEditorLifetime: () => lifetimeController.signal,
1039
+ stickyColumn,
1040
+ edgeAffinity,
1041
+ blockEdit,
1042
+ controller,
1043
+ history,
1044
+ pluginEditor: pluginEditorLookup,
1045
+ getPresentationMode: () => effectiveMode,
1046
+ linkRef: linkRefView,
1047
+ onCommandError: commandErrorSink,
1048
+ crossBlockCommands,
1049
+ pasteCoordinator,
1050
+ getKeybindingOverrides: () => overridesMap,
1051
+ grammar: registryView.grammar,
1052
+ activePlugins,
1053
+ events,
1054
+ getCursorOffset: () => selectionState.focus?.offset ?? null,
1055
+ afterReactivity: () => tick()
1056
+ });
1057
+
1058
+ // Document-level chords for the windowed-out caret, plus the search shortcuts. Every
1059
+ // arm is contained to THIS instance: the listener sees every editor's keystrokes on
1060
+ // the page, so an unguarded handler let one Ctrl+Z revert two editors.
1061
+ const rootKeydown = createEditorRootKeydown({
1062
+ get searchBarEnabled() {
1063
+ return searchBar;
1064
+ },
1065
+ get mode() {
1066
+ return effectiveMode;
1067
+ },
1068
+ get canReplace() {
1069
+ return canReplace;
1070
+ },
1071
+ get keybindingOverrides() {
1072
+ return overridesMap;
1073
+ },
1074
+ get isCrossBlock() {
1075
+ return selectionState.isCrossBlock;
1076
+ },
1077
+ search: searchState,
1078
+ history,
1079
+ pluginEditor: pluginEditorLookup,
1080
+ activation: activePlugins,
1081
+ onCommandError: commandErrorSink,
1082
+ crossBlock: editorCrossBlock,
1083
+ isHostChrome,
1084
+ saveSearchRange: searchCaret.save,
1085
+ setReplaceExpanded: (expanded) => (replaceExpanded = expanded)
1086
+ });
1087
+
1088
+ $effect(() => {
1089
+ if (!editorEl) return;
1090
+ const root = editorEl;
1091
+ return onRoot(root.ownerDocument, 'keydown', (e: KeyboardEvent) =>
1092
+ rootKeydown.handleKeyDown(e, root)
1093
+ );
1094
+ });
1095
+
1096
+ // ── Editor-root clipboard routing ────────────────────────────────────
1097
+ //
1098
+ // The keydown sibling's counterpart: a Ctrl+C/X/V that Chromium retargeted to <body> because
1099
+ // the selection found no text position to park a caret in. Same containment — the arms claim
1100
+ // only events landing on THIS root, or on the body with this instance holding the chord claim.
1101
+ const rootClipboard = createEditorRootClipboard({
1102
+ selection: selectionState,
1103
+ getDoc,
1104
+ crossBlock: editorCrossBlock,
1105
+ // A live policy value, like the accessor the blocks' policies context hands out.
1106
+ get onPasteImage() {
1107
+ return onPasteImage;
1108
+ },
1109
+ events,
1110
+ getSelectedWidgetBlock: () => {
1111
+ const selected = widgetSelection.getSelected();
1112
+ return selected ? getBlockComponent(selected.paragraphPath) : null;
1113
+ }
1114
+ });
1115
+
1116
+ $effect(() => {
1117
+ if (!editorEl) return;
1118
+ const root = editorEl;
1119
+ const doc = root.ownerDocument;
1120
+ return removeAll(
1121
+ onRoot(doc, 'copy', (e: ClipboardEvent) => rootClipboard.handleCopy(e, root)),
1122
+ onRoot(doc, 'cut', (e: ClipboardEvent) => rootClipboard.handleCut(e, root)),
1123
+ onRoot(doc, 'paste', (e: ClipboardEvent) => rootClipboard.handlePaste(e, root))
1124
+ );
1125
+ });
1126
+
1127
+ // ── Height oracle ───────────────────────────────────────────────────
1128
+
1129
+ // How far the host scaled the type off the size HEIGHT_ESTIMATES were calibrated
1130
+ // at. Plain `let`, not `$state`: the oracle reads it inside `estimate()`, the
1131
+ // feature's hottest path, and `widthVersion` is already the rebuild signal.
1132
+ let typeScale = 1;
1133
+
1134
+ // Only the font-relative terms scale: block chrome is absolute padding and an
1135
+ // image's height is its own. Getters, so a scale change lands without rebuilding
1136
+ // the oracle or dropping its measured heights.
1137
+ const heightOracle = createHeightOracle({
1138
+ get lineHeight() {
1139
+ return HEIGHT_ESTIMATES.proseLineHeight * typeScale;
1140
+ },
1141
+ get codeLineHeight() {
1142
+ return HEIGHT_ESTIMATES.codeLineHeight * typeScale;
1143
+ },
1144
+ get avgCharWidth() {
1145
+ return HEIGHT_ESTIMATES.avgCharWidth * typeScale;
1146
+ },
1147
+ blockChrome: HEIGHT_ESTIMATES.blockChrome,
1148
+ imageBlockMinHeight: HEIGHT_ESTIMATES.imageBlockMinHeight
1149
+ });
1150
+
1151
+ // ── Resize invalidation ─────────────────────────────────────────────
1152
+
1153
+ // A WIDTH change re-wraps prose, staling every cached height, so the scopes rebuild
1154
+ // off this counter; a height-only resize spares the measured cache. ResizeObserver's
1155
+ // per-callback batching is the coalescing — no setTimeout/rAF debounce (G4.4).
1156
+ let widthVersion = $state(0);
1157
+ $effect(() => {
1158
+ const el = editorEl;
1159
+ if (!el) return;
1160
+ let lastWidth = el.clientWidth;
1161
+ const observer = new ResizeObserver(() => {
1162
+ const width = el.clientWidth;
1163
+ if (width === lastWidth) return;
1164
+ lastWidth = width;
1165
+ heightOracle.dropMeasured();
1166
+ widthVersion++;
1167
+ });
1168
+ observer.observe(el);
1169
+ return () => observer.disconnect();
1170
+ });
1171
+
1172
+ // The slice's own axis, watched on the RESOLVED port: the window's extent comes from the
1173
+ // scrollport's height, so a height-only resize otherwise leaves the newly-exposed band as
1174
+ // bare spacer until the next scroll. Its own counter, never `widthVersion` — that one
1175
+ // drops every measured height, which a resize re-wrapping no prose has not earned.
1176
+ let viewportHeightVersion = $state(0);
1177
+ $effect(() => {
1178
+ if (!editorEl) return;
1179
+ const target = getScrollHost();
1180
+ if (!target) return;
1181
+ return installViewportHeightWatcher(target, () => viewportHeightVersion++);
1182
+ });
1183
+
1184
+ // ── Type scale ──────────────────────────────────────────────────────
1185
+
1186
+ // The width change's sibling: a font-size move puts estimates off several-fold, so a
1187
+ // document whose true height clears the activation watermark can fail to window at
1188
+ // all. Only the off-window set depends on the ESTIMATE moving. The width observer
1189
+ // can't see this (no other box in the root resizes), hence the `1em` probe.
1190
+ function applyTypeScale(fontSizePx: number): void {
1191
+ const next = fontSizePx / ESTIMATE_BASE_FONT_SIZE;
1192
+ // Sub-percent moves are sub-pixel on a line box — not worth a full rebuild.
1193
+ if (!(next > 0) || Math.abs(next - typeScale) < 0.01) return;
1194
+ typeScale = next;
1195
+ heightOracle.dropMeasured();
1196
+ widthVersion++;
1197
+ }
1198
+ $effect(() => {
1199
+ const el = typeScaleProbeEl;
1200
+ if (!el) return;
1201
+ applyTypeScale(el.getBoundingClientRect().height);
1202
+ const observer = new ResizeObserver((entries) => {
1203
+ const box = entries[0]?.borderBoxSize?.[0];
1204
+ applyTypeScale(box ? box.blockSize : el.getBoundingClientRect().height);
1205
+ });
1206
+ observer.observe(el);
1207
+ return () => observer.disconnect();
1208
+ });
1209
+
1210
+ // ── Header slot compensation ────────────────────────────────────────
1211
+
1212
+ // The header slot's height lives outside the height model, so while the editor owns the
1213
+ // correction a growing header would slide the document under the reader. Compensating from
1214
+ // the SLOT's own resize is what composes with `correctAnchor` instead of double-correcting;
1215
+ // a reveal already holding the scroll outranks it.
1216
+ $effect(() => {
1217
+ const el = headerEl;
1218
+ if (!el || !editorEl) return;
1219
+ const port = getScrollport();
1220
+ if (!port) return;
1221
+ let lastHeight = el.getBoundingClientRect().height;
1222
+ const observer = new ResizeObserver((entries) => {
1223
+ // Border boxes throughout, seed and fallback alike, so a browser without
1224
+ // `borderBoxSize` computes the same delta.
1225
+ const box = entries[0]?.borderBoxSize?.[0];
1226
+ const height = box ? box.blockSize : el.getBoundingClientRect().height;
1227
+ const delta = height - lastHeight;
1228
+ lastHeight = height;
1229
+ if (delta === 0 || !ownsScrollCorrection() || port.scrollTop() === 0) return;
1230
+ if (!topWindowing.revealHoldsScroll()) port.setScrollTop(port.scrollTop() + delta);
1231
+ });
1232
+ observer.observe(el);
1233
+ return () => observer.disconnect();
1234
+ });
1235
+
1236
+ // ── Focus attribution ───────────────────────────────────────────────
1237
+
1238
+ // Drives each windowing scope's per-level pin, so a scroll that pushes the caret
1239
+ // off-screen never tears down native focus/IME. Plain `let`, not $state: focusout
1240
+ // fires mid-teardown during a structural commit, where a reactive write would trip
1241
+ // state_unsafe_mutation.
1242
+ let focusedPath: number[] | null = null;
1243
+
1244
+ // Marks the block host whose leaf holds the caret; both preview modes' CSS key their
1245
+ // focused-block reveal off it. Imperative for focusedPath's teardown-safety reason,
1246
+ // and mode-gated so source/reading DOM stays byte-identical.
1247
+ let focusedHostEl: HTMLElement | null = null;
1248
+ function applyFocusedAttr(): void {
1249
+ if (focusedHostEl && isPreviewMode(effectiveMode)) {
1250
+ focusedHostEl.setAttribute('data-focused', '');
1251
+ } else {
1252
+ focusedHostEl?.removeAttribute('data-focused');
1253
+ }
1254
+ }
1255
+ function setFocusedHost(host: HTMLElement | null): void {
1256
+ if (focusedHostEl === host) return;
1257
+ focusedHostEl?.removeAttribute('data-focused');
1258
+ focusedHostEl = host;
1259
+ applyFocusedAttr();
1260
+ }
1261
+ // Entering a preview mode marks the already-focused block, since no re-focus fires.
1262
+ $effect(() => {
1263
+ void effectiveMode;
1264
+ applyFocusedAttr();
1265
+ });
1266
+
1267
+ $effect(() => {
1268
+ if (!editorEl) return;
1269
+ const root = editorEl;
1270
+ const onFocusIn = (e: FocusEvent) => {
1271
+ const host = (e.target as Element | null)?.closest('[data-block-path]');
1272
+ if (!host || !root.contains(host)) {
1273
+ focusedPath = null;
1274
+ setFocusedHost(null);
1275
+ return;
1276
+ }
1277
+ setFocusedHost(host as HTMLElement);
1278
+ const path = readBlockPath(host);
1279
+ focusedPath = path && path.length > 0 ? path : null;
1280
+ // G1.33 at the seam every caret door crosses: a door seats a caret by focusing the
1281
+ // surface, whoever minted it, so a consumer's own door inherits the guard here.
1282
+ const landed = e.target;
1283
+ if (landed instanceof HTMLElement) {
1284
+ assertInvariant('landable-caret', () =>
1285
+ checkLandableCaret(landed, effectiveMode, path ?? [])
1286
+ );
1287
+ }
1288
+ };
1289
+ const onFocusOut = (e: FocusEvent) => {
1290
+ const next = e.relatedTarget as Node | null;
1291
+ if (next && root.contains(next)) return; // moving between blocks — keep the pin
1292
+ focusedPath = null;
1293
+ setFocusedHost(null);
1294
+ };
1295
+ return removeAll(onRoot(root, 'focusin', onFocusIn), onRoot(root, 'focusout', onFocusOut));
1296
+ });
1297
+ // ── Top-level windowing ─────────────────────────────────────────────
1298
+
1299
+ // Assembled here, after the windowing signals it carries exist; the block
1300
+ // components and the windowing hook below both read it back through getContext.
1301
+ setContext(EDITOR_DOC_KEY, {
1302
+ doc: getDoc,
1303
+ contentVersion: contentVersion.read,
1304
+ linkRef: linkRefView,
1305
+ pluginEditor: pluginEditorLookup,
1306
+ lifetime: lifetimeController.signal,
1307
+ editorRoot: () => editorEl ?? null,
1308
+ scrollHost: getScrollHost,
1309
+ scrollport: getScrollport,
1310
+ blockElLookup: getBlockElByPath,
1311
+ focusedPath: () => focusedPath,
1312
+ heightOracle,
1313
+ correctsScroll: ownsScrollCorrection,
1314
+ widthVersion: () => widthVersion,
1315
+ viewportHeightVersion: () => viewportHeightVersion
1316
+ } satisfies EditorDoc);
1317
+
1318
+ // getListEl is the inner .block-list wrapper, never editorEl (== scrollEl): it
1319
+ // scrolls with content, so its top maps root scrollTop into local coordinates,
1320
+ // where editorEl would collapse to 0.
1321
+ const topWindowing = useContainerWindowing({
1322
+ getIndex: () => 0, // ignored — root has no parent sink (reportSelfHeight is undefined)
1323
+ getParentPath: () => [],
1324
+ getChildren: () => doc.children,
1325
+ getChildIds: () => blockIds,
1326
+ getListEl: () => editorEl?.querySelector(':scope > .block-list') ?? null,
1327
+ provideLeafChannel: true
1328
+ });
1329
+
1330
+ // Plain `let`, not $state or $derived: the correction path asks this mid-measure, where
1331
+ // evaluating the window derived would force the layout read the batched pass exists to
1332
+ // avoid (VR-4). Nothing reactive reads it — the root's own attribute reads the derived,
1333
+ // so the flag lags the attribute one flush at a watermark crossing (measured harmless).
1334
+ let rootWindowingActive = false;
1335
+ $effect(() => {
1336
+ rootWindowingActive = topWindowing.window.active;
1337
+ });
1338
+
1339
+ // Who holds the reader's place through a height mutation. Self mode always; host mode only
1340
+ // while windowing runs, since below the budget the host's own native anchoring does it and
1341
+ // both correcting would double-count. The `overflow-anchor` opt-out keys off the same fact.
1342
+ function ownsScrollCorrection(): boolean {
1343
+ return !hostScroll || rootWindowingActive;
1344
+ }
1345
+
1346
+ // ── Public API ──────────────────────────────────────────────────────
1347
+
1348
+ export function getSource(): string {
1349
+ return serialize(doc);
1350
+ }
1351
+
1352
+ // The kind alone, never the node: a host reads the tree's shape without holding a handle into
1353
+ // it. See `editor-props.ts` for the contract.
1354
+ export function getBlockKindAt(path: number[]): AnyBlockKind | null {
1355
+ return blockNodeAt(doc, path)?.kind ?? null;
1356
+ }
1357
+
1358
+ /**
1359
+ * A frozen snapshot of the current selection, or null when nothing is focused.
1360
+ * Path arrays are copies, so mutating the result does not affect internal state.
1361
+ */
1362
+ export function getSelection(): EditorSelection | null {
1363
+ return readCurrentSelection(selectionState, blockRefs);
1364
+ }
1365
+
1366
+ /**
1367
+ * The one restore road: resolve + clamp, reveal, place. `reveal` picks which reveal. The two
1368
+ * scrolling ones differ in whether the pin outlives the call — a navigation holds, a consumer
1369
+ * restore hands the viewport back so a kept pin can't override the host's next scroll — and
1370
+ * `mount` is the history swap's bare mount, which promises no block IN VIEW (overscan keeps
1371
+ * blocks mounted past the fold) and in exchange writes no scrollport.
1372
+ */
1373
+ function restoreThroughRevealRoad(
1374
+ selection: EditorSelection,
1375
+ reveal: 'hold' | 'release' | 'mount'
1376
+ ): Promise<SelectionRestoreOutcome> {
1377
+ return restoreSelection(selection, {
1378
+ getDoc,
1379
+ selectionState,
1380
+ getBlockElByPath,
1381
+ revealTarget: async (path) =>
1382
+ reveal === 'mount'
1383
+ ? (await revealPath(path)) !== null
1384
+ : rects.scrollTo(path, { block: 'nearest', hold: reveal === 'hold' })
1385
+ });
1386
+ }
1387
+
1388
+ function caretAt(path: number[], offset = 0): EditorSelection {
1389
+ return { anchor: { path, offset }, focus: { path, offset } };
1390
+ }
1391
+
1392
+ /** Land the caret at a raw offset through the shared restore road — the link card's return
1393
+ * door after a commit, so the next keystroke (Ctrl+Z included) addresses the document. */
1394
+ async function landCaretAtOffset(path: number[], offset: number): Promise<boolean> {
1395
+ return (await restoreThroughRevealRoad(caretAt(path, offset), 'hold')) === 'applied';
1396
+ }
1397
+
1398
+ /**
1399
+ * Restore a snapshot from {@link getSelection}, sharing the whole restore road with
1400
+ * the undo swap and plugin navigation so the three cannot diverge. True iff the
1401
+ * selection was placed AND its focus block is in view; a later programmatic reveal
1402
+ * mid-settle owns the viewport and makes this false, a user gesture does not.
1403
+ */
1404
+ export async function setSelection(selection: EditorSelection): Promise<boolean> {
1405
+ return (await restoreThroughRevealRoad(selection, 'release')) === 'applied';
1406
+ }
1407
+
1408
+ // The dead-space click's own landing walk, minus the press/target discrimination a host
1409
+ // caller has already done for itself. See `editor-props.ts` for the contract.
1410
+ export function placeCaretAtPoint(x: number, y: number): boolean {
1411
+ return editorEl ? deadSpaceCaret.placeAtPoint(editorEl, x, y) : false;
1412
+ }
1413
+
1414
+ /**
1415
+ * The block path behind `document.activeElement`, for the public doors that address the
1416
+ * focused surface. A gap caret declines: its proxy is not a block, and a NESTED gap's proxy
1417
+ * sits inside its container's host, which must not receive what was aimed at the gap.
1418
+ */
1419
+ function focusedSurfacePath(): number[] | null {
1420
+ if (selectionState.gapCaret) return null;
1421
+ const active = document.activeElement;
1422
+ if (!(active instanceof HTMLElement) || !editorEl?.contains(active)) return null;
1423
+ return findSurfacePathForElement(active);
1424
+ }
1425
+
1426
+ // Routed to the focused SURFACE, the way a paste event is: everything the pipeline owes
1427
+ // (transforms, delete-first, one undo entry, focus) lives below that seam, not here. See
1428
+ // `editor-props.ts` for the contract.
1429
+ export function insertMarkdown(md: string): boolean {
1430
+ const path = focusedSurfacePath();
1431
+ if (!path) return false;
1432
+ return getBlockComponent(path)?.insertMarkdown?.(md) ?? false;
1433
+ }
1434
+
1435
+ const commandDispatchContext: CommandDispatchContext = {
1436
+ history,
1437
+ pluginEditor: pluginEditorLookup,
1438
+ activation: activePlugins,
1439
+ getPresentationMode: () => effectiveMode,
1440
+ isCrossBlockRange: () => selectionState.isCrossBlock,
1441
+ crossBlockCommands: crossBlockCommands
1442
+ };
1443
+
1444
+ // A gap caret focuses a proxy, not a block, so no block-local command has a surface to run
1445
+ // on; global ones still reach the seam, exactly as the gap caret's own chord proxy does.
1446
+ function focusedCommandTarget(): KindCommandTarget | null {
1447
+ const path = focusedSurfacePath();
1448
+ if (!path) return null;
1449
+ const component = getBlockComponent(path);
1450
+ const node = blockNodeAt(doc, path);
1451
+ if (!component?.runCommand || !node) return null;
1452
+ return {
1453
+ kind: node.kind,
1454
+ runCommand: (id, arg) => component.runCommand!(id, arg),
1455
+ isCommandActive: component.isCommandActive
1456
+ ? (id) => component.isCommandActive!(id)
1457
+ : undefined
1458
+ };
1459
+ }
1460
+
1461
+ // The door only resolves the focused surface; every rule (the reading gate, the cross-block
1462
+ // range decline, the arms themselves) lives below the seam. See `editor-props.ts`.
1463
+ export function runCommand(commandId: string): boolean {
1464
+ return runCommandById(
1465
+ commandId as AnyCommandId,
1466
+ undefined,
1467
+ focusedCommandTarget(),
1468
+ commandDispatchContext,
1469
+ commandErrorSink
1470
+ );
1471
+ }
1472
+
1473
+ // The same seam the door dispatches through, so what a host greys out and what a click declines
1474
+ // cannot drift. See `editor-props.ts` for the contract.
1475
+ export function canRunCommand(commandId: string): boolean {
1476
+ return canRunCommandById(
1477
+ commandId as AnyCommandId,
1478
+ focusedCommandTarget(),
1479
+ commandDispatchContext
1480
+ );
1481
+ }
1482
+
1483
+ // State, not admissibility: the focused surface reports its own toggle-state, so a toolbar's
1484
+ // pressed paint reads the same bytes the toggle would rewrite. See `editor-props.ts`.
1485
+ export function isCommandActive(commandId: string): boolean {
1486
+ return isCommandActiveById(
1487
+ commandId as AnyCommandId,
1488
+ focusedCommandTarget(),
1489
+ commandDispatchContext
1490
+ );
1491
+ }
1492
+
1493
+ export function getEvents(): EditorEvents {
1494
+ return events;
1495
+ }
1496
+
1497
+ export function getSearch(): SearchState {
1498
+ return searchState;
1499
+ }
1500
+
1501
+ export function getDecorations(): DecorationRegistry {
1502
+ return decorations;
1503
+ }
1504
+
1505
+ export function getRects(): EditorRects {
1506
+ return rects;
1507
+ }
1508
+
1509
+ // Recomposed per call rather than derived: the kind and plugin registries are
1510
+ // process-global and mutate outside this component's reactive graph.
1511
+ export function reservedChords(): ReadonlySet<string> {
1512
+ return collectReservedChords({
1513
+ searchBar,
1514
+ keybindings: overridesMap,
1515
+ activation: activePlugins
1516
+ });
1517
+ }
1518
+
1519
+ export function claimsChord(event: KeyboardEvent): boolean {
1520
+ return chordIsClaimed(event, reservedChords());
1521
+ }
1522
+
1523
+ // Reads the public snapshot, so it covers single-block carets the cross-block
1524
+ // SelectionState never holds.
1525
+ function selectionSummary(): string {
1526
+ const sel = getSelection();
1527
+ if (!sel) return '(no selection)';
1528
+ const fmt = (p: { path: number[]; offset: number }) => `[${p.path.join(',')}]@${p.offset}`;
1529
+ return `anchor=${fmt(sel.anchor)} focus=${fmt(sel.focus)}`;
1530
+ }
1531
+
1532
+ export function getDiagnostics(): EditorDiagnostics {
1533
+ return {
1534
+ enableTrace: enableInteractionTrace,
1535
+ disableTrace: disableInteractionTrace,
1536
+ isTraceEnabled: isInteractionTraceEnabled,
1537
+ traceSnapshot: interactionTraceSnapshot,
1538
+ serializeDiagnostics: (opts) => {
1539
+ const includeSource = opts?.includeSource ?? false;
1540
+ return buildDiagnosticsReport({
1541
+ timestamp: new Date().toISOString(),
1542
+ trace: dumpInteractionTrace(interactionTraceSnapshot()),
1543
+ opsLog: dumpOperationsLog(operationsLog),
1544
+ selection: selectionSummary(),
1545
+ // Serialize only when opted in — the report stays document-free by default.
1546
+ source: includeSource ? getSource() : '',
1547
+ includeSource
1548
+ });
1549
+ }
1550
+ };
1551
+ }
1552
+
1553
+ // Compile-time conformance: the published handle can't drift from the exports.
1554
+ void ({
1555
+ getSource,
1556
+ getBlockKindAt,
1557
+ getSelection,
1558
+ setSelection,
1559
+ placeCaretAtPoint,
1560
+ insertMarkdown,
1561
+ runCommand,
1562
+ canRunCommand,
1563
+ isCommandActive,
1564
+ getEvents,
1565
+ getSearch,
1566
+ getDecorations,
1567
+ getRects,
1568
+ getDiagnostics,
1569
+ reservedChords,
1570
+ claimsChord
1571
+ } satisfies EditorInstance);
1572
+
1573
+ // ── Test-only surface ───────────────────────────────────────────────
1574
+
1575
+ function getOperationsLog() {
1576
+ return operationsLog;
1577
+ }
1578
+
1579
+ function getUndoStack() {
1580
+ return undoManager.getStacks();
1581
+ }
1582
+
1583
+ /** The live CST Document; treat it as read-only, since mutating it bypasses the
1584
+ * undo pipeline. */
1585
+ function getDocument() {
1586
+ return doc;
1587
+ }
1588
+
1589
+ export const __test = {
1590
+ getDocument,
1591
+ // The swap door's only oracle: every other door is reachable headlessly, but the
1592
+ // `source` prop's reset lives in this component.
1593
+ getContentVersion: contentVersion.read,
1594
+ getBlockComponent,
1595
+ getUndoStack,
1596
+ getOperationsLog,
1597
+ // Specs need the state, not the `data-cross-block` mirror: a deferred $effect
1598
+ // writes the attribute, and an intra-table rectangle keeps one path on both
1599
+ // endpoints, so neither the DOM nor getSelection() answers this reliably.
1600
+ isCrossBlockActive: () => selectionState.isCrossBlock,
1601
+ // The gap caret has no public selection shape and no paint yet, so the state is the
1602
+ // only place arrival can be observed.
1603
+ getGapCaret: () => selectionState.gapCaret,
1604
+ // The engine, not the `addSource`-only public registry: the derived per-path
1605
+ // buckets are the only oracle for a stale bucket, since jsdom measures every
1606
+ // range at zero width and no overlay ever paints there.
1607
+ getDecorationEngine: () => decorationEngine,
1608
+ // The measured-height cache is root-constructed and handed down through context,
1609
+ // so its lifetime against a document swap has no headless seam either.
1610
+ getHeightOracle: () => heightOracle,
1611
+ // The one signal a windowing scope rebuilds off when no id moved, so it is the
1612
+ // oracle for a mode flip having asked for the rebuild it needs.
1613
+ getWidthVersion: () => widthVersion,
1614
+ // Constructs the detached-slot artifact the windowed each-block's cleanup can
1615
+ // leave behind (see `isSlotDetached`); e2e-only.
1616
+ setBlockRefSlot: blockRefSlots.set
1617
+ };
1618
+ </script>
1619
+
1620
+ <!-- tabindex="-1": focusable so a windowed-out block hands focus here rather than to
1621
+ <body>, but not tab-reachable. Non-editable, so focusing it creates no native
1622
+ selection for the selectionchange bridge to collapse. -->
1623
+ <!-- data-presentation is ABSENT in source mode on purpose: the default path's DOM
1624
+ stays byte-identical, and reading-mode CSS keys on the attribute's presence. -->
1625
+ <div
1626
+ class="editor"
1627
+ data-editor-theme={theme}
1628
+ data-scroll-mode={hostScroll ? 'host' : undefined}
1629
+ data-windowing={topWindowing.window.active ? 'active' : undefined}
1630
+ data-presentation={effectiveMode === 'source' ? undefined : effectiveMode}
1631
+ bind:this={editorEl}
1632
+ tabindex="-1"
1633
+ role="group"
1634
+ aria-label={EDITOR_LABEL}
1635
+ >
1636
+ {#if searchBar}
1637
+ <!-- Zero-height sticky anchor, so the bar doesn't scroll away with content. Portaled
1638
+ out, it drops that positioning (the consumer's element is the box) and carries the
1639
+ editor's own theme scope, since custom properties resolve by DOM ancestry. -->
1640
+ <div
1641
+ class:search-anchor={!searchBarAnchor}
1642
+ class:aragonite-editor-theme={!!searchBarAnchor && inThemedScope}
1643
+ data-editor-theme={searchBarAnchor ? theme : undefined}
1644
+ {@attach portalInto(searchBarAnchor)}
1645
+ >
1646
+ <SearchBar
1647
+ replaceExpanded={replaceExpanded && canReplace}
1648
+ onToggleReplace={() => (replaceExpanded = canReplace && !replaceExpanded)}
1649
+ />
1650
+ </div>
1651
+ {/if}
1652
+ <!-- One `em` tall and out of flow: its box IS the root's computed font size, which
1653
+ no other box reports, and windowing's activation decision needs that scale. -->
1654
+ <div class="type-scale-probe" bind:this={typeScaleProbeEl} aria-hidden="true"></div>
1655
+ {#if header}
1656
+ <!-- A SIBLING of the block list, never a wrapper: the windowing scope resolves
1657
+ its list as a direct child of this root. -->
1658
+ <div class="editor-header" bind:this={headerEl}>{@render header()}</div>
1659
+ {/if}
1660
+ <BlockList
1661
+ children={doc.children}
1662
+ {blockIds}
1663
+ slots={blockRefSlots}
1664
+ parentPath={[]}
1665
+ window={topWindowing.window}
1666
+ reorderable={true}
1667
+ />
1668
+ <ImageOverlayHost
1669
+ {widgetSelection}
1670
+ {controller}
1671
+ {events}
1672
+ {getDoc}
1673
+ getEditorEl={() => editorEl ?? null}
1674
+ getSelectionIsCustomRendered={() => selectionState.isCustomRendered}
1675
+ getPresentationMode={() => effectiveMode}
1676
+ grammar={registryView.grammar}
1677
+ lifetime={lifetimeController.signal}
1678
+ />
1679
+ <LinkCardHost
1680
+ card={linkCard}
1681
+ {controller}
1682
+ {events}
1683
+ {getDoc}
1684
+ getEditorEl={() => editorEl ?? null}
1685
+ measureRange={rects.rangeRects}
1686
+ landCaret={landCaretAtOffset}
1687
+ {activateLink}
1688
+ resolveLinkUrl={resolveLinkUrlImpl}
1689
+ caretRestore={linkCardCaret}
1690
+ linkRef={linkRefView}
1691
+ grammar={registryView.grammar}
1692
+ />
1693
+ <div class="editor-sr-live" role="status" aria-live="polite">{selectionDescription}</div>
1694
+ <div class="editor-sr-live-reorder" role="status" aria-live="polite">{reorderAnnouncement}</div>
1695
+ {#if reorderLine}
1696
+ <div
1697
+ class="reorder-line"
1698
+ style="left:{reorderLine.left}px;top:{reorderLine.top}px;width:{reorderLine.width}px"
1699
+ ></div>
1700
+ {/if}
1701
+ {#if reorderGhost}
1702
+ <div class="reorder-ghost" style="left:{reorderGhost.clientX}px;top:{reorderGhost.clientY}px">
1703
+ {reorderGhost.label}
1704
+ </div>
1705
+ {/if}
1706
+ </div>
1707
+
1708
+ <style>
1709
+ .editor {
1710
+ width: 100%;
1711
+ flex: 1;
1712
+ padding: 1rem;
1713
+ font-family: var(--font-editor, ui-monospace, monospace);
1714
+ /* The type-scale root: every construct sizes in `em` off this, so one
1715
+ declaration scales the whole surface. */
1716
+ font-size: var(--editor-font-size, 1rem);
1717
+ line-height: 1.6;
1718
+ color: var(--color-text-primary, #ffffff);
1719
+ min-height: 200px;
1720
+ overflow-y: auto;
1721
+ /* The editor corrects the scroll anchor by hand (list-windowing's
1722
+ correctAnchor); native anchoring independently rewrites scrollTop and
1723
+ double-corrects. Do NOT restore `overflow-anchor` (VR-2). */
1724
+ overflow-anchor: none;
1725
+ scrollbar-width: thin;
1726
+ scrollbar-color: var(--color-ui-muted, #a4a4a4) transparent;
1727
+ border: 1px solid var(--color-ui-muted, #a4a4a4);
1728
+ border-radius: 4px;
1729
+ /* Containing block for the image overlay portal. */
1730
+ position: relative;
1731
+ }
1732
+
1733
+ /* Embedded flow mode: an ancestor owns the scroll, so the root drops its scrollport and the
1734
+ standalone-widget chrome that would box every entry of a journal. Below the windowing
1735
+ budget nothing corrects by hand, so native anchoring is restored — `none` would strip the
1736
+ subtree from the HOST's anchor candidates and hold nothing in its place. */
1737
+ .editor[data-scroll-mode='host'] {
1738
+ overflow-y: visible;
1739
+ overflow-anchor: auto;
1740
+ min-height: 0;
1741
+ flex: none;
1742
+ border: none;
1743
+ padding: 0;
1744
+ }
1745
+
1746
+ /* The stated trade of windowing under host scroll: native anchoring and the manual
1747
+ correction cannot coexist, so an active editor withdraws its own subtree from the host's
1748
+ anchor candidates and holds the line itself (VR-2). The host's scroller is untouched. */
1749
+ .editor[data-scroll-mode='host'][data-windowing='active'] {
1750
+ overflow-anchor: none;
1751
+ }
1752
+
1753
+ /* Absolute and zero-width so it takes no part in layout; never `display: none`,
1754
+ which stops a ResizeObserver reporting. */
1755
+ .type-scale-probe {
1756
+ position: absolute;
1757
+ top: 0;
1758
+ left: 0;
1759
+ width: 0;
1760
+ height: 1em;
1761
+ visibility: hidden;
1762
+ pointer-events: none;
1763
+ }
1764
+
1765
+ /* Sticks to the scrollport top reserving no space; the bar positions absolutely
1766
+ against it and stays put as the editor scrolls. */
1767
+ .search-anchor {
1768
+ position: sticky;
1769
+ top: 0;
1770
+ height: 0;
1771
+ z-index: 5;
1772
+ }
1773
+
1774
+ /* Sticky resolves against the nearest SCROLLPORT, which in flow mode is the host's,
1775
+ floating the bar over unrelated page content; absolute re-homes it to the root. */
1776
+ .editor[data-scroll-mode='host'] .search-anchor {
1777
+ position: absolute;
1778
+ top: 0;
1779
+ left: 0;
1780
+ right: 0;
1781
+ }
1782
+
1783
+ .editor::-webkit-scrollbar {
1784
+ width: 6px;
1785
+ }
1786
+
1787
+ .editor::-webkit-scrollbar-track {
1788
+ background: transparent;
1789
+ }
1790
+
1791
+ .editor::-webkit-scrollbar-thumb {
1792
+ background: var(--color-ui-muted, #a4a4a4);
1793
+ border-radius: 3px;
1794
+ }
1795
+
1796
+ .editor::-webkit-scrollbar-thumb:hover {
1797
+ background: var(--color-ui-dulled, #afb1b3);
1798
+ }
1799
+
1800
+ .editor-sr-live,
1801
+ .editor-sr-live-reorder {
1802
+ position: absolute;
1803
+ width: 1px;
1804
+ height: 1px;
1805
+ padding: 0;
1806
+ margin: -1px;
1807
+ overflow: hidden;
1808
+ clip: rect(0 0 0 0);
1809
+ white-space: nowrap;
1810
+ border: 0;
1811
+ }
1812
+
1813
+ /* A nested drag reorders only within its container, so the container takes a faint
1814
+ transient wash — deliberately not an outline (a document should feel like a
1815
+ document, not a pile of blocks). Applied by editor-actions/reorder-drag.ts. */
1816
+ :global(.reorder-scope) {
1817
+ background: var(--reorder-scope-bg, rgba(100, 150, 255, 0.14));
1818
+ border-radius: 4px;
1819
+ transition: background-color 0.12s ease;
1820
+ }
1821
+
1822
+ /* Viewport-fixed, since the rects come from client coords; pointer-events:none so
1823
+ they never intercept the drag's own pointer stream. */
1824
+ .reorder-line {
1825
+ position: fixed;
1826
+ height: 2px;
1827
+ background: var(--md-reorder-indicator);
1828
+ border-radius: 2px;
1829
+ pointer-events: none;
1830
+ z-index: 20;
1831
+ }
1832
+
1833
+ .reorder-ghost {
1834
+ position: fixed;
1835
+ transform: translate(0.75rem, 0.5rem);
1836
+ max-width: 16rem;
1837
+ padding: 0.15rem 0.5rem;
1838
+ font-size: 0.85em;
1839
+ white-space: nowrap;
1840
+ overflow: hidden;
1841
+ text-overflow: ellipsis;
1842
+ background: var(--md-reorder-indicator);
1843
+ color: #fff;
1844
+ border-radius: 4px;
1845
+ opacity: 0.9;
1846
+ pointer-events: none;
1847
+ z-index: 21;
1848
+ }
1849
+ </style>