@gravity-ui/markdown-editor 15.34.5 → 15.35.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/cjs/bundle/MarkupEditorView.js +1 -1
- package/build/cjs/bundle/MarkupEditorView.js.map +1 -1
- package/build/cjs/bundle/ToolbarView.d.ts +1 -2
- package/build/cjs/bundle/ToolbarView.js +22 -10
- package/build/cjs/bundle/ToolbarView.js.map +1 -1
- package/build/cjs/bundle/WysiwygEditorView.d.ts +1 -1
- package/build/cjs/bundle/WysiwygEditorView.js +4 -4
- package/build/cjs/bundle/WysiwygEditorView.js.map +1 -1
- package/build/cjs/bundle/config/markup.js +1 -0
- package/build/cjs/bundle/config/markup.js.map +1 -1
- package/build/cjs/bundle/config/wysiwyg.js +2 -0
- package/build/cjs/bundle/config/wysiwyg.js.map +1 -1
- package/build/cjs/bundle/emoji.js +3 -0
- package/build/cjs/bundle/emoji.js.map +1 -1
- package/build/cjs/bundle/toolbar/wysiwyg/WToolbarColors.js +36 -2
- package/build/cjs/bundle/toolbar/wysiwyg/WToolbarColors.js.map +1 -1
- package/build/cjs/extensions/additional/Mermaid/MermaidNodeView/MermaidView.js +11 -7
- package/build/cjs/extensions/additional/Mermaid/MermaidNodeView/MermaidView.js.map +1 -1
- package/build/cjs/extensions/additional/Mermaid/index.d.ts +5 -0
- package/build/cjs/extensions/additional/Mermaid/index.js.map +1 -1
- package/build/cjs/extensions/markdown/Lists/commands.d.ts +1 -0
- package/build/cjs/extensions/markdown/Lists/commands.js +14 -0
- package/build/cjs/extensions/markdown/Lists/commands.js.map +1 -1
- package/build/cjs/extensions/markdown/Lists/index.js +1 -0
- package/build/cjs/extensions/markdown/Lists/index.js.map +1 -1
- package/build/cjs/extensions/yfm/YfmTable/plugins/YfmTableControls/dnd/dnd-auto-scroll.d.ts +27 -0
- package/build/cjs/extensions/yfm/YfmTable/plugins/YfmTableControls/dnd/dnd-auto-scroll.js +81 -0
- package/build/cjs/extensions/yfm/YfmTable/plugins/YfmTableControls/dnd/dnd-auto-scroll.js.map +1 -0
- package/build/cjs/extensions/yfm/YfmTable/plugins/YfmTableControls/dnd/dnd.js +33 -0
- package/build/cjs/extensions/yfm/YfmTable/plugins/YfmTableControls/dnd/dnd.js.map +1 -1
- package/build/cjs/modules/toolbars/items.js +2 -0
- package/build/cjs/modules/toolbars/items.js.map +1 -1
- package/build/cjs/modules/toolbars/types.d.ts +1 -0
- package/build/cjs/modules/toolbars/types.js.map +1 -1
- package/build/cjs/react-utils/memo.d.ts +1 -0
- package/build/cjs/react-utils/memo.js +8 -0
- package/build/cjs/react-utils/memo.js.map +1 -0
- package/build/cjs/styles/markdown.css +1 -1
- package/build/cjs/styles/styles.css +5 -0
- package/build/cjs/styles/yfm-overrides.css +1 -1
- package/build/cjs/toolbar/Toolbar.d.ts +4 -0
- package/build/cjs/toolbar/Toolbar.js +9 -4
- package/build/cjs/toolbar/Toolbar.js.map +1 -1
- package/build/cjs/toolbar/ToolbarButton.js +3 -3
- package/build/cjs/toolbar/ToolbarButton.js.map +1 -1
- package/build/cjs/toolbar/ToolbarButtonPopup.js +3 -3
- package/build/cjs/toolbar/ToolbarButtonPopup.js.map +1 -1
- package/build/cjs/toolbar/ToolbarGroup.js +5 -4
- package/build/cjs/toolbar/ToolbarGroup.js.map +1 -1
- package/build/cjs/toolbar/ToolbarListButton.js +9 -6
- package/build/cjs/toolbar/ToolbarListButton.js.map +1 -1
- package/build/cjs/toolbar/ToolbarRerender.d.ts +3 -0
- package/build/cjs/toolbar/ToolbarRerender.js +48 -0
- package/build/cjs/toolbar/ToolbarRerender.js.map +1 -0
- package/build/cjs/toolbar/context.d.ts +10 -0
- package/build/cjs/toolbar/context.js +12 -0
- package/build/cjs/toolbar/context.js.map +1 -0
- package/build/cjs/toolbar/hooks.d.ts +8 -0
- package/build/cjs/toolbar/hooks.js +68 -0
- package/build/cjs/toolbar/hooks.js.map +1 -0
- package/build/cjs/toolbar/index.d.ts +1 -0
- package/build/cjs/toolbar/index.js +4 -0
- package/build/cjs/toolbar/index.js.map +1 -1
- package/build/cjs/toolbar/types.d.ts +1 -0
- package/build/cjs/toolbar/types.js.map +1 -1
- package/build/cjs/version.js +1 -1
- package/build/cjs/version.js.map +1 -1
- package/build/cjs/view/hocs/withMermaid/index.js +6 -1
- package/build/cjs/view/hocs/withMermaid/index.js.map +1 -1
- package/build/esm/bundle/MarkupEditorView.js +1 -1
- package/build/esm/bundle/MarkupEditorView.js.map +1 -1
- package/build/esm/bundle/ToolbarView.d.ts +1 -2
- package/build/esm/bundle/ToolbarView.js +24 -12
- package/build/esm/bundle/ToolbarView.js.map +1 -1
- package/build/esm/bundle/WysiwygEditorView.d.ts +1 -1
- package/build/esm/bundle/WysiwygEditorView.js +3 -4
- package/build/esm/bundle/WysiwygEditorView.js.map +1 -1
- package/build/esm/bundle/config/markup.js +1 -0
- package/build/esm/bundle/config/markup.js.map +1 -1
- package/build/esm/bundle/config/wysiwyg.js +2 -0
- package/build/esm/bundle/config/wysiwyg.js.map +1 -1
- package/build/esm/bundle/emoji.js +3 -0
- package/build/esm/bundle/emoji.js.map +1 -1
- package/build/esm/bundle/toolbar/wysiwyg/WToolbarColors.js +36 -2
- package/build/esm/bundle/toolbar/wysiwyg/WToolbarColors.js.map +1 -1
- package/build/esm/extensions/additional/Mermaid/MermaidNodeView/MermaidView.js +11 -7
- package/build/esm/extensions/additional/Mermaid/MermaidNodeView/MermaidView.js.map +1 -1
- package/build/esm/extensions/additional/Mermaid/index.d.ts +5 -0
- package/build/esm/extensions/additional/Mermaid/index.js.map +1 -1
- package/build/esm/extensions/markdown/Lists/commands.d.ts +1 -0
- package/build/esm/extensions/markdown/Lists/commands.js +13 -0
- package/build/esm/extensions/markdown/Lists/commands.js.map +1 -1
- package/build/esm/extensions/markdown/Lists/index.js +2 -1
- package/build/esm/extensions/markdown/Lists/index.js.map +1 -1
- package/build/esm/extensions/yfm/YfmTable/plugins/YfmTableControls/dnd/dnd-auto-scroll.d.ts +27 -0
- package/build/esm/extensions/yfm/YfmTable/plugins/YfmTableControls/dnd/dnd-auto-scroll.js +77 -0
- package/build/esm/extensions/yfm/YfmTable/plugins/YfmTableControls/dnd/dnd-auto-scroll.js.map +1 -0
- package/build/esm/extensions/yfm/YfmTable/plugins/YfmTableControls/dnd/dnd.js +33 -0
- package/build/esm/extensions/yfm/YfmTable/plugins/YfmTableControls/dnd/dnd.js.map +1 -1
- package/build/esm/modules/toolbars/items.js +2 -0
- package/build/esm/modules/toolbars/items.js.map +1 -1
- package/build/esm/modules/toolbars/types.d.ts +1 -0
- package/build/esm/modules/toolbars/types.js.map +1 -1
- package/build/esm/react-utils/memo.d.ts +1 -0
- package/build/esm/react-utils/memo.js +5 -0
- package/build/esm/react-utils/memo.js.map +1 -0
- package/build/esm/styles/markdown.css +1 -1
- package/build/esm/styles/styles.css +5 -0
- package/build/esm/styles/yfm-overrides.css +1 -1
- package/build/esm/toolbar/Toolbar.d.ts +4 -0
- package/build/esm/toolbar/Toolbar.js +9 -4
- package/build/esm/toolbar/Toolbar.js.map +1 -1
- package/build/esm/toolbar/ToolbarButton.js +3 -3
- package/build/esm/toolbar/ToolbarButton.js.map +1 -1
- package/build/esm/toolbar/ToolbarButtonPopup.js +3 -3
- package/build/esm/toolbar/ToolbarButtonPopup.js.map +1 -1
- package/build/esm/toolbar/ToolbarGroup.js +5 -4
- package/build/esm/toolbar/ToolbarGroup.js.map +1 -1
- package/build/esm/toolbar/ToolbarListButton.js +9 -6
- package/build/esm/toolbar/ToolbarListButton.js.map +1 -1
- package/build/esm/toolbar/ToolbarRerender.d.ts +3 -0
- package/build/esm/toolbar/ToolbarRerender.js +44 -0
- package/build/esm/toolbar/ToolbarRerender.js.map +1 -0
- package/build/esm/toolbar/context.d.ts +10 -0
- package/build/esm/toolbar/context.js +8 -0
- package/build/esm/toolbar/context.js.map +1 -0
- package/build/esm/toolbar/hooks.d.ts +8 -0
- package/build/esm/toolbar/hooks.js +64 -0
- package/build/esm/toolbar/hooks.js.map +1 -0
- package/build/esm/toolbar/index.d.ts +1 -0
- package/build/esm/toolbar/index.js +1 -0
- package/build/esm/toolbar/index.js.map +1 -1
- package/build/esm/toolbar/types.d.ts +1 -0
- package/build/esm/toolbar/types.js.map +1 -1
- package/build/esm/version.js +1 -1
- package/build/esm/version.js.map +1 -1
- package/build/esm/view/hocs/withMermaid/index.js +6 -1
- package/build/esm/view/hocs/withMermaid/index.js.map +1 -1
- package/build/styles.css +7 -2
- package/package.json +17 -79
- package/README.md +0 -89
|
@@ -1,10 +1,44 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useState } from 'react';
|
|
3
|
+
import { useLatest } from 'react-use';
|
|
4
|
+
import { isEqual } from "../../../lodash.js";
|
|
5
|
+
import { useToolbarContext } from "../../../toolbar/context.js";
|
|
2
6
|
import { ToolbarColors } from "../custom/ToolbarColors.js";
|
|
3
7
|
export const WToolbarColors = ({ disablePortal, className, editor, focus, onClick, }) => {
|
|
8
|
+
const { active, enabled, currentColor } = useColorsState(editor);
|
|
4
9
|
const action = editor.actions.colorify;
|
|
5
|
-
|
|
6
|
-
return (_jsx(ToolbarColors, { active: action.isActive(), enable: action.isEnable(), currentColor: currentColor, exec: (color) => {
|
|
10
|
+
return (_jsx(ToolbarColors, { active: active, enable: enabled, currentColor: currentColor, exec: (color) => {
|
|
7
11
|
action.run({ color: color === currentColor ? '' : color });
|
|
8
12
|
}, disablePortal: disablePortal, className: className, focus: focus, onClick: onClick, withDefault: true }));
|
|
9
13
|
};
|
|
14
|
+
function useColorsState(editor) {
|
|
15
|
+
const action = editor.actions.colorify;
|
|
16
|
+
const context = useToolbarContext();
|
|
17
|
+
const [state, setState] = useState({
|
|
18
|
+
active: false,
|
|
19
|
+
enabled: true,
|
|
20
|
+
currentColor: '',
|
|
21
|
+
});
|
|
22
|
+
const stateRef = useLatest(state);
|
|
23
|
+
useEffect(() => {
|
|
24
|
+
if (!context)
|
|
25
|
+
return undefined;
|
|
26
|
+
const onUpdate = () => {
|
|
27
|
+
const newState = {
|
|
28
|
+
active: action.isActive(),
|
|
29
|
+
enabled: action.isEnable(),
|
|
30
|
+
currentColor: action.meta(),
|
|
31
|
+
};
|
|
32
|
+
if (!isEqual(stateRef.current, newState)) {
|
|
33
|
+
setState(newState);
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
onUpdate();
|
|
37
|
+
context.eventBus.on('update', onUpdate);
|
|
38
|
+
return () => {
|
|
39
|
+
context.eventBus.off('update', onUpdate);
|
|
40
|
+
};
|
|
41
|
+
}, [action, context, stateRef]);
|
|
42
|
+
return state;
|
|
43
|
+
}
|
|
10
44
|
//# sourceMappingURL=WToolbarColors.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WToolbarColors.js","sourceRoot":"../../../../../src","sources":["bundle/toolbar/wysiwyg/WToolbarColors.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAC,aAAa,EAA0B,mCAAgC;AAK/E,MAAM,CAAC,MAAM,cAAc,GAAkC,CAAC,EAC1D,aAAa,EACb,SAAS,EACT,MAAM,EACN,KAAK,EACL,OAAO,GACV,EAAE,EAAE;IACD,MAAM,MAAM,GAAG,
|
|
1
|
+
{"version":3,"file":"WToolbarColors.js","sourceRoot":"../../../../../src","sources":["bundle/toolbar/wysiwyg/WToolbarColors.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAC,SAAS,EAAE,QAAQ,EAAC,MAAM,OAAO,CAAC;AAE1C,OAAO,EAAC,SAAS,EAAC,MAAM,WAAW,CAAC;AAGpC,OAAO,EAAC,OAAO,EAAC,2BAAmB;AACnC,OAAO,EAAC,iBAAiB,EAAC,oCAA4B;AAEtD,OAAO,EAAC,aAAa,EAA0B,mCAAgC;AAK/E,MAAM,CAAC,MAAM,cAAc,GAAkC,CAAC,EAC1D,aAAa,EACb,SAAS,EACT,MAAM,EACN,KAAK,EACL,OAAO,GACV,EAAE,EAAE;IACD,MAAM,EAAC,MAAM,EAAE,OAAO,EAAE,YAAY,EAAC,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;IAC/D,MAAM,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC;IAEvC,OAAO,CACH,KAAC,aAAa,IACV,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,OAAO,EACf,YAAY,EAAE,YAAY,EAC1B,IAAI,EAAE,CAAC,KAAK,EAAE,EAAE;YACZ,MAAM,CAAC,GAAG,CAAC,EAAC,KAAK,EAAE,KAAK,KAAK,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,EAAC,CAAC,CAAC;QAC7D,CAAC,EACD,aAAa,EAAE,aAAa,EAC5B,SAAS,EAAE,SAAS,EACpB,KAAK,EAAE,KAAK,EACZ,OAAO,EAAE,OAAO,EAChB,WAAW,SACb,CACL,CAAC;AACN,CAAC,CAAC;AAQF,SAAS,cAAc,CAAC,MAAqB;IACzC,MAAM,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC;IAEvC,MAAM,OAAO,GAAG,iBAAiB,EAAE,CAAC;IAEpC,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAc;QAC5C,MAAM,EAAE,KAAK;QACb,OAAO,EAAE,IAAI;QACb,YAAY,EAAE,EAAE;KACnB,CAAC,CAAC;IACH,MAAM,QAAQ,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC;IAElC,SAAS,CAAC,GAAG,EAAE;QACX,IAAI,CAAC,OAAO;YAAE,OAAO,SAAS,CAAC;QAE/B,MAAM,QAAQ,GAAG,GAAG,EAAE;YAClB,MAAM,QAAQ,GAAG;gBACb,MAAM,EAAE,MAAM,CAAC,QAAQ,EAAE;gBACzB,OAAO,EAAE,MAAM,CAAC,QAAQ,EAAE;gBAC1B,YAAY,EAAE,MAAM,CAAC,IAAI,EAAE;aAC9B,CAAC;YAEF,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,EAAE,CAAC;gBACvC,QAAQ,CAAC,QAAQ,CAAC,CAAC;YACvB,CAAC;QACL,CAAC,CAAC;QAEF,QAAQ,EAAE,CAAC;QAEX,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QAExC,OAAO,GAAG,EAAE;YACR,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QAC7C,CAAC,CAAC;IACN,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC;IAEhC,OAAO,KAAK,CAAC;AACjB,CAAC","sourcesContent":["import {useEffect, useState} from 'react';\n\nimport {useLatest} from 'react-use';\n\nimport type {ActionStorage} from '#core';\nimport {isEqual} from 'src/lodash';\nimport {useToolbarContext} from 'src/toolbar/context';\n\nimport {ToolbarColors, type ToolbarColorsProps} from '../custom/ToolbarColors';\nimport type {WToolbarBaseProps} from '../types';\n\nexport type WToolbarColorsProps = WToolbarBaseProps & Pick<ToolbarColorsProps, 'disablePortal'>;\n\nexport const WToolbarColors: React.FC<WToolbarColorsProps> = ({\n disablePortal,\n className,\n editor,\n focus,\n onClick,\n}) => {\n const {active, enabled, currentColor} = useColorsState(editor);\n const action = editor.actions.colorify;\n\n return (\n <ToolbarColors\n active={active}\n enable={enabled}\n currentColor={currentColor}\n exec={(color) => {\n action.run({color: color === currentColor ? '' : color});\n }}\n disablePortal={disablePortal}\n className={className}\n focus={focus}\n onClick={onClick}\n withDefault\n />\n );\n};\n\ntype ColorsState = {\n active: boolean;\n enabled: boolean;\n currentColor: string;\n};\n\nfunction useColorsState(editor: ActionStorage): ColorsState {\n const action = editor.actions.colorify;\n\n const context = useToolbarContext();\n\n const [state, setState] = useState<ColorsState>({\n active: false,\n enabled: true,\n currentColor: '',\n });\n const stateRef = useLatest(state);\n\n useEffect(() => {\n if (!context) return undefined;\n\n const onUpdate = () => {\n const newState = {\n active: action.isActive(),\n enabled: action.isEnable(),\n currentColor: action.meta(),\n };\n\n if (!isEqual(stateRef.current, newState)) {\n setState(newState);\n }\n };\n\n onUpdate();\n\n context.eventBus.on('update', onUpdate);\n\n return () => {\n context.eventBus.off('update', onUpdate);\n };\n }, [action, context, stateRef]);\n\n return state;\n}\n"]}
|
|
@@ -14,7 +14,7 @@ export const cnMermaid = cn('Mermaid');
|
|
|
14
14
|
export const STOP_EVENT_CLASSNAME = 'prosemirror-stop-event';
|
|
15
15
|
import "./Mermaid.css";
|
|
16
16
|
const b = cnMermaid;
|
|
17
|
-
const MermaidPreview = ({ mermaidInstance, text = '', }) => {
|
|
17
|
+
const MermaidPreview = ({ mermaidInstance, text = '', options }) => {
|
|
18
18
|
const [svg, setSvg] = useState();
|
|
19
19
|
const [error, setError] = useState(null);
|
|
20
20
|
const theme = useThemeType();
|
|
@@ -24,7 +24,11 @@ const MermaidPreview = ({ mermaidInstance, text = '', }) => {
|
|
|
24
24
|
try {
|
|
25
25
|
// Validates syntax and throws error if text is invalid
|
|
26
26
|
await mermaidInstance.parse(text);
|
|
27
|
-
|
|
27
|
+
if (options.theme) {
|
|
28
|
+
mermaidInstance.initialize({
|
|
29
|
+
theme: theme === 'dark' ? options.theme.dark : options.theme.light,
|
|
30
|
+
});
|
|
31
|
+
}
|
|
28
32
|
const { svg: S } = await mermaidInstance.render(`mermaid-${Date.now()}`, text);
|
|
29
33
|
setSvg(S);
|
|
30
34
|
setError(null);
|
|
@@ -35,20 +39,20 @@ const MermaidPreview = ({ mermaidInstance, text = '', }) => {
|
|
|
35
39
|
}
|
|
36
40
|
};
|
|
37
41
|
p();
|
|
38
|
-
}, [mermaidInstance, text, theme]);
|
|
42
|
+
}, [mermaidInstance, text, theme, options.theme]);
|
|
39
43
|
if (error) {
|
|
40
44
|
return _jsx("div", { className: b('Error'), children: error && _jsx("div", { children: error }) });
|
|
41
45
|
}
|
|
42
46
|
return (_jsx("div", { className: b('Preview'), children: svg ? _jsx("div", { className: "mermaid", dangerouslySetInnerHTML: { __html: svg } }) : _jsx(Loader, {}) }));
|
|
43
47
|
};
|
|
44
|
-
const DiagramEditMode = ({ initialText, onSave, onCancel, mermaidInstance, options
|
|
48
|
+
const DiagramEditMode = ({ initialText, onSave, onCancel, mermaidInstance, options }) => {
|
|
45
49
|
const { value, handleChange, handleManualSave, isSaveDisabled, isAutoSaveEnabled } = useAutoSave({
|
|
46
50
|
initialValue: initialText || '',
|
|
47
51
|
onSave,
|
|
48
52
|
onClose: onCancel,
|
|
49
|
-
autoSave,
|
|
53
|
+
autoSave: options.autoSave,
|
|
50
54
|
});
|
|
51
|
-
return (_jsxs("div", { className: b(), children: [_jsx(MermaidPreview, { mermaidInstance: mermaidInstance, text: value }), _jsxs("div", { className: b('Editor'), children: [_jsx("div", { children: _jsx(TextArea, { controlProps: {
|
|
55
|
+
return (_jsxs("div", { className: b(), children: [_jsx(MermaidPreview, { mermaidInstance: mermaidInstance, text: value, options: options }), _jsxs("div", { className: b('Editor'), children: [_jsx("div", { children: _jsx(TextArea, { controlProps: {
|
|
52
56
|
className: STOP_EVENT_CLASSNAME,
|
|
53
57
|
}, value: value, onUpdate: handleChange, autoFocus: true }) }), _jsx("div", { className: b('Controls'), children: _jsxs("div", { children: [_jsx(Button, { onClick: onCancel, view: 'flat', children: _jsx("span", { className: STOP_EVENT_CLASSNAME, children: isAutoSaveEnabled ? i18n('close') : i18n('cancel') }) }), !isAutoSaveEnabled && (_jsx(Button, { onClick: handleManualSave, view: 'action', disabled: isSaveDisabled, children: _jsx("span", { className: STOP_EVENT_CLASSNAME, children: i18n('save') }) }))] }) })] })] }));
|
|
54
58
|
};
|
|
@@ -75,7 +79,7 @@ export const MermaidView = ({ onChange, node, getPos, view, getMermaidInstance,
|
|
|
75
79
|
onChange({ [MermaidConsts.NodeAttrs.content]: v });
|
|
76
80
|
}, options: options }));
|
|
77
81
|
}
|
|
78
|
-
return (_jsxs("div", { className: b(), onDoubleClick: setEditing, children: [_jsx(MermaidPreview, { mermaidInstance: mermaidInstance, text: node.attrs[MermaidConsts.NodeAttrs.content] }), _jsxs("div", { children: [_jsx(Button, { onClick: toggleMenuOpen, ref: setAnchorElement, size: 's', className: STOP_EVENT_CLASSNAME, children: _jsx(Icon, { data: DotsIcon, className: STOP_EVENT_CLASSNAME }) }), _jsx(Popup, { open: menuOpen, anchorElement: anchorElement, onOpenChange: closeMenu, placement: "bottom-end", children: _jsxs(Menu, { children: [_jsx(Menu.Item, { onClick: () => {
|
|
82
|
+
return (_jsxs("div", { className: b(), onDoubleClick: setEditing, children: [_jsx(MermaidPreview, { mermaidInstance: mermaidInstance, text: node.attrs[MermaidConsts.NodeAttrs.content], options: options }), _jsxs("div", { children: [_jsx(Button, { onClick: toggleMenuOpen, ref: setAnchorElement, size: 's', className: STOP_EVENT_CLASSNAME, children: _jsx(Icon, { data: DotsIcon, className: STOP_EVENT_CLASSNAME }) }), _jsx(Popup, { open: menuOpen, anchorElement: anchorElement, onOpenChange: closeMenu, placement: "bottom-end", children: _jsxs(Menu, { children: [_jsx(Menu.Item, { onClick: () => {
|
|
79
83
|
setEditing();
|
|
80
84
|
closeMenu();
|
|
81
85
|
}, children: i18n('edit') }), _jsx(Menu.Item, { onClick: () => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MermaidView.js","sourceRoot":"../../../../../../src","sources":["extensions/additional/Mermaid/MermaidNodeView/MermaidView.tsx"],"names":[],"mappings":"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","sourcesContent":["import {useEffect, useMemo, useState} from 'react';\n\nimport {Ellipsis as DotsIcon} from '@gravity-ui/icons';\nimport {Button, Icon, Loader, Menu, Popup, useThemeType} from '@gravity-ui/uikit';\nimport type {Mermaid} from 'mermaid' with {'resolution-mode': 'import'};\nimport type {Node} from 'prosemirror-model';\nimport type {EditorView} from 'prosemirror-view';\n\nimport {SharedStateKey} from 'src/extensions/behavior/SharedState';\nimport {useSharedEditingState} from 'src/react-utils/useSharedEditingState';\n\nimport {cn} from '../../../../classname';\nimport {TextAreaFixed as TextArea} from '../../../../forms/TextInput';\nimport {i18n} from '../../../../i18n/common';\nimport {useAutoSave, useBooleanState, useElementState} from '../../../../react-utils';\nimport {removeNode} from '../../../../utils';\nimport {MermaidConsts} from '../MermaidSpecs/const';\nimport type {MermaidOptions} from '../index';\nimport type {MermaidEntitySharedState} from '../types';\n\nexport const cnMermaid = cn('Mermaid');\n\nexport const STOP_EVENT_CLASSNAME = 'prosemirror-stop-event';\n\nimport './Mermaid.scss';\n\nconst b = cnMermaid;\n\nconst MermaidPreview: React.FC<{mermaidInstance: Mermaid | null; text: string}> = ({\n mermaidInstance,\n text = '',\n}) => {\n const [svg, setSvg] = useState<string>();\n const [error, setError] = useState<string | null>(null);\n\n const theme = useThemeType();\n\n useEffect(() => {\n const p = async () => {\n if (mermaidInstance) {\n try {\n // Validates syntax and throws error if text is invalid\n await mermaidInstance.parse(text);\n\n mermaidInstance.initialize({theme: theme === 'dark' ? 'dark' : 'forest'});\n\n const {svg: S} = await mermaidInstance.render(`mermaid-${Date.now()}`, text);\n\n setSvg(S);\n setError(null);\n } catch (e) {\n setError((e as Error).message);\n }\n }\n };\n\n p();\n }, [mermaidInstance, text, theme]);\n\n if (error) {\n return <div className={b('Error')}>{error && <div>{error}</div>}</div>;\n }\n\n return (\n <div className={b('Preview')}>\n {svg ? <div className=\"mermaid\" dangerouslySetInnerHTML={{__html: svg}} /> : <Loader />}\n </div>\n );\n};\n\nconst DiagramEditMode: React.FC<{\n initialText: string;\n mermaidInstance: Mermaid | null;\n onSave: (v: string) => void;\n onCancel: () => void;\n options: MermaidOptions;\n}> = ({initialText, onSave, onCancel, mermaidInstance, options: {autoSave}}) => {\n const {value, handleChange, handleManualSave, isSaveDisabled, isAutoSaveEnabled} = useAutoSave({\n initialValue: initialText || '',\n onSave,\n onClose: onCancel,\n autoSave,\n });\n\n return (\n <div className={b()}>\n <MermaidPreview mermaidInstance={mermaidInstance} text={value} />\n <div className={b('Editor')}>\n <div>\n <TextArea\n controlProps={{\n className: STOP_EVENT_CLASSNAME,\n }}\n value={value}\n onUpdate={handleChange}\n autoFocus\n />\n </div>\n <div className={b('Controls')}>\n <div>\n <Button onClick={onCancel} view={'flat'}>\n <span className={STOP_EVENT_CLASSNAME}>\n {isAutoSaveEnabled ? i18n('close') : i18n('cancel')}\n </span>\n </Button>\n {!isAutoSaveEnabled && (\n <Button\n onClick={handleManualSave}\n view={'action'}\n disabled={isSaveDisabled}\n >\n <span className={STOP_EVENT_CLASSNAME}>{i18n('save')}</span>\n </Button>\n )}\n </div>\n </div>\n </div>\n </div>\n );\n};\n\nexport const MermaidView: React.FC<{\n view: EditorView;\n onChange: (attrs: {[MermaidConsts.NodeAttrs.content]: string}) => void;\n getMermaidInstance: () => Mermaid;\n node: Node;\n getPos: () => number | undefined;\n options: MermaidOptions;\n}> = ({onChange, node, getPos, view, getMermaidInstance, options}) => {\n const enitityId: string = node.attrs[MermaidConsts.NodeAttrs.EntityId];\n const entityKey = useMemo(\n () => SharedStateKey.define<MermaidEntitySharedState>({name: enitityId}),\n [enitityId],\n );\n\n const [editing, setEditing, unsetEditing] = useSharedEditingState(view, entityKey);\n const [menuOpen, , closeMenu, toggleMenuOpen] = useBooleanState(false);\n const [anchorElement, setAnchorElement] = useElementState();\n\n const [mermaidInstance, setMermaidInstance] = useState<Mermaid | null>(null);\n useEffect(() => {\n const waitForMermaid = () =>\n setTimeout(() => {\n const instance = getMermaidInstance();\n if (instance) {\n setMermaidInstance(instance);\n\n return;\n }\n\n waitForMermaid();\n }, 100);\n\n waitForMermaid();\n }, []);\n\n if (editing) {\n return (\n <DiagramEditMode\n initialText={node.attrs[MermaidConsts.NodeAttrs.content]}\n mermaidInstance={mermaidInstance}\n onCancel={unsetEditing}\n onSave={(v) => {\n onChange({[MermaidConsts.NodeAttrs.content]: v});\n }}\n options={options}\n />\n );\n }\n\n return (\n <div className={b()} onDoubleClick={setEditing}>\n <MermaidPreview\n mermaidInstance={mermaidInstance}\n text={node.attrs[MermaidConsts.NodeAttrs.content]}\n />\n <div>\n <Button\n onClick={toggleMenuOpen}\n ref={setAnchorElement}\n size={'s'}\n className={STOP_EVENT_CLASSNAME}\n >\n <Icon data={DotsIcon} className={STOP_EVENT_CLASSNAME} />\n </Button>\n <Popup\n open={menuOpen}\n anchorElement={anchorElement}\n onOpenChange={closeMenu}\n placement=\"bottom-end\"\n >\n <Menu>\n <Menu.Item\n onClick={() => {\n setEditing();\n closeMenu();\n }}\n >\n {i18n('edit')}\n </Menu.Item>\n <Menu.Item\n onClick={() => {\n const pos = getPos();\n if (pos === undefined) return;\n removeNode({\n node,\n pos,\n tr: view.state.tr,\n dispatch: view.dispatch,\n });\n }}\n >\n {i18n('remove')}\n </Menu.Item>\n </Menu>\n </Popup>\n </div>\n </div>\n );\n};\n"]}
|
|
1
|
+
{"version":3,"file":"MermaidView.js","sourceRoot":"../../../../../../src","sources":["extensions/additional/Mermaid/MermaidNodeView/MermaidView.tsx"],"names":[],"mappings":"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","sourcesContent":["import {useEffect, useMemo, useState} from 'react';\n\nimport {Ellipsis as DotsIcon} from '@gravity-ui/icons';\nimport {Button, Icon, Loader, Menu, Popup, useThemeType} from '@gravity-ui/uikit';\nimport type {Mermaid} from 'mermaid' with {'resolution-mode': 'import'};\nimport type {Node} from 'prosemirror-model';\nimport type {EditorView} from 'prosemirror-view';\n\nimport {SharedStateKey} from 'src/extensions/behavior/SharedState';\nimport {useSharedEditingState} from 'src/react-utils/useSharedEditingState';\n\nimport {cn} from '../../../../classname';\nimport {TextAreaFixed as TextArea} from '../../../../forms/TextInput';\nimport {i18n} from '../../../../i18n/common';\nimport {useAutoSave, useBooleanState, useElementState} from '../../../../react-utils';\nimport {removeNode} from '../../../../utils';\nimport {MermaidConsts} from '../MermaidSpecs/const';\nimport type {MermaidOptions} from '../index';\nimport type {MermaidEntitySharedState} from '../types';\n\nexport const cnMermaid = cn('Mermaid');\n\nexport const STOP_EVENT_CLASSNAME = 'prosemirror-stop-event';\n\nimport './Mermaid.scss';\n\nconst b = cnMermaid;\n\nconst MermaidPreview: React.FC<{\n mermaidInstance: Mermaid | null;\n text: string;\n options: MermaidOptions;\n}> = ({mermaidInstance, text = '', options}) => {\n const [svg, setSvg] = useState<string>();\n const [error, setError] = useState<string | null>(null);\n\n const theme = useThemeType();\n\n useEffect(() => {\n const p = async () => {\n if (mermaidInstance) {\n try {\n // Validates syntax and throws error if text is invalid\n await mermaidInstance.parse(text);\n\n if (options.theme) {\n mermaidInstance.initialize({\n theme: theme === 'dark' ? options.theme.dark : options.theme.light,\n });\n }\n\n const {svg: S} = await mermaidInstance.render(`mermaid-${Date.now()}`, text);\n\n setSvg(S);\n setError(null);\n } catch (e) {\n setError((e as Error).message);\n }\n }\n };\n\n p();\n }, [mermaidInstance, text, theme, options.theme]);\n\n if (error) {\n return <div className={b('Error')}>{error && <div>{error}</div>}</div>;\n }\n\n return (\n <div className={b('Preview')}>\n {svg ? <div className=\"mermaid\" dangerouslySetInnerHTML={{__html: svg}} /> : <Loader />}\n </div>\n );\n};\n\nconst DiagramEditMode: React.FC<{\n initialText: string;\n mermaidInstance: Mermaid | null;\n onSave: (v: string) => void;\n onCancel: () => void;\n options: MermaidOptions;\n}> = ({initialText, onSave, onCancel, mermaidInstance, options}) => {\n const {value, handleChange, handleManualSave, isSaveDisabled, isAutoSaveEnabled} = useAutoSave({\n initialValue: initialText || '',\n onSave,\n onClose: onCancel,\n autoSave: options.autoSave,\n });\n\n return (\n <div className={b()}>\n <MermaidPreview mermaidInstance={mermaidInstance} text={value} options={options} />\n <div className={b('Editor')}>\n <div>\n <TextArea\n controlProps={{\n className: STOP_EVENT_CLASSNAME,\n }}\n value={value}\n onUpdate={handleChange}\n autoFocus\n />\n </div>\n <div className={b('Controls')}>\n <div>\n <Button onClick={onCancel} view={'flat'}>\n <span className={STOP_EVENT_CLASSNAME}>\n {isAutoSaveEnabled ? i18n('close') : i18n('cancel')}\n </span>\n </Button>\n {!isAutoSaveEnabled && (\n <Button\n onClick={handleManualSave}\n view={'action'}\n disabled={isSaveDisabled}\n >\n <span className={STOP_EVENT_CLASSNAME}>{i18n('save')}</span>\n </Button>\n )}\n </div>\n </div>\n </div>\n </div>\n );\n};\n\nexport const MermaidView: React.FC<{\n view: EditorView;\n onChange: (attrs: {[MermaidConsts.NodeAttrs.content]: string}) => void;\n getMermaidInstance: () => Mermaid;\n node: Node;\n getPos: () => number | undefined;\n options: MermaidOptions;\n}> = ({onChange, node, getPos, view, getMermaidInstance, options}) => {\n const enitityId: string = node.attrs[MermaidConsts.NodeAttrs.EntityId];\n const entityKey = useMemo(\n () => SharedStateKey.define<MermaidEntitySharedState>({name: enitityId}),\n [enitityId],\n );\n\n const [editing, setEditing, unsetEditing] = useSharedEditingState(view, entityKey);\n const [menuOpen, , closeMenu, toggleMenuOpen] = useBooleanState(false);\n const [anchorElement, setAnchorElement] = useElementState();\n\n const [mermaidInstance, setMermaidInstance] = useState<Mermaid | null>(null);\n useEffect(() => {\n const waitForMermaid = () =>\n setTimeout(() => {\n const instance = getMermaidInstance();\n if (instance) {\n setMermaidInstance(instance);\n\n return;\n }\n\n waitForMermaid();\n }, 100);\n\n waitForMermaid();\n }, []);\n\n if (editing) {\n return (\n <DiagramEditMode\n initialText={node.attrs[MermaidConsts.NodeAttrs.content]}\n mermaidInstance={mermaidInstance}\n onCancel={unsetEditing}\n onSave={(v) => {\n onChange({[MermaidConsts.NodeAttrs.content]: v});\n }}\n options={options}\n />\n );\n }\n\n return (\n <div className={b()} onDoubleClick={setEditing}>\n <MermaidPreview\n mermaidInstance={mermaidInstance}\n text={node.attrs[MermaidConsts.NodeAttrs.content]}\n options={options}\n />\n <div>\n <Button\n onClick={toggleMenuOpen}\n ref={setAnchorElement}\n size={'s'}\n className={STOP_EVENT_CLASSNAME}\n >\n <Icon data={DotsIcon} className={STOP_EVENT_CLASSNAME} />\n </Button>\n <Popup\n open={menuOpen}\n anchorElement={anchorElement}\n onOpenChange={closeMenu}\n placement=\"bottom-end\"\n >\n <Menu>\n <Menu.Item\n onClick={() => {\n setEditing();\n closeMenu();\n }}\n >\n {i18n('edit')}\n </Menu.Item>\n <Menu.Item\n onClick={() => {\n const pos = getPos();\n if (pos === undefined) return;\n removeNode({\n node,\n pos,\n tr: view.state.tr,\n dispatch: view.dispatch,\n });\n }}\n >\n {i18n('remove')}\n </Menu.Item>\n </Menu>\n </Popup>\n </div>\n </div>\n );\n};\n"]}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { MermaidConfig } from 'mermaid' with { 'resolution-mode': 'import' };
|
|
1
2
|
import type { Action, ExtensionAuto } from "../../../core/index.js";
|
|
2
3
|
import { MermaidAction } from "./MermaidSpecs/const.js";
|
|
3
4
|
export type MermaidOptions = {
|
|
@@ -6,6 +7,10 @@ export type MermaidOptions = {
|
|
|
6
7
|
enabled: boolean;
|
|
7
8
|
delay?: number;
|
|
8
9
|
};
|
|
10
|
+
theme?: {
|
|
11
|
+
dark: MermaidConfig['theme'];
|
|
12
|
+
light: MermaidConfig['theme'];
|
|
13
|
+
};
|
|
9
14
|
};
|
|
10
15
|
export declare const Mermaid: ExtensionAuto<MermaidOptions>;
|
|
11
16
|
declare global {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"../../../../../src","sources":["extensions/additional/Mermaid/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"../../../../../src","sources":["extensions/additional/Mermaid/index.ts"],"names":[],"mappings":"AAIA,OAAO,EAAC,gBAAgB,EAAC,mCAA0B;AACnD,OAAO,EAAC,YAAY,EAAC,gCAAuB;AAC5C,OAAO,EAAC,aAAa,EAAC,gCAA6B;AACnD,OAAO,EAAC,UAAU,EAAC,qBAAkB;AAcrC,MAAM,CAAC,MAAM,OAAO,GAAkC,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE;IACvE,OAAO,CAAC,GAAG,CAAC,YAAY,EAAE;QACtB,QAAQ,EAAE,sBAAsB,CAAC,OAAO,CAAC;KAC5C,CAAC,CAAC;IAEH,OAAO,CAAC,SAAS,CAAC,aAAa,EAAE,GAAG,EAAE,CAAC,UAAU,CAAC,CAAC;AACvD,CAAC,CAAC;AAEF,MAAM,sBAAsB,GAEwB,CAAC,OAAO,EAAE,EAAE,CAAC,GAAG,EAAE,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE;IAC1F,OAAO,IAAI,gBAAgB,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;AAC7D,CAAC,CAAC","sourcesContent":["import type {MermaidConfig} from 'mermaid' with {'resolution-mode': 'import'};\n\nimport type {Action, ExtensionAuto, ExtensionDeps, NodeViewConstructor} from '../../../core';\n\nimport {WMermaidNodeView} from './MermaidNodeView';\nimport {MermaidSpecs} from './MermaidSpecs';\nimport {MermaidAction} from './MermaidSpecs/const';\nimport {addMermaid} from './actions';\n\nexport type MermaidOptions = {\n loadRuntimeScript: () => void;\n autoSave?: {\n enabled: boolean;\n delay?: number;\n };\n theme?: {\n dark: MermaidConfig['theme'];\n light: MermaidConfig['theme'];\n };\n};\n\nexport const Mermaid: ExtensionAuto<MermaidOptions> = (builder, options) => {\n builder.use(MermaidSpecs, {\n nodeView: MermaidNodeViewFactory(options),\n });\n\n builder.addAction(MermaidAction, () => addMermaid);\n};\n\nconst MermaidNodeViewFactory: (\n opts: MermaidOptions,\n) => (deps: ExtensionDeps) => NodeViewConstructor = (options) => () => (node, view, getPos) => {\n return new WMermaidNodeView(node, view, getPos, options);\n};\n\ndeclare global {\n namespace WysiwygEditor {\n interface Actions {\n [MermaidAction]: Action;\n }\n }\n interface Window {\n mermaidJsonp: Function[];\n }\n}\n"]}
|
|
@@ -2,4 +2,5 @@ import { type NodeType } from 'prosemirror-model';
|
|
|
2
2
|
import type { Command } from 'prosemirror-state';
|
|
3
3
|
export declare function toList(listType: NodeType): Command;
|
|
4
4
|
export declare const joinPrevList: Command;
|
|
5
|
+
export declare function liftEmptyListItem(itemType: NodeType): Command;
|
|
5
6
|
export declare function sinkOnlySelectedListItem(itemType: NodeType): Command;
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
import { liftEmptyBlock } from 'prosemirror-commands';
|
|
1
2
|
import { Fragment, Slice } from 'prosemirror-model';
|
|
2
3
|
import { wrapInList } from 'prosemirror-schema-list';
|
|
3
4
|
import { ReplaceAroundStep, liftTarget } from 'prosemirror-transform';
|
|
4
5
|
import { joinPreviousBlock } from "../../../commands/join.js";
|
|
6
|
+
import { get$CursorAtBlockStart } from "../../../utils/selection.js";
|
|
5
7
|
import { findAnyParentList, isListNode, isListOrItemNode } from "./utils.js";
|
|
6
8
|
export function toList(listType) {
|
|
7
9
|
return (state, dispatch) => {
|
|
@@ -19,6 +21,17 @@ export const joinPrevList = joinPreviousBlock({
|
|
|
19
21
|
checkPrevNode: isListNode,
|
|
20
22
|
skipNode: isListOrItemNode,
|
|
21
23
|
});
|
|
24
|
+
export function liftEmptyListItem(itemType) {
|
|
25
|
+
return (state, dispatch) => {
|
|
26
|
+
const $cursor = get$CursorAtBlockStart(state.selection);
|
|
27
|
+
if (!$cursor ||
|
|
28
|
+
$cursor.parent.content.size !== 0 ||
|
|
29
|
+
$cursor.node(-1).type !== itemType ||
|
|
30
|
+
$cursor.node(-1).childCount !== 1)
|
|
31
|
+
return false;
|
|
32
|
+
return liftEmptyBlock(state, dispatch);
|
|
33
|
+
};
|
|
34
|
+
}
|
|
22
35
|
/*
|
|
23
36
|
Simplified `sinkListItem` from `prosemirror-schema-list` without `state`/`dispatch`,
|
|
24
37
|
sinks list items deeper.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"commands.js","sourceRoot":"../../../../../src","sources":["extensions/markdown/Lists/commands.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,QAAQ,EAAiC,KAAK,EAAC,MAAM,mBAAmB,CAAC;AACjF,OAAO,EAAC,UAAU,EAAC,MAAM,yBAAyB,CAAC;AAEnD,OAAO,EAAC,iBAAiB,EAAE,UAAU,EAAC,MAAM,uBAAuB,CAAC;AAEpE,OAAO,EAAC,iBAAiB,EAAC,kCAA+B;
|
|
1
|
+
{"version":3,"file":"commands.js","sourceRoot":"../../../../../src","sources":["extensions/markdown/Lists/commands.ts"],"names":[],"mappings":"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","sourcesContent":["import {liftEmptyBlock} from 'prosemirror-commands';\nimport {Fragment, type NodeRange, type NodeType, Slice} from 'prosemirror-model';\nimport {wrapInList} from 'prosemirror-schema-list';\nimport type {Command, Transaction} from 'prosemirror-state';\nimport {ReplaceAroundStep, liftTarget} from 'prosemirror-transform';\n\nimport {joinPreviousBlock} from '../../../commands/join';\nimport {get$CursorAtBlockStart} from '../../../utils/selection';\n\nimport {findAnyParentList, isListNode, isListOrItemNode} from './utils';\n\nexport function toList(listType: NodeType): Command {\n return (state, dispatch) => {\n const parentList = findAnyParentList(state.schema)(state.selection);\n if (parentList) {\n if (listType === parentList.node.type) return true;\n\n dispatch?.(state.tr.setNodeMarkup(parentList.pos, listType));\n return true;\n }\n return wrapInList(listType)(state, dispatch);\n };\n}\n\nexport const joinPrevList = joinPreviousBlock({\n checkPrevNode: isListNode,\n skipNode: isListOrItemNode,\n});\n\nexport function liftEmptyListItem(itemType: NodeType): Command {\n return (state, dispatch) => {\n const $cursor = get$CursorAtBlockStart(state.selection);\n if (\n !$cursor ||\n $cursor.parent.content.size !== 0 ||\n $cursor.node(-1).type !== itemType ||\n $cursor.node(-1).childCount !== 1\n )\n return false;\n\n return liftEmptyBlock(state, dispatch);\n };\n}\n\n/*\n Simplified `sinkListItem` from `prosemirror-schema-list` without `state`/`dispatch`,\n sinks list items deeper.\n */\nconst sink = (tr: Transaction, range: NodeRange, itemType: NodeType) => {\n const before = tr.mapping.map(range.start);\n const after = tr.mapping.map(range.end);\n const startIndex = tr.mapping.map(range.startIndex);\n\n const parent = range.parent;\n const nodeBefore = parent.child(startIndex - 1);\n\n const nestedBefore = nodeBefore.lastChild && nodeBefore.lastChild.type === parent.type;\n const inner = Fragment.from(nestedBefore ? itemType.create() : null);\n const slice = new Slice(\n Fragment.from(itemType.create(null, Fragment.from(parent.type.create(null, inner)))),\n nestedBefore ? 3 : 1,\n 0,\n );\n\n tr.step(\n new ReplaceAroundStep(\n before - (nestedBefore ? 3 : 1),\n after,\n before,\n after,\n slice,\n 1,\n true,\n ),\n );\n return true;\n};\n\nexport function sinkOnlySelectedListItem(itemType: NodeType): Command {\n return ({tr, selection}, dispatch) => {\n const {$from, $to} = selection;\n const selectionRange = $from.blockRange(\n $to,\n (node) => node.childCount > 0 && node.firstChild!.type === itemType,\n );\n if (!selectionRange) {\n return false;\n }\n\n const {startIndex, parent, start, end} = selectionRange;\n if (startIndex === 0) {\n return false;\n }\n\n const nodeBefore = parent.child(startIndex - 1);\n if (nodeBefore.type !== itemType) {\n return false;\n }\n\n if (dispatch) {\n // lifts following list items sequentially to prepare correct nesting structure\n let currentEnd = end - 1;\n while (currentEnd > start) {\n const selectionEnd = tr.mapping.map($to.pos);\n\n const $candidateBlockEnd = tr.doc.resolve(currentEnd);\n const candidateBlockStartPos = $candidateBlockEnd.before($candidateBlockEnd.depth);\n const $candidateBlockStart = tr.doc.resolve(candidateBlockStartPos);\n const candidateBlockRange = $candidateBlockStart.blockRange($candidateBlockEnd);\n\n if (candidateBlockRange?.start) {\n const $rangeStart = tr.doc.resolve(candidateBlockRange.start);\n const shouldLift =\n candidateBlockRange.start > selectionEnd && isListNode($rangeStart.parent);\n\n if (shouldLift) {\n currentEnd = candidateBlockRange.start;\n\n const targetDepth = liftTarget(candidateBlockRange);\n if (targetDepth !== null) {\n tr.lift(candidateBlockRange, targetDepth);\n }\n }\n }\n\n currentEnd--;\n }\n\n // sinks the selected list item deeper into the list hierarchy\n sink(tr, selectionRange, itemType);\n\n dispatch(tr.scrollIntoView());\n return true;\n }\n return true;\n };\n}\n"]}
|
|
@@ -2,7 +2,7 @@ import { liftListItem, splitListItem } from 'prosemirror-schema-list';
|
|
|
2
2
|
import { withLogAction } from "../../../utils/keymap.js";
|
|
3
3
|
import { ListsSpecs, blType, liType, olType } from "./ListsSpecs/index.js";
|
|
4
4
|
import { actions } from "./actions.js";
|
|
5
|
-
import { joinPrevList, sinkOnlySelectedListItem, toList } from "./commands.js";
|
|
5
|
+
import { joinPrevList, liftEmptyListItem, sinkOnlySelectedListItem, toList } from "./commands.js";
|
|
6
6
|
import { ListAction } from "./const.js";
|
|
7
7
|
import { ListsInputRulesExtension } from "./inputrules.js";
|
|
8
8
|
import { collapseListsPlugin } from "./plugins/CollapseListsPlugin.js";
|
|
@@ -20,6 +20,7 @@ export const Lists = (builder, opts) => {
|
|
|
20
20
|
return {
|
|
21
21
|
Tab: sinkOnlySelectedListItem(liType(schema)),
|
|
22
22
|
'Shift-Tab': liftListItem(liType(schema)),
|
|
23
|
+
Backspace: liftEmptyListItem(liType(schema)),
|
|
23
24
|
'Mod-[': liftListItem(liType(schema)),
|
|
24
25
|
'Mod-]': sinkOnlySelectedListItem(liType(schema)),
|
|
25
26
|
...bindings,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"../../../../../src","sources":["extensions/markdown/Lists/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,YAAY,EAAE,aAAa,EAAC,MAAM,yBAAyB,CAAC;AAGpE,OAAO,EAAC,aAAa,EAAC,iCAA8B;AAEpD,OAAO,EAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAC,8BAAqB;AAChE,OAAO,EAAC,OAAO,EAAC,qBAAkB;AAClC,OAAO,EAAC,YAAY,EAAE,wBAAwB,EAAE,MAAM,EAAC,sBAAmB;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"../../../../../src","sources":["extensions/markdown/Lists/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,YAAY,EAAE,aAAa,EAAC,MAAM,yBAAyB,CAAC;AAGpE,OAAO,EAAC,aAAa,EAAC,iCAA8B;AAEpD,OAAO,EAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAC,8BAAqB;AAChE,OAAO,EAAC,OAAO,EAAC,qBAAkB;AAClC,OAAO,EAAC,YAAY,EAAE,iBAAiB,EAAE,wBAAwB,EAAE,MAAM,EAAC,sBAAmB;AAC7F,OAAO,EAAC,UAAU,EAAC,mBAAgB;AACnC,OAAO,EAAC,wBAAwB,EAA8B,wBAAqB;AACnF,OAAO,EAAC,mBAAmB,EAAC,yCAAsC;AAClE,OAAO,EAAC,gBAAgB,EAAC,sCAAmC;AAE5D,OAAO,EAAC,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAC,8BAAqB;AAQzE,MAAM,CAAC,MAAM,KAAK,GAAgC,CAAC,OAAO,EAAE,IAAI,EAAE,EAAE;IAChE,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IAExB,OAAO,CAAC,SAAS,CAAC,CAAC,EAAC,MAAM,EAAC,EAAE,EAAE;QAC3B,MAAM,EAAC,KAAK,EAAE,KAAK,EAAC,GAAG,IAAI,IAAI,EAAE,CAAC;QAClC,MAAM,QAAQ,GAAW,EAAE,CAAC;QAC5B,IAAI,KAAK;YAAE,QAAQ,CAAC,KAAK,CAAC,GAAG,aAAa,CAAC,YAAY,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QACjF,IAAI,KAAK;YAAE,QAAQ,CAAC,KAAK,CAAC,GAAG,aAAa,CAAC,aAAa,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QAElF,OAAO;YACH,GAAG,EAAE,wBAAwB,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;YAC7C,WAAW,EAAE,YAAY,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;YACzC,SAAS,EAAE,iBAAiB,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;YAE5C,OAAO,EAAE,YAAY,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;YACrC,OAAO,EAAE,wBAAwB,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;YAEjD,GAAG,QAAQ;SACd,CAAC;IACN,CAAC,EAAE,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IAE1B,OAAO,CAAC,SAAS,CACb,CAAC,EAAC,MAAM,EAAC,EAAE,EAAE,CAAC,CAAC;QACX,KAAK,EAAE,aAAa,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QACpC,SAAS,EAAE,YAAY;KAC1B,CAAC,EACF,OAAO,CAAC,QAAQ,CAAC,GAAG,CACvB,CAAC;IAEF,OAAO,CAAC,GAAG,CAAC,wBAAwB,EAAE,EAAC,mBAAmB,EAAE,IAAI,EAAE,YAAY,EAAC,CAAC,CAAC;IAEjF,OAAO,CAAC,SAAS,CAAC,gBAAgB,CAAC,CAAC;IAEpC,OAAO,CAAC,SAAS,CAAC,mBAAmB,CAAC,CAAC;IAEvC,OAAO;SACF,SAAS,CAAC,UAAU,CAAC,YAAY,EAAE,OAAO,CAAC,YAAY,CAAC;SACxD,SAAS,CAAC,UAAU,CAAC,aAAa,EAAE,OAAO,CAAC,aAAa,CAAC;SAC1D,SAAS,CAAC,UAAU,CAAC,YAAY,EAAE,OAAO,CAAC,YAAY,CAAC;SACxD,SAAS,CAAC,UAAU,CAAC,YAAY,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC;AAClE,CAAC,CAAC","sourcesContent":["import {liftListItem, splitListItem} from 'prosemirror-schema-list';\n\nimport type {Action, ExtensionAuto, Keymap} from '../../../core';\nimport {withLogAction} from '../../../utils/keymap';\n\nimport {ListsSpecs, blType, liType, olType} from './ListsSpecs';\nimport {actions} from './actions';\nimport {joinPrevList, liftEmptyListItem, sinkOnlySelectedListItem, toList} from './commands';\nimport {ListAction} from './const';\nimport {ListsInputRulesExtension, type ListsInputRulesOptions} from './inputrules';\nimport {collapseListsPlugin} from './plugins/CollapseListsPlugin';\nimport {mergeListsPlugin} from './plugins/MergeListsPlugin';\n\nexport {ListNode, ListsAttr, blType, liType, olType} from './ListsSpecs';\n\nexport type ListsOptions = {\n ulKey?: string | null;\n olKey?: string | null;\n ulInputRules?: ListsInputRulesOptions['bulletListInputRule'];\n};\n\nexport const Lists: ExtensionAuto<ListsOptions> = (builder, opts) => {\n builder.use(ListsSpecs);\n\n builder.addKeymap(({schema}) => {\n const {ulKey, olKey} = opts ?? {};\n const bindings: Keymap = {};\n if (ulKey) bindings[ulKey] = withLogAction('bulletList', toList(blType(schema)));\n if (olKey) bindings[olKey] = withLogAction('orderedList', toList(olType(schema)));\n\n return {\n Tab: sinkOnlySelectedListItem(liType(schema)),\n 'Shift-Tab': liftListItem(liType(schema)),\n Backspace: liftEmptyListItem(liType(schema)),\n\n 'Mod-[': liftListItem(liType(schema)),\n 'Mod-]': sinkOnlySelectedListItem(liType(schema)),\n\n ...bindings,\n };\n }, builder.Priority.High);\n\n builder.addKeymap(\n ({schema}) => ({\n Enter: splitListItem(liType(schema)),\n Backspace: joinPrevList,\n }),\n builder.Priority.Low,\n );\n\n builder.use(ListsInputRulesExtension, {bulletListInputRule: opts?.ulInputRules});\n\n builder.addPlugin(mergeListsPlugin);\n\n builder.addPlugin(collapseListsPlugin);\n\n builder\n .addAction(ListAction.ToBulletList, actions.toBulletList)\n .addAction(ListAction.ToOrderedList, actions.toOrderedList)\n .addAction(ListAction.SinkListItem, actions.sinkListItem)\n .addAction(ListAction.LiftListItem, actions.liftListItem);\n};\n\ndeclare global {\n namespace WysiwygEditor {\n interface Actions {\n [ListAction.ToBulletList]: Action;\n [ListAction.ToOrderedList]: Action;\n [ListAction.SinkListItem]: Action;\n [ListAction.LiftListItem]: Action;\n }\n }\n}\n"]}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
type AutoScrollDirection = 'horizontal' | 'vertical' | 'both';
|
|
2
|
+
type AutoScrollOptions = {
|
|
3
|
+
edgeThreshold?: number;
|
|
4
|
+
maxSpeed?: number;
|
|
5
|
+
};
|
|
6
|
+
export declare class DnDAutoScroller {
|
|
7
|
+
private readonly _container;
|
|
8
|
+
private readonly _direction;
|
|
9
|
+
private readonly _edgeThreshold;
|
|
10
|
+
private readonly _maxSpeed;
|
|
11
|
+
private _clientX;
|
|
12
|
+
private _clientY;
|
|
13
|
+
private _rafId;
|
|
14
|
+
private _active;
|
|
15
|
+
constructor(scrollContainer: HTMLElement, direction: AutoScrollDirection, options?: AutoScrollOptions);
|
|
16
|
+
update(clientX: number, clientY: number): void;
|
|
17
|
+
destroy(): void;
|
|
18
|
+
private _startLoop;
|
|
19
|
+
private _getVisibleRect;
|
|
20
|
+
private _scrollStep;
|
|
21
|
+
/**
|
|
22
|
+
* Returns scroll delta for one axis.
|
|
23
|
+
* Negative when cursor is near the start edge, positive when near the end edge.
|
|
24
|
+
*/
|
|
25
|
+
private _calcDelta;
|
|
26
|
+
}
|
|
27
|
+
export {};
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
const DEFAULT_EDGE_THRESHOLD = 40; // px
|
|
2
|
+
const DEFAULT_MAX_SPEED = 15; // px per frame
|
|
3
|
+
export class DnDAutoScroller {
|
|
4
|
+
_container;
|
|
5
|
+
_direction;
|
|
6
|
+
_edgeThreshold;
|
|
7
|
+
_maxSpeed;
|
|
8
|
+
_clientX = 0;
|
|
9
|
+
_clientY = 0;
|
|
10
|
+
_rafId = null;
|
|
11
|
+
_active = false;
|
|
12
|
+
constructor(scrollContainer, direction, options) {
|
|
13
|
+
this._container = scrollContainer;
|
|
14
|
+
this._direction = direction;
|
|
15
|
+
this._edgeThreshold = options?.edgeThreshold ?? DEFAULT_EDGE_THRESHOLD;
|
|
16
|
+
this._maxSpeed = options?.maxSpeed ?? DEFAULT_MAX_SPEED;
|
|
17
|
+
}
|
|
18
|
+
update(clientX, clientY) {
|
|
19
|
+
this._clientX = clientX;
|
|
20
|
+
this._clientY = clientY;
|
|
21
|
+
if (!this._active) {
|
|
22
|
+
this._active = true;
|
|
23
|
+
this._startLoop();
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
destroy() {
|
|
27
|
+
if (this._rafId !== null) {
|
|
28
|
+
cancelAnimationFrame(this._rafId);
|
|
29
|
+
this._rafId = null;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
_startLoop() {
|
|
33
|
+
const tick = () => {
|
|
34
|
+
this._scrollStep();
|
|
35
|
+
this._rafId = requestAnimationFrame(tick);
|
|
36
|
+
};
|
|
37
|
+
this._rafId = requestAnimationFrame(tick);
|
|
38
|
+
}
|
|
39
|
+
_getVisibleRect() {
|
|
40
|
+
if (this._container === this._container.ownerDocument.documentElement) {
|
|
41
|
+
return { left: 0, top: 0, right: window.innerWidth, bottom: window.innerHeight };
|
|
42
|
+
}
|
|
43
|
+
return this._container.getBoundingClientRect();
|
|
44
|
+
}
|
|
45
|
+
_scrollStep() {
|
|
46
|
+
const rect = this._getVisibleRect();
|
|
47
|
+
let dx = 0;
|
|
48
|
+
let dy = 0;
|
|
49
|
+
if (this._direction === 'horizontal' || this._direction === 'both') {
|
|
50
|
+
dx = this._calcDelta(this._clientX, rect.left, rect.right);
|
|
51
|
+
}
|
|
52
|
+
if (this._direction === 'vertical' || this._direction === 'both') {
|
|
53
|
+
dy = this._calcDelta(this._clientY, rect.top, rect.bottom);
|
|
54
|
+
}
|
|
55
|
+
if (dx !== 0 || dy !== 0) {
|
|
56
|
+
this._container.scrollBy(dx, dy);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Returns scroll delta for one axis.
|
|
61
|
+
* Negative when cursor is near the start edge, positive when near the end edge.
|
|
62
|
+
*/
|
|
63
|
+
_calcDelta(cursor, edgeStart, edgeEnd) {
|
|
64
|
+
const distToStart = cursor - edgeStart;
|
|
65
|
+
const distToEnd = edgeEnd - cursor;
|
|
66
|
+
if (distToStart >= 0 && distToStart < this._edgeThreshold) {
|
|
67
|
+
const ratio = 1 - distToStart / this._edgeThreshold;
|
|
68
|
+
return -Math.round(this._maxSpeed * ratio);
|
|
69
|
+
}
|
|
70
|
+
if (distToEnd >= 0 && distToEnd < this._edgeThreshold) {
|
|
71
|
+
const ratio = 1 - distToEnd / this._edgeThreshold;
|
|
72
|
+
return Math.round(this._maxSpeed * ratio);
|
|
73
|
+
}
|
|
74
|
+
return 0;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=dnd-auto-scroll.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dnd-auto-scroll.js","sourceRoot":"../../../../../../../../src","sources":["extensions/yfm/YfmTable/plugins/YfmTableControls/dnd/dnd-auto-scroll.ts"],"names":[],"mappings":"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","sourcesContent":["type AutoScrollDirection = 'horizontal' | 'vertical' | 'both';\n\ntype AutoScrollOptions = {\n edgeThreshold?: number;\n maxSpeed?: number;\n};\n\nconst DEFAULT_EDGE_THRESHOLD = 40; // px\nconst DEFAULT_MAX_SPEED = 15; // px per frame\n\nexport class DnDAutoScroller {\n private readonly _container: HTMLElement;\n private readonly _direction: AutoScrollDirection;\n private readonly _edgeThreshold: number;\n private readonly _maxSpeed: number;\n\n private _clientX = 0;\n private _clientY = 0;\n private _rafId: number | null = null;\n private _active = false;\n\n constructor(\n scrollContainer: HTMLElement,\n direction: AutoScrollDirection,\n options?: AutoScrollOptions,\n ) {\n this._container = scrollContainer;\n this._direction = direction;\n this._edgeThreshold = options?.edgeThreshold ?? DEFAULT_EDGE_THRESHOLD;\n this._maxSpeed = options?.maxSpeed ?? DEFAULT_MAX_SPEED;\n }\n\n update(clientX: number, clientY: number): void {\n this._clientX = clientX;\n this._clientY = clientY;\n\n if (!this._active) {\n this._active = true;\n this._startLoop();\n }\n }\n\n destroy(): void {\n if (this._rafId !== null) {\n cancelAnimationFrame(this._rafId);\n this._rafId = null;\n }\n }\n\n private _startLoop(): void {\n const tick = () => {\n this._scrollStep();\n this._rafId = requestAnimationFrame(tick);\n };\n this._rafId = requestAnimationFrame(tick);\n }\n\n private _getVisibleRect(): {left: number; right: number; top: number; bottom: number} {\n if (this._container === this._container.ownerDocument.documentElement) {\n return {left: 0, top: 0, right: window.innerWidth, bottom: window.innerHeight};\n }\n return this._container.getBoundingClientRect();\n }\n\n private _scrollStep(): void {\n const rect = this._getVisibleRect();\n let dx = 0;\n let dy = 0;\n\n if (this._direction === 'horizontal' || this._direction === 'both') {\n dx = this._calcDelta(this._clientX, rect.left, rect.right);\n }\n\n if (this._direction === 'vertical' || this._direction === 'both') {\n dy = this._calcDelta(this._clientY, rect.top, rect.bottom);\n }\n\n if (dx !== 0 || dy !== 0) {\n this._container.scrollBy(dx, dy);\n }\n }\n\n /**\n * Returns scroll delta for one axis.\n * Negative when cursor is near the start edge, positive when near the end edge.\n */\n private _calcDelta(cursor: number, edgeStart: number, edgeEnd: number): number {\n const distToStart = cursor - edgeStart;\n const distToEnd = edgeEnd - cursor;\n\n if (distToStart >= 0 && distToStart < this._edgeThreshold) {\n const ratio = 1 - distToStart / this._edgeThreshold;\n return -Math.round(this._maxSpeed * ratio);\n }\n\n if (distToEnd >= 0 && distToEnd < this._edgeThreshold) {\n const ratio = 1 - distToEnd / this._edgeThreshold;\n return Math.round(this._maxSpeed * ratio);\n }\n\n return 0;\n }\n}\n"]}
|
|
@@ -8,6 +8,7 @@ import { YfmTableNode } from "../../../YfmTableSpecs/index.js";
|
|
|
8
8
|
import { clearAllSelections, selectDraggedColumn, selectDraggedRow } from "../plugins/dnd-plugin.js";
|
|
9
9
|
import { hideHoverDecos } from "../plugins/focus-plugin.js";
|
|
10
10
|
import { getSelectedCellsForColumns, getSelectedCellsForRows } from "../utils.js";
|
|
11
|
+
import { DnDAutoScroller } from "./dnd-auto-scroll.js";
|
|
11
12
|
import { TableColumnDropCursor, TableRowDropCursor, } from "./dnd-drop-cursor.js";
|
|
12
13
|
import { YfmTableDnDGhost } from "./dnd-ghost.js";
|
|
13
14
|
import "./dnd.css";
|
|
@@ -162,6 +163,10 @@ class YfmTableRowDnDHandler extends YfmTableDnDAbstractHandler {
|
|
|
162
163
|
rangeIdx: draggedRangeIdx,
|
|
163
164
|
tableDesc,
|
|
164
165
|
});
|
|
166
|
+
const scrollContainer = findScrollableAncestor(this._editorView.dom, 'vertical');
|
|
167
|
+
const autoScroller = scrollContainer
|
|
168
|
+
? new DnDAutoScroller(scrollContainer, 'vertical')
|
|
169
|
+
: null;
|
|
165
170
|
const onMoveDebounced = debounce((event) => {
|
|
166
171
|
this._moveDragging(event, {
|
|
167
172
|
rangeIdx: draggedRangeIdx,
|
|
@@ -170,11 +175,13 @@ class YfmTableRowDnDHandler extends YfmTableDnDAbstractHandler {
|
|
|
170
175
|
}, MOUSE_MOVE_DEBOUNCE, { maxWait: MOUSE_MOVE_DEBOUNCE });
|
|
171
176
|
const onMove = (event) => {
|
|
172
177
|
ghost.move(event);
|
|
178
|
+
autoScroller?.update(event.clientX, event.clientY);
|
|
173
179
|
onMoveDebounced(event);
|
|
174
180
|
};
|
|
175
181
|
document.addEventListener('mousemove', onMove);
|
|
176
182
|
document.addEventListener('mouseup', () => {
|
|
177
183
|
onMoveDebounced.flush();
|
|
184
|
+
autoScroller?.destroy();
|
|
178
185
|
ghost.destroy();
|
|
179
186
|
document.removeEventListener('mousemove', onMove);
|
|
180
187
|
this._endDragging(currRowRange, tableDesc);
|
|
@@ -323,6 +330,8 @@ class YfmTableColumnDnDHandler extends YfmTableDnDAbstractHandler {
|
|
|
323
330
|
rangeIdx: draggedRangeIdx,
|
|
324
331
|
tableDesc,
|
|
325
332
|
});
|
|
333
|
+
const { node: tableElem } = this._editorView.domAtPos(tableDesc.pos + 1);
|
|
334
|
+
const autoScroller = tableElem instanceof HTMLElement ? new DnDAutoScroller(tableElem, 'horizontal') : null;
|
|
326
335
|
const onMoveDebounced = debounce((event) => {
|
|
327
336
|
this._moveDragging(event, {
|
|
328
337
|
rangeIdx: draggedRangeIdx,
|
|
@@ -331,11 +340,13 @@ class YfmTableColumnDnDHandler extends YfmTableDnDAbstractHandler {
|
|
|
331
340
|
}, MOUSE_MOVE_DEBOUNCE, { maxWait: MOUSE_MOVE_DEBOUNCE });
|
|
332
341
|
const onMove = (event) => {
|
|
333
342
|
ghost.move(event);
|
|
343
|
+
autoScroller?.update(event.clientX, event.clientY);
|
|
334
344
|
onMoveDebounced(event);
|
|
335
345
|
};
|
|
336
346
|
document.addEventListener('mousemove', onMove);
|
|
337
347
|
document.addEventListener('mouseup', () => {
|
|
338
348
|
onMoveDebounced.flush();
|
|
349
|
+
autoScroller?.destroy();
|
|
339
350
|
ghost.destroy();
|
|
340
351
|
document.removeEventListener('mousemove', onMove);
|
|
341
352
|
this._endDragging(currColumnRange, tableDesc);
|
|
@@ -475,4 +486,26 @@ function isDragThresholdPassed(init, curr) {
|
|
|
475
486
|
return (Math.abs(init.pageX - curr.pageX) >= DRAG_START_THRESHOLD ||
|
|
476
487
|
Math.abs(init.pageY - curr.pageY) >= DRAG_START_THRESHOLD);
|
|
477
488
|
}
|
|
489
|
+
function findScrollableAncestor(element, axis) {
|
|
490
|
+
const prop = axis === 'vertical' ? 'overflowY' : 'overflowX';
|
|
491
|
+
let current = element.parentElement;
|
|
492
|
+
while (current && current !== document.documentElement) {
|
|
493
|
+
const overflow = getComputedStyle(current)[prop];
|
|
494
|
+
if (overflow === 'auto' || overflow === 'scroll') {
|
|
495
|
+
const hasScroll = axis === 'vertical'
|
|
496
|
+
? current.scrollHeight > current.clientHeight
|
|
497
|
+
: current.scrollWidth > current.clientWidth;
|
|
498
|
+
if (hasScroll)
|
|
499
|
+
return current;
|
|
500
|
+
}
|
|
501
|
+
current = current.parentElement;
|
|
502
|
+
}
|
|
503
|
+
const docEl = element.ownerDocument.documentElement;
|
|
504
|
+
const hasDocScroll = axis === 'vertical'
|
|
505
|
+
? docEl.scrollHeight > docEl.clientHeight
|
|
506
|
+
: docEl.scrollWidth > docEl.clientWidth;
|
|
507
|
+
if (hasDocScroll)
|
|
508
|
+
return docEl;
|
|
509
|
+
return null;
|
|
510
|
+
}
|
|
478
511
|
//# sourceMappingURL=dnd.js.map
|