@barocss/math-editor 0.5.0 → 0.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/API-SESSION.md +25 -1
- package/CHANGELOG.md +48 -0
- package/CLIPBOARD.md +54 -0
- package/EDITING-SCENARIOS.md +55 -20
- package/GETTING-STARTED.md +54 -0
- package/IMPLEMENTATION.md +10 -0
- package/KEYBOARD.md +41 -0
- package/LATEX-GUIDE.md +30 -2
- package/README.md +52 -10
- package/RELEASING.md +22 -8
- package/ROADMAP.md +106 -1
- package/STYLING.md +28 -1
- package/TEXT-EDITORS.md +157 -0
- package/VALIDATION.md +102 -0
- package/dist/dom/caret-geometry.js +1 -1
- package/dist/dom/help.d.ts +5 -0
- package/dist/dom/help.js +104 -0
- package/dist/dom/menu-position.js +4 -3
- package/dist/dom/readable-layout.d.ts +3 -0
- package/dist/dom/readable-layout.js +52 -0
- package/dist/dom/toolbar-catalog.d.ts +1 -1
- package/dist/dom/toolbar.d.ts +2 -0
- package/dist/dom/toolbar.js +8 -1
- package/dist/dom.d.ts +11 -1
- package/dist/dom.js +138 -15
- package/dist/enter-policy.js +1 -1
- package/dist/lines.d.ts +2 -0
- package/dist/lines.js +15 -0
- package/dist/locales/en.js +21 -3
- package/dist/locales/en.json +21 -3
- package/dist/locales/ko.js +21 -3
- package/dist/locales/ko.json +21 -3
- package/dist/math-editor-toolbar.js +2 -1
- package/dist/math-editor.d.ts +1 -0
- package/dist/math-editor.js +135 -39
- package/dist/model.d.ts +2 -0
- package/dist/model.js +23 -1
- package/dist/range.d.ts +10 -2
- package/dist/range.js +31 -6
- package/dist/selection-shortcuts.d.ts +13 -0
- package/dist/selection-shortcuts.js +35 -0
- package/dist/session.d.ts +1 -0
- package/dist/session.js +1 -1
- package/dist/symbols.d.ts +1 -1
- package/dist/symbols.js +1 -0
- package/dist/vertical-navigation.d.ts +5 -0
- package/dist/vertical-navigation.js +33 -0
- package/package.json +1 -1
- package/src/style.css +227 -57
package/dist/dom/help.js
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { translate } from '../i18n.js';
|
|
2
|
+
const helpEvent = 'math-editor-help';
|
|
3
|
+
/** Route a toolbar request to its owning field, including fields inside an iframe. */
|
|
4
|
+
export function requestMathHelp(control) {
|
|
5
|
+
const EventClass = control.ownerDocument.defaultView.Event;
|
|
6
|
+
control.dispatchEvent(new EventClass(helpEvent, { bubbles: true }));
|
|
7
|
+
}
|
|
8
|
+
/** Shared help UI. It does not execute model commands or read the clipboard. */
|
|
9
|
+
export function attachMathHelp(root, locale) {
|
|
10
|
+
let dialog;
|
|
11
|
+
let previous = null;
|
|
12
|
+
let selection;
|
|
13
|
+
const close = (restore = true) => {
|
|
14
|
+
dialog?.close();
|
|
15
|
+
dialog?.remove();
|
|
16
|
+
dialog = undefined;
|
|
17
|
+
if (restore && previous?.isConnected) {
|
|
18
|
+
previous.focus({ preventScroll: true });
|
|
19
|
+
if (selection && previous.tagName === 'INPUT') {
|
|
20
|
+
previous.setSelectionRange(selection.start, selection.end, selection.direction);
|
|
21
|
+
previous.dispatchEvent(new root.ownerDocument.defaultView.Event('select', { bubbles: true }));
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
const open = () => {
|
|
26
|
+
if (dialog)
|
|
27
|
+
return;
|
|
28
|
+
const doc = root.ownerDocument;
|
|
29
|
+
const t = (key) => translate(locale(), key);
|
|
30
|
+
previous = doc.activeElement;
|
|
31
|
+
const input = previous?.tagName === 'INPUT' ? previous : undefined;
|
|
32
|
+
selection =
|
|
33
|
+
input && input.selectionStart !== null && input.selectionEnd !== null
|
|
34
|
+
? {
|
|
35
|
+
start: input.selectionStart,
|
|
36
|
+
end: input.selectionEnd,
|
|
37
|
+
direction: input.selectionDirection ?? 'none',
|
|
38
|
+
}
|
|
39
|
+
: undefined;
|
|
40
|
+
dialog = doc.createElement('dialog');
|
|
41
|
+
dialog.className = 'me-help me-utility-panel';
|
|
42
|
+
dialog.setAttribute('aria-label', t('help.title'));
|
|
43
|
+
const heading = doc.createElement('h2');
|
|
44
|
+
heading.textContent = t('help.title');
|
|
45
|
+
const intro = doc.createElement('p');
|
|
46
|
+
intro.textContent = t('help.intro');
|
|
47
|
+
const list = doc.createElement('dl');
|
|
48
|
+
for (const [keys, message] of [
|
|
49
|
+
['Tab / Shift+Tab', 'help.slots'],
|
|
50
|
+
['Ctrl+←/→ · Mac: ⌥+←/→ (+Shift)', 'help.units'],
|
|
51
|
+
['Shift+← / →', 'help.select'],
|
|
52
|
+
['( [ { | / ^ _', 'help.wrap'],
|
|
53
|
+
['Alt+↓', 'help.suggestions'],
|
|
54
|
+
['↑ / ↓ · Enter · Esc', 'help.menu'],
|
|
55
|
+
['Ctrl/Cmd+C · X · V', 'help.clipboard'],
|
|
56
|
+
['Alt+Shift+V', 'help.latex'],
|
|
57
|
+
['Ctrl/Cmd+Z · Ctrl/Cmd+Shift+Z', 'help.history'],
|
|
58
|
+
['Enter / Shift+Enter', 'help.lines'],
|
|
59
|
+
['F1', 'help.open'],
|
|
60
|
+
]) {
|
|
61
|
+
const term = doc.createElement('dt');
|
|
62
|
+
term.textContent = keys;
|
|
63
|
+
const definition = doc.createElement('dd');
|
|
64
|
+
definition.textContent = t(message);
|
|
65
|
+
list.append(term, definition);
|
|
66
|
+
}
|
|
67
|
+
const note = doc.createElement('p');
|
|
68
|
+
note.textContent = t('help.platform');
|
|
69
|
+
const button = doc.createElement('button');
|
|
70
|
+
button.type = 'button';
|
|
71
|
+
button.textContent = t('common.close');
|
|
72
|
+
button.onclick = () => close();
|
|
73
|
+
dialog.append(heading, intro, list, note, button);
|
|
74
|
+
dialog.addEventListener('cancel', (event) => {
|
|
75
|
+
event.preventDefault();
|
|
76
|
+
close();
|
|
77
|
+
});
|
|
78
|
+
// Help text selection/copy must not invoke the formula's clipboard or keyboard handlers.
|
|
79
|
+
for (const name of ['copy', 'cut', 'paste', 'keydown', 'keyup'])
|
|
80
|
+
dialog.addEventListener(name, (event) => event.stopPropagation());
|
|
81
|
+
root.append(dialog);
|
|
82
|
+
dialog.showModal();
|
|
83
|
+
button.focus();
|
|
84
|
+
};
|
|
85
|
+
const keydown = (event) => {
|
|
86
|
+
if (event.key !== 'F1' ||
|
|
87
|
+
event.isComposing ||
|
|
88
|
+
event.ctrlKey ||
|
|
89
|
+
event.metaKey ||
|
|
90
|
+
event.altKey ||
|
|
91
|
+
event.shiftKey)
|
|
92
|
+
return;
|
|
93
|
+
event.preventDefault();
|
|
94
|
+
event.stopPropagation();
|
|
95
|
+
open();
|
|
96
|
+
};
|
|
97
|
+
root.addEventListener(helpEvent, open);
|
|
98
|
+
root.addEventListener('keydown', keydown, true);
|
|
99
|
+
return () => {
|
|
100
|
+
root.removeEventListener(helpEvent, open);
|
|
101
|
+
root.removeEventListener('keydown', keydown, true);
|
|
102
|
+
close(false);
|
|
103
|
+
};
|
|
104
|
+
}
|
|
@@ -117,10 +117,11 @@ export function positionMathMenu(menu, anchor, maxHeight, avoidElements = []) {
|
|
|
117
117
|
for (let parent = menu.parentElement; parent; parent = parent.parentElement) {
|
|
118
118
|
const style = win.getComputedStyle(parent);
|
|
119
119
|
contained ||= establishesFixedContainingBlock(style);
|
|
120
|
-
const dialog = parent.matches('dialog, [role="dialog"]');
|
|
121
120
|
const paintClip = /paint|strict|content/.test(style.contain) || style.contentVisibility === 'auto';
|
|
122
|
-
|
|
123
|
-
|
|
121
|
+
// Dialog semantics do not create a CSS clipping boundary. A compact dialog
|
|
122
|
+
// can host a fixed menu taller than itself; constrain only actual paint clips.
|
|
123
|
+
const clipX = paintClip || (contained && /auto|scroll|hidden|clip/.test(style.overflowX));
|
|
124
|
+
const clipY = paintClip || (contained && /auto|scroll|hidden|clip/.test(style.overflowY));
|
|
124
125
|
if (!clipX && !clipY)
|
|
125
126
|
continue;
|
|
126
127
|
const rect = parent.getBoundingClientRect();
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/** Reserve line space for translated scripts. Their visual bounds are not part
|
|
2
|
+
* of flex layout, and a font floor can make them taller than the base row. */
|
|
3
|
+
export function followReadableMathLayout(surface) {
|
|
4
|
+
const win = surface.ownerDocument.defaultView;
|
|
5
|
+
let frame = 0;
|
|
6
|
+
const measure = () => {
|
|
7
|
+
frame = 0;
|
|
8
|
+
const minimum = win.getComputedStyle(surface).getPropertyValue('--me-min-font-size').trim();
|
|
9
|
+
const enabled = !minimum || Number.parseFloat(minimum) !== 0;
|
|
10
|
+
for (const line of surface.querySelectorAll('.me-document-line')) {
|
|
11
|
+
const row = line.querySelector(':scope > .me-row');
|
|
12
|
+
if (!row)
|
|
13
|
+
continue;
|
|
14
|
+
const bounds = row.getBoundingClientRect();
|
|
15
|
+
let top = bounds.top, bottom = bounds.bottom;
|
|
16
|
+
if (enabled) {
|
|
17
|
+
for (const glyph of row.querySelectorAll('.me-measure, .me-delimiter, .me-radical, .me-operator-glyph')) {
|
|
18
|
+
const rect = glyph.getBoundingClientRect();
|
|
19
|
+
top = Math.min(top, rect.top);
|
|
20
|
+
bottom = Math.max(bottom, rect.bottom);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
const before = `${Math.ceil(bounds.top - top)}px`;
|
|
24
|
+
const after = `${Math.ceil(bottom - bounds.bottom)}px`;
|
|
25
|
+
if (line.style.paddingTop !== before)
|
|
26
|
+
line.style.paddingTop = before;
|
|
27
|
+
if (line.style.paddingBottom !== after)
|
|
28
|
+
line.style.paddingBottom = after;
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
const schedule = () => {
|
|
32
|
+
if (!frame)
|
|
33
|
+
frame = win.requestAnimationFrame(measure);
|
|
34
|
+
};
|
|
35
|
+
const mutations = new MutationObserver(schedule);
|
|
36
|
+
mutations.observe(surface, {
|
|
37
|
+
childList: true,
|
|
38
|
+
subtree: true,
|
|
39
|
+
attributes: true,
|
|
40
|
+
attributeFilter: ['style', 'class'],
|
|
41
|
+
});
|
|
42
|
+
const resize = typeof ResizeObserver === 'undefined' ? undefined : new ResizeObserver(schedule);
|
|
43
|
+
resize?.observe(surface);
|
|
44
|
+
win.addEventListener('resize', schedule);
|
|
45
|
+
schedule();
|
|
46
|
+
return () => {
|
|
47
|
+
mutations.disconnect();
|
|
48
|
+
resize?.disconnect();
|
|
49
|
+
win.cancelAnimationFrame(frame);
|
|
50
|
+
win.removeEventListener('resize', schedule);
|
|
51
|
+
};
|
|
52
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type MathLocale } from '../i18n.js';
|
|
2
2
|
import type { StructureKind } from '../model.js';
|
|
3
3
|
/** Full discovery search retains the symbol catalog and suggestion engine's ranking. */
|
|
4
|
-
export declare function findToolbarSymbols(query: string, locale: MathLocale): (readonly ["↑", "symbol.upArrow", "uparrow arrow 화살표", "- ->", "\\uparrow"] | readonly ["↕", "symbol.upDownArrow", "updownarrow arrow 화살표", "- ->", "\\updownarrow"] | readonly ["⇐", "symbol.doubleLeftArrow", "Leftarrow arrow 화살표", "- ->", "\\Leftarrow"] | readonly ["⇑", "symbol.doubleUpArrow", "Uparrow arrow 화살표", "- ->", "\\Uparrow"] | readonly ["⇓", "symbol.doubleDownArrow", "Downarrow arrow 화살표", "- ->", "\\Downarrow"] | readonly ["⇕", "symbol.doubleUpDownArrow", "Updownarrow arrow 화살표", "- ->", "\\Updownarrow"] | readonly ["↗", "symbol.northEastArrow", "nearrow arrow 화살표", "- ->", "\\nearrow"] | readonly ["↘", "symbol.southEastArrow", "searrow arrow 화살표", "- ->", "\\searrow"] | readonly ["↙", "symbol.southWestArrow", "swarrow arrow 화살표", "- ->", "\\swarrow"] | readonly ["↖", "symbol.northWestArrow", "nwarrow arrow 화살표", "- ->", "\\nwarrow"] | readonly ["⟶", "symbol.longRightArrow", "longrightarrow arrow 화살표", "- ->", "\\longrightarrow"] | readonly ["⟵", "symbol.longLeftArrow", "longleftarrow arrow 화살표", "- ->", "\\longleftarrow"] | readonly ["⟷", "symbol.longLeftRightArrow", "longleftrightarrow arrow 화살표", "-", "\\longleftrightarrow"] | readonly ["⟹", "symbol.longDoubleRightArrow", "Longrightarrow arrow 화살표", "- ->", "\\Longrightarrow"] | readonly ["⟸", "symbol.longDoubleLeftArrow", "Longleftarrow arrow 화살표", "- ->", "\\Longleftarrow"] | readonly ["⟺", "symbol.longDoubleLeftRightArrow", "Longleftrightarrow arrow 화살표", "", "\\Longleftrightarrow"] | readonly ["↪", "symbol.hookRightArrow", "hookrightarrow arrow 화살표", "- ->", "\\hookrightarrow"] | readonly ["↩", "symbol.hookLeftArrow", "hookleftarrow arrow 화살표", "- ->", "\\hookleftarrow"] | readonly ["⇀", "symbol.rightHarpoonUp", "rightharpoonup arrow 화살표", "- ->", "\\rightharpoonup"] | readonly ["↼", "symbol.leftHarpoonUp", "leftharpoonup arrow 화살표", "- ->", "\\leftharpoonup"] | readonly ["⇁", "symbol.rightHarpoonDown", "rightharpoondown arrow 화살표", "- ->", "\\rightharpoondown"] | readonly ["↽", "symbol.leftHarpoonDown", "leftharpoondown arrow 화살표", "- ->", "\\leftharpoondown"] | readonly ["⇌", "symbol.rightLeftHarpoons", "rightleftharpoons arrow 화살표", "- ->", "\\rightleftharpoons"] | readonly ["⇋", "symbol.leftRightHarpoons", "leftrightharpoons arrow 화살표", "- ->", "\\leftrightharpoons"] | readonly ["↓", "symbol.downArrow", "downarrow down 아래화살표 아래쪽화살표", "- ->", "\\downarrow"] | readonly ["⩾", "symbol.greaterOrEqualSlanted", "geqslant", "", "\\geqslant"] | readonly ["⩽", "symbol.lessOrEqualSlanted", "leqslant", "", "\\leqslant"] | readonly ["∋", "symbol.contains", "ni contains", "", "\\ni"] | readonly ["⊃", "symbol.superset", "supset superset", "", "\\supset"] | readonly ["⊇", "symbol.supersetOrEqual", "supseteq", "", "\\supseteq"] | readonly ["⊈", "symbol.notSubsetOrEqual", "nsubseteq", "", "\\nsubseteq"] | readonly ["∖", "symbol.setDifference", "setminus difference", "", "\\setminus"] | readonly ["ℕ", "symbol.naturals", "naturals natural", "", "\\mathbb{N}"] | readonly ["ℤ", "symbol.integers", "integers integer", "", "\\mathbb{Z}"] | readonly ["ℚ", "symbol.rationals", "rationals rational", "", "\\mathbb{Q}"] | readonly ["ℝ", "symbol.reals", "reals real", "", "\\mathbb{R}"] | readonly ["ℂ", "symbol.complexes", "complexes complex", "", "\\mathbb{C}"] | readonly ["⊥", "symbol.perpendicular", "perp perpendicular", "", "\\perp"] | readonly ["∥", "symbol.parallel", "parallel", "", "\\parallel"] | readonly ["≅", "symbol.congruent", "cong congruent", "", "\\cong"] | readonly ["∼", "symbol.similar", "sim similar", "", "\\sim"] | readonly ["↦", "symbol.mapsTo", "mapsto maps arrow 화살표", "|-> - ->", "\\mapsto"] | readonly ["…", "symbol.ellipsis", "ldots ellipsis", "", "\\ldots"] | readonly ["⋯", "symbol.centeredDots", "cdots", "", "\\cdots"] | readonly ["⋮", "symbol.verticalDots", "vdots", "", "\\vdots"] | readonly ["⋱", "symbol.diagonalDots", "ddots", "", "\\ddots"] | readonly ["°", "symbol.degree", "degree degrees 각도", "", "{}^{\\circ}"] | readonly ["∠", "symbol.angle", "angle", "", "\\angle"] | readonly ["+", "symbol.plus", "plus sum", "+", "+"] | readonly ["−", "symbol.minus", "minus", "-", "-"] | readonly ["±", "symbol.plusMinus", "plusminus sum", "+- +", "\\pm"] | readonly ["∓", "symbol.minusPlus", "minusplus", "-+ -", "\\mp"] | readonly ["×", "symbol.times", "times multiply", "*", "\\times"] | readonly ["·", "symbol.dot", "dot multiply", "*", "\\cdot"] | readonly ["÷", "symbol.divide", "divide division", "/", "\\div"] | readonly ["=", "symbol.equal", "equal", "=", "="] | readonly ["≠", "symbol.notEqual", "neq unequal", "!= /= =", "\\ne"] | readonly ["≈", "symbol.approximatelyEqual", "approx", "~ ~~ =", "\\approx"] | readonly ["≡", "symbol.equivalent", "equiv", "=== =", "\\equiv"] | readonly ["<", "symbol.lessThan", "less", "<", "<"] | readonly [">", "symbol.greaterThan", "greater", ">", ">"] | readonly ["≤", "symbol.lessOrEqual", "leq less", "<= <- <", "\\le"] | readonly ["≥", "symbol.greaterOrEqual", "geq greater", ">= >- >", "\\ge"] | readonly ["∝", "symbol.proportional", "proportional", "~", "\\propto"] | readonly ["→", "symbol.rightArrow", "rightarrow arrow", "-> -", "\\to"] | readonly ["←", "symbol.leftArrow", "leftarrow arrow", "<- < - ->", "\\leftarrow"] | readonly ["↔", "symbol.leftRightArrow", "leftrightarrow arrow", "<-> - ->", "\\leftrightarrow"] | readonly ["⇒", "symbol.implies", "implies arrow 화살표", "=> = - ->", "\\Rightarrow"] | readonly ["⇔", "symbol.iff", "iff arrow 화살표", "<=> - ->", "\\Leftrightarrow"] | readonly ["∈", "symbol.elementOf", "in element", "E", "\\in"] | readonly ["∉", "symbol.notElementOf", "notin element", "E/", "\\notin"] | readonly ["∀", "symbol.forAll", "forall", "A", "\\forall"] | readonly ["∃", "symbol.exists", "exists", "E", "\\exists"] | readonly ["∪", "symbol.union", "union", "U", "\\cup"] | readonly ["∩", "symbol.intersection", "intersection", "", "\\cap"] | readonly ["⊂", "symbol.subset", "subset", "<", "\\subset"] | readonly ["⊆", "symbol.subsetOrEqual", "subseteq", "<=", "\\subseteq"] | readonly ["∅", "symbol.emptySet", "emptyset", "", "\\emptyset"] | readonly ["∞", "symbol.infinity", "infinity infty", "", "\\infty"] | readonly ["∂", "symbol.partialDerivative", "partial derivative", "", "\\partial"] | readonly ["∇", "symbol.nabla", "nabla gradient", "", "\\nabla"] | readonly ["∧", "symbol.logicalAnd", "and wedge", "^", "\\wedge"] | readonly ["∨", "symbol.logicalOr", "or vee", "", "\\vee"] | readonly ["¬", "symbol.logicalNot", "not neg", "!", "\\neg"] | readonly ["α", "symbol.alpha", "alpha", "", "\\alpha"] | readonly ["β", "symbol.beta", "beta", "", "\\beta"] | readonly ["γ", "symbol.gamma", "gamma", "", "\\gamma"] | readonly ["δ", "symbol.delta", "delta", "", "\\delta"] | readonly ["ε", "symbol.epsilon", "epsilon", "", "\\epsilon"] | readonly ["ζ", "symbol.zeta", "zeta", "", "\\zeta"] | readonly ["η", "symbol.eta", "eta", "", "\\eta"] | readonly ["θ", "symbol.theta", "theta", "", "\\theta"] | readonly ["ι", "symbol.iota", "iota", "", "\\iota"] | readonly ["κ", "symbol.kappa", "kappa", "", "\\kappa"] | readonly ["λ", "symbol.lambda", "lambda", "", "\\lambda"] | readonly ["μ", "symbol.mu", "mu", "", "\\mu"] | readonly ["ν", "symbol.nu", "nu", "", "\\nu"] | readonly ["ξ", "symbol.xi", "xi", "", "\\xi"] | readonly ["π", "symbol.pi", "pi", "", "\\pi"] | readonly ["ρ", "symbol.rho", "rho", "", "\\rho"] | readonly ["σ", "symbol.sigma", "sigma", "", "\\sigma"] | readonly ["τ", "symbol.tau", "tau", "", "\\tau"] | readonly ["υ", "symbol.upsilon", "upsilon", "", "\\upsilon"] | readonly ["φ", "symbol.phi", "phi", "", "\\phi"] | readonly ["χ", "symbol.chi", "chi", "", "\\chi"] | readonly ["ψ", "symbol.psi", "psi", "", "\\psi"] | readonly ["ω", "symbol.omega", "omega", "", "\\omega"] | readonly ["Γ", "symbol.upperGamma", "Gamma", "", "\\Gamma"] | readonly ["Δ", "symbol.upperDelta", "Delta", "", "\\Delta"] | readonly ["Θ", "symbol.upperTheta", "Theta", "", "\\Theta"] | readonly ["Λ", "symbol.upperLambda", "Lambda", "", "\\Lambda"] | readonly ["Ξ", "symbol.upperXi", "Xi", "", "\\Xi"] | readonly ["Π", "symbol.upperPi", "Pi", "", "\\Pi"] | readonly ["Σ", "symbol.upperSigma", "Sigma", "", "\\Sigma"] | readonly ["Φ", "symbol.upperPhi", "Phi", "", "\\Phi"] | readonly ["Ψ", "symbol.upperPsi", "Psi", "", "\\Psi"] | readonly ["Ω", "symbol.upperOmega", "Omega", "", "\\Omega"])[];
|
|
4
|
+
export declare function findToolbarSymbols(query: string, locale: MathLocale): (readonly ["↑", "symbol.upArrow", "uparrow arrow 화살표", "- ->", "\\uparrow"] | readonly ["↕", "symbol.upDownArrow", "updownarrow arrow 화살표", "- ->", "\\updownarrow"] | readonly ["⇐", "symbol.doubleLeftArrow", "Leftarrow arrow 화살표", "- ->", "\\Leftarrow"] | readonly ["⇑", "symbol.doubleUpArrow", "Uparrow arrow 화살표", "- ->", "\\Uparrow"] | readonly ["⇓", "symbol.doubleDownArrow", "Downarrow arrow 화살표", "- ->", "\\Downarrow"] | readonly ["⇕", "symbol.doubleUpDownArrow", "Updownarrow arrow 화살표", "- ->", "\\Updownarrow"] | readonly ["↗", "symbol.northEastArrow", "nearrow arrow 화살표", "- ->", "\\nearrow"] | readonly ["↘", "symbol.southEastArrow", "searrow arrow 화살표", "- ->", "\\searrow"] | readonly ["↙", "symbol.southWestArrow", "swarrow arrow 화살표", "- ->", "\\swarrow"] | readonly ["↖", "symbol.northWestArrow", "nwarrow arrow 화살표", "- ->", "\\nwarrow"] | readonly ["⟶", "symbol.longRightArrow", "longrightarrow arrow 화살표", "- ->", "\\longrightarrow"] | readonly ["⟵", "symbol.longLeftArrow", "longleftarrow arrow 화살표", "- ->", "\\longleftarrow"] | readonly ["⟷", "symbol.longLeftRightArrow", "longleftrightarrow arrow 화살표", "-", "\\longleftrightarrow"] | readonly ["⟹", "symbol.longDoubleRightArrow", "Longrightarrow arrow 화살표", "- ->", "\\Longrightarrow"] | readonly ["⟸", "symbol.longDoubleLeftArrow", "Longleftarrow arrow 화살표", "- ->", "\\Longleftarrow"] | readonly ["⟺", "symbol.longDoubleLeftRightArrow", "Longleftrightarrow arrow 화살표", "", "\\Longleftrightarrow"] | readonly ["↪", "symbol.hookRightArrow", "hookrightarrow arrow 화살표", "- ->", "\\hookrightarrow"] | readonly ["↩", "symbol.hookLeftArrow", "hookleftarrow arrow 화살표", "- ->", "\\hookleftarrow"] | readonly ["⇀", "symbol.rightHarpoonUp", "rightharpoonup arrow 화살표", "- ->", "\\rightharpoonup"] | readonly ["↼", "symbol.leftHarpoonUp", "leftharpoonup arrow 화살표", "- ->", "\\leftharpoonup"] | readonly ["⇁", "symbol.rightHarpoonDown", "rightharpoondown arrow 화살표", "- ->", "\\rightharpoondown"] | readonly ["↽", "symbol.leftHarpoonDown", "leftharpoondown arrow 화살표", "- ->", "\\leftharpoondown"] | readonly ["⇌", "symbol.rightLeftHarpoons", "rightleftharpoons arrow 화살표", "- ->", "\\rightleftharpoons"] | readonly ["⇋", "symbol.leftRightHarpoons", "leftrightharpoons arrow 화살표", "- ->", "\\leftrightharpoons"] | readonly ["↓", "symbol.downArrow", "downarrow down 아래화살표 아래쪽화살표", "- ->", "\\downarrow"] | readonly ["⩾", "symbol.greaterOrEqualSlanted", "geqslant", "", "\\geqslant"] | readonly ["⩽", "symbol.lessOrEqualSlanted", "leqslant", "", "\\leqslant"] | readonly ["∋", "symbol.contains", "ni contains", "", "\\ni"] | readonly ["⊃", "symbol.superset", "supset superset", "", "\\supset"] | readonly ["⊇", "symbol.supersetOrEqual", "supseteq", "", "\\supseteq"] | readonly ["⊈", "symbol.notSubsetOrEqual", "nsubseteq", "", "\\nsubseteq"] | readonly ["∖", "symbol.setDifference", "setminus difference", "", "\\setminus"] | readonly ["ℕ", "symbol.naturals", "naturals natural", "", "\\mathbb{N}"] | readonly ["ℤ", "symbol.integers", "integers integer", "", "\\mathbb{Z}"] | readonly ["ℚ", "symbol.rationals", "rationals rational", "", "\\mathbb{Q}"] | readonly ["ℝ", "symbol.reals", "reals real", "", "\\mathbb{R}"] | readonly ["ℂ", "symbol.complexes", "complexes complex", "", "\\mathbb{C}"] | readonly ["⊥", "symbol.perpendicular", "perp perpendicular", "", "\\perp"] | readonly ["∥", "symbol.parallel", "parallel", "", "\\parallel"] | readonly ["≅", "symbol.congruent", "cong congruent", "", "\\cong"] | readonly ["∼", "symbol.similar", "sim similar", "", "\\sim"] | readonly ["↦", "symbol.mapsTo", "mapsto maps arrow 화살표", "|-> - ->", "\\mapsto"] | readonly ["…", "symbol.ellipsis", "ldots ellipsis", "", "\\ldots"] | readonly ["⋯", "symbol.centeredDots", "cdots", "", "\\cdots"] | readonly ["⋮", "symbol.verticalDots", "vdots", "", "\\vdots"] | readonly ["⋱", "symbol.diagonalDots", "ddots", "", "\\ddots"] | readonly ["′", "symbol.prime", "prime 프라임 미분", "", "\\prime"] | readonly ["°", "symbol.degree", "degree degrees 각도", "", "{}^{\\circ}"] | readonly ["∠", "symbol.angle", "angle", "", "\\angle"] | readonly ["+", "symbol.plus", "plus sum", "+", "+"] | readonly ["−", "symbol.minus", "minus", "-", "-"] | readonly ["±", "symbol.plusMinus", "plusminus sum", "+- +", "\\pm"] | readonly ["∓", "symbol.minusPlus", "minusplus", "-+ -", "\\mp"] | readonly ["×", "symbol.times", "times multiply", "*", "\\times"] | readonly ["·", "symbol.dot", "dot multiply", "*", "\\cdot"] | readonly ["÷", "symbol.divide", "divide division", "/", "\\div"] | readonly ["=", "symbol.equal", "equal", "=", "="] | readonly ["≠", "symbol.notEqual", "neq unequal", "!= /= =", "\\ne"] | readonly ["≈", "symbol.approximatelyEqual", "approx", "~ ~~ =", "\\approx"] | readonly ["≡", "symbol.equivalent", "equiv", "=== =", "\\equiv"] | readonly ["<", "symbol.lessThan", "less", "<", "<"] | readonly [">", "symbol.greaterThan", "greater", ">", ">"] | readonly ["≤", "symbol.lessOrEqual", "leq less", "<= <- <", "\\le"] | readonly ["≥", "symbol.greaterOrEqual", "geq greater", ">= >- >", "\\ge"] | readonly ["∝", "symbol.proportional", "proportional", "~", "\\propto"] | readonly ["→", "symbol.rightArrow", "rightarrow arrow", "-> -", "\\to"] | readonly ["←", "symbol.leftArrow", "leftarrow arrow", "<- < - ->", "\\leftarrow"] | readonly ["↔", "symbol.leftRightArrow", "leftrightarrow arrow", "<-> - ->", "\\leftrightarrow"] | readonly ["⇒", "symbol.implies", "implies arrow 화살표", "=> = - ->", "\\Rightarrow"] | readonly ["⇔", "symbol.iff", "iff arrow 화살표", "<=> - ->", "\\Leftrightarrow"] | readonly ["∈", "symbol.elementOf", "in element", "E", "\\in"] | readonly ["∉", "symbol.notElementOf", "notin element", "E/", "\\notin"] | readonly ["∀", "symbol.forAll", "forall", "A", "\\forall"] | readonly ["∃", "symbol.exists", "exists", "E", "\\exists"] | readonly ["∪", "symbol.union", "union", "U", "\\cup"] | readonly ["∩", "symbol.intersection", "intersection", "", "\\cap"] | readonly ["⊂", "symbol.subset", "subset", "<", "\\subset"] | readonly ["⊆", "symbol.subsetOrEqual", "subseteq", "<=", "\\subseteq"] | readonly ["∅", "symbol.emptySet", "emptyset", "", "\\emptyset"] | readonly ["∞", "symbol.infinity", "infinity infty", "", "\\infty"] | readonly ["∂", "symbol.partialDerivative", "partial derivative", "", "\\partial"] | readonly ["∇", "symbol.nabla", "nabla gradient", "", "\\nabla"] | readonly ["∧", "symbol.logicalAnd", "and wedge", "^", "\\wedge"] | readonly ["∨", "symbol.logicalOr", "or vee", "", "\\vee"] | readonly ["¬", "symbol.logicalNot", "not neg", "!", "\\neg"] | readonly ["α", "symbol.alpha", "alpha", "", "\\alpha"] | readonly ["β", "symbol.beta", "beta", "", "\\beta"] | readonly ["γ", "symbol.gamma", "gamma", "", "\\gamma"] | readonly ["δ", "symbol.delta", "delta", "", "\\delta"] | readonly ["ε", "symbol.epsilon", "epsilon", "", "\\epsilon"] | readonly ["ζ", "symbol.zeta", "zeta", "", "\\zeta"] | readonly ["η", "symbol.eta", "eta", "", "\\eta"] | readonly ["θ", "symbol.theta", "theta", "", "\\theta"] | readonly ["ι", "symbol.iota", "iota", "", "\\iota"] | readonly ["κ", "symbol.kappa", "kappa", "", "\\kappa"] | readonly ["λ", "symbol.lambda", "lambda", "", "\\lambda"] | readonly ["μ", "symbol.mu", "mu", "", "\\mu"] | readonly ["ν", "symbol.nu", "nu", "", "\\nu"] | readonly ["ξ", "symbol.xi", "xi", "", "\\xi"] | readonly ["π", "symbol.pi", "pi", "", "\\pi"] | readonly ["ρ", "symbol.rho", "rho", "", "\\rho"] | readonly ["σ", "symbol.sigma", "sigma", "", "\\sigma"] | readonly ["τ", "symbol.tau", "tau", "", "\\tau"] | readonly ["υ", "symbol.upsilon", "upsilon", "", "\\upsilon"] | readonly ["φ", "symbol.phi", "phi", "", "\\phi"] | readonly ["χ", "symbol.chi", "chi", "", "\\chi"] | readonly ["ψ", "symbol.psi", "psi", "", "\\psi"] | readonly ["ω", "symbol.omega", "omega", "", "\\omega"] | readonly ["Γ", "symbol.upperGamma", "Gamma", "", "\\Gamma"] | readonly ["Δ", "symbol.upperDelta", "Delta", "", "\\Delta"] | readonly ["Θ", "symbol.upperTheta", "Theta", "", "\\Theta"] | readonly ["Λ", "symbol.upperLambda", "Lambda", "", "\\Lambda"] | readonly ["Ξ", "symbol.upperXi", "Xi", "", "\\Xi"] | readonly ["Π", "symbol.upperPi", "Pi", "", "\\Pi"] | readonly ["Σ", "symbol.upperSigma", "Sigma", "", "\\Sigma"] | readonly ["Φ", "symbol.upperPhi", "Phi", "", "\\Phi"] | readonly ["Ψ", "symbol.upperPsi", "Psi", "", "\\Psi"] | readonly ["Ω", "symbol.upperOmega", "Omega", "", "\\Omega"])[];
|
|
5
5
|
/** Templates must not offer a back door around a host's allowed structure kinds. */
|
|
6
6
|
export declare function toolbarTemplates(kinds?: readonly StructureKind[]): import("../templates.js").MathTemplate[];
|
|
7
7
|
export declare function parseToolbarMatrixPreset(value: string): {
|
package/dist/dom/toolbar.d.ts
CHANGED
|
@@ -9,6 +9,8 @@ export interface MathToolbarOptions {
|
|
|
9
9
|
locale?: MathLocale;
|
|
10
10
|
onExecute?: () => void;
|
|
11
11
|
onPasteLatex?: () => void;
|
|
12
|
+
/** Connect help to the field when the toolbar is mounted separately. */
|
|
13
|
+
onHelp?: () => void;
|
|
12
14
|
/** Close another utility owned by the editing surface before opening a toolbar panel. */
|
|
13
15
|
onOpenPanel?: () => void;
|
|
14
16
|
}
|
package/dist/dom/toolbar.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { requestMathHelp } from './help.js';
|
|
1
2
|
import { drawPresentationControls } from './presentation-controls.js';
|
|
2
3
|
import { mountQuickPanel } from './quick-panel.js';
|
|
3
4
|
import { mountLatexPanel } from './latex-panel.js';
|
|
@@ -87,6 +88,12 @@ export function mountMathToolbar(host, session, options = {}) {
|
|
|
87
88
|
control.dataset.mathTool = item.kind;
|
|
88
89
|
toolbar.append(control);
|
|
89
90
|
}
|
|
91
|
+
if (options.onHelp || host.closest('.me-editor')) {
|
|
92
|
+
const help = button(t('help.title'), () => options.onHelp ? options.onHelp() : requestMathHelp(help));
|
|
93
|
+
help.dataset.mathTool = 'help';
|
|
94
|
+
help.setAttribute('aria-keyshortcuts', 'F1');
|
|
95
|
+
toolbar.append(help);
|
|
96
|
+
}
|
|
90
97
|
if (expanded) {
|
|
91
98
|
const quick = button(t('quick.title'), () => {
|
|
92
99
|
options.onOpenPanel?.();
|
|
@@ -283,7 +290,7 @@ export function mountMathToolbar(host, session, options = {}) {
|
|
|
283
290
|
control.dataset.mathTool = `${axis}-${action}`;
|
|
284
291
|
if (action === 'delete') {
|
|
285
292
|
control.title = t(axis === 'row' ? 'grid.deleteRowShortcut' : 'grid.deleteColumnShortcut');
|
|
286
|
-
control.setAttribute('aria-keyshortcuts', axis === 'row' ? 'Alt+Shift+ArrowUp' : 'Alt+Shift+
|
|
293
|
+
control.setAttribute('aria-keyshortcuts', axis === 'row' ? 'Alt+Shift+ArrowUp' : 'Alt+Shift+Backspace');
|
|
287
294
|
}
|
|
288
295
|
gridTools.append(control);
|
|
289
296
|
}
|
package/dist/dom.d.ts
CHANGED
|
@@ -3,7 +3,8 @@ export { mountMathLatex, mountMathPreview, type MathOutput, type MathPreviewOpti
|
|
|
3
3
|
export { mountMathToolbar, type MathToolbarOptions } from './dom/toolbar.js';
|
|
4
4
|
import { type MathSession, type MathEditorMode } from './session.js';
|
|
5
5
|
import { type MathLocale } from './i18n.js';
|
|
6
|
-
import { type MathDocument, type StructureKind } from './model.js';
|
|
6
|
+
import { type MathDocument, type MathState, type StructureKind } from './model.js';
|
|
7
|
+
import { type MathSuggestion } from './suggestions.js';
|
|
7
8
|
export interface DOMMathEditorOptions {
|
|
8
9
|
/** Mount-only UI preferences; ignored when an external session owns the store. */
|
|
9
10
|
preferences?: MathPreferences;
|
|
@@ -19,11 +20,19 @@ export interface DOMMathEditorOptions {
|
|
|
19
20
|
toolbarMaxItems?: number;
|
|
20
21
|
/** Show contextual structure actions below the editing surface. Defaults to true. */
|
|
21
22
|
contextTools?: boolean;
|
|
23
|
+
/** Disable built-in suggestion and selection popups when the host renders its own controls. */
|
|
24
|
+
suggestionMenu?: boolean;
|
|
25
|
+
/** Filter or reorder generated suggestions without replacing editor selection/acceptance behavior. */
|
|
26
|
+
filterSuggestions?: (candidates: readonly MathSuggestion[], query: string, state: MathState) => readonly MathSuggestion[];
|
|
27
|
+
/** Limit selection wrapping actions for a host. Omit to show every supported kind. */
|
|
28
|
+
selectionKinds?: readonly StructureKind[];
|
|
22
29
|
showLineNumbers?: boolean;
|
|
23
30
|
onChange?: (document: MathDocument, latex: string) => void;
|
|
24
31
|
/** Final DOM/caret notification, including focus and selection-only updates. */
|
|
25
32
|
onRender?: () => void;
|
|
26
33
|
onExit?: (direction: -1 | 1) => void;
|
|
34
|
+
/** Host structure commands. Return true when handled; preserve suggestions where appropriate. */
|
|
35
|
+
onEditKeyDown?: (event: KeyboardEvent, snapshot: ReturnType<MathSession['getSnapshot']>, acceptsSuggestion: boolean) => boolean;
|
|
27
36
|
/** Default: block=newline, inline=commit. Suggestions always take priority. */
|
|
28
37
|
enterBehavior?: 'newline' | 'commit';
|
|
29
38
|
/** The host creates the next block, saves a popup, or restores its caret. No model mutation. */
|
|
@@ -34,6 +43,7 @@ export interface DOMMathEditorOptions {
|
|
|
34
43
|
export interface DOMMathEditor {
|
|
35
44
|
session: MathSession;
|
|
36
45
|
focus(): void;
|
|
46
|
+
showHelp(): void;
|
|
37
47
|
update(options: Partial<Omit<DOMMathEditorOptions, 'session' | 'defaultValue' | 'menuHost'>>): void;
|
|
38
48
|
destroy(): void;
|
|
39
49
|
}
|