@barocss/math-editor 0.2.1 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (202) hide show
  1. package/ADAPTERS.md +25 -14
  2. package/API-JAVASCRIPT.md +1 -1
  3. package/API-REACT.md +5 -1
  4. package/API-SESSION.md +178 -6
  5. package/API-SOLID.md +1 -1
  6. package/API-SVELTE.md +1 -1
  7. package/API-VUE.md +1 -1
  8. package/API-WEB-COMPONENT.md +3 -1
  9. package/CHANGELOG.md +106 -0
  10. package/EDITING-SCENARIOS.md +174 -0
  11. package/EMBEDDING.md +4 -0
  12. package/IMPLEMENTATION.md +122 -2
  13. package/JSON-MODEL.md +1 -0
  14. package/LATEX-GUIDE.md +30 -1
  15. package/LATEX-MODEL.md +12 -0
  16. package/LATEX-SCOPE.md +12 -3
  17. package/LICENSE +1 -3
  18. package/README.md +201 -39
  19. package/RELEASING.md +81 -10
  20. package/RENDERING-TESTS.md +79 -0
  21. package/ROADMAP.md +220 -11
  22. package/STYLING.md +157 -0
  23. package/SUPPORT.md +24 -12
  24. package/VALIDATION.md +444 -4
  25. package/dist/context-tools.d.ts +21 -0
  26. package/dist/context-tools.js +37 -0
  27. package/dist/core.d.ts +5 -1
  28. package/dist/core.js +5 -1
  29. package/dist/document-codec.d.ts +0 -1
  30. package/dist/document-codec.js +0 -1
  31. package/dist/dom/caret-geometry.d.ts +3 -0
  32. package/dist/dom/caret-geometry.js +41 -0
  33. package/dist/dom/context-keyboard.d.ts +2 -0
  34. package/dist/dom/context-keyboard.js +22 -0
  35. package/dist/dom/elements.d.ts +1 -2
  36. package/dist/dom/elements.js +2 -3
  37. package/dist/dom/latex-panel.d.ts +10 -0
  38. package/dist/dom/latex-panel.js +59 -0
  39. package/dist/dom/matrix-selection.d.ts +11 -0
  40. package/dist/dom/matrix-selection.js +30 -0
  41. package/dist/dom/menu-position.d.ts +17 -2
  42. package/dist/dom/menu-position.js +129 -16
  43. package/dist/dom/presentation-controls.d.ts +4 -0
  44. package/dist/dom/presentation-controls.js +56 -0
  45. package/dist/dom/quick-panel.d.ts +12 -0
  46. package/dist/dom/quick-panel.js +102 -0
  47. package/dist/dom/selection.d.ts +29 -0
  48. package/dist/dom/selection.js +53 -0
  49. package/dist/dom/symbol-panel.d.ts +9 -0
  50. package/dist/dom/symbol-panel.js +146 -0
  51. package/dist/dom/theme.d.ts +6 -0
  52. package/dist/dom/theme.js +68 -0
  53. package/dist/dom/toolbar-catalog.d.ts +10 -0
  54. package/dist/dom/toolbar-catalog.js +35 -0
  55. package/dist/dom/toolbar.d.ts +13 -2
  56. package/dist/dom/toolbar.js +295 -28
  57. package/dist/dom.d.ts +9 -1
  58. package/dist/dom.js +682 -151
  59. package/dist/editor-labels.d.ts +0 -1
  60. package/dist/editor-labels.js +0 -1
  61. package/dist/enter-policy.d.ts +0 -1
  62. package/dist/enter-policy.js +0 -1
  63. package/dist/fences.d.ts +0 -1
  64. package/dist/fences.js +0 -1
  65. package/dist/i18n.d.ts +0 -1
  66. package/dist/i18n.js +0 -1
  67. package/dist/index.d.ts +4 -1
  68. package/dist/index.js +4 -1
  69. package/dist/latex-insertion.d.ts +12 -0
  70. package/dist/latex-insertion.js +26 -0
  71. package/dist/latex-paste-panel.d.ts +3 -0
  72. package/dist/latex-paste-panel.js +18 -0
  73. package/dist/latex.d.ts +0 -1
  74. package/dist/latex.js +11 -1
  75. package/dist/lines.d.ts +0 -1
  76. package/dist/lines.js +0 -1
  77. package/dist/locales/en.js +39 -1
  78. package/dist/locales/en.json +39 -1
  79. package/dist/locales/ko.js +39 -1
  80. package/dist/locales/ko.json +39 -1
  81. package/dist/math-editor-toolbar.d.ts +4 -2
  82. package/dist/math-editor-toolbar.js +3 -4
  83. package/dist/math-editor.d.ts +7 -2
  84. package/dist/math-editor.js +661 -308
  85. package/dist/math-layout.d.ts +12 -0
  86. package/dist/math-layout.js +59 -0
  87. package/dist/math-spacing.d.ts +13 -0
  88. package/dist/math-spacing.js +87 -0
  89. package/dist/matrix-range.d.ts +40 -0
  90. package/dist/matrix-range.js +242 -0
  91. package/dist/matrix.d.ts +0 -1
  92. package/dist/matrix.js +0 -1
  93. package/dist/model.d.ts +4 -1
  94. package/dist/model.js +49 -5
  95. package/dist/outputs.d.ts +0 -1
  96. package/dist/outputs.js +0 -1
  97. package/dist/preferences.d.ts +24 -0
  98. package/dist/preferences.js +66 -0
  99. package/dist/presentation-controls.d.ts +10 -0
  100. package/dist/presentation-controls.js +10 -0
  101. package/dist/presentation.d.ts +13 -0
  102. package/dist/presentation.js +86 -0
  103. package/dist/quick-panel.d.ts +2 -0
  104. package/dist/quick-panel.js +17 -0
  105. package/dist/range.d.ts +2 -1
  106. package/dist/range.js +11 -1
  107. package/dist/react.d.ts +0 -1
  108. package/dist/react.js +0 -1
  109. package/dist/root-transform.d.ts +19 -0
  110. package/dist/root-transform.js +69 -0
  111. package/dist/session.d.ts +31 -2
  112. package/dist/session.js +108 -7
  113. package/dist/solid.d.ts +0 -1
  114. package/dist/solid.js +0 -1
  115. package/dist/suggestions.d.ts +13 -1
  116. package/dist/suggestions.js +153 -12
  117. package/dist/svelte.d.ts +0 -1
  118. package/dist/svelte.js +0 -1
  119. package/dist/symbol-browser.d.ts +0 -1
  120. package/dist/symbol-browser.js +0 -1
  121. package/dist/symbols.d.ts +0 -1
  122. package/dist/symbols.js +0 -1
  123. package/dist/templates.d.ts +0 -1
  124. package/dist/templates.js +0 -1
  125. package/dist/tokens.d.ts +0 -1
  126. package/dist/tokens.js +0 -1
  127. package/dist/vertical-navigation.d.ts +15 -0
  128. package/dist/vertical-navigation.js +145 -0
  129. package/dist/vue.d.ts +0 -1
  130. package/dist/vue.js +0 -1
  131. package/dist/web-component.d.ts +0 -1
  132. package/dist/web-component.js +9 -2
  133. package/package.json +11 -3
  134. package/src/fonts/KaTeX_Math-Italic.woff2 +0 -0
  135. package/src/fonts/KaTeX_Size1-Regular.woff2 +0 -0
  136. package/src/fonts/README.md +18 -0
  137. package/src/shapes/README.md +21 -0
  138. package/src/shapes/parenthesis-bottom.svg +1 -0
  139. package/src/shapes/parenthesis-top.svg +1 -0
  140. package/src/shapes/parenthesis.svg +1 -0
  141. package/src/shapes/radical.svg +1 -0
  142. package/src/style.css +949 -173
  143. package/dist/core.d.ts.map +0 -1
  144. package/dist/core.js.map +0 -1
  145. package/dist/document-codec.d.ts.map +0 -1
  146. package/dist/document-codec.js.map +0 -1
  147. package/dist/dom/elements.d.ts.map +0 -1
  148. package/dist/dom/elements.js.map +0 -1
  149. package/dist/dom/menu-position.d.ts.map +0 -1
  150. package/dist/dom/menu-position.js.map +0 -1
  151. package/dist/dom/toolbar.d.ts.map +0 -1
  152. package/dist/dom/toolbar.js.map +0 -1
  153. package/dist/dom.d.ts.map +0 -1
  154. package/dist/dom.js.map +0 -1
  155. package/dist/editor-labels.d.ts.map +0 -1
  156. package/dist/editor-labels.js.map +0 -1
  157. package/dist/enter-policy.d.ts.map +0 -1
  158. package/dist/enter-policy.js.map +0 -1
  159. package/dist/fences.d.ts.map +0 -1
  160. package/dist/fences.js.map +0 -1
  161. package/dist/i18n.d.ts.map +0 -1
  162. package/dist/i18n.js.map +0 -1
  163. package/dist/index.d.ts.map +0 -1
  164. package/dist/index.js.map +0 -1
  165. package/dist/latex.d.ts.map +0 -1
  166. package/dist/latex.js.map +0 -1
  167. package/dist/lines.d.ts.map +0 -1
  168. package/dist/lines.js.map +0 -1
  169. package/dist/math-editor-toolbar.d.ts.map +0 -1
  170. package/dist/math-editor-toolbar.js.map +0 -1
  171. package/dist/math-editor.d.ts.map +0 -1
  172. package/dist/math-editor.js.map +0 -1
  173. package/dist/matrix.d.ts.map +0 -1
  174. package/dist/matrix.js.map +0 -1
  175. package/dist/model.d.ts.map +0 -1
  176. package/dist/model.js.map +0 -1
  177. package/dist/outputs.d.ts.map +0 -1
  178. package/dist/outputs.js.map +0 -1
  179. package/dist/range.d.ts.map +0 -1
  180. package/dist/range.js.map +0 -1
  181. package/dist/react.d.ts.map +0 -1
  182. package/dist/react.js.map +0 -1
  183. package/dist/session.d.ts.map +0 -1
  184. package/dist/session.js.map +0 -1
  185. package/dist/solid.d.ts.map +0 -1
  186. package/dist/solid.js.map +0 -1
  187. package/dist/suggestions.d.ts.map +0 -1
  188. package/dist/suggestions.js.map +0 -1
  189. package/dist/svelte.d.ts.map +0 -1
  190. package/dist/svelte.js.map +0 -1
  191. package/dist/symbol-browser.d.ts.map +0 -1
  192. package/dist/symbol-browser.js.map +0 -1
  193. package/dist/symbols.d.ts.map +0 -1
  194. package/dist/symbols.js.map +0 -1
  195. package/dist/templates.d.ts.map +0 -1
  196. package/dist/templates.js.map +0 -1
  197. package/dist/tokens.d.ts.map +0 -1
  198. package/dist/tokens.js.map +0 -1
  199. package/dist/vue.d.ts.map +0 -1
  200. package/dist/vue.js.map +0 -1
  201. package/dist/web-component.d.ts.map +0 -1
  202. package/dist/web-component.js.map +0 -1
