@barocss/math-editor 0.2.1 → 0.5.0

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 (202) hide show
  1. package/ADAPTERS.md +25 -14
  2. package/API-JAVASCRIPT.md +1 -1
  3. package/API-REACT.md +5 -1
  4. package/API-SESSION.md +178 -6
  5. package/API-SOLID.md +1 -1
  6. package/API-SVELTE.md +1 -1
  7. package/API-VUE.md +1 -1
  8. package/API-WEB-COMPONENT.md +3 -1
  9. package/CHANGELOG.md +106 -0
  10. package/EDITING-SCENARIOS.md +174 -0
  11. package/EMBEDDING.md +4 -0
  12. package/IMPLEMENTATION.md +122 -2
  13. package/JSON-MODEL.md +1 -0
  14. package/LATEX-GUIDE.md +30 -1
  15. package/LATEX-MODEL.md +12 -0
  16. package/LATEX-SCOPE.md +12 -3
  17. package/LICENSE +1 -3
  18. package/README.md +201 -39
  19. package/RELEASING.md +81 -10
  20. package/RENDERING-TESTS.md +79 -0
  21. package/ROADMAP.md +220 -11
  22. package/STYLING.md +157 -0
  23. package/SUPPORT.md +24 -12
  24. package/VALIDATION.md +444 -4
  25. package/dist/context-tools.d.ts +21 -0
  26. package/dist/context-tools.js +37 -0
  27. package/dist/core.d.ts +5 -1
  28. package/dist/core.js +5 -1
  29. package/dist/document-codec.d.ts +0 -1
  30. package/dist/document-codec.js +0 -1
  31. package/dist/dom/caret-geometry.d.ts +3 -0
  32. package/dist/dom/caret-geometry.js +41 -0
  33. package/dist/dom/context-keyboard.d.ts +2 -0
  34. package/dist/dom/context-keyboard.js +22 -0
  35. package/dist/dom/elements.d.ts +1 -2
  36. package/dist/dom/elements.js +2 -3
  37. package/dist/dom/latex-panel.d.ts +10 -0
  38. package/dist/dom/latex-panel.js +59 -0
  39. package/dist/dom/matrix-selection.d.ts +11 -0
  40. package/dist/dom/matrix-selection.js +30 -0
  41. package/dist/dom/menu-position.d.ts +17 -2
  42. package/dist/dom/menu-position.js +129 -16
  43. package/dist/dom/presentation-controls.d.ts +4 -0
  44. package/dist/dom/presentation-controls.js +56 -0
  45. package/dist/dom/quick-panel.d.ts +12 -0
  46. package/dist/dom/quick-panel.js +102 -0
  47. package/dist/dom/selection.d.ts +29 -0
  48. package/dist/dom/selection.js +53 -0
  49. package/dist/dom/symbol-panel.d.ts +9 -0
  50. package/dist/dom/symbol-panel.js +146 -0
  51. package/dist/dom/theme.d.ts +6 -0
  52. package/dist/dom/theme.js +68 -0
  53. package/dist/dom/toolbar-catalog.d.ts +10 -0
  54. package/dist/dom/toolbar-catalog.js +35 -0
  55. package/dist/dom/toolbar.d.ts +13 -2
  56. package/dist/dom/toolbar.js +295 -28
  57. package/dist/dom.d.ts +9 -1
  58. package/dist/dom.js +682 -151
  59. package/dist/editor-labels.d.ts +0 -1
  60. package/dist/editor-labels.js +0 -1
  61. package/dist/enter-policy.d.ts +0 -1
  62. package/dist/enter-policy.js +0 -1
  63. package/dist/fences.d.ts +0 -1
  64. package/dist/fences.js +0 -1
  65. package/dist/i18n.d.ts +0 -1
  66. package/dist/i18n.js +0 -1
  67. package/dist/index.d.ts +4 -1
  68. package/dist/index.js +4 -1
  69. package/dist/latex-insertion.d.ts +12 -0
  70. package/dist/latex-insertion.js +26 -0
  71. package/dist/latex-paste-panel.d.ts +3 -0
  72. package/dist/latex-paste-panel.js +18 -0
  73. package/dist/latex.d.ts +0 -1
  74. package/dist/latex.js +11 -1
  75. package/dist/lines.d.ts +0 -1
  76. package/dist/lines.js +0 -1
  77. package/dist/locales/en.js +39 -1
  78. package/dist/locales/en.json +39 -1
  79. package/dist/locales/ko.js +39 -1
  80. package/dist/locales/ko.json +39 -1
  81. package/dist/math-editor-toolbar.d.ts +4 -2
  82. package/dist/math-editor-toolbar.js +3 -4
  83. package/dist/math-editor.d.ts +7 -2
  84. package/dist/math-editor.js +661 -308
  85. package/dist/math-layout.d.ts +12 -0
  86. package/dist/math-layout.js +59 -0
  87. package/dist/math-spacing.d.ts +13 -0
  88. package/dist/math-spacing.js +87 -0
  89. package/dist/matrix-range.d.ts +40 -0
  90. package/dist/matrix-range.js +242 -0
  91. package/dist/matrix.d.ts +0 -1
  92. package/dist/matrix.js +0 -1
  93. package/dist/model.d.ts +4 -1
  94. package/dist/model.js +49 -5
  95. package/dist/outputs.d.ts +0 -1
  96. package/dist/outputs.js +0 -1
  97. package/dist/preferences.d.ts +24 -0
  98. package/dist/preferences.js +66 -0
  99. package/dist/presentation-controls.d.ts +10 -0
  100. package/dist/presentation-controls.js +10 -0
  101. package/dist/presentation.d.ts +13 -0
  102. package/dist/presentation.js +86 -0
  103. package/dist/quick-panel.d.ts +2 -0
  104. package/dist/quick-panel.js +17 -0
  105. package/dist/range.d.ts +2 -1
  106. package/dist/range.js +11 -1
  107. package/dist/react.d.ts +0 -1
  108. package/dist/react.js +0 -1
  109. package/dist/root-transform.d.ts +19 -0
  110. package/dist/root-transform.js +69 -0
  111. package/dist/session.d.ts +31 -2
  112. package/dist/session.js +108 -7
  113. package/dist/solid.d.ts +0 -1
  114. package/dist/solid.js +0 -1
  115. package/dist/suggestions.d.ts +13 -1
  116. package/dist/suggestions.js +153 -12
  117. package/dist/svelte.d.ts +0 -1
  118. package/dist/svelte.js +0 -1
  119. package/dist/symbol-browser.d.ts +0 -1
  120. package/dist/symbol-browser.js +0 -1
  121. package/dist/symbols.d.ts +0 -1
  122. package/dist/symbols.js +0 -1
  123. package/dist/templates.d.ts +0 -1
  124. package/dist/templates.js +0 -1
  125. package/dist/tokens.d.ts +0 -1
  126. package/dist/tokens.js +0 -1
  127. package/dist/vertical-navigation.d.ts +15 -0
  128. package/dist/vertical-navigation.js +145 -0
  129. package/dist/vue.d.ts +0 -1
  130. package/dist/vue.js +0 -1
  131. package/dist/web-component.d.ts +0 -1
  132. package/dist/web-component.js +9 -2
  133. package/package.json +11 -3
  134. package/src/fonts/KaTeX_Math-Italic.woff2 +0 -0
  135. package/src/fonts/KaTeX_Size1-Regular.woff2 +0 -0
  136. package/src/fonts/README.md +18 -0
  137. package/src/shapes/README.md +21 -0
  138. package/src/shapes/parenthesis-bottom.svg +1 -0
  139. package/src/shapes/parenthesis-top.svg +1 -0
  140. package/src/shapes/parenthesis.svg +1 -0
  141. package/src/shapes/radical.svg +1 -0
  142. package/src/style.css +949 -173
  143. package/dist/core.d.ts.map +0 -1
  144. package/dist/core.js.map +0 -1
  145. package/dist/document-codec.d.ts.map +0 -1
  146. package/dist/document-codec.js.map +0 -1
  147. package/dist/dom/elements.d.ts.map +0 -1
  148. package/dist/dom/elements.js.map +0 -1
  149. package/dist/dom/menu-position.d.ts.map +0 -1
  150. package/dist/dom/menu-position.js.map +0 -1
  151. package/dist/dom/toolbar.d.ts.map +0 -1
  152. package/dist/dom/toolbar.js.map +0 -1
  153. package/dist/dom.d.ts.map +0 -1
  154. package/dist/dom.js.map +0 -1
  155. package/dist/editor-labels.d.ts.map +0 -1
  156. package/dist/editor-labels.js.map +0 -1
  157. package/dist/enter-policy.d.ts.map +0 -1
  158. package/dist/enter-policy.js.map +0 -1
  159. package/dist/fences.d.ts.map +0 -1
  160. package/dist/fences.js.map +0 -1
  161. package/dist/i18n.d.ts.map +0 -1
  162. package/dist/i18n.js.map +0 -1
  163. package/dist/index.d.ts.map +0 -1
  164. package/dist/index.js.map +0 -1
  165. package/dist/latex.d.ts.map +0 -1
  166. package/dist/latex.js.map +0 -1
  167. package/dist/lines.d.ts.map +0 -1
  168. package/dist/lines.js.map +0 -1
  169. package/dist/math-editor-toolbar.d.ts.map +0 -1
  170. package/dist/math-editor-toolbar.js.map +0 -1
  171. package/dist/math-editor.d.ts.map +0 -1
  172. package/dist/math-editor.js.map +0 -1
  173. package/dist/matrix.d.ts.map +0 -1
  174. package/dist/matrix.js.map +0 -1
  175. package/dist/model.d.ts.map +0 -1
  176. package/dist/model.js.map +0 -1
  177. package/dist/outputs.d.ts.map +0 -1
  178. package/dist/outputs.js.map +0 -1
  179. package/dist/range.d.ts.map +0 -1
  180. package/dist/range.js.map +0 -1
  181. package/dist/react.d.ts.map +0 -1
  182. package/dist/react.js.map +0 -1
  183. package/dist/session.d.ts.map +0 -1
  184. package/dist/session.js.map +0 -1
  185. package/dist/solid.d.ts.map +0 -1
  186. package/dist/solid.js.map +0 -1
  187. package/dist/suggestions.d.ts.map +0 -1
  188. package/dist/suggestions.js.map +0 -1
  189. package/dist/svelte.d.ts.map +0 -1
  190. package/dist/svelte.js.map +0 -1
  191. package/dist/symbol-browser.d.ts.map +0 -1
  192. package/dist/symbol-browser.js.map +0 -1
  193. package/dist/symbols.d.ts.map +0 -1
  194. package/dist/symbols.js.map +0 -1
  195. package/dist/templates.d.ts.map +0 -1
  196. package/dist/templates.js.map +0 -1
  197. package/dist/tokens.d.ts.map +0 -1
  198. package/dist/tokens.js.map +0 -1
  199. package/dist/vue.d.ts.map +0 -1
  200. package/dist/vue.js.map +0 -1
  201. package/dist/web-component.d.ts.map +0 -1
  202. package/dist/web-component.js.map +0 -1
