@barocss/math-editor 0.2.1 → 0.4.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 (180) 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 +168 -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 +1 -1
  9. package/CHANGELOG.md +45 -0
  10. package/EMBEDDING.md +4 -0
  11. package/IMPLEMENTATION.md +27 -2
  12. package/JSON-MODEL.md +1 -0
  13. package/LATEX-GUIDE.md +8 -1
  14. package/LATEX-SCOPE.md +2 -2
  15. package/LICENSE +1 -3
  16. package/README.md +145 -37
  17. package/ROADMAP.md +93 -11
  18. package/STYLING.md +157 -0
  19. package/SUPPORT.md +24 -12
  20. package/VALIDATION.md +113 -4
  21. package/dist/core.d.ts +5 -1
  22. package/dist/core.js +5 -1
  23. package/dist/document-codec.d.ts +0 -1
  24. package/dist/document-codec.js +0 -1
  25. package/dist/dom/caret-geometry.d.ts +3 -0
  26. package/dist/dom/caret-geometry.js +41 -0
  27. package/dist/dom/elements.d.ts +1 -2
  28. package/dist/dom/elements.js +2 -3
  29. package/dist/dom/latex-panel.d.ts +10 -0
  30. package/dist/dom/latex-panel.js +59 -0
  31. package/dist/dom/matrix-selection.d.ts +11 -0
  32. package/dist/dom/matrix-selection.js +30 -0
  33. package/dist/dom/menu-position.d.ts +14 -2
  34. package/dist/dom/menu-position.js +84 -15
  35. package/dist/dom/presentation-controls.d.ts +4 -0
  36. package/dist/dom/presentation-controls.js +56 -0
  37. package/dist/dom/quick-panel.d.ts +12 -0
  38. package/dist/dom/quick-panel.js +102 -0
  39. package/dist/dom/selection.d.ts +29 -0
  40. package/dist/dom/selection.js +53 -0
  41. package/dist/dom/symbol-panel.d.ts +9 -0
  42. package/dist/dom/symbol-panel.js +146 -0
  43. package/dist/dom/theme.d.ts +6 -0
  44. package/dist/dom/theme.js +68 -0
  45. package/dist/dom/toolbar-catalog.d.ts +10 -0
  46. package/dist/dom/toolbar-catalog.js +35 -0
  47. package/dist/dom/toolbar.d.ts +13 -2
  48. package/dist/dom/toolbar.js +295 -28
  49. package/dist/dom.d.ts +7 -1
  50. package/dist/dom.js +510 -128
  51. package/dist/editor-labels.d.ts +0 -1
  52. package/dist/editor-labels.js +0 -1
  53. package/dist/enter-policy.d.ts +0 -1
  54. package/dist/enter-policy.js +0 -1
  55. package/dist/fences.d.ts +0 -1
  56. package/dist/fences.js +0 -1
  57. package/dist/i18n.d.ts +0 -1
  58. package/dist/i18n.js +0 -1
  59. package/dist/index.d.ts +4 -1
  60. package/dist/index.js +4 -1
  61. package/dist/latex-insertion.d.ts +12 -0
  62. package/dist/latex-insertion.js +26 -0
  63. package/dist/latex-paste-panel.d.ts +3 -0
  64. package/dist/latex-paste-panel.js +18 -0
  65. package/dist/latex.d.ts +0 -1
  66. package/dist/latex.js +0 -1
  67. package/dist/lines.d.ts +0 -1
  68. package/dist/lines.js +0 -1
  69. package/dist/locales/en.js +27 -1
  70. package/dist/locales/en.json +27 -1
  71. package/dist/locales/ko.js +27 -1
  72. package/dist/locales/ko.json +27 -1
  73. package/dist/math-editor-toolbar.d.ts +4 -2
  74. package/dist/math-editor-toolbar.js +3 -4
  75. package/dist/math-editor.d.ts +5 -2
  76. package/dist/math-editor.js +285 -46
  77. package/dist/matrix-range.d.ts +40 -0
  78. package/dist/matrix-range.js +242 -0
  79. package/dist/matrix.d.ts +0 -1
  80. package/dist/matrix.js +0 -1
  81. package/dist/model.d.ts +0 -1
  82. package/dist/model.js +0 -1
  83. package/dist/outputs.d.ts +0 -1
  84. package/dist/outputs.js +0 -1
  85. package/dist/preferences.d.ts +24 -0
  86. package/dist/preferences.js +66 -0
  87. package/dist/presentation-controls.d.ts +10 -0
  88. package/dist/presentation-controls.js +10 -0
  89. package/dist/presentation.d.ts +13 -0
  90. package/dist/presentation.js +86 -0
  91. package/dist/quick-panel.d.ts +2 -0
  92. package/dist/quick-panel.js +17 -0
  93. package/dist/range.d.ts +2 -1
  94. package/dist/range.js +11 -1
  95. package/dist/react.d.ts +0 -1
  96. package/dist/react.js +0 -1
  97. package/dist/session.d.ts +31 -2
  98. package/dist/session.js +108 -7
  99. package/dist/solid.d.ts +0 -1
  100. package/dist/solid.js +0 -1
  101. package/dist/suggestions.d.ts +4 -1
  102. package/dist/suggestions.js +100 -12
  103. package/dist/svelte.d.ts +0 -1
  104. package/dist/svelte.js +0 -1
  105. package/dist/symbol-browser.d.ts +0 -1
  106. package/dist/symbol-browser.js +0 -1
  107. package/dist/symbols.d.ts +0 -1
  108. package/dist/symbols.js +0 -1
  109. package/dist/templates.d.ts +0 -1
  110. package/dist/templates.js +0 -1
  111. package/dist/tokens.d.ts +0 -1
  112. package/dist/tokens.js +0 -1
  113. package/dist/vertical-navigation.d.ts +15 -0
  114. package/dist/vertical-navigation.js +145 -0
  115. package/dist/vue.d.ts +0 -1
  116. package/dist/vue.js +0 -1
  117. package/dist/web-component.d.ts +0 -1
  118. package/dist/web-component.js +0 -1
  119. package/package.json +1 -1
  120. package/src/style.css +254 -129
  121. package/dist/core.d.ts.map +0 -1
  122. package/dist/core.js.map +0 -1
  123. package/dist/document-codec.d.ts.map +0 -1
  124. package/dist/document-codec.js.map +0 -1
  125. package/dist/dom/elements.d.ts.map +0 -1
  126. package/dist/dom/elements.js.map +0 -1
  127. package/dist/dom/menu-position.d.ts.map +0 -1
  128. package/dist/dom/menu-position.js.map +0 -1
  129. package/dist/dom/toolbar.d.ts.map +0 -1
  130. package/dist/dom/toolbar.js.map +0 -1
  131. package/dist/dom.d.ts.map +0 -1
  132. package/dist/dom.js.map +0 -1
  133. package/dist/editor-labels.d.ts.map +0 -1
  134. package/dist/editor-labels.js.map +0 -1
  135. package/dist/enter-policy.d.ts.map +0 -1
  136. package/dist/enter-policy.js.map +0 -1
  137. package/dist/fences.d.ts.map +0 -1
  138. package/dist/fences.js.map +0 -1
  139. package/dist/i18n.d.ts.map +0 -1
  140. package/dist/i18n.js.map +0 -1
  141. package/dist/index.d.ts.map +0 -1
  142. package/dist/index.js.map +0 -1
  143. package/dist/latex.d.ts.map +0 -1
  144. package/dist/latex.js.map +0 -1
  145. package/dist/lines.d.ts.map +0 -1
  146. package/dist/lines.js.map +0 -1
  147. package/dist/math-editor-toolbar.d.ts.map +0 -1
  148. package/dist/math-editor-toolbar.js.map +0 -1
  149. package/dist/math-editor.d.ts.map +0 -1
  150. package/dist/math-editor.js.map +0 -1
  151. package/dist/matrix.d.ts.map +0 -1
  152. package/dist/matrix.js.map +0 -1
  153. package/dist/model.d.ts.map +0 -1
  154. package/dist/model.js.map +0 -1
  155. package/dist/outputs.d.ts.map +0 -1
  156. package/dist/outputs.js.map +0 -1
  157. package/dist/range.d.ts.map +0 -1
  158. package/dist/range.js.map +0 -1
  159. package/dist/react.d.ts.map +0 -1
  160. package/dist/react.js.map +0 -1
  161. package/dist/session.d.ts.map +0 -1
  162. package/dist/session.js.map +0 -1
  163. package/dist/solid.d.ts.map +0 -1
  164. package/dist/solid.js.map +0 -1
  165. package/dist/suggestions.d.ts.map +0 -1
  166. package/dist/suggestions.js.map +0 -1
  167. package/dist/svelte.d.ts.map +0 -1
  168. package/dist/svelte.js.map +0 -1
  169. package/dist/symbol-browser.d.ts.map +0 -1
  170. package/dist/symbol-browser.js.map +0 -1
  171. package/dist/symbols.d.ts.map +0 -1
  172. package/dist/symbols.js.map +0 -1
  173. package/dist/templates.d.ts.map +0 -1
  174. package/dist/templates.js.map +0 -1
  175. package/dist/tokens.d.ts.map +0 -1
  176. package/dist/tokens.js.map +0 -1
  177. package/dist/vue.d.ts.map +0 -1
  178. package/dist/vue.js.map +0 -1
  179. package/dist/web-component.d.ts.map +0 -1
  180. package/dist/web-component.js.map +0 -1