@@ -6,4 +6,3 @@ export declare function createEditorLabels(locale: MathLocale): {
6
6
  slot: (parent: string, kind: StructureKind, index: number) => string;
7
7
  grid: (parent: string, kind: "matrix" | "aligned" | "cases", index: number, columns: number) => string;
8
8
  };
9
- //# sourceMappingURL=editor-labels.d.ts.map
@@ -70,4 +70,3 @@ export function createEditorLabels(locale) {
70
70
  })}`,
71
71
  };
72
72
  }
73
- //# sourceMappingURL=editor-labels.js.map
@@ -8,4 +8,3 @@ export interface MathEnterContext {
8
8
  }
9
9
  /** Keep host completion separate from internal grid editing and suggestion acceptance. */
10
10
  export declare function mathEnterAction(context: MathEnterContext): 'suggestion' | 'grid-row' | 'commit' | 'newline' | 'none';
11
- //# sourceMappingURL=enter-policy.d.ts.map
@@ -10,4 +10,3 @@ export function mathEnterAction(context) {
10
10
  return context.gridKind === 'matrix' ? 'none' : 'grid-row';
11
11
  return 'newline';
12
12
  }
13
- //# sourceMappingURL=enter-policy.js.map
package/dist/fences.d.ts CHANGED
@@ -8,4 +8,3 @@ export declare function fences(node: {
8
8
  right?: FenceCharacter;
9
9
  }): readonly ["(" | ")" | "[" | "]" | "{" | "}" | "⟨" | "⟩" | "|" | "‖" | ".", "(" | ")" | "[" | "]" | "{" | "}" | "⟨" | "⟩" | "|" | "‖" | "."];
10
10
  export declare function fenceLatex(value: FenceCharacter): string;
11
- //# sourceMappingURL=fences.d.ts.map
package/dist/fences.js CHANGED
@@ -18,4 +18,3 @@ export function fences(node) {
18
18
  export function fenceLatex(value) {
19
19
  return ({ '‖': '\\Vert ', '{': '\\{', '}': '\\}', '⟨': '\\langle ', '⟩': '\\rangle ' }[value] ?? value);
20
20
  }
21
- //# sourceMappingURL=fences.js.map
package/dist/i18n.d.ts CHANGED
@@ -17,4 +17,3 @@ export declare const mathLocaleAliases: (locale: string, id: string) => readonly
17
17
  /** A small dictionary resolver: lookup, fallback and named interpolation. No rendering or fetching. */
18
18
  export declare function translate(locale: MathLocale, key: string, parameters?: MathMessageParameters): string;
19
19
  export declare const mathEnglishMessages: Readonly<Record<string, string>>;
20
- //# sourceMappingURL=i18n.d.ts.map
package/dist/i18n.js CHANGED
@@ -55,4 +55,3 @@ function interpolate(template, parameters) {
55
55
  export const mathEnglishMessages = Object.freeze({
56
56
  ...english.messages,
57
57
  });
58
- //# sourceMappingURL=i18n.js.map
package/dist/index.d.ts CHANGED
@@ -2,6 +2,7 @@ export * from './model.js';
2
2
  export { MathEditor, type MathEditorProps, type MathEditorHandle } from './math-editor.js';
3
3
  export { findSuggestions, acceptSuggestion, mathStructures, type MathSuggestion, } from './suggestions.js';
4
4
  export * from './matrix.js';
5
+ export * from './matrix-range.js';
5
6
  export * from './lines.js';
6
7
  export * from './tokens.js';
7
8
  export * from './range.js';
@@ -11,4 +12,6 @@ export * from './templates.js';
11
12
  export { mathSymbols } from './symbols.js';
12
13
  export * from './latex.js';
13
14
  export * from './document-codec.js';
14
- //# sourceMappingURL=index.d.ts.map
15
+ export * from './preferences.js';
16
+ export * from './presentation.js';
17
+ export * from './latex-insertion.js';
package/dist/index.js CHANGED
@@ -2,6 +2,7 @@ export * from './model.js';
2
2
  export { MathEditor } from './math-editor.js';
3
3
  export { findSuggestions, acceptSuggestion, mathStructures, } from './suggestions.js';
4
4
  export * from './matrix.js';
5
+ export * from './matrix-range.js';
5
6
  export * from './lines.js';
6
7
  export * from './tokens.js';
7
8
  export * from './range.js';
@@ -11,4 +12,6 @@ export * from './templates.js';
11
12
  export { mathSymbols } from './symbols.js';
12
13
  export * from './latex.js';
13
14
  export * from './document-codec.js';
14
- //# sourceMappingURL=index.js.map
15
+ export * from './preferences.js';
16
+ export * from './presentation.js';
17
+ export * from './latex-insertion.js';
@@ -0,0 +1,12 @@
1
+ import { type LatexImportOptions, type LatexParseResult } from './latex.js';
2
+ import { type MathState } from './model.js';
3
+ import { type MathRange } from './range.js';
4
+ export type LatexInsertionResult = (Extract<LatexParseResult, {
5
+ ok: true;
6
+ }> & {
7
+ state: MathState;
8
+ }) | Extract<LatexParseResult, {
9
+ ok: false;
10
+ }>;
11
+ /** Parse first, then insert at the caret/range. Rejected input never changes the source tree. */
12
+ export declare function insertLatex(state: MathState, source: string, range?: MathRange, options?: LatexImportOptions): LatexInsertionResult;
@@ -0,0 +1,26 @@
1
+ import { parseLatex } from './latex.js';
2
+ import { documentRows } from './model.js';
3
+ import { pasteFragment } from './range.js';
4
+ /** Parse first, then insert at the caret/range. Rejected input never changes the source tree. */
5
+ export function insertLatex(state, source, range, options) {
6
+ const parsed = parseLatex(source, options);
7
+ if (!parsed.ok)
8
+ return parsed;
9
+ const next = source.trim()
10
+ ? pasteFragment(state, { version: 1, rows: documentRows(parsed.document) }, range)
11
+ : state;
12
+ if (next === state)
13
+ return {
14
+ ok: false,
15
+ source,
16
+ diagnostics: [
17
+ {
18
+ code: 'unsupported-structure',
19
+ message: 'This input cannot be inserted at the current selection.',
20
+ start: 0,
21
+ end: source.length,
22
+ },
23
+ ],
24
+ };
25
+ return { ...parsed, state: next };
26
+ }
@@ -0,0 +1,3 @@
1
+ import { mountLatexPanel } from './dom/latex-panel.js';
2
+ /** Both renderers use the same paste form and diagnostic behavior. */
3
+ export declare function LatexPastePanel(props: Parameters<typeof mountLatexPanel>[1]): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,18 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useLayoutEffect, useRef } from 'react';
3
+ import { mountLatexPanel } from './dom/latex-panel.js';
4
+ /** Both renderers use the same paste form and diagnostic behavior. */
5
+ export function LatexPastePanel(props) {
6
+ const host = useRef(null);
7
+ const current = useRef(props);
8
+ current.current = props;
9
+ useLayoutEffect(() => {
10
+ const panel = mountLatexPanel(host.current, {
11
+ locale: props.locale,
12
+ onInsert: (source) => current.current.onInsert(source),
13
+ onClose: () => current.current.onClose(),
14
+ });
15
+ return () => panel.destroy();
16
+ }, [props.locale]);
17
+ return _jsx("div", { ref: host });
18
+ }
package/dist/latex.d.ts CHANGED
@@ -23,4 +23,3 @@ export interface LatexImportOptions {
23
23
  }
24
24
  /** Parse without changing editor state. Failures retain the complete original source. */
25
25
  export declare function parseLatex(source: string, options?: LatexImportOptions): LatexParseResult;
26
- //# sourceMappingURL=latex.d.ts.map
package/dist/latex.js CHANGED
@@ -391,6 +391,17 @@ class LatexParser {
391
391
  return row(command);
392
392
  if (command === 'backslash')
393
393
  return row('\\');
394
+ if (command === 'char') {
395
+ // Canonical math-mode literal caret/tilde output. This is intentionally
396
+ // bounded; arbitrary TeX character codes are not part of the model API.
397
+ this.skip();
398
+ const match = this.source.slice(this.at, this.end).match(/^"([0-9a-f]+)/i);
399
+ const code = match ? Number.parseInt(match[1], 16) : NaN;
400
+ if (code !== 0x5e && code !== 0x7e)
401
+ this.fail('unsupported-command', 'Only literal caret and tilde character codes are supported.', start);
402
+ this.at += match[0].length;
403
+ return row(String.fromCodePoint(code));
404
+ }
394
405
  if (command === 'textasciicircum' || command === 'textasciitilde') {
395
406
  this.skip();
396
407
  if (!this.starts('{}'))
@@ -686,4 +697,3 @@ export function parseLatex(source, options = {}) {
686
697
  throw error;
687
698
  }
688
699
  }
689
- //# sourceMappingURL=latex.js.map
package/dist/lines.d.ts CHANGED
@@ -4,4 +4,3 @@ export declare function splitLine(state: MathState): MathState;
4
4
  /** Backspace at the start of a top-level line merges it with the previous line. */
5
5
  export declare function joinPreviousLine(state: MathState): MathState;
6
6
  export declare function moveLineVertical(state: MathState, direction: -1 | 1): MathState;
7
- //# sourceMappingURL=lines.d.ts.map
package/dist/lines.js CHANGED
@@ -48,4 +48,3 @@ export function moveLineVertical(state, direction) {
48
48
  const offset = Math.min(state.caret.start, target.text.length);
49
49
  return { ...state, caret: { id: target.id, start: offset, end: offset } };
50
50
  }
51
- //# sourceMappingURL=lines.js.map
@@ -315,7 +315,45 @@ export default {
315
315
  "structure.xleftarrow": "Labeled left arrow",
316
316
  "structure.arrowLabelsDetail": "Edit labels above and below a stretchy arrow",
317
317
  "slot.arrowUpper": "Upper label",
318
- "slot.arrowLower": "Lower label"
318
+ "slot.arrowLower": "Lower label",
319
+ "matrix.selectCells": "Select cells",
320
+ "matrix.selectAll": "Select all cells",
321
+ "matrix.transpose": "Transpose matrix",
322
+ "matrix.rangeHint": "{rows} × {columns} cells selected · Shift+arrows extends · Copy / Paste · Delete clears · Enter edits",
323
+ "matrix.pasteRejected": "The cell sizes do not match, the clipboard is invalid, or the result exceeds 20 × 20. The matrix was not changed.",
324
+ "clipboard.latexTitle": "Paste as LaTeX",
325
+ "clipboard.latexHint": "Paste LaTeX here. Insert replaces the selected range or inserts at the caret. Ctrl/Cmd+Enter inserts.",
326
+ "clipboard.latexInsert": "Insert formula",
327
+ "clipboard.latexError": "Cannot insert LaTeX",
328
+ "clipboard.latexShortcut": "Alt+Shift+V: Paste as LaTeX",
329
+ "quick.title": "Recent & favorites",
330
+ "quick.filter": "Show items",
331
+ "quick.all": "All symbols and templates",
332
+ "quick.recent": "Recently used",
333
+ "quick.favorites": "Favorites",
334
+ "quick.favorite": "Favorite",
335
+ "quick.empty": "No items here yet.",
336
+ "presentation.title": "Structure settings",
337
+ "presentation.fence": "Brackets",
338
+ "presentation.size": "Fraction size",
339
+ "presentation.limits": "Limit placement",
340
+ "presentation.default": "Automatic",
341
+ "presentation.display": "Display size",
342
+ "presentation.text": "Text size",
343
+ "presentation.aboveBelow": "Above and below",
344
+ "presentation.side": "Beside operator",
345
+ "suggestion.transform": "Change to {kind}",
346
+ "suggestion.transformRootDetail": "Keep the radicand. A square root requires an empty index or 2.",
347
+ "context.label": "Structure tools",
348
+ "context.current": "Editing: {kind}",
349
+ "context.editIndex": "Edit index",
350
+ "context.keyboardHint": "F6: tools · Esc: back to input",
351
+ "context.squareIndexRequired": "Change the index to 2 or clear it to use a square root.",
352
+ "context.root": "Square root",
353
+ "context.indexedRoot": "Indexed root",
354
+ "context.fenceKeyboardHint": "F6: tools · ← →: choose · Enter: apply · Esc: back to input",
355
+ "suggestion.transformFence": "Change brackets: {kind}",
356
+ "suggestion.transformFenceDetail": "Keep the enclosed formula and cursor position"
319
357
  },
320
358
  "aliases": {}
321
359
  };
@@ -314,7 +314,45 @@
314
314
  "structure.xleftarrow": "Labeled left arrow",
315
315
  "structure.arrowLabelsDetail": "Edit labels above and below a stretchy arrow",
316
316
  "slot.arrowUpper": "Upper label",
317
- "slot.arrowLower": "Lower label"
317
+ "slot.arrowLower": "Lower label",
318
+ "matrix.selectCells": "Select cells",
319
+ "matrix.selectAll": "Select all cells",
320
+ "matrix.transpose": "Transpose matrix",
321
+ "matrix.rangeHint": "{rows} × {columns} cells selected · Shift+arrows extends · Copy / Paste · Delete clears · Enter edits",
322
+ "matrix.pasteRejected": "The cell sizes do not match, the clipboard is invalid, or the result exceeds 20 × 20. The matrix was not changed.",
323
+ "clipboard.latexTitle": "Paste as LaTeX",
324
+ "clipboard.latexHint": "Paste LaTeX here. Insert replaces the selected range or inserts at the caret. Ctrl/Cmd+Enter inserts.",
325
+ "clipboard.latexInsert": "Insert formula",
326
+ "clipboard.latexError": "Cannot insert LaTeX",
327
+ "clipboard.latexShortcut": "Alt+Shift+V: Paste as LaTeX",
328
+ "quick.title": "Recent & favorites",
329
+ "quick.filter": "Show items",
330
+ "quick.all": "All symbols and templates",
331
+ "quick.recent": "Recently used",
332
+ "quick.favorites": "Favorites",
333
+ "quick.favorite": "Favorite",
334
+ "quick.empty": "No items here yet.",
335
+ "presentation.title": "Structure settings",
336
+ "presentation.fence": "Brackets",
337
+ "presentation.size": "Fraction size",
338
+ "presentation.limits": "Limit placement",
339
+ "presentation.default": "Automatic",
340
+ "presentation.display": "Display size",
341
+ "presentation.text": "Text size",
342
+ "presentation.aboveBelow": "Above and below",
343
+ "presentation.side": "Beside operator",
344
+ "suggestion.transform": "Change to {kind}",
345
+ "suggestion.transformRootDetail": "Keep the radicand. A square root requires an empty index or 2.",
346
+ "context.label": "Structure tools",
347
+ "context.current": "Editing: {kind}",
348
+ "context.editIndex": "Edit index",
349
+ "context.keyboardHint": "F6: tools · Esc: back to input",
350
+ "context.squareIndexRequired": "Change the index to 2 or clear it to use a square root.",
351
+ "context.root": "Square root",
352
+ "context.indexedRoot": "Indexed root",
353
+ "context.fenceKeyboardHint": "F6: tools · ← →: choose · Enter: apply · Esc: back to input",
354
+ "suggestion.transformFence": "Change brackets: {kind}",
355
+ "suggestion.transformFenceDetail": "Keep the enclosed formula and cursor position"
318
356
  },
319
357
  "aliases": {}
320
358
  }
@@ -315,7 +315,45 @@ export default {
315
315
  "structure.xleftarrow": "왼쪽 설명 화살표",
316
316
  "structure.arrowLabelsDetail": "길이가 늘어나는 화살표 위·아래 설명 편집",
317
317
  "slot.arrowUpper": "위 설명",
318
- "slot.arrowLower": "아래 설명"
318
+ "slot.arrowLower": "아래 설명",
319
+ "matrix.selectCells": "셀 선택",
320
+ "matrix.selectAll": "모든 셀 선택",
321
+ "matrix.transpose": "행렬 전치",
322
+ "matrix.rangeHint": "{rows} × {columns} 셀 선택 · Shift+방향키로 확장 · 복사 / 붙여넣기 · Delete로 비우기 · Enter로 편집",
323
+ "matrix.pasteRejected": "셀 크기가 맞지 않거나 클립보드가 올바르지 않거나 20 × 20을 초과합니다. 행렬은 그대로 유지됩니다.",
324
+ "clipboard.latexTitle": "LaTeX로 붙여넣기",
325
+ "clipboard.latexHint": "LaTeX를 붙여넣으세요. 선택 영역을 바꾸거나 커서 위치에 넣습니다. Ctrl/Cmd+Enter로 삽입합니다.",
326
+ "clipboard.latexInsert": "수식 삽입",
327
+ "clipboard.latexError": "LaTeX를 넣을 수 없습니다",
328
+ "clipboard.latexShortcut": "Alt+Shift+V: LaTeX로 붙여넣기",
329
+ "quick.title": "최근 사용·즐겨찾기",
330
+ "quick.filter": "목록 보기",
331
+ "quick.all": "모든 기호와 템플릿",
332
+ "quick.recent": "최근 사용",
333
+ "quick.favorites": "즐겨찾기",
334
+ "quick.favorite": "즐겨찾기",
335
+ "quick.empty": "아직 항목이 없습니다.",
336
+ "presentation.title": "구조 설정",
337
+ "presentation.fence": "괄호 종류",
338
+ "presentation.size": "분수 크기",
339
+ "presentation.limits": "첨자 배치",
340
+ "presentation.default": "자동",
341
+ "presentation.display": "큰 표시",
342
+ "presentation.text": "작은 표시",
343
+ "presentation.aboveBelow": "위·아래",
344
+ "presentation.side": "오른쪽",
345
+ "suggestion.transform": "{kind}으로 변형",
346
+ "suggestion.transformRootDetail": "루트 안의 수식을 유지합니다. 제곱근으로 바꾸려면 차수가 2이거나 비어 있어야 합니다.",
347
+ "context.label": "구조 편집 도구",
348
+ "context.current": "현재 구조: {kind}",
349
+ "context.editIndex": "차수 편집",
350
+ "context.keyboardHint": "F6: 도구로 이동 · Esc: 입력으로",
351
+ "context.squareIndexRequired": "제곱근으로 바꾸려면 차수를 2로 바꾸거나 비워 주세요.",
352
+ "context.root": "제곱근",
353
+ "context.indexedRoot": "n제곱근",
354
+ "context.fenceKeyboardHint": "F6: 도구로 이동 · ← →: 선택 · Enter: 적용 · Esc: 입력으로",
355
+ "suggestion.transformFence": "괄호 변경: {kind}",
356
+ "suggestion.transformFenceDetail": "안의 수식과 커서 위치를 유지합니다"
319
357
  },
320
358
  "aliases": {
321
359
  "function-sin": ["사인"],
@@ -314,7 +314,45 @@
314
314
  "structure.xleftarrow": "왼쪽 설명 화살표",
315
315
  "structure.arrowLabelsDetail": "길이가 늘어나는 화살표 위·아래 설명 편집",
316
316
  "slot.arrowUpper": "위 설명",
317
- "slot.arrowLower": "아래 설명"
317
+ "slot.arrowLower": "아래 설명",
318
+ "matrix.selectCells": "셀 선택",
319
+ "matrix.selectAll": "모든 셀 선택",
320
+ "matrix.transpose": "행렬 전치",
321
+ "matrix.rangeHint": "{rows} × {columns} 셀 선택 · Shift+방향키로 확장 · 복사 / 붙여넣기 · Delete로 비우기 · Enter로 편집",
322
+ "matrix.pasteRejected": "셀 크기가 맞지 않거나 클립보드가 올바르지 않거나 20 × 20을 초과합니다. 행렬은 그대로 유지됩니다.",
323
+ "clipboard.latexTitle": "LaTeX로 붙여넣기",
324
+ "clipboard.latexHint": "LaTeX를 붙여넣으세요. 선택 영역을 바꾸거나 커서 위치에 넣습니다. Ctrl/Cmd+Enter로 삽입합니다.",
325
+ "clipboard.latexInsert": "수식 삽입",
326
+ "clipboard.latexError": "LaTeX를 넣을 수 없습니다",
327
+ "clipboard.latexShortcut": "Alt+Shift+V: LaTeX로 붙여넣기",
328
+ "quick.title": "최근 사용·즐겨찾기",
329
+ "quick.filter": "목록 보기",
330
+ "quick.all": "모든 기호와 템플릿",
331
+ "quick.recent": "최근 사용",
332
+ "quick.favorites": "즐겨찾기",
333
+ "quick.favorite": "즐겨찾기",
334
+ "quick.empty": "아직 항목이 없습니다.",
335
+ "presentation.title": "구조 설정",
336
+ "presentation.fence": "괄호 종류",
337
+ "presentation.size": "분수 크기",
338
+ "presentation.limits": "첨자 배치",
339
+ "presentation.default": "자동",
340
+ "presentation.display": "큰 표시",
341
+ "presentation.text": "작은 표시",
342
+ "presentation.aboveBelow": "위·아래",
343
+ "presentation.side": "오른쪽",
344
+ "suggestion.transform": "{kind}으로 변형",
345
+ "suggestion.transformRootDetail": "루트 안의 수식을 유지합니다. 제곱근으로 바꾸려면 차수가 2이거나 비어 있어야 합니다.",
346
+ "context.label": "구조 편집 도구",
347
+ "context.current": "현재 구조: {kind}",
348
+ "context.editIndex": "차수 편집",
349
+ "context.keyboardHint": "F6: 도구로 이동 · Esc: 입력으로",
350
+ "context.squareIndexRequired": "제곱근으로 바꾸려면 차수를 2로 바꾸거나 비워 주세요.",
351
+ "context.root": "제곱근",
352
+ "context.indexedRoot": "n제곱근",
353
+ "context.fenceKeyboardHint": "F6: 도구로 이동 · ← →: 선택 · Enter: 적용 · Esc: 입력으로",
354
+ "suggestion.transformFence": "괄호 변경: {kind}",
355
+ "suggestion.transformFenceDetail": "안의 수식과 커서 위치를 유지합니다"
318
356
  },
319
357
  "aliases": {
320
358
  "function-sin": ["사인"],
@@ -8,6 +8,7 @@ interface MathEditorToolbarProps {
8
8
  excludedStructures?: readonly StructureKind[];
9
9
  composing: boolean;
10
10
  hasRange: boolean;
11
+ cellRange?: boolean;
11
12
  canWrap: boolean;
12
13
  canUndo: boolean;
13
14
  canRedo: boolean;
@@ -17,11 +18,12 @@ interface MathEditorToolbarProps {
17
18
  onTemplate: (id: string) => void;
18
19
  onToggleSymbols: () => void;
19
20
  onInsertSymbol: (glyph: string) => void;
21
+ onQuick: () => void;
22
+ onPasteLatex: () => void;
20
23
  onUndo: () => void;
21
24
  onRedo: () => void;
22
25
  children?: ReactNode;
23
26
  }
24
27
  /** Presentation-only toolbar. The editor keeps selection, composition and history ownership. */
25
- export declare function MathEditorToolbar({ locale, kinds, maxItems, excludedStructures, composing, hasRange, canWrap, canUndo, canRedo, symbolsOpen, onInsertStructure, onMatrixPreset, onTemplate, onToggleSymbols, onInsertSymbol, onUndo, onRedo, children, }: MathEditorToolbarProps): import("react/jsx-runtime").JSX.Element;
28
+ export declare function MathEditorToolbar({ locale, kinds, maxItems, excludedStructures, composing, hasRange, cellRange, canWrap, canUndo, canRedo, symbolsOpen, onInsertStructure, onMatrixPreset, onTemplate, onToggleSymbols, onInsertSymbol, onQuick, onPasteLatex, onUndo, onRedo, children, }: MathEditorToolbarProps): import("react/jsx-runtime").JSX.Element;
26
29
  export {};
27
- //# sourceMappingURL=math-editor-toolbar.d.ts.map
@@ -12,14 +12,13 @@ const symbols = [
12
12
  { label: 'symbol.infinity', value: '∞' },
13
13
  ];
14
14
  /** Presentation-only toolbar. The editor keeps selection, composition and history ownership. */
15
- export function MathEditorToolbar({ locale, kinds, maxItems = 8, excludedStructures = [], composing, hasRange, canWrap, canUndo, canRedo, symbolsOpen, onInsertStructure, onMatrixPreset, onTemplate, onToggleSymbols, onInsertSymbol, onUndo, onRedo, children, }) {
15
+ export function MathEditorToolbar({ locale, kinds, maxItems = 8, excludedStructures = [], composing, hasRange, cellRange = false, canWrap, canUndo, canRedo, symbolsOpen, onInsertStructure, onMatrixPreset, onTemplate, onToggleSymbols, onInsertSymbol, onQuick, onPasteLatex, onUndo, onRedo, children, }) {
16
16
  const [expanded, setExpanded] = useState(false);
17
17
  const visibleCount = Math.max(0, Math.floor(Number.isFinite(maxItems) ? maxItems : 8));
18
18
  const items = mathStructures.filter((s) => s.kind && !excludedStructures.includes(s.kind) && (!kinds || kinds.includes(s.kind)));
19
19
  const t = (key, parameters) => translate(locale, key, parameters);
20
- return (_jsxs("div", { className: "me-tools", role: "toolbar", "aria-label": t('toolbar.label'), children: [(expanded ? items : items.slice(0, visibleCount)).map((s) => (_jsxs("button", { type: "button", "aria-label": t(s.label), disabled: composing || (hasRange && (!canWrap || !wrappingKinds.includes(s.kind))), onMouseDown: (event) => event.preventDefault(), onClick: () => onInsertStructure(s.kind), children: [_jsx("span", { children: s.glyph }), t(s.label)] }, s.kind))), expanded && (_jsxs(_Fragment, { children: [_jsxs("select", { disabled: composing || hasRange, className: "me-matrix-size", "aria-label": t('matrix.preset'), value: "", onChange: (event) => {
20
+ return (_jsxs("div", { className: "me-tools", role: "toolbar", "aria-label": t('toolbar.label'), children: [(expanded ? items : items.slice(0, visibleCount)).map((s) => (_jsxs("button", { type: "button", "aria-label": t(s.label), disabled: composing || (hasRange && (!canWrap || !wrappingKinds.includes(s.kind))), onMouseDown: (event) => event.preventDefault(), onClick: () => onInsertStructure(s.kind), children: [_jsx("span", { children: s.glyph }), t(s.label)] }, s.kind))), expanded && (_jsxs(_Fragment, { children: [_jsx("button", { type: "button", "data-math-tool": "quick", disabled: composing || cellRange, onMouseDown: (event) => event.preventDefault(), onClick: onQuick, children: t('quick.title') }), _jsx("button", { type: "button", "data-math-tool": "paste-latex", disabled: composing || cellRange, onMouseDown: (event) => event.preventDefault(), onClick: onPasteLatex, title: t('clipboard.latexShortcut'), children: t('clipboard.latexTitle') }), _jsxs("select", { disabled: composing || hasRange, className: "me-matrix-size", "aria-label": t('matrix.preset'), value: "", onChange: (event) => {
21
21
  const value = event.target.value;
22
22
  onMatrixPreset(value);
23
- }, children: [_jsx("option", { value: "", disabled: true, children: t('matrix.presetPlaceholder') }), [2, 3, 4].map((size) => (_jsx("option", { value: size, children: t('matrix.insert', { rows: size, columns: size }) }, size))), [2, 3, 4].map((size) => (_jsx("option", { value: `identity-${size}`, children: t('matrix.insertIdentity', { rows: size, columns: size }) }, `identity-${size}`)))] }), _jsxs("select", { className: "me-matrix-size", "aria-label": t('template.label'), value: "", disabled: composing, onChange: (event) => onTemplate(event.target.value), children: [_jsx("option", { value: "", disabled: true, children: t('template.placeholder') }), mathTemplates.map((item) => (_jsx("option", { value: item.id, children: t(item.label, item.labelParameters) }, item.id)))] }), _jsx("button", { type: "button", "aria-expanded": symbolsOpen, disabled: composing, onClick: onToggleSymbols, children: t('symbols.title') }), _jsx("span", { className: "me-divider" }), symbols.map((s) => (_jsx("button", { type: "button", "aria-label": t(s.label), disabled: composing || hasRange, onMouseDown: (event) => event.preventDefault(), onClick: () => onInsertSymbol(s.value), children: s.value }, s.label)))] })), _jsx("button", { type: "button", className: "me-toolbar-toggle", "aria-expanded": expanded, onMouseDown: (event) => event.preventDefault(), onClick: () => setExpanded((value) => !value), children: t(expanded ? 'toolbar.less' : 'toolbar.more') }), _jsx("button", { type: "button", disabled: !canUndo || composing, onMouseDown: (event) => event.preventDefault(), onClick: onUndo, children: t('history.undo') }), _jsx("button", { type: "button", disabled: !canRedo || composing, onMouseDown: (event) => event.preventDefault(), onClick: onRedo, children: t('history.redo') }), children] }));
23
+ }, children: [_jsx("option", { value: "", disabled: true, children: t('matrix.presetPlaceholder') }), [2, 3, 4].map((size) => (_jsx("option", { value: size, children: t('matrix.insert', { rows: size, columns: size }) }, size))), [2, 3, 4].map((size) => (_jsx("option", { value: `identity-${size}`, children: t('matrix.insertIdentity', { rows: size, columns: size }) }, `identity-${size}`)))] }), _jsxs("select", { className: "me-matrix-size", "aria-label": t('template.label'), value: "", disabled: composing || cellRange, onChange: (event) => onTemplate(event.target.value), children: [_jsx("option", { value: "", disabled: true, children: t('template.placeholder') }), mathTemplates.map((item) => (_jsx("option", { value: item.id, children: t(item.label, item.labelParameters) }, item.id)))] }), _jsx("button", { type: "button", "aria-expanded": symbolsOpen, disabled: composing || cellRange, onClick: onToggleSymbols, children: t('symbols.title') }), _jsx("span", { className: "me-divider" }), symbols.map((s) => (_jsx("button", { type: "button", "aria-label": t(s.label), disabled: composing || hasRange, onMouseDown: (event) => event.preventDefault(), onClick: () => onInsertSymbol(s.value), children: s.value }, s.label)))] })), _jsx("button", { type: "button", className: "me-toolbar-toggle", "aria-expanded": expanded, onMouseDown: (event) => event.preventDefault(), onClick: () => setExpanded((value) => !value), children: t(expanded ? 'toolbar.less' : 'toolbar.more') }), _jsx("button", { type: "button", disabled: !canUndo || composing, onMouseDown: (event) => event.preventDefault(), onClick: onUndo, children: t('history.undo') }), _jsx("button", { type: "button", disabled: !canRedo || composing, onMouseDown: (event) => event.preventDefault(), onClick: onRedo, children: t('history.redo') }), children] }));
24
24
  }
25
- //# sourceMappingURL=math-editor-toolbar.js.map
@@ -1,3 +1,5 @@
1
+ import { type MathPreferences } from './preferences.js';
2
+ import { type LatexInsertionResult } from './latex-insertion.js';
1
3
  import { type LatexParseResult } from './latex.js';
2
4
  import { type MathLocale } from './i18n.js';
3
5
  import { type ReactNode, type Ref } from 'react';
@@ -5,8 +7,10 @@ import { type MathDocument, type StructureKind } from './model.js';
5
7
  export interface MathEditorHandle {
6
8
  /** Replace with supported LaTeX as one undoable edit; failures preserve all editor state. */
7
9
  importLatex(source: string): LatexParseResult;
10
+ pasteLatex(source: string): LatexInsertionResult;
8
11
  }
9
12
  export interface MathEditorProps {
13
+ preferences?: MathPreferences;
10
14
  apiRef?: Ref<MathEditorHandle>;
11
15
  /** Start editing at the initial caret when embedded in a host editor. */
12
16
  autoFocus?: boolean;
@@ -24,6 +28,8 @@ export interface MathEditorProps {
24
28
  toolbar?: boolean | readonly StructureKind[];
25
29
  /** Visible structure buttons before More; defaults to 8. */
26
30
  toolbarMaxItems?: number;
31
+ /** Show contextual structure actions below the editing surface. Defaults to true. */
32
+ contextTools?: boolean;
27
33
  /** Host-owned actions rendered at the end of the main toolbar. */
28
34
  toolbarEnd?: ReactNode;
29
35
  showTokenLegend?: boolean;
@@ -39,5 +45,4 @@ export interface MathEditorProps {
39
45
  label?: string;
40
46
  }
41
47
  /** Native text fields own IME and local text selection; the tree owns structural editing. */
42
- export declare function MathEditor({ apiRef, autoFocus, enterBehavior, onCommit, onCancel, showPopovers, defaultValue, excludedStructures, multiline, onChange, onExit, label, locale, showLineNumbers, toolbar, toolbarMaxItems, toolbarEnd, showTokenLegend, }: MathEditorProps): import("react/jsx-runtime").JSX.Element;
43
- //# sourceMappingURL=math-editor.d.ts.map
48
+ export declare function MathEditor({ preferences: suppliedPreferences, apiRef, autoFocus, enterBehavior, onCommit, onCancel, showPopovers, defaultValue, excludedStructures, multiline, onChange, onExit, label, locale, showLineNumbers, toolbar, toolbarMaxItems, contextTools, toolbarEnd, showTokenLegend, }: MathEditorProps): import("react/jsx-runtime").JSX.Element;