@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.
- package/ADAPTERS.md +25 -14
- package/API-JAVASCRIPT.md +1 -1
- package/API-REACT.md +5 -1
- package/API-SESSION.md +178 -6
- package/API-SOLID.md +1 -1
- package/API-SVELTE.md +1 -1
- package/API-VUE.md +1 -1
- package/API-WEB-COMPONENT.md +3 -1
- package/CHANGELOG.md +106 -0
- package/EDITING-SCENARIOS.md +174 -0
- package/EMBEDDING.md +4 -0
- package/IMPLEMENTATION.md +122 -2
- package/JSON-MODEL.md +1 -0
- package/LATEX-GUIDE.md +30 -1
- package/LATEX-MODEL.md +12 -0
- package/LATEX-SCOPE.md +12 -3
- package/LICENSE +1 -3
- package/README.md +201 -39
- package/RELEASING.md +81 -10
- package/RENDERING-TESTS.md +79 -0
- package/ROADMAP.md +220 -11
- package/STYLING.md +157 -0
- package/SUPPORT.md +24 -12
- package/VALIDATION.md +444 -4
- package/dist/context-tools.d.ts +21 -0
- package/dist/context-tools.js +37 -0
- package/dist/core.d.ts +5 -1
- package/dist/core.js +5 -1
- package/dist/document-codec.d.ts +0 -1
- package/dist/document-codec.js +0 -1
- package/dist/dom/caret-geometry.d.ts +3 -0
- package/dist/dom/caret-geometry.js +41 -0
- package/dist/dom/context-keyboard.d.ts +2 -0
- package/dist/dom/context-keyboard.js +22 -0
- package/dist/dom/elements.d.ts +1 -2
- package/dist/dom/elements.js +2 -3
- package/dist/dom/latex-panel.d.ts +10 -0
- package/dist/dom/latex-panel.js +59 -0
- package/dist/dom/matrix-selection.d.ts +11 -0
- package/dist/dom/matrix-selection.js +30 -0
- package/dist/dom/menu-position.d.ts +17 -2
- package/dist/dom/menu-position.js +129 -16
- package/dist/dom/presentation-controls.d.ts +4 -0
- package/dist/dom/presentation-controls.js +56 -0
- package/dist/dom/quick-panel.d.ts +12 -0
- package/dist/dom/quick-panel.js +102 -0
- package/dist/dom/selection.d.ts +29 -0
- package/dist/dom/selection.js +53 -0
- package/dist/dom/symbol-panel.d.ts +9 -0
- package/dist/dom/symbol-panel.js +146 -0
- package/dist/dom/theme.d.ts +6 -0
- package/dist/dom/theme.js +68 -0
- package/dist/dom/toolbar-catalog.d.ts +10 -0
- package/dist/dom/toolbar-catalog.js +35 -0
- package/dist/dom/toolbar.d.ts +13 -2
- package/dist/dom/toolbar.js +295 -28
- package/dist/dom.d.ts +9 -1
- package/dist/dom.js +682 -151
- package/dist/editor-labels.d.ts +0 -1
- package/dist/editor-labels.js +0 -1
- package/dist/enter-policy.d.ts +0 -1
- package/dist/enter-policy.js +0 -1
- package/dist/fences.d.ts +0 -1
- package/dist/fences.js +0 -1
- package/dist/i18n.d.ts +0 -1
- package/dist/i18n.js +0 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.js +4 -1
- package/dist/latex-insertion.d.ts +12 -0
- package/dist/latex-insertion.js +26 -0
- package/dist/latex-paste-panel.d.ts +3 -0
- package/dist/latex-paste-panel.js +18 -0
- package/dist/latex.d.ts +0 -1
- package/dist/latex.js +11 -1
- package/dist/lines.d.ts +0 -1
- package/dist/lines.js +0 -1
- package/dist/locales/en.js +39 -1
- package/dist/locales/en.json +39 -1
- package/dist/locales/ko.js +39 -1
- package/dist/locales/ko.json +39 -1
- package/dist/math-editor-toolbar.d.ts +4 -2
- package/dist/math-editor-toolbar.js +3 -4
- package/dist/math-editor.d.ts +7 -2
- package/dist/math-editor.js +661 -308
- package/dist/math-layout.d.ts +12 -0
- package/dist/math-layout.js +59 -0
- package/dist/math-spacing.d.ts +13 -0
- package/dist/math-spacing.js +87 -0
- package/dist/matrix-range.d.ts +40 -0
- package/dist/matrix-range.js +242 -0
- package/dist/matrix.d.ts +0 -1
- package/dist/matrix.js +0 -1
- package/dist/model.d.ts +4 -1
- package/dist/model.js +49 -5
- package/dist/outputs.d.ts +0 -1
- package/dist/outputs.js +0 -1
- package/dist/preferences.d.ts +24 -0
- package/dist/preferences.js +66 -0
- package/dist/presentation-controls.d.ts +10 -0
- package/dist/presentation-controls.js +10 -0
- package/dist/presentation.d.ts +13 -0
- package/dist/presentation.js +86 -0
- package/dist/quick-panel.d.ts +2 -0
- package/dist/quick-panel.js +17 -0
- package/dist/range.d.ts +2 -1
- package/dist/range.js +11 -1
- package/dist/react.d.ts +0 -1
- package/dist/react.js +0 -1
- package/dist/root-transform.d.ts +19 -0
- package/dist/root-transform.js +69 -0
- package/dist/session.d.ts +31 -2
- package/dist/session.js +108 -7
- package/dist/solid.d.ts +0 -1
- package/dist/solid.js +0 -1
- package/dist/suggestions.d.ts +13 -1
- package/dist/suggestions.js +153 -12
- package/dist/svelte.d.ts +0 -1
- package/dist/svelte.js +0 -1
- package/dist/symbol-browser.d.ts +0 -1
- package/dist/symbol-browser.js +0 -1
- package/dist/symbols.d.ts +0 -1
- package/dist/symbols.js +0 -1
- package/dist/templates.d.ts +0 -1
- package/dist/templates.js +0 -1
- package/dist/tokens.d.ts +0 -1
- package/dist/tokens.js +0 -1
- package/dist/vertical-navigation.d.ts +15 -0
- package/dist/vertical-navigation.js +145 -0
- package/dist/vue.d.ts +0 -1
- package/dist/vue.js +0 -1
- package/dist/web-component.d.ts +0 -1
- package/dist/web-component.js +9 -2
- package/package.json +11 -3
- package/src/fonts/KaTeX_Math-Italic.woff2 +0 -0
- package/src/fonts/KaTeX_Size1-Regular.woff2 +0 -0
- package/src/fonts/README.md +18 -0
- package/src/shapes/README.md +21 -0
- package/src/shapes/parenthesis-bottom.svg +1 -0
- package/src/shapes/parenthesis-top.svg +1 -0
- package/src/shapes/parenthesis.svg +1 -0
- package/src/shapes/radical.svg +1 -0
- package/src/style.css +949 -173
- package/dist/core.d.ts.map +0 -1
- package/dist/core.js.map +0 -1
- package/dist/document-codec.d.ts.map +0 -1
- package/dist/document-codec.js.map +0 -1
- package/dist/dom/elements.d.ts.map +0 -1
- package/dist/dom/elements.js.map +0 -1
- package/dist/dom/menu-position.d.ts.map +0 -1
- package/dist/dom/menu-position.js.map +0 -1
- package/dist/dom/toolbar.d.ts.map +0 -1
- package/dist/dom/toolbar.js.map +0 -1
- package/dist/dom.d.ts.map +0 -1
- package/dist/dom.js.map +0 -1
- package/dist/editor-labels.d.ts.map +0 -1
- package/dist/editor-labels.js.map +0 -1
- package/dist/enter-policy.d.ts.map +0 -1
- package/dist/enter-policy.js.map +0 -1
- package/dist/fences.d.ts.map +0 -1
- package/dist/fences.js.map +0 -1
- package/dist/i18n.d.ts.map +0 -1
- package/dist/i18n.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/latex.d.ts.map +0 -1
- package/dist/latex.js.map +0 -1
- package/dist/lines.d.ts.map +0 -1
- package/dist/lines.js.map +0 -1
- package/dist/math-editor-toolbar.d.ts.map +0 -1
- package/dist/math-editor-toolbar.js.map +0 -1
- package/dist/math-editor.d.ts.map +0 -1
- package/dist/math-editor.js.map +0 -1
- package/dist/matrix.d.ts.map +0 -1
- package/dist/matrix.js.map +0 -1
- package/dist/model.d.ts.map +0 -1
- package/dist/model.js.map +0 -1
- package/dist/outputs.d.ts.map +0 -1
- package/dist/outputs.js.map +0 -1
- package/dist/range.d.ts.map +0 -1
- package/dist/range.js.map +0 -1
- package/dist/react.d.ts.map +0 -1
- package/dist/react.js.map +0 -1
- package/dist/session.d.ts.map +0 -1
- package/dist/session.js.map +0 -1
- package/dist/solid.d.ts.map +0 -1
- package/dist/solid.js.map +0 -1
- package/dist/suggestions.d.ts.map +0 -1
- package/dist/suggestions.js.map +0 -1
- package/dist/svelte.d.ts.map +0 -1
- package/dist/svelte.js.map +0 -1
- package/dist/symbol-browser.d.ts.map +0 -1
- package/dist/symbol-browser.js.map +0 -1
- package/dist/symbols.d.ts.map +0 -1
- package/dist/symbols.js.map +0 -1
- package/dist/templates.d.ts.map +0 -1
- package/dist/templates.js.map +0 -1
- package/dist/tokens.d.ts.map +0 -1
- package/dist/tokens.js.map +0 -1
- package/dist/vue.d.ts.map +0 -1
- package/dist/vue.js.map +0 -1
- package/dist/web-component.d.ts.map +0 -1
- package/dist/web-component.js.map +0 -1
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import { elementFactory } from './elements.js';
|
|
2
|
+
import { findToolbarSymbols } from './toolbar-catalog.js';
|
|
3
|
+
import { translate, mathLocaleDirection } from '../i18n.js';
|
|
4
|
+
import { mathSymbols } from '../symbols.js';
|
|
5
|
+
/** Native, nonmodal symbol discovery. The panel stays inside its toolbar's containment boundary. */
|
|
6
|
+
export function mountSymbolPanel(host, options) {
|
|
7
|
+
const doc = host.ownerDocument;
|
|
8
|
+
const element = elementFactory(doc);
|
|
9
|
+
const t = (key) => translate(options.locale, key);
|
|
10
|
+
const panel = element('section', 'me-symbol-browser me-dom-symbol-browser');
|
|
11
|
+
panel.setAttribute('aria-label', t('symbols.title'));
|
|
12
|
+
panel.dir = mathLocaleDirection(options.locale);
|
|
13
|
+
const heading = element('div', 'me-symbol-browser-heading');
|
|
14
|
+
const title = element('strong', '', t('symbols.title'));
|
|
15
|
+
const count = element('small');
|
|
16
|
+
count.setAttribute('role', 'status');
|
|
17
|
+
title.append(' ', count);
|
|
18
|
+
const close = element('button', '', t('common.close'));
|
|
19
|
+
close.type = 'button';
|
|
20
|
+
close.onclick = options.onClose;
|
|
21
|
+
heading.append(title, close);
|
|
22
|
+
const label = element('label', 'me-symbol-search', t('symbols.search'));
|
|
23
|
+
const search = element('input');
|
|
24
|
+
search.type = 'search';
|
|
25
|
+
search.placeholder = t('symbols.searchPlaceholder');
|
|
26
|
+
label.append(search);
|
|
27
|
+
const help = element('p', 'me-symbol-help', t('symbols.help'));
|
|
28
|
+
const grid = element('div', 'me-symbol-grid');
|
|
29
|
+
grid.setAttribute('role', 'group');
|
|
30
|
+
grid.setAttribute('aria-label', t('symbols.title'));
|
|
31
|
+
const empty = element('p', '', t('symbols.noMatches'));
|
|
32
|
+
empty.setAttribute('role', 'status');
|
|
33
|
+
panel.append(heading, label, help, grid, empty);
|
|
34
|
+
host.append(panel);
|
|
35
|
+
let composing = false;
|
|
36
|
+
let destroyed = false;
|
|
37
|
+
let active = 0;
|
|
38
|
+
let buttons = [];
|
|
39
|
+
const focusResult = (index) => {
|
|
40
|
+
if (!buttons.length)
|
|
41
|
+
return;
|
|
42
|
+
active = Math.max(0, Math.min(index, buttons.length - 1));
|
|
43
|
+
buttons.forEach((button, at) => {
|
|
44
|
+
button.tabIndex = at === active ? 0 : -1;
|
|
45
|
+
});
|
|
46
|
+
buttons[active].focus();
|
|
47
|
+
buttons[active].scrollIntoView({ block: 'nearest', inline: 'nearest' });
|
|
48
|
+
};
|
|
49
|
+
const draw = () => {
|
|
50
|
+
const matches = findToolbarSymbols(search.value, options.locale);
|
|
51
|
+
active = 0;
|
|
52
|
+
buttons = matches.map(([glyph, key]) => {
|
|
53
|
+
const button = element('button');
|
|
54
|
+
button.type = 'button';
|
|
55
|
+
button.dataset.symbol = glyph;
|
|
56
|
+
button.setAttribute('aria-label', `${glyph} — ${t(key)}`);
|
|
57
|
+
button.title = `${translate('en', key)} / ${translate('ko', key)}`;
|
|
58
|
+
const symbol = element('span', 'me-symbol-glyph', glyph);
|
|
59
|
+
symbol.setAttribute('aria-hidden', 'true');
|
|
60
|
+
button.append(symbol, element('span', '', t(key)));
|
|
61
|
+
button.onclick = () => {
|
|
62
|
+
if (!composing && !destroyed)
|
|
63
|
+
options.onInsert(glyph);
|
|
64
|
+
};
|
|
65
|
+
button.onfocus = () => {
|
|
66
|
+
active = buttons.indexOf(button);
|
|
67
|
+
buttons.forEach((item, index) => {
|
|
68
|
+
item.tabIndex = index === active ? 0 : -1;
|
|
69
|
+
});
|
|
70
|
+
};
|
|
71
|
+
return button;
|
|
72
|
+
});
|
|
73
|
+
buttons.forEach((button, index) => {
|
|
74
|
+
button.tabIndex = index === 0 ? 0 : -1;
|
|
75
|
+
});
|
|
76
|
+
grid.replaceChildren(...buttons);
|
|
77
|
+
count.textContent = `${matches.length} / ${mathSymbols.length}`;
|
|
78
|
+
empty.hidden = matches.length !== 0;
|
|
79
|
+
};
|
|
80
|
+
search.oninput = draw;
|
|
81
|
+
search.addEventListener('compositionstart', () => {
|
|
82
|
+
composing = true;
|
|
83
|
+
});
|
|
84
|
+
search.addEventListener('compositionend', () => {
|
|
85
|
+
composing = false;
|
|
86
|
+
draw();
|
|
87
|
+
});
|
|
88
|
+
panel.addEventListener('keydown', (event) => {
|
|
89
|
+
event.stopPropagation();
|
|
90
|
+
if (event.isComposing || composing || event.ctrlKey || event.metaKey || event.altKey)
|
|
91
|
+
return;
|
|
92
|
+
if (event.key === 'Escape') {
|
|
93
|
+
event.preventDefault();
|
|
94
|
+
options.onClose();
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
if (event.target === search) {
|
|
98
|
+
if (event.key === 'ArrowDown' || event.key === 'ArrowUp') {
|
|
99
|
+
event.preventDefault();
|
|
100
|
+
focusResult(event.key === 'ArrowDown' ? 0 : buttons.length - 1);
|
|
101
|
+
}
|
|
102
|
+
else if (event.key === 'Enter' && buttons.length) {
|
|
103
|
+
event.preventDefault();
|
|
104
|
+
buttons[0].click();
|
|
105
|
+
}
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
if (!buttons.includes(event.target))
|
|
109
|
+
return;
|
|
110
|
+
const firstTop = buttons[0].getBoundingClientRect().top;
|
|
111
|
+
const nextRow = buttons.findIndex((button) => Math.abs(button.getBoundingClientRect().top - firstTop) > 2);
|
|
112
|
+
const columns = nextRow < 0 ? buttons.length : Math.max(1, nextRow);
|
|
113
|
+
const rtl = panel.dir === 'rtl';
|
|
114
|
+
const next = event.key === 'ArrowDown'
|
|
115
|
+
? active + columns
|
|
116
|
+
: event.key === 'ArrowUp'
|
|
117
|
+
? active - columns
|
|
118
|
+
: event.key === 'ArrowRight'
|
|
119
|
+
? active + (rtl ? -1 : 1)
|
|
120
|
+
: event.key === 'ArrowLeft'
|
|
121
|
+
? active + (rtl ? 1 : -1)
|
|
122
|
+
: event.key === 'Home'
|
|
123
|
+
? 0
|
|
124
|
+
: event.key === 'End'
|
|
125
|
+
? buttons.length - 1
|
|
126
|
+
: undefined;
|
|
127
|
+
if (next !== undefined) {
|
|
128
|
+
event.preventDefault();
|
|
129
|
+
if (event.key === 'ArrowUp' && next < 0)
|
|
130
|
+
search.focus();
|
|
131
|
+
else
|
|
132
|
+
focusResult(next);
|
|
133
|
+
}
|
|
134
|
+
});
|
|
135
|
+
for (const name of ['keyup', 'beforeinput', 'input', 'copy', 'cut', 'paste']) {
|
|
136
|
+
panel.addEventListener(name, (event) => event.stopPropagation());
|
|
137
|
+
}
|
|
138
|
+
draw();
|
|
139
|
+
search.focus();
|
|
140
|
+
return {
|
|
141
|
+
destroy() {
|
|
142
|
+
destroyed = true;
|
|
143
|
+
panel.remove();
|
|
144
|
+
},
|
|
145
|
+
};
|
|
146
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/** Copy resolved values, including host var() references, without copying layout or content.
|
|
2
|
+
* Explicit `initial` blocks unrelated tokens inherited from the portal container. */
|
|
3
|
+
export declare function syncMathTheme(source: HTMLElement, target: HTMLElement): void;
|
|
4
|
+
/** Follow scoped class/style/theme switches without polling or observing formula mutations.
|
|
5
|
+
* The observer and frame belong to the editor's document, including iframe hosts. */
|
|
6
|
+
export declare function followMathTheme(source: HTMLElement, target: HTMLElement): () => void;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/** Public presentation tokens, copied to menus that live outside the editor's DOM tree.
|
|
2
|
+
* Keep this list aligned with STYLING.md. Internal slot/glyph variables stay local. */
|
|
3
|
+
const themeProperties = [
|
|
4
|
+
'--me-font-size',
|
|
5
|
+
'--me-ui-font-family',
|
|
6
|
+
'--me-text',
|
|
7
|
+
'--me-muted',
|
|
8
|
+
'--me-accent',
|
|
9
|
+
'--me-line',
|
|
10
|
+
'--me-background',
|
|
11
|
+
'--me-panel-background',
|
|
12
|
+
'--me-toolbar-background',
|
|
13
|
+
'--me-subtle-background',
|
|
14
|
+
'--me-hover-background',
|
|
15
|
+
'--me-active-background',
|
|
16
|
+
'--me-variable',
|
|
17
|
+
'--me-number',
|
|
18
|
+
'--me-symbol',
|
|
19
|
+
'--me-function',
|
|
20
|
+
'--me-input-background',
|
|
21
|
+
'--me-input-focus-background',
|
|
22
|
+
'--me-selection-background',
|
|
23
|
+
'--me-selection-color',
|
|
24
|
+
'--me-focus-color',
|
|
25
|
+
'--me-radius',
|
|
26
|
+
'--me-control-radius',
|
|
27
|
+
'--me-menu-shadow',
|
|
28
|
+
'--me-menu-z-index',
|
|
29
|
+
];
|
|
30
|
+
/** Copy resolved values, including host var() references, without copying layout or content.
|
|
31
|
+
* Explicit `initial` blocks unrelated tokens inherited from the portal container. */
|
|
32
|
+
export function syncMathTheme(source, target) {
|
|
33
|
+
const computed = source.ownerDocument.defaultView.getComputedStyle(source);
|
|
34
|
+
for (const property of themeProperties) {
|
|
35
|
+
const value = computed.getPropertyValue(property).trim() || 'initial';
|
|
36
|
+
if (target.style.getPropertyValue(property) !== value)
|
|
37
|
+
target.style.setProperty(property, value);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
/** Follow scoped class/style/theme switches without polling or observing formula mutations.
|
|
41
|
+
* The observer and frame belong to the editor's document, including iframe hosts. */
|
|
42
|
+
export function followMathTheme(source, target) {
|
|
43
|
+
const win = source.ownerDocument.defaultView;
|
|
44
|
+
let frame;
|
|
45
|
+
const refresh = () => {
|
|
46
|
+
if (frame !== undefined)
|
|
47
|
+
return;
|
|
48
|
+
frame = win.requestAnimationFrame(() => {
|
|
49
|
+
frame = undefined;
|
|
50
|
+
syncMathTheme(source, target);
|
|
51
|
+
});
|
|
52
|
+
};
|
|
53
|
+
const observer = new win.MutationObserver(refresh);
|
|
54
|
+
for (let ancestor = source; ancestor; ancestor = ancestor.parentElement)
|
|
55
|
+
observer.observe(ancestor, { attributes: true });
|
|
56
|
+
// CSS media queries can change a theme without changing an ancestor attribute.
|
|
57
|
+
const colorScheme = win.matchMedia('(prefers-color-scheme: dark)');
|
|
58
|
+
colorScheme.addEventListener('change', refresh);
|
|
59
|
+
win.addEventListener('resize', refresh);
|
|
60
|
+
syncMathTheme(source, target);
|
|
61
|
+
return () => {
|
|
62
|
+
observer.disconnect();
|
|
63
|
+
colorScheme.removeEventListener('change', refresh);
|
|
64
|
+
win.removeEventListener('resize', refresh);
|
|
65
|
+
if (frame !== undefined)
|
|
66
|
+
win.cancelAnimationFrame(frame);
|
|
67
|
+
};
|
|
68
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type MathLocale } from '../i18n.js';
|
|
2
|
+
import type { StructureKind } from '../model.js';
|
|
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"])[];
|
|
5
|
+
/** Templates must not offer a back door around a host's allowed structure kinds. */
|
|
6
|
+
export declare function toolbarTemplates(kinds?: readonly StructureKind[]): import("../templates.js").MathTemplate[];
|
|
7
|
+
export declare function parseToolbarMatrixPreset(value: string): {
|
|
8
|
+
size: number;
|
|
9
|
+
identity: boolean;
|
|
10
|
+
} | undefined;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { mathLocaleAliases, translate } from '../i18n.js';
|
|
2
|
+
import { findSuggestions } from '../suggestions.js';
|
|
3
|
+
import { mathSymbols } from '../symbols.js';
|
|
4
|
+
import { createTemplate, mathTemplates } from '../templates.js';
|
|
5
|
+
/** Full discovery search retains the symbol catalog and suggestion engine's ranking. */
|
|
6
|
+
export function findToolbarSymbols(query, locale) {
|
|
7
|
+
const needle = query.trim().normalize('NFC').toLowerCase();
|
|
8
|
+
if (!needle)
|
|
9
|
+
return [...mathSymbols];
|
|
10
|
+
const matches = mathSymbols.filter(([glyph, label, aliases, triggers, latex]) => [
|
|
11
|
+
glyph,
|
|
12
|
+
translate('en', label),
|
|
13
|
+
translate('ko', label),
|
|
14
|
+
translate(locale, label),
|
|
15
|
+
...mathLocaleAliases(locale, `symbol-${glyph}`),
|
|
16
|
+
aliases,
|
|
17
|
+
triggers,
|
|
18
|
+
latex,
|
|
19
|
+
].some((value) => value.normalize('NFC').toLowerCase().includes(needle)));
|
|
20
|
+
const ranked = findSuggestions(query.trim(), query.trim().length, locale).candidates.filter((item) => item.value !== undefined);
|
|
21
|
+
const order = new Map(ranked.map((item, index) => [item.value, index]));
|
|
22
|
+
return matches.sort((a, b) => (order.get(a[0]) ?? Infinity) - (order.get(b[0]) ?? Infinity));
|
|
23
|
+
}
|
|
24
|
+
/** Templates must not offer a back door around a host's allowed structure kinds. */
|
|
25
|
+
export function toolbarTemplates(kinds) {
|
|
26
|
+
if (!kinds)
|
|
27
|
+
return mathTemplates;
|
|
28
|
+
const allowed = new Set(kinds);
|
|
29
|
+
const accepts = (row) => row.children.every((node) => node.type === 'text' || (allowed.has(node.type) && node.slots.every(accepts)));
|
|
30
|
+
return mathTemplates.filter((template) => createTemplate(template.id).rows.every(accepts));
|
|
31
|
+
}
|
|
32
|
+
export function parseToolbarMatrixPreset(value) {
|
|
33
|
+
const match = /^(identity-)?([234])$/.exec(value);
|
|
34
|
+
return match ? { size: Number(match[2]), identity: !!match[1] } : undefined;
|
|
35
|
+
}
|
package/dist/dom/toolbar.d.ts
CHANGED
|
@@ -1,13 +1,24 @@
|
|
|
1
|
+
import { type MathLocale } from '../i18n.js';
|
|
1
2
|
import type { MathSession } from '../session.js';
|
|
2
3
|
import type { StructureKind } from '../model.js';
|
|
3
4
|
export interface MathToolbarOptions {
|
|
4
5
|
kinds?: readonly StructureKind[];
|
|
5
6
|
/** Visible structure buttons before More; defaults to 8. */
|
|
6
7
|
maxItems?: number;
|
|
8
|
+
/** Labels while no editor is active; an attached session supplies its own locale. */
|
|
9
|
+
locale?: MathLocale;
|
|
7
10
|
onExecute?: () => void;
|
|
11
|
+
onPasteLatex?: () => void;
|
|
12
|
+
/** Close another utility owned by the editing surface before opening a toolbar panel. */
|
|
13
|
+
onOpenPanel?: () => void;
|
|
8
14
|
}
|
|
9
15
|
/** Independently mounted toolbar; the host may instead build any UI around session.execute(). */
|
|
10
|
-
export declare function mountMathToolbar(host: HTMLElement, session: MathSession, options?: MathToolbarOptions): {
|
|
16
|
+
export declare function mountMathToolbar(host: HTMLElement, session: MathSession | null, options?: MathToolbarOptions): {
|
|
17
|
+
/** Close discovery/paste panels without changing the formula or its selection. */
|
|
18
|
+
closePanels: () => void;
|
|
19
|
+
/** Reuse one toolbar for multiple editors without retaining previous subscriptions. */
|
|
20
|
+
setSession(next: MathSession | null): void;
|
|
21
|
+
/** Disable mutation controls while the attached native editor is composing. */
|
|
22
|
+
setDisabled(next: boolean): void;
|
|
11
23
|
destroy(): void;
|
|
12
24
|
};
|
|
13
|
-
//# sourceMappingURL=toolbar.d.ts.map
|