@@ -1,4 +1,13 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { setMathPresentation } from './presentation.js';
3
+ import { PresentationControls } from './presentation-controls.js';
4
+ import { createMathPreferences } from './preferences.js';
5
+ import { QuickPanel } from './quick-panel.js';
6
+ import { toolbarTemplates } from './dom/toolbar-catalog.js';
7
+ import { insertLatex } from './latex-insertion.js';
8
+ import { LatexPastePanel } from './latex-paste-panel.js';
9
+ import { followMathTheme } from './dom/theme.js';
10
+ import { matrixPointerRange } from './dom/matrix-selection.js';
2
11
  import { positionMathMenu } from './dom/menu-position.js';
3
12
  import { fences } from './fences.js';
4
13
  import { parseLatex } from './latex.js';
@@ -7,26 +16,34 @@ import { MathEditorToolbar } from './math-editor-toolbar.js';
7
16
  import { SymbolBrowser } from './symbol-browser.js';
8
17
  import { insertTemplate } from './templates.js';
9
18
  import { translate, mathLocaleDirection, } from './i18n.js';
10
- import { extendKeyboardRange, wrapRange, wrappingKinds, copyRange, deleteRange, fragmentLatex, MATH_CLIPBOARD_TYPE, parseFragment, pasteFragment, resolveRange, } from './range.js';
19
+ import { extendKeyboardRange, collapseKeyboardRange, wrapRange, wrappingKinds, copyRange, deleteRange, fragmentLatex, MATH_CLIPBOARD_TYPE, parseFragment, pasteFragment, resolveRange, } from './range.js';
11
20
  import { tokenizeMathText, tokenIndexAt } from './tokens.js';
12
- import { splitLine, joinPreviousLine, moveLineVertical } from './lines.js';
13
- import { insertIdentityMatrix, insertMatrix, activeGrid, MATRIX_MAX_SIZE, matrixEnvironments, moveMatrixVertical, resizeMatrix, setMatrixEnvironment, } from './matrix.js';
21
+ import { splitLine, joinPreviousLine } from './lines.js';
22
+ import { moveVertical } from './vertical-navigation.js';
23
+ import { renderedCaretGeometry } from './dom/caret-geometry.js';
24
+ import { insertIdentityMatrix, insertMatrix, activeGrid, MATRIX_MAX_SIZE, matrixEnvironments, resizeMatrix, setMatrixEnvironment, } from './matrix.js';
25
+ import { MATH_MATRIX_CLIPBOARD_TYPE, parseMatrixFragment, matrixFragment, matrixFromTSV, matrixRangeBetween, resolveMatrixRange, extendMatrixRange, focusMatrixCell, copyMatrixRange, clearMatrixRange, pasteMatrixFragment, transposeMatrix, } from './matrix-range.js';
14
26
  import { createPortal } from 'react-dom';
15
27
  import { acceptSuggestion, findSuggestions, mathStructures } from './suggestions.js';
16
28
  import { useId, useImperativeHandle, useLayoutEffect, useRef, useState, } from 'react';
17
29
  import { gridDeletionTarget, removeGrid, row, documentRows, isLiteralText, isGrid, commit, createHistory, initialState, insertStructure, moveCaret, redo, setText, textNodes, toLatex, undo, unwrapPrevious, } from './model.js';
18
30
  const structures = mathStructures;
19
31
  /** Native text fields own IME and local text selection; the tree owns structural editing. */