package/VALIDATION.md CHANGED
@@ -1,6 +1,143 @@
1
1
  # Validation report
2
2
 
3
- ## Current release status0.2.0
3
+ ## Inline fence transformation suggestions workspace, 2026-09-09
4
+
5
+ Core: **584 tests in 36 files passed**. Core type checking and the main site/docs
6
+ build passed. `fence-suggestions-check.js` passed in Chromium for rich React and
7
+ all nine host demos, including menu reopening, keyboard acceptance, cancellation,
8
+ retained caret, continued typing and separate Undo entries. Editor.js is a block
9
+ host; this run does not claim an inline placement for that adapter.
10
+
11
+ `fence-context-check.js` passed all eight bracket choices through the optional
12
+ footer in the same ten editor views. `fence-inline-options-check.js` passed in a
13
+ native inline iframe with toolbar and footer disabled, including nearest nested
14
+ fence targeting, ko/en switching, unchanged document on locale changes, retained
15
+ input focus/caret, continued typing and teardown.
16
+
17
+ Existing root conversion suggestions were rerun in React and Quill and passed.
18
+ `fence-rendering-check.js` verifies the exported source after changing a bracket
19
+ around a fraction. The editor and KaTeX screenshots were visually inspected:
20
+ `output/playwright/fence-transform-editor.png` and
21
+ `output/playwright/fence-transform-katex.png`. This uses the existing delimiter
22
+ renderer and does not claim pixel-identical layout.
23
+
24
+ See EDIT-029 through EDIT-032 for acceptance criteria. This is local Chromium
25
+ workspace evidence, not a release, real OS IME or cross-browser certification.
26
+
27
+ ## Contextual radical tools — workspace, 2026-09-09
28
+
29
+ Core: **570 tests passed in 35 files**. Type checking and the main documentation/demo build passed.
30
+
31
+ `context-tools-check.js` passed in local Chromium for rich React and all nine
32
+ host examples: Tiptap, ProseMirror, Lexical, Editor.js, TinyMCE, CKEditor, Quill,
33
+ Slate and Gutenberg. It covers query-independent discovery, retained tools after
34
+ suggestion dismissal, F6/Escape focus, conversion, selected index editing, a
35
+ non-square-index explanation, radicand retention, Undo, leaving a radical and
36
+ hiding tools during model range selection.
37
+
38
+ `context-tools-options-check.js` passed for nearest nested targeting, native DOM
39
+ inside an iframe, owner-document keyboard focus, dynamic `contextTools`, en/ko
40
+ labels, synthetic composition guards, outside blur, teardown, and dynamic Web
41
+ Component `context-tools` attributes. Synthetic events do not certify OS IME.
42
+
43
+ The footer was visually inspected separately from the suggestion popup. Evidence
44
+ is in `output/playwright/context-tools-footer.png` and the two browser fixtures.
45
+ EDIT-021 through EDIT-028 record acceptance criteria and remaining checks: native
46
+ Tab order, document equality across locale changes, individual framework-wrapper
47
+ option smoke tests, and broader browsers/platforms. The new footer currently
48
+ covers square/indexed roots. Other structure families remain roadmap work.
49
+ These are workspace-source checks; no package or site was published.
50
+
51
+ ## Fractional scripts and empty-slot deletion — workspace, 2026-09-09
52
+
53
+ Core: 568 tests passed in 35 files; type checking and formatting passed. The
54
+ main documentation/demo build passed. `empty-slot-deletion-check.js` passed
55
+ 16 real-key checks across React/native DOM: Delete and Backspace from empty
56
+ root, fraction, exponent and root-index slots, retained content, focus and Undo.
57
+ Grid cells and populated rows are protected by the added core tests.
58
+
59
+ `rendering-regression-check.js` passed 12 Chromium comparisons: three formulas,
60
+ two base sizes and two renderers. Fraction terms matched KaTeX font sizes;
61
+ vertical offset differences were at most 0.109em against a 0.25em threshold.
62
+ Horizontal gap, active-input size and focus assertions passed. Matching-size
63
+ editor/KaTeX screenshots were visually inspected for the indexed-root power
64
+ and simple fractional power. Full pixel identity is not claimed.
65
+
66
+ Local evidence: `output/playwright/math-rendering-regression-evidence.json`
67
+ records metrics and source SHA-256 values. Screenshot pairs use the paths in
68
+ [Rendering checks](RENDERING-TESTS.md). This is workspace-source evidence, not
69
+ packed-release, all-host, cross-browser or full notation certification.
70
+
71
+ See [Editing scenarios](EDITING-SCENARIOS.md) for stable scenario IDs, acceptance criteria, coverage gaps and per-run reporting.
72
+
73
+
74
+ ## Radical conversion suggestions — workspace, 2026-09-09
75
+
76
+ Core tests: 558 passed in 34 files; type checking passed. Ten added cases cover
77
+ nested radicands, retained node IDs, selected index `2`, safe reverse conversion,
78
+ non-square and structured indices, nearest-root targeting, stale targets, empty
79
+ slots, localization, literal text and Undo/Redo.
80
+
81
+ `root-transform-check.js` passed in Chromium for rich React and Quill's native
82
+ DOM field. It checks pointer and arrow/Enter acceptance, selected index editing,
83
+ radicand preservation, reverse conversion, and rejection of index `3` conversion.
84
+ The generated LaTeX and KaTeX preview match; editor/KaTeX radical screenshots
85
+ were inspected. This does not certify every browser or every host adapter.
86
+
87
+ ## Selection suggestion navigation — workspace, 2026-09-09
88
+
89
+ `apps/math-integrations/tests/selection-suggestions-check.js` passed in Chromium
90
+ for rich React and all nine host integrations. The check covers Shift+arrow
91
+ ranges, Up/Down navigation, the Alt+Down alias, Enter wrapping the selected
92
+ characters, retained input focus after wrapping, and native mouse-drag selection.
93
+ No page errors were reported. Core tests: 548 passed; core type check passed.
94
+ `selection-collapse-check.js` also passed for React horizontal caret recovery,
95
+ fraction boundaries and resumed typing. `tinymce-inline-check.js` passed for
96
+ inline and classic iframe hosts, including vertical caret recovery after Escape
97
+ dismisses the wrapping menu, Apply/Cancel, serialization and Undo/Redo.
98
+
99
+ A visible wrapping menu now owns vertical arrows. Left/Right still collapses
100
+ a model selection to its ordered edge. This replaces the Alt-only menu
101
+ navigation policy in the historical selection-collapse record below.
102
+
103
+ ## Styling and themes — workspace, 2026-09-09
104
+
105
+ Release browser regression: all 385 existing Chromium cases passed across the
106
+ full run and a focused rerun. Three stale expectations were updated for locale
107
+ query parameters, the explicit toolbar overflow button and Alt+arrow wrapping
108
+ navigation; all 26 cases in those three files passed on rerun. Shared integration
109
+ unit tests: 52 passing. No notation/model changes were needed for theming.
110
+
111
+ `apps/math-integrations/tests/style-customization-check.js` passed in Chromium:
112
+ independent light/dark instances, resolved host `var()` aliases, isolation from
113
+ unrelated portal-container variables, external toolbar styling, native iframe
114
+ menus, rich React suggestions/selection menus, and live theme switches preserving
115
+ input focus, document state and history. The site controls and styling reader
116
+ were also checked in Korean; English controls are covered by the fixture.
117
+
118
+ `tinymce-inline-check.js` additionally passed palette/action styling and the
119
+ existing typing, Apply/Cancel, serialization, history and cleanup cases in both
120
+ inline and classic iframe TinyMCE. The Apply control now has an explicit class,
121
+ so prepended size controls cannot prevent its primary style. These checks do not
122
+ certify arbitrary customer CSS palettes or browser/assistive-technology contrast.
123
+
124
+
125
+ ## Selection collapse — workspace, 2026-09-09
126
+
127
+ Core unit regression: 503 tests in 31 files. The added cases cover ordered edges
128
+ for forward/reversed structural ranges, partial-text and collapsed ranges,
129
+ absent ranges/non-arrow keys and unchanged source. Plain arrows now restore
130
+ a caret from model selection in both renderers; Alt+Up/Down retains a range for
131
+ wrapping-suggestion navigation.
132
+
133
+ Real Chromium checks in `apps/math-integrations/tests/selection-collapse-check.js`
134
+ passed for rich React, including subsequent typing and fraction-boundary collapse.
135
+ `tinymce-inline-check.js` passed all four plain arrows and subsequent typing in
136
+ both inline TinyMCE and its classic iframe. Native selection/toolbar, shared iframe
137
+ and all nine matrix host regressions also passed. Wider browser and OS IME checks
138
+ remain open. This is workspace evidence, not a new published package version.
139
+
140
+ ## Current release status — 0.2.1
4
141
 
