@barocss/math-editor 0.4.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.
Files changed (76) hide show
  1. package/API-SESSION.md +35 -1
  2. package/API-WEB-COMPONENT.md +2 -0
  3. package/CHANGELOG.md +109 -0
  4. package/CLIPBOARD.md +54 -0
  5. package/EDITING-SCENARIOS.md +209 -0
  6. package/GETTING-STARTED.md +54 -0
  7. package/IMPLEMENTATION.md +105 -0
  8. package/KEYBOARD.md +41 -0
  9. package/LATEX-GUIDE.md +52 -2
  10. package/LATEX-MODEL.md +12 -0
  11. package/LATEX-SCOPE.md +10 -1
  12. package/README.md +119 -23
  13. package/RELEASING.md +95 -10
  14. package/RENDERING-TESTS.md +79 -0
  15. package/ROADMAP.md +238 -6
  16. package/STYLING.md +28 -1
  17. package/TEXT-EDITORS.md +157 -0
  18. package/VALIDATION.md +433 -0
  19. package/dist/context-tools.d.ts +21 -0
  20. package/dist/context-tools.js +37 -0
  21. package/dist/dom/caret-geometry.js +1 -1
  22. package/dist/dom/context-keyboard.d.ts +2 -0
  23. package/dist/dom/context-keyboard.js +22 -0
  24. package/dist/dom/help.d.ts +5 -0
  25. package/dist/dom/help.js +104 -0
  26. package/dist/dom/menu-position.d.ts +3 -0
  27. package/dist/dom/menu-position.js +49 -4
  28. package/dist/dom/readable-layout.d.ts +3 -0
  29. package/dist/dom/readable-layout.js +52 -0
  30. package/dist/dom/toolbar-catalog.d.ts +1 -1
  31. package/dist/dom/toolbar.d.ts +2 -0
  32. package/dist/dom/toolbar.js +8 -1
  33. package/dist/dom.d.ts +13 -1
  34. package/dist/dom.js +323 -51
  35. package/dist/enter-policy.js +1 -1
  36. package/dist/latex.js +11 -0
  37. package/dist/lines.d.ts +2 -0
  38. package/dist/lines.js +15 -0
  39. package/dist/locales/en.js +33 -3
  40. package/dist/locales/en.json +33 -3
  41. package/dist/locales/ko.js +33 -3
  42. package/dist/locales/ko.json +33 -3
  43. package/dist/math-editor-toolbar.js +2 -1
  44. package/dist/math-editor.d.ts +4 -1
  45. package/dist/math-editor.js +506 -296
  46. package/dist/math-layout.d.ts +12 -0
  47. package/dist/math-layout.js +59 -0
  48. package/dist/math-spacing.d.ts +13 -0
  49. package/dist/math-spacing.js +87 -0
  50. package/dist/model.d.ts +6 -0
  51. package/dist/model.js +72 -5
  52. package/dist/range.d.ts +10 -2
  53. package/dist/range.js +31 -6
  54. package/dist/root-transform.d.ts +19 -0
  55. package/dist/root-transform.js +69 -0
  56. package/dist/selection-shortcuts.d.ts +13 -0
  57. package/dist/selection-shortcuts.js +35 -0
  58. package/dist/session.d.ts +1 -0
  59. package/dist/session.js +1 -1
  60. package/dist/suggestions.d.ts +9 -0
  61. package/dist/suggestions.js +53 -0
  62. package/dist/symbols.d.ts +1 -1
  63. package/dist/symbols.js +1 -0
  64. package/dist/vertical-navigation.d.ts +5 -0
  65. package/dist/vertical-navigation.js +33 -0
  66. package/dist/web-component.js +9 -1
  67. package/package.json +11 -3
  68. package/src/fonts/KaTeX_Math-Italic.woff2 +0 -0
  69. package/src/fonts/KaTeX_Size1-Regular.woff2 +0 -0
  70. package/src/fonts/README.md +18 -0
  71. package/src/shapes/README.md +21 -0
  72. package/src/shapes/parenthesis-bottom.svg +1 -0
  73. package/src/shapes/parenthesis-top.svg +1 -0
  74. package/src/shapes/parenthesis.svg +1 -0
  75. package/src/shapes/radical.svg +1 -0
  76. package/src/style.css +882 -61