20
- export function MathEditor({ apiRef, autoFocus = false, enterBehavior = 'newline', onCommit, onCancel, showPopovers = true, defaultValue, excludedStructures = [], multiline = true, onChange, onExit, label, locale = 'ko', showLineNumbers = true, toolbar = true, toolbarMaxItems = 8, toolbarEnd, showTokenLegend = true, }) {
32
+ export function MathEditor({ preferences: suppliedPreferences, apiRef, autoFocus = false, enterBehavior = 'newline', onCommit, onCancel, showPopovers = true, defaultValue, excludedStructures = [], multiline = true, onChange, onExit, label, locale = 'ko', showLineNumbers = true, toolbar = true, toolbarMaxItems = 8, toolbarEnd, showTokenLegend = true, }) {
21
33
  const t = (key, parameters) => translate(locale, key, parameters);
22
34
  const labels = createEditorLabels(locale);
23
35
  const [history, setHistory] = useState(() => createHistory(initialState(defaultValue)));
24
36
  const historyRef = useRef(history);
25
37
  const suggestionMenu = useRef(null);
26
38
  const selectionMenu = useRef(null);
39
+ const [ownPreferences] = useState(createMathPreferences);
40
+ const preferences = suppliedPreferences ?? ownPreferences;
41
+ const [quickOpen, setQuickOpen] = useState(false);
42
+ const [latexOpen, setLatexOpen] = useState(false);
27
43
  const [symbolsOpen, setSymbolsOpen] = useState(false);
28
44
  const [editing, setEditing] = useState(autoFocus);
29
45
  const [range, setRange] = useState();
46
+ const [matrixRange, setMatrixRange] = useState();
30
47
  const [clipboardMessage, setClipboardMessage] = useState('');
31
48
  const surface = useRef(null);
32
49
  const drag = useRef(undefined);
@@ -61,6 +78,7 @@ export function MathEditor({ apiRef, autoFocus = false, enterBehavior = 'newline
61
78
  const suggestionId = useId();
62
79
  const state = history.present;
63
80
  const matrixContext = activeGrid(state);
81
+ const matrixSelection = matrixRange && resolveMatrixRange(state.document, matrixRange);
64
82
  const active = textNodes(state.document).find((n) => n.id === state.caret.id);
65
83
  const searchCaret = composing ? state.caret.end : state.caret.start;
66
84
  const matches = findSuggestions(active.text, searchCaret, locale);
@@ -73,6 +91,7 @@ export function MathEditor({ apiRef, autoFocus = false, enterBehavior = 'newline
73
91
  !isLiteralText(state.document, state.caret.id) &&
74
92
  (composing || state.caret.start === state.caret.end) &&
75
93
  !range &&
94
+ !matrixRange &&
76
95
  focused &&
77
96
  (composing || state.caret.start === state.caret.end) &&
78
97
  dismissed !== queryKey
@@ -85,6 +104,7 @@ export function MathEditor({ apiRef, autoFocus = false, enterBehavior = 'newline
85
104
  if (changed) {
86
105
  setSelectedGrid(undefined);
87
106
  setRange(undefined);
107
+ setMatrixRange(undefined);
88
108
  }
89
109
  if (focus)
90
110
  setEditing(true);
@@ -98,7 +118,30 @@ export function MathEditor({ apiRef, autoFocus = false, enterBehavior = 'newline
98
118
  setSelectedGrid(undefined);
99
119
  publish(commit(historyRef.current, next), true);
100
120
  };
121
+ const pasteLatex = (source) => {
122
+ if (composing || matrixRange)
123
+ return {
124
+ ok: false,
125
+ source,
126
+ diagnostics: [
127
+ {
128
+ code: 'unsupported-structure',
129
+ message: 'Finish composition or select one insertion point.',
130
+ start: 0,
131
+ end: source.length,
132
+ },
133
+ ],
134
+ };
135
+ const result = insertLatex(historyRef.current.present, source, range, {
136
+ multiline,
137
+ excludedStructures,
138
+ });
139
+ if (result.ok)
140
+ apply(result.state);
141
+ return result;
142
+ };
101
143
  useImperativeHandle(apiRef, () => ({
144
+ pasteLatex,
102
145
  importLatex(source) {
103
146
  const result = parseLatex(source, { multiline, excludedStructures });
104
147
  if (!result.ok)
@@ -167,10 +210,14 @@ export function MathEditor({ apiRef, autoFocus = false, enterBehavior = 'newline
167
210
  if (suggestionMenu.current)
168
211
  positionMathMenu(suggestionMenu.current, new DOMRect(x, rect.top, 0, rect.height), 340);
169
212
  };
213
+ const stopTheme = surface.current && suggestionMenu.current
214
+ ? followMathTheme(surface.current.closest('.me-editor'), suggestionMenu.current)
215
+ : undefined;
170
216
  position();
171
217
  window.addEventListener('resize', position);
172
218
  window.addEventListener('scroll', position, true);
173
219
  return () => {
220
+ stopTheme?.();
174
221
  window.removeEventListener('resize', position);
175
222
  window.removeEventListener('scroll', position, true);
176
223
  };
@@ -195,6 +242,7 @@ export function MathEditor({ apiRef, autoFocus = false, enterBehavior = 'newline
195
242
  if (!candidate)
196
243
  return;
197
244
  apply(acceptSuggestion(historyRef.current.present, query, candidate));
245
+ preferences.record(candidate.id);
198
246
  setCandidateIndex(0);
199
247
  setDismissed(`${active.id}:${state.caret.start}:${query}`);
200
248
  };
@@ -257,6 +305,7 @@ export function MathEditor({ apiRef, autoFocus = false, enterBehavior = 'newline
257
305
  };
258
306
  };
259
307
  const activate = (point) => {
308
+ setMatrixRange(undefined);
260
309
  setRange(undefined);
261
310
  setFocused(true);
262
311
  setSelectedGrid(undefined);
@@ -273,6 +322,19 @@ export function MathEditor({ apiRef, autoFocus = false, enterBehavior = 'newline
273
322
  },
274
323
  }, true);
275
324
  };
325
+ const selectCells = (selection) => {
326
+ if (!resolveMatrixRange(historyRef.current.present.document, selection))
327
+ return;
328
+ setMatrixRange(selection);
329
+ setRange(undefined);
330
+ setEditing(false);
331
+ setSymbolsOpen(false);
332
+ publish({
333
+ ...historyRef.current,
334
+ present: focusMatrixCell(historyRef.current.present, selection.matrixId, selection.focus),
335
+ });
336
+ surface.current?.focus({ preventScroll: true });
337
+ };
276
338
  // Promote a pointer drag to a model range, including a drag that starts in the active input.
277
339
  const beginPointer = (event) => {
278
340
  if (event.button !== 0 ||
@@ -282,6 +344,17 @@ export function MathEditor({ apiRef, autoFocus = false, enterBehavior = 'newline
282
344
  const point = pointAt(event.clientX, event.clientY);
283
345
  if (!point)
284
346
  return;
347
+ if (event.shiftKey) {
348
+ const current = historyRef.current.present;
349
+ const rectangle = matrixRangeBetween(current.document, matrixRange
350
+ ? focusMatrixCell(current, matrixRange.matrixId, matrixRange.anchor).caret.id
351
+ : current.caret.id, point.id);
352
+ if (rectangle) {
353
+ event.preventDefault();
354
+ selectCells(rectangle);
355
+ return;
356
+ }
357
+ }
285
358
  const input = event.target instanceof HTMLInputElement;
286
359
  drag.current = { anchor: point, x: event.clientX, y: event.clientY, moving: false, input };
287
360
  if (!input) {
@@ -308,10 +381,20 @@ export function MathEditor({ apiRef, autoFocus = false, enterBehavior = 'newline
308
381
  event.preventDefault();
309
382
  current.moving = true;
310
383
  setEditing(false);
311
- setRange({ anchor: current.anchor, focus: point });
384
+ const rectangle = current.matrixRange ??
385
+ matrixRangeBetween(historyRef.current.present.document, current.anchor.id, point.id);
386
+ const bounds = rectangle && resolveMatrixRange(historyRef.current.present.document, rectangle);
387
+ if (rectangle && bounds) {
388
+ current.matrixRange = matrixPointerRange(event.currentTarget, rectangle, bounds.matrix.columns, event.clientX, event.clientY);
389
+ selectCells(current.matrixRange);
390
+ }
391
+ else {
392
+ setMatrixRange(undefined);
393
+ setRange({ anchor: current.anchor, focus: point });
394
+ }
312
395
  setSelectedGrid(undefined);
313
396
  event.currentTarget.setPointerCapture(event.pointerId);
314
- event.currentTarget.focus();
397
+ event.currentTarget.focus({ preventScroll: true });
315
398
  };
316
399
  const endPointer = (event) => {
317
400
  const current = drag.current;
@@ -345,17 +428,24 @@ export function MathEditor({ apiRef, autoFocus = false, enterBehavior = 'newline
345
428
  };
346
429
  // Structured clipboard data preserves editable math; plain LaTeX is the interoperability fallback.
347
430
  const copySelection = (event, cut = false) => {
348
- if (!range || compositionStart.current)
431
+ if (compositionStart.current || (!range && !matrixRange))
349
432
  return;
350
- const fragment = copyRange(historyRef.current.present.document, range);
433
+ const cells = matrixRange && copyMatrixRange(historyRef.current.present.document, matrixRange);
434
+ const fragment = cells
435
+ ? matrixFragment(cells)
436
+ : copyRange(historyRef.current.present.document, range);
351
437
  if (!fragment)
352
438
  return;
353
439
  event.preventDefault();
354
440
  event.stopPropagation();
441
+ if (cells)
442
+ event.clipboardData.setData(MATH_MATRIX_CLIPBOARD_TYPE, JSON.stringify(cells));
355
443
  event.clipboardData.setData(MATH_CLIPBOARD_TYPE, JSON.stringify(fragment));
356
444
  event.clipboardData.setData('text/plain', toLatex(fragmentLatex(fragment)));
357
445
  if (cut)
358
- apply(deleteRange(historyRef.current.present, range));
446
+ apply(matrixRange
447
+ ? clearMatrixRange(historyRef.current.present, matrixRange)
448
+ : deleteRange(historyRef.current.present, range));
359
449
  setClipboardMessage(cut ? 'clipboard.cut' : 'clipboard.copied');
360
450
  };
361
451
  const pasteSelection = (event) => {
@@ -364,6 +454,40 @@ export function MathEditor({ apiRef, autoFocus = false, enterBehavior = 'newline
364
454
  const source = event.clipboardData.getData(MATH_CLIPBOARD_TYPE);
365
455
  const fragment = source ? parseFragment(source) : undefined;
366
456
  const text = event.clipboardData.getData('text/plain');
457
+ const matrixSource = event.clipboardData.getData(MATH_MATRIX_CLIPBOARD_TYPE);
458
+ const cells = matrixSource ? parseMatrixFragment(matrixSource) : matrixFromTSV(text);
459
+ const current = historyRef.current.present;
460
+ const inMatrix = !!matrixRange || activeGrid(current)?.matrix.type === 'matrix';
461
+ if (matrixSource || (inMatrix && text.includes('\t'))) {
462
+ event.preventDefault();
463
+ event.stopPropagation();
464
+ if (!cells) {
465
+ setClipboardMessage('matrix.pasteRejected');
466
+ return;
467
+ }
468
+ const next = inMatrix
469
+ ? pasteMatrixFragment(current, cells, matrixRange)
470
+ : pasteFragment(current, matrixFragment(cells), range);
471
+ if (next === current)
472
+ setClipboardMessage('matrix.pasteRejected');
473
+ else {
474
+ apply(next);
475
+ setClipboardMessage('clipboard.pasted');
476
+ }
477
+ return;
478
+ }
479
+ if (matrixRange && !fragment && !text.includes('\n') && !text.includes('\r')) {
480
+ event.preventDefault();
481
+ event.stopPropagation();
482
+ apply(clearMatrixRange(current, matrixRange, text));
483
+ return;
484
+ }
485
+ if (matrixRange) {
486
+ event.preventDefault();
487
+ event.stopPropagation();
488
+ setClipboardMessage('matrix.pasteRejected');
489
+ return;
490
+ }
367
491
  if (!fragment && !text)
368
492
  return;
369
493
  event.preventDefault();
@@ -383,6 +507,43 @@ export function MathEditor({ apiRef, autoFocus = false, enterBehavior = 'newline
383
507
  apply(next);
384
508
  setClipboardMessage('clipboard.pasted');
385
509
  };
510
+ const matrixSelectionKey = (event) => {
511
+ if (!matrixRange || compositionStart.current || event.nativeEvent.isComposing)
512
+ return false;
513
+ const current = historyRef.current.present;
514
+ if ((event.metaKey || event.ctrlKey) && event.key.toLowerCase() === 'a') {
515
+ event.preventDefault();
516
+ event.stopPropagation();
517
+ const matrix = resolveMatrixRange(current.document, matrixRange)?.matrix;
518
+ if (matrix)
519
+ selectCells({ matrixId: matrix.id, anchor: 0, focus: matrix.slots.length - 1 });
520
+ return true;
521
+ }
522
+ if (event.metaKey || event.ctrlKey || event.altKey)
523
+ return false;
524
+ const arrow = ['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown'].includes(event.key);
525
+ if (arrow || ['Escape', 'Enter', 'F2'].includes(event.key)) {
526
+ event.preventDefault();
527
+ event.stopPropagation();
528
+ const next = arrow
529
+ ? extendMatrixRange(current.document, matrixRange, event.key)
530
+ : matrixRange;
531
+ if (arrow && event.shiftKey)
532
+ selectCells(next);
533
+ else {
534
+ const caret = focusMatrixCell(current, next.matrixId, next.focus).caret;
535
+ activate({ id: caret.id, offset: caret.start });
536
+ }
537
+ return true;
538
+ }
539
+ if (['Delete', 'Backspace'].includes(event.key) || Array.from(event.key).length === 1) {
540
+ event.preventDefault();
541
+ event.stopPropagation();
542
+ apply(clearMatrixRange(current, matrixRange, ['Delete', 'Backspace'].includes(event.key) ? '' : event.key));
543
+ return true;
544
+ }
545
+ return false;
546
+ };
386
547
  const keyboardSelect = (event) => {
387
548
  if (!event.shiftKey ||
388
549
  event.altKey ||
@@ -399,7 +560,7 @@ export function MathEditor({ apiRef, autoFocus = false, enterBehavior = 'newline
399
560
  const selectionKey = (event) => {
400
561
  if (event.target instanceof HTMLInputElement || compositionStart.current)
401
562
  return;
402
- if (keyboardSelect(event))
563
+ if (matrixSelectionKey(event) || keyboardSelect(event))
403
564
  return;
404
565
  const current = historyRef.current.present, nodes = textNodes(current.document);
405
566
  if ((event.metaKey || event.ctrlKey) && event.key.toLowerCase() === 'a') {
@@ -415,9 +576,17 @@ export function MathEditor({ apiRef, autoFocus = false, enterBehavior = 'newline
415
576
  publish((event.shiftKey ? redo : undo)(historyRef.current), false);
416
577
  return;
417
578
  }
418
- if (event.metaKey || event.ctrlKey || event.altKey)
579
+ if (event.metaKey || event.ctrlKey)
580
+ return;
581
+ const point = !event.altKey && collapseKeyboardRange(current.document, range, event.key);
582
+ if (point) {
583
+ event.preventDefault();
584
+ activate(point);
419
585
  return;
420
- if (range && selectionChoices.length && ['ArrowDown', 'ArrowUp', 'Enter'].includes(event.key)) {
586
+ }
587
+ if (range &&
588
+ selectionChoices.length &&
589
+ (event.key === 'Enter' || (event.altKey && ['ArrowDown', 'ArrowUp'].includes(event.key)))) {
421
590
  event.preventDefault();
422
591
  if (event.key === 'Enter') {
423
592
  if (canWrap)
@@ -428,6 +597,8 @@ export function MathEditor({ apiRef, autoFocus = false, enterBehavior = 'newline
428
597
  selectionChoices.length);
429
598
  return;
430
599
  }
600
+ if (event.altKey)
601
+ return;
431
602
  // A model selection must behave like a text selection when typing resumes.
432
603
  if (range && !event.nativeEvent.isComposing && Array.from(event.key).length === 1) {
433
604
  event.preventDefault();
@@ -441,6 +612,7 @@ export function MathEditor({ apiRef, autoFocus = false, enterBehavior = 'newline
441
612
  }
442
613
  if (event.key === 'Escape') {
443
614
  setRange(undefined);
615
+ setMatrixRange(undefined);
444
616
  return;
445
617
  }
446
618
  if (event.key === 'Enter' || event.key === 'F2') {
@@ -448,13 +620,15 @@ export function MathEditor({ apiRef, autoFocus = false, enterBehavior = 'newline
448
620
  activate(range?.focus ?? { id: current.caret.id, offset: current.caret.start });
449
621
  }
450
622
  };
451
- const selectedRange = range ??
452
- (state.caret.start !== state.caret.end
453
- ? {
454
- anchor: { id: state.caret.id, offset: state.caret.start },
455
- focus: { id: state.caret.id, offset: state.caret.end },
456
- }
457
- : undefined);
623
+ const selectedRange = matrixRange
624
+ ? undefined
625
+ : range ??
626
+ (state.caret.start !== state.caret.end
627
+ ? {
628
+ anchor: { id: state.caret.id, offset: state.caret.start },
629
+ focus: { id: state.caret.id, offset: state.caret.end },
630
+ }
631
+ : undefined);
458
632
  const selectionFragment = selectedRange ? copyRange(state.document, selectedRange) : undefined;
459
633
  const canWrap = selectionFragment?.rows.length === 1 &&
460
634
  !isLiteralText(state.document, selectedRange.anchor.id);
@@ -504,11 +678,15 @@ export function MathEditor({ apiRef, autoFocus = false, enterBehavior = 'newline
504
678
  if (rect && selectionMenu.current)
505
679
  positionMathMenu(selectionMenu.current, rect, 340);
506
680
  };
681
+ const stopTheme = surface.current && selectionMenu.current
682
+ ? followMathTheme(surface.current.closest('.me-editor'), selectionMenu.current)
683
+ : undefined;
507
684
  position();
508
685
  window.addEventListener('scroll', position, true);
509
686
  window.addEventListener('resize', position);
510
687
  return () => {
511
688
  window.removeEventListener('scroll', position, true);
689
+ stopTheme?.();
512
690
  window.removeEventListener('resize', position);
513
691
  };
514
692
  }, [range, state.document, state.caret, showPopovers]);
@@ -524,7 +702,7 @@ export function MathEditor({ apiRef, autoFocus = false, enterBehavior = 'newline
524
702
  list.scrollTop += item.bottom - box.bottom;
525
703
  }, [selectionIndex]);
526
704
  const insertTool = (kind) => {
527
- if (excludedStructures.includes(kind))
705
+ if (excludedStructures.includes(kind) || matrixRange)
528
706
  return;
529
707
  const current = historyRef.current.present;
530
708
  const selection = range ??
@@ -545,11 +723,13 @@ export function MathEditor({ apiRef, autoFocus = false, enterBehavior = 'newline
545
723
  // Nested slots share the same caret model. Only the active lexical token mounts an input.
546
724
  const renderRow = (r, name, role = 'expression') => (_jsx("span", { className: "me-row", "data-math-role": role, children: r.children.map((node) => {
547
725
  if (isGrid(node))
548
- return (_jsxs("span", { className: "me-matrix", "data-selected": selectedGrid === node.id || undefined, "data-structure": node.type, "data-environment": node.type === 'matrix'
726
+ return (_jsxs("span", { className: "me-matrix", "data-selected": selectedGrid === node.id || undefined, "data-structure": node.type, "data-matrix-id": node.id, "data-environment": node.type === 'matrix'
549
727
  ? node.environment
550
728
  : node.type === 'cases'
551
729
  ? 'Bmatrix'
552
- : 'matrix', children: [_jsx("span", { className: "me-matrix-delimiter me-matrix-left", "aria-hidden": "true" }), _jsx("span", { className: "me-matrix-grid", style: { gridTemplateColumns: `repeat(${node.columns}, max-content)` }, children: node.slots.map((cell, index) => (_jsx("span", { className: "me-matrix-cell", children: renderRow(cell, labels.grid(name, node.type, index, node.columns), 'group') }, cell.id))) }), _jsx("span", { className: "me-matrix-delimiter me-matrix-right", "aria-hidden": "true" })] }, node.id));
730
+ : 'matrix', children: [_jsx("span", { className: "me-matrix-delimiter me-matrix-left", "aria-hidden": "true" }), _jsx("span", { className: "me-matrix-grid", style: { gridTemplateColumns: `repeat(${node.columns}, max-content)` }, children: node.slots.map((cell, index) => (_jsx("span", { className: "me-matrix-cell", "data-cell-index": index, "data-cell-selected": (matrixSelection?.matrix.id === node.id &&
731
+ matrixSelection.indices.includes(index)) ||
732
+ undefined, children: renderRow(cell, labels.grid(name, node.type, index, node.columns), 'group') }, cell.id))) }), _jsx("span", { className: "me-matrix-delimiter me-matrix-right", "aria-hidden": "true" })] }, node.id));
553
733
  if (node.type === 'limit' || node.type === 'limsup' || node.type === 'liminf')
554
734
  return (_jsxs("span", { className: "me-structure me-limit-operator", "data-structure": node.type, "data-math-style": node.mathStyle, "data-limit-placement": node.limits === false ? 'nolimits' : node.limits ? 'limits' : 'auto', children: [_jsxs("span", { className: "me-limits", children: [_jsx("span", { className: "me-limit-glyph", "aria-hidden": "true", children: node.type === 'limit' ? 'lim' : node.type === 'limsup' ? 'lim sup' : 'lim inf' }), _jsx("span", { className: "me-limit me-slot", children: renderRow(node.slots[0], labels.slot(name, node.type, 0), 'lower') })] }), _jsx("span", { className: "me-slot", children: renderRow(node.slots[1], labels.slot(name, node.type, 1)) })] }, node.id));
555
735
  if (node.type !== 'text' &&
@@ -591,6 +771,7 @@ export function MathEditor({ apiRef, autoFocus = false, enterBehavior = 'newline
591
771
  const selected = selectedText(node.id, token.start, token.end);
592
772
  const isActive = editing &&
593
773
  !range &&
774
+ !matrixRange &&
594
775
  state.caret.id === node.id &&
595
776
  tokenIndexAt(parts, state.caret.start, state.caret.affinity) === tokenIndex;
596
777
  const caretFrom = (input) => ({
@@ -651,7 +832,7 @@ export function MathEditor({ apiRef, autoFocus = false, enterBehavior = 'newline
651
832
  compositionStart.current ||
652
833
  event.keyCode === 229)
653
834
  return;
654
- if (keyboardSelect(event))
835
+ if (matrixSelectionKey(event) || keyboardSelect(event))
655
836
  return;
656
837
  const current = historyRef.current.present;
657
838
  if (selectedGrid) {
@@ -773,21 +954,10 @@ export function MathEditor({ apiRef, autoFocus = false, enterBehavior = 'newline
773
954
  }
774
955
  return;
775
956
  }
776
- if (!event.shiftKey &&
777
- current.caret.start === current.caret.end &&
778
- activeGrid(current) &&
779
- ['ArrowUp', 'ArrowDown'].includes(event.key)) {
780
- event.preventDefault();
781
- publish({
782
- ...historyRef.current,
783
- present: moveMatrixVertical(current, event.key === 'ArrowUp' ? -1 : 1),
784
- }, true);
785
- return;
786
- }
787
957
  if (!event.shiftKey &&
788
958
  current.caret.start === current.caret.end &&
789
959
  ['ArrowUp', 'ArrowDown'].includes(event.key)) {
790
- const next = moveLineVertical(current, event.key === 'ArrowUp' ? -1 : 1);
960
+ const next = moveVertical(current, event.key === 'ArrowUp' ? -1 : 1, surface.current ? renderedCaretGeometry(surface.current) : undefined);
791
961
  if (next !== current) {
792
962
  event.preventDefault();
793
963
  publish({ ...historyRef.current, present: next }, true);
@@ -836,7 +1006,19 @@ export function MathEditor({ apiRef, autoFocus = false, enterBehavior = 'newline
836
1006
  } })) : (_jsx("span", { className: "me-preview-token", "data-token-kind": token.kind, "aria-label": name, role: "button", tabIndex: -1, children: selected && token.text ? (_jsxs("span", { children: [token.text.slice(0, selected[0]), _jsx("mark", { className: "me-range-highlight", children: token.text.slice(selected[0], selected[1]) }), token.text.slice(selected[1])] })) : (token.text || (r.children.length === 1 ? '□' : '\u200b')) }))] }, key));
837
1007
  });
838
1008
  }) }, r.id));
839
- return (_jsxs("div", { className: "me-editor", "data-math-editor-owner": suggestionId, onCopy: copySelection, onCut: (event) => copySelection(event, true), onPaste: pasteSelection, role: "group", lang: locale, dir: mathLocaleDirection(locale), "aria-label": label ?? t('editor.label'), onBlur: (event) => {
1009
+ return (_jsxs("div", { className: "me-editor", "data-math-editor-owner": suggestionId, onKeyDownCapture: (event) => {
1010
+ if (!event.nativeEvent.isComposing &&
1011
+ !composing &&
1012
+ event.altKey &&
1013
+ event.shiftKey &&
1014
+ event.code === 'KeyV') {
1015
+ event.preventDefault();
1016
+ event.stopPropagation();
1017
+ setQuickOpen(false);
1018
+ setSymbolsOpen(false);
1019
+ setLatexOpen(true);
1020
+ }
1021
+ }, onCopy: copySelection, onCut: (event) => copySelection(event, true), onPaste: pasteSelection, role: "group", lang: locale, dir: mathLocaleDirection(locale), "aria-label": label ?? t('editor.label'), onBlur: (event) => {
840
1022
  if (!event.currentTarget.contains(event.relatedTarget) &&
841
1023
  !suggestionMenu.current?.contains(event.relatedTarget) &&
842
1024
  !selectionMenu.current?.contains(event.relatedTarget) &&
@@ -846,19 +1028,74 @@ export function MathEditor({ apiRef, autoFocus = false, enterBehavior = 'newline
846
1028
  setFocused(false);
847
1029
  setEditing(false);
848
1030
  }
849
- }, children: [toolbar && (_jsx(MathEditorToolbar, { locale: locale, kinds: Array.isArray(toolbar) ? toolbar : undefined, maxItems: toolbarMaxItems, excludedStructures: excludedStructures, composing: composing, hasRange: !!range, canWrap: canWrap, canUndo: !!history.past.length, canRedo: !!history.future.length, symbolsOpen: symbolsOpen, onInsertStructure: insertTool, onMatrixPreset: (value) => apply(value.startsWith('identity-')
1031
+ }, children: [toolbar && (_jsx(MathEditorToolbar, { locale: locale, kinds: Array.isArray(toolbar) ? toolbar : undefined, maxItems: toolbarMaxItems, excludedStructures: excludedStructures, composing: composing, hasRange: !!range || !!matrixRange, cellRange: !!matrixRange, canWrap: canWrap, canUndo: !!history.past.length, canRedo: !!history.future.length, symbolsOpen: symbolsOpen, onQuick: () => {
1032
+ setSymbolsOpen(false);
1033
+ setLatexOpen(false);
1034
+ setQuickOpen(true);
1035
+ }, onPasteLatex: () => {
1036
+ setQuickOpen(false);
1037
+ setSymbolsOpen(false);
1038
+ setLatexOpen(true);
1039
+ }, onInsertStructure: insertTool, onMatrixPreset: (value) => apply(value.startsWith('identity-')
850
1040
  ? insertIdentityMatrix(historyRef.current.present, Number(value.slice(9)))
851
- : insertMatrix(historyRef.current.present, Number(value))), onTemplate: (id) => apply(insertTemplate(historyRef.current.present, id, range)), onToggleSymbols: () => setSymbolsOpen((value) => !value), onInsertSymbol: (glyph) => {
1041
+ : insertMatrix(historyRef.current.present, Number(value))), onTemplate: (id) => {
1042
+ apply(insertTemplate(historyRef.current.present, id, range));
1043
+ preferences.record(`template-${id}`);
1044
+ }, onToggleSymbols: () => {
1045
+ setQuickOpen(false);
1046
+ setLatexOpen(false);
1047
+ setSymbolsOpen((value) => !value);
1048
+ }, onInsertSymbol: (glyph) => {
1049
+ preferences.record(`symbol-${glyph}`);
852
1050
  const current = historyRef.current.present, caret = current.caret;
853
1051
  const value = textNodes(current.document).find((node) => node.id === caret.id).text;
854
1052
  apply(setText(current, value.slice(0, caret.start) + glyph + value.slice(caret.end), caret.start + glyph.length));
855
- }, onUndo: () => publish(undo(historyRef.current), true), onRedo: () => publish(redo(historyRef.current), true), children: toolbarEnd })), toolbar && symbolsOpen && (_jsx(SymbolBrowser, { locale: locale, onClose: () => {
1053
+ }, onUndo: () => publish(undo(historyRef.current), true), onRedo: () => publish(redo(historyRef.current), true), children: toolbarEnd })), toolbar && (_jsx(PresentationControls, { state: state, locale: locale, disabled: composing || !!range || !!matrixRange, kinds: mathStructures
1054
+ .filter((item) => !excludedStructures.includes(item.kind) &&
1055
+ (!Array.isArray(toolbar) || toolbar.includes(item.kind)))
1056
+ .map((item) => item.kind), onChange: (id, change) => apply(setMathPresentation(historyRef.current.present, id, change)) })), quickOpen && (_jsx(QuickPanel, { locale: locale, preferences: preferences, allowedTemplates: toolbarTemplates(mathStructures
1057
+ .filter((item) => !excludedStructures.includes(item.kind) &&
1058
+ (!Array.isArray(toolbar) || toolbar.includes(item.kind)))
1059
+ .map((item) => item.kind)).map((item) => item.id), onInsert: (item) => {
1060
+ if (composing || matrixRange)
1061
+ return false;
1062
+ const current = historyRef.current.present;
1063
+ const next = item.template
1064
+ ? insertTemplate(current, item.template, range)
1065
+ : pasteFragment(current, { version: 1, rows: [row(item.glyph)] }, range);
1066
+ if (next === current)
1067
+ return false;
1068
+ apply(next);
1069
+ return true;
1070
+ }, onClose: () => {
1071
+ setQuickOpen(false);
1072
+ publish({ ...historyRef.current }, true);
1073
+ } })), latexOpen && (_jsx(LatexPastePanel, { locale: locale, onInsert: pasteLatex, onClose: () => {
1074
+ setLatexOpen(false);
1075
+ focusNext.current = true;
1076
+ setEditing(true);
1077
+ publish({ ...historyRef.current }, true);
1078
+ } })), toolbar && symbolsOpen && (_jsx(SymbolBrowser, { locale: locale, onClose: () => {
856
1079
  setSymbolsOpen(false);
857
1080
  surface.current?.focus();
858
1081
  }, onInsert: (glyph) => {
1082
+ preferences.record(`symbol-${glyph}`);
859
1083
  apply(pasteFragment(historyRef.current.present, { version: 1, rows: [row(glyph)] }, range));
860
1084
  setSymbolsOpen(false);
861
- } })), showTokenLegend && (_jsxs("div", { className: "me-token-legend", "aria-label": t('token.legend'), children: [_jsx("span", { "data-kind": "variable", children: t('token.variable') }), _jsx("span", { "data-kind": "constant", children: t('token.constant') }), _jsx("span", { "data-kind": "symbol", children: t('token.symbol') }), _jsx("span", { "data-kind": "function", children: t('token.function') }), _jsx("small", { children: t('editor.interactionHint') })] })), clipboardMessage && (_jsx("div", { className: "me-grid-selection-hint", role: "status", children: t(clipboardMessage) })), selectedGrid && (_jsx("div", { className: "me-grid-selection-hint", role: "status", children: t('grid.selectionHint') })), toolbar && matrixContext && (_jsxs("div", { className: "me-matrix-tools", role: "toolbar", "aria-label": t(matrixContext.matrix.type === 'matrix' ? 'matrix.edit' : 'grid.editRows'), children: [_jsxs("span", { children: [matrixContext.rows, " \u00D7 ", matrixContext.matrix.columns, ' ', _jsxs("small", { children: ["\u00B7", ' ', t('grid.position', { row: matrixContext.row + 1, column: matrixContext.column + 1 })] })] }), matrixContext.matrix.type === 'matrix' && (_jsx("select", { "aria-label": t('matrix.delimiters'), value: matrixContext.matrix.environment, disabled: composing, onChange: (event) => apply(setMatrixEnvironment(historyRef.current.present, event.target.value)), children: matrixEnvironments.map((item) => (_jsx("option", { value: item.value, children: t(item.label) }, item.value))) })), ['row', 'column']
1085
+ } })), showTokenLegend && (_jsxs("div", { className: "me-token-legend", "aria-label": t('token.legend'), children: [_jsx("span", { "data-kind": "variable", children: t('token.variable') }), _jsx("span", { "data-kind": "constant", children: t('token.constant') }), _jsx("span", { "data-kind": "symbol", children: t('token.symbol') }), _jsx("span", { "data-kind": "function", children: t('token.function') }), _jsx("small", { children: t('editor.interactionHint') })] })), clipboardMessage && (_jsx("div", { className: "me-grid-selection-hint", role: "status", children: t(clipboardMessage) })), selectedGrid && (_jsx("div", { className: "me-grid-selection-hint", role: "status", children: t('grid.selectionHint') })), toolbar && matrixContext && (_jsxs("div", { className: "me-matrix-tools", role: "toolbar", "aria-label": t(matrixContext.matrix.type === 'matrix' ? 'matrix.edit' : 'grid.editRows'), children: [_jsxs("span", { children: [matrixContext.rows, " \u00D7 ", matrixContext.matrix.columns, ' ', _jsxs("small", { children: ["\u00B7", ' ', t('grid.position', { row: matrixContext.row + 1, column: matrixContext.column + 1 })] })] }), matrixContext.matrix.type === 'matrix' && (_jsx("select", { "aria-label": t('matrix.delimiters'), value: matrixContext.matrix.environment, disabled: composing || !!matrixRange || !!range, onChange: (event) => apply(setMatrixEnvironment(historyRef.current.present, event.target.value)), children: matrixEnvironments.map((item) => (_jsx("option", { value: item.value, children: t(item.label) }, item.value))) })), matrixContext.matrix.type === 'matrix' && (_jsxs(_Fragment, { children: [_jsx("button", { type: "button", disabled: composing || !!range, onMouseDown: (event) => event.preventDefault(), onClick: () => selectCells({
1086
+ matrixId: matrixContext.matrix.id,
1087
+ anchor: matrixContext.cell,
1088
+ focus: matrixContext.cell,
1089
+ }), children: t('matrix.selectCells') }), _jsx("button", { type: "button", disabled: composing || !!range, onMouseDown: (event) => event.preventDefault(), onClick: () => selectCells({
1090
+ matrixId: matrixContext.matrix.id,
1091
+ anchor: 0,
1092
+ focus: matrixContext.matrix.slots.length - 1,
1093
+ }), children: t('matrix.selectAll') }), _jsx("button", { type: "button", disabled: composing || !!range, onMouseDown: (event) => event.preventDefault(), onClick: () => {
1094
+ const current = historyRef.current.present;
1095
+ const next = transposeMatrix(current, matrixRange?.matrixId);
1096
+ if (next !== current)
1097
+ apply(next);
1098
+ }, children: t('matrix.transpose') })] })), ['row', 'column']
862
1099
  .filter((axis) => axis === 'row' || matrixContext.matrix.type === 'matrix')
863
1100
  .flatMap((axis) => ['insert', 'delete'].map((action) => {
864
1101
  const size = axis === 'row' ? matrixContext.rows : matrixContext.matrix.columns;
@@ -868,7 +1105,10 @@ export function MathEditor({ apiRef, autoFocus = false, enterBehavior = 'newline
868
1105
  ? axis === 'row'
869
1106
  ? 'Alt+Shift+ArrowUp'
870
1107
  : 'Alt+Shift+ArrowLeft'
871
- : undefined, disabled: composing || (action === 'delete' ? size === 1 : size >= MATRIX_MAX_SIZE), onMouseDown: (event) => event.preventDefault(), onClick: () => apply(resizeMatrix(historyRef.current.present, axis, action)), children: t(axis === 'row'
1108
+ : undefined, disabled: composing ||
1109
+ !!matrixRange ||
1110
+ !!range ||
1111
+ (action === 'delete' ? size === 1 : size >= MATRIX_MAX_SIZE), onMouseDown: (event) => event.preventDefault(), onClick: () => apply(resizeMatrix(historyRef.current.present, axis, action)), children: t(axis === 'row'
872
1112
  ? action === 'insert'
873
1113
  ? 'grid.addRow'
874
1114
  : 'grid.deleteRow'
@@ -879,10 +1119,9 @@ export function MathEditor({ apiRef, autoFocus = false, enterBehavior = 'newline
879
1119
  ? t('matrix.keyboardHint')
880
1120
  : `${t(matrixContext.matrix.type === 'aligned' ? 'aligned.inputHint' : 'cases.inputHint')} · ${t('grid.keyboardHint')}` })] })), showPopovers &&
881
1121
  candidates.length > 0 &&
882
- createPortal(_jsxs("div", { className: "me-suggestion-panel", "data-math-editor-owner": suggestionId, lang: locale, dir: mathLocaleDirection(locale), ref: suggestionMenu, onMouseDown: (event) => event.preventDefault(), children: [_jsxs("div", { className: "me-suggestion-heading", children: [t('suggestion.create', { query }), ' ', _jsx("span", { children: t(composing ? 'suggestion.composing' : 'suggestion.keyboardHint') })] }), _jsx("div", { className: "me-suggestions", id: suggestionId, role: "listbox", "aria-label": t('suggestion.label'), children: candidates.map((c, index) => (_jsxs("button", { type: "button", id: `${suggestionId}-${index}`, role: "option", disabled: composing, "aria-selected": !composing && index === selectedIndex, onClick: () => choose(index), children: [_jsx("span", { className: "me-candidate-glyph", children: c.glyph }), _jsxs("span", { children: [_jsx("strong", { children: c.label }), _jsx("small", { children: c.detail })] })] }, c.id))) }), _jsx("div", { className: "me-suggestion-footer", children: t(composing ? 'suggestion.imeHint' : 'suggestion.keepSource') })] }), surface.current?.closest('dialog, [role="dialog"]') ?? document.body), _jsx("div", { className: "me-surface", dir: "ltr", ref: surface, tabIndex: 0, "aria-label": t('selection.surface'), "data-mode": editing ? 'edit' : 'preview', onPointerDown: beginPointer, onPointerMove: movePointer, onPointerUp: endPointer, onPointerCancel: () => {
1122
+ createPortal(_jsxs("div", { className: "me-suggestion-panel", "data-math-editor-owner": suggestionId, lang: locale, dir: mathLocaleDirection(locale), ref: suggestionMenu, onMouseDown: (event) => event.preventDefault(), children: [_jsxs("div", { className: "me-suggestion-heading", children: [_jsx("span", { className: "me-suggestion-query", children: t('suggestion.create', { query }) }), _jsx("span", { children: t(composing ? 'suggestion.composing' : 'suggestion.keyboardHint') })] }), _jsx("div", { className: "me-suggestions", id: suggestionId, role: "listbox", "aria-label": t('suggestion.label'), children: candidates.map((c, index) => (_jsxs("button", { type: "button", id: `${suggestionId}-${index}`, role: "option", disabled: composing, "aria-selected": !composing && index === selectedIndex, onClick: () => choose(index), children: [_jsx("span", { className: "me-candidate-glyph", children: c.glyph }), _jsxs("span", { className: "me-candidate-copy", children: [_jsx("strong", { children: c.label }), _jsx("small", { children: c.detail })] })] }, c.id))) }), _jsx("div", { className: "me-suggestion-footer", children: t(composing ? 'suggestion.imeHint' : 'suggestion.keepSource') })] }), surface.current?.closest('dialog, [role="dialog"]') ?? document.body), _jsx("div", { className: "me-surface", dir: "ltr", ref: surface, tabIndex: 0, "aria-label": t('selection.surface'), "data-mode": editing ? 'edit' : 'preview', onPointerDown: beginPointer, onPointerMove: movePointer, onPointerUp: endPointer, onPointerCancel: () => {
883
1123
  drag.current = undefined;
884
- }, onKeyDown: selectionKey, children: _jsx("div", { className: "me-document-lines", children: documentRows(state.document).map((line, index) => (_jsxs("div", { className: "me-document-line", children: [showLineNumbers && documentRows(state.document).length > 1 && (_jsx("span", { className: "me-line-number", "aria-hidden": "true", children: index + 1 })), renderRow(line, labels.line(index))] }, line.id))) }) }), showPopovers &&
1124
+ }, onKeyDown: selectionKey, children: _jsx("div", { className: "me-document-lines", children: documentRows(state.document).map((line, index) => (_jsxs("div", { className: "me-document-line", children: [showLineNumbers && documentRows(state.document).length > 1 && (_jsx("span", { className: "me-line-number", "aria-hidden": "true", children: index + 1 })), renderRow(line, labels.line(index))] }, line.id))) }) }), matrixSelection && (_jsx("div", { className: "me-grid-selection-hint", role: "status", children: t('matrix.rangeHint', { rows: matrixSelection.rows, columns: matrixSelection.columns }) })), showPopovers &&
885
1125
  selectionFragment &&
886
- createPortal(_jsxs("div", { className: "me-suggestion-panel", "data-math-editor-owner": suggestionId, ref: selectionMenu, role: "presentation", "aria-label": t('selection.toolbar'), onKeyDown: selectionKey, children: [_jsx("div", { className: "me-suggestion-heading", children: t(canWrap ? 'selection.highlighted' : 'selection.singleRowRequired') }), _jsx("div", { className: "me-suggestions", role: "listbox", "aria-label": t('selection.toolbar'), children: selectionChoices.map((s, index) => (_jsxs("button", { type: "button", role: "option", "aria-selected": index === selectionIndex, disabled: !canWrap, onMouseDown: (event) => event.preventDefault(), onClick: () => insertTool(s.kind), "aria-label": t('selection.wrap', { kind: t(s.label) }), children: [_jsx("span", { className: "me-candidate-glyph", children: s.glyph }), _jsxs("span", { children: [_jsx("strong", { children: t(s.label) }), _jsx("small", { children: t(s.detail) })] })] }, s.kind))) })] }), surface.current?.closest('dialog, [role="dialog"]') ?? document.body)] }));
1126
+ createPortal(_jsxs("div", { className: "me-suggestion-panel", "data-math-editor-owner": suggestionId, ref: selectionMenu, role: "presentation", "aria-label": t('selection.toolbar'), onKeyDown: selectionKey, children: [_jsx("div", { className: "me-suggestion-heading", children: t(canWrap ? 'selection.highlighted' : 'selection.singleRowRequired') }), _jsx("div", { className: "me-suggestions", role: "listbox", "aria-label": t('selection.toolbar'), children: selectionChoices.map((s, index) => (_jsxs("button", { type: "button", role: "option", "aria-selected": index === selectionIndex, disabled: !canWrap, onMouseDown: (event) => event.preventDefault(), onClick: () => insertTool(s.kind), "aria-label": t('selection.wrap', { kind: t(s.label) }), children: [_jsx("span", { className: "me-candidate-glyph", children: s.glyph }), _jsxs("span", { className: "me-candidate-copy", children: [_jsx("strong", { children: t(s.label) }), _jsx("small", { children: t(s.detail) })] })] }, s.kind))) })] }), surface.current?.closest('dialog, [role="dialog"]') ?? document.body)] }));
887
1127
  }
888
- //# sourceMappingURL=math-editor.js.map