5
142
  The dated entries below are historical verification records, not current release availability claims. Note inline editing is resolved according to the user; this release does not change or deploy Note. Math-editor release checks and site validation are recorded separately at the end of this document.
6
143
 
@@ -43,14 +180,68 @@ The in-app browser also verified the complete English demo/editor UI, quadratic-
43
180
  - Real OS Korean IME testing is deferred at the user's request. Synthetic composition events verify guarding and draft handling only.
44
181
  - Automated browser coverage is Chromium on macOS. Narrow viewport checks are not mobile-browser or touch validation.
45
182
  - Full screen-reader math navigation, high contrast, and every theme are not certified.
46
- - There is no saved-document validator, persistence/restart-recovery test, migration path or host-wide undo integration.
47
- - Rectangular matrix selections, keyboard model range extension, general LaTeX import and symbolic computation are not implemented.
183
+ - Saved-document validation, bounded LaTeX import and keyboard model ranges are implemented; model-version migration and recovery remain open. Host persistence/Undo evidence is recorded separately in the integration validation guide.
184
+ - Matrix rectangles and transpose are implemented in the workspace; full TeX interpretation and symbolic computation are not implemented.
48
185
  - Deep nesting and very large expressions have no agreed performance budget yet.
49
186
 
50
187
  ## Integration gates
