@pie-lib/editable-html-tip-tap 2.1.2-next.23 → 2.1.2-next.29
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/respArea/InlineDropdown.js +52 -8
- package/lib/components/respArea/InlineDropdown.js.map +1 -1
- package/lib/components/respArea/inlineDropdownUtils.js +67 -0
- package/lib/components/respArea/inlineDropdownUtils.js.map +1 -0
- package/lib/extensions/math.js +24 -25
- package/lib/extensions/math.js.map +1 -1
- package/lib/index.js +7 -0
- package/lib/index.js.map +1 -1
- package/package.json +2 -2
- package/src/components/__tests__/InlineDropdown.test.jsx +8 -0
- package/src/components/respArea/InlineDropdown.jsx +72 -19
- package/src/components/respArea/inlineDropdownUtils.js +79 -0
- package/src/extensions/__tests__/math.test.js +184 -40
- package/src/extensions/math.js +21 -22
- package/src/index.jsx +2 -2
|
@@ -10,6 +10,7 @@ var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/sli
|
|
|
10
10
|
var _react = _interopRequireWildcard(require("react"));
|
|
11
11
|
var _propTypes = _interopRequireDefault(require("prop-types"));
|
|
12
12
|
var _react2 = require("@tiptap/react");
|
|
13
|
+
var _prosemirrorState = require("prosemirror-state");
|
|
13
14
|
var _RespArea = require("../icons/RespArea");
|
|
14
15
|
var _reactDom = _interopRequireDefault(require("react-dom"));
|
|
15
16
|
var _customToolbarWrapper = _interopRequireDefault(require("../../extensions/custom-toolbar-wrapper"));
|
|
@@ -23,12 +24,14 @@ var InlineDropdown = function InlineDropdown(props) {
|
|
|
23
24
|
var attributes = node.attrs;
|
|
24
25
|
var value = attributes.value,
|
|
25
26
|
error = attributes.error;
|
|
26
|
-
// TODO: Investigate
|
|
27
|
-
// Needed because items with values inside have different positioning for some reason
|
|
28
27
|
var html = value || '<div> </div>';
|
|
29
28
|
var pos = getPos();
|
|
30
29
|
var toolbarRef = (0, _react.useRef)(null);
|
|
31
30
|
var toolbarEditor = (0, _react.useRef)(null);
|
|
31
|
+
var pendingCloseRequest = (0, _react.useRef)(false);
|
|
32
|
+
var isHeld = function isHeld() {
|
|
33
|
+
return editor._holdInlineDropdownToolbarIndex != null && String(editor._holdInlineDropdownToolbarIndex) === String(node.attrs.index);
|
|
34
|
+
};
|
|
32
35
|
var _useState = (0, _react.useState)(false),
|
|
33
36
|
_useState2 = (0, _slicedToArray2["default"])(_useState, 2),
|
|
34
37
|
showToolbar = _useState2[0],
|
|
@@ -40,16 +43,55 @@ var InlineDropdown = function InlineDropdown(props) {
|
|
|
40
43
|
_useState4 = (0, _slicedToArray2["default"])(_useState3, 2),
|
|
41
44
|
position = _useState4[0],
|
|
42
45
|
setPosition = _useState4[1];
|
|
43
|
-
var
|
|
46
|
+
var closeToolbar = function closeToolbar() {
|
|
47
|
+
if (isHeld()) {
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
setShowToolbar(false);
|
|
51
|
+
};
|
|
52
|
+
var InlineDropdownToolbar = options.respAreaToolbar([node, pos], editor, closeToolbar);
|
|
53
|
+
var reselectNode = function reselectNode() {
|
|
54
|
+
var tr = editor.state.tr;
|
|
55
|
+
var nodeAtPos = tr.doc.nodeAt(pos);
|
|
56
|
+
if (!nodeAtPos) {
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
var selection = tr.selection;
|
|
60
|
+
if (selection.from === pos && selection.to === pos + nodeAtPos.nodeSize) {
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
tr.setSelection(_prosemirrorState.NodeSelection.create(tr.doc, pos));
|
|
64
|
+
editor.view.dispatch(tr);
|
|
65
|
+
};
|
|
66
|
+
var requestClose = function requestClose() {
|
|
67
|
+
if (pendingCloseRequest.current) {
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
if (options.onToolbarCloseRequest) {
|
|
71
|
+
pendingCloseRequest.current = true;
|
|
72
|
+
options.onToolbarCloseRequest([node, pos], editor, function () {
|
|
73
|
+
pendingCloseRequest.current = false;
|
|
74
|
+
delete editor._holdInlineDropdownToolbarIndex;
|
|
75
|
+
closeToolbar();
|
|
76
|
+
}, function () {
|
|
77
|
+
pendingCloseRequest.current = false;
|
|
78
|
+
delete editor._holdInlineDropdownToolbarIndex;
|
|
79
|
+
setShowToolbar(true);
|
|
80
|
+
setTimeout(reselectNode, 0);
|
|
81
|
+
});
|
|
82
|
+
} else {
|
|
83
|
+
closeToolbar();
|
|
84
|
+
}
|
|
85
|
+
};
|
|
44
86
|
(0, _react.useEffect)(function () {
|
|
45
87
|
var selection = editor.state.selection;
|
|
46
88
|
var onlyThisNodeSelected = selection.from + node.nodeSize === selection.to;
|
|
47
89
|
if (selected) {
|
|
48
90
|
if (onlyThisNodeSelected) {
|
|
49
|
-
setShowToolbar(
|
|
91
|
+
setShowToolbar(true);
|
|
50
92
|
}
|
|
51
|
-
} else {
|
|
52
|
-
|
|
93
|
+
} else if (showToolbar) {
|
|
94
|
+
requestClose();
|
|
53
95
|
}
|
|
54
96
|
}, [editor, node, selected]);
|
|
55
97
|
(0, _react.useEffect)(function () {
|
|
@@ -63,9 +105,10 @@ var InlineDropdown = function InlineDropdown(props) {
|
|
|
63
105
|
left: start.left
|
|
64
106
|
});
|
|
65
107
|
var handleClickOutside = function handleClickOutside(event) {
|
|
108
|
+
var _toolbarEditor$curren;
|
|
66
109
|
var insideSomeEditor = event.target.closest('[data-toolbar-for]');
|
|
67
|
-
if ((!insideSomeEditor || insideSomeEditor.dataset.toolbarFor !== toolbarEditor.current.instanceId) && !editor._toolbarOpened && toolbarRef.current && !toolbarRef.current.contains(event.target) && !event.target.closest('[data-inline-node]')) {
|
|
68
|
-
|
|
110
|
+
if (!event.target.closest('[data-inline-dropdown-toolbar]') && (!insideSomeEditor || insideSomeEditor.dataset.toolbarFor !== ((_toolbarEditor$curren = toolbarEditor.current) === null || _toolbarEditor$curren === void 0 ? void 0 : _toolbarEditor$curren.instanceId)) && !editor._toolbarOpened && toolbarRef.current && !toolbarRef.current.contains(event.target) && !event.target.closest('[data-inline-node]')) {
|
|
111
|
+
requestClose();
|
|
69
112
|
}
|
|
70
113
|
};
|
|
71
114
|
if (showToolbar) {
|
|
@@ -150,6 +193,7 @@ var InlineDropdown = function InlineDropdown(props) {
|
|
|
150
193
|
// Prevent the debounced onBlur/onDone from firing into the
|
|
151
194
|
// now-deleted node's stale position
|
|
152
195
|
editor._toolbarOpened = false;
|
|
196
|
+
delete editor._holdInlineDropdownToolbarIndex;
|
|
153
197
|
editor.view.dispatch(tr);
|
|
154
198
|
setShowToolbar(false);
|
|
155
199
|
editor.commands.focus();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InlineDropdown.js","names":["_react","_interopRequireWildcard","require","_propTypes","_interopRequireDefault","_react2","_RespArea","_reactDom","_customToolbarWrapper","e","t","WeakMap","r","n","__esModule","o","i","f","__proto__","_typeof","has","get","set","_t","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","InlineDropdown","props","editor","node","getPos","options","selected","attributes","attrs","value","error","html","pos","toolbarRef","useRef","toolbarEditor","_useState","useState","_useState2","_slicedToArray2","showToolbar","setShowToolbar","_useState3","top","left","_useState4","position","setPosition","InlineDropdownToolbar","respAreaToolbar","useEffect","selection","state","onlyThisNodeSelected","from","nodeSize","to","bodyRect","document","body","getBoundingClientRect","start","view","coordsAtPos","Math","abs","handleClickOutside","event","insideSomeEditor","target","closest","dataset","toolbarFor","current","instanceId","_toolbarOpened","contains","addEventListener","removeEventListener","createElement","NodeViewWrapper","className","style","display","height","cursor","minWidth","background","border","boxSizing","borderRadius","margin","alignItems","onClick","flex","overflow","padding","whiteSpace","textOverflow","verticalAlign","dangerouslySetInnerHTML","__html","Chevron","direction","right","Fragment","ReactDOM","createPortal","ref","zIndex","editorCallback","instance","_tiptapContainerEl","deletable","toolbarOpts","autoWidth","onDelete","tr","dispatch","commands","focus","showDone","propTypes","PropTypes","object","selectedItem","oneOfType","string","_default","exports"],"sources":["../../../src/components/respArea/InlineDropdown.jsx"],"sourcesContent":["import React, { useEffect, useRef, useState } from 'react';\nimport PropTypes from 'prop-types';\nimport { NodeViewWrapper } from '@tiptap/react';\nimport { Chevron } from '../icons/RespArea';\nimport ReactDOM from 'react-dom';\nimport CustomToolbarWrapper from '../../extensions/custom-toolbar-wrapper';\n\nconst InlineDropdown = (props) => {\n const { editor, node, getPos, options, selected } = props;\n const { attrs: attributes } = node;\n const { value, error } = attributes;\n // TODO: Investigate\n // Needed because items with values inside have different positioning for some reason\n const html = value || '<div> </div>';\n const pos = getPos();\n const toolbarRef = useRef(null);\n const toolbarEditor = useRef(null);\n const [showToolbar, setShowToolbar] = useState(false);\n const [position, setPosition] = useState({ top: 0, left: 0 });\n const InlineDropdownToolbar = options.respAreaToolbar([node, pos], editor, () => {});\n\n useEffect(() => {\n const { selection } = editor.state;\n const onlyThisNodeSelected = selection.from + node.nodeSize === selection.to;\n\n if (selected) {\n if (onlyThisNodeSelected) {\n setShowToolbar(selected);\n }\n } else {\n setShowToolbar(selected);\n }\n }, [editor, node, selected]);\n\n useEffect(() => {\n // Calculate position relative to selection\n const bodyRect = document.body.getBoundingClientRect();\n const { from } = editor.state.selection;\n const start = editor.view.coordsAtPos(from);\n\n setPosition({\n top: start.top + Math.abs(bodyRect.top) + 40, // shift above\n left: start.left,\n });\n\n const handleClickOutside = (event) => {\n const insideSomeEditor = event.target.closest('[data-toolbar-for]');\n\n if (\n (!insideSomeEditor || insideSomeEditor.dataset.toolbarFor !== toolbarEditor.current.instanceId) &&\n !editor._toolbarOpened &&\n toolbarRef.current &&\n !toolbarRef.current.contains(event.target) &&\n !event.target.closest('[data-inline-node]')\n ) {\n setShowToolbar(false);\n }\n };\n\n if (showToolbar) {\n document.addEventListener('mousedown', handleClickOutside);\n } else {\n document.removeEventListener('mousedown', handleClickOutside);\n }\n\n return () => document.removeEventListener('mousedown', handleClickOutside);\n }, [showToolbar]);\n\n return (\n <NodeViewWrapper\n className=\"inline-dropdown\"\n data-selected={selected}\n style={{\n display: 'inline-flex',\n height: '50px',\n cursor: 'pointer',\n }}\n >\n <div\n style={{\n display: 'inline-flex',\n minWidth: '178px',\n height: '36px',\n background: '#FFF',\n border: '1px solid #C0C3CF',\n boxSizing: 'border-box',\n borderRadius: '3px',\n margin: '0 2px',\n position: 'relative',\n alignItems: 'center',\n }}\n onClick={() => setShowToolbar(true)}\n >\n <div\n style={{\n flex: 1,\n overflow: 'hidden',\n padding: '0 25px 0 8px',\n whiteSpace: 'nowrap',\n textOverflow: 'ellipsis',\n }}\n >\n <span\n style={{\n display: 'inline-block',\n verticalAlign: 'middle',\n }}\n dangerouslySetInnerHTML={{\n __html: html,\n }}\n />\n </div>\n <Chevron\n direction=\"down\"\n style={{\n position: 'absolute',\n top: '5px',\n right: '5px',\n }}\n />\n </div>\n {showToolbar && (\n <React.Fragment>\n {ReactDOM.createPortal(\n <div ref={toolbarRef} style={{ zIndex: 1 }}>\n <InlineDropdownToolbar\n editorCallback={(instance) => {\n toolbarEditor.current = instance;\n }}\n />\n </div>,\n document.body,\n )}\n\n {editor._tiptapContainerEl &&\n ReactDOM.createPortal(\n <CustomToolbarWrapper\n deletable\n toolbarOpts={{ minWidth: 'auto' }}\n autoWidth\n style={{ top: -40, left: 0, right: 0 }}\n onDelete={() => {\n const { tr } = editor.state;\n tr.delete(pos, pos + node.nodeSize);\n // Prevent the debounced onBlur/onDone from firing into the\n // now-deleted node's stale position\n editor._toolbarOpened = false;\n editor.view.dispatch(tr);\n setShowToolbar(false);\n editor.commands.focus();\n }}\n showDone={false}\n />,\n editor._tiptapContainerEl,\n )}\n </React.Fragment>\n )}\n </NodeViewWrapper>\n );\n};\n\nInlineDropdown.propTypes = {\n attributes: PropTypes.object,\n selectedItem: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),\n};\n\nexport default InlineDropdown;\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"InlineDropdown.js","names":["_react","_interopRequireWildcard","require","_propTypes","_interopRequireDefault","_react2","_prosemirrorState","_RespArea","_reactDom","_customToolbarWrapper","e","t","WeakMap","r","n","__esModule","o","i","f","__proto__","_typeof","has","get","set","_t","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","InlineDropdown","props","editor","node","getPos","options","selected","attributes","attrs","value","error","html","pos","toolbarRef","useRef","toolbarEditor","pendingCloseRequest","isHeld","_holdInlineDropdownToolbarIndex","String","index","_useState","useState","_useState2","_slicedToArray2","showToolbar","setShowToolbar","_useState3","top","left","_useState4","position","setPosition","closeToolbar","InlineDropdownToolbar","respAreaToolbar","reselectNode","tr","state","nodeAtPos","doc","nodeAt","selection","from","to","nodeSize","setSelection","NodeSelection","create","view","dispatch","requestClose","current","onToolbarCloseRequest","setTimeout","useEffect","onlyThisNodeSelected","bodyRect","document","body","getBoundingClientRect","start","coordsAtPos","Math","abs","handleClickOutside","event","_toolbarEditor$curren","insideSomeEditor","target","closest","dataset","toolbarFor","instanceId","_toolbarOpened","contains","addEventListener","removeEventListener","createElement","NodeViewWrapper","className","style","display","height","cursor","minWidth","background","border","boxSizing","borderRadius","margin","alignItems","onClick","flex","overflow","padding","whiteSpace","textOverflow","verticalAlign","dangerouslySetInnerHTML","__html","Chevron","direction","right","Fragment","ReactDOM","createPortal","ref","zIndex","editorCallback","instance","_tiptapContainerEl","deletable","toolbarOpts","autoWidth","onDelete","commands","focus","showDone","propTypes","PropTypes","object","selectedItem","oneOfType","string","_default","exports"],"sources":["../../../src/components/respArea/InlineDropdown.jsx"],"sourcesContent":["import React, { useEffect, useRef, useState } from 'react';\nimport PropTypes from 'prop-types';\nimport { NodeViewWrapper } from '@tiptap/react';\nimport { NodeSelection } from 'prosemirror-state';\nimport { Chevron } from '../icons/RespArea';\nimport ReactDOM from 'react-dom';\nimport CustomToolbarWrapper from '../../extensions/custom-toolbar-wrapper';\n\nconst InlineDropdown = (props) => {\n const { editor, node, getPos, options, selected } = props;\n const { attrs: attributes } = node;\n const { value, error } = attributes;\n const html = value || '<div> </div>';\n const pos = getPos();\n const toolbarRef = useRef(null);\n const toolbarEditor = useRef(null);\n const pendingCloseRequest = useRef(false);\n\n const isHeld = () =>\n editor._holdInlineDropdownToolbarIndex != null &&\n String(editor._holdInlineDropdownToolbarIndex) === String(node.attrs.index);\n\n const [showToolbar, setShowToolbar] = useState(false);\n const [position, setPosition] = useState({ top: 0, left: 0 });\n\n const closeToolbar = () => {\n if (isHeld()) {\n return;\n }\n\n setShowToolbar(false);\n };\n\n const InlineDropdownToolbar = options.respAreaToolbar([node, pos], editor, closeToolbar);\n\n const reselectNode = () => {\n const { tr } = editor.state;\n const nodeAtPos = tr.doc.nodeAt(pos);\n\n if (!nodeAtPos) {\n return;\n }\n\n const { selection } = tr;\n\n if (selection.from === pos && selection.to === pos + nodeAtPos.nodeSize) {\n return;\n }\n\n tr.setSelection(NodeSelection.create(tr.doc, pos));\n editor.view.dispatch(tr);\n };\n\n const requestClose = () => {\n if (pendingCloseRequest.current) {\n return;\n }\n\n if (options.onToolbarCloseRequest) {\n pendingCloseRequest.current = true;\n\n options.onToolbarCloseRequest(\n [node, pos],\n editor,\n () => {\n pendingCloseRequest.current = false;\n delete editor._holdInlineDropdownToolbarIndex;\n closeToolbar();\n },\n () => {\n pendingCloseRequest.current = false;\n delete editor._holdInlineDropdownToolbarIndex;\n setShowToolbar(true);\n setTimeout(reselectNode, 0);\n },\n );\n } else {\n closeToolbar();\n }\n };\n\n useEffect(() => {\n const { selection } = editor.state;\n const onlyThisNodeSelected = selection.from + node.nodeSize === selection.to;\n\n if (selected) {\n if (onlyThisNodeSelected) {\n setShowToolbar(true);\n }\n } else if (showToolbar) {\n requestClose();\n }\n }, [editor, node, selected]);\n\n useEffect(() => {\n // Calculate position relative to selection\n const bodyRect = document.body.getBoundingClientRect();\n const { from } = editor.state.selection;\n const start = editor.view.coordsAtPos(from);\n\n setPosition({\n top: start.top + Math.abs(bodyRect.top) + 40, // shift above\n left: start.left,\n });\n\n const handleClickOutside = (event) => {\n const insideSomeEditor = event.target.closest('[data-toolbar-for]');\n\n if (\n !event.target.closest('[data-inline-dropdown-toolbar]') &&\n (!insideSomeEditor || insideSomeEditor.dataset.toolbarFor !== toolbarEditor.current?.instanceId) &&\n !editor._toolbarOpened &&\n toolbarRef.current &&\n !toolbarRef.current.contains(event.target) &&\n !event.target.closest('[data-inline-node]')\n ) {\n requestClose();\n }\n };\n\n if (showToolbar) {\n document.addEventListener('mousedown', handleClickOutside);\n } else {\n document.removeEventListener('mousedown', handleClickOutside);\n }\n\n return () => document.removeEventListener('mousedown', handleClickOutside);\n }, [showToolbar]);\n\n return (\n <NodeViewWrapper\n className=\"inline-dropdown\"\n data-selected={selected}\n style={{\n display: 'inline-flex',\n height: '50px',\n cursor: 'pointer',\n }}\n >\n <div\n style={{\n display: 'inline-flex',\n minWidth: '178px',\n height: '36px',\n background: '#FFF',\n border: '1px solid #C0C3CF',\n boxSizing: 'border-box',\n borderRadius: '3px',\n margin: '0 2px',\n position: 'relative',\n alignItems: 'center',\n }}\n onClick={() => setShowToolbar(true)}\n >\n <div\n style={{\n flex: 1,\n overflow: 'hidden',\n padding: '0 25px 0 8px',\n whiteSpace: 'nowrap',\n textOverflow: 'ellipsis',\n }}\n >\n <span\n style={{\n display: 'inline-block',\n verticalAlign: 'middle',\n }}\n dangerouslySetInnerHTML={{ __html: html }}\n />\n </div>\n <Chevron direction=\"down\" style={{ position: 'absolute', top: '5px', right: '5px' }} />\n </div>\n {showToolbar && (\n <React.Fragment>\n {ReactDOM.createPortal(\n <div ref={toolbarRef} style={{ zIndex: 1 }}>\n <InlineDropdownToolbar\n editorCallback={(instance) => {\n toolbarEditor.current = instance;\n }}\n />\n </div>,\n document.body,\n )}\n\n {editor._tiptapContainerEl &&\n ReactDOM.createPortal(\n <CustomToolbarWrapper\n deletable\n toolbarOpts={{ minWidth: 'auto' }}\n autoWidth\n style={{ top: -40, left: 0, right: 0 }}\n onDelete={() => {\n const { tr } = editor.state;\n tr.delete(pos, pos + node.nodeSize);\n // Prevent the debounced onBlur/onDone from firing into the\n // now-deleted node's stale position\n editor._toolbarOpened = false;\n delete editor._holdInlineDropdownToolbarIndex;\n editor.view.dispatch(tr);\n setShowToolbar(false);\n editor.commands.focus();\n }}\n showDone={false}\n />,\n editor._tiptapContainerEl,\n )}\n </React.Fragment>\n )}\n </NodeViewWrapper>\n );\n};\n\nInlineDropdown.propTypes = {\n attributes: PropTypes.object,\n selectedItem: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),\n};\n\nexport default InlineDropdown;\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.selectInlineDropdownNode = exports.releaseInlineDropdownToolbarHold = exports.isInlineDropdownToolbarHeld = exports.holdInlineDropdownToolbar = exports.findInlineDropdownPos = exports.deleteInlineDropdownByIndex = exports.HOLD_INLINE_DROPDOWN_TOOLBAR_INDEX = void 0;
|
|
7
|
+
var _prosemirrorState = require("prosemirror-state");
|
|
8
|
+
var HOLD_INLINE_DROPDOWN_TOOLBAR_INDEX = exports.HOLD_INLINE_DROPDOWN_TOOLBAR_INDEX = '_holdInlineDropdownToolbarIndex';
|
|
9
|
+
var findInlineDropdownPos = exports.findInlineDropdownPos = function findInlineDropdownPos(editor, index) {
|
|
10
|
+
var foundPos = null;
|
|
11
|
+
editor.state.doc.descendants(function (n, p) {
|
|
12
|
+
var _n$type, _n$attrs;
|
|
13
|
+
if (((_n$type = n.type) === null || _n$type === void 0 ? void 0 : _n$type.name) === 'inline_dropdown' && String((_n$attrs = n.attrs) === null || _n$attrs === void 0 ? void 0 : _n$attrs.index) === String(index)) {
|
|
14
|
+
foundPos = p;
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
return true;
|
|
18
|
+
});
|
|
19
|
+
return foundPos;
|
|
20
|
+
};
|
|
21
|
+
var holdInlineDropdownToolbar = exports.holdInlineDropdownToolbar = function holdInlineDropdownToolbar(editor, index) {
|
|
22
|
+
editor[HOLD_INLINE_DROPDOWN_TOOLBAR_INDEX] = index;
|
|
23
|
+
};
|
|
24
|
+
var releaseInlineDropdownToolbarHold = exports.releaseInlineDropdownToolbarHold = function releaseInlineDropdownToolbarHold(editor) {
|
|
25
|
+
delete editor[HOLD_INLINE_DROPDOWN_TOOLBAR_INDEX];
|
|
26
|
+
};
|
|
27
|
+
var isInlineDropdownToolbarHeld = exports.isInlineDropdownToolbarHeld = function isInlineDropdownToolbarHeld(editor, index) {
|
|
28
|
+
return editor[HOLD_INLINE_DROPDOWN_TOOLBAR_INDEX] != null && String(editor[HOLD_INLINE_DROPDOWN_TOOLBAR_INDEX]) === String(index);
|
|
29
|
+
};
|
|
30
|
+
var selectInlineDropdownNode = exports.selectInlineDropdownNode = function selectInlineDropdownNode(editor, index, fallbackPos) {
|
|
31
|
+
var _findInlineDropdownPo;
|
|
32
|
+
var pos = (_findInlineDropdownPo = findInlineDropdownPos(editor, index)) !== null && _findInlineDropdownPo !== void 0 ? _findInlineDropdownPo : fallbackPos;
|
|
33
|
+
if (pos == null) {
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
var tr = editor.state.tr;
|
|
37
|
+
var nodeAtPos = tr.doc.nodeAt(pos);
|
|
38
|
+
if (!nodeAtPos) {
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
var selection = tr.selection;
|
|
42
|
+
if (selection.from === pos && selection.to === pos + nodeAtPos.nodeSize) {
|
|
43
|
+
return pos;
|
|
44
|
+
}
|
|
45
|
+
tr.setSelection(_prosemirrorState.NodeSelection.create(tr.doc, pos));
|
|
46
|
+
editor.view.dispatch(tr);
|
|
47
|
+
return pos;
|
|
48
|
+
};
|
|
49
|
+
var deleteInlineDropdownByIndex = exports.deleteInlineDropdownByIndex = function deleteInlineDropdownByIndex(editor, index, fallbackPos) {
|
|
50
|
+
var _findInlineDropdownPo2;
|
|
51
|
+
var pos = (_findInlineDropdownPo2 = findInlineDropdownPos(editor, index)) !== null && _findInlineDropdownPo2 !== void 0 ? _findInlineDropdownPo2 : fallbackPos;
|
|
52
|
+
if (pos == null) {
|
|
53
|
+
releaseInlineDropdownToolbarHold(editor);
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
var tr = editor.state.tr;
|
|
57
|
+
var nodeAtPos = tr.doc.nodeAt(pos);
|
|
58
|
+
if (!nodeAtPos) {
|
|
59
|
+
releaseInlineDropdownToolbarHold(editor);
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
tr["delete"](pos, pos + nodeAtPos.nodeSize);
|
|
63
|
+
editor.view.dispatch(tr);
|
|
64
|
+
releaseInlineDropdownToolbarHold(editor);
|
|
65
|
+
return true;
|
|
66
|
+
};
|
|
67
|
+
//# sourceMappingURL=inlineDropdownUtils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inlineDropdownUtils.js","names":["_prosemirrorState","require","HOLD_INLINE_DROPDOWN_TOOLBAR_INDEX","exports","findInlineDropdownPos","editor","index","foundPos","state","doc","descendants","n","p","_n$type","_n$attrs","type","name","String","attrs","holdInlineDropdownToolbar","releaseInlineDropdownToolbarHold","isInlineDropdownToolbarHeld","selectInlineDropdownNode","fallbackPos","_findInlineDropdownPo","pos","tr","nodeAtPos","nodeAt","selection","from","to","nodeSize","setSelection","NodeSelection","create","view","dispatch","deleteInlineDropdownByIndex","_findInlineDropdownPo2"],"sources":["../../../src/components/respArea/inlineDropdownUtils.js"],"sourcesContent":["import { NodeSelection } from 'prosemirror-state';\n\nexport const HOLD_INLINE_DROPDOWN_TOOLBAR_INDEX = '_holdInlineDropdownToolbarIndex';\n\nexport const findInlineDropdownPos = (editor, index) => {\n let foundPos = null;\n\n editor.state.doc.descendants((n, p) => {\n if (n.type?.name === 'inline_dropdown' && String(n.attrs?.index) === String(index)) {\n foundPos = p;\n return false;\n }\n\n return true;\n });\n\n return foundPos;\n};\n\nexport const holdInlineDropdownToolbar = (editor, index) => {\n editor[HOLD_INLINE_DROPDOWN_TOOLBAR_INDEX] = index;\n};\n\nexport const releaseInlineDropdownToolbarHold = (editor) => {\n delete editor[HOLD_INLINE_DROPDOWN_TOOLBAR_INDEX];\n};\n\nexport const isInlineDropdownToolbarHeld = (editor, index) =>\n editor[HOLD_INLINE_DROPDOWN_TOOLBAR_INDEX] != null &&\n String(editor[HOLD_INLINE_DROPDOWN_TOOLBAR_INDEX]) === String(index);\n\nexport const selectInlineDropdownNode = (editor, index, fallbackPos) => {\n const pos = findInlineDropdownPos(editor, index) ?? fallbackPos;\n\n if (pos == null) {\n return null;\n }\n\n const { tr } = editor.state;\n const nodeAtPos = tr.doc.nodeAt(pos);\n\n if (!nodeAtPos) {\n return null;\n }\n\n const { selection } = tr;\n\n if (selection.from === pos && selection.to === pos + nodeAtPos.nodeSize) {\n return pos;\n }\n\n tr.setSelection(NodeSelection.create(tr.doc, pos));\n editor.view.dispatch(tr);\n\n return pos;\n};\n\nexport const deleteInlineDropdownByIndex = (editor, index, fallbackPos) => {\n const pos = findInlineDropdownPos(editor, index) ?? fallbackPos;\n\n if (pos == null) {\n releaseInlineDropdownToolbarHold(editor);\n return false;\n }\n\n const { tr } = editor.state;\n const nodeAtPos = tr.doc.nodeAt(pos);\n\n if (!nodeAtPos) {\n releaseInlineDropdownToolbarHold(editor);\n return false;\n }\n\n tr.delete(pos, pos + nodeAtPos.nodeSize);\n editor.view.dispatch(tr);\n releaseInlineDropdownToolbarHold(editor);\n\n return true;\n};"],"mappings":"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","ignoreList":[]}
|
package/lib/extensions/math.js
CHANGED
|
@@ -230,6 +230,28 @@ var MathNodeView = exports.MathNodeView = function MathNodeView(props) {
|
|
|
230
230
|
keyPadCharacterRef = mathOptions.keyPadCharacterRef,
|
|
231
231
|
setKeypadInteraction = mathOptions.setKeypadInteraction;
|
|
232
232
|
var latex = node.attrs.latex || '';
|
|
233
|
+
var handleChange = function handleChange(newLatex) {
|
|
234
|
+
updateAttributes({
|
|
235
|
+
latex: newLatex
|
|
236
|
+
});
|
|
237
|
+
};
|
|
238
|
+
var handleDone = function handleDone(newLatex) {
|
|
239
|
+
updateAttributes({
|
|
240
|
+
latex: newLatex
|
|
241
|
+
});
|
|
242
|
+
setShowToolbar(false);
|
|
243
|
+
editor._toolbarOpened = false;
|
|
244
|
+
var _editor$state = editor.state,
|
|
245
|
+
selection = _editor$state.selection,
|
|
246
|
+
tr = _editor$state.tr,
|
|
247
|
+
doc = _editor$state.doc;
|
|
248
|
+
var sel = _prosemirrorState.TextSelection.create(doc, selection.from + 1);
|
|
249
|
+
|
|
250
|
+
// Build a fresh transaction from the current state and set the selection
|
|
251
|
+
tr.setSelection(sel);
|
|
252
|
+
editor.view.dispatch(tr);
|
|
253
|
+
editor.commands.focus();
|
|
254
|
+
};
|
|
233
255
|
(0, _react.useEffect)(function () {
|
|
234
256
|
if (selected) {
|
|
235
257
|
setShowToolbar(true);
|
|
@@ -240,12 +262,10 @@ var MathNodeView = exports.MathNodeView = function MathNodeView(props) {
|
|
|
240
262
|
}, [showToolbar]);
|
|
241
263
|
(0, _react.useEffect)(function () {
|
|
242
264
|
// Calculate position relative to selection
|
|
243
|
-
var container = (editor === null || editor === void 0 ? void 0 : editor._tiptapContainerEl) || document.body;
|
|
244
|
-
var bodyRect = container.getBoundingClientRect();
|
|
245
265
|
var from = editor.state.selection.from;
|
|
246
266
|
var start = editor.view.coordsAtPos(from);
|
|
247
267
|
setPosition({
|
|
248
|
-
top:
|
|
268
|
+
top: 40,
|
|
249
269
|
// shift above
|
|
250
270
|
left: start.left
|
|
251
271
|
});
|
|
@@ -267,6 +287,7 @@ var MathNodeView = exports.MathNodeView = function MathNodeView(props) {
|
|
|
267
287
|
var clickedMathNode = !!(target !== null && target !== void 0 && (_target$closest2 = target.closest) !== null && _target$closest2 !== void 0 && _target$closest2.call(target, '.math-node'));
|
|
268
288
|
if (toolbarRef.current && !toolbarRef.current.contains(target) && !(target !== null && target !== void 0 && (_target$closest3 = target.closest) !== null && _target$closest3 !== void 0 && _target$closest3.call(target, '[data-inline-node]')) && !equationEditorPopoverOpen && !clickedEquationEditorSelect && !clickedMathNode) {
|
|
269
289
|
setShowToolbar(false);
|
|
290
|
+
handleDone(node.attrs.latex);
|
|
270
291
|
}
|
|
271
292
|
};
|
|
272
293
|
if (showToolbar) {
|
|
@@ -280,28 +301,6 @@ var MathNodeView = exports.MathNodeView = function MathNodeView(props) {
|
|
|
280
301
|
return document.removeEventListener('click', handleClickOutside);
|
|
281
302
|
};
|
|
282
303
|
}, [editor, showToolbar]);
|
|
283
|
-
var handleChange = function handleChange(newLatex) {
|
|
284
|
-
updateAttributes({
|
|
285
|
-
latex: newLatex
|
|
286
|
-
});
|
|
287
|
-
};
|
|
288
|
-
var handleDone = function handleDone(newLatex) {
|
|
289
|
-
updateAttributes({
|
|
290
|
-
latex: newLatex
|
|
291
|
-
});
|
|
292
|
-
setShowToolbar(false);
|
|
293
|
-
editor._toolbarOpened = false;
|
|
294
|
-
var _editor$state = editor.state,
|
|
295
|
-
selection = _editor$state.selection,
|
|
296
|
-
tr = _editor$state.tr,
|
|
297
|
-
doc = _editor$state.doc;
|
|
298
|
-
var sel = _prosemirrorState.TextSelection.create(doc, selection.from + 1);
|
|
299
|
-
|
|
300
|
-
// Build a fresh transaction from the current state and set the selection
|
|
301
|
-
tr.setSelection(sel);
|
|
302
|
-
editor.view.dispatch(tr);
|
|
303
|
-
editor.commands.focus();
|
|
304
|
-
};
|
|
305
304
|
return /*#__PURE__*/_react["default"].createElement(_react2.NodeViewWrapper, {
|
|
306
305
|
className: "math-node",
|
|
307
306
|
style: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"math.js","names":["_react","_interopRequireWildcard","require","_reactDom","_interopRequireDefault","_core","_react2","_prosemirrorState","_mathToolbar","_mathRendering","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","_useState3","top","left","_useState4","position","setPosition","_ref3","_ref3$math","mathOptions","keypadMode","_mathOptions$controll","controlledKeypadMode","_mathOptions$customKe","customKeys","keyPadCharacterRef","setKeypadInteraction","attrs","useEffect","_toolbarOpened","container","_tiptapContainerEl","document","body","bodyRect","getBoundingClientRect","start","coordsAtPos","Math","abs","handleClickOutside","_document$querySelect","_document","_target$closest","_target$closest2","_target$closest3","target","equationEditorListboxes","querySelectorAll","equationEditorPopoverOpen","clickedEquationEditorSelect","id","includes","closest","clickedMathNode","current","contains","addEventListener","removeEventListener","handleChange","newLatex","handleDone","_editor$state","commands","focus","NodeViewWrapper","className","style","display","cursor","margin","onClick","contentEditable","MathPreview","ReactDOM","createPortal","ref","instanceId","concat","zIndex","background","boxShadow","MathToolbar","autoFocus","onChange","onDone","additionalKeys"],"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';\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 [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 useEffect(() => {\n if (selected) {\n setShowToolbar(true);\n }\n }, [selected]);\n\n useEffect(() => {\n editor._toolbarOpened = !!showToolbar;\n }, [showToolbar]);\n\n useEffect(() => {\n // Calculate position relative to selection\n const container = editor?._tiptapContainerEl || document.body;\n const bodyRect = container.getBoundingClientRect();\n const { from } = editor.state.selection;\n const start = editor.view.coordsAtPos(from);\n setPosition({\n top: start.top + Math.abs(bodyRect.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');\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 }\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 const handleChange = (newLatex) => {\n updateAttributes({ latex: newLatex });\n };\n\n const handleDone = (newLatex) => {\n updateAttributes({ latex: newLatex });\n setShowToolbar(false);\n\n editor._toolbarOpened = 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 return (\n <NodeViewWrapper\n className=\"math-node\"\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":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"math.js","names":["_react","_interopRequireWildcard","require","_reactDom","_interopRequireDefault","_core","_react2","_prosemirrorState","_mathToolbar","_mathRendering","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","_useState3","top","left","_useState4","position","setPosition","_ref3","_ref3$math","mathOptions","keypadMode","_mathOptions$controll","controlledKeypadMode","_mathOptions$customKe","customKeys","keyPadCharacterRef","setKeypadInteraction","attrs","handleChange","newLatex","handleDone","_toolbarOpened","_editor$state","commands","focus","useEffect","start","coordsAtPos","handleClickOutside","_document$querySelect","_document","_target$closest","_target$closest2","_target$closest3","target","equationEditorListboxes","document","querySelectorAll","equationEditorPopoverOpen","clickedEquationEditorSelect","id","includes","closest","clickedMathNode","current","contains","addEventListener","removeEventListener","NodeViewWrapper","className","style","display","cursor","margin","onClick","contentEditable","MathPreview","ReactDOM","createPortal","ref","instanceId","concat","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';\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 [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 editor._toolbarOpened = 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 editor._toolbarOpened = !!showToolbar;\n }, [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');\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\"\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":"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","ignoreList":[]}
|
package/lib/index.js
CHANGED
|
@@ -23,8 +23,15 @@ Object.defineProperty(exports, "EditableHtml", {
|
|
|
23
23
|
}
|
|
24
24
|
});
|
|
25
25
|
exports["default"] = void 0;
|
|
26
|
+
Object.defineProperty(exports, "deleteInlineDropdownByIndex", {
|
|
27
|
+
enumerable: true,
|
|
28
|
+
get: function get() {
|
|
29
|
+
return _inlineDropdownUtils.deleteInlineDropdownByIndex;
|
|
30
|
+
}
|
|
31
|
+
});
|
|
26
32
|
var _EditableHtml = _interopRequireWildcard(require("./components/EditableHtml"));
|
|
27
33
|
var _extensions = require("./extensions");
|
|
34
|
+
var _inlineDropdownUtils = require("./components/respArea/inlineDropdownUtils");
|
|
28
35
|
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, "default": e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); }
|
|
29
36
|
var _default = exports["default"] = _EditableHtml["default"];
|
|
30
37
|
//# sourceMappingURL=index.js.map
|
package/lib/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["_EditableHtml","_interopRequireWildcard","require","_extensions","e","t","WeakMap","r","n","__esModule","o","i","f","__proto__","_typeof","has","get","set","_t","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","_default","exports","StyledEditor"],"sources":["../src/index.jsx"],"sourcesContent":["import StyledEditor, { EditableHtml } from './components/EditableHtml';\nimport { ALL_PLUGINS, DEFAULT_PLUGINS } from './extensions';\
|
|
1
|
+
{"version":3,"file":"index.js","names":["_EditableHtml","_interopRequireWildcard","require","_extensions","_inlineDropdownUtils","e","t","WeakMap","r","n","__esModule","o","i","f","__proto__","_typeof","has","get","set","_t","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","_default","exports","StyledEditor"],"sources":["../src/index.jsx"],"sourcesContent":["import StyledEditor, { EditableHtml } from './components/EditableHtml';\nimport { ALL_PLUGINS, DEFAULT_PLUGINS } from './extensions';\nimport { deleteInlineDropdownByIndex } from './components/respArea/inlineDropdownUtils';\nexport { EditableHtml, ALL_PLUGINS, DEFAULT_PLUGINS, deleteInlineDropdownByIndex };\nexport default StyledEditor;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,IAAAA,aAAA,GAAAC,uBAAA,CAAAC,OAAA;AACA,IAAAC,WAAA,GAAAD,OAAA;AACA,IAAAE,oBAAA,GAAAF,OAAA;AAAwF,SAAAD,wBAAAI,CAAA,EAAAC,CAAA,6BAAAC,OAAA,MAAAC,CAAA,OAAAD,OAAA,IAAAE,CAAA,OAAAF,OAAA,YAAAN,uBAAA,YAAAA,wBAAAI,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,IAAAmB,QAAA,GAAAC,OAAA,cAEzEC,wBAAY","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.29+da8cd556a",
|
|
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": "da8cd556af749eda4370280b3dc1b33548242ab2",
|
|
63
63
|
"scripts": {}
|
|
64
64
|
}
|
|
@@ -17,8 +17,15 @@ jest.mock('react-dom', () => ({
|
|
|
17
17
|
|
|
18
18
|
describe('InlineDropdown', () => {
|
|
19
19
|
const buildMockEditor = (overrides = {}) => {
|
|
20
|
+
const mockNodeAt = jest.fn((pos) => (pos === 5 ? { nodeSize: 1 } : null));
|
|
21
|
+
const mockDoc = {
|
|
22
|
+
descendants: jest.fn(),
|
|
23
|
+
nodeAt: mockNodeAt,
|
|
24
|
+
};
|
|
20
25
|
const mockTr = {
|
|
21
26
|
delete: jest.fn(),
|
|
27
|
+
doc: { nodeAt: mockNodeAt },
|
|
28
|
+
setSelection: jest.fn(),
|
|
22
29
|
};
|
|
23
30
|
return {
|
|
24
31
|
state: {
|
|
@@ -27,6 +34,7 @@ describe('InlineDropdown', () => {
|
|
|
27
34
|
to: 1,
|
|
28
35
|
},
|
|
29
36
|
tr: mockTr,
|
|
37
|
+
doc: mockDoc,
|
|
30
38
|
},
|
|
31
39
|
view: {
|
|
32
40
|
coordsAtPos: jest.fn(() => ({ top: 100, left: 50 })),
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import React, { useEffect, useRef, useState } from 'react';
|
|
2
2
|
import PropTypes from 'prop-types';
|
|
3
3
|
import { NodeViewWrapper } from '@tiptap/react';
|
|
4
|
+
import { NodeSelection } from 'prosemirror-state';
|
|
4
5
|
import { Chevron } from '../icons/RespArea';
|
|
5
6
|
import ReactDOM from 'react-dom';
|
|
6
7
|
import CustomToolbarWrapper from '../../extensions/custom-toolbar-wrapper';
|
|
@@ -9,15 +10,74 @@ const InlineDropdown = (props) => {
|
|
|
9
10
|
const { editor, node, getPos, options, selected } = props;
|
|
10
11
|
const { attrs: attributes } = node;
|
|
11
12
|
const { value, error } = attributes;
|
|
12
|
-
// TODO: Investigate
|
|
13
|
-
// Needed because items with values inside have different positioning for some reason
|
|
14
13
|
const html = value || '<div> </div>';
|
|
15
14
|
const pos = getPos();
|
|
16
15
|
const toolbarRef = useRef(null);
|
|
17
16
|
const toolbarEditor = useRef(null);
|
|
17
|
+
const pendingCloseRequest = useRef(false);
|
|
18
|
+
|
|
19
|
+
const isHeld = () =>
|
|
20
|
+
editor._holdInlineDropdownToolbarIndex != null &&
|
|
21
|
+
String(editor._holdInlineDropdownToolbarIndex) === String(node.attrs.index);
|
|
22
|
+
|
|
18
23
|
const [showToolbar, setShowToolbar] = useState(false);
|
|
19
24
|
const [position, setPosition] = useState({ top: 0, left: 0 });
|
|
20
|
-
|
|
25
|
+
|
|
26
|
+
const closeToolbar = () => {
|
|
27
|
+
if (isHeld()) {
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
setShowToolbar(false);
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
const InlineDropdownToolbar = options.respAreaToolbar([node, pos], editor, closeToolbar);
|
|
35
|
+
|
|
36
|
+
const reselectNode = () => {
|
|
37
|
+
const { tr } = editor.state;
|
|
38
|
+
const nodeAtPos = tr.doc.nodeAt(pos);
|
|
39
|
+
|
|
40
|
+
if (!nodeAtPos) {
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const { selection } = tr;
|
|
45
|
+
|
|
46
|
+
if (selection.from === pos && selection.to === pos + nodeAtPos.nodeSize) {
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
tr.setSelection(NodeSelection.create(tr.doc, pos));
|
|
51
|
+
editor.view.dispatch(tr);
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
const requestClose = () => {
|
|
55
|
+
if (pendingCloseRequest.current) {
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (options.onToolbarCloseRequest) {
|
|
60
|
+
pendingCloseRequest.current = true;
|
|
61
|
+
|
|
62
|
+
options.onToolbarCloseRequest(
|
|
63
|
+
[node, pos],
|
|
64
|
+
editor,
|
|
65
|
+
() => {
|
|
66
|
+
pendingCloseRequest.current = false;
|
|
67
|
+
delete editor._holdInlineDropdownToolbarIndex;
|
|
68
|
+
closeToolbar();
|
|
69
|
+
},
|
|
70
|
+
() => {
|
|
71
|
+
pendingCloseRequest.current = false;
|
|
72
|
+
delete editor._holdInlineDropdownToolbarIndex;
|
|
73
|
+
setShowToolbar(true);
|
|
74
|
+
setTimeout(reselectNode, 0);
|
|
75
|
+
},
|
|
76
|
+
);
|
|
77
|
+
} else {
|
|
78
|
+
closeToolbar();
|
|
79
|
+
}
|
|
80
|
+
};
|
|
21
81
|
|
|
22
82
|
useEffect(() => {
|
|
23
83
|
const { selection } = editor.state;
|
|
@@ -25,10 +85,10 @@ const InlineDropdown = (props) => {
|
|
|
25
85
|
|
|
26
86
|
if (selected) {
|
|
27
87
|
if (onlyThisNodeSelected) {
|
|
28
|
-
setShowToolbar(
|
|
88
|
+
setShowToolbar(true);
|
|
29
89
|
}
|
|
30
|
-
} else {
|
|
31
|
-
|
|
90
|
+
} else if (showToolbar) {
|
|
91
|
+
requestClose();
|
|
32
92
|
}
|
|
33
93
|
}, [editor, node, selected]);
|
|
34
94
|
|
|
@@ -47,13 +107,14 @@ const InlineDropdown = (props) => {
|
|
|
47
107
|
const insideSomeEditor = event.target.closest('[data-toolbar-for]');
|
|
48
108
|
|
|
49
109
|
if (
|
|
50
|
-
|
|
110
|
+
!event.target.closest('[data-inline-dropdown-toolbar]') &&
|
|
111
|
+
(!insideSomeEditor || insideSomeEditor.dataset.toolbarFor !== toolbarEditor.current?.instanceId) &&
|
|
51
112
|
!editor._toolbarOpened &&
|
|
52
113
|
toolbarRef.current &&
|
|
53
114
|
!toolbarRef.current.contains(event.target) &&
|
|
54
115
|
!event.target.closest('[data-inline-node]')
|
|
55
116
|
) {
|
|
56
|
-
|
|
117
|
+
requestClose();
|
|
57
118
|
}
|
|
58
119
|
};
|
|
59
120
|
|
|
@@ -105,19 +166,10 @@ const InlineDropdown = (props) => {
|
|
|
105
166
|
display: 'inline-block',
|
|
106
167
|
verticalAlign: 'middle',
|
|
107
168
|
}}
|
|
108
|
-
dangerouslySetInnerHTML={{
|
|
109
|
-
__html: html,
|
|
110
|
-
}}
|
|
169
|
+
dangerouslySetInnerHTML={{ __html: html }}
|
|
111
170
|
/>
|
|
112
171
|
</div>
|
|
113
|
-
<Chevron
|
|
114
|
-
direction="down"
|
|
115
|
-
style={{
|
|
116
|
-
position: 'absolute',
|
|
117
|
-
top: '5px',
|
|
118
|
-
right: '5px',
|
|
119
|
-
}}
|
|
120
|
-
/>
|
|
172
|
+
<Chevron direction="down" style={{ position: 'absolute', top: '5px', right: '5px' }} />
|
|
121
173
|
</div>
|
|
122
174
|
{showToolbar && (
|
|
123
175
|
<React.Fragment>
|
|
@@ -145,6 +197,7 @@ const InlineDropdown = (props) => {
|
|
|
145
197
|
// Prevent the debounced onBlur/onDone from firing into the
|
|
146
198
|
// now-deleted node's stale position
|
|
147
199
|
editor._toolbarOpened = false;
|
|
200
|
+
delete editor._holdInlineDropdownToolbarIndex;
|
|
148
201
|
editor.view.dispatch(tr);
|
|
149
202
|
setShowToolbar(false);
|
|
150
203
|
editor.commands.focus();
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { NodeSelection } from 'prosemirror-state';
|
|
2
|
+
|
|
3
|
+
export const HOLD_INLINE_DROPDOWN_TOOLBAR_INDEX = '_holdInlineDropdownToolbarIndex';
|
|
4
|
+
|
|
5
|
+
export const findInlineDropdownPos = (editor, index) => {
|
|
6
|
+
let foundPos = null;
|
|
7
|
+
|
|
8
|
+
editor.state.doc.descendants((n, p) => {
|
|
9
|
+
if (n.type?.name === 'inline_dropdown' && String(n.attrs?.index) === String(index)) {
|
|
10
|
+
foundPos = p;
|
|
11
|
+
return false;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
return true;
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
return foundPos;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export const holdInlineDropdownToolbar = (editor, index) => {
|
|
21
|
+
editor[HOLD_INLINE_DROPDOWN_TOOLBAR_INDEX] = index;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export const releaseInlineDropdownToolbarHold = (editor) => {
|
|
25
|
+
delete editor[HOLD_INLINE_DROPDOWN_TOOLBAR_INDEX];
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export const isInlineDropdownToolbarHeld = (editor, index) =>
|
|
29
|
+
editor[HOLD_INLINE_DROPDOWN_TOOLBAR_INDEX] != null &&
|
|
30
|
+
String(editor[HOLD_INLINE_DROPDOWN_TOOLBAR_INDEX]) === String(index);
|
|
31
|
+
|
|
32
|
+
export const selectInlineDropdownNode = (editor, index, fallbackPos) => {
|
|
33
|
+
const pos = findInlineDropdownPos(editor, index) ?? fallbackPos;
|
|
34
|
+
|
|
35
|
+
if (pos == null) {
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const { tr } = editor.state;
|
|
40
|
+
const nodeAtPos = tr.doc.nodeAt(pos);
|
|
41
|
+
|
|
42
|
+
if (!nodeAtPos) {
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const { selection } = tr;
|
|
47
|
+
|
|
48
|
+
if (selection.from === pos && selection.to === pos + nodeAtPos.nodeSize) {
|
|
49
|
+
return pos;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
tr.setSelection(NodeSelection.create(tr.doc, pos));
|
|
53
|
+
editor.view.dispatch(tr);
|
|
54
|
+
|
|
55
|
+
return pos;
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
export const deleteInlineDropdownByIndex = (editor, index, fallbackPos) => {
|
|
59
|
+
const pos = findInlineDropdownPos(editor, index) ?? fallbackPos;
|
|
60
|
+
|
|
61
|
+
if (pos == null) {
|
|
62
|
+
releaseInlineDropdownToolbarHold(editor);
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const { tr } = editor.state;
|
|
67
|
+
const nodeAtPos = tr.doc.nodeAt(pos);
|
|
68
|
+
|
|
69
|
+
if (!nodeAtPos) {
|
|
70
|
+
releaseInlineDropdownToolbarHold(editor);
|
|
71
|
+
return false;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
tr.delete(pos, pos + nodeAtPos.nodeSize);
|
|
75
|
+
editor.view.dispatch(tr);
|
|
76
|
+
releaseInlineDropdownToolbarHold(editor);
|
|
77
|
+
|
|
78
|
+
return true;
|
|
79
|
+
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { render, waitFor, fireEvent } from '@testing-library/react';
|
|
3
|
-
import { MathNode, MathNodeView } from '../math';
|
|
3
|
+
import { EnsureTextAfterMathPlugin, MathNode, MathNodeView, ZeroWidthSpaceHandlingPlugin } from '../math';
|
|
4
4
|
|
|
5
5
|
jest.mock('@tiptap/react', () => ({
|
|
6
6
|
NodeViewWrapper: ({ children, ...props }) => (
|
|
@@ -156,6 +156,151 @@ describe('MathNode', () => {
|
|
|
156
156
|
expect(result).toBeDefined();
|
|
157
157
|
});
|
|
158
158
|
});
|
|
159
|
+
|
|
160
|
+
describe('addProseMirrorPlugins', () => {
|
|
161
|
+
it('registers ensure-text-after-math and zero-width-space plugins', () => {
|
|
162
|
+
const plugins = MathNode.addProseMirrorPlugins();
|
|
163
|
+
|
|
164
|
+
expect(plugins).toHaveLength(2);
|
|
165
|
+
expect(plugins[0].appendTransaction).toBeDefined();
|
|
166
|
+
expect(plugins[1].props.handleKeyDown).toBeDefined();
|
|
167
|
+
});
|
|
168
|
+
});
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
describe('EnsureTextAfterMathPlugin', () => {
|
|
172
|
+
it('inserts a zero-width space after a math node when no text follows', () => {
|
|
173
|
+
const plugin = EnsureTextAfterMathPlugin('math');
|
|
174
|
+
const textNode = { type: { name: 'text' } };
|
|
175
|
+
const mathNode = { type: { name: 'math' }, nodeSize: 3 };
|
|
176
|
+
const tr = { insert: jest.fn() };
|
|
177
|
+
|
|
178
|
+
const newState = {
|
|
179
|
+
schema: { text: jest.fn((value) => ({ type: textNode.type, text: value })) },
|
|
180
|
+
tr,
|
|
181
|
+
doc: {
|
|
182
|
+
descendants: (cb) => cb(mathNode, 5),
|
|
183
|
+
nodeAt: jest.fn(() => null),
|
|
184
|
+
},
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
const result = plugin.appendTransaction([{ docChanged: true }], {}, newState);
|
|
188
|
+
|
|
189
|
+
expect(tr.insert).toHaveBeenCalledWith(8, expect.anything());
|
|
190
|
+
expect(result).toBe(tr);
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
it('does not insert when text already follows the math node', () => {
|
|
194
|
+
const plugin = EnsureTextAfterMathPlugin('math');
|
|
195
|
+
const tr = { insert: jest.fn() };
|
|
196
|
+
const mathNode = { type: { name: 'math' }, nodeSize: 3 };
|
|
197
|
+
|
|
198
|
+
const newState = {
|
|
199
|
+
schema: { text: jest.fn() },
|
|
200
|
+
tr,
|
|
201
|
+
doc: {
|
|
202
|
+
descendants: (cb) => cb(mathNode, 5),
|
|
203
|
+
nodeAt: jest.fn(() => ({ type: { name: 'text' } })),
|
|
204
|
+
},
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
const result = plugin.appendTransaction([{ docChanged: true }], {}, newState);
|
|
208
|
+
|
|
209
|
+
expect(tr.insert).not.toHaveBeenCalled();
|
|
210
|
+
expect(result).toBeNull();
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
it('returns null when the document did not change', () => {
|
|
214
|
+
const plugin = EnsureTextAfterMathPlugin('math');
|
|
215
|
+
|
|
216
|
+
const result = plugin.appendTransaction([{ docChanged: false }], {}, {});
|
|
217
|
+
expect(result).toBeNull();
|
|
218
|
+
});
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
describe('ZeroWidthSpaceHandlingPlugin', () => {
|
|
222
|
+
const createDefaultDoc = () => ({
|
|
223
|
+
textBetween: jest.fn(() => '\u200b'),
|
|
224
|
+
resolve: jest.fn(() => ({
|
|
225
|
+
nodeAfter: null,
|
|
226
|
+
nodeBefore: null,
|
|
227
|
+
})),
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
const createView = ({ state: stateOverrides = {} } = {}) => {
|
|
231
|
+
const dispatch = jest.fn();
|
|
232
|
+
const tr = {
|
|
233
|
+
delete: jest.fn().mockReturnThis(),
|
|
234
|
+
setSelection: jest.fn().mockReturnThis(),
|
|
235
|
+
};
|
|
236
|
+
|
|
237
|
+
return {
|
|
238
|
+
state: {
|
|
239
|
+
selection: { from: 2, empty: true },
|
|
240
|
+
doc: createDefaultDoc(),
|
|
241
|
+
tr,
|
|
242
|
+
...stateOverrides,
|
|
243
|
+
doc: { ...createDefaultDoc(), ...stateOverrides.doc },
|
|
244
|
+
},
|
|
245
|
+
dispatch,
|
|
246
|
+
};
|
|
247
|
+
};
|
|
248
|
+
|
|
249
|
+
it('deletes math and zero-width space on Backspace', () => {
|
|
250
|
+
const view = createView();
|
|
251
|
+
const event = { key: 'Backspace' };
|
|
252
|
+
const handled = ZeroWidthSpaceHandlingPlugin.props.handleKeyDown(view, event);
|
|
253
|
+
|
|
254
|
+
expect(handled).toBe(true);
|
|
255
|
+
expect(view.state.tr.delete).toHaveBeenCalledWith(0, 2);
|
|
256
|
+
expect(view.dispatch).toHaveBeenCalledWith(view.state.tr);
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
it('selects the math node on ArrowLeft before a zero-width space', () => {
|
|
260
|
+
const mathNode = { nodeSize: 3 };
|
|
261
|
+
const view = createView({
|
|
262
|
+
state: {
|
|
263
|
+
doc: {
|
|
264
|
+
resolve: jest
|
|
265
|
+
.fn()
|
|
266
|
+
.mockReturnValueOnce({ nodeAfter: mathNode, nodeBefore: null })
|
|
267
|
+
.mockReturnValueOnce({ pos: 4 }),
|
|
268
|
+
},
|
|
269
|
+
},
|
|
270
|
+
});
|
|
271
|
+
const { NodeSelection } = require('prosemirror-state');
|
|
272
|
+
|
|
273
|
+
const handled = ZeroWidthSpaceHandlingPlugin.props.handleKeyDown(view, { key: 'ArrowLeft' });
|
|
274
|
+
|
|
275
|
+
expect(handled).toBe(true);
|
|
276
|
+
expect(NodeSelection.create).toHaveBeenCalledWith(view.state.doc, 4);
|
|
277
|
+
expect(view.dispatch).toHaveBeenCalled();
|
|
278
|
+
});
|
|
279
|
+
|
|
280
|
+
it('moves the text cursor before the zero-width space when no inline node precedes it', () => {
|
|
281
|
+
const view = createView();
|
|
282
|
+
const { TextSelection } = require('prosemirror-state');
|
|
283
|
+
|
|
284
|
+
const handled = ZeroWidthSpaceHandlingPlugin.props.handleKeyDown(view, { key: 'ArrowLeft' });
|
|
285
|
+
|
|
286
|
+
expect(handled).toBe(true);
|
|
287
|
+
expect(TextSelection.create).toHaveBeenCalledWith(view.state.doc, 0);
|
|
288
|
+
expect(view.dispatch).toHaveBeenCalled();
|
|
289
|
+
});
|
|
290
|
+
|
|
291
|
+
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
|
+
});
|
|
300
|
+
|
|
301
|
+
const handled = ZeroWidthSpaceHandlingPlugin.props.handleKeyDown(view, { key: 'Enter' });
|
|
302
|
+
expect(handled).toBe(false);
|
|
303
|
+
});
|
|
159
304
|
});
|
|
160
305
|
|
|
161
306
|
describe('MathNodeView', () => {
|
|
@@ -244,37 +389,30 @@ describe('MathNodeView', () => {
|
|
|
244
389
|
});
|
|
245
390
|
|
|
246
391
|
describe('toolbar positioning', () => {
|
|
247
|
-
it('uses
|
|
248
|
-
const
|
|
249
|
-
containerEl.getBoundingClientRect = jest.fn(() => ({ top: -50, left: 20, width: 600, height: 400 }));
|
|
250
|
-
|
|
251
|
-
const editor = {
|
|
252
|
-
...defaultProps.editor,
|
|
253
|
-
_tiptapContainerEl: containerEl,
|
|
254
|
-
};
|
|
255
|
-
|
|
256
|
-
const { container } = render(<MathNodeView {...defaultProps} editor={editor} selected={true} />);
|
|
392
|
+
it('uses a fixed top offset and horizontal position from coordsAtPos', async () => {
|
|
393
|
+
const { container } = render(<MathNodeView {...defaultProps} selected={true} />);
|
|
257
394
|
await waitFor(() => {
|
|
258
395
|
const toolbar = container.querySelector('[data-toolbar-for]');
|
|
259
396
|
expect(toolbar).toBeInTheDocument();
|
|
260
|
-
|
|
261
|
-
expect(toolbar.style.top).toBe('190px');
|
|
397
|
+
expect(toolbar.style.top).toBe('40px');
|
|
262
398
|
expect(toolbar.style.left).toBe('50px');
|
|
263
399
|
});
|
|
264
400
|
});
|
|
265
401
|
|
|
266
|
-
it('
|
|
402
|
+
it('keeps the fixed top offset when the editor container is scrolled', async () => {
|
|
403
|
+
const containerEl = document.createElement('div');
|
|
404
|
+
containerEl.getBoundingClientRect = jest.fn(() => ({ top: -200, left: 0, width: 600, height: 400 }));
|
|
405
|
+
|
|
267
406
|
const editor = {
|
|
268
407
|
...defaultProps.editor,
|
|
269
|
-
_tiptapContainerEl:
|
|
408
|
+
_tiptapContainerEl: containerEl,
|
|
270
409
|
};
|
|
271
410
|
|
|
272
411
|
const { container } = render(<MathNodeView {...defaultProps} editor={editor} selected={true} />);
|
|
273
412
|
await waitFor(() => {
|
|
274
413
|
const toolbar = container.querySelector('[data-toolbar-for]');
|
|
275
414
|
expect(toolbar).toBeInTheDocument();
|
|
276
|
-
|
|
277
|
-
expect(toolbar.style.top).toBe('140px');
|
|
415
|
+
expect(toolbar.style.top).toBe('40px');
|
|
278
416
|
expect(toolbar.style.left).toBe('50px');
|
|
279
417
|
});
|
|
280
418
|
});
|
|
@@ -288,7 +426,7 @@ describe('MathNodeView', () => {
|
|
|
288
426
|
});
|
|
289
427
|
});
|
|
290
428
|
|
|
291
|
-
it('
|
|
429
|
+
it('updates horizontal position from coordsAtPos when selection changes', async () => {
|
|
292
430
|
const editor = {
|
|
293
431
|
...defaultProps.editor,
|
|
294
432
|
view: {
|
|
@@ -302,30 +440,11 @@ describe('MathNodeView', () => {
|
|
|
302
440
|
await waitFor(() => {
|
|
303
441
|
const toolbar = container.querySelector('[data-toolbar-for]');
|
|
304
442
|
expect(toolbar).toBeInTheDocument();
|
|
305
|
-
|
|
306
|
-
expect(toolbar.style.top).toBe('240px');
|
|
443
|
+
expect(toolbar.style.top).toBe('40px');
|
|
307
444
|
expect(toolbar.style.left).toBe('150px');
|
|
308
445
|
});
|
|
309
446
|
});
|
|
310
447
|
|
|
311
|
-
it('accounts for negative container top (scrolled container)', async () => {
|
|
312
|
-
const containerEl = document.createElement('div');
|
|
313
|
-
containerEl.getBoundingClientRect = jest.fn(() => ({ top: -200, left: 0, width: 600, height: 400 }));
|
|
314
|
-
|
|
315
|
-
const editor = {
|
|
316
|
-
...defaultProps.editor,
|
|
317
|
-
_tiptapContainerEl: containerEl,
|
|
318
|
-
};
|
|
319
|
-
|
|
320
|
-
const { container } = render(<MathNodeView {...defaultProps} editor={editor} selected={true} />);
|
|
321
|
-
await waitFor(() => {
|
|
322
|
-
const toolbar = container.querySelector('[data-toolbar-for]');
|
|
323
|
-
expect(toolbar).toBeInTheDocument();
|
|
324
|
-
// top = 100 + Math.abs(-200) + 40 = 340
|
|
325
|
-
expect(toolbar.style.top).toBe('340px');
|
|
326
|
-
});
|
|
327
|
-
});
|
|
328
|
-
|
|
329
448
|
it('portals toolbar into _tiptapContainerEl when available', async () => {
|
|
330
449
|
const containerEl = document.createElement('div');
|
|
331
450
|
containerEl.getBoundingClientRect = jest.fn(() => ({ top: 0, left: 0, width: 600, height: 400 }));
|
|
@@ -410,8 +529,13 @@ describe('MathNodeView', () => {
|
|
|
410
529
|
});
|
|
411
530
|
});
|
|
412
531
|
|
|
413
|
-
it('closes toolbar on outside click', async () => {
|
|
414
|
-
const
|
|
532
|
+
it('closes toolbar on outside click and runs handleDone', async () => {
|
|
533
|
+
const updateAttributes = jest.fn();
|
|
534
|
+
const editor = createMockEditor();
|
|
535
|
+
const { TextSelection } = require('prosemirror-state');
|
|
536
|
+
const { queryByTestId } = render(
|
|
537
|
+
<MathNodeView {...defaultProps} editor={editor} updateAttributes={updateAttributes} selected={true} />,
|
|
538
|
+
);
|
|
415
539
|
|
|
416
540
|
await waitFor(() => {
|
|
417
541
|
expect(queryByTestId('math-toolbar')).toBeInTheDocument();
|
|
@@ -421,6 +545,26 @@ describe('MathNodeView', () => {
|
|
|
421
545
|
|
|
422
546
|
await waitFor(() => {
|
|
423
547
|
expect(queryByTestId('math-toolbar')).not.toBeInTheDocument();
|
|
548
|
+
expect(updateAttributes).toHaveBeenCalledWith({ latex: 'x^2' });
|
|
549
|
+
expect(TextSelection.create).toHaveBeenCalledWith(editor.state.doc, 1);
|
|
550
|
+
expect(editor.state.tr.setSelection).toHaveBeenCalled();
|
|
551
|
+
expect(editor.view.dispatch).toHaveBeenCalledWith(editor.state.tr);
|
|
552
|
+
expect(editor.commands.focus).toHaveBeenCalled();
|
|
553
|
+
expect(editor._toolbarOpened).toBe(false);
|
|
554
|
+
});
|
|
555
|
+
});
|
|
556
|
+
|
|
557
|
+
it('does not close toolbar when clicking the math node preview', async () => {
|
|
558
|
+
const { getByTestId, queryByTestId } = render(<MathNodeView {...defaultProps} selected={true} />);
|
|
559
|
+
|
|
560
|
+
await waitFor(() => {
|
|
561
|
+
expect(queryByTestId('math-toolbar')).toBeInTheDocument();
|
|
562
|
+
});
|
|
563
|
+
|
|
564
|
+
fireEvent.click(getByTestId('math-preview'));
|
|
565
|
+
|
|
566
|
+
await waitFor(() => {
|
|
567
|
+
expect(queryByTestId('math-toolbar')).toBeInTheDocument();
|
|
424
568
|
});
|
|
425
569
|
});
|
|
426
570
|
|
package/src/extensions/math.js
CHANGED
|
@@ -195,6 +195,25 @@ export const MathNodeView = (props) => {
|
|
|
195
195
|
|
|
196
196
|
const latex = node.attrs.latex || '';
|
|
197
197
|
|
|
198
|
+
const handleChange = (newLatex) => {
|
|
199
|
+
updateAttributes({ latex: newLatex });
|
|
200
|
+
};
|
|
201
|
+
|
|
202
|
+
const handleDone = (newLatex) => {
|
|
203
|
+
updateAttributes({ latex: newLatex });
|
|
204
|
+
setShowToolbar(false);
|
|
205
|
+
|
|
206
|
+
editor._toolbarOpened = false;
|
|
207
|
+
|
|
208
|
+
const { selection, tr, doc } = editor.state;
|
|
209
|
+
const sel = TextSelection.create(doc, selection.from + 1);
|
|
210
|
+
|
|
211
|
+
// Build a fresh transaction from the current state and set the selection
|
|
212
|
+
tr.setSelection(sel);
|
|
213
|
+
editor.view.dispatch(tr);
|
|
214
|
+
editor.commands.focus();
|
|
215
|
+
};
|
|
216
|
+
|
|
198
217
|
useEffect(() => {
|
|
199
218
|
if (selected) {
|
|
200
219
|
setShowToolbar(true);
|
|
@@ -207,12 +226,10 @@ export const MathNodeView = (props) => {
|
|
|
207
226
|
|
|
208
227
|
useEffect(() => {
|
|
209
228
|
// Calculate position relative to selection
|
|
210
|
-
const container = editor?._tiptapContainerEl || document.body;
|
|
211
|
-
const bodyRect = container.getBoundingClientRect();
|
|
212
229
|
const { from } = editor.state.selection;
|
|
213
230
|
const start = editor.view.coordsAtPos(from);
|
|
214
231
|
setPosition({
|
|
215
|
-
top:
|
|
232
|
+
top: 40, // shift above
|
|
216
233
|
left: start.left,
|
|
217
234
|
});
|
|
218
235
|
|
|
@@ -247,6 +264,7 @@ export const MathNodeView = (props) => {
|
|
|
247
264
|
!clickedMathNode
|
|
248
265
|
) {
|
|
249
266
|
setShowToolbar(false);
|
|
267
|
+
handleDone(node.attrs.latex);
|
|
250
268
|
}
|
|
251
269
|
};
|
|
252
270
|
|
|
@@ -261,25 +279,6 @@ export const MathNodeView = (props) => {
|
|
|
261
279
|
return () => document.removeEventListener('click', handleClickOutside);
|
|
262
280
|
}, [editor, showToolbar]);
|
|
263
281
|
|
|
264
|
-
const handleChange = (newLatex) => {
|
|
265
|
-
updateAttributes({ latex: newLatex });
|
|
266
|
-
};
|
|
267
|
-
|
|
268
|
-
const handleDone = (newLatex) => {
|
|
269
|
-
updateAttributes({ latex: newLatex });
|
|
270
|
-
setShowToolbar(false);
|
|
271
|
-
|
|
272
|
-
editor._toolbarOpened = false;
|
|
273
|
-
|
|
274
|
-
const { selection, tr, doc } = editor.state;
|
|
275
|
-
const sel = TextSelection.create(doc, selection.from + 1);
|
|
276
|
-
|
|
277
|
-
// Build a fresh transaction from the current state and set the selection
|
|
278
|
-
tr.setSelection(sel);
|
|
279
|
-
editor.view.dispatch(tr);
|
|
280
|
-
editor.commands.focus();
|
|
281
|
-
};
|
|
282
|
-
|
|
283
282
|
return (
|
|
284
283
|
<NodeViewWrapper
|
|
285
284
|
className="math-node"
|
package/src/index.jsx
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import StyledEditor, { EditableHtml } from './components/EditableHtml';
|
|
2
2
|
import { ALL_PLUGINS, DEFAULT_PLUGINS } from './extensions';
|
|
3
|
-
|
|
4
|
-
export { EditableHtml, ALL_PLUGINS, DEFAULT_PLUGINS };
|
|
3
|
+
import { deleteInlineDropdownByIndex } from './components/respArea/inlineDropdownUtils';
|
|
4
|
+
export { EditableHtml, ALL_PLUGINS, DEFAULT_PLUGINS, deleteInlineDropdownByIndex };
|
|
5
5
|
export default StyledEditor;
|