@pie-lib/editable-html-tip-tap 2.1.2-next.46 → 2.1.2-next.51
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/lib/components/CharacterPicker.js +41 -16
- package/lib/components/CharacterPicker.js.map +1 -1
- package/lib/extensions/math.js +47 -34
- package/lib/extensions/math.js.map +1 -1
- package/package.json +2 -2
- package/src/components/CharacterPicker.jsx +46 -16
- package/src/components/__tests__/CharacterPicker.test.jsx +10 -1
- package/src/extensions/__tests__/math.test.js +160 -65
- package/src/extensions/math.js +56 -35
|
@@ -90,22 +90,44 @@ function CharacterPicker(_ref2) {
|
|
|
90
90
|
// ref so click-outside always calls the latest close handler.
|
|
91
91
|
(0, _react.useEffect)(function () {
|
|
92
92
|
if (!editor) return;
|
|
93
|
-
|
|
94
|
-
// Calculate position relative to selection
|
|
95
93
|
var editorDOM = editor.options.element;
|
|
96
|
-
var editorRect = editorDOM.getBoundingClientRect();
|
|
97
|
-
var bodyRect = document.body.getBoundingClientRect();
|
|
98
|
-
var from = editor.state.selection.from;
|
|
99
|
-
var start = editor.view.coordsAtPos(from);
|
|
100
|
-
var top = editorRect.top + Math.abs(bodyRect.top) + editorRect.height + 60;
|
|
101
|
-
if (editorRect.y > containerRef.current.offsetHeight) {
|
|
102
|
-
top = top - (containerRef.current.offsetHeight + editorRect.height) - 80;
|
|
103
|
-
}
|
|
104
|
-
setPosition({
|
|
105
|
-
top: top,
|
|
106
|
-
left: start.left
|
|
107
|
-
});
|
|
108
94
|
var editorViewDom = editor.view.dom;
|
|
95
|
+
|
|
96
|
+
// Position is computed in viewport coordinates (the dialog uses position: fixed),
|
|
97
|
+
// so coordsAtPos / getBoundingClientRect values can be used directly without
|
|
98
|
+
// adding scroll offsets. The dialog is then clamped to the viewport so it does
|
|
99
|
+
// not get cut off by fixed page headers/footers.
|
|
100
|
+
var updatePosition = function updatePosition() {
|
|
101
|
+
if (!containerRef.current) return;
|
|
102
|
+
var editorRect = editorDOM.getBoundingClientRect();
|
|
103
|
+
var from = editor.state.selection.from;
|
|
104
|
+
var start = editor.view.coordsAtPos(from);
|
|
105
|
+
var dialogHeight = containerRef.current.offsetHeight;
|
|
106
|
+
var dialogWidth = containerRef.current.offsetWidth;
|
|
107
|
+
|
|
108
|
+
// prefer below the editor; flip above when there isn't room below.
|
|
109
|
+
var spaceBelow = window.innerHeight - (editorRect.bottom + 60);
|
|
110
|
+
var top = spaceBelow >= dialogHeight || editorRect.top < dialogHeight + 80 ? editorRect.bottom + 60 : editorRect.top - dialogHeight - 20;
|
|
111
|
+
var left = start.left;
|
|
112
|
+
var margin = 8;
|
|
113
|
+
top = Math.max(margin, Math.min(top, window.innerHeight - dialogHeight - margin));
|
|
114
|
+
left = Math.max(margin, Math.min(left, window.innerWidth - dialogWidth - margin));
|
|
115
|
+
setPosition({
|
|
116
|
+
top: top,
|
|
117
|
+
left: left
|
|
118
|
+
});
|
|
119
|
+
};
|
|
120
|
+
updatePosition();
|
|
121
|
+
var frame = null;
|
|
122
|
+
var scheduleUpdate = function scheduleUpdate() {
|
|
123
|
+
if (frame !== null) return;
|
|
124
|
+
frame = requestAnimationFrame(function () {
|
|
125
|
+
frame = null;
|
|
126
|
+
updatePosition();
|
|
127
|
+
});
|
|
128
|
+
};
|
|
129
|
+
window.addEventListener('scroll', scheduleUpdate, true);
|
|
130
|
+
window.addEventListener('resize', scheduleUpdate);
|
|
109
131
|
var handleClickOutside = function handleClickOutside(e) {
|
|
110
132
|
if (containerRef.current && !containerRef.current.contains(e.target) && !editorViewDom.contains(e.target)) {
|
|
111
133
|
onCloseRef.current();
|
|
@@ -116,6 +138,9 @@ function CharacterPicker(_ref2) {
|
|
|
116
138
|
});
|
|
117
139
|
return function () {
|
|
118
140
|
clearTimeout(timeoutId);
|
|
141
|
+
if (frame !== null) cancelAnimationFrame(frame);
|
|
142
|
+
window.removeEventListener('scroll', scheduleUpdate, true);
|
|
143
|
+
window.removeEventListener('resize', scheduleUpdate);
|
|
119
144
|
document.removeEventListener('click', handleClickOutside);
|
|
120
145
|
};
|
|
121
146
|
}, [editor]);
|
|
@@ -136,11 +161,11 @@ function CharacterPicker(_ref2) {
|
|
|
136
161
|
"data-toolbar-for": editor.instanceId,
|
|
137
162
|
style: {
|
|
138
163
|
visibility: position.top === 0 && position.left === 0 ? 'hidden' : 'initial',
|
|
139
|
-
position: '
|
|
164
|
+
position: 'fixed',
|
|
140
165
|
top: "".concat(position.top, "px"),
|
|
141
166
|
left: "".concat(position.left, "px"),
|
|
142
167
|
maxWidth: '500px',
|
|
143
|
-
zIndex:
|
|
168
|
+
zIndex: 1000
|
|
144
169
|
}
|
|
145
170
|
}, /*#__PURE__*/_react["default"].createElement("div", null, /*#__PURE__*/_react["default"].createElement(_mathToolbar.PureToolbar, {
|
|
146
171
|
keyPadCharacterRef: opts.keyPadCharacterRef,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CharacterPicker.js","names":["_react","_interopRequireWildcard","require","_reactDom","_interopRequireDefault","_propTypes","_get","_mathToolbar","_customPopper","_characterUtils","e","t","WeakMap","r","n","__esModule","o","i","f","__proto__","_typeof","has","get","set","_t","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","ownKeys","keys","getOwnPropertySymbols","filter","enumerable","push","apply","_objectSpread","arguments","length","forEach","_defineProperty2","getOwnPropertyDescriptors","defineProperties","CharacterIcon","exports","_ref","letter","createElement","style","fontSize","lineHeight","propTypes","PropTypes","string","CharacterPicker","_ref2","_opts$characters","editor","opts","onClose","characters","containerRef","useRef","onCloseRef","_useState","useState","top","left","_useState2","_slicedToArray2","position","setPosition","_useState3","_useState4","popover","setPopover","current","configToUse","useMemo","spanishConfig","language","specialConfig","layoutForCharacters","reduce","obj","arr","columns","rows","closePopOver","useEffect","editorDOM","options","element","editorRect","getBoundingClientRect","bodyRect","document","body","from","state","selection","start","view","coordsAtPos","Math","abs","height","y","offsetHeight","editorViewDom","dom","handleClickOutside","contains","target","timeoutId","setTimeout","addEventListener","clearTimeout","removeEventListener","renderPopOver","event","el","anchorEl","currentTarget","handleChange","val","chain","focus","insertContent","run","Fragment","ReactDOM","createPortal","ref","className","instanceId","visibility","concat","maxWidth","zIndex","PureToolbar","keyPadCharacterRef","setKeypadInteraction","autoFocus","noDecimal","hideInput","noLatexHandling","hideDoneButtonBackground","layoutForKeyPad","additionalKeys","_toConsumableArray2","map","k","name","write","label","category","extraClass","extraProps","border","hasPreview","actions","onMouseEnter","ev","onMouseLeave","keypadMode","onChange","onDone","description","unicode","object","func","isRequired"],"sources":["../../src/components/CharacterPicker.jsx"],"sourcesContent":["import React, { useEffect, useMemo, useRef, useState } from 'react';\nimport ReactDOM from 'react-dom';\nimport PropTypes from 'prop-types';\nimport get from 'lodash-es/get';\n\nimport { PureToolbar } from '@pie-lib/math-toolbar';\n\nimport CustomPopper from './characters/custom-popper';\nimport { spanishConfig, specialConfig } from './characters/characterUtils';\n\nconst CharacterIcon = ({ letter }) => (\n <div\n style={{\n fontSize: '24px',\n lineHeight: '24px',\n }}\n >\n {letter}\n </div>\n);\n\nCharacterIcon.propTypes = {\n letter: PropTypes.string,\n};\n\nexport function CharacterPicker({ editor, opts, onClose }) {\n if (!opts?.characters?.length) {\n return null;\n }\n\n const containerRef = useRef(null);\n const onCloseRef = useRef(onClose);\n const [position, setPosition] = useState({ top: 0, left: 0 });\n const [popover, setPopover] = useState(null);\n\n onCloseRef.current = onClose;\n\n const configToUse = useMemo(() => {\n if (!opts) return spanishConfig;\n\n switch (true) {\n case opts.language === 'spanish':\n return spanishConfig;\n case opts.language === 'special':\n return specialConfig;\n default:\n return opts;\n }\n }, [opts]);\n\n const layoutForCharacters = useMemo(\n () =>\n configToUse.characters.reduce(\n (obj, arr) => {\n if (arr.length >= obj.columns) {\n obj.columns = arr.length;\n }\n\n return obj;\n },\n { rows: configToUse.characters.length, columns: 0 },\n ),\n [configToUse],\n );\n\n const closePopOver = () => setPopover(null);\n\n useEffect(\n () => () => {\n closePopOver();\n },\n [],\n );\n\n // Keep `onClose` out of the dependency array — parents often pass a new callback each\n // render (e.g. after each keystroke), which would re-run this effect constantly. Use a\n // ref so click-outside always calls the latest close handler.\n useEffect(() => {\n if (!editor) return;\n\n // Calculate position relative to selection\n const editorDOM = editor.options.element;\n const editorRect = editorDOM.getBoundingClientRect();\n const bodyRect = document.body.getBoundingClientRect();\n const { from } = editor.state.selection;\n const start = editor.view.coordsAtPos(from);\n\n let top = editorRect.top + Math.abs(bodyRect.top) + editorRect.height + 60;\n\n if (editorRect.y > containerRef.current.offsetHeight) {\n top = top - (containerRef.current.offsetHeight + editorRect.height) - 80;\n }\n\n setPosition({\n top: top,\n left: start.left,\n });\n\n const editorViewDom = editor.view.dom;\n\n const handleClickOutside = (e) => {\n if (containerRef.current && !containerRef.current.contains(e.target) && !editorViewDom.contains(e.target)) {\n onCloseRef.current();\n }\n };\n\n const timeoutId = setTimeout(() => {\n document.addEventListener('click', handleClickOutside);\n });\n\n return () => {\n clearTimeout(timeoutId);\n document.removeEventListener('click', handleClickOutside);\n };\n }, [editor]);\n\n const renderPopOver = (event, el) => setPopover({ anchorEl: event.currentTarget, el });\n\n const handleChange = (val) => {\n if (typeof val === 'string') {\n editor.chain().focus().insertContent(val).run();\n }\n };\n\n return (\n <>\n {ReactDOM.createPortal(\n <div\n ref={containerRef}\n className=\"insert-character-dialog\"\n data-toolbar-for={editor.instanceId}\n style={{\n visibility: position.top === 0 && position.left === 0 ? 'hidden' : 'initial',\n position: 'absolute',\n top: `${position.top}px`,\n left: `${position.left}px`,\n maxWidth: '500px',\n zIndex: 99,\n }}\n >\n <div>\n <PureToolbar\n keyPadCharacterRef={opts.keyPadCharacterRef}\n setKeypadInteraction={opts.setKeypadInteraction}\n autoFocus\n noDecimal\n hideInput\n noLatexHandling\n hideDoneButtonBackground\n layoutForKeyPad={layoutForCharacters}\n additionalKeys={configToUse.characters.reduce((arr, n) => {\n arr = [\n ...arr,\n ...n.map((k) => ({\n name: get(k, 'name') || k,\n write: get(k, 'write') || k,\n label: get(k, 'label') || k,\n category: 'character',\n extraClass: 'character',\n extraProps: {\n ...(k.extraProps || {}),\n style: {\n ...(k.extraProps || {}).style,\n border: '1px solid #000',\n },\n },\n ...(configToUse.hasPreview\n ? {\n actions: {\n onMouseEnter: (ev) => renderPopOver(ev, k),\n onMouseLeave: closePopOver,\n },\n }\n : {}),\n })),\n ];\n\n return arr;\n }, [])}\n keypadMode=\"language\"\n onChange={handleChange}\n onDone={onClose}\n />\n </div>\n </div>,\n document.body,\n )}\n {popover &&\n ReactDOM.createPortal(\n <CustomPopper onClose={closePopOver} anchorEl={popover.anchorEl}>\n <div>{popover.el.label}</div>\n <div style={{ fontSize: 20, lineHeight: '20px' }}>{popover.el.description}</div>\n <div style={{ fontSize: 20, lineHeight: '20px' }}>{popover.el.unicode}</div>\n </CustomPopper>,\n document.body,\n )}\n </>\n );\n}\n\nCharacterPicker.propTypes = {\n editor: PropTypes.object,\n opts: PropTypes.object,\n onClose: PropTypes.func.isRequired,\n};\n\nexport { CharacterIcon };\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"CharacterPicker.js","names":["_react","_interopRequireWildcard","require","_reactDom","_interopRequireDefault","_propTypes","_get","_mathToolbar","_customPopper","_characterUtils","e","t","WeakMap","r","n","__esModule","o","i","f","__proto__","_typeof","has","get","set","_t","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","ownKeys","keys","getOwnPropertySymbols","filter","enumerable","push","apply","_objectSpread","arguments","length","forEach","_defineProperty2","getOwnPropertyDescriptors","defineProperties","CharacterIcon","exports","_ref","letter","createElement","style","fontSize","lineHeight","propTypes","PropTypes","string","CharacterPicker","_ref2","_opts$characters","editor","opts","onClose","characters","containerRef","useRef","onCloseRef","_useState","useState","top","left","_useState2","_slicedToArray2","position","setPosition","_useState3","_useState4","popover","setPopover","current","configToUse","useMemo","spanishConfig","language","specialConfig","layoutForCharacters","reduce","obj","arr","columns","rows","closePopOver","useEffect","editorDOM","options","element","editorViewDom","view","dom","updatePosition","editorRect","getBoundingClientRect","from","state","selection","start","coordsAtPos","dialogHeight","offsetHeight","dialogWidth","offsetWidth","spaceBelow","window","innerHeight","bottom","margin","Math","max","min","innerWidth","frame","scheduleUpdate","requestAnimationFrame","addEventListener","handleClickOutside","contains","target","timeoutId","setTimeout","document","clearTimeout","cancelAnimationFrame","removeEventListener","renderPopOver","event","el","anchorEl","currentTarget","handleChange","val","chain","focus","insertContent","run","Fragment","ReactDOM","createPortal","ref","className","instanceId","visibility","concat","maxWidth","zIndex","PureToolbar","keyPadCharacterRef","setKeypadInteraction","autoFocus","noDecimal","hideInput","noLatexHandling","hideDoneButtonBackground","layoutForKeyPad","additionalKeys","_toConsumableArray2","map","k","name","write","label","category","extraClass","extraProps","border","hasPreview","actions","onMouseEnter","ev","onMouseLeave","keypadMode","onChange","onDone","body","description","unicode","object","func","isRequired"],"sources":["../../src/components/CharacterPicker.jsx"],"sourcesContent":["import React, { useEffect, useMemo, useRef, useState } from 'react';\nimport ReactDOM from 'react-dom';\nimport PropTypes from 'prop-types';\nimport get from 'lodash-es/get';\n\nimport { PureToolbar } from '@pie-lib/math-toolbar';\n\nimport CustomPopper from './characters/custom-popper';\nimport { spanishConfig, specialConfig } from './characters/characterUtils';\n\nconst CharacterIcon = ({ letter }) => (\n <div\n style={{\n fontSize: '24px',\n lineHeight: '24px',\n }}\n >\n {letter}\n </div>\n);\n\nCharacterIcon.propTypes = {\n letter: PropTypes.string,\n};\n\nexport function CharacterPicker({ editor, opts, onClose }) {\n if (!opts?.characters?.length) {\n return null;\n }\n\n const containerRef = useRef(null);\n const onCloseRef = useRef(onClose);\n const [position, setPosition] = useState({ top: 0, left: 0 });\n const [popover, setPopover] = useState(null);\n\n onCloseRef.current = onClose;\n\n const configToUse = useMemo(() => {\n if (!opts) return spanishConfig;\n\n switch (true) {\n case opts.language === 'spanish':\n return spanishConfig;\n case opts.language === 'special':\n return specialConfig;\n default:\n return opts;\n }\n }, [opts]);\n\n const layoutForCharacters = useMemo(\n () =>\n configToUse.characters.reduce(\n (obj, arr) => {\n if (arr.length >= obj.columns) {\n obj.columns = arr.length;\n }\n\n return obj;\n },\n { rows: configToUse.characters.length, columns: 0 },\n ),\n [configToUse],\n );\n\n const closePopOver = () => setPopover(null);\n\n useEffect(\n () => () => {\n closePopOver();\n },\n [],\n );\n\n // Keep `onClose` out of the dependency array — parents often pass a new callback each\n // render (e.g. after each keystroke), which would re-run this effect constantly. Use a\n // ref so click-outside always calls the latest close handler.\n useEffect(() => {\n if (!editor) return;\n\n const editorDOM = editor.options.element;\n const editorViewDom = editor.view.dom;\n\n // Position is computed in viewport coordinates (the dialog uses position: fixed),\n // so coordsAtPos / getBoundingClientRect values can be used directly without\n // adding scroll offsets. The dialog is then clamped to the viewport so it does\n // not get cut off by fixed page headers/footers.\n const updatePosition = () => {\n if (!containerRef.current) return;\n\n const editorRect = editorDOM.getBoundingClientRect();\n const { from } = editor.state.selection;\n const start = editor.view.coordsAtPos(from);\n\n const dialogHeight = containerRef.current.offsetHeight;\n const dialogWidth = containerRef.current.offsetWidth;\n\n // prefer below the editor; flip above when there isn't room below.\n const spaceBelow = window.innerHeight - (editorRect.bottom + 60);\n let top =\n spaceBelow >= dialogHeight || editorRect.top < dialogHeight + 80\n ? editorRect.bottom + 60\n : editorRect.top - dialogHeight - 20;\n\n let left = start.left;\n\n const margin = 8;\n top = Math.max(margin, Math.min(top, window.innerHeight - dialogHeight - margin));\n left = Math.max(margin, Math.min(left, window.innerWidth - dialogWidth - margin));\n\n setPosition({ top, left });\n };\n\n updatePosition();\n\n let frame = null;\n const scheduleUpdate = () => {\n if (frame !== null) return;\n frame = requestAnimationFrame(() => {\n frame = null;\n updatePosition();\n });\n };\n\n window.addEventListener('scroll', scheduleUpdate, true);\n window.addEventListener('resize', scheduleUpdate);\n\n const handleClickOutside = (e) => {\n if (containerRef.current && !containerRef.current.contains(e.target) && !editorViewDom.contains(e.target)) {\n onCloseRef.current();\n }\n };\n\n const timeoutId = setTimeout(() => {\n document.addEventListener('click', handleClickOutside);\n });\n\n return () => {\n clearTimeout(timeoutId);\n if (frame !== null) cancelAnimationFrame(frame);\n window.removeEventListener('scroll', scheduleUpdate, true);\n window.removeEventListener('resize', scheduleUpdate);\n document.removeEventListener('click', handleClickOutside);\n };\n }, [editor]);\n\n const renderPopOver = (event, el) => setPopover({ anchorEl: event.currentTarget, el });\n\n const handleChange = (val) => {\n if (typeof val === 'string') {\n editor.chain().focus().insertContent(val).run();\n }\n };\n\n return (\n <>\n {ReactDOM.createPortal(\n <div\n ref={containerRef}\n className=\"insert-character-dialog\"\n data-toolbar-for={editor.instanceId}\n style={{\n visibility: position.top === 0 && position.left === 0 ? 'hidden' : 'initial',\n position: 'fixed',\n top: `${position.top}px`,\n left: `${position.left}px`,\n maxWidth: '500px',\n zIndex: 1000,\n }}\n >\n <div>\n <PureToolbar\n keyPadCharacterRef={opts.keyPadCharacterRef}\n setKeypadInteraction={opts.setKeypadInteraction}\n autoFocus\n noDecimal\n hideInput\n noLatexHandling\n hideDoneButtonBackground\n layoutForKeyPad={layoutForCharacters}\n additionalKeys={configToUse.characters.reduce((arr, n) => {\n arr = [\n ...arr,\n ...n.map((k) => ({\n name: get(k, 'name') || k,\n write: get(k, 'write') || k,\n label: get(k, 'label') || k,\n category: 'character',\n extraClass: 'character',\n extraProps: {\n ...(k.extraProps || {}),\n style: {\n ...(k.extraProps || {}).style,\n border: '1px solid #000',\n },\n },\n ...(configToUse.hasPreview\n ? {\n actions: {\n onMouseEnter: (ev) => renderPopOver(ev, k),\n onMouseLeave: closePopOver,\n },\n }\n : {}),\n })),\n ];\n\n return arr;\n }, [])}\n keypadMode=\"language\"\n onChange={handleChange}\n onDone={onClose}\n />\n </div>\n </div>,\n document.body,\n )}\n {popover &&\n ReactDOM.createPortal(\n <CustomPopper onClose={closePopOver} anchorEl={popover.anchorEl}>\n <div>{popover.el.label}</div>\n <div style={{ fontSize: 20, lineHeight: '20px' }}>{popover.el.description}</div>\n <div style={{ fontSize: 20, lineHeight: '20px' }}>{popover.el.unicode}</div>\n </CustomPopper>,\n document.body,\n )}\n </>\n );\n}\n\nCharacterPicker.propTypes = {\n editor: PropTypes.object,\n opts: PropTypes.object,\n onClose: PropTypes.func.isRequired,\n};\n\nexport { CharacterIcon };\n"],"mappings":"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","ignoreList":[]}
|
package/lib/extensions/math.js
CHANGED
|
@@ -57,6 +57,23 @@ var EnsureTextAfterMathPlugin = exports.EnsureTextAfterMathPlugin = function Ens
|
|
|
57
57
|
}
|
|
58
58
|
});
|
|
59
59
|
};
|
|
60
|
+
var nodeBeforeZeroWidthSpace = function nodeBeforeZeroWidthSpace(doc, from) {
|
|
61
|
+
var i;
|
|
62
|
+
|
|
63
|
+
// finding if previous to the cursor there's a zero-width space
|
|
64
|
+
// and a non-text element, and deleting everything until the space
|
|
65
|
+
for (i = from; i > 0; i--) {
|
|
66
|
+
var _currentDoc$type, _currentDoc$type2;
|
|
67
|
+
var currentDoc = doc.nodeAt(i);
|
|
68
|
+
if ((currentDoc === null || currentDoc === void 0 || (_currentDoc$type = currentDoc.type) === null || _currentDoc$type === void 0 ? void 0 : _currentDoc$type.name) === 'text' && currentDoc.textContent !== "\u200B") {
|
|
69
|
+
return -1;
|
|
70
|
+
}
|
|
71
|
+
if (currentDoc && (currentDoc === null || currentDoc === void 0 || (_currentDoc$type2 = currentDoc.type) === null || _currentDoc$type2 === void 0 ? void 0 : _currentDoc$type2.name) !== 'text') {
|
|
72
|
+
break;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return i;
|
|
76
|
+
};
|
|
60
77
|
var ZeroWidthSpaceHandlingPlugin = exports.ZeroWidthSpaceHandlingPlugin = new _prosemirrorState.Plugin({
|
|
61
78
|
key: new _prosemirrorState.PluginKey('zeroWidthSpaceHandling'),
|
|
62
79
|
props: {
|
|
@@ -68,34 +85,33 @@ var ZeroWidthSpaceHandlingPlugin = exports.ZeroWidthSpaceHandlingPlugin = new _p
|
|
|
68
85
|
var from = selection.from,
|
|
69
86
|
empty = selection.empty;
|
|
70
87
|
if (empty && event.key === 'Backspace' && from > 0) {
|
|
71
|
-
var
|
|
72
|
-
if (
|
|
73
|
-
|
|
74
|
-
dispatch(tr);
|
|
75
|
-
return true; // handled
|
|
88
|
+
var start = nodeBeforeZeroWidthSpace(doc, from);
|
|
89
|
+
if (start === -1) {
|
|
90
|
+
return false;
|
|
76
91
|
}
|
|
92
|
+
var tr = state.tr["delete"](start, from);
|
|
93
|
+
dispatch(tr);
|
|
94
|
+
return true; // handled
|
|
77
95
|
}
|
|
78
96
|
if (empty && event.key === 'ArrowLeft' && from > 0) {
|
|
79
|
-
var
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
97
|
+
var _start = nodeBeforeZeroWidthSpace(doc, from);
|
|
98
|
+
if (_start === -1) {
|
|
99
|
+
return false;
|
|
100
|
+
}
|
|
101
|
+
var resolved = state.doc.resolve(_start);
|
|
102
|
+
var maybeNode = resolved.nodeAfter || resolved.nodeBefore;
|
|
85
103
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
return true;
|
|
98
|
-
}
|
|
104
|
+
// Check if there's an inline selectable node (e.g., your math node)
|
|
105
|
+
if (maybeNode) {
|
|
106
|
+
var nodeResolved = state.doc.resolve(_start);
|
|
107
|
+
var _tr = state.tr.setSelection(_prosemirrorState.NodeSelection.create(state.doc, nodeResolved.pos));
|
|
108
|
+
dispatch(_tr);
|
|
109
|
+
return true;
|
|
110
|
+
} else {
|
|
111
|
+
// Just move the text cursor before the zwsp
|
|
112
|
+
var _tr2 = state.tr.setSelection(_prosemirrorState.TextSelection.create(state.doc, from - 2));
|
|
113
|
+
dispatch(_tr2);
|
|
114
|
+
return true;
|
|
99
115
|
}
|
|
100
116
|
}
|
|
101
117
|
return false;
|
|
@@ -167,15 +183,10 @@ var MathNode = exports.MathNode = _core.Node.create({
|
|
|
167
183
|
tr.setSelection(sel);
|
|
168
184
|
}
|
|
169
185
|
dispatch(tr);
|
|
186
|
+
(0, _toolbar.setToolbarOpened)(editor, true);
|
|
170
187
|
return true;
|
|
171
188
|
};
|
|
172
189
|
}
|
|
173
|
-
// insertMath: (latex = '') => ({ commands }) => {
|
|
174
|
-
// return commands.insertContent({
|
|
175
|
-
// type: this.name,
|
|
176
|
-
// attrs: { latex },
|
|
177
|
-
// });
|
|
178
|
-
// },
|
|
179
190
|
};
|
|
180
191
|
},
|
|
181
192
|
renderHTML: function renderHTML(_ref2) {
|
|
@@ -259,16 +270,18 @@ var MathNodeView = exports.MathNodeView = function MathNodeView(props) {
|
|
|
259
270
|
}
|
|
260
271
|
}, [selected]);
|
|
261
272
|
(0, _react.useEffect)(function () {
|
|
262
|
-
(0, _toolbar.setToolbarOpened)(editor, showToolbar);
|
|
263
|
-
}, [editor, showToolbar]);
|
|
273
|
+
(0, _toolbar.setToolbarOpened)(editor, selected || showToolbar);
|
|
274
|
+
}, [editor, showToolbar, selected]);
|
|
264
275
|
(0, _react.useEffect)(function () {
|
|
265
276
|
// Calculate position relative to selection
|
|
266
277
|
var from = editor.state.selection.from;
|
|
267
278
|
var start = editor.view.coordsAtPos(from);
|
|
279
|
+
var editorDOM = editor.options.element;
|
|
280
|
+
var editorRect = editorDOM.getBoundingClientRect();
|
|
268
281
|
setPosition({
|
|
269
|
-
top: 40,
|
|
282
|
+
top: start.top - editorRect.top + 40,
|
|
270
283
|
// shift above
|
|
271
|
-
left: start.left
|
|
284
|
+
left: start.left - editorRect.left
|
|
272
285
|
});
|
|
273
286
|
var handleClickOutside = function handleClickOutside(event) {
|
|
274
287
|
var _document$querySelect, _document, _target$closest, _target$closest2, _target$closest3;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"math.js","names":["_react","_interopRequireWildcard","require","_reactDom","_interopRequireDefault","_core","_react2","_prosemirrorState","_mathToolbar","_mathRendering","_toolbar","e","t","WeakMap","r","n","__esModule","o","i","f","__proto__","_typeof","has","get","set","_t","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","ownKeys","keys","getOwnPropertySymbols","filter","enumerable","push","apply","_objectSpread","arguments","length","forEach","_defineProperty2","getOwnPropertyDescriptors","defineProperties","ensureTextAfterMathPluginKey","PluginKey","generateAdditionalKeys","keyData","undefined","map","key","name","latex","write","label","EnsureTextAfterMathPlugin","exports","mathNodeName","Plugin","appendTransaction","transactions","oldState","newState","some","tr","docChanged","changed","doc","descendants","node","pos","type","nextPos","nodeSize","nextNode","nodeAt","insert","schema","text","ZeroWidthSpaceHandlingPlugin","props","handleKeyDown","view","event","state","dispatch","selection","from","empty","prevChar","textBetween","posBefore","resolved","resolve","maybeNode","nodeAfter","nodeBefore","nodePos","nodeResolved","setSelection","NodeSelection","create","TextSelection","MathNode","Node","group","inline","atom","addAttributes","wrapper","html","addProseMirrorPlugins","parseHTML","tag","getAttrs","el","getAttribute","textContent","innerHTML","addCommands","_this","insertMath","_ref","_node$type","editor","nodes","math","$from","sel","renderHTML","_ref2","HTMLAttributes","dangerouslySetInnerHTML","__html","wrapMath","addNodeView","_this2","ReactNodeViewRenderer","createElement","MathNodeView","options","updateAttributes","selected","_useState","useState","_useState2","_slicedToArray2","showToolbar","setShowToolbar","toolbarRef","useRef","timestamp","Date","now","_useState3","top","left","_useState4","position","setPosition","_ref3","_ref3$math","mathOptions","keypadMode","_mathOptions$controll","controlledKeypadMode","_mathOptions$customKe","customKeys","keyPadCharacterRef","setKeypadInteraction","attrs","handleChange","newLatex","handleDone","_editor$state","commands","focus","useEffect","setToolbarOpened","start","coordsAtPos","handleClickOutside","_document$querySelect","_document","_target$closest","_target$closest2","_target$closest3","target","equationEditorListboxes","document","querySelectorAll","equationEditorPopoverOpen","clickedEquationEditorSelect","id","includes","closest","clickedMathNode","concat","current","contains","addEventListener","removeEventListener","NodeViewWrapper","className","style","display","cursor","margin","onClick","contentEditable","MathPreview","ReactDOM","createPortal","ref","instanceId","zIndex","background","boxShadow","MathToolbar","autoFocus","onChange","onDone","additionalKeys","_tiptapContainerEl","body"],"sources":["../../src/extensions/math.js"],"sourcesContent":["import React, { useEffect, useRef, useState } from 'react';\nimport ReactDOM from 'react-dom';\nimport { Node } from '@tiptap/core';\nimport { NodeViewWrapper, ReactNodeViewRenderer } from '@tiptap/react';\nimport { NodeSelection, Plugin, PluginKey, TextSelection } from 'prosemirror-state';\nimport { MathPreview, MathToolbar } from '@pie-lib/math-toolbar';\nimport { wrapMath } from '@pie-lib/math-rendering';\nimport { setToolbarOpened } from '../utils/toolbar';\n\nconst ensureTextAfterMathPluginKey = new PluginKey('ensureTextAfterMath');\n\nconst generateAdditionalKeys = (keyData = []) => {\n return keyData.map((key) => ({\n name: key,\n latex: key,\n write: key,\n label: key,\n }));\n};\n\nexport const EnsureTextAfterMathPlugin = (mathNodeName) =>\n new Plugin({\n key: ensureTextAfterMathPluginKey,\n appendTransaction: (transactions, oldState, newState) => {\n // Only act when the doc actually changed\n if (!transactions.some((tr) => tr.docChanged)) return null;\n\n const tr = newState.tr;\n let changed = false;\n\n newState.doc.descendants((node, pos) => {\n if (node.type.name === mathNodeName) {\n const nextPos = pos + node.nodeSize;\n const nextNode = newState.doc.nodeAt(nextPos);\n\n // If there's no node after, or the next node isn't text, insert a space\n if (!nextNode || nextNode.type.name !== 'text') {\n tr.insert(nextPos, newState.schema.text('\\u200b'));\n changed = true;\n }\n }\n });\n\n return changed ? tr : null;\n },\n });\n\nexport const ZeroWidthSpaceHandlingPlugin = new Plugin({\n key: new PluginKey('zeroWidthSpaceHandling'),\n props: {\n handleKeyDown(view, event) {\n const { state, dispatch } = view;\n const { selection, doc } = state;\n const { from, empty } = selection;\n\n if (empty && event.key === 'Backspace' && from > 0) {\n const prevChar = doc.textBetween(from - 1, from, '\\uFFFC', '\\uFFFC');\n if (prevChar === '\\u200b') {\n const tr = state.tr.delete(from - 2, from);\n dispatch(tr);\n return true; // handled\n }\n }\n\n if (empty && event.key === 'ArrowLeft' && from > 0) {\n const prevChar = doc.textBetween(from - 1, from, '\\uFFFC', '\\uFFFC');\n // If the previous character is the zero-width space...\n if (prevChar === '\\u200b') {\n const posBefore = from - 1;\n const resolved = state.doc.resolve(posBefore - 1); // look just before the zwsp\n const maybeNode = resolved.nodeAfter || resolved.nodeBefore;\n\n // Check if there's an inline selectable node (e.g., your math node)\n if (maybeNode) {\n const nodePos = posBefore - maybeNode.nodeSize;\n const nodeResolved = state.doc.resolve(nodePos);\n const tr = state.tr.setSelection(NodeSelection.create(state.doc, nodeResolved.pos));\n dispatch(tr);\n return true;\n } else {\n // Just move the text cursor before the zwsp\n const tr = state.tr.setSelection(TextSelection.create(state.doc, from - 2));\n dispatch(tr);\n return true;\n }\n }\n }\n\n return false;\n },\n },\n});\n\nexport const MathNode = Node.create({\n name: 'math',\n group: 'inline',\n inline: true,\n atom: true,\n\n addAttributes() {\n return {\n latex: { default: '' },\n wrapper: { default: null },\n html: { default: null },\n };\n },\n\n addProseMirrorPlugins() {\n return [EnsureTextAfterMathPlugin(this.name), ZeroWidthSpaceHandlingPlugin];\n },\n\n parseHTML() {\n return [\n {\n tag: 'span[data-latex]',\n getAttrs: (el) => ({\n latex: el.getAttribute('data-raw') || el.textContent,\n }),\n },\n {\n tag: 'span[data-type=\"mathml\"]',\n getAttrs: (el) => ({\n html: el.innerHTML,\n }),\n },\n ];\n },\n\n addCommands() {\n return {\n insertMath:\n (latex = '') =>\n ({ tr, editor, dispatch }) => {\n const { state } = editor.view;\n const node = state.schema.nodes.math.create({\n latex,\n });\n const { selection } = state;\n\n // The inserted node is typically just before the cursor\n const pos = selection.$from.pos;\n\n tr.insert(pos, node);\n\n if (node?.type?.name === this.name) {\n // Create a NodeSelection from the current doc\n const sel = NodeSelection.create(tr.doc, selection.$from.pos);\n\n // Build a fresh transaction from the current state and set the selection\n tr.setSelection(sel);\n }\n\n dispatch(tr);\n\n return true;\n },\n // insertMath: (latex = '') => ({ commands }) => {\n // return commands.insertContent({\n // type: this.name,\n // attrs: { latex },\n // });\n // },\n };\n },\n\n renderHTML({ HTMLAttributes }) {\n if (HTMLAttributes.html) {\n return ['span', { 'data-type': 'mathml', dangerouslySetInnerHTML: { __html: HTMLAttributes.html } }];\n }\n\n return [\n 'span',\n { 'data-latex': '', 'data-raw': HTMLAttributes.latex },\n wrapMath(HTMLAttributes.latex, HTMLAttributes.wrapper),\n ];\n },\n\n addNodeView() {\n return ReactNodeViewRenderer((props) => <MathNodeView {...{ ...props, options: this.options }} />);\n },\n});\n\nexport const MathNodeView = (props) => {\n const { node, updateAttributes, editor, selected, options } = props;\n const [showToolbar, setShowToolbar] = useState(selected);\n const toolbarRef = useRef(null);\n const timestamp = useRef(Date.now());\n const [position, setPosition] = useState({ top: 0, left: 0 });\n const { math: mathOptions = {} } = options || {};\n const {\n keypadMode,\n controlledKeypadMode = true,\n customKeys = [],\n keyPadCharacterRef,\n setKeypadInteraction,\n } = mathOptions;\n\n const latex = node.attrs.latex || '';\n\n const handleChange = (newLatex) => {\n updateAttributes({ latex: newLatex });\n };\n\n const handleDone = (newLatex) => {\n updateAttributes({ latex: newLatex });\n setShowToolbar(false);\n\n const { selection, tr, doc } = editor.state;\n const sel = TextSelection.create(doc, selection.from + 1);\n\n // Build a fresh transaction from the current state and set the selection\n tr.setSelection(sel);\n editor.view.dispatch(tr);\n editor.commands.focus();\n };\n\n useEffect(() => {\n if (selected) {\n setShowToolbar(true);\n }\n }, [selected]);\n\n useEffect(() => {\n setToolbarOpened(editor, showToolbar);\n }, [editor, showToolbar]);\n\n useEffect(() => {\n // Calculate position relative to selection\n const { from } = editor.state.selection;\n const start = editor.view.coordsAtPos(from);\n setPosition({\n top: 40, // shift above\n left: start.left,\n });\n\n const handleClickOutside = (event) => {\n const target = event?.target;\n\n // MUI's `Select` renders its dropdown options in a portal attached to `document.body`.\n // Those clicks should not dismiss the math toolbar.\n const equationEditorListboxes =\n document.querySelectorAll?.(\n '[id^=\"equation-editor-select\"][id*=\"listbox\"], [aria-labelledby=\"equation-editor-label\"][role=\"listbox\"]',\n ) || [];\n\n const equationEditorPopoverOpen = equationEditorListboxes.length > 0;\n const clickedEquationEditorSelect =\n !!(target?.id && target.id.includes('equation-editor-select')) ||\n !!target?.closest?.('[id*=\"equation-editor-select\"]');\n\n // If the click originated from the math node preview itself (the element\n // that opens the toolbar), ignore it here — the node's own onClick handler\n // will keep/re-open the toolbar. Without this guard, closing and then\n // immediately clicking the math node would fire this listener in the same\n // event cycle and close the toolbar before it could open.\n const clickedMathNode = !!target?.closest?.(`.math-node-${timestamp.current}`);\n\n if (\n toolbarRef.current &&\n !toolbarRef.current.contains(target) &&\n !target?.closest?.('[data-inline-node]') &&\n !equationEditorPopoverOpen &&\n !clickedEquationEditorSelect &&\n !clickedMathNode\n ) {\n setShowToolbar(false);\n handleDone(node.attrs.latex);\n }\n };\n\n if (showToolbar) {\n // Use `click` (not `mousedown`) so interacting with browser UI like the scrollbar\n // doesn't automatically dismiss the math toolbar.\n document.addEventListener('click', handleClickOutside);\n } else {\n document.removeEventListener('click', handleClickOutside);\n }\n\n return () => document.removeEventListener('click', handleClickOutside);\n }, [editor, showToolbar]);\n\n return (\n <NodeViewWrapper\n className={`math-node-${timestamp.current}`}\n style={{\n display: 'inline-flex',\n cursor: 'pointer',\n margin: '0 4px',\n }}\n data-selected={selected}\n >\n <div onClick={() => setShowToolbar(true)} contentEditable={false}>\n <MathPreview latex={latex} />\n </div>\n {showToolbar &&\n ReactDOM.createPortal(\n <div\n ref={toolbarRef}\n data-toolbar-for={editor.instanceId}\n style={{\n position: 'absolute',\n top: `${position.top}px`,\n left: `${position.left}px`,\n zIndex: 20,\n background: 'var(--editable-html-toolbar-bg, #efefef)',\n boxShadow:\n '0px 1px 5px 0px rgba(0, 0, 0, 0.2), 0px 2px 2px 0px rgba(0, 0, 0, 0.14), 0px 3px 1px -2px rgba(0, 0, 0, 0.12)',\n }}\n >\n <MathToolbar\n latex={latex}\n autoFocus\n onChange={handleChange}\n onDone={handleDone}\n keypadMode={keypadMode}\n controlledKeypadMode={controlledKeypadMode}\n additionalKeys={generateAdditionalKeys(customKeys)}\n keyPadCharacterRef={keyPadCharacterRef}\n setKeypadInteraction={setKeypadInteraction}\n />\n </div>,\n editor?._tiptapContainerEl || document.body,\n )}\n </NodeViewWrapper>\n );\n};\n"],"mappings":";;;;;;;;;;AAAA,IAAAA,MAAA,GAAAC,uBAAA,CAAAC,OAAA;AACA,IAAAC,SAAA,GAAAC,sBAAA,CAAAF,OAAA;AACA,IAAAG,KAAA,GAAAH,OAAA;AACA,IAAAI,OAAA,GAAAJ,OAAA;AACA,IAAAK,iBAAA,GAAAL,OAAA;AACA,IAAAM,YAAA,GAAAN,OAAA;AACA,IAAAO,cAAA,GAAAP,OAAA;AACA,IAAAQ,QAAA,GAAAR,OAAA;AAAoD,SAAAD,wBAAAU,CAAA,EAAAC,CAAA,6BAAAC,OAAA,MAAAC,CAAA,OAAAD,OAAA,IAAAE,CAAA,OAAAF,OAAA,YAAAZ,uBAAA,YAAAA,wBAAAU,CAAA,EAAAC,CAAA,SAAAA,CAAA,IAAAD,CAAA,IAAAA,CAAA,CAAAK,UAAA,SAAAL,CAAA,MAAAM,CAAA,EAAAC,CAAA,EAAAC,CAAA,KAAAC,SAAA,mBAAAT,CAAA,iBAAAA,CAAA,gBAAAU,OAAA,CAAAV,CAAA,0BAAAA,CAAA,SAAAQ,CAAA,MAAAF,CAAA,GAAAL,CAAA,GAAAG,CAAA,GAAAD,CAAA,QAAAG,CAAA,CAAAK,GAAA,CAAAX,CAAA,UAAAM,CAAA,CAAAM,GAAA,CAAAZ,CAAA,GAAAM,CAAA,CAAAO,GAAA,CAAAb,CAAA,EAAAQ,CAAA,cAAAM,EAAA,IAAAd,CAAA,gBAAAc,EAAA,OAAAC,cAAA,CAAAC,IAAA,CAAAhB,CAAA,EAAAc,EAAA,OAAAP,CAAA,IAAAD,CAAA,GAAAW,MAAA,CAAAC,cAAA,KAAAD,MAAA,CAAAE,wBAAA,CAAAnB,CAAA,EAAAc,EAAA,OAAAP,CAAA,CAAAK,GAAA,IAAAL,CAAA,CAAAM,GAAA,IAAAP,CAAA,CAAAE,CAAA,EAAAM,EAAA,EAAAP,CAAA,IAAAC,CAAA,CAAAM,EAAA,IAAAd,CAAA,CAAAc,EAAA,WAAAN,CAAA,KAAAR,CAAA,EAAAC,CAAA;AAAA,SAAAmB,QAAApB,CAAA,EAAAG,CAAA,QAAAF,CAAA,GAAAgB,MAAA,CAAAI,IAAA,CAAArB,CAAA,OAAAiB,MAAA,CAAAK,qBAAA,QAAAhB,CAAA,GAAAW,MAAA,CAAAK,qBAAA,CAAAtB,CAAA,GAAAG,CAAA,KAAAG,CAAA,GAAAA,CAAA,CAAAiB,MAAA,WAAApB,CAAA,WAAAc,MAAA,CAAAE,wBAAA,CAAAnB,CAAA,EAAAG,CAAA,EAAAqB,UAAA,OAAAvB,CAAA,CAAAwB,IAAA,CAAAC,KAAA,CAAAzB,CAAA,EAAAK,CAAA,YAAAL,CAAA;AAAA,SAAA0B,cAAA3B,CAAA,aAAAG,CAAA,MAAAA,CAAA,GAAAyB,SAAA,CAAAC,MAAA,EAAA1B,CAAA,UAAAF,CAAA,WAAA2B,SAAA,CAAAzB,CAAA,IAAAyB,SAAA,CAAAzB,CAAA,QAAAA,CAAA,OAAAiB,OAAA,CAAAH,MAAA,CAAAhB,CAAA,OAAA6B,OAAA,WAAA3B,CAAA,QAAA4B,gBAAA,aAAA/B,CAAA,EAAAG,CAAA,EAAAF,CAAA,CAAAE,CAAA,SAAAc,MAAA,CAAAe,yBAAA,GAAAf,MAAA,CAAAgB,gBAAA,CAAAjC,CAAA,EAAAiB,MAAA,CAAAe,yBAAA,CAAA/B,CAAA,KAAAmB,OAAA,CAAAH,MAAA,CAAAhB,CAAA,GAAA6B,OAAA,WAAA3B,CAAA,IAAAc,MAAA,CAAAC,cAAA,CAAAlB,CAAA,EAAAG,CAAA,EAAAc,MAAA,CAAAE,wBAAA,CAAAlB,CAAA,EAAAE,CAAA,iBAAAH,CAAA;AAEpD,IAAMkC,4BAA4B,GAAG,IAAIC,2BAAS,CAAC,qBAAqB,CAAC;AAEzE,IAAMC,sBAAsB,GAAG,SAAzBA,sBAAsBA,CAAA,EAAqB;EAAA,IAAjBC,OAAO,GAAAT,SAAA,CAAAC,MAAA,QAAAD,SAAA,QAAAU,SAAA,GAAAV,SAAA,MAAG,EAAE;EAC1C,OAAOS,OAAO,CAACE,GAAG,CAAC,UAACC,GAAG;IAAA,OAAM;MAC3BC,IAAI,EAAED,GAAG;MACTE,KAAK,EAAEF,GAAG;MACVG,KAAK,EAAEH,GAAG;MACVI,KAAK,EAAEJ;IACT,CAAC;EAAA,CAAC,CAAC;AACL,CAAC;AAEM,IAAMK,yBAAyB,GAAAC,OAAA,CAAAD,yBAAA,GAAG,SAA5BA,yBAAyBA,CAAIE,YAAY;EAAA,OACpD,IAAIC,wBAAM,CAAC;IACTR,GAAG,EAAEN,4BAA4B;IACjCe,iBAAiB,EAAE,SAAnBA,iBAAiBA,CAAGC,YAAY,EAAEC,QAAQ,EAAEC,QAAQ,EAAK;MACvD;MACA,IAAI,CAACF,YAAY,CAACG,IAAI,CAAC,UAACC,EAAE;QAAA,OAAKA,EAAE,CAACC,UAAU;MAAA,EAAC,EAAE,OAAO,IAAI;MAE1D,IAAMD,EAAE,GAAGF,QAAQ,CAACE,EAAE;MACtB,IAAIE,OAAO,GAAG,KAAK;MAEnBJ,QAAQ,CAACK,GAAG,CAACC,WAAW,CAAC,UAACC,IAAI,EAAEC,GAAG,EAAK;QACtC,IAAID,IAAI,CAACE,IAAI,CAACpB,IAAI,KAAKM,YAAY,EAAE;UACnC,IAAMe,OAAO,GAAGF,GAAG,GAAGD,IAAI,CAACI,QAAQ;UACnC,IAAMC,QAAQ,GAAGZ,QAAQ,CAACK,GAAG,CAACQ,MAAM,CAACH,OAAO,CAAC;;UAE7C;UACA,IAAI,CAACE,QAAQ,IAAIA,QAAQ,CAACH,IAAI,CAACpB,IAAI,KAAK,MAAM,EAAE;YAC9Ca,EAAE,CAACY,MAAM,CAACJ,OAAO,EAAEV,QAAQ,CAACe,MAAM,CAACC,IAAI,CAAC,QAAQ,CAAC,CAAC;YAClDZ,OAAO,GAAG,IAAI;UAChB;QACF;MACF,CAAC,CAAC;MAEF,OAAOA,OAAO,GAAGF,EAAE,GAAG,IAAI;IAC5B;EACF,CAAC,CAAC;AAAA;AAEG,IAAMe,4BAA4B,GAAAvB,OAAA,CAAAuB,4BAAA,GAAG,IAAIrB,wBAAM,CAAC;EACrDR,GAAG,EAAE,IAAIL,2BAAS,CAAC,wBAAwB,CAAC;EAC5CmC,KAAK,EAAE;IACLC,aAAa,WAAbA,aAAaA,CAACC,IAAI,EAAEC,KAAK,EAAE;MACzB,IAAQC,KAAK,GAAeF,IAAI,CAAxBE,KAAK;QAAEC,QAAQ,GAAKH,IAAI,CAAjBG,QAAQ;MACvB,IAAQC,SAAS,GAAUF,KAAK,CAAxBE,SAAS;QAAEnB,GAAG,GAAKiB,KAAK,CAAbjB,GAAG;MACtB,IAAQoB,IAAI,GAAYD,SAAS,CAAzBC,IAAI;QAAEC,KAAK,GAAKF,SAAS,CAAnBE,KAAK;MAEnB,IAAIA,KAAK,IAAIL,KAAK,CAACjC,GAAG,KAAK,WAAW,IAAIqC,IAAI,GAAG,CAAC,EAAE;QAClD,IAAME,QAAQ,GAAGtB,GAAG,CAACuB,WAAW,CAACH,IAAI,GAAG,CAAC,EAAEA,IAAI,EAAE,QAAQ,EAAE,QAAQ,CAAC;QACpE,IAAIE,QAAQ,KAAK,QAAQ,EAAE;UACzB,IAAMzB,EAAE,GAAGoB,KAAK,CAACpB,EAAE,UAAO,CAACuB,IAAI,GAAG,CAAC,EAAEA,IAAI,CAAC;UAC1CF,QAAQ,CAACrB,EAAE,CAAC;UACZ,OAAO,IAAI,CAAC,CAAC;QACf;MACF;MAEA,IAAIwB,KAAK,IAAIL,KAAK,CAACjC,GAAG,KAAK,WAAW,IAAIqC,IAAI,GAAG,CAAC,EAAE;QAClD,IAAME,SAAQ,GAAGtB,GAAG,CAACuB,WAAW,CAACH,IAAI,GAAG,CAAC,EAAEA,IAAI,EAAE,QAAQ,EAAE,QAAQ,CAAC;QACpE;QACA,IAAIE,SAAQ,KAAK,QAAQ,EAAE;UACzB,IAAME,SAAS,GAAGJ,IAAI,GAAG,CAAC;UAC1B,IAAMK,QAAQ,GAAGR,KAAK,CAACjB,GAAG,CAAC0B,OAAO,CAACF,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC;UACnD,IAAMG,SAAS,GAAGF,QAAQ,CAACG,SAAS,IAAIH,QAAQ,CAACI,UAAU;;UAE3D;UACA,IAAIF,SAAS,EAAE;YACb,IAAMG,OAAO,GAAGN,SAAS,GAAGG,SAAS,CAACrB,QAAQ;YAC9C,IAAMyB,YAAY,GAAGd,KAAK,CAACjB,GAAG,CAAC0B,OAAO,CAACI,OAAO,CAAC;YAC/C,IAAMjC,GAAE,GAAGoB,KAAK,CAACpB,EAAE,CAACmC,YAAY,CAACC,+BAAa,CAACC,MAAM,CAACjB,KAAK,CAACjB,GAAG,EAAE+B,YAAY,CAAC5B,GAAG,CAAC,CAAC;YACnFe,QAAQ,CAACrB,GAAE,CAAC;YACZ,OAAO,IAAI;UACb,CAAC,MAAM;YACL;YACA,IAAMA,IAAE,GAAGoB,KAAK,CAACpB,EAAE,CAACmC,YAAY,CAACG,+BAAa,CAACD,MAAM,CAACjB,KAAK,CAACjB,GAAG,EAAEoB,IAAI,GAAG,CAAC,CAAC,CAAC;YAC3EF,QAAQ,CAACrB,IAAE,CAAC;YACZ,OAAO,IAAI;UACb;QACF;MACF;MAEA,OAAO,KAAK;IACd;EACF;AACF,CAAC,CAAC;AAEK,IAAMuC,QAAQ,GAAA/C,OAAA,CAAA+C,QAAA,GAAGC,UAAI,CAACH,MAAM,CAAC;EAClClD,IAAI,EAAE,MAAM;EACZsD,KAAK,EAAE,QAAQ;EACfC,MAAM,EAAE,IAAI;EACZC,IAAI,EAAE,IAAI;EAEVC,aAAa,WAAbA,aAAaA,CAAA,EAAG;IACd,OAAO;MACLxD,KAAK,EAAE;QAAE,WAAS;MAAG,CAAC;MACtByD,OAAO,EAAE;QAAE,WAAS;MAAK,CAAC;MAC1BC,IAAI,EAAE;QAAE,WAAS;MAAK;IACxB,CAAC;EACH,CAAC;EAEDC,qBAAqB,WAArBA,qBAAqBA,CAAA,EAAG;IACtB,OAAO,CAACxD,yBAAyB,CAAC,IAAI,CAACJ,IAAI,CAAC,EAAE4B,4BAA4B,CAAC;EAC7E,CAAC;EAEDiC,SAAS,WAATA,SAASA,CAAA,EAAG;IACV,OAAO,CACL;MACEC,GAAG,EAAE,kBAAkB;MACvBC,QAAQ,EAAE,SAAVA,QAAQA,CAAGC,EAAE;QAAA,OAAM;UACjB/D,KAAK,EAAE+D,EAAE,CAACC,YAAY,CAAC,UAAU,CAAC,IAAID,EAAE,CAACE;QAC3C,CAAC;MAAA;IACH,CAAC,EACD;MACEJ,GAAG,EAAE,0BAA0B;MAC/BC,QAAQ,EAAE,SAAVA,QAAQA,CAAGC,EAAE;QAAA,OAAM;UACjBL,IAAI,EAAEK,EAAE,CAACG;QACX,CAAC;MAAA;IACH,CAAC,CACF;EACH,CAAC;EAEDC,WAAW,WAAXA,WAAWA,CAAA,EAAG;IAAA,IAAAC,KAAA;IACZ,OAAO;MACLC,UAAU,EACR,SADFA,UAAUA,CAAA;QAAA,IACPrE,KAAK,GAAAd,SAAA,CAAAC,MAAA,QAAAD,SAAA,QAAAU,SAAA,GAAAV,SAAA,MAAG,EAAE;QAAA,OACX,UAAAoF,IAAA,EAA8B;UAAA,IAAAC,UAAA;UAAA,IAA3B3D,EAAE,GAAA0D,IAAA,CAAF1D,EAAE;YAAE4D,MAAM,GAAAF,IAAA,CAANE,MAAM;YAAEvC,QAAQ,GAAAqC,IAAA,CAARrC,QAAQ;UACrB,IAAQD,KAAK,GAAKwC,MAAM,CAAC1C,IAAI,CAArBE,KAAK;UACb,IAAMf,IAAI,GAAGe,KAAK,CAACP,MAAM,CAACgD,KAAK,CAACC,IAAI,CAACzB,MAAM,CAAC;YAC1CjD,KAAK,EAALA;UACF,CAAC,CAAC;UACF,IAAQkC,SAAS,GAAKF,KAAK,CAAnBE,SAAS;;UAEjB;UACA,IAAMhB,GAAG,GAAGgB,SAAS,CAACyC,KAAK,CAACzD,GAAG;UAE/BN,EAAE,CAACY,MAAM,CAACN,GAAG,EAAED,IAAI,CAAC;UAEpB,IAAI,CAAAA,IAAI,aAAJA,IAAI,gBAAAsD,UAAA,GAAJtD,IAAI,CAAEE,IAAI,cAAAoD,UAAA,uBAAVA,UAAA,CAAYxE,IAAI,MAAKqE,KAAI,CAACrE,IAAI,EAAE;YAClC;YACA,IAAM6E,GAAG,GAAG5B,+BAAa,CAACC,MAAM,CAACrC,EAAE,CAACG,GAAG,EAAEmB,SAAS,CAACyC,KAAK,CAACzD,GAAG,CAAC;;YAE7D;YACAN,EAAE,CAACmC,YAAY,CAAC6B,GAAG,CAAC;UACtB;UAEA3C,QAAQ,CAACrB,EAAE,CAAC;UAEZ,OAAO,IAAI;QACb,CAAC;MAAA;MACH;MACA;MACA;MACA;MACA;MACA;IACF,CAAC;EACH,CAAC;EAEDiE,UAAU,WAAVA,UAAUA,CAAAC,KAAA,EAAqB;IAAA,IAAlBC,cAAc,GAAAD,KAAA,CAAdC,cAAc;IACzB,IAAIA,cAAc,CAACrB,IAAI,EAAE;MACvB,OAAO,CAAC,MAAM,EAAE;QAAE,WAAW,EAAE,QAAQ;QAAEsB,uBAAuB,EAAE;UAAEC,MAAM,EAAEF,cAAc,CAACrB;QAAK;MAAE,CAAC,CAAC;IACtG;IAEA,OAAO,CACL,MAAM,EACN;MAAE,YAAY,EAAE,EAAE;MAAE,UAAU,EAAEqB,cAAc,CAAC/E;IAAM,CAAC,EACtD,IAAAkF,uBAAQ,EAACH,cAAc,CAAC/E,KAAK,EAAE+E,cAAc,CAACtB,OAAO,CAAC,CACvD;EACH,CAAC;EAED0B,WAAW,WAAXA,WAAWA,CAAA,EAAG;IAAA,IAAAC,MAAA;IACZ,OAAO,IAAAC,6BAAqB,EAAC,UAACzD,KAAK;MAAA,oBAAKjF,MAAA,YAAA2I,aAAA,CAACC,YAAY,EAAAtG,aAAA,CAAAA,aAAA,KAAU2C,KAAK;QAAE4D,OAAO,EAAEJ,MAAI,CAACI;MAAO,EAAK,CAAC;IAAA,EAAC;EACpG;AACF,CAAC,CAAC;AAEK,IAAMD,YAAY,GAAAnF,OAAA,CAAAmF,YAAA,GAAG,SAAfA,YAAYA,CAAI3D,KAAK,EAAK;EACrC,IAAQX,IAAI,GAAkDW,KAAK,CAA3DX,IAAI;IAAEwE,gBAAgB,GAAgC7D,KAAK,CAArD6D,gBAAgB;IAAEjB,MAAM,GAAwB5C,KAAK,CAAnC4C,MAAM;IAAEkB,QAAQ,GAAc9D,KAAK,CAA3B8D,QAAQ;IAAEF,OAAO,GAAK5D,KAAK,CAAjB4D,OAAO;EACzD,IAAAG,SAAA,GAAsC,IAAAC,eAAQ,EAACF,QAAQ,CAAC;IAAAG,UAAA,OAAAC,eAAA,aAAAH,SAAA;IAAjDI,WAAW,GAAAF,UAAA;IAAEG,cAAc,GAAAH,UAAA;EAClC,IAAMI,UAAU,GAAG,IAAAC,aAAM,EAAC,IAAI,CAAC;EAC/B,IAAMC,SAAS,GAAG,IAAAD,aAAM,EAACE,IAAI,CAACC,GAAG,CAAC,CAAC,CAAC;EACpC,IAAAC,UAAA,GAAgC,IAAAV,eAAQ,EAAC;MAAEW,GAAG,EAAE,CAAC;MAAEC,IAAI,EAAE;IAAE,CAAC,CAAC;IAAAC,UAAA,OAAAX,eAAA,aAAAQ,UAAA;IAAtDI,QAAQ,GAAAD,UAAA;IAAEE,WAAW,GAAAF,UAAA;EAC5B,IAAAG,KAAA,GAAmCpB,OAAO,IAAI,CAAC,CAAC;IAAAqB,UAAA,GAAAD,KAAA,CAAxClC,IAAI;IAAEoC,WAAW,GAAAD,UAAA,cAAG,CAAC,CAAC,GAAAA,UAAA;EAC9B,IACEE,UAAU,GAKRD,WAAW,CALbC,UAAU;IAAAC,qBAAA,GAKRF,WAAW,CAJbG,oBAAoB;IAApBA,oBAAoB,GAAAD,qBAAA,cAAG,IAAI,GAAAA,qBAAA;IAAAE,qBAAA,GAIzBJ,WAAW,CAHbK,UAAU;IAAVA,UAAU,GAAAD,qBAAA,cAAG,EAAE,GAAAA,qBAAA;IACfE,kBAAkB,GAEhBN,WAAW,CAFbM,kBAAkB;IAClBC,oBAAoB,GAClBP,WAAW,CADbO,oBAAoB;EAGtB,IAAMrH,KAAK,GAAGiB,IAAI,CAACqG,KAAK,CAACtH,KAAK,IAAI,EAAE;EAEpC,IAAMuH,YAAY,GAAG,SAAfA,YAAYA,CAAIC,QAAQ,EAAK;IACjC/B,gBAAgB,CAAC;MAAEzF,KAAK,EAAEwH;IAAS,CAAC,CAAC;EACvC,CAAC;EAED,IAAMC,UAAU,GAAG,SAAbA,UAAUA,CAAID,QAAQ,EAAK;IAC/B/B,gBAAgB,CAAC;MAAEzF,KAAK,EAAEwH;IAAS,CAAC,CAAC;IACrCxB,cAAc,CAAC,KAAK,CAAC;IAErB,IAAA0B,aAAA,GAA+BlD,MAAM,CAACxC,KAAK;MAAnCE,SAAS,GAAAwF,aAAA,CAATxF,SAAS;MAAEtB,EAAE,GAAA8G,aAAA,CAAF9G,EAAE;MAAEG,GAAG,GAAA2G,aAAA,CAAH3G,GAAG;IAC1B,IAAM6D,GAAG,GAAG1B,+BAAa,CAACD,MAAM,CAAClC,GAAG,EAAEmB,SAAS,CAACC,IAAI,GAAG,CAAC,CAAC;;IAEzD;IACAvB,EAAE,CAACmC,YAAY,CAAC6B,GAAG,CAAC;IACpBJ,MAAM,CAAC1C,IAAI,CAACG,QAAQ,CAACrB,EAAE,CAAC;IACxB4D,MAAM,CAACmD,QAAQ,CAACC,KAAK,CAAC,CAAC;EACzB,CAAC;EAED,IAAAC,gBAAS,EAAC,YAAM;IACd,IAAInC,QAAQ,EAAE;MACZM,cAAc,CAAC,IAAI,CAAC;IACtB;EACF,CAAC,EAAE,CAACN,QAAQ,CAAC,CAAC;EAEd,IAAAmC,gBAAS,EAAC,YAAM;IACd,IAAAC,yBAAgB,EAACtD,MAAM,EAAEuB,WAAW,CAAC;EACvC,CAAC,EAAE,CAACvB,MAAM,EAAEuB,WAAW,CAAC,CAAC;EAEzB,IAAA8B,gBAAS,EAAC,YAAM;IACd;IACA,IAAQ1F,IAAI,GAAKqC,MAAM,CAACxC,KAAK,CAACE,SAAS,CAA/BC,IAAI;IACZ,IAAM4F,KAAK,GAAGvD,MAAM,CAAC1C,IAAI,CAACkG,WAAW,CAAC7F,IAAI,CAAC;IAC3CwE,WAAW,CAAC;MACVJ,GAAG,EAAE,EAAE;MAAE;MACTC,IAAI,EAAEuB,KAAK,CAACvB;IACd,CAAC,CAAC;IAEF,IAAMyB,kBAAkB,GAAG,SAArBA,kBAAkBA,CAAIlG,KAAK,EAAK;MAAA,IAAAmG,qBAAA,EAAAC,SAAA,EAAAC,eAAA,EAAAC,gBAAA,EAAAC,gBAAA;MACpC,IAAMC,MAAM,GAAGxG,KAAK,aAALA,KAAK,uBAALA,KAAK,CAAEwG,MAAM;;MAE5B;MACA;MACA,IAAMC,uBAAuB,GAC3B,EAAAN,qBAAA,IAAAC,SAAA,GAAAM,QAAQ,EAACC,gBAAgB,cAAAR,qBAAA,uBAAzBA,qBAAA,CAAA5J,IAAA,CAAA6J,SAAA,EACE,0GACF,CAAC,KAAI,EAAE;MAET,IAAMQ,yBAAyB,GAAGH,uBAAuB,CAACrJ,MAAM,GAAG,CAAC;MACpE,IAAMyJ,2BAA2B,GAC/B,CAAC,EAAEL,MAAM,aAANA,MAAM,eAANA,MAAM,CAAEM,EAAE,IAAIN,MAAM,CAACM,EAAE,CAACC,QAAQ,CAAC,wBAAwB,CAAC,CAAC,IAC9D,CAAC,EAACP,MAAM,aAANA,MAAM,gBAAAH,eAAA,GAANG,MAAM,CAAEQ,OAAO,cAAAX,eAAA,eAAfA,eAAA,CAAA9J,IAAA,CAAAiK,MAAM,EAAY,gCAAgC,CAAC;;MAEvD;MACA;MACA;MACA;MACA;MACA,IAAMS,eAAe,GAAG,CAAC,EAACT,MAAM,aAANA,MAAM,gBAAAF,gBAAA,GAANE,MAAM,CAAEQ,OAAO,cAAAV,gBAAA,eAAfA,gBAAA,CAAA/J,IAAA,CAAAiK,MAAM,gBAAAU,MAAA,CAA0B9C,SAAS,CAAC+C,OAAO,CAAE,CAAC;MAE9E,IACEjD,UAAU,CAACiD,OAAO,IAClB,CAACjD,UAAU,CAACiD,OAAO,CAACC,QAAQ,CAACZ,MAAM,CAAC,IACpC,EAACA,MAAM,aAANA,MAAM,gBAAAD,gBAAA,GAANC,MAAM,CAAEQ,OAAO,cAAAT,gBAAA,eAAfA,gBAAA,CAAAhK,IAAA,CAAAiK,MAAM,EAAY,oBAAoB,CAAC,KACxC,CAACI,yBAAyB,IAC1B,CAACC,2BAA2B,IAC5B,CAACI,eAAe,EAChB;QACAhD,cAAc,CAAC,KAAK,CAAC;QACrByB,UAAU,CAACxG,IAAI,CAACqG,KAAK,CAACtH,KAAK,CAAC;MAC9B;IACF,CAAC;IAED,IAAI+F,WAAW,EAAE;MACf;MACA;MACA0C,QAAQ,CAACW,gBAAgB,CAAC,OAAO,EAAEnB,kBAAkB,CAAC;IACxD,CAAC,MAAM;MACLQ,QAAQ,CAACY,mBAAmB,CAAC,OAAO,EAAEpB,kBAAkB,CAAC;IAC3D;IAEA,OAAO;MAAA,OAAMQ,QAAQ,CAACY,mBAAmB,CAAC,OAAO,EAAEpB,kBAAkB,CAAC;IAAA;EACxE,CAAC,EAAE,CAACzD,MAAM,EAAEuB,WAAW,CAAC,CAAC;EAEzB,oBACEpJ,MAAA,YAAA2I,aAAA,CAACrI,OAAA,CAAAqM,eAAe;IACdC,SAAS,eAAAN,MAAA,CAAe9C,SAAS,CAAC+C,OAAO,CAAG;IAC5CM,KAAK,EAAE;MACLC,OAAO,EAAE,aAAa;MACtBC,MAAM,EAAE,SAAS;MACjBC,MAAM,EAAE;IACV,CAAE;IACF,iBAAejE;EAAS,gBAExB/I,MAAA,YAAA2I,aAAA;IAAKsE,OAAO,EAAE,SAATA,OAAOA,CAAA;MAAA,OAAQ5D,cAAc,CAAC,IAAI,CAAC;IAAA,CAAC;IAAC6D,eAAe,EAAE;EAAM,gBAC/DlN,MAAA,YAAA2I,aAAA,CAACnI,YAAA,CAAA2M,WAAW;IAAC9J,KAAK,EAAEA;EAAM,CAAE,CACzB,CAAC,EACL+F,WAAW,iBACVgE,oBAAQ,CAACC,YAAY,cACnBrN,MAAA,YAAA2I,aAAA;IACE2E,GAAG,EAAEhE,UAAW;IAChB,oBAAkBzB,MAAM,CAAC0F,UAAW;IACpCV,KAAK,EAAE;MACL9C,QAAQ,EAAE,UAAU;MACpBH,GAAG,KAAA0C,MAAA,CAAKvC,QAAQ,CAACH,GAAG,OAAI;MACxBC,IAAI,KAAAyC,MAAA,CAAKvC,QAAQ,CAACF,IAAI,OAAI;MAC1B2D,MAAM,EAAE,EAAE;MACVC,UAAU,EAAE,0CAA0C;MACtDC,SAAS,EACP;IACJ;EAAE,gBAEF1N,MAAA,YAAA2I,aAAA,CAACnI,YAAA,CAAAmN,WAAW;IACVtK,KAAK,EAAEA,KAAM;IACbuK,SAAS;IACTC,QAAQ,EAAEjD,YAAa;IACvBkD,MAAM,EAAEhD,UAAW;IACnBV,UAAU,EAAEA,UAAW;IACvBE,oBAAoB,EAAEA,oBAAqB;IAC3CyD,cAAc,EAAEhL,sBAAsB,CAACyH,UAAU,CAAE;IACnDC,kBAAkB,EAAEA,kBAAmB;IACvCC,oBAAoB,EAAEA;EAAqB,CAC5C,CACE,CAAC,EACN,CAAA7C,MAAM,aAANA,MAAM,uBAANA,MAAM,CAAEmG,kBAAkB,KAAIlC,QAAQ,CAACmC,IACzC,CACa,CAAC;AAEtB,CAAC","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"math.js","names":["_react","_interopRequireWildcard","require","_reactDom","_interopRequireDefault","_core","_react2","_prosemirrorState","_mathToolbar","_mathRendering","_toolbar","e","t","WeakMap","r","n","__esModule","o","i","f","__proto__","_typeof","has","get","set","_t","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","ownKeys","keys","getOwnPropertySymbols","filter","enumerable","push","apply","_objectSpread","arguments","length","forEach","_defineProperty2","getOwnPropertyDescriptors","defineProperties","ensureTextAfterMathPluginKey","PluginKey","generateAdditionalKeys","keyData","undefined","map","key","name","latex","write","label","EnsureTextAfterMathPlugin","exports","mathNodeName","Plugin","appendTransaction","transactions","oldState","newState","some","tr","docChanged","changed","doc","descendants","node","pos","type","nextPos","nodeSize","nextNode","nodeAt","insert","schema","text","nodeBeforeZeroWidthSpace","from","_currentDoc$type","_currentDoc$type2","currentDoc","textContent","ZeroWidthSpaceHandlingPlugin","props","handleKeyDown","view","event","state","dispatch","selection","empty","start","resolved","resolve","maybeNode","nodeAfter","nodeBefore","nodeResolved","setSelection","NodeSelection","create","TextSelection","MathNode","Node","group","inline","atom","addAttributes","wrapper","html","addProseMirrorPlugins","parseHTML","tag","getAttrs","el","getAttribute","innerHTML","addCommands","_this","insertMath","_ref","_node$type","editor","nodes","math","$from","sel","setToolbarOpened","renderHTML","_ref2","HTMLAttributes","dangerouslySetInnerHTML","__html","wrapMath","addNodeView","_this2","ReactNodeViewRenderer","createElement","MathNodeView","options","updateAttributes","selected","_useState","useState","_useState2","_slicedToArray2","showToolbar","setShowToolbar","toolbarRef","useRef","timestamp","Date","now","_useState3","top","left","_useState4","position","setPosition","_ref3","_ref3$math","mathOptions","keypadMode","_mathOptions$controll","controlledKeypadMode","_mathOptions$customKe","customKeys","keyPadCharacterRef","setKeypadInteraction","attrs","handleChange","newLatex","handleDone","_editor$state","commands","focus","useEffect","coordsAtPos","editorDOM","element","editorRect","getBoundingClientRect","handleClickOutside","_document$querySelect","_document","_target$closest","_target$closest2","_target$closest3","target","equationEditorListboxes","document","querySelectorAll","equationEditorPopoverOpen","clickedEquationEditorSelect","id","includes","closest","clickedMathNode","concat","current","contains","addEventListener","removeEventListener","NodeViewWrapper","className","style","display","cursor","margin","onClick","contentEditable","MathPreview","ReactDOM","createPortal","ref","instanceId","zIndex","background","boxShadow","MathToolbar","autoFocus","onChange","onDone","additionalKeys","_tiptapContainerEl","body"],"sources":["../../src/extensions/math.js"],"sourcesContent":["import React, { useEffect, useRef, useState } from 'react';\nimport ReactDOM from 'react-dom';\nimport { Node } from '@tiptap/core';\nimport { NodeViewWrapper, ReactNodeViewRenderer } from '@tiptap/react';\nimport { NodeSelection, Plugin, PluginKey, TextSelection } from 'prosemirror-state';\nimport { MathPreview, MathToolbar } from '@pie-lib/math-toolbar';\nimport { wrapMath } from '@pie-lib/math-rendering';\nimport { setToolbarOpened } from '../utils/toolbar';\n\nconst ensureTextAfterMathPluginKey = new PluginKey('ensureTextAfterMath');\n\nconst generateAdditionalKeys = (keyData = []) => {\n return keyData.map((key) => ({\n name: key,\n latex: key,\n write: key,\n label: key,\n }));\n};\n\nexport const EnsureTextAfterMathPlugin = (mathNodeName) =>\n new Plugin({\n key: ensureTextAfterMathPluginKey,\n appendTransaction: (transactions, oldState, newState) => {\n // Only act when the doc actually changed\n if (!transactions.some((tr) => tr.docChanged)) return null;\n\n const tr = newState.tr;\n let changed = false;\n\n newState.doc.descendants((node, pos) => {\n if (node.type.name === mathNodeName) {\n const nextPos = pos + node.nodeSize;\n const nextNode = newState.doc.nodeAt(nextPos);\n\n // If there's no node after, or the next node isn't text, insert a space\n if (!nextNode || nextNode.type.name !== 'text') {\n tr.insert(nextPos, newState.schema.text('\\u200b'));\n changed = true;\n }\n }\n });\n\n return changed ? tr : null;\n },\n });\n\nconst nodeBeforeZeroWidthSpace = (doc, from) => {\n let i;\n\n // finding if previous to the cursor there's a zero-width space\n // and a non-text element, and deleting everything until the space\n for (i = from; i > 0; i--) {\n const currentDoc = doc.nodeAt(i);\n\n if (currentDoc?.type?.name === 'text' && currentDoc.textContent !== '\\u200b') {\n return -1;\n }\n\n if (currentDoc && currentDoc?.type?.name !== 'text') {\n break;\n }\n }\n\n return i;\n};\n\nexport const ZeroWidthSpaceHandlingPlugin = new Plugin({\n key: new PluginKey('zeroWidthSpaceHandling'),\n props: {\n handleKeyDown(view, event) {\n const { state, dispatch } = view;\n const { selection, doc } = state;\n const { from, empty } = selection;\n\n if (empty && event.key === 'Backspace' && from > 0) {\n const start = nodeBeforeZeroWidthSpace(doc, from);\n\n if (start === -1) {\n return false;\n }\n\n const tr = state.tr.delete(start, from);\n dispatch(tr);\n return true; // handled\n }\n\n if (empty && event.key === 'ArrowLeft' && from > 0) {\n const start = nodeBeforeZeroWidthSpace(doc, from);\n\n if (start === -1) {\n return false;\n }\n\n const resolved = state.doc.resolve(start);\n const maybeNode = resolved.nodeAfter || resolved.nodeBefore;\n\n // Check if there's an inline selectable node (e.g., your math node)\n if (maybeNode) {\n const nodeResolved = state.doc.resolve(start);\n const tr = state.tr.setSelection(NodeSelection.create(state.doc, nodeResolved.pos));\n dispatch(tr);\n return true;\n } else {\n // Just move the text cursor before the zwsp\n const tr = state.tr.setSelection(TextSelection.create(state.doc, from - 2));\n dispatch(tr);\n return true;\n }\n }\n\n return false;\n },\n },\n});\n\nexport const MathNode = Node.create({\n name: 'math',\n group: 'inline',\n inline: true,\n atom: true,\n\n addAttributes() {\n return {\n latex: { default: '' },\n wrapper: { default: null },\n html: { default: null },\n };\n },\n\n addProseMirrorPlugins() {\n return [EnsureTextAfterMathPlugin(this.name), ZeroWidthSpaceHandlingPlugin];\n },\n\n parseHTML() {\n return [\n {\n tag: 'span[data-latex]',\n getAttrs: (el) => ({\n latex: el.getAttribute('data-raw') || el.textContent,\n }),\n },\n {\n tag: 'span[data-type=\"mathml\"]',\n getAttrs: (el) => ({\n html: el.innerHTML,\n }),\n },\n ];\n },\n\n addCommands() {\n return {\n insertMath:\n (latex = '') =>\n ({ tr, editor, dispatch }) => {\n const { state } = editor.view;\n const node = state.schema.nodes.math.create({\n latex,\n });\n const { selection } = state;\n\n // The inserted node is typically just before the cursor\n const pos = selection.$from.pos;\n\n tr.insert(pos, node);\n\n if (node?.type?.name === this.name) {\n // Create a NodeSelection from the current doc\n const sel = NodeSelection.create(tr.doc, selection.$from.pos);\n\n // Build a fresh transaction from the current state and set the selection\n tr.setSelection(sel);\n }\n\n dispatch(tr);\n\n setToolbarOpened(editor, true);\n return true;\n },\n };\n },\n\n renderHTML({ HTMLAttributes }) {\n if (HTMLAttributes.html) {\n return ['span', { 'data-type': 'mathml', dangerouslySetInnerHTML: { __html: HTMLAttributes.html } }];\n }\n\n return [\n 'span',\n { 'data-latex': '', 'data-raw': HTMLAttributes.latex },\n wrapMath(HTMLAttributes.latex, HTMLAttributes.wrapper),\n ];\n },\n\n addNodeView() {\n return ReactNodeViewRenderer((props) => <MathNodeView {...{ ...props, options: this.options }} />);\n },\n});\n\nexport const MathNodeView = (props) => {\n const { node, updateAttributes, editor, selected, options } = props;\n const [showToolbar, setShowToolbar] = useState(selected);\n const toolbarRef = useRef(null);\n const timestamp = useRef(Date.now());\n const [position, setPosition] = useState({ top: 0, left: 0 });\n const { math: mathOptions = {} } = options || {};\n const {\n keypadMode,\n controlledKeypadMode = true,\n customKeys = [],\n keyPadCharacterRef,\n setKeypadInteraction,\n } = mathOptions;\n\n const latex = node.attrs.latex || '';\n\n const handleChange = (newLatex) => {\n updateAttributes({ latex: newLatex });\n };\n\n const handleDone = (newLatex) => {\n updateAttributes({ latex: newLatex });\n setShowToolbar(false);\n\n const { selection, tr, doc } = editor.state;\n const sel = TextSelection.create(doc, selection.from + 1);\n\n // Build a fresh transaction from the current state and set the selection\n tr.setSelection(sel);\n editor.view.dispatch(tr);\n editor.commands.focus();\n };\n\n useEffect(() => {\n if (selected) {\n setShowToolbar(true);\n }\n }, [selected]);\n\n useEffect(() => {\n setToolbarOpened(editor, selected || showToolbar);\n }, [editor, showToolbar, selected]);\n\n useEffect(() => {\n // Calculate position relative to selection\n const { from } = editor.state.selection;\n const start = editor.view.coordsAtPos(from);\n const editorDOM = editor.options.element;\n const editorRect = editorDOM.getBoundingClientRect();\n\n setPosition({\n top: start.top - editorRect.top + 40, // shift above\n left: start.left - editorRect.left,\n });\n\n const handleClickOutside = (event) => {\n const target = event?.target;\n\n // MUI's `Select` renders its dropdown options in a portal attached to `document.body`.\n // Those clicks should not dismiss the math toolbar.\n const equationEditorListboxes =\n document.querySelectorAll?.(\n '[id^=\"equation-editor-select\"][id*=\"listbox\"], [aria-labelledby=\"equation-editor-label\"][role=\"listbox\"]',\n ) || [];\n\n const equationEditorPopoverOpen = equationEditorListboxes.length > 0;\n const clickedEquationEditorSelect =\n !!(target?.id && target.id.includes('equation-editor-select')) ||\n !!target?.closest?.('[id*=\"equation-editor-select\"]');\n\n // If the click originated from the math node preview itself (the element\n // that opens the toolbar), ignore it here — the node's own onClick handler\n // will keep/re-open the toolbar. Without this guard, closing and then\n // immediately clicking the math node would fire this listener in the same\n // event cycle and close the toolbar before it could open.\n const clickedMathNode = !!target?.closest?.(`.math-node-${timestamp.current}`);\n\n if (\n toolbarRef.current &&\n !toolbarRef.current.contains(target) &&\n !target?.closest?.('[data-inline-node]') &&\n !equationEditorPopoverOpen &&\n !clickedEquationEditorSelect &&\n !clickedMathNode\n ) {\n setShowToolbar(false);\n handleDone(node.attrs.latex);\n }\n };\n\n if (showToolbar) {\n // Use `click` (not `mousedown`) so interacting with browser UI like the scrollbar\n // doesn't automatically dismiss the math toolbar.\n document.addEventListener('click', handleClickOutside);\n } else {\n document.removeEventListener('click', handleClickOutside);\n }\n\n return () => document.removeEventListener('click', handleClickOutside);\n }, [editor, showToolbar]);\n\n return (\n <NodeViewWrapper\n className={`math-node-${timestamp.current}`}\n style={{\n display: 'inline-flex',\n cursor: 'pointer',\n margin: '0 4px',\n }}\n data-selected={selected}\n >\n <div onClick={() => setShowToolbar(true)} contentEditable={false}>\n <MathPreview latex={latex} />\n </div>\n {showToolbar &&\n ReactDOM.createPortal(\n <div\n ref={toolbarRef}\n data-toolbar-for={editor.instanceId}\n style={{\n position: 'absolute',\n top: `${position.top}px`,\n left: `${position.left}px`,\n zIndex: 20,\n background: 'var(--editable-html-toolbar-bg, #efefef)',\n boxShadow:\n '0px 1px 5px 0px rgba(0, 0, 0, 0.2), 0px 2px 2px 0px rgba(0, 0, 0, 0.14), 0px 3px 1px -2px rgba(0, 0, 0, 0.12)',\n }}\n >\n <MathToolbar\n latex={latex}\n autoFocus\n onChange={handleChange}\n onDone={handleDone}\n keypadMode={keypadMode}\n controlledKeypadMode={controlledKeypadMode}\n additionalKeys={generateAdditionalKeys(customKeys)}\n keyPadCharacterRef={keyPadCharacterRef}\n setKeypadInteraction={setKeypadInteraction}\n />\n </div>,\n editor?._tiptapContainerEl || document.body,\n )}\n </NodeViewWrapper>\n );\n};\n"],"mappings":";;;;;;;;;;AAAA,IAAAA,MAAA,GAAAC,uBAAA,CAAAC,OAAA;AACA,IAAAC,SAAA,GAAAC,sBAAA,CAAAF,OAAA;AACA,IAAAG,KAAA,GAAAH,OAAA;AACA,IAAAI,OAAA,GAAAJ,OAAA;AACA,IAAAK,iBAAA,GAAAL,OAAA;AACA,IAAAM,YAAA,GAAAN,OAAA;AACA,IAAAO,cAAA,GAAAP,OAAA;AACA,IAAAQ,QAAA,GAAAR,OAAA;AAAoD,SAAAD,wBAAAU,CAAA,EAAAC,CAAA,6BAAAC,OAAA,MAAAC,CAAA,OAAAD,OAAA,IAAAE,CAAA,OAAAF,OAAA,YAAAZ,uBAAA,YAAAA,wBAAAU,CAAA,EAAAC,CAAA,SAAAA,CAAA,IAAAD,CAAA,IAAAA,CAAA,CAAAK,UAAA,SAAAL,CAAA,MAAAM,CAAA,EAAAC,CAAA,EAAAC,CAAA,KAAAC,SAAA,mBAAAT,CAAA,iBAAAA,CAAA,gBAAAU,OAAA,CAAAV,CAAA,0BAAAA,CAAA,SAAAQ,CAAA,MAAAF,CAAA,GAAAL,CAAA,GAAAG,CAAA,GAAAD,CAAA,QAAAG,CAAA,CAAAK,GAAA,CAAAX,CAAA,UAAAM,CAAA,CAAAM,GAAA,CAAAZ,CAAA,GAAAM,CAAA,CAAAO,GAAA,CAAAb,CAAA,EAAAQ,CAAA,cAAAM,EAAA,IAAAd,CAAA,gBAAAc,EAAA,OAAAC,cAAA,CAAAC,IAAA,CAAAhB,CAAA,EAAAc,EAAA,OAAAP,CAAA,IAAAD,CAAA,GAAAW,MAAA,CAAAC,cAAA,KAAAD,MAAA,CAAAE,wBAAA,CAAAnB,CAAA,EAAAc,EAAA,OAAAP,CAAA,CAAAK,GAAA,IAAAL,CAAA,CAAAM,GAAA,IAAAP,CAAA,CAAAE,CAAA,EAAAM,EAAA,EAAAP,CAAA,IAAAC,CAAA,CAAAM,EAAA,IAAAd,CAAA,CAAAc,EAAA,WAAAN,CAAA,KAAAR,CAAA,EAAAC,CAAA;AAAA,SAAAmB,QAAApB,CAAA,EAAAG,CAAA,QAAAF,CAAA,GAAAgB,MAAA,CAAAI,IAAA,CAAArB,CAAA,OAAAiB,MAAA,CAAAK,qBAAA,QAAAhB,CAAA,GAAAW,MAAA,CAAAK,qBAAA,CAAAtB,CAAA,GAAAG,CAAA,KAAAG,CAAA,GAAAA,CAAA,CAAAiB,MAAA,WAAApB,CAAA,WAAAc,MAAA,CAAAE,wBAAA,CAAAnB,CAAA,EAAAG,CAAA,EAAAqB,UAAA,OAAAvB,CAAA,CAAAwB,IAAA,CAAAC,KAAA,CAAAzB,CAAA,EAAAK,CAAA,YAAAL,CAAA;AAAA,SAAA0B,cAAA3B,CAAA,aAAAG,CAAA,MAAAA,CAAA,GAAAyB,SAAA,CAAAC,MAAA,EAAA1B,CAAA,UAAAF,CAAA,WAAA2B,SAAA,CAAAzB,CAAA,IAAAyB,SAAA,CAAAzB,CAAA,QAAAA,CAAA,OAAAiB,OAAA,CAAAH,MAAA,CAAAhB,CAAA,OAAA6B,OAAA,WAAA3B,CAAA,QAAA4B,gBAAA,aAAA/B,CAAA,EAAAG,CAAA,EAAAF,CAAA,CAAAE,CAAA,SAAAc,MAAA,CAAAe,yBAAA,GAAAf,MAAA,CAAAgB,gBAAA,CAAAjC,CAAA,EAAAiB,MAAA,CAAAe,yBAAA,CAAA/B,CAAA,KAAAmB,OAAA,CAAAH,MAAA,CAAAhB,CAAA,GAAA6B,OAAA,WAAA3B,CAAA,IAAAc,MAAA,CAAAC,cAAA,CAAAlB,CAAA,EAAAG,CAAA,EAAAc,MAAA,CAAAE,wBAAA,CAAAlB,CAAA,EAAAE,CAAA,iBAAAH,CAAA;AAEpD,IAAMkC,4BAA4B,GAAG,IAAIC,2BAAS,CAAC,qBAAqB,CAAC;AAEzE,IAAMC,sBAAsB,GAAG,SAAzBA,sBAAsBA,CAAA,EAAqB;EAAA,IAAjBC,OAAO,GAAAT,SAAA,CAAAC,MAAA,QAAAD,SAAA,QAAAU,SAAA,GAAAV,SAAA,MAAG,EAAE;EAC1C,OAAOS,OAAO,CAACE,GAAG,CAAC,UAACC,GAAG;IAAA,OAAM;MAC3BC,IAAI,EAAED,GAAG;MACTE,KAAK,EAAEF,GAAG;MACVG,KAAK,EAAEH,GAAG;MACVI,KAAK,EAAEJ;IACT,CAAC;EAAA,CAAC,CAAC;AACL,CAAC;AAEM,IAAMK,yBAAyB,GAAAC,OAAA,CAAAD,yBAAA,GAAG,SAA5BA,yBAAyBA,CAAIE,YAAY;EAAA,OACpD,IAAIC,wBAAM,CAAC;IACTR,GAAG,EAAEN,4BAA4B;IACjCe,iBAAiB,EAAE,SAAnBA,iBAAiBA,CAAGC,YAAY,EAAEC,QAAQ,EAAEC,QAAQ,EAAK;MACvD;MACA,IAAI,CAACF,YAAY,CAACG,IAAI,CAAC,UAACC,EAAE;QAAA,OAAKA,EAAE,CAACC,UAAU;MAAA,EAAC,EAAE,OAAO,IAAI;MAE1D,IAAMD,EAAE,GAAGF,QAAQ,CAACE,EAAE;MACtB,IAAIE,OAAO,GAAG,KAAK;MAEnBJ,QAAQ,CAACK,GAAG,CAACC,WAAW,CAAC,UAACC,IAAI,EAAEC,GAAG,EAAK;QACtC,IAAID,IAAI,CAACE,IAAI,CAACpB,IAAI,KAAKM,YAAY,EAAE;UACnC,IAAMe,OAAO,GAAGF,GAAG,GAAGD,IAAI,CAACI,QAAQ;UACnC,IAAMC,QAAQ,GAAGZ,QAAQ,CAACK,GAAG,CAACQ,MAAM,CAACH,OAAO,CAAC;;UAE7C;UACA,IAAI,CAACE,QAAQ,IAAIA,QAAQ,CAACH,IAAI,CAACpB,IAAI,KAAK,MAAM,EAAE;YAC9Ca,EAAE,CAACY,MAAM,CAACJ,OAAO,EAAEV,QAAQ,CAACe,MAAM,CAACC,IAAI,CAAC,QAAQ,CAAC,CAAC;YAClDZ,OAAO,GAAG,IAAI;UAChB;QACF;MACF,CAAC,CAAC;MAEF,OAAOA,OAAO,GAAGF,EAAE,GAAG,IAAI;IAC5B;EACF,CAAC,CAAC;AAAA;AAEJ,IAAMe,wBAAwB,GAAG,SAA3BA,wBAAwBA,CAAIZ,GAAG,EAAEa,IAAI,EAAK;EAC9C,IAAI/D,CAAC;;EAEL;EACA;EACA,KAAKA,CAAC,GAAG+D,IAAI,EAAE/D,CAAC,GAAG,CAAC,EAAEA,CAAC,EAAE,EAAE;IAAA,IAAAgE,gBAAA,EAAAC,iBAAA;IACzB,IAAMC,UAAU,GAAGhB,GAAG,CAACQ,MAAM,CAAC1D,CAAC,CAAC;IAEhC,IAAI,CAAAkE,UAAU,aAAVA,UAAU,gBAAAF,gBAAA,GAAVE,UAAU,CAAEZ,IAAI,cAAAU,gBAAA,uBAAhBA,gBAAA,CAAkB9B,IAAI,MAAK,MAAM,IAAIgC,UAAU,CAACC,WAAW,KAAK,QAAQ,EAAE;MAC5E,OAAO,CAAC,CAAC;IACX;IAEA,IAAID,UAAU,IAAI,CAAAA,UAAU,aAAVA,UAAU,gBAAAD,iBAAA,GAAVC,UAAU,CAAEZ,IAAI,cAAAW,iBAAA,uBAAhBA,iBAAA,CAAkB/B,IAAI,MAAK,MAAM,EAAE;MACnD;IACF;EACF;EAEA,OAAOlC,CAAC;AACV,CAAC;AAEM,IAAMoE,4BAA4B,GAAA7B,OAAA,CAAA6B,4BAAA,GAAG,IAAI3B,wBAAM,CAAC;EACrDR,GAAG,EAAE,IAAIL,2BAAS,CAAC,wBAAwB,CAAC;EAC5CyC,KAAK,EAAE;IACLC,aAAa,WAAbA,aAAaA,CAACC,IAAI,EAAEC,KAAK,EAAE;MACzB,IAAQC,KAAK,GAAeF,IAAI,CAAxBE,KAAK;QAAEC,QAAQ,GAAKH,IAAI,CAAjBG,QAAQ;MACvB,IAAQC,SAAS,GAAUF,KAAK,CAAxBE,SAAS;QAAEzB,GAAG,GAAKuB,KAAK,CAAbvB,GAAG;MACtB,IAAQa,IAAI,GAAYY,SAAS,CAAzBZ,IAAI;QAAEa,KAAK,GAAKD,SAAS,CAAnBC,KAAK;MAEnB,IAAIA,KAAK,IAAIJ,KAAK,CAACvC,GAAG,KAAK,WAAW,IAAI8B,IAAI,GAAG,CAAC,EAAE;QAClD,IAAMc,KAAK,GAAGf,wBAAwB,CAACZ,GAAG,EAAEa,IAAI,CAAC;QAEjD,IAAIc,KAAK,KAAK,CAAC,CAAC,EAAE;UAChB,OAAO,KAAK;QACd;QAEA,IAAM9B,EAAE,GAAG0B,KAAK,CAAC1B,EAAE,UAAO,CAAC8B,KAAK,EAAEd,IAAI,CAAC;QACvCW,QAAQ,CAAC3B,EAAE,CAAC;QACZ,OAAO,IAAI,CAAC,CAAC;MACf;MAEA,IAAI6B,KAAK,IAAIJ,KAAK,CAACvC,GAAG,KAAK,WAAW,IAAI8B,IAAI,GAAG,CAAC,EAAE;QAClD,IAAMc,MAAK,GAAGf,wBAAwB,CAACZ,GAAG,EAAEa,IAAI,CAAC;QAEjD,IAAIc,MAAK,KAAK,CAAC,CAAC,EAAE;UAChB,OAAO,KAAK;QACd;QAEA,IAAMC,QAAQ,GAAGL,KAAK,CAACvB,GAAG,CAAC6B,OAAO,CAACF,MAAK,CAAC;QACzC,IAAMG,SAAS,GAAGF,QAAQ,CAACG,SAAS,IAAIH,QAAQ,CAACI,UAAU;;QAE3D;QACA,IAAIF,SAAS,EAAE;UACb,IAAMG,YAAY,GAAGV,KAAK,CAACvB,GAAG,CAAC6B,OAAO,CAACF,MAAK,CAAC;UAC7C,IAAM9B,GAAE,GAAG0B,KAAK,CAAC1B,EAAE,CAACqC,YAAY,CAACC,+BAAa,CAACC,MAAM,CAACb,KAAK,CAACvB,GAAG,EAAEiC,YAAY,CAAC9B,GAAG,CAAC,CAAC;UACnFqB,QAAQ,CAAC3B,GAAE,CAAC;UACZ,OAAO,IAAI;QACb,CAAC,MAAM;UACL;UACA,IAAMA,IAAE,GAAG0B,KAAK,CAAC1B,EAAE,CAACqC,YAAY,CAACG,+BAAa,CAACD,MAAM,CAACb,KAAK,CAACvB,GAAG,EAAEa,IAAI,GAAG,CAAC,CAAC,CAAC;UAC3EW,QAAQ,CAAC3B,IAAE,CAAC;UACZ,OAAO,IAAI;QACb;MACF;MAEA,OAAO,KAAK;IACd;EACF;AACF,CAAC,CAAC;AAEK,IAAMyC,QAAQ,GAAAjD,OAAA,CAAAiD,QAAA,GAAGC,UAAI,CAACH,MAAM,CAAC;EAClCpD,IAAI,EAAE,MAAM;EACZwD,KAAK,EAAE,QAAQ;EACfC,MAAM,EAAE,IAAI;EACZC,IAAI,EAAE,IAAI;EAEVC,aAAa,WAAbA,aAAaA,CAAA,EAAG;IACd,OAAO;MACL1D,KAAK,EAAE;QAAE,WAAS;MAAG,CAAC;MACtB2D,OAAO,EAAE;QAAE,WAAS;MAAK,CAAC;MAC1BC,IAAI,EAAE;QAAE,WAAS;MAAK;IACxB,CAAC;EACH,CAAC;EAEDC,qBAAqB,WAArBA,qBAAqBA,CAAA,EAAG;IACtB,OAAO,CAAC1D,yBAAyB,CAAC,IAAI,CAACJ,IAAI,CAAC,EAAEkC,4BAA4B,CAAC;EAC7E,CAAC;EAED6B,SAAS,WAATA,SAASA,CAAA,EAAG;IACV,OAAO,CACL;MACEC,GAAG,EAAE,kBAAkB;MACvBC,QAAQ,EAAE,SAAVA,QAAQA,CAAGC,EAAE;QAAA,OAAM;UACjBjE,KAAK,EAAEiE,EAAE,CAACC,YAAY,CAAC,UAAU,CAAC,IAAID,EAAE,CAACjC;QAC3C,CAAC;MAAA;IACH,CAAC,EACD;MACE+B,GAAG,EAAE,0BAA0B;MAC/BC,QAAQ,EAAE,SAAVA,QAAQA,CAAGC,EAAE;QAAA,OAAM;UACjBL,IAAI,EAAEK,EAAE,CAACE;QACX,CAAC;MAAA;IACH,CAAC,CACF;EACH,CAAC;EAEDC,WAAW,WAAXA,WAAWA,CAAA,EAAG;IAAA,IAAAC,KAAA;IACZ,OAAO;MACLC,UAAU,EACR,SADFA,UAAUA,CAAA;QAAA,IACPtE,KAAK,GAAAd,SAAA,CAAAC,MAAA,QAAAD,SAAA,QAAAU,SAAA,GAAAV,SAAA,MAAG,EAAE;QAAA,OACX,UAAAqF,IAAA,EAA8B;UAAA,IAAAC,UAAA;UAAA,IAA3B5D,EAAE,GAAA2D,IAAA,CAAF3D,EAAE;YAAE6D,MAAM,GAAAF,IAAA,CAANE,MAAM;YAAElC,QAAQ,GAAAgC,IAAA,CAARhC,QAAQ;UACrB,IAAQD,KAAK,GAAKmC,MAAM,CAACrC,IAAI,CAArBE,KAAK;UACb,IAAMrB,IAAI,GAAGqB,KAAK,CAACb,MAAM,CAACiD,KAAK,CAACC,IAAI,CAACxB,MAAM,CAAC;YAC1CnD,KAAK,EAALA;UACF,CAAC,CAAC;UACF,IAAQwC,SAAS,GAAKF,KAAK,CAAnBE,SAAS;;UAEjB;UACA,IAAMtB,GAAG,GAAGsB,SAAS,CAACoC,KAAK,CAAC1D,GAAG;UAE/BN,EAAE,CAACY,MAAM,CAACN,GAAG,EAAED,IAAI,CAAC;UAEpB,IAAI,CAAAA,IAAI,aAAJA,IAAI,gBAAAuD,UAAA,GAAJvD,IAAI,CAAEE,IAAI,cAAAqD,UAAA,uBAAVA,UAAA,CAAYzE,IAAI,MAAKsE,KAAI,CAACtE,IAAI,EAAE;YAClC;YACA,IAAM8E,GAAG,GAAG3B,+BAAa,CAACC,MAAM,CAACvC,EAAE,CAACG,GAAG,EAAEyB,SAAS,CAACoC,KAAK,CAAC1D,GAAG,CAAC;;YAE7D;YACAN,EAAE,CAACqC,YAAY,CAAC4B,GAAG,CAAC;UACtB;UAEAtC,QAAQ,CAAC3B,EAAE,CAAC;UAEZ,IAAAkE,yBAAgB,EAACL,MAAM,EAAE,IAAI,CAAC;UAC9B,OAAO,IAAI;QACb,CAAC;MAAA;IACL,CAAC;EACH,CAAC;EAEDM,UAAU,WAAVA,UAAUA,CAAAC,KAAA,EAAqB;IAAA,IAAlBC,cAAc,GAAAD,KAAA,CAAdC,cAAc;IACzB,IAAIA,cAAc,CAACrB,IAAI,EAAE;MACvB,OAAO,CAAC,MAAM,EAAE;QAAE,WAAW,EAAE,QAAQ;QAAEsB,uBAAuB,EAAE;UAAEC,MAAM,EAAEF,cAAc,CAACrB;QAAK;MAAE,CAAC,CAAC;IACtG;IAEA,OAAO,CACL,MAAM,EACN;MAAE,YAAY,EAAE,EAAE;MAAE,UAAU,EAAEqB,cAAc,CAACjF;IAAM,CAAC,EACtD,IAAAoF,uBAAQ,EAACH,cAAc,CAACjF,KAAK,EAAEiF,cAAc,CAACtB,OAAO,CAAC,CACvD;EACH,CAAC;EAED0B,WAAW,WAAXA,WAAWA,CAAA,EAAG;IAAA,IAAAC,MAAA;IACZ,OAAO,IAAAC,6BAAqB,EAAC,UAACrD,KAAK;MAAA,oBAAKvF,MAAA,YAAA6I,aAAA,CAACC,YAAY,EAAAxG,aAAA,CAAAA,aAAA,KAAUiD,KAAK;QAAEwD,OAAO,EAAEJ,MAAI,CAACI;MAAO,EAAK,CAAC;IAAA,EAAC;EACpG;AACF,CAAC,CAAC;AAEK,IAAMD,YAAY,GAAArF,OAAA,CAAAqF,YAAA,GAAG,SAAfA,YAAYA,CAAIvD,KAAK,EAAK;EACrC,IAAQjB,IAAI,GAAkDiB,KAAK,CAA3DjB,IAAI;IAAE0E,gBAAgB,GAAgCzD,KAAK,CAArDyD,gBAAgB;IAAElB,MAAM,GAAwBvC,KAAK,CAAnCuC,MAAM;IAAEmB,QAAQ,GAAc1D,KAAK,CAA3B0D,QAAQ;IAAEF,OAAO,GAAKxD,KAAK,CAAjBwD,OAAO;EACzD,IAAAG,SAAA,GAAsC,IAAAC,eAAQ,EAACF,QAAQ,CAAC;IAAAG,UAAA,OAAAC,eAAA,aAAAH,SAAA;IAAjDI,WAAW,GAAAF,UAAA;IAAEG,cAAc,GAAAH,UAAA;EAClC,IAAMI,UAAU,GAAG,IAAAC,aAAM,EAAC,IAAI,CAAC;EAC/B,IAAMC,SAAS,GAAG,IAAAD,aAAM,EAACE,IAAI,CAACC,GAAG,CAAC,CAAC,CAAC;EACpC,IAAAC,UAAA,GAAgC,IAAAV,eAAQ,EAAC;MAAEW,GAAG,EAAE,CAAC;MAAEC,IAAI,EAAE;IAAE,CAAC,CAAC;IAAAC,UAAA,OAAAX,eAAA,aAAAQ,UAAA;IAAtDI,QAAQ,GAAAD,UAAA;IAAEE,WAAW,GAAAF,UAAA;EAC5B,IAAAG,KAAA,GAAmCpB,OAAO,IAAI,CAAC,CAAC;IAAAqB,UAAA,GAAAD,KAAA,CAAxCnC,IAAI;IAAEqC,WAAW,GAAAD,UAAA,cAAG,CAAC,CAAC,GAAAA,UAAA;EAC9B,IACEE,UAAU,GAKRD,WAAW,CALbC,UAAU;IAAAC,qBAAA,GAKRF,WAAW,CAJbG,oBAAoB;IAApBA,oBAAoB,GAAAD,qBAAA,cAAG,IAAI,GAAAA,qBAAA;IAAAE,qBAAA,GAIzBJ,WAAW,CAHbK,UAAU;IAAVA,UAAU,GAAAD,qBAAA,cAAG,EAAE,GAAAA,qBAAA;IACfE,kBAAkB,GAEhBN,WAAW,CAFbM,kBAAkB;IAClBC,oBAAoB,GAClBP,WAAW,CADbO,oBAAoB;EAGtB,IAAMvH,KAAK,GAAGiB,IAAI,CAACuG,KAAK,CAACxH,KAAK,IAAI,EAAE;EAEpC,IAAMyH,YAAY,GAAG,SAAfA,YAAYA,CAAIC,QAAQ,EAAK;IACjC/B,gBAAgB,CAAC;MAAE3F,KAAK,EAAE0H;IAAS,CAAC,CAAC;EACvC,CAAC;EAED,IAAMC,UAAU,GAAG,SAAbA,UAAUA,CAAID,QAAQ,EAAK;IAC/B/B,gBAAgB,CAAC;MAAE3F,KAAK,EAAE0H;IAAS,CAAC,CAAC;IACrCxB,cAAc,CAAC,KAAK,CAAC;IAErB,IAAA0B,aAAA,GAA+BnD,MAAM,CAACnC,KAAK;MAAnCE,SAAS,GAAAoF,aAAA,CAATpF,SAAS;MAAE5B,EAAE,GAAAgH,aAAA,CAAFhH,EAAE;MAAEG,GAAG,GAAA6G,aAAA,CAAH7G,GAAG;IAC1B,IAAM8D,GAAG,GAAGzB,+BAAa,CAACD,MAAM,CAACpC,GAAG,EAAEyB,SAAS,CAACZ,IAAI,GAAG,CAAC,CAAC;;IAEzD;IACAhB,EAAE,CAACqC,YAAY,CAAC4B,GAAG,CAAC;IACpBJ,MAAM,CAACrC,IAAI,CAACG,QAAQ,CAAC3B,EAAE,CAAC;IACxB6D,MAAM,CAACoD,QAAQ,CAACC,KAAK,CAAC,CAAC;EACzB,CAAC;EAED,IAAAC,gBAAS,EAAC,YAAM;IACd,IAAInC,QAAQ,EAAE;MACZM,cAAc,CAAC,IAAI,CAAC;IACtB;EACF,CAAC,EAAE,CAACN,QAAQ,CAAC,CAAC;EAEd,IAAAmC,gBAAS,EAAC,YAAM;IACd,IAAAjD,yBAAgB,EAACL,MAAM,EAAEmB,QAAQ,IAAIK,WAAW,CAAC;EACnD,CAAC,EAAE,CAACxB,MAAM,EAAEwB,WAAW,EAAEL,QAAQ,CAAC,CAAC;EAEnC,IAAAmC,gBAAS,EAAC,YAAM;IACd;IACA,IAAQnG,IAAI,GAAK6C,MAAM,CAACnC,KAAK,CAACE,SAAS,CAA/BZ,IAAI;IACZ,IAAMc,KAAK,GAAG+B,MAAM,CAACrC,IAAI,CAAC4F,WAAW,CAACpG,IAAI,CAAC;IAC3C,IAAMqG,SAAS,GAAGxD,MAAM,CAACiB,OAAO,CAACwC,OAAO;IACxC,IAAMC,UAAU,GAAGF,SAAS,CAACG,qBAAqB,CAAC,CAAC;IAEpDvB,WAAW,CAAC;MACVJ,GAAG,EAAE/D,KAAK,CAAC+D,GAAG,GAAG0B,UAAU,CAAC1B,GAAG,GAAG,EAAE;MAAE;MACtCC,IAAI,EAAEhE,KAAK,CAACgE,IAAI,GAAGyB,UAAU,CAACzB;IAChC,CAAC,CAAC;IAEF,IAAM2B,kBAAkB,GAAG,SAArBA,kBAAkBA,CAAIhG,KAAK,EAAK;MAAA,IAAAiG,qBAAA,EAAAC,SAAA,EAAAC,eAAA,EAAAC,gBAAA,EAAAC,gBAAA;MACpC,IAAMC,MAAM,GAAGtG,KAAK,aAALA,KAAK,uBAALA,KAAK,CAAEsG,MAAM;;MAE5B;MACA;MACA,IAAMC,uBAAuB,GAC3B,EAAAN,qBAAA,IAAAC,SAAA,GAAAM,QAAQ,EAACC,gBAAgB,cAAAR,qBAAA,uBAAzBA,qBAAA,CAAAhK,IAAA,CAAAiK,SAAA,EACE,0GACF,CAAC,KAAI,EAAE;MAET,IAAMQ,yBAAyB,GAAGH,uBAAuB,CAACzJ,MAAM,GAAG,CAAC;MACpE,IAAM6J,2BAA2B,GAC/B,CAAC,EAAEL,MAAM,aAANA,MAAM,eAANA,MAAM,CAAEM,EAAE,IAAIN,MAAM,CAACM,EAAE,CAACC,QAAQ,CAAC,wBAAwB,CAAC,CAAC,IAC9D,CAAC,EAACP,MAAM,aAANA,MAAM,gBAAAH,eAAA,GAANG,MAAM,CAAEQ,OAAO,cAAAX,eAAA,eAAfA,eAAA,CAAAlK,IAAA,CAAAqK,MAAM,EAAY,gCAAgC,CAAC;;MAEvD;MACA;MACA;MACA;MACA;MACA,IAAMS,eAAe,GAAG,CAAC,EAACT,MAAM,aAANA,MAAM,gBAAAF,gBAAA,GAANE,MAAM,CAAEQ,OAAO,cAAAV,gBAAA,eAAfA,gBAAA,CAAAnK,IAAA,CAAAqK,MAAM,gBAAAU,MAAA,CAA0BhD,SAAS,CAACiD,OAAO,CAAE,CAAC;MAE9E,IACEnD,UAAU,CAACmD,OAAO,IAClB,CAACnD,UAAU,CAACmD,OAAO,CAACC,QAAQ,CAACZ,MAAM,CAAC,IACpC,EAACA,MAAM,aAANA,MAAM,gBAAAD,gBAAA,GAANC,MAAM,CAAEQ,OAAO,cAAAT,gBAAA,eAAfA,gBAAA,CAAApK,IAAA,CAAAqK,MAAM,EAAY,oBAAoB,CAAC,KACxC,CAACI,yBAAyB,IAC1B,CAACC,2BAA2B,IAC5B,CAACI,eAAe,EAChB;QACAlD,cAAc,CAAC,KAAK,CAAC;QACrByB,UAAU,CAAC1G,IAAI,CAACuG,KAAK,CAACxH,KAAK,CAAC;MAC9B;IACF,CAAC;IAED,IAAIiG,WAAW,EAAE;MACf;MACA;MACA4C,QAAQ,CAACW,gBAAgB,CAAC,OAAO,EAAEnB,kBAAkB,CAAC;IACxD,CAAC,MAAM;MACLQ,QAAQ,CAACY,mBAAmB,CAAC,OAAO,EAAEpB,kBAAkB,CAAC;IAC3D;IAEA,OAAO;MAAA,OAAMQ,QAAQ,CAACY,mBAAmB,CAAC,OAAO,EAAEpB,kBAAkB,CAAC;IAAA;EACxE,CAAC,EAAE,CAAC5D,MAAM,EAAEwB,WAAW,CAAC,CAAC;EAEzB,oBACEtJ,MAAA,YAAA6I,aAAA,CAACvI,OAAA,CAAAyM,eAAe;IACdC,SAAS,eAAAN,MAAA,CAAehD,SAAS,CAACiD,OAAO,CAAG;IAC5CM,KAAK,EAAE;MACLC,OAAO,EAAE,aAAa;MACtBC,MAAM,EAAE,SAAS;MACjBC,MAAM,EAAE;IACV,CAAE;IACF,iBAAenE;EAAS,gBAExBjJ,MAAA,YAAA6I,aAAA;IAAKwE,OAAO,EAAE,SAATA,OAAOA,CAAA;MAAA,OAAQ9D,cAAc,CAAC,IAAI,CAAC;IAAA,CAAC;IAAC+D,eAAe,EAAE;EAAM,gBAC/DtN,MAAA,YAAA6I,aAAA,CAACrI,YAAA,CAAA+M,WAAW;IAAClK,KAAK,EAAEA;EAAM,CAAE,CACzB,CAAC,EACLiG,WAAW,iBACVkE,oBAAQ,CAACC,YAAY,cACnBzN,MAAA,YAAA6I,aAAA;IACE6E,GAAG,EAAElE,UAAW;IAChB,oBAAkB1B,MAAM,CAAC6F,UAAW;IACpCV,KAAK,EAAE;MACLhD,QAAQ,EAAE,UAAU;MACpBH,GAAG,KAAA4C,MAAA,CAAKzC,QAAQ,CAACH,GAAG,OAAI;MACxBC,IAAI,KAAA2C,MAAA,CAAKzC,QAAQ,CAACF,IAAI,OAAI;MAC1B6D,MAAM,EAAE,EAAE;MACVC,UAAU,EAAE,0CAA0C;MACtDC,SAAS,EACP;IACJ;EAAE,gBAEF9N,MAAA,YAAA6I,aAAA,CAACrI,YAAA,CAAAuN,WAAW;IACV1K,KAAK,EAAEA,KAAM;IACb2K,SAAS;IACTC,QAAQ,EAAEnD,YAAa;IACvBoD,MAAM,EAAElD,UAAW;IACnBV,UAAU,EAAEA,UAAW;IACvBE,oBAAoB,EAAEA,oBAAqB;IAC3C2D,cAAc,EAAEpL,sBAAsB,CAAC2H,UAAU,CAAE;IACnDC,kBAAkB,EAAEA,kBAAmB;IACvCC,oBAAoB,EAAEA;EAAqB,CAC5C,CACE,CAAC,EACN,CAAA9C,MAAM,aAANA,MAAM,uBAANA,MAAM,CAAEsG,kBAAkB,KAAIlC,QAAQ,CAACmC,IACzC,CACa,CAAC;AAEtB,CAAC","ignoreList":[]}
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"publishConfig": {
|
|
4
4
|
"access": "public"
|
|
5
5
|
},
|
|
6
|
-
"version": "2.1.2-next.
|
|
6
|
+
"version": "2.1.2-next.51+2e746851d",
|
|
7
7
|
"description": "",
|
|
8
8
|
"license": "ISC",
|
|
9
9
|
"main": "lib/index.js",
|
|
@@ -59,6 +59,6 @@
|
|
|
59
59
|
"peerDependencies": {
|
|
60
60
|
"react": "^18.2.0"
|
|
61
61
|
},
|
|
62
|
-
"gitHead": "
|
|
62
|
+
"gitHead": "2e746851d8b7966a72f67fac35db7334664fb383",
|
|
63
63
|
"scripts": {}
|
|
64
64
|
}
|
|
@@ -78,25 +78,52 @@ export function CharacterPicker({ editor, opts, onClose }) {
|
|
|
78
78
|
useEffect(() => {
|
|
79
79
|
if (!editor) return;
|
|
80
80
|
|
|
81
|
-
// Calculate position relative to selection
|
|
82
81
|
const editorDOM = editor.options.element;
|
|
83
|
-
const
|
|
84
|
-
const bodyRect = document.body.getBoundingClientRect();
|
|
85
|
-
const { from } = editor.state.selection;
|
|
86
|
-
const start = editor.view.coordsAtPos(from);
|
|
82
|
+
const editorViewDom = editor.view.dom;
|
|
87
83
|
|
|
88
|
-
|
|
84
|
+
// Position is computed in viewport coordinates (the dialog uses position: fixed),
|
|
85
|
+
// so coordsAtPos / getBoundingClientRect values can be used directly without
|
|
86
|
+
// adding scroll offsets. The dialog is then clamped to the viewport so it does
|
|
87
|
+
// not get cut off by fixed page headers/footers.
|
|
88
|
+
const updatePosition = () => {
|
|
89
|
+
if (!containerRef.current) return;
|
|
89
90
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
91
|
+
const editorRect = editorDOM.getBoundingClientRect();
|
|
92
|
+
const { from } = editor.state.selection;
|
|
93
|
+
const start = editor.view.coordsAtPos(from);
|
|
93
94
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
left: start.left,
|
|
97
|
-
});
|
|
95
|
+
const dialogHeight = containerRef.current.offsetHeight;
|
|
96
|
+
const dialogWidth = containerRef.current.offsetWidth;
|
|
98
97
|
|
|
99
|
-
|
|
98
|
+
// prefer below the editor; flip above when there isn't room below.
|
|
99
|
+
const spaceBelow = window.innerHeight - (editorRect.bottom + 60);
|
|
100
|
+
let top =
|
|
101
|
+
spaceBelow >= dialogHeight || editorRect.top < dialogHeight + 80
|
|
102
|
+
? editorRect.bottom + 60
|
|
103
|
+
: editorRect.top - dialogHeight - 20;
|
|
104
|
+
|
|
105
|
+
let left = start.left;
|
|
106
|
+
|
|
107
|
+
const margin = 8;
|
|
108
|
+
top = Math.max(margin, Math.min(top, window.innerHeight - dialogHeight - margin));
|
|
109
|
+
left = Math.max(margin, Math.min(left, window.innerWidth - dialogWidth - margin));
|
|
110
|
+
|
|
111
|
+
setPosition({ top, left });
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
updatePosition();
|
|
115
|
+
|
|
116
|
+
let frame = null;
|
|
117
|
+
const scheduleUpdate = () => {
|
|
118
|
+
if (frame !== null) return;
|
|
119
|
+
frame = requestAnimationFrame(() => {
|
|
120
|
+
frame = null;
|
|
121
|
+
updatePosition();
|
|
122
|
+
});
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
window.addEventListener('scroll', scheduleUpdate, true);
|
|
126
|
+
window.addEventListener('resize', scheduleUpdate);
|
|
100
127
|
|
|
101
128
|
const handleClickOutside = (e) => {
|
|
102
129
|
if (containerRef.current && !containerRef.current.contains(e.target) && !editorViewDom.contains(e.target)) {
|
|
@@ -110,6 +137,9 @@ export function CharacterPicker({ editor, opts, onClose }) {
|
|
|
110
137
|
|
|
111
138
|
return () => {
|
|
112
139
|
clearTimeout(timeoutId);
|
|
140
|
+
if (frame !== null) cancelAnimationFrame(frame);
|
|
141
|
+
window.removeEventListener('scroll', scheduleUpdate, true);
|
|
142
|
+
window.removeEventListener('resize', scheduleUpdate);
|
|
113
143
|
document.removeEventListener('click', handleClickOutside);
|
|
114
144
|
};
|
|
115
145
|
}, [editor]);
|
|
@@ -131,11 +161,11 @@ export function CharacterPicker({ editor, opts, onClose }) {
|
|
|
131
161
|
data-toolbar-for={editor.instanceId}
|
|
132
162
|
style={{
|
|
133
163
|
visibility: position.top === 0 && position.left === 0 ? 'hidden' : 'initial',
|
|
134
|
-
position: '
|
|
164
|
+
position: 'fixed',
|
|
135
165
|
top: `${position.top}px`,
|
|
136
166
|
left: `${position.left}px`,
|
|
137
167
|
maxWidth: '500px',
|
|
138
|
-
zIndex:
|
|
168
|
+
zIndex: 1000,
|
|
139
169
|
}}
|
|
140
170
|
>
|
|
141
171
|
<div>
|
|
@@ -234,7 +234,16 @@ describe('CharacterPicker', () => {
|
|
|
234
234
|
};
|
|
235
235
|
const { container } = render(<CharacterPicker editor={mockEditor} opts={opts} onClose={jest.fn()} />);
|
|
236
236
|
const dialog = container.querySelector('.insert-character-dialog');
|
|
237
|
-
expect(dialog).toHaveStyle({ position: '
|
|
237
|
+
expect(dialog).toHaveStyle({ position: 'fixed' });
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
it('renders above other editor overlays with a high z-index', () => {
|
|
241
|
+
const opts = {
|
|
242
|
+
characters: [['á']],
|
|
243
|
+
};
|
|
244
|
+
const { container } = render(<CharacterPicker editor={mockEditor} opts={opts} onClose={jest.fn()} />);
|
|
245
|
+
const dialog = container.querySelector('.insert-character-dialog');
|
|
246
|
+
expect(dialog).toHaveStyle({ zIndex: '1000' });
|
|
238
247
|
});
|
|
239
248
|
|
|
240
249
|
it('adds data-toolbar-for attribute with editor instanceId', () => {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { render, waitFor, fireEvent } from '@testing-library/react';
|
|
3
3
|
import { EnsureTextAfterMathPlugin, MathNode, MathNodeView, ZeroWidthSpaceHandlingPlugin } from '../math';
|
|
4
|
+
import * as toolbarUtils from '../../utils/toolbar';
|
|
4
5
|
|
|
5
6
|
jest.mock('@tiptap/react', () => ({
|
|
6
7
|
NodeViewWrapper: ({ children, ...props }) => (
|
|
@@ -147,6 +148,35 @@ describe('MathNode', () => {
|
|
|
147
148
|
expect(commands).toHaveProperty('insertMath');
|
|
148
149
|
expect(typeof commands.insertMath).toBe('function');
|
|
149
150
|
});
|
|
151
|
+
|
|
152
|
+
it('insertMath opens the toolbar after inserting a math node', () => {
|
|
153
|
+
const setToolbarOpenedSpy = jest.spyOn(toolbarUtils, 'setToolbarOpened');
|
|
154
|
+
const mathNode = { type: { name: 'math' }, nodeSize: 1 };
|
|
155
|
+
const tr = {
|
|
156
|
+
insert: jest.fn().mockReturnThis(),
|
|
157
|
+
setSelection: jest.fn().mockReturnThis(),
|
|
158
|
+
doc: {},
|
|
159
|
+
};
|
|
160
|
+
const editor = {
|
|
161
|
+
view: {
|
|
162
|
+
state: {
|
|
163
|
+
schema: { nodes: { math: { create: jest.fn(() => mathNode) } } },
|
|
164
|
+
selection: { $from: { pos: 1 } },
|
|
165
|
+
},
|
|
166
|
+
},
|
|
167
|
+
};
|
|
168
|
+
const dispatch = jest.fn();
|
|
169
|
+
const insertMath = MathNode.addCommands().insertMath('x^2');
|
|
170
|
+
|
|
171
|
+
insertMath({ tr, editor, dispatch });
|
|
172
|
+
|
|
173
|
+
expect(tr.insert).toHaveBeenCalledWith(1, mathNode);
|
|
174
|
+
expect(tr.setSelection).toHaveBeenCalled();
|
|
175
|
+
expect(dispatch).toHaveBeenCalledWith(tr);
|
|
176
|
+
expect(setToolbarOpenedSpy).toHaveBeenCalledWith(editor, true);
|
|
177
|
+
|
|
178
|
+
setToolbarOpenedSpy.mockRestore();
|
|
179
|
+
});
|
|
150
180
|
});
|
|
151
181
|
|
|
152
182
|
describe('addNodeView', () => {
|
|
@@ -219,12 +249,32 @@ describe('EnsureTextAfterMathPlugin', () => {
|
|
|
219
249
|
});
|
|
220
250
|
|
|
221
251
|
describe('ZeroWidthSpaceHandlingPlugin', () => {
|
|
222
|
-
const
|
|
223
|
-
|
|
224
|
-
resolve: jest.fn(() => ({
|
|
252
|
+
const createDocWithMathAndZwsp = (resolveOverrides = {}) => ({
|
|
253
|
+
resolve: jest.fn((pos) => ({
|
|
225
254
|
nodeAfter: null,
|
|
226
255
|
nodeBefore: null,
|
|
256
|
+
pos,
|
|
257
|
+
...resolveOverrides[pos],
|
|
227
258
|
})),
|
|
259
|
+
nodeAt: jest.fn((pos) => {
|
|
260
|
+
if (pos === 1) {
|
|
261
|
+
return { type: { name: 'text' }, textContent: '\u200b' };
|
|
262
|
+
}
|
|
263
|
+
if (pos === 0) {
|
|
264
|
+
return { type: { name: 'math' }, nodeSize: 1 };
|
|
265
|
+
}
|
|
266
|
+
return null;
|
|
267
|
+
}),
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
const createDocWithRegularTextBeforeCursor = () => ({
|
|
271
|
+
resolve: jest.fn((pos) => ({ nodeAfter: null, nodeBefore: null, pos })),
|
|
272
|
+
nodeAt: jest.fn((pos) => {
|
|
273
|
+
if (pos === 1) {
|
|
274
|
+
return { type: { name: 'text' }, textContent: 'a' };
|
|
275
|
+
}
|
|
276
|
+
return null;
|
|
277
|
+
}),
|
|
228
278
|
});
|
|
229
279
|
|
|
230
280
|
const createView = ({ state: stateOverrides = {} } = {}) => {
|
|
@@ -237,66 +287,88 @@ describe('ZeroWidthSpaceHandlingPlugin', () => {
|
|
|
237
287
|
return {
|
|
238
288
|
state: {
|
|
239
289
|
selection: { from: 2, empty: true },
|
|
240
|
-
doc:
|
|
290
|
+
doc: createDocWithMathAndZwsp(),
|
|
241
291
|
tr,
|
|
242
292
|
...stateOverrides,
|
|
243
|
-
doc: { ...createDefaultDoc(), ...stateOverrides.doc },
|
|
244
293
|
},
|
|
245
294
|
dispatch,
|
|
246
295
|
};
|
|
247
296
|
};
|
|
248
297
|
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
298
|
+
describe('Backspace', () => {
|
|
299
|
+
it('deletes the inline node and zero-width space before the cursor', () => {
|
|
300
|
+
const view = createView();
|
|
301
|
+
const handled = ZeroWidthSpaceHandlingPlugin.props.handleKeyDown(view, { key: 'Backspace' });
|
|
302
|
+
|
|
303
|
+
expect(handled).toBe(true);
|
|
304
|
+
expect(view.state.tr.delete).toHaveBeenCalledWith(0, 2);
|
|
305
|
+
expect(view.dispatch).toHaveBeenCalledWith(view.state.tr);
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
it('returns false when regular text precedes the cursor', () => {
|
|
309
|
+
const view = createView({
|
|
310
|
+
state: {
|
|
311
|
+
doc: createDocWithRegularTextBeforeCursor(),
|
|
312
|
+
},
|
|
313
|
+
});
|
|
253
314
|
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
315
|
+
const handled = ZeroWidthSpaceHandlingPlugin.props.handleKeyDown(view, { key: 'Backspace' });
|
|
316
|
+
|
|
317
|
+
expect(handled).toBe(false);
|
|
318
|
+
expect(view.state.tr.delete).not.toHaveBeenCalled();
|
|
319
|
+
expect(view.dispatch).not.toHaveBeenCalled();
|
|
320
|
+
});
|
|
257
321
|
});
|
|
258
322
|
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
.mockReturnValueOnce({ pos: 4 }),
|
|
323
|
+
describe('ArrowLeft', () => {
|
|
324
|
+
it('selects the inline node before a zero-width space', () => {
|
|
325
|
+
const mathNode = { nodeSize: 3 };
|
|
326
|
+
const view = createView({
|
|
327
|
+
state: {
|
|
328
|
+
doc: createDocWithMathAndZwsp({
|
|
329
|
+
0: { nodeAfter: mathNode, nodeBefore: null, pos: 0 },
|
|
330
|
+
}),
|
|
268
331
|
},
|
|
269
|
-
}
|
|
332
|
+
});
|
|
333
|
+
const { NodeSelection } = require('prosemirror-state');
|
|
334
|
+
|
|
335
|
+
const handled = ZeroWidthSpaceHandlingPlugin.props.handleKeyDown(view, { key: 'ArrowLeft' });
|
|
336
|
+
|
|
337
|
+
expect(handled).toBe(true);
|
|
338
|
+
expect(view.state.doc.resolve).toHaveBeenCalledWith(0);
|
|
339
|
+
expect(NodeSelection.create).toHaveBeenCalledWith(view.state.doc, 0);
|
|
340
|
+
expect(view.dispatch).toHaveBeenCalled();
|
|
270
341
|
});
|
|
271
|
-
const { NodeSelection } = require('prosemirror-state');
|
|
272
342
|
|
|
273
|
-
|
|
343
|
+
it('moves the text cursor before the zero-width space when no inline node precedes it', () => {
|
|
344
|
+
const view = createView();
|
|
345
|
+
const { TextSelection } = require('prosemirror-state');
|
|
274
346
|
|
|
275
|
-
|
|
276
|
-
expect(NodeSelection.create).toHaveBeenCalledWith(view.state.doc, 4);
|
|
277
|
-
expect(view.dispatch).toHaveBeenCalled();
|
|
278
|
-
});
|
|
347
|
+
const handled = ZeroWidthSpaceHandlingPlugin.props.handleKeyDown(view, { key: 'ArrowLeft' });
|
|
279
348
|
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
349
|
+
expect(handled).toBe(true);
|
|
350
|
+
expect(view.state.doc.resolve).toHaveBeenCalledWith(0);
|
|
351
|
+
expect(TextSelection.create).toHaveBeenCalledWith(view.state.doc, 0);
|
|
352
|
+
expect(view.dispatch).toHaveBeenCalled();
|
|
353
|
+
});
|
|
354
|
+
|
|
355
|
+
it('returns false when regular text precedes the cursor', () => {
|
|
356
|
+
const view = createView({
|
|
357
|
+
state: {
|
|
358
|
+
doc: createDocWithRegularTextBeforeCursor(),
|
|
359
|
+
},
|
|
360
|
+
});
|
|
283
361
|
|
|
284
|
-
|
|
362
|
+
const handled = ZeroWidthSpaceHandlingPlugin.props.handleKeyDown(view, { key: 'ArrowLeft' });
|
|
285
363
|
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
364
|
+
expect(handled).toBe(false);
|
|
365
|
+
expect(view.state.tr.setSelection).not.toHaveBeenCalled();
|
|
366
|
+
expect(view.dispatch).not.toHaveBeenCalled();
|
|
367
|
+
});
|
|
289
368
|
});
|
|
290
369
|
|
|
291
370
|
it('returns false for unrelated keys', () => {
|
|
292
|
-
const view = createView(
|
|
293
|
-
state: {
|
|
294
|
-
doc: {
|
|
295
|
-
textBetween: jest.fn(() => 'a'),
|
|
296
|
-
resolve: jest.fn(),
|
|
297
|
-
},
|
|
298
|
-
},
|
|
299
|
-
});
|
|
371
|
+
const view = createView();
|
|
300
372
|
|
|
301
373
|
const handled = ZeroWidthSpaceHandlingPlugin.props.handleKeyDown(view, { key: 'Enter' });
|
|
302
374
|
expect(handled).toBe(false);
|
|
@@ -304,6 +376,15 @@ describe('ZeroWidthSpaceHandlingPlugin', () => {
|
|
|
304
376
|
});
|
|
305
377
|
|
|
306
378
|
describe('MathNodeView', () => {
|
|
379
|
+
const createEditorElement = (rect = { top: 0, left: 0, width: 600, height: 400 }) => {
|
|
380
|
+
const element = document.createElement('div');
|
|
381
|
+
Object.defineProperty(element, 'getBoundingClientRect', {
|
|
382
|
+
value: jest.fn(() => rect),
|
|
383
|
+
configurable: true,
|
|
384
|
+
});
|
|
385
|
+
return element;
|
|
386
|
+
};
|
|
387
|
+
|
|
307
388
|
const createMockEditor = () => ({
|
|
308
389
|
state: {
|
|
309
390
|
selection: {
|
|
@@ -320,6 +401,9 @@ describe('MathNodeView', () => {
|
|
|
320
401
|
coordsAtPos: jest.fn(() => ({ top: 100, left: 50 })),
|
|
321
402
|
dispatch: jest.fn(),
|
|
322
403
|
},
|
|
404
|
+
options: {
|
|
405
|
+
element: createEditorElement(),
|
|
406
|
+
},
|
|
323
407
|
commands: {
|
|
324
408
|
focus: jest.fn(),
|
|
325
409
|
},
|
|
@@ -335,13 +419,6 @@ describe('MathNodeView', () => {
|
|
|
335
419
|
|
|
336
420
|
let defaultProps;
|
|
337
421
|
|
|
338
|
-
beforeAll(() => {
|
|
339
|
-
Object.defineProperty(document.body, 'getBoundingClientRect', {
|
|
340
|
-
value: jest.fn(() => ({ top: 0, left: 0 })),
|
|
341
|
-
configurable: true,
|
|
342
|
-
});
|
|
343
|
-
});
|
|
344
|
-
|
|
345
422
|
beforeEach(() => {
|
|
346
423
|
jest.clearAllMocks();
|
|
347
424
|
mockCreatePortal.mockImplementation((node) => node);
|
|
@@ -390,30 +467,29 @@ describe('MathNodeView', () => {
|
|
|
390
467
|
});
|
|
391
468
|
|
|
392
469
|
describe('toolbar positioning', () => {
|
|
393
|
-
it('
|
|
470
|
+
it('positions relative to the editor element using coordsAtPos', async () => {
|
|
394
471
|
const { container } = render(<MathNodeView {...defaultProps} selected={true} />);
|
|
395
472
|
await waitFor(() => {
|
|
396
473
|
const toolbar = container.querySelector('[data-toolbar-for]');
|
|
397
474
|
expect(toolbar).toBeInTheDocument();
|
|
398
|
-
expect(toolbar.style.top).toBe('
|
|
475
|
+
expect(toolbar.style.top).toBe('140px');
|
|
399
476
|
expect(toolbar.style.left).toBe('50px');
|
|
400
477
|
});
|
|
401
478
|
});
|
|
402
479
|
|
|
403
|
-
it('
|
|
404
|
-
const
|
|
405
|
-
containerEl.getBoundingClientRect = jest.fn(() => ({ top: -200, left: 0, width: 600, height: 400 }));
|
|
480
|
+
it('accounts for editor scroll offset when calculating toolbar position', async () => {
|
|
481
|
+
const editorElement = createEditorElement({ top: -200, left: 0, width: 600, height: 400 });
|
|
406
482
|
|
|
407
483
|
const editor = {
|
|
408
484
|
...defaultProps.editor,
|
|
409
|
-
|
|
485
|
+
options: { element: editorElement },
|
|
410
486
|
};
|
|
411
487
|
|
|
412
488
|
const { container } = render(<MathNodeView {...defaultProps} editor={editor} selected={true} />);
|
|
413
489
|
await waitFor(() => {
|
|
414
490
|
const toolbar = container.querySelector('[data-toolbar-for]');
|
|
415
491
|
expect(toolbar).toBeInTheDocument();
|
|
416
|
-
expect(toolbar.style.top).toBe('
|
|
492
|
+
expect(toolbar.style.top).toBe('340px');
|
|
417
493
|
expect(toolbar.style.left).toBe('50px');
|
|
418
494
|
});
|
|
419
495
|
});
|
|
@@ -427,7 +503,7 @@ describe('MathNodeView', () => {
|
|
|
427
503
|
});
|
|
428
504
|
});
|
|
429
505
|
|
|
430
|
-
it('updates
|
|
506
|
+
it('updates position from coordsAtPos when selection changes', async () => {
|
|
431
507
|
const editor = {
|
|
432
508
|
...defaultProps.editor,
|
|
433
509
|
view: {
|
|
@@ -441,7 +517,7 @@ describe('MathNodeView', () => {
|
|
|
441
517
|
await waitFor(() => {
|
|
442
518
|
const toolbar = container.querySelector('[data-toolbar-for]');
|
|
443
519
|
expect(toolbar).toBeInTheDocument();
|
|
444
|
-
expect(toolbar.style.top).toBe('
|
|
520
|
+
expect(toolbar.style.top).toBe('240px');
|
|
445
521
|
expect(toolbar.style.left).toBe('150px');
|
|
446
522
|
});
|
|
447
523
|
});
|
|
@@ -515,18 +591,35 @@ describe('MathNodeView', () => {
|
|
|
515
591
|
});
|
|
516
592
|
});
|
|
517
593
|
|
|
518
|
-
it('unsets editor._toolbarOpened when toolbar is closed', async () => {
|
|
594
|
+
it('unsets editor._toolbarOpened when toolbar is closed and node is not selected', async () => {
|
|
595
|
+
const { getByTestId } = render(<MathNodeView {...defaultProps} selected={false} />);
|
|
596
|
+
|
|
597
|
+
fireEvent.click(getByTestId('math-preview'));
|
|
598
|
+
|
|
599
|
+
await waitFor(() => {
|
|
600
|
+
expect(getByTestId('math-toolbar')).toBeInTheDocument();
|
|
601
|
+
expect(defaultProps.editor._toolbarOpened).toBe(true);
|
|
602
|
+
});
|
|
603
|
+
|
|
604
|
+
fireEvent.click(getByTestId('done-button'));
|
|
605
|
+
|
|
606
|
+
await waitFor(() => {
|
|
607
|
+
expect(defaultProps.editor._toolbarOpened).toBe(false);
|
|
608
|
+
});
|
|
609
|
+
});
|
|
610
|
+
|
|
611
|
+
it('keeps editor._toolbarOpened true while the math node remains selected', async () => {
|
|
519
612
|
const { getByTestId } = render(<MathNodeView {...defaultProps} selected={true} />);
|
|
520
613
|
|
|
521
614
|
await waitFor(() => {
|
|
522
615
|
expect(getByTestId('done-button')).toBeInTheDocument();
|
|
616
|
+
expect(defaultProps.editor._toolbarOpened).toBe(true);
|
|
523
617
|
});
|
|
524
618
|
|
|
525
|
-
|
|
526
|
-
fireEvent.click(doneButton);
|
|
619
|
+
fireEvent.click(getByTestId('done-button'));
|
|
527
620
|
|
|
528
621
|
await waitFor(() => {
|
|
529
|
-
expect(defaultProps.editor._toolbarOpened).toBe(
|
|
622
|
+
expect(defaultProps.editor._toolbarOpened).toBe(true);
|
|
530
623
|
});
|
|
531
624
|
});
|
|
532
625
|
|
|
@@ -551,7 +644,7 @@ describe('MathNodeView', () => {
|
|
|
551
644
|
expect(editor.state.tr.setSelection).toHaveBeenCalled();
|
|
552
645
|
expect(editor.view.dispatch).toHaveBeenCalledWith(editor.state.tr);
|
|
553
646
|
expect(editor.commands.focus).toHaveBeenCalled();
|
|
554
|
-
expect(editor._toolbarOpened).toBe(
|
|
647
|
+
expect(editor._toolbarOpened).toBe(true);
|
|
555
648
|
});
|
|
556
649
|
});
|
|
557
650
|
|
|
@@ -608,11 +701,13 @@ describe('MathNodeView', () => {
|
|
|
608
701
|
|
|
609
702
|
const { getAllByTestId, queryAllByTestId } = render(
|
|
610
703
|
<>
|
|
611
|
-
<MathNodeView {...defaultProps} editor={editorA} updateAttributes={updateAttributes} selected={
|
|
704
|
+
<MathNodeView {...defaultProps} editor={editorA} updateAttributes={updateAttributes} selected={false} />
|
|
612
705
|
<MathNodeView {...defaultProps} editor={editorB} node={{ attrs: { latex: 'y^2' } }} selected={false} />
|
|
613
706
|
</>,
|
|
614
707
|
);
|
|
615
708
|
|
|
709
|
+
fireEvent.click(getAllByTestId('math-preview')[0]);
|
|
710
|
+
|
|
616
711
|
await waitFor(() => {
|
|
617
712
|
expect(queryAllByTestId('math-toolbar')).toHaveLength(1);
|
|
618
713
|
});
|
package/src/extensions/math.js
CHANGED
|
@@ -45,6 +45,26 @@ export const EnsureTextAfterMathPlugin = (mathNodeName) =>
|
|
|
45
45
|
},
|
|
46
46
|
});
|
|
47
47
|
|
|
48
|
+
const nodeBeforeZeroWidthSpace = (doc, from) => {
|
|
49
|
+
let i;
|
|
50
|
+
|
|
51
|
+
// finding if previous to the cursor there's a zero-width space
|
|
52
|
+
// and a non-text element, and deleting everything until the space
|
|
53
|
+
for (i = from; i > 0; i--) {
|
|
54
|
+
const currentDoc = doc.nodeAt(i);
|
|
55
|
+
|
|
56
|
+
if (currentDoc?.type?.name === 'text' && currentDoc.textContent !== '\u200b') {
|
|
57
|
+
return -1;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (currentDoc && currentDoc?.type?.name !== 'text') {
|
|
61
|
+
break;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return i;
|
|
66
|
+
};
|
|
67
|
+
|
|
48
68
|
export const ZeroWidthSpaceHandlingPlugin = new Plugin({
|
|
49
69
|
key: new PluginKey('zeroWidthSpaceHandling'),
|
|
50
70
|
props: {
|
|
@@ -54,35 +74,38 @@ export const ZeroWidthSpaceHandlingPlugin = new Plugin({
|
|
|
54
74
|
const { from, empty } = selection;
|
|
55
75
|
|
|
56
76
|
if (empty && event.key === 'Backspace' && from > 0) {
|
|
57
|
-
const
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
return true; // handled
|
|
77
|
+
const start = nodeBeforeZeroWidthSpace(doc, from);
|
|
78
|
+
|
|
79
|
+
if (start === -1) {
|
|
80
|
+
return false;
|
|
62
81
|
}
|
|
82
|
+
|
|
83
|
+
const tr = state.tr.delete(start, from);
|
|
84
|
+
dispatch(tr);
|
|
85
|
+
return true; // handled
|
|
63
86
|
}
|
|
64
87
|
|
|
65
88
|
if (empty && event.key === 'ArrowLeft' && from > 0) {
|
|
66
|
-
const
|
|
67
|
-
|
|
68
|
-
if (
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
89
|
+
const start = nodeBeforeZeroWidthSpace(doc, from);
|
|
90
|
+
|
|
91
|
+
if (start === -1) {
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const resolved = state.doc.resolve(start);
|
|
96
|
+
const maybeNode = resolved.nodeAfter || resolved.nodeBefore;
|
|
97
|
+
|
|
98
|
+
// Check if there's an inline selectable node (e.g., your math node)
|
|
99
|
+
if (maybeNode) {
|
|
100
|
+
const nodeResolved = state.doc.resolve(start);
|
|
101
|
+
const tr = state.tr.setSelection(NodeSelection.create(state.doc, nodeResolved.pos));
|
|
102
|
+
dispatch(tr);
|
|
103
|
+
return true;
|
|
104
|
+
} else {
|
|
105
|
+
// Just move the text cursor before the zwsp
|
|
106
|
+
const tr = state.tr.setSelection(TextSelection.create(state.doc, from - 2));
|
|
107
|
+
dispatch(tr);
|
|
108
|
+
return true;
|
|
86
109
|
}
|
|
87
110
|
}
|
|
88
111
|
|
|
@@ -152,14 +175,9 @@ export const MathNode = Node.create({
|
|
|
152
175
|
|
|
153
176
|
dispatch(tr);
|
|
154
177
|
|
|
178
|
+
setToolbarOpened(editor, true);
|
|
155
179
|
return true;
|
|
156
180
|
},
|
|
157
|
-
// insertMath: (latex = '') => ({ commands }) => {
|
|
158
|
-
// return commands.insertContent({
|
|
159
|
-
// type: this.name,
|
|
160
|
-
// attrs: { latex },
|
|
161
|
-
// });
|
|
162
|
-
// },
|
|
163
181
|
};
|
|
164
182
|
},
|
|
165
183
|
|
|
@@ -221,16 +239,19 @@ export const MathNodeView = (props) => {
|
|
|
221
239
|
}, [selected]);
|
|
222
240
|
|
|
223
241
|
useEffect(() => {
|
|
224
|
-
setToolbarOpened(editor, showToolbar);
|
|
225
|
-
}, [editor, showToolbar]);
|
|
242
|
+
setToolbarOpened(editor, selected || showToolbar);
|
|
243
|
+
}, [editor, showToolbar, selected]);
|
|
226
244
|
|
|
227
245
|
useEffect(() => {
|
|
228
246
|
// Calculate position relative to selection
|
|
229
247
|
const { from } = editor.state.selection;
|
|
230
248
|
const start = editor.view.coordsAtPos(from);
|
|
249
|
+
const editorDOM = editor.options.element;
|
|
250
|
+
const editorRect = editorDOM.getBoundingClientRect();
|
|
251
|
+
|
|
231
252
|
setPosition({
|
|
232
|
-
top: 40, // shift above
|
|
233
|
-
left: start.left,
|
|
253
|
+
top: start.top - editorRect.top + 40, // shift above
|
|
254
|
+
left: start.left - editorRect.left,
|
|
234
255
|
});
|
|
235
256
|
|
|
236
257
|
const handleClickOutside = (event) => {
|