51
188
 
52
189
  Before shipping inside a host product, test actual input methods and target browsers, establish a single undo owner, validate saved documents, verify focus across host/math boundaries, and define recoverable clipboard/import failures. Every new structure must have localized labels, deterministic transformations, one-step structural undo, browser interaction coverage and supported LaTeX output.
53
190
 
191
+ ## Matrix cell ranges and transpose — 2026-09-09 workspace
192
+
193
+ - 498 core tests pass, including 16 cell-rectangle/model/history cases and a grid
194
+ hit-test regression for tall fractions. Selection snapshots stay isolated;
195
+ invalid shapes and oversized pastes preserve the entire document/history.
196
+ - `apps/math-integrations/tests/matrix-range-check.js` passes in both rich React
197
+ and the native renderer with zero page errors. It covers active-input drag,
198
+ reversed corners, keyboard extension/shrinking, Shift+click, exact nested-cell
199
+ clipboard payloads, mismatched paste rejection, paste/cut/clear/typing Undo,
200
+ anchored TSV growth, full transpose and resumed nested-denominator editing.
201
+ - The same exported transposed matrix was inspected in both editors and KaTeX.
202
+ Screenshots: `output/playwright/matrix-range-native-katex.png` and
203
+ `output/playwright/matrix-range-react-katex.png`. Cell order and nested structure
204
+ match; editing retains its existing spacing and caret targets.
205
+ - Pointer hit testing uses row and column tracks independently once a cell range
206
+ starts. A tall fraction no longer attracts the pointer away from a neighboring
207
+ cell during edge scrolling. Pointer focus uses `preventScroll`, and the React
208
+ selection hint is below the expression to avoid moving it mid-drag.
209
+ - Clipboard checks dispatch ClipboardEvent with DataTransfer; they do not certify
210
+ system clipboard transfer to other applications. OS IME, touch, Safari/Firefox
211
+ and screen-reader coverage remain open. No new LaTeX syntax or model version was
212
+ introduced; neither npm publication nor site deployment is part of this run.
213
+
214
+ ## Native controls and precise selection — 2026-09-09 workspace
215
+
216
+ The native surface now exposes symbol search, templates and matrix presets behind
217
+ More tools, plus contextual row/column/delimiter controls. Selected passive text
218
+ is highlighted at its exact endpoints. Pointer drags can start in the live input
219
+ and extend through structures while ordinary within-input selection stays native.
220
+
221
+ - The core suite passes 481 tests, including toolbar catalog restrictions,
222
+ partial-text intersections, Shift-drag anchors, selection-menu dismissal and
223
+ suggestion placement around reserved host controls.
224
+ - `apps/math-integrations/tests/native-parity-check.js` passes in Chromium with
225
+ zero page errors: exact partial highlights, native within-input replacement,
226
+ cross-fraction selection in both directions, Shift-drag forward/backward anchors,
227
+ shrinking the range back, replacement and Undo, symbol insertion into selected
228
+ text, editable templates, matrix edits, filtered/hidden toolbars and teardown.
229
+ - Selection Escape checks preserve the model/native range on the first Escape,
230
+ reopen suggestions for a changed selection, and notify host Cancel on the second.
231
+ - The browser clipboard check dispatches a ClipboardEvent with DataTransfer and
232
+ verifies both exact LaTeX endpoints and the structured MIME payload. This is
233
+ handler validation, not an OS clipboard compatibility claim.
234
+ - Synthetic formula composition disables toolbar mutations and restores them on
235
+ composition end. Real OS IME testing remains deferred.
236
+ - The existing fraction fixture is shown alongside its KaTeX output in
237
+ `output/playwright/native-parity-editor-katex.png`; this addition changes
238
+ controls and selection presentation, not supported notation or glyph geometry.
239
+
240
+ These are workspace changes awaiting release. Whole logical-run active inputs,
241
+ one active-run role color, additional
242
+ complete locale packs and broader browser/accessibility certification remain open.
243
+ Host-specific browser findings are recorded in the integration validation guide.
244
+
54
245
  ## Line numbers and symbol discovery
55
246
 
56
247
  Three browser tests verify the UI-only line gutter through split/join/undo, its exclusion from LaTeX and model clipboard, the complete 90-symbol grid, bilingual search, insertion before typing, range replacement, undo, Escape and clipboard isolation in the search field. A native Home key did not move the caret in the macOS test environment; the test uses the supported Left arrow to reach the line start. The in-app browser visually confirmed the full symbol grid with names and search focus.
@@ -63,7 +254,12 @@ Three browser tests verify the UI-only line gutter through split/join/undo, its
63
254
  - A packed tarball was extracted into a temporary directory. Five entry points (`core`, `dom`, `web-component`, `vue`, `svelte`) imported without framework peers or browser globals; main/React/Solid entries imported after installing links to only their relevant local peers. All eight JS export paths and declared CSS/type targets exist. This is a local packaging smoke test, not publication or an exhaustive downstream TypeScript/bundler matrix.
64
255
  - The in-app browser visually verified the adapter lab and actual pure-JS `x/ → ↓ → Enter → 2` input, producing `\frac{x}{2}`. Inline mode displays without the block editor's large surface and toolbar.
65
256
 