package/dist/lines.js CHANGED
@@ -39,6 +39,21 @@ export function joinPreviousLine(state) {
39
39
  delete document.additionalLines;
40
40
  return { document, caret: { id: tail.id, start: offset, end: offset } };
41
41
  }
42
+ /** Delete at the end of a top-level line joins the following line without moving the caret. */
43
+ export function joinNextLine(state) {
44
+ if (state.caret.start !== state.caret.end)
45
+ return state;
46
+ const lines = documentRows(state.document);
47
+ const index = lines.findIndex((line) => line.children.at(-1)?.id === state.caret.id);
48
+ const tail = lines[index]?.children.at(-1);
49
+ const head = lines[index + 1]?.children[0];
50
+ if (index < 0 ||
51
+ tail?.type !== 'text' ||
52
+ head?.type !== 'text' ||
53
+ state.caret.end !== tail.text.length)
54
+ return state;
55
+ return joinPreviousLine({ ...state, caret: { id: head.id, start: 0, end: 0 } });
56
+ }
42
57
  export function moveLineVertical(state, direction) {
43
58
  const lines = documentRows(state.document);
44
59
  const index = lines.findIndex((line) => line.children.some((node) => node.type === 'text' && node.id === state.caret.id));
@@ -92,7 +92,8 @@ export default {
92
92
  "grid.addColumn": "Add column",
93
93
  "grid.deleteColumn": "Delete column",
94
94
  "grid.deleteRowShortcut": "Delete row: Alt(⌥)+Shift+↑",
95
- "grid.deleteColumnShortcut": "Delete column: Alt(⌥)+Shift+←",
95
+ "grid.deleteColumnShortcut": "Delete column: Alt(⌥)+Shift+Backspace",
96
+ "clipboard.invalid": "The copied formula data is invalid. The formula was not changed.",
96
97
  "clipboard.cut": "Selected math cut.",
97
98
  "clipboard.copied": "Selected math copied as structure and LaTeX.",
98
99
  "clipboard.pasted": "Pasted.",
@@ -101,13 +102,15 @@ export default {
101
102
  "grid.selectionHint": "Structure selected · Backspace/Delete to remove · Esc to cancel",
102
103
  "selection.toolbar": "Wrap selected math",
103
104
  "selection.highlighted": "Wrap highlighted range",
105
+ "selection.asNumerator": "Use as numerator",
106
+ "selection.asDenominator": "Use as denominator",
104
107
  "selection.singleRowRequired": "Select a range within one row.",
105
108
  "suggestion.label": "Math suggestions",
106
109
  "suggestion.composing": "Composing · Choose after committing",
107
110
  "suggestion.keyboardHint": "↑ ↓ to choose · Enter to apply",
108
111
  "suggestion.imeHint": "Suggestion preview · Enter and arrows are reserved for the IME",
109
112
  "suggestion.keepSource": "Keep typing, or use Space / Esc to keep the source",
110
- "matrix.keyboardHint": "Shift+Enter add row · Shift+Space add column · Alt(⌥)+Shift+↑ delete row · Alt(⌥)+Shift+← delete column",
113
+ "matrix.keyboardHint": "Shift+Enter add row · Shift+Space add column · Alt(⌥)+Shift+↑ delete row · Alt(⌥)+Shift+Backspace delete column",
111
114
  "aligned.inputHint": "Left: left-hand side · Right: start with =",
112
115
  "cases.inputHint": "Left: expression · Right: condition",
113
116
  "grid.keyboardHint": "Enter add row · Alt(⌥)+Shift+↑ delete row",
@@ -155,6 +158,7 @@ export default {
155
158
  "template.detail": "Editable math template",
156
159
  "template.quadratic": "Quadratic formula",
157
160
  "template.pythagorean": "Pythagorean theorem",
161
+ "symbol.prime": "Prime",
158
162
  "symbol.degree": "Degree",
159
163
  "symbol.angle": "Angle",
160
164
  "symbol.plus": "Plus",
@@ -341,7 +345,33 @@ export default {
341
345
  "presentation.display": "Display size",
342
346
  "presentation.text": "Text size",
343
347
  "presentation.aboveBelow": "Above and below",
344
- "presentation.side": "Beside operator"
348
+ "presentation.side": "Beside operator",
349
+ "suggestion.transform": "Change to {kind}",
350
+ "suggestion.transformRootDetail": "Keep the radicand. A square root requires an empty index or 2.",
351
+ "context.label": "Structure tools",
352
+ "context.current": "Editing: {kind}",
353
+ "context.editIndex": "Edit index",
354
+ "context.keyboardHint": "F6: tools · Esc: back to input",
355
+ "context.squareIndexRequired": "Change the index to 2 or clear it to use a square root.",
356
+ "context.root": "Square root",
357
+ "context.indexedRoot": "Indexed root",
358
+ "context.fenceKeyboardHint": "F6: tools · ← →: choose · Enter: apply · Esc: back to input",
359
+ "suggestion.transformFence": "Change brackets: {kind}",
360
+ "suggestion.transformFenceDetail": "Keep the enclosed formula and cursor position",
361
+ "help.title": "Keyboard & clipboard help",
362
+ "help.intro": "Keep typing with these controls. Close help to return to your formula.",
363
+ "help.units": "Move by a variable, number or whole structure. Add Shift to extend selection. Inside a slot, reach the current token edge before leaving the structure.",
364
+ "help.slots": "Move to the next or previous editable slot.",
365
+ "help.select": "Extend the formula selection.",
366
+ "help.wrap": "With math selected: wrap in brackets, absolute value, a fraction, a power or a subscript.",
367
+ "help.suggestions": "Open suggestions and available transformations, even without a toolbar.",
368
+ "help.menu": "Choose a suggestion, apply it, or dismiss the menu.",
369
+ "help.clipboard": "Copy, cut or paste. Editor data preserves structure when the browser retains it. Ordinary text pastes literally.",
370
+ "help.latex": "Open Paste as LaTeX. Paste the source, then Ctrl/Cmd+Enter to insert. Invalid input leaves the formula unchanged.",
371
+ "help.history": "Undo or redo an edit.",
372
+ "help.lines": "Enter follows the host/mode policy. Shift+Enter adds a grid row or a block line. Inline mode never adds a top-level formula line.",
373
+ "help.open": "Open this help while the formula has focus.",
374
+ "help.platform": "Cmd on macOS, Ctrl on Windows/Linux. Alt is Option on macOS. Some keyboards require Fn+F1. Host or OS shortcuts can take precedence."
345
375
  },
346
376
  "aliases": {}
347
377
  };
@@ -91,7 +91,8 @@
91
91
  "grid.addColumn": "Add column",
92
92
  "grid.deleteColumn": "Delete column",
93
93
  "grid.deleteRowShortcut": "Delete row: Alt(⌥)+Shift+↑",
94
- "grid.deleteColumnShortcut": "Delete column: Alt(⌥)+Shift+←",
94
+ "grid.deleteColumnShortcut": "Delete column: Alt(⌥)+Shift+Backspace",
95
+ "clipboard.invalid": "The copied formula data is invalid. The formula was not changed.",
95
96
  "clipboard.cut": "Selected math cut.",
96
97
  "clipboard.copied": "Selected math copied as structure and LaTeX.",
97
98
  "clipboard.pasted": "Pasted.",
@@ -100,13 +101,15 @@
100
101
  "grid.selectionHint": "Structure selected · Backspace/Delete to remove · Esc to cancel",
101
102
  "selection.toolbar": "Wrap selected math",
102
103
  "selection.highlighted": "Wrap highlighted range",
104
+ "selection.asNumerator": "Use as numerator",
105
+ "selection.asDenominator": "Use as denominator",
103
106
  "selection.singleRowRequired": "Select a range within one row.",
104
107
  "suggestion.label": "Math suggestions",
105
108
  "suggestion.composing": "Composing · Choose after committing",
106
109
  "suggestion.keyboardHint": "↑ ↓ to choose · Enter to apply",
107
110
  "suggestion.imeHint": "Suggestion preview · Enter and arrows are reserved for the IME",
108
111
  "suggestion.keepSource": "Keep typing, or use Space / Esc to keep the source",
109
- "matrix.keyboardHint": "Shift+Enter add row · Shift+Space add column · Alt(⌥)+Shift+↑ delete row · Alt(⌥)+Shift+← delete column",
112
+ "matrix.keyboardHint": "Shift+Enter add row · Shift+Space add column · Alt(⌥)+Shift+↑ delete row · Alt(⌥)+Shift+Backspace delete column",
110
113
  "aligned.inputHint": "Left: left-hand side · Right: start with =",
111
114
  "cases.inputHint": "Left: expression · Right: condition",
112
115
  "grid.keyboardHint": "Enter add row · Alt(⌥)+Shift+↑ delete row",
@@ -154,6 +157,7 @@
154
157
  "template.detail": "Editable math template",
155
158
  "template.quadratic": "Quadratic formula",
156
159
  "template.pythagorean": "Pythagorean theorem",
160
+ "symbol.prime": "Prime",
157
161
  "symbol.degree": "Degree",
158
162
  "symbol.angle": "Angle",
159
163
  "symbol.plus": "Plus",
@@ -340,7 +344,33 @@
340
344
  "presentation.display": "Display size",
341
345
  "presentation.text": "Text size",
342
346
  "presentation.aboveBelow": "Above and below",
343
- "presentation.side": "Beside operator"
347
+ "presentation.side": "Beside operator",
348
+ "suggestion.transform": "Change to {kind}",
349
+ "suggestion.transformRootDetail": "Keep the radicand. A square root requires an empty index or 2.",
350
+ "context.label": "Structure tools",
351
+ "context.current": "Editing: {kind}",
352
+ "context.editIndex": "Edit index",
353
+ "context.keyboardHint": "F6: tools · Esc: back to input",
354
+ "context.squareIndexRequired": "Change the index to 2 or clear it to use a square root.",
355
+ "context.root": "Square root",
356
+ "context.indexedRoot": "Indexed root",
357
+ "context.fenceKeyboardHint": "F6: tools · ← →: choose · Enter: apply · Esc: back to input",
358
+ "suggestion.transformFence": "Change brackets: {kind}",
359
+ "suggestion.transformFenceDetail": "Keep the enclosed formula and cursor position",
360
+ "help.title": "Keyboard & clipboard help",
361
+ "help.intro": "Keep typing with these controls. Close help to return to your formula.",
362
+ "help.units": "Move by a variable, number or whole structure. Add Shift to extend selection. Inside a slot, reach the current token edge before leaving the structure.",
363
+ "help.slots": "Move to the next or previous editable slot.",
364
+ "help.select": "Extend the formula selection.",
365
+ "help.wrap": "With math selected: wrap in brackets, absolute value, a fraction, a power or a subscript.",
366
+ "help.suggestions": "Open suggestions and available transformations, even without a toolbar.",
367
+ "help.menu": "Choose a suggestion, apply it, or dismiss the menu.",
368
+ "help.clipboard": "Copy, cut or paste. Editor data preserves structure when the browser retains it. Ordinary text pastes literally.",
369
+ "help.latex": "Open Paste as LaTeX. Paste the source, then Ctrl/Cmd+Enter to insert. Invalid input leaves the formula unchanged.",
370
+ "help.history": "Undo or redo an edit.",
371
+ "help.lines": "Enter follows the host/mode policy. Shift+Enter adds a grid row or a block line. Inline mode never adds a top-level formula line.",
372
+ "help.open": "Open this help while the formula has focus.",
373
+ "help.platform": "Cmd on macOS, Ctrl on Windows/Linux. Alt is Option on macOS. Some keyboards require Fn+F1. Host or OS shortcuts can take precedence."
344
374
  },
345
375
  "aliases": {}
346
376
  }
@@ -92,7 +92,8 @@ export default {
92
92
  "grid.addColumn": "열 추가",
93
93
  "grid.deleteColumn": "열 삭제",
94
94
  "grid.deleteRowShortcut": "행 삭제: Alt(⌥)+Shift+↑",
95
- "grid.deleteColumnShortcut": "열 삭제: Alt(⌥)+Shift+←",
95
+ "grid.deleteColumnShortcut": "열 삭제: Alt(⌥)+Shift+Backspace",
96
+ "clipboard.invalid": "복사한 수식 데이터가 올바르지 않습니다. 기존 수식은 유지됩니다.",
96
97
  "clipboard.cut": "선택한 수식을 잘라냈습니다.",
97
98
  "clipboard.copied": "선택한 수식을 구조와 LaTeX로 복사했습니다.",
98
99
  "clipboard.pasted": "붙여넣었습니다.",
@@ -101,13 +102,15 @@ export default {
101
102
  "grid.selectionHint": "수식 구조 전체 선택 · Backspace/Delete로 삭제 · Esc로 취소",
102
103
  "selection.toolbar": "선택한 수식 감싸기",
103
104
  "selection.highlighted": "강조된 범위 감싸기",
105
+ "selection.asNumerator": "분자로 넣기",
106
+ "selection.asDenominator": "분모로 넣기",
104
107
  "selection.singleRowRequired": "한 줄 안의 범위를 선택해 주세요.",
105
108
  "suggestion.label": "수식 추천",
106
109
  "suggestion.composing": "한글 조합 중 · 확정 후 선택",
107
110
  "suggestion.keyboardHint": "↑ ↓ 선택 · Enter 적용",
108
111
  "suggestion.imeHint": "후보 미리보기 · Enter와 방향키는 한글 입력에 사용됩니다",
109
112
  "suggestion.keepSource": "계속 입력하거나 Space · Esc로 원문 유지",
110
- "matrix.keyboardHint": "Shift+Enter 행 추가 · Shift+Space 열 추가 · Alt(⌥)+Shift+↑ 행 삭제 · Alt(⌥)+Shift+← 열 삭제",
113
+ "matrix.keyboardHint": "Shift+Enter 행 추가 · Shift+Space 열 추가 · Alt(⌥)+Shift+↑ 행 삭제 · Alt(⌥)+Shift+Backspace 열 삭제",
111
114
  "aligned.inputHint": "왼쪽: 좌변 · 오른쪽: =부터 입력",
112
115
  "cases.inputHint": "왼쪽: 식 · 오른쪽: 조건",
113
116
  "grid.keyboardHint": "Enter 행 추가 · Alt(⌥)+Shift+↑ 행 삭제",
@@ -155,6 +158,7 @@ export default {
155
158
  "template.detail": "편집 가능한 수식 템플릿",
156
159
  "template.quadratic": "근의 공식",
157
160
  "template.pythagorean": "피타고라스 정리",
161
+ "symbol.prime": "프라임",
158
162
  "symbol.degree": "도",
159
163
  "symbol.angle": "각 기호",
160
164
  "symbol.plus": "더하기",
@@ -341,7 +345,33 @@ export default {
341
345
  "presentation.display": "큰 표시",
342
346
  "presentation.text": "작은 표시",
343
347
  "presentation.aboveBelow": "위·아래",
344
- "presentation.side": "오른쪽"
348
+ "presentation.side": "오른쪽",
349
+ "suggestion.transform": "{kind}으로 변형",
350
+ "suggestion.transformRootDetail": "루트 안의 수식을 유지합니다. 제곱근으로 바꾸려면 차수가 2이거나 비어 있어야 합니다.",
351
+ "context.label": "구조 편집 도구",
352
+ "context.current": "현재 구조: {kind}",
353
+ "context.editIndex": "차수 편집",
354
+ "context.keyboardHint": "F6: 도구로 이동 · Esc: 입력으로",
355
+ "context.squareIndexRequired": "제곱근으로 바꾸려면 차수를 2로 바꾸거나 비워 주세요.",
356
+ "context.root": "제곱근",
357
+ "context.indexedRoot": "n제곱근",
358
+ "context.fenceKeyboardHint": "F6: 도구로 이동 · ← →: 선택 · Enter: 적용 · Esc: 입력으로",
359
+ "suggestion.transformFence": "괄호 변경: {kind}",
360
+ "suggestion.transformFenceDetail": "안의 수식과 커서 위치를 유지합니다",
361
+ "help.title": "단축키와 복사·붙여넣기",
362
+ "help.intro": "키보드로 수식을 편집하는 방법입니다. 도움말을 닫으면 수식으로 돌아갑니다.",
363
+ "help.units": "변수·숫자·구조 단위로 이동합니다. Shift를 함께 누르면 선택합니다. 구조 안에서는 현재 항목의 경계로 이동한 뒤 구조 밖으로 나갑니다.",
364
+ "help.slots": "다음 또는 이전 입력 칸으로 이동합니다.",
365
+ "help.select": "수식의 선택 범위를 늘립니다.",
366
+ "help.wrap": "수식을 선택한 상태에서 괄호·절대값·분수·지수·아래첨자로 감쌉니다.",
367
+ "help.suggestions": "툴바 없이도 제안 목록과 가능한 변형을 엽니다.",
368
+ "help.menu": "제안을 고르고 적용하거나 목록을 닫습니다.",
369
+ "help.clipboard": "복사·잘라내기·붙여넣기입니다. 브라우저가 편집기 데이터를 유지하면 구조도 보존됩니다. 일반 텍스트는 글자로 붙여넣습니다.",
370
+ "help.latex": "LaTeX 붙여넣기를 엽니다. 원문을 붙여넣고 Ctrl/Cmd+Enter로 삽입합니다. 잘못된 입력은 기존 수식을 바꾸지 않습니다.",
371
+ "help.history": "편집을 실행 취소하거나 다시 실행합니다.",
372
+ "help.lines": "Enter는 모드와 연동 설정을 따릅니다. Shift+Enter는 행렬의 행 또는 블록 수식의 줄을 추가합니다. 인라인 모드는 수식의 바깥 줄을 추가하지 않습니다.",
373
+ "help.open": "수식에 포커스가 있을 때 도움말을 엽니다.",
374
+ "help.platform": "macOS에서는 Cmd, Windows/Linux에서는 Ctrl을 사용합니다. macOS의 Alt는 Option입니다. 일부 키보드는 Fn+F1이 필요합니다. 운영체제나 연동 편집기의 단축키가 우선할 수 있습니다."
345
375
  },
346
376
  "aliases": {
347
377
  "function-sin": ["사인"],
@@ -91,7 +91,8 @@
91
91
  "grid.addColumn": "열 추가",
92
92
  "grid.deleteColumn": "열 삭제",
93
93
  "grid.deleteRowShortcut": "행 삭제: Alt(⌥)+Shift+↑",
94
- "grid.deleteColumnShortcut": "열 삭제: Alt(⌥)+Shift+←",
94
+ "grid.deleteColumnShortcut": "열 삭제: Alt(⌥)+Shift+Backspace",
95
+ "clipboard.invalid": "복사한 수식 데이터가 올바르지 않습니다. 기존 수식은 유지됩니다.",
95
96
  "clipboard.cut": "선택한 수식을 잘라냈습니다.",
96
97
  "clipboard.copied": "선택한 수식을 구조와 LaTeX로 복사했습니다.",
97
98
  "clipboard.pasted": "붙여넣었습니다.",
@@ -100,13 +101,15 @@
100
101
  "grid.selectionHint": "수식 구조 전체 선택 · Backspace/Delete로 삭제 · Esc로 취소",
101
102
  "selection.toolbar": "선택한 수식 감싸기",
102
103
  "selection.highlighted": "강조된 범위 감싸기",
104
+ "selection.asNumerator": "분자로 넣기",
105
+ "selection.asDenominator": "분모로 넣기",
103
106
  "selection.singleRowRequired": "한 줄 안의 범위를 선택해 주세요.",
104
107
  "suggestion.label": "수식 추천",
105
108
  "suggestion.composing": "한글 조합 중 · 확정 후 선택",
106
109
  "suggestion.keyboardHint": "↑ ↓ 선택 · Enter 적용",
107
110
  "suggestion.imeHint": "후보 미리보기 · Enter와 방향키는 한글 입력에 사용됩니다",
108
111
  "suggestion.keepSource": "계속 입력하거나 Space · Esc로 원문 유지",
109
- "matrix.keyboardHint": "Shift+Enter 행 추가 · Shift+Space 열 추가 · Alt(⌥)+Shift+↑ 행 삭제 · Alt(⌥)+Shift+← 열 삭제",
112
+ "matrix.keyboardHint": "Shift+Enter 행 추가 · Shift+Space 열 추가 · Alt(⌥)+Shift+↑ 행 삭제 · Alt(⌥)+Shift+Backspace 열 삭제",
110
113
  "aligned.inputHint": "왼쪽: 좌변 · 오른쪽: =부터 입력",
111
114
  "cases.inputHint": "왼쪽: 식 · 오른쪽: 조건",
112
115
  "grid.keyboardHint": "Enter 행 추가 · Alt(⌥)+Shift+↑ 행 삭제",
@@ -154,6 +157,7 @@
154
157
  "template.detail": "편집 가능한 수식 템플릿",
155
158
  "template.quadratic": "근의 공식",
156
159
  "template.pythagorean": "피타고라스 정리",
160
+ "symbol.prime": "프라임",
157
161
  "symbol.degree": "도",
158
162
  "symbol.angle": "각 기호",
159
163
  "symbol.plus": "더하기",
@@ -340,7 +344,33 @@
340
344
  "presentation.display": "큰 표시",
341
345
  "presentation.text": "작은 표시",
342
346
  "presentation.aboveBelow": "위·아래",
343
- "presentation.side": "오른쪽"
347
+ "presentation.side": "오른쪽",
348
+ "suggestion.transform": "{kind}으로 변형",
349
+ "suggestion.transformRootDetail": "루트 안의 수식을 유지합니다. 제곱근으로 바꾸려면 차수가 2이거나 비어 있어야 합니다.",
350
+ "context.label": "구조 편집 도구",
351
+ "context.current": "현재 구조: {kind}",
352
+ "context.editIndex": "차수 편집",
353
+ "context.keyboardHint": "F6: 도구로 이동 · Esc: 입력으로",
354
+ "context.squareIndexRequired": "제곱근으로 바꾸려면 차수를 2로 바꾸거나 비워 주세요.",
355
+ "context.root": "제곱근",
356
+ "context.indexedRoot": "n제곱근",
357
+ "context.fenceKeyboardHint": "F6: 도구로 이동 · ← →: 선택 · Enter: 적용 · Esc: 입력으로",
358
+ "suggestion.transformFence": "괄호 변경: {kind}",
359
+ "suggestion.transformFenceDetail": "안의 수식과 커서 위치를 유지합니다",
360
+ "help.title": "단축키와 복사·붙여넣기",
361
+ "help.intro": "키보드로 수식을 편집하는 방법입니다. 도움말을 닫으면 수식으로 돌아갑니다.",
362
+ "help.units": "변수·숫자·구조 단위로 이동합니다. Shift를 함께 누르면 선택합니다. 구조 안에서는 현재 항목의 경계로 이동한 뒤 구조 밖으로 나갑니다.",
363
+ "help.slots": "다음 또는 이전 입력 칸으로 이동합니다.",
364
+ "help.select": "수식의 선택 범위를 늘립니다.",
365
+ "help.wrap": "수식을 선택한 상태에서 괄호·절대값·분수·지수·아래첨자로 감쌉니다.",
366
+ "help.suggestions": "툴바 없이도 제안 목록과 가능한 변형을 엽니다.",
367
+ "help.menu": "제안을 고르고 적용하거나 목록을 닫습니다.",
368
+ "help.clipboard": "복사·잘라내기·붙여넣기입니다. 브라우저가 편집기 데이터를 유지하면 구조도 보존됩니다. 일반 텍스트는 글자로 붙여넣습니다.",
369
+ "help.latex": "LaTeX 붙여넣기를 엽니다. 원문을 붙여넣고 Ctrl/Cmd+Enter로 삽입합니다. 잘못된 입력은 기존 수식을 바꾸지 않습니다.",
370
+ "help.history": "편집을 실행 취소하거나 다시 실행합니다.",
371
+ "help.lines": "Enter는 모드와 연동 설정을 따릅니다. Shift+Enter는 행렬의 행 또는 블록 수식의 줄을 추가합니다. 인라인 모드는 수식의 바깥 줄을 추가하지 않습니다.",
372
+ "help.open": "수식에 포커스가 있을 때 도움말을 엽니다.",
373
+ "help.platform": "macOS에서는 Cmd, Windows/Linux에서는 Ctrl을 사용합니다. macOS의 Alt는 Option입니다. 일부 키보드는 Fn+F1이 필요합니다. 운영체제나 연동 편집기의 단축키가 우선할 수 있습니다."
344
374
  },
345
375
  "aliases": {
346
376
  "function-sin": ["사인"],
@@ -1,4 +1,5 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { requestMathHelp } from './dom/help.js';
2
3
  import { useState } from 'react';
3
4
  import { mathStructures } from './suggestions.js';
4
5
  import { wrappingKinds } from './range.js';
@@ -17,7 +18,7 @@ export function MathEditorToolbar({ locale, kinds, maxItems = 8, excludedStructu
17
18
  const visibleCount = Math.max(0, Math.floor(Number.isFinite(maxItems) ? maxItems : 8));
18
19
  const items = mathStructures.filter((s) => s.kind && !excludedStructures.includes(s.kind) && (!kinds || kinds.includes(s.kind)));
19
20
  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: [_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
+ return (_jsxs("div", { className: "me-tools", role: "toolbar", "aria-label": t('toolbar.label'), children: [_jsx("button", { type: "button", "data-math-tool": "help", disabled: composing, title: `${t('help.title')} (F1)`, "aria-keyshortcuts": "F1", onMouseDown: (event) => event.preventDefault(), onClick: (event) => requestMathHelp(event.currentTarget), children: t('help.title') }), (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
22
  const value = event.target.value;
22
23
  onMatrixPreset(value);
23
24
  }, 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] }));
@@ -8,6 +8,7 @@ export interface MathEditorHandle {
8
8
  /** Replace with supported LaTeX as one undoable edit; failures preserve all editor state. */
9
9
  importLatex(source: string): LatexParseResult;
10
10
  pasteLatex(source: string): LatexInsertionResult;
11
+ showHelp(): void;
11
12
  }
12
13
  export interface MathEditorProps {
13
14
  preferences?: MathPreferences;
@@ -28,6 +29,8 @@ export interface MathEditorProps {
28
29
  toolbar?: boolean | readonly StructureKind[];
29
30
  /** Visible structure buttons before More; defaults to 8. */
30
31
  toolbarMaxItems?: number;
32
+ /** Show contextual structure actions below the editing surface. Defaults to true. */
33
+ contextTools?: boolean;
31
34
  /** Host-owned actions rendered at the end of the main toolbar. */
32
35
  toolbarEnd?: ReactNode;
33
36
  showTokenLegend?: boolean;
@@ -43,4 +46,4 @@ export interface MathEditorProps {
43
46
  label?: string;
44
47
  }
45
48
  /** Native text fields own IME and local text selection; the tree owns structural editing. */
46
- export declare function MathEditor({ preferences: suppliedPreferences, 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;
49
+ 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;