@barocss/math-editor 0.2.0 → 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 +51 -1
  10. package/EMBEDDING.md +4 -0
  11. package/IMPLEMENTATION.md +27 -2
  12. package/JSON-MODEL.md +1 -0
  13. package/LATEX-GUIDE.md +13 -0
  14. package/LATEX-SCOPE.md +2 -2
  15. package/LICENSE +1 -3
  16. package/README.md +150 -36
  17. package/ROADMAP.md +96 -10
  18. package/STYLING.md +157 -0
  19. package/SUPPORT.md +29 -11
  20. package/VALIDATION.md +117 -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 +527 -126
  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 +28 -2
  70. package/dist/locales/en.json +28 -2
  71. package/dist/locales/ko.js +28 -2
  72. package/dist/locales/ko.json +28 -2
  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 +300 -44
  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 +4 -1
  94. package/dist/range.js +57 -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 +103 -13
  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 { 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,9 +507,61 @@ 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
+ };
547
+ const keyboardSelect = (event) => {
548
+ if (!event.shiftKey ||
549
+ event.altKey ||
550
+ event.ctrlKey ||
551
+ event.metaKey ||
552
+ !['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown'].includes(event.key))
553
+ return false;
554
+ event.preventDefault();
555
+ setRange(extendKeyboardRange(historyRef.current.present, range, event.key));
556
+ setEditing(false);
557
+ surface.current?.focus();
558
+ return true;
559
+ };
386
560
  const selectionKey = (event) => {
387
561
  if (event.target instanceof HTMLInputElement || compositionStart.current)
388
562
  return;
563
+ if (matrixSelectionKey(event) || keyboardSelect(event))
564
+ return;
389
565
  const current = historyRef.current.present, nodes = textNodes(current.document);
390
566
  if ((event.metaKey || event.ctrlKey) && event.key.toLowerCase() === 'a') {
391
567
  event.preventDefault();
@@ -400,9 +576,17 @@ export function MathEditor({ apiRef, autoFocus = false, enterBehavior = 'newline
400
576
  publish((event.shiftKey ? redo : undo)(historyRef.current), false);
401
577
  return;
402
578
  }
403
- 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);
404
585
  return;
405
- 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)))) {
406
590
  event.preventDefault();
407
591
  if (event.key === 'Enter') {
408
592
  if (canWrap)
@@ -413,6 +597,8 @@ export function MathEditor({ apiRef, autoFocus = false, enterBehavior = 'newline
413
597
  selectionChoices.length);
414
598
  return;
415
599
  }
600
+ if (event.altKey)
601
+ return;
416
602
  // A model selection must behave like a text selection when typing resumes.
417
603
  if (range && !event.nativeEvent.isComposing && Array.from(event.key).length === 1) {
418
604
  event.preventDefault();
@@ -426,6 +612,7 @@ export function MathEditor({ apiRef, autoFocus = false, enterBehavior = 'newline
426
612
  }
427
613
  if (event.key === 'Escape') {
428
614
  setRange(undefined);
615
+ setMatrixRange(undefined);
429
616
  return;
430
617
  }
431
618
  if (event.key === 'Enter' || event.key === 'F2') {
@@ -433,13 +620,15 @@ export function MathEditor({ apiRef, autoFocus = false, enterBehavior = 'newline
433
620
  activate(range?.focus ?? { id: current.caret.id, offset: current.caret.start });
434
621
  }
435
622
  };
436
- const selectedRange = range ??
437
- (state.caret.start !== state.caret.end
438
- ? {
439
- anchor: { id: state.caret.id, offset: state.caret.start },
440
- focus: { id: state.caret.id, offset: state.caret.end },
441
- }
442
- : 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);
443
632
  const selectionFragment = selectedRange ? copyRange(state.document, selectedRange) : undefined;
444
633
  const canWrap = selectionFragment?.rows.length === 1 &&
445
634
  !isLiteralText(state.document, selectedRange.anchor.id);
@@ -489,11 +678,15 @@ export function MathEditor({ apiRef, autoFocus = false, enterBehavior = 'newline
489
678
  if (rect && selectionMenu.current)
490
679
  positionMathMenu(selectionMenu.current, rect, 340);
491
680
  };
681
+ const stopTheme = surface.current && selectionMenu.current
682
+ ? followMathTheme(surface.current.closest('.me-editor'), selectionMenu.current)
683
+ : undefined;
492
684
  position();
493
685
  window.addEventListener('scroll', position, true);
494
686
  window.addEventListener('resize', position);
495
687
  return () => {
496
688
  window.removeEventListener('scroll', position, true);
689
+ stopTheme?.();
497
690
  window.removeEventListener('resize', position);
498
691
  };
499
692
  }, [range, state.document, state.caret, showPopovers]);
@@ -509,7 +702,7 @@ export function MathEditor({ apiRef, autoFocus = false, enterBehavior = 'newline
509
702
  list.scrollTop += item.bottom - box.bottom;
510
703
  }, [selectionIndex]);
511
704
  const insertTool = (kind) => {
512
- if (excludedStructures.includes(kind))
705
+ if (excludedStructures.includes(kind) || matrixRange)
513
706
  return;
514
707
  const current = historyRef.current.present;
515
708
  const selection = range ??
@@ -530,11 +723,13 @@ export function MathEditor({ apiRef, autoFocus = false, enterBehavior = 'newline
530
723
  // Nested slots share the same caret model. Only the active lexical token mounts an input.
531
724
  const renderRow = (r, name, role = 'expression') => (_jsx("span", { className: "me-row", "data-math-role": role, children: r.children.map((node) => {
532
725
  if (isGrid(node))
533
- 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'
534
727
  ? node.environment
535
728
  : node.type === 'cases'
536
729
  ? 'Bmatrix'
537
- : '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));
538
733
  if (node.type === 'limit' || node.type === 'limsup' || node.type === 'liminf')
539
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));
540
735
  if (node.type !== 'text' &&
@@ -576,6 +771,7 @@ export function MathEditor({ apiRef, autoFocus = false, enterBehavior = 'newline
576
771
  const selected = selectedText(node.id, token.start, token.end);
577
772
  const isActive = editing &&
578
773
  !range &&
774
+ !matrixRange &&
579
775
  state.caret.id === node.id &&
580
776
  tokenIndexAt(parts, state.caret.start, state.caret.affinity) === tokenIndex;
581
777
  const caretFrom = (input) => ({
@@ -636,6 +832,8 @@ export function MathEditor({ apiRef, autoFocus = false, enterBehavior = 'newline
636
832
  compositionStart.current ||
637
833
  event.keyCode === 229)
638
834
  return;
835
+ if (matrixSelectionKey(event) || keyboardSelect(event))
836
+ return;
639
837
  const current = historyRef.current.present;
640
838
  if (selectedGrid) {
641
839
  if (!event.metaKey &&
@@ -756,21 +954,10 @@ export function MathEditor({ apiRef, autoFocus = false, enterBehavior = 'newline
756
954
  }
757
955
  return;
758
956
  }
759
- if (!event.shiftKey &&
760
- current.caret.start === current.caret.end &&
761
- activeGrid(current) &&
762
- ['ArrowUp', 'ArrowDown'].includes(event.key)) {
763
- event.preventDefault();
764
- publish({
765
- ...historyRef.current,
766
- present: moveMatrixVertical(current, event.key === 'ArrowUp' ? -1 : 1),
767
- }, true);
768
- return;
769
- }
770
957
  if (!event.shiftKey &&
771
958
  current.caret.start === current.caret.end &&
772
959
  ['ArrowUp', 'ArrowDown'].includes(event.key)) {
773
- 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);
774
961
  if (next !== current) {
775
962
  event.preventDefault();
776
963
  publish({ ...historyRef.current, present: next }, true);
@@ -819,7 +1006,19 @@ export function MathEditor({ apiRef, autoFocus = false, enterBehavior = 'newline
819
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));
820
1007
  });
821
1008
  }) }, r.id));
822
- 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) => {
823
1022
  if (!event.currentTarget.contains(event.relatedTarget) &&
824
1023
  !suggestionMenu.current?.contains(event.relatedTarget) &&
825
1024
  !selectionMenu.current?.contains(event.relatedTarget) &&
@@ -829,19 +1028,74 @@ export function MathEditor({ apiRef, autoFocus = false, enterBehavior = 'newline
829
1028
  setFocused(false);
830
1029
  setEditing(false);
831
1030
  }
832
- }, 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-')
833
1040
  ? insertIdentityMatrix(historyRef.current.present, Number(value.slice(9)))
834
- : 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}`);
835
1050
  const current = historyRef.current.present, caret = current.caret;
836
1051
  const value = textNodes(current.document).find((node) => node.id === caret.id).text;
837
1052
  apply(setText(current, value.slice(0, caret.start) + glyph + value.slice(caret.end), caret.start + glyph.length));
838
- }, 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: () => {
839
1079
  setSymbolsOpen(false);
840
1080
  surface.current?.focus();
841
1081
  }, onInsert: (glyph) => {
1082
+ preferences.record(`symbol-${glyph}`);
842
1083
  apply(pasteFragment(historyRef.current.present, { version: 1, rows: [row(glyph)] }, range));
843
1084
  setSymbolsOpen(false);
844
- } })), 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']
845
1099
  .filter((axis) => axis === 'row' || matrixContext.matrix.type === 'matrix')
846
1100
  .flatMap((axis) => ['insert', 'delete'].map((action) => {
847
1101
  const size = axis === 'row' ? matrixContext.rows : matrixContext.matrix.columns;
@@ -851,7 +1105,10 @@ export function MathEditor({ apiRef, autoFocus = false, enterBehavior = 'newline
851
1105
  ? axis === 'row'
852
1106
  ? 'Alt+Shift+ArrowUp'
853
1107
  : 'Alt+Shift+ArrowLeft'
854
- : 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'
855
1112
  ? action === 'insert'
856
1113
  ? 'grid.addRow'
857
1114
  : 'grid.deleteRow'
@@ -862,10 +1119,9 @@ export function MathEditor({ apiRef, autoFocus = false, enterBehavior = 'newline
862
1119
  ? t('matrix.keyboardHint')
863
1120
  : `${t(matrixContext.matrix.type === 'aligned' ? 'aligned.inputHint' : 'cases.inputHint')} · ${t('grid.keyboardHint')}` })] })), showPopovers &&
864
1121
  candidates.length > 0 &&
865
- 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: () => {
866
1123
  drag.current = undefined;
867
- }, 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 &&
868
1125
  selectionFragment &&
869
- 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)] }));
870
1127
  }
871
- //# sourceMappingURL=math-editor.js.map