66
- Remaining adapter gates: exact range highlighting, active-input cross-structure dragging, token-level edit colors, composition preview parity, native all-symbol/context toolbars, reactive-option/version matrix and accessibility/browser coverage. Native `MathEditorSurface` is not advertised as complete rich React parity. OS IME testing remains deferred.
257
+ Updated 2026-09-09: exact range highlighting, active-input cross-structure dragging
258
+ and native symbol/template/grid controls are implemented in the workspace.
259
+ Remaining adapter gates include token-level active input/colors, composition
260
+ preview parity, framework/version coverage and accessibility/browser coverage.
261
+ Native `MathEditorSurface` is not advertised as complete rich React parity.
262
+ OS IME testing remains deferred.
67
263
 
68
264
  ## Composition, source readability and JSON locales — 2026-09-08
69
265
 
@@ -258,3 +454,247 @@ Package build and 388 unit tests passed. Built-in locale tests reject misplaced
258
454
  ## 0.2.1 release verification
259
455
 
260
456
  Formatting, types, 390 unit tests and all eight packed entry points passed. Thirty-nine related Chromium cases passed for keyboard and drag selection, clipboard, wrapping, tokens, brace/cases discovery, preview and bundled locales. Website PNG download/copy checks validate dimensions and nonblank raster pixels. Long-formula fitting and transparent alpha were checked separately. Image generation is a demo dependency, not a library API.
457
+
458
+ ## Editing utilities — workspace, 2026-09-09
459
+
460
+ Core unit regression: **548 tests**. Shared integrations: **52 tests**. Core, integration package and both demo applications pass TypeScript checks. The main demo documentation/site build and the integration demo production build pass. The integration demo retains its existing large host-SDK chunk warnings.
461
+
462
+ - `token-paste-check.js`: Vue and rich React pass continuous token typing, middle insertion, boundary deletion, range replacement through explicit LaTeX paste, atomic diagnostics, continued typing and Undo.
463
+ - `quick-presentation-check.js`: Vue, rich React and Quill pass symbol/template favorites, recent items, insertion focus, bracket/size/limit changes and Undo. Editor views and the live KaTeX output were visually compared.
464
+ - `host-composition-check.js`: 16 supported inline/block combinations across nine host demos preserve browser preedit, commit/cancel and subsequent typing without per-key refocusing.
465
+ - `latex-paste-host-check.js`: the same 16 combinations keep Ctrl/Cmd+Enter inside the paste form. Inserted fractions remain local drafts, typing resumes, and Cancel preserves host serialization.
466
+ - `native-parity-check.js`: exact text and cross-structure selection, Shift-drag, shrinkback, structured copy, discovery, grid controls, restrictions and teardown pass. Its coordinate helper now maps logical text across token spans.
467
+ - Quill composition and typing regression fixtures pass, including read-only recovery, host history and matrix-cell entry.
468
+
469
+ This is local Chromium evidence. OS IME, Safari/Firefox, installed WordPress and cross-application system clipboard checks were not repeated. No new mathematical grammar or numerical behavior is introduced. Release artifacts prepared before these changes require regeneration; nothing was published by this work.
470
+
471
+
472
+ ## EDIT-019 continuous editing — workspace, 2026-09-10
473
+
474
+ - Run: `2026-09-09T17-47-53-597Z`; source fingerprint remained stable.
475
+ - Evidence: [report](../../output/playwright/editing-scenarios/2026-09-09T17-47-53-597Z/REPORT.md), [checkpoints and source hashes](../../output/playwright/editing-scenarios/2026-09-09T17-47-53-597Z/report.json).
476
+ - Command: `pnpm --filter @barocss/math-editor test:editing`.
477
+ - Environment: Chromium 152 / macOS, English locale, workspace source.
478
+ - **React standalone block: PASS, 28 checkpoints. Quill in-place block: PASS, 29 checkpoints.**
479
+ - Real key input creates `fraction(indexedRoot(3, ab), 2) + matrix(1, 2; 3, 4)`;
480
+ an explicit tree assertion checks content and nesting. The last cell becomes
481
+ `456789` in a second uninterrupted typing chain.
482
+ - Both surfaces pass two five-step Undo/Redo chains, retained typing focus,
483
+ empty-root Delete/Undo/Redo and unchanged retained content. Each first history
484
+ step is compared with its recorded structural checkpoint.
485
+ - Quill draft operations leave host data unchanged. Apply is one host Undo step;
486
+ Redo restores it. Save, page reload, Restore and reopen preserve the Delta and
487
+ formula structure. The restored matrix remains editable; Cancel preserves the
488
+ saved document. React has no host persistence lifecycle, so that part is N/A.
489
+ - The runner fails on either scenario failure or a changed source fingerprint.
490
+ It stores the executed fixture, failure screenshots, diagnostics and final data.
491
+ - No runtime library changes were required. Earlier fixture failures exposed OS
492
+ `End` assumptions and selection of the wrong saved block; the final fixture
493
+ verifies caret offsets with arrows and reopens the uniquely identified formula.
494
+ - Not covered: other hosts, Quill inline mode, real OS IME/clipboard,
495
+ Firefox/WebKit, touch, accessibility and performance budgets. No release-wide
496
+ pass or new rendering pass is claimed.
497
+
498
+
499
+ ## EDIT-019 Quill inline extension — workspace, 2026-09-10
500
+
501
+ - Run: `2026-09-09T22-30-59-017Z`; source fingerprint remained stable.
502
+ - [Report](../../output/playwright/editing-scenarios/2026-09-09T22-30-59-017Z/REPORT.md) and
503
+ [checkpoints](../../output/playwright/editing-scenarios/2026-09-09T22-30-59-017Z/report.json).
504
+ - **React block: PASS (28 checkpoints); Quill block: PASS (29); Quill inline: PASS (30).**
505
+ - The unchanged continuous editing chain runs in all three targets. Renderer and
506
+ mode are recorded separately, including artifact names and the failure summary.
507
+ - Quill inline commits with Enter from the outer boundary. No extra formula line
508
+ or host paragraph appears; prose is unchanged by math editing.
509
+ - Apply/host Undo/Redo, Save/reload/Restore, re-edit and Cancel preserve the
510
+ inline formula. A later Right-arrow exit returns focus to Quill; typing `q`
511
+ inserts exactly one character immediately after that formula. Host Undo
512
+ restores the committed Delta, including formula data.
513
+ - Runtime library code was unchanged. The runner and scenario documentation were
514
+ extended; no npm publication or new rendering audit was required.
515
+ - Other hosts, standalone inline adapters, OS IME/clipboard, Firefox/WebKit,
516
+ touch, accessibility and performance remain outside this run.
517
+
518
+
519
+ ## EDIT-019 Tiptap and ProseMirror — workspace, 2026-09-10
520
+
521
+ - Run: `2026-09-09T22-39-51-097Z`, stable source fingerprint.
522
+ - [Report](../../output/playwright/editing-scenarios/2026-09-09T22-39-51-097Z/REPORT.md) and
523
+ [checkpoints and hashes](../../output/playwright/editing-scenarios/2026-09-09T22-39-51-097Z/report.json).
524
+ - **7 targets PASS / 205 checkpoints:** React block (28), Quill block/inline
525
+ (29/30), Tiptap block/inline (29/30), ProseMirror block/inline (29/30).
526
+ - Chromium 152 on macOS, English UI, workspace source. The extended runner hashes
527
+ both newly covered plugin sources and package metadata.
528
+ - Each target passes the existing continuous formula chain. Integrated hosts
529
+ additionally check Apply/host Undo/Redo, Save/reload/Restore, re-edit/Cancel,
530
+ retained formula data and unchanged prose/container structure. Inline targets
531
+ check Enter commit, right-boundary exit, exact prose position and host Undo.
532
+ - Initial integrated run `2026-09-09T22-36-38-459Z`: six PASS, Tiptap inline FAIL.
533
+ A quick prose edit after Restore shared the restored document's history event;
534
+ Undo removed both. The sample now brackets `setContent` with `closeHistory`
535
+ transactions, keeping the replacement and subsequent typing separate.
536
+ - Corrected run `2026-09-09T22-38-26-544Z`: seven PASS. The final run above repeats
537
+ all seven targets with the final runner documentation and source hashes.
538
+ - Integration-demo TypeScript and production build pass. Existing large-chunk
539
+ build warnings remain. Test source formatting passes. Core/plugin runtime
540
+ code was unchanged; the fix belongs to the Tiptap demo's restoration callback.
541
+ - Remaining: Lexical, Editor.js, TinyMCE, CKEditor, Slate and Gutenberg; native OS
542
+ IME/clipboard, other browser engines, touch, accessibility and performance.
543
+
544
+
545
+ ## EDIT-019 Lexical — workspace, 2026-09-10
546
+
547
+ - Run: `2026-09-09T23-08-15-353Z`, stable source fingerprint.
548
+ - [Report](../../output/playwright/editing-scenarios/2026-09-09T23-08-15-353Z/REPORT.md) and
549
+ [checkpoints and hashes](../../output/playwright/editing-scenarios/2026-09-09T23-08-15-353Z/report.json).
550
+ - **9 targets PASS / 264 checkpoints:** React block (28), Quill block/inline
551
+ (29/30), Tiptap block/inline (29/30), ProseMirror block/inline (29/30),
552
+ Lexical block/inline (29/30).
553
+ - Chromium 152 on macOS, English UI, workspace source. Fingerprints now include
554
+ the Lexical plugin source and package metadata.
555
+ - Lexical passes the full nested editing and two history chains, Apply as one
556
+ host Undo event, Redo, Save/reload/Restore, re-edit and Cancel. Inline also
557
+ passes Enter commit without a new paragraph, right-boundary exit, focus return,
558
+ typing immediately after the formula and host Undo.
559
+ - Host checks read Lexical serialized state and retain container boundaries and
560
+ formula atoms. Drafts must not change saved host state. Restoration must match
561
+ the complete saved JSON; math rendering alone is not the persistence check.
562
+ - The initial run `2026-09-09T23-06-35-494Z` reached Save/Restore in both Lexical
563
+ modes but used an incorrect locator for reopening. Lexical uses a mounted
564
+ `.bme-lexical-node` widget; `data-barocss-math` belongs to its HTML export.
565
+ The fixture now locates its live widget. No product code change was needed.
566
+ - Runner formatting passes. This change only extends tests and documentation;
567
+ no new build, package publication or rendering audit was required.
568
+ - Next: Editor.js, TinyMCE, CKEditor, Slate and Gutenberg. Native OS IME/clipboard,
569
+ other browser engines, touch, accessibility and performance remain outside this run.
570
+
571
+
572
+ ## EDIT-019 Editor.js — workspace, 2026-09-10
573
+
574
+ - Run: `2026-09-09T23-25-26-845Z`, stable source fingerprint.
575
+ - [Report](../../output/playwright/editing-scenarios/2026-09-09T23-25-26-845Z/REPORT.md) and
576
+ [checkpoints and hashes](../../output/playwright/editing-scenarios/2026-09-09T23-25-26-845Z/report.json).
577
+ - **10 targets PASS / 293 checkpoints:** React block (28), Quill/Tiptap/
578
+ ProseMirror/Lexical block and inline (29/30 each), Editor.js block (29).
579
+ - Chromium 152 on macOS, English UI, workspace source. Fingerprints include
580
+ Editor.js plugin source and package metadata.
581
+ - Editor.js passes nested fraction/root/matrix editing, suggestion selection,
582
+ two uninterrupted formula Undo/Redo chains, empty-root deletion/restoration,
583
+ Apply, Save/reload/Restore, re-edit and Cancel. Draft checks confirm saved host
584
+ data stays unchanged until Apply; prose blocks and block order remain intact.
585
+ - Async `save()` comparisons exclude only the generated `time` field. Block IDs,
586
+ saved model data, paragraph data and version remain in persistence assertions.
587
+ - **Editor.js host Undo/Redo is not covered:** the demo has no document history
588
+ integration. The runner records this limitation in `hostHistory`; it retains
589
+ the mandatory host Undo/Redo assertions for other configured hosts. Editor.js
590
+ inline mode is outside the block tool's contract.
591
+ - Test-source formatting passes. Only the runner, fixture and documentation
592
+ changed; no runtime fix, build, publication or new rendering audit was needed.
593
+ - Next: TinyMCE, CKEditor, Slate and Gutenberg. Native OS IME/clipboard, other
594
+ browser engines, touch, accessibility and performance remain separate work.
595
+
596
+
597
+ ## EDIT-019 TinyMCE — workspace, 2026-09-10
598
+
599
+ - Run: `2026-09-09T23-39-57-339Z`, stable source fingerprint.
600
+ - [Report](../../output/playwright/editing-scenarios/2026-09-09T23-39-57-339Z/REPORT.md) and
601
+ [checkpoints and hashes](../../output/playwright/editing-scenarios/2026-09-09T23-39-57-339Z/report.json).
602
+ - **12 targets PASS / 352 checkpoints:** React block (28), Quill/Tiptap/
603
+ ProseMirror/Lexical/TinyMCE block and inline (29/30 each), Editor.js block (29).
604
+ - Chromium 152 on macOS, English UI, workspace source. TinyMCE 8.9.0 uses
605
+ `inline: true` for its host. Both math modes are covered; classic iframe mode
606
+ is not covered by this run. Fingerprints include TinyMCE source and metadata.
607
+ - TinyMCE passes the sustained fraction/root/matrix chain, formula history,
608
+ draft isolation, one host Undo/Redo for Apply, Save/reload/Restore, re-edit and
609
+ Cancel. Inline also passes Enter commit, right-boundary exit, focus return,
610
+ typing immediately after the formula and host Undo.
611
+ - The fixture applies and reopens an empty atom before the chain because TinyMCE
612
+ inserts on Apply. This exposed a real bug: the empty preview renderer returned
613
+ no visible content, leaving no click target. The adapter now shows the existing
614
+ localized empty-formula message and skips the renderer for empty LaTeX.
615
+ Serialized content stays empty; the test checks the label does not leak into HTML.
616
+ - HTML comparisons retain the complete serialized document. A detached parser
617
+ reads prose and element boundaries for caret checks. Live locators exclude
618
+ TinyMCE's `.mce-offscreen-selection` clone inside the editable body.
619
+ - Diagnostic run `2026-09-09T23-38-20-112Z` confirmed that a reported prose Undo
620
+ failure was in the fixture: saved and actual HTML were identical, but building
621
+ the expected prose result had mutated the saved units array. The fixture now
622
+ copies that array. No timing wait or product history change is used to pass it.
623
+ - TinyMCE package TypeScript, two unit tests, build and changed-source formatting
624
+ pass. Package-local build also exposed a metafile path check using the wrong
625
+ working directory. The build now sets esbuild's working directory to the repo
626
+ root; the normal package build command succeeds with its dependency checks intact.
627
+ - Patch changeset: `.changeset/tiny-math-empty-preview.md`. No package was published.
628
+ - Remaining: CKEditor, Slate, Gutenberg, TinyMCE iframe mode, native OS
629
+ IME/clipboard and other browser/input environments. Editor.js document history
630
+ remains unverified because its demo has no host history integration.
631
+
632
+
633
+ ## EDIT-019 CKEditor — workspace, 2026-09-10
634
+
635
+ - Run: `2026-09-09T23-44-59-263Z`, stable source fingerprint.
636
+ - [Report](../../output/playwright/editing-scenarios/2026-09-09T23-44-59-263Z/REPORT.md) and
637
+ [checkpoints and hashes](../../output/playwright/editing-scenarios/2026-09-09T23-44-59-263Z/report.json).
638
+ - **14 targets PASS / 411 checkpoints:** React block (28), Quill/Tiptap/
639
+ ProseMirror/Lexical/TinyMCE/CKEditor block and inline (29/30 each),
640
+ Editor.js block (29).
641
+ - Chromium 152 on macOS, English UI, workspace source. CKEditor 48.5.0 uses the
642
+ local ClassicEditor demo. Fingerprints include CKEditor plugin source and
643
+ package metadata. This run does not cover other CKEditor builds or collaboration.
644
+ - CKEditor passes the sustained fraction/root/matrix chain, keyboard suggestion
645
+ selection, two formula Undo/Redo chains, empty-root deletion/restoration,
646
+ unchanged host data during drafts, Apply as one host Undo event and host Redo.
647
+ - Save/reload/Restore retains the complete serialized HTML and editable math
648
+ structure. Re-edit and Cancel leave that HTML unchanged. Inline also passes
649
+ Enter commit without another paragraph, Right-arrow exit, focus return,
650
+ prose input immediately after the formula and host Undo.
651
+ - The fixture reuses the detached HTML parser for prose/container checks and
652
+ copies parsed units when constructing expectations. Full saved-state equality
653
+ remains required for history and persistence checks.
654
+ - Test-source formatting passes. Only tests and documentation changed in this
655
+ extension; no runtime fix, additional build or package publication was needed.
656
+ - Next: Slate and Gutenberg. TinyMCE iframe hosts, other CKEditor builds,
657
+ native OS IME/clipboard and other browser/input environments remain separate
658
+ targets. Editor.js document history is still outside its demo's configuration.
659
+
660
+
661
+ ## EDIT-019 all integration demos — workspace, 2026-09-10
662
+
663
+ - Run: `2026-09-09T23-55-26-302Z`, stable source fingerprint.
664
+ - [Report](../../output/playwright/editing-scenarios/2026-09-09T23-55-26-302Z/REPORT.md) and
665
+ [checkpoints and hashes](../../output/playwright/editing-scenarios/2026-09-09T23-55-26-302Z/report.json).
666
+ - **17 targets PASS / 499 checkpoints**, covering all nine integration demos
667
+ plus standalone React block. Chromium 152 on macOS, English UI, workspace source.
668
+
669
+ | Editor | Tested math modes | Checkpoints | Host Undo/Redo |
670
+ | --- | --- | ---: | --- |
671
+ | React standalone | Block | 28 | Not applicable |
672
+ | Quill | Block + inline | 59 | PASS |
673
+ | Tiptap | Block + inline | 59 | PASS |
674
+ | ProseMirror | Block + inline | 59 | PASS |
675
+ | Lexical | Block + inline | 59 | PASS |
676
+ | Editor.js | Block | 29 | Not configured; unverified |
677
+ | TinyMCE | Block + inline, inline host | 59 | PASS |
678
+ | CKEditor | Block + inline, ClassicEditor | 59 | PASS |
679
+ | Slate | Block + inline | 59 | PASS |
680
+ | Gutenberg | Block, standalone provider | 29 | PASS |
681
+
682
+ - Slate passes the sustained nested editing chain, two formula Undo/Redo chains,
683
+ Apply as one host history event, Save/reload/Restore, re-edit and Cancel.
684
+ Inline also passes Enter commit, Right-arrow exit, host focus, exact prose
685
+ insertion position and host Undo. Comparisons retain the saved descendant
686
+ array and formula objects; prose checks also preserve paragraph boundaries.
687
+ - Gutenberg passes the same block chain and provider host Undo/Redo. Full saved
688
+ HTML equality includes WordPress comments and encoded math data. A separate
689
+ detached DOM comparison checks prose and block order; comments are not prose.
690
+ - Both new hosts keep saved document data unchanged while editing a draft.
691
+ Restore reproduces the full saved state and reopens the same editable model.
692
+ - Fingerprints now include Slate and Gutenberg source/package metadata, as well
693
+ as the previously covered hosts, core, shared helpers, demos and test runner.
694
+ - Formatting passes. This extension changed only tests and documentation; no
695
+ runtime fix, new build or publication was needed.
696
+ - This run covers local demo configurations. It does not replace the separate
697
+ WordPress admin/plugin ZIP checks. TinyMCE iframe, other CKEditor builds,
698
+ collaboration, native OS IME/clipboard, Firefox/WebKit, touch, accessibility
699
+ and performance remain separate targets. Editor.js/Gutenberg are block tools;
700
+ no inline mode is claimed for them.
@@ -0,0 +1,21 @@
1
+ import { type MathState, type MathStructure } from './model.js';
2
+ /** The closest supported wrapper owns the footer, even when roots and fences are nested. */
3
+ export declare function structureEditingContext(state: MathState): {
4
+ fence: MathStructure;
5
+ root?: undefined;
6
+ } | {
7
+ root: {
8
+ id: string;
9
+ kind: "root" | "indexedRoot";
10
+ target: "root" | "indexedRoot";
11
+ canTransform: boolean;
12
+ indexCaret: {
13
+ id: string;
14
+ start: number;
15
+ end: number;
16
+ } | undefined;
17
+ } | undefined;
18
+ fence?: undefined;
19
+ } | undefined;
20
+ /** Reject an action if focus has moved to a different wrapper since it was displayed. */
21
+ export declare function changeContextFence(state: MathState, id: string, kind: string): MathState;
@@ -0,0 +1,37 @@
1
+ import { documentRows, isLiteralText, } from './model.js';
2
+ import { fences } from './fences.js';
3
+ import { rootEditingContext } from './root-transform.js';
4
+ import { setMathPresentation } from './presentation.js';
5
+ /** The closest supported wrapper owns the footer, even when roots and fences are nested. */
6
+ export function structureEditingContext(state) {
7
+ if (isLiteralText(state.document, state.caret.id))
8
+ return;
9
+ const visit = (row, parent) => {
10
+ for (const node of row.children) {
11
+ if (node.type === 'text') {
12
+ if (node.id === state.caret.id)
13
+ return parent;
14
+ }
15
+ else {
16
+ const target = fences(node) || ['root', 'indexedRoot'].includes(node.type) ? node : parent;
17
+ for (const slot of node.slots) {
18
+ const found = visit(slot, target);
19
+ if (found)
20
+ return found;
21
+ }
22
+ }
23
+ }
24
+ };
25
+ const node = documentRows(state.document)
26
+ .map((row) => visit(row))
27
+ .find(Boolean);
28
+ if (!node)
29
+ return;
30
+ return fences(node) ? { fence: node } : { root: rootEditingContext(state) };
31
+ }
32
+ /** Reject an action if focus has moved to a different wrapper since it was displayed. */
33
+ export function changeContextFence(state, id, kind) {
34
+ return structureEditingContext(state)?.fence?.id === id
35
+ ? setMathPresentation(state, id, { fence: kind })
36
+ : state;
37
+ }
package/dist/core.d.ts CHANGED
@@ -1,6 +1,8 @@
1
1
  export * from './model.js';
2
2
  export * from './matrix.js';
3
+ export * from './matrix-range.js';
3
4
  export * from './lines.js';
5
+ export * from './vertical-navigation.js';
4
6
  export * from './range.js';
5
7
  export * from './tokens.js';
6
8
  export * from './symbols.js';
@@ -10,4 +12,6 @@ export * from './session.js';
10
12
  export * from './i18n.js';
11
13
  export * from './latex.js';
12
14
  export * from './document-codec.js';
13
- //# sourceMappingURL=core.d.ts.map
15
+ export * from './latex-insertion.js';
16
+ export * from './preferences.js';
17
+ export * from './presentation.js';
package/dist/core.js CHANGED
@@ -1,6 +1,8 @@
1
1
  export * from './model.js';
2
2
  export * from './matrix.js';
3
+ export * from './matrix-range.js';
3
4
  export * from './lines.js';
5
+ export * from './vertical-navigation.js';
4
6
  export * from './range.js';
5
7
  export * from './tokens.js';
6
8
  export * from './symbols.js';
@@ -10,4 +12,6 @@ export * from './session.js';
10
12
  export * from './i18n.js';
11
13
  export * from './latex.js';
12
14
  export * from './document-codec.js';
13
- //# sourceMappingURL=core.js.map
15
+ export * from './latex-insertion.js';
16
+ export * from './preferences.js';
17
+ export * from './presentation.js';
@@ -1,4 +1,3 @@
1
1
  import { type MathDocument } from './model.js';
2
2
  /** Validate persisted JSON before passing it to a renderer. Reject duplicate caret addresses. */
3
3
  export declare function parseMathDocument(source: string): MathDocument | undefined;
4
- //# sourceMappingURL=document-codec.d.ts.map
@@ -34,4 +34,3 @@ export function parseMathDocument(source) {
34
34
  return;
35
35
  }
36
36
  }
37
- //# sourceMappingURL=document-codec.js.map
@@ -0,0 +1,3 @@
1
+ import type { MathCaretGeometry } from '../vertical-navigation.js';
2
+ /** Measure existing mirrors, including React and native DOM token spans. */
3
+ export declare function renderedCaretGeometry(surface: HTMLElement): MathCaretGeometry;
@@ -0,0 +1,41 @@
1
+ /** Measure existing mirrors, including React and native DOM token spans. */
2
+ export function renderedCaretGeometry(surface) {
3
+ const runs = new Map();
4
+ for (const run of surface.querySelectorAll('.me-run[data-run-id]')) {
5
+ const id = run.dataset.runId;
6
+ const group = runs.get(id) ?? [];
7
+ group.push(run);
8
+ runs.set(id, group);
9
+ }
10
+ return ({ id, offset, affinity }) => {
11
+ const group = runs.get(id);
12
+ if (!group)
13
+ return;
14
+ const contains = (run) => {
15
+ const start = Number(run.dataset.tokenStart ?? 0);
16
+ return offset >= start && offset <= start + (run.dataset.value?.length ?? 0);
17
+ };
18
+ const candidates = group.filter(contains);
19
+ // An explicit side must win over active-input state when measuring target candidates.
20
+ const run = affinity
21
+ ? affinity === 'forward'
22
+ ? candidates.at(-1)
23
+ : candidates[0]
24
+ : candidates.find((item) => item.querySelector('.me-input')) ?? candidates[0];
25
+ const mirror = run?.querySelector('.me-measure');
26
+ if (!run || !mirror)
27
+ return;
28
+ const value = run.dataset.value ?? '';
29
+ if (value && mirror.firstChild?.nodeType === 3) {
30
+ const range = surface.ownerDocument.createRange();
31
+ range.setStart(mirror.firstChild, offset - Number(run.dataset.tokenStart ?? 0));
32
+ range.collapse(true);
33
+ const rect = range.getBoundingClientRect();
34
+ if (rect.height)
35
+ return { x: rect.left, y: rect.top + rect.height / 2 };
36
+ }
37
+ const rect = mirror.getBoundingClientRect();
38
+ if (!value && rect.height)
39
+ return { x: rect.left + rect.width / 2, y: rect.top + rect.height / 2 };
40
+ };
41
+ }
@@ -0,0 +1,2 @@
1
+ /** Keep focus in the same document (including iframe hosts). Arrow keys only browse; Enter applies. */
2
+ export declare function focusContextAction(host: HTMLElement, key: string): boolean;