@firecms/editor 3.0.0-canary.99 → 3.0.0-rc.2
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/dist/components/editor-bubble.d.ts +5 -2
- package/dist/components/index.d.ts +0 -3
- package/dist/editor.d.ts +18 -2
- package/dist/editor_extensions.d.ts +9 -3
- package/dist/extensions/CustomBlockComponent.d.ts +8 -0
- package/dist/extensions/HighlightDecorationExtension.d.ts +35 -0
- package/dist/extensions/Image.d.ts +6 -3
- package/dist/extensions/InlineAutocomplete.d.ts +7 -0
- package/dist/extensions/TextLoadingDecorationExtension.d.ts +18 -0
- package/dist/extensions/clipboard.d.ts +7 -0
- package/dist/extensions/index.d.ts +2 -3
- package/dist/extensions/slashCommand.d.ts +91 -0
- package/dist/index.es.js +1626 -802
- package/dist/index.es.js.map +1 -1
- package/dist/index.umd.js +1611 -797
- package/dist/index.umd.js.map +1 -1
- package/dist/selectors/node-selector.d.ts +2 -1
- package/dist/types.d.ts +3 -0
- package/package.json +49 -34
- package/dist/components/editor-command-item.d.ts +0 -19
- package/dist/components/editor-command.d.ts +0 -23
- package/dist/components/editor.d.ts +0 -29
- package/dist/extensions/slash-command.d.ts +0 -29
- package/dist/extensions/updated-image.d.ts +0 -2
package/dist/index.es.js
CHANGED
|
@@ -1,15 +1,21 @@
|
|
|
1
1
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
-
import React, { forwardRef, useRef, useEffect, useMemo,
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
import
|
|
2
|
+
import React, { forwardRef, useRef, useEffect, useState, useImperativeHandle, useMemo, useDeferredValue } from "react";
|
|
3
|
+
import { TextFieldsIcon, LooksOneIcon, LooksTwoIcon, Looks3Icon, CheckBoxIcon, FormatListBulletedIcon, FormatListNumberedIcon, FormatQuoteIcon, CodeIcon, CheckIcon, KeyboardArrowDownIcon, Button, Popover, cls, focusedDisabled, DeleteIcon, FormatBoldIcon, FormatItalicIcon, FormatUnderlinedIcon, FormatStrikethroughIcon, defaultBorderMixin, ImageIcon, AutoFixHighIcon, useInjectStyles, Separator } from "@firecms/ui";
|
|
4
|
+
import { useCurrentEditor, ReactRenderer, EditorProvider } from "@tiptap/react";
|
|
5
|
+
import Document from "@tiptap/extension-document";
|
|
6
6
|
import { Markdown } from "tiptap-markdown";
|
|
7
|
+
import Underline from "@tiptap/extension-underline";
|
|
8
|
+
import Heading from "@tiptap/extension-heading";
|
|
9
|
+
import { TextStyleKit } from "@tiptap/extension-text-style";
|
|
10
|
+
import Color from "@tiptap/extension-color";
|
|
7
11
|
import Highlight from "@tiptap/extension-highlight";
|
|
8
|
-
import
|
|
9
|
-
import
|
|
12
|
+
import Bold from "@tiptap/extension-bold";
|
|
13
|
+
import Italic from "@tiptap/extension-italic";
|
|
14
|
+
import Strike from "@tiptap/extension-strike";
|
|
15
|
+
import { c } from "react-compiler-runtime";
|
|
16
|
+
import { BubbleMenu } from "@tiptap/react/menus";
|
|
17
|
+
import { NodeSelection, PluginKey, Plugin } from "@tiptap/pm/state";
|
|
10
18
|
import { Slot } from "@radix-ui/react-slot";
|
|
11
|
-
import tunnel from "tunnel-rat";
|
|
12
|
-
import { Command as Command$1, CommandItem, CommandEmpty } from "cmdk";
|
|
13
19
|
import StarterKit from "@tiptap/starter-kit";
|
|
14
20
|
import HorizontalRule from "@tiptap/extension-horizontal-rule";
|
|
15
21
|
import TiptapLink from "@tiptap/extension-link";
|
|
@@ -17,320 +23,311 @@ import TiptapImage from "@tiptap/extension-image";
|
|
|
17
23
|
import Placeholder from "@tiptap/extension-placeholder";
|
|
18
24
|
import { TaskItem } from "@tiptap/extension-task-item";
|
|
19
25
|
import { TaskList } from "@tiptap/extension-task-list";
|
|
20
|
-
import { Extension, InputRule } from "@tiptap/core";
|
|
26
|
+
import { Extension, InputRule, Node, mergeAttributes } from "@tiptap/core";
|
|
27
|
+
import { DecorationSet, Decoration } from "@tiptap/pm/view";
|
|
28
|
+
import OrderedList from "@tiptap/extension-ordered-list";
|
|
29
|
+
import BulletList from "@tiptap/extension-bullet-list";
|
|
30
|
+
import ListItem from "@tiptap/extension-list-item";
|
|
31
|
+
import CodeBlock from "@tiptap/extension-code-block";
|
|
32
|
+
import Blockquote from "@tiptap/extension-blockquote";
|
|
33
|
+
import Code from "@tiptap/extension-code";
|
|
34
|
+
import { DOMSerializer } from "@tiptap/pm/model";
|
|
21
35
|
import Suggestion from "@tiptap/suggestion";
|
|
22
|
-
import
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
};
|
|
60
|
-
}, [rest, tippyOptions]);
|
|
61
|
-
if (!editor) return null;
|
|
62
|
-
return (
|
|
63
|
-
//We need to add this because of https://github.com/ueberdosis/tiptap/issues/2658
|
|
64
|
-
/* @__PURE__ */ jsx("div", { ref, children: /* @__PURE__ */ jsx(BubbleMenu, { editor, ...bubbleMenuProps, children }) })
|
|
65
|
-
);
|
|
66
|
-
}
|
|
67
|
-
);
|
|
68
|
-
const EditorBubbleItem = forwardRef(({ children, asChild, onSelect, ...rest }, ref) => {
|
|
69
|
-
const { editor } = useCurrentEditor();
|
|
70
|
-
const Comp = asChild ? Slot : "div";
|
|
71
|
-
if (!editor) return null;
|
|
72
|
-
return /* @__PURE__ */ jsx(Comp, { ref, ...rest, onClick: () => onSelect?.(editor), children });
|
|
73
|
-
});
|
|
74
|
-
EditorBubbleItem.displayName = "EditorBubbleItem";
|
|
75
|
-
const t = tunnel();
|
|
76
|
-
const queryAtom = atom("");
|
|
77
|
-
const rangeAtom = atom(null);
|
|
78
|
-
const EditorCommandOut = ({
|
|
79
|
-
query,
|
|
80
|
-
range
|
|
81
|
-
}) => {
|
|
82
|
-
const setQuery = useSetAtom(queryAtom, { store: editorStore });
|
|
83
|
-
const setRange = useSetAtom(rangeAtom, { store: editorStore });
|
|
84
|
-
useEffect(() => {
|
|
85
|
-
setQuery(query);
|
|
86
|
-
}, [query, setQuery]);
|
|
87
|
-
useEffect(() => {
|
|
88
|
-
setRange(range);
|
|
89
|
-
}, [range, setRange]);
|
|
90
|
-
useEffect(() => {
|
|
91
|
-
const navigationKeys = ["ArrowUp", "ArrowDown", "Enter"];
|
|
92
|
-
const onKeyDown = (e) => {
|
|
93
|
-
if (navigationKeys.includes(e.key)) {
|
|
94
|
-
e.preventDefault();
|
|
95
|
-
const commandRef = document.querySelector("#slash-command");
|
|
96
|
-
if (commandRef)
|
|
97
|
-
commandRef.dispatchEvent(
|
|
98
|
-
new KeyboardEvent("keydown", { key: e.key, cancelable: true, bubbles: true })
|
|
99
|
-
);
|
|
100
|
-
}
|
|
101
|
-
};
|
|
102
|
-
document.addEventListener("keydown", onKeyDown);
|
|
103
|
-
return () => {
|
|
104
|
-
document.removeEventListener("keydown", onKeyDown);
|
|
36
|
+
import { computePosition, offset, flip, shift, autoUpdate } from "@floating-ui/dom";
|
|
37
|
+
const EditorBubble = forwardRef((t0, ref) => {
|
|
38
|
+
const $ = c(18);
|
|
39
|
+
let children;
|
|
40
|
+
let options;
|
|
41
|
+
let rest;
|
|
42
|
+
let tippyOptions;
|
|
43
|
+
if ($[0] !== t0) {
|
|
44
|
+
({
|
|
45
|
+
children,
|
|
46
|
+
tippyOptions,
|
|
47
|
+
options,
|
|
48
|
+
...rest
|
|
49
|
+
} = t0);
|
|
50
|
+
$[0] = t0;
|
|
51
|
+
$[1] = children;
|
|
52
|
+
$[2] = options;
|
|
53
|
+
$[3] = rest;
|
|
54
|
+
$[4] = tippyOptions;
|
|
55
|
+
} else {
|
|
56
|
+
children = $[1];
|
|
57
|
+
options = $[2];
|
|
58
|
+
rest = $[3];
|
|
59
|
+
tippyOptions = $[4];
|
|
60
|
+
}
|
|
61
|
+
const {
|
|
62
|
+
editor
|
|
63
|
+
} = useCurrentEditor();
|
|
64
|
+
tippyOptions?.placement;
|
|
65
|
+
let t1;
|
|
66
|
+
const shouldShow = _temp$1;
|
|
67
|
+
const t2 = tippyOptions?.placement ?? options?.placement;
|
|
68
|
+
let t3;
|
|
69
|
+
if ($[5] !== options || $[6] !== t2) {
|
|
70
|
+
t3 = {
|
|
71
|
+
...options,
|
|
72
|
+
placement: t2
|
|
105
73
|
};
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
},
|
|
120
|
-
id: "slash-command",
|
|
121
|
-
className,
|
|
122
|
-
...rest,
|
|
123
|
-
children: [
|
|
124
|
-
/* @__PURE__ */ jsx(Command$1.Input, { value: query, onValueChange: setQuery, style: { display: "none" } }),
|
|
125
|
-
/* @__PURE__ */ jsx(Command$1.List, { ref: commandListRef, children })
|
|
126
|
-
]
|
|
127
|
-
}
|
|
128
|
-
) });
|
|
129
|
-
}
|
|
130
|
-
);
|
|
131
|
-
const EditorCommandItem = forwardRef(({ children, onCommand, ...rest }, ref) => {
|
|
132
|
-
const { editor } = useCurrentEditor();
|
|
133
|
-
const range = useAtomValue(rangeAtom);
|
|
134
|
-
if (!editor || !range) return null;
|
|
135
|
-
return /* @__PURE__ */ jsx(CommandItem, { ref, ...rest, onSelect: () => onCommand({ editor, range }), children });
|
|
136
|
-
});
|
|
137
|
-
EditorCommandItem.displayName = "EditorCommandItem";
|
|
138
|
-
const EditorCommandEmpty = CommandEmpty;
|
|
139
|
-
const Command = Extension.create({
|
|
140
|
-
name: "slash-command",
|
|
141
|
-
addOptions() {
|
|
142
|
-
return {
|
|
143
|
-
suggestion: {
|
|
144
|
-
char: "/",
|
|
145
|
-
command: ({ editor, range, props }) => {
|
|
146
|
-
props.command({ editor, range });
|
|
147
|
-
}
|
|
148
|
-
}
|
|
74
|
+
$[5] = options;
|
|
75
|
+
$[6] = t2;
|
|
76
|
+
$[7] = t3;
|
|
77
|
+
} else {
|
|
78
|
+
t3 = $[7];
|
|
79
|
+
}
|
|
80
|
+
const mergedOptions = t3;
|
|
81
|
+
let t4;
|
|
82
|
+
if ($[8] !== mergedOptions || $[9] !== rest) {
|
|
83
|
+
t4 = {
|
|
84
|
+
shouldShow,
|
|
85
|
+
options: mergedOptions,
|
|
86
|
+
...rest
|
|
149
87
|
};
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
...this.options.suggestion
|
|
156
|
-
})
|
|
157
|
-
];
|
|
88
|
+
$[8] = mergedOptions;
|
|
89
|
+
$[9] = rest;
|
|
90
|
+
$[10] = t4;
|
|
91
|
+
} else {
|
|
92
|
+
t4 = $[10];
|
|
158
93
|
}
|
|
94
|
+
t1 = t4;
|
|
95
|
+
const bubbleMenuProps = t1;
|
|
96
|
+
if (!editor) {
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
99
|
+
let t5;
|
|
100
|
+
if ($[11] !== bubbleMenuProps || $[12] !== children || $[13] !== editor) {
|
|
101
|
+
t5 = /* @__PURE__ */ jsx(BubbleMenu, { editor, ...bubbleMenuProps, children });
|
|
102
|
+
$[11] = bubbleMenuProps;
|
|
103
|
+
$[12] = children;
|
|
104
|
+
$[13] = editor;
|
|
105
|
+
$[14] = t5;
|
|
106
|
+
} else {
|
|
107
|
+
t5 = $[14];
|
|
108
|
+
}
|
|
109
|
+
let t6;
|
|
110
|
+
if ($[15] !== ref || $[16] !== t5) {
|
|
111
|
+
t6 = /* @__PURE__ */ jsx("div", { ref, children: t5 });
|
|
112
|
+
$[15] = ref;
|
|
113
|
+
$[16] = t5;
|
|
114
|
+
$[17] = t6;
|
|
115
|
+
} else {
|
|
116
|
+
t6 = $[17];
|
|
117
|
+
}
|
|
118
|
+
return t6;
|
|
159
119
|
});
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
includeChildren: true
|
|
207
|
-
});
|
|
208
|
-
const Horizontal = HorizontalRule.extend({
|
|
209
|
-
addInputRules() {
|
|
210
|
-
return [
|
|
211
|
-
new InputRule({
|
|
212
|
-
find: /^(?:---|—-|___\s|\*\*\*\s)$/,
|
|
213
|
-
handler: ({ state, range }) => {
|
|
214
|
-
const attributes = {};
|
|
215
|
-
const { tr } = state;
|
|
216
|
-
const start = range.from;
|
|
217
|
-
const end = range.to;
|
|
218
|
-
tr.insert(start - 1, this.type.create(attributes)).delete(
|
|
219
|
-
tr.mapping.map(start),
|
|
220
|
-
tr.mapping.map(end)
|
|
221
|
-
);
|
|
222
|
-
}
|
|
223
|
-
})
|
|
224
|
-
];
|
|
120
|
+
function _temp$1(t0) {
|
|
121
|
+
const {
|
|
122
|
+
editor: editor_0,
|
|
123
|
+
state
|
|
124
|
+
} = t0;
|
|
125
|
+
const {
|
|
126
|
+
selection
|
|
127
|
+
} = state;
|
|
128
|
+
const {
|
|
129
|
+
empty
|
|
130
|
+
} = selection;
|
|
131
|
+
if (editor_0.isActive("image") || empty || selection instanceof NodeSelection) {
|
|
132
|
+
return false;
|
|
133
|
+
}
|
|
134
|
+
return true;
|
|
135
|
+
}
|
|
136
|
+
const EditorBubbleItem = forwardRef((t0, ref) => {
|
|
137
|
+
const $ = c(14);
|
|
138
|
+
let asChild;
|
|
139
|
+
let children;
|
|
140
|
+
let onSelect;
|
|
141
|
+
let rest;
|
|
142
|
+
if ($[0] !== t0) {
|
|
143
|
+
({
|
|
144
|
+
children,
|
|
145
|
+
asChild,
|
|
146
|
+
onSelect,
|
|
147
|
+
...rest
|
|
148
|
+
} = t0);
|
|
149
|
+
$[0] = t0;
|
|
150
|
+
$[1] = asChild;
|
|
151
|
+
$[2] = children;
|
|
152
|
+
$[3] = onSelect;
|
|
153
|
+
$[4] = rest;
|
|
154
|
+
} else {
|
|
155
|
+
asChild = $[1];
|
|
156
|
+
children = $[2];
|
|
157
|
+
onSelect = $[3];
|
|
158
|
+
rest = $[4];
|
|
159
|
+
}
|
|
160
|
+
const {
|
|
161
|
+
editor
|
|
162
|
+
} = useCurrentEditor();
|
|
163
|
+
const Comp = asChild ? Slot : "div";
|
|
164
|
+
if (!editor) {
|
|
165
|
+
return null;
|
|
225
166
|
}
|
|
167
|
+
let t1;
|
|
168
|
+
if ($[5] !== editor || $[6] !== onSelect) {
|
|
169
|
+
t1 = () => onSelect?.(editor);
|
|
170
|
+
$[5] = editor;
|
|
171
|
+
$[6] = onSelect;
|
|
172
|
+
$[7] = t1;
|
|
173
|
+
} else {
|
|
174
|
+
t1 = $[7];
|
|
175
|
+
}
|
|
176
|
+
let t2;
|
|
177
|
+
if ($[8] !== Comp || $[9] !== children || $[10] !== ref || $[11] !== rest || $[12] !== t1) {
|
|
178
|
+
t2 = /* @__PURE__ */ jsx(Comp, { ref, ...rest, onClick: t1, children });
|
|
179
|
+
$[8] = Comp;
|
|
180
|
+
$[9] = children;
|
|
181
|
+
$[10] = ref;
|
|
182
|
+
$[11] = rest;
|
|
183
|
+
$[12] = t1;
|
|
184
|
+
$[13] = t2;
|
|
185
|
+
} else {
|
|
186
|
+
t2 = $[13];
|
|
187
|
+
}
|
|
188
|
+
return t2;
|
|
226
189
|
});
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
const
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
190
|
+
EditorBubbleItem.displayName = "EditorBubbleItem";
|
|
191
|
+
const items = [{
|
|
192
|
+
name: "Text",
|
|
193
|
+
icon: TextFieldsIcon,
|
|
194
|
+
command: (editor) => editor?.chain().focus().toggleNode("paragraph", "paragraph").run(),
|
|
195
|
+
// I feel like there has to be a more efficient way to do this – feel free to PR if you know how!
|
|
196
|
+
isActive: (editor) => (editor?.isActive("paragraph") && !editor?.isActive("bulletList") && !editor?.isActive("orderedList")) ?? false
|
|
197
|
+
}, {
|
|
198
|
+
name: "Heading 1",
|
|
199
|
+
icon: LooksOneIcon,
|
|
200
|
+
command: (editor) => editor?.chain().focus().toggleHeading({
|
|
201
|
+
level: 1
|
|
202
|
+
}).run(),
|
|
203
|
+
isActive: (editor) => editor?.isActive("heading", {
|
|
204
|
+
level: 1
|
|
205
|
+
}) ?? false
|
|
206
|
+
}, {
|
|
207
|
+
name: "Heading 2",
|
|
208
|
+
icon: LooksTwoIcon,
|
|
209
|
+
command: (editor) => editor?.chain().focus().toggleHeading({
|
|
210
|
+
level: 2
|
|
211
|
+
}).run(),
|
|
212
|
+
isActive: (editor) => editor?.isActive("heading", {
|
|
213
|
+
level: 2
|
|
214
|
+
}) ?? false
|
|
215
|
+
}, {
|
|
216
|
+
name: "Heading 3",
|
|
217
|
+
icon: Looks3Icon,
|
|
218
|
+
command: (editor) => editor?.chain().focus().toggleHeading({
|
|
219
|
+
level: 3
|
|
220
|
+
}).run(),
|
|
221
|
+
isActive: (editor) => editor?.isActive("heading", {
|
|
222
|
+
level: 3
|
|
223
|
+
}) ?? false
|
|
224
|
+
}, {
|
|
225
|
+
name: "To-do List",
|
|
226
|
+
icon: CheckBoxIcon,
|
|
227
|
+
command: (editor) => editor?.chain().focus().toggleTaskList().run(),
|
|
228
|
+
isActive: (editor) => editor?.isActive("taskItem") ?? false
|
|
229
|
+
}, {
|
|
230
|
+
name: "Bullet List",
|
|
231
|
+
icon: FormatListBulletedIcon,
|
|
232
|
+
command: (editor) => editor?.chain().focus().toggleBulletList().run(),
|
|
233
|
+
isActive: (editor) => editor?.isActive("bulletList") ?? false
|
|
234
|
+
}, {
|
|
235
|
+
name: "Numbered List",
|
|
236
|
+
icon: FormatListNumberedIcon,
|
|
237
|
+
command: (editor) => editor?.chain().focus().toggleOrderedList().run(),
|
|
238
|
+
isActive: (editor) => editor?.isActive("orderedList") ?? false
|
|
239
|
+
}, {
|
|
240
|
+
name: "Quote",
|
|
241
|
+
icon: FormatQuoteIcon,
|
|
242
|
+
command: (editor) => editor?.chain().focus().toggleNode("paragraph", "paragraph").toggleBlockquote().run(),
|
|
243
|
+
isActive: (editor) => editor?.isActive("blockquote") ?? false
|
|
244
|
+
}, {
|
|
245
|
+
name: "Code",
|
|
246
|
+
icon: CodeIcon,
|
|
247
|
+
command: (editor) => editor?.chain().focus().toggleCodeBlock().run(),
|
|
248
|
+
isActive: (editor) => editor?.isActive("codeBlock") ?? false
|
|
249
|
+
}];
|
|
250
|
+
const NodeSelector = (t0) => {
|
|
251
|
+
const $ = c(16);
|
|
252
|
+
const {
|
|
253
|
+
open,
|
|
254
|
+
onOpenChange,
|
|
255
|
+
portalContainer
|
|
256
|
+
} = t0;
|
|
257
|
+
const {
|
|
258
|
+
editor
|
|
259
|
+
} = useCurrentEditor();
|
|
260
|
+
if (!editor) {
|
|
261
|
+
return null;
|
|
262
|
+
}
|
|
263
|
+
let t1;
|
|
264
|
+
if ($[0] !== editor) {
|
|
265
|
+
t1 = items.filter((item) => item.isActive(editor)).pop() ?? {
|
|
266
|
+
name: "Multiple"
|
|
267
|
+
};
|
|
268
|
+
$[0] = editor;
|
|
269
|
+
$[1] = t1;
|
|
270
|
+
} else {
|
|
271
|
+
t1 = $[1];
|
|
272
|
+
}
|
|
273
|
+
const activeItem = t1;
|
|
274
|
+
let t2;
|
|
275
|
+
if ($[2] !== activeItem.name) {
|
|
276
|
+
t2 = /* @__PURE__ */ jsx("span", { className: "whitespace-nowrap text-sm", children: activeItem.name });
|
|
277
|
+
$[2] = activeItem.name;
|
|
278
|
+
$[3] = t2;
|
|
279
|
+
} else {
|
|
280
|
+
t2 = $[3];
|
|
281
|
+
}
|
|
282
|
+
let t3;
|
|
283
|
+
if ($[4] === Symbol.for("react.memo_cache_sentinel")) {
|
|
284
|
+
t3 = /* @__PURE__ */ jsx(KeyboardArrowDownIcon, { size: "small" });
|
|
285
|
+
$[4] = t3;
|
|
286
|
+
} else {
|
|
287
|
+
t3 = $[4];
|
|
288
|
+
}
|
|
289
|
+
let t4;
|
|
290
|
+
if ($[5] !== t2) {
|
|
291
|
+
t4 = /* @__PURE__ */ jsxs(Button, { variant: "text", className: "gap-2 rounded-none", color: "text", children: [
|
|
292
|
+
t2,
|
|
293
|
+
t3
|
|
294
|
+
] });
|
|
295
|
+
$[5] = t2;
|
|
296
|
+
$[6] = t4;
|
|
297
|
+
} else {
|
|
298
|
+
t4 = $[6];
|
|
299
|
+
}
|
|
300
|
+
let t5;
|
|
301
|
+
if ($[7] !== activeItem.name || $[8] !== onOpenChange) {
|
|
302
|
+
t5 = items.map((item_0, index) => /* @__PURE__ */ jsxs(EditorBubbleItem, { onSelect: (editor_0) => {
|
|
303
|
+
item_0.command(editor_0);
|
|
304
|
+
onOpenChange(false);
|
|
305
|
+
}, className: "flex cursor-pointer items-center justify-between rounded px-2 py-1 text-sm hover:bg-blue-50 hover:dark:bg-surface-700 text-surface-900 dark:text-white", children: [
|
|
306
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center space-x-2", children: [
|
|
307
|
+
/* @__PURE__ */ jsx(item_0.icon, { size: "smallest" }),
|
|
308
|
+
/* @__PURE__ */ jsx("span", { children: item_0.name })
|
|
309
|
+
] }),
|
|
310
|
+
activeItem.name === item_0.name && /* @__PURE__ */ jsx(CheckIcon, { size: "smallest" })
|
|
311
|
+
] }, index));
|
|
312
|
+
$[7] = activeItem.name;
|
|
313
|
+
$[8] = onOpenChange;
|
|
314
|
+
$[9] = t5;
|
|
315
|
+
} else {
|
|
316
|
+
t5 = $[9];
|
|
317
|
+
}
|
|
318
|
+
let t6;
|
|
319
|
+
if ($[10] !== onOpenChange || $[11] !== open || $[12] !== portalContainer || $[13] !== t4 || $[14] !== t5) {
|
|
320
|
+
t6 = /* @__PURE__ */ jsx(Popover, { sideOffset: 5, align: "start", portalContainer, className: "w-48 p-1", trigger: t4, modal: true, open, onOpenChange, children: t5 });
|
|
321
|
+
$[10] = onOpenChange;
|
|
322
|
+
$[11] = open;
|
|
323
|
+
$[12] = portalContainer;
|
|
324
|
+
$[13] = t4;
|
|
325
|
+
$[14] = t5;
|
|
326
|
+
$[15] = t6;
|
|
327
|
+
} else {
|
|
328
|
+
t6 = $[15];
|
|
329
|
+
}
|
|
330
|
+
return t6;
|
|
334
331
|
};
|
|
335
332
|
function isValidUrl(url) {
|
|
336
333
|
try {
|
|
@@ -351,162 +348,201 @@ function getUrlFromString(str) {
|
|
|
351
348
|
return null;
|
|
352
349
|
}
|
|
353
350
|
}
|
|
354
|
-
const LinkSelector = ({
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
351
|
+
const LinkSelector = (t0) => {
|
|
352
|
+
const $ = c(24);
|
|
353
|
+
const {
|
|
354
|
+
open,
|
|
355
|
+
onOpenChange
|
|
356
|
+
} = t0;
|
|
358
357
|
const inputRef = useRef(null);
|
|
359
|
-
const {
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
if (
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
358
|
+
const {
|
|
359
|
+
editor
|
|
360
|
+
} = useCurrentEditor();
|
|
361
|
+
let t1;
|
|
362
|
+
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
|
|
363
|
+
t1 = () => {
|
|
364
|
+
inputRef.current && inputRef.current?.focus();
|
|
365
|
+
};
|
|
366
|
+
$[0] = t1;
|
|
367
|
+
} else {
|
|
368
|
+
t1 = $[0];
|
|
369
|
+
}
|
|
370
|
+
useEffect(t1);
|
|
371
|
+
if (!editor) {
|
|
372
|
+
return null;
|
|
373
|
+
}
|
|
374
|
+
let t2;
|
|
375
|
+
if ($[1] !== editor) {
|
|
376
|
+
t2 = cls("underline decoration-stone-400 underline-offset-4", {
|
|
377
|
+
"text-blue-500": editor.isActive("link")
|
|
378
|
+
});
|
|
379
|
+
$[1] = editor;
|
|
380
|
+
$[2] = t2;
|
|
381
|
+
} else {
|
|
382
|
+
t2 = $[2];
|
|
383
|
+
}
|
|
384
|
+
let t3;
|
|
385
|
+
if ($[3] !== t2) {
|
|
386
|
+
t3 = /* @__PURE__ */ jsx(Button, { variant: "text", className: "gap-2 rounded-none", color: "text", children: /* @__PURE__ */ jsx("p", { className: t2, children: "Link" }) });
|
|
387
|
+
$[3] = t2;
|
|
388
|
+
$[4] = t3;
|
|
389
|
+
} else {
|
|
390
|
+
t3 = $[4];
|
|
391
|
+
}
|
|
392
|
+
let t4;
|
|
393
|
+
if ($[5] !== editor) {
|
|
394
|
+
t4 = (e) => {
|
|
395
|
+
const target = e.currentTarget;
|
|
396
|
+
e.preventDefault();
|
|
397
|
+
const input = target[0];
|
|
398
|
+
const url = getUrlFromString(input.value);
|
|
399
|
+
url && editor.chain().focus().setLink({
|
|
400
|
+
href: url
|
|
401
|
+
}).run();
|
|
402
|
+
};
|
|
403
|
+
$[5] = editor;
|
|
404
|
+
$[6] = t4;
|
|
405
|
+
} else {
|
|
406
|
+
t4 = $[6];
|
|
407
|
+
}
|
|
408
|
+
let t5;
|
|
409
|
+
if ($[7] !== editor) {
|
|
410
|
+
t5 = editor.getAttributes("link").href || "";
|
|
411
|
+
$[7] = editor;
|
|
412
|
+
$[8] = t5;
|
|
413
|
+
} else {
|
|
414
|
+
t5 = $[8];
|
|
415
|
+
}
|
|
416
|
+
let t6;
|
|
417
|
+
if ($[9] === Symbol.for("react.memo_cache_sentinel")) {
|
|
418
|
+
t6 = cls("text-surface-900 dark:text-white flex-grow bg-transparent p-1 text-sm outline-none", focusedDisabled);
|
|
419
|
+
$[9] = t6;
|
|
420
|
+
} else {
|
|
421
|
+
t6 = $[9];
|
|
422
|
+
}
|
|
423
|
+
let t7;
|
|
424
|
+
if ($[10] !== open || $[11] !== t5) {
|
|
425
|
+
t7 = /* @__PURE__ */ jsx("input", { ref: inputRef, autoFocus: open, placeholder: "Paste a link", defaultValue: t5, className: t6 });
|
|
426
|
+
$[10] = open;
|
|
427
|
+
$[11] = t5;
|
|
428
|
+
$[12] = t7;
|
|
429
|
+
} else {
|
|
430
|
+
t7 = $[12];
|
|
431
|
+
}
|
|
432
|
+
let t8;
|
|
433
|
+
if ($[13] !== editor) {
|
|
434
|
+
t8 = editor.getAttributes("link").href ? /* @__PURE__ */ jsx(Button, { size: "small", variant: "text", type: "button", color: "text", className: "flex items-center", onClick: () => {
|
|
435
|
+
editor.chain().focus().unsetLink().run();
|
|
436
|
+
}, children: /* @__PURE__ */ jsx(DeleteIcon, { size: "small" }) }) : /* @__PURE__ */ jsx(Button, { size: "small", variant: "text", children: /* @__PURE__ */ jsx(CheckIcon, { size: "small" }) });
|
|
437
|
+
$[13] = editor;
|
|
438
|
+
$[14] = t8;
|
|
439
|
+
} else {
|
|
440
|
+
t8 = $[14];
|
|
441
|
+
}
|
|
442
|
+
let t9;
|
|
443
|
+
if ($[15] !== t4 || $[16] !== t7 || $[17] !== t8) {
|
|
444
|
+
t9 = /* @__PURE__ */ jsxs("form", { onSubmit: t4, className: "flex p-1", children: [
|
|
445
|
+
t7,
|
|
446
|
+
t8
|
|
447
|
+
] });
|
|
448
|
+
$[15] = t4;
|
|
449
|
+
$[16] = t7;
|
|
450
|
+
$[17] = t8;
|
|
451
|
+
$[18] = t9;
|
|
452
|
+
} else {
|
|
453
|
+
t9 = $[18];
|
|
454
|
+
}
|
|
455
|
+
let t10;
|
|
456
|
+
if ($[19] !== onOpenChange || $[20] !== open || $[21] !== t3 || $[22] !== t9) {
|
|
457
|
+
t10 = /* @__PURE__ */ jsx(Popover, { modal: true, open, onOpenChange, trigger: t3, children: t9 });
|
|
458
|
+
$[19] = onOpenChange;
|
|
459
|
+
$[20] = open;
|
|
460
|
+
$[21] = t3;
|
|
461
|
+
$[22] = t9;
|
|
462
|
+
$[23] = t10;
|
|
463
|
+
} else {
|
|
464
|
+
t10 = $[23];
|
|
465
|
+
}
|
|
466
|
+
return t10;
|
|
429
467
|
};
|
|
430
468
|
const TextButtons = () => {
|
|
431
|
-
const
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
469
|
+
const $ = c(2);
|
|
470
|
+
const {
|
|
471
|
+
editor
|
|
472
|
+
} = useCurrentEditor();
|
|
473
|
+
if (!editor) {
|
|
474
|
+
return null;
|
|
475
|
+
}
|
|
476
|
+
let t0;
|
|
477
|
+
if ($[0] !== editor) {
|
|
478
|
+
const items2 = [{
|
|
435
479
|
name: "bold",
|
|
436
|
-
isActive:
|
|
437
|
-
command:
|
|
480
|
+
isActive: _temp,
|
|
481
|
+
command: _temp2,
|
|
438
482
|
icon: FormatBoldIcon
|
|
439
|
-
},
|
|
440
|
-
{
|
|
483
|
+
}, {
|
|
441
484
|
name: "italic",
|
|
442
|
-
isActive:
|
|
443
|
-
command:
|
|
485
|
+
isActive: _temp3,
|
|
486
|
+
command: _temp4,
|
|
444
487
|
icon: FormatItalicIcon
|
|
445
|
-
},
|
|
446
|
-
{
|
|
488
|
+
}, {
|
|
447
489
|
name: "underline",
|
|
448
|
-
isActive:
|
|
449
|
-
command:
|
|
490
|
+
isActive: _temp5,
|
|
491
|
+
command: _temp6,
|
|
450
492
|
icon: FormatUnderlinedIcon
|
|
451
|
-
},
|
|
452
|
-
{
|
|
493
|
+
}, {
|
|
453
494
|
name: "strike",
|
|
454
|
-
isActive:
|
|
455
|
-
command:
|
|
495
|
+
isActive: _temp7,
|
|
496
|
+
command: _temp8,
|
|
456
497
|
icon: FormatStrikethroughIcon
|
|
457
|
-
},
|
|
458
|
-
{
|
|
498
|
+
}, {
|
|
459
499
|
name: "code",
|
|
460
|
-
isActive:
|
|
461
|
-
command:
|
|
500
|
+
isActive: _temp9,
|
|
501
|
+
command: _temp0,
|
|
462
502
|
icon: CodeIcon
|
|
463
|
-
}
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
className: "gap-2 rounded-none h-full",
|
|
477
|
-
variant: "text",
|
|
478
|
-
children: /* @__PURE__ */ jsx(
|
|
479
|
-
item.icon,
|
|
480
|
-
{
|
|
481
|
-
className: cls({
|
|
482
|
-
"text-inherit": !item.isActive(editor),
|
|
483
|
-
"text-blue-500": item.isActive(editor)
|
|
484
|
-
})
|
|
485
|
-
}
|
|
486
|
-
)
|
|
487
|
-
}
|
|
488
|
-
)
|
|
489
|
-
},
|
|
490
|
-
index
|
|
491
|
-
)) });
|
|
503
|
+
}];
|
|
504
|
+
t0 = /* @__PURE__ */ jsx("div", { className: "flex", children: items2.map((item, index) => /* @__PURE__ */ jsx(EditorBubbleItem, { onSelect: (editor_10) => {
|
|
505
|
+
item.command(editor_10);
|
|
506
|
+
}, children: /* @__PURE__ */ jsx(Button, { size: "small", color: "text", className: "gap-2 rounded-none h-full", variant: "text", children: /* @__PURE__ */ jsx(item.icon, { className: cls({
|
|
507
|
+
"text-inherit": !item.isActive(editor),
|
|
508
|
+
"text-blue-500": item.isActive(editor)
|
|
509
|
+
}) }) }) }, index)) });
|
|
510
|
+
$[0] = editor;
|
|
511
|
+
$[1] = t0;
|
|
512
|
+
} else {
|
|
513
|
+
t0 = $[1];
|
|
514
|
+
}
|
|
515
|
+
return t0;
|
|
492
516
|
};
|
|
493
|
-
function
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
);
|
|
517
|
+
function _temp(editor_0) {
|
|
518
|
+
return editor_0?.isActive("bold") ?? false;
|
|
519
|
+
}
|
|
520
|
+
function _temp2(editor_1) {
|
|
521
|
+
return editor_1?.chain().focus().toggleBold().run();
|
|
522
|
+
}
|
|
523
|
+
function _temp3(editor_2) {
|
|
524
|
+
return editor_2?.isActive("italic") ?? false;
|
|
525
|
+
}
|
|
526
|
+
function _temp4(editor_3) {
|
|
527
|
+
return editor_3?.chain().focus().toggleItalic().run();
|
|
528
|
+
}
|
|
529
|
+
function _temp5(editor_4) {
|
|
530
|
+
return editor_4?.isActive("underline") ?? false;
|
|
531
|
+
}
|
|
532
|
+
function _temp6(editor_5) {
|
|
533
|
+
return editor_5?.chain().focus().toggleUnderline().run();
|
|
534
|
+
}
|
|
535
|
+
function _temp7(editor_6) {
|
|
536
|
+
return editor_6?.isActive("strike") ?? false;
|
|
537
|
+
}
|
|
538
|
+
function _temp8(editor_7) {
|
|
539
|
+
return editor_7?.chain().focus().toggleStrike().run();
|
|
540
|
+
}
|
|
541
|
+
function _temp9(editor_8) {
|
|
542
|
+
return editor_8?.isActive("code") ?? false;
|
|
543
|
+
}
|
|
544
|
+
function _temp0(editor_9) {
|
|
545
|
+
return editor_9?.chain().focus().toggleCode().run();
|
|
510
546
|
}
|
|
511
547
|
function removeClassesFromJson(jsonObj) {
|
|
512
548
|
if (Array.isArray(jsonObj)) {
|
|
@@ -521,12 +557,158 @@ function removeClassesFromJson(jsonObj) {
|
|
|
521
557
|
}
|
|
522
558
|
return jsonObj;
|
|
523
559
|
}
|
|
560
|
+
const loadingDecorationKey = new PluginKey("loadingDecoration");
|
|
561
|
+
const TextLoadingDecorationExtension = Extension.create({
|
|
562
|
+
name: "loadingDecoration",
|
|
563
|
+
addOptions() {
|
|
564
|
+
return {
|
|
565
|
+
pluginKey: loadingDecorationKey
|
|
566
|
+
};
|
|
567
|
+
},
|
|
568
|
+
addProseMirrorPlugins() {
|
|
569
|
+
const pluginKey = this.options.pluginKey;
|
|
570
|
+
return [new Plugin({
|
|
571
|
+
key: pluginKey,
|
|
572
|
+
state: {
|
|
573
|
+
init() {
|
|
574
|
+
return {
|
|
575
|
+
decorationSet: DecorationSet.empty,
|
|
576
|
+
hasDecoration: false
|
|
577
|
+
};
|
|
578
|
+
},
|
|
579
|
+
apply(tr, oldState) {
|
|
580
|
+
const action = tr.getMeta(pluginKey);
|
|
581
|
+
if (action?.type === "loadingDecoration") {
|
|
582
|
+
const {
|
|
583
|
+
pos,
|
|
584
|
+
remove,
|
|
585
|
+
loadingHtml
|
|
586
|
+
} = action;
|
|
587
|
+
if (remove) {
|
|
588
|
+
return {
|
|
589
|
+
decorationSet: DecorationSet.empty,
|
|
590
|
+
hasDecoration: false
|
|
591
|
+
};
|
|
592
|
+
}
|
|
593
|
+
const decoration = Decoration.widget(pos, () => {
|
|
594
|
+
const container = document.createElement("span");
|
|
595
|
+
container.className = "loading-decoration";
|
|
596
|
+
if (loadingHtml) {
|
|
597
|
+
container.innerHTML = loadingHtml;
|
|
598
|
+
} else {
|
|
599
|
+
const span = document.createElement("span");
|
|
600
|
+
span.innerText = "loading...";
|
|
601
|
+
container.appendChild(span);
|
|
602
|
+
}
|
|
603
|
+
return container;
|
|
604
|
+
});
|
|
605
|
+
return {
|
|
606
|
+
decorationSet: DecorationSet.empty.add(tr.doc, [decoration]),
|
|
607
|
+
hasDecoration: true
|
|
608
|
+
};
|
|
609
|
+
}
|
|
610
|
+
return {
|
|
611
|
+
decorationSet: oldState.decorationSet.map(tr.mapping, tr.doc),
|
|
612
|
+
hasDecoration: oldState.hasDecoration
|
|
613
|
+
};
|
|
614
|
+
}
|
|
615
|
+
},
|
|
616
|
+
props: {
|
|
617
|
+
decorations(state) {
|
|
618
|
+
return this.getState(state)?.decorationSet || DecorationSet.empty;
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
})];
|
|
622
|
+
},
|
|
623
|
+
addCommands() {
|
|
624
|
+
return {
|
|
625
|
+
toggleLoadingDecoration: (loadingHtml) => ({
|
|
626
|
+
state,
|
|
627
|
+
dispatch
|
|
628
|
+
}) => {
|
|
629
|
+
const {
|
|
630
|
+
selection
|
|
631
|
+
} = state;
|
|
632
|
+
const pos = selection.from;
|
|
633
|
+
if (!dispatch) return false;
|
|
634
|
+
const pluginKey = this.options.pluginKey;
|
|
635
|
+
const tr = state.tr.setMeta(pluginKey, {
|
|
636
|
+
pos,
|
|
637
|
+
type: "loadingDecoration",
|
|
638
|
+
remove: false,
|
|
639
|
+
loadingHtml
|
|
640
|
+
});
|
|
641
|
+
dispatch(tr);
|
|
642
|
+
return true;
|
|
643
|
+
},
|
|
644
|
+
removeLoadingDecoration: () => ({
|
|
645
|
+
state,
|
|
646
|
+
dispatch
|
|
647
|
+
}) => {
|
|
648
|
+
if (!dispatch) return false;
|
|
649
|
+
const pluginKey = this.options.pluginKey;
|
|
650
|
+
const tr = state.tr.setMeta(pluginKey, {
|
|
651
|
+
pos: 0,
|
|
652
|
+
// We can pass any position as it will remove the entire decoration set
|
|
653
|
+
type: "loadingDecoration",
|
|
654
|
+
remove: true
|
|
655
|
+
});
|
|
656
|
+
dispatch(tr);
|
|
657
|
+
return true;
|
|
658
|
+
}
|
|
659
|
+
};
|
|
660
|
+
}
|
|
661
|
+
});
|
|
662
|
+
const PlaceholderExtension = Placeholder.configure({
|
|
663
|
+
placeholder: ({
|
|
664
|
+
node,
|
|
665
|
+
editor
|
|
666
|
+
}) => {
|
|
667
|
+
const {
|
|
668
|
+
from,
|
|
669
|
+
to
|
|
670
|
+
} = editor.state.selection;
|
|
671
|
+
function hasLoadingDecoration(editor2) {
|
|
672
|
+
const pluginState = loadingDecorationKey.get(editor2.state);
|
|
673
|
+
return pluginState?.getState(editor2.state)?.hasDecoration ?? false;
|
|
674
|
+
}
|
|
675
|
+
const hasDecoration = hasLoadingDecoration(editor);
|
|
676
|
+
if (hasDecoration) {
|
|
677
|
+
return "";
|
|
678
|
+
}
|
|
679
|
+
if (node.type.name === "heading") {
|
|
680
|
+
return `Heading ${node.attrs.level}`;
|
|
681
|
+
}
|
|
682
|
+
if (node.type.name === "paragraph") {
|
|
683
|
+
return "Press '/' for commands";
|
|
684
|
+
}
|
|
685
|
+
return "";
|
|
686
|
+
},
|
|
687
|
+
includeChildren: true
|
|
688
|
+
});
|
|
689
|
+
const Horizontal = HorizontalRule.extend({
|
|
690
|
+
addInputRules() {
|
|
691
|
+
return [new InputRule({
|
|
692
|
+
find: /^(?:---|—-|___\s|\*\*\*\s)$/,
|
|
693
|
+
handler: ({
|
|
694
|
+
state,
|
|
695
|
+
range
|
|
696
|
+
}) => {
|
|
697
|
+
const attributes = {};
|
|
698
|
+
const {
|
|
699
|
+
tr
|
|
700
|
+
} = state;
|
|
701
|
+
const start = range.from;
|
|
702
|
+
const end = range.to;
|
|
703
|
+
tr.insert(start - 1, this.type.create(attributes)).delete(tr.mapping.map(start), tr.mapping.map(end));
|
|
704
|
+
}
|
|
705
|
+
})];
|
|
706
|
+
}
|
|
707
|
+
});
|
|
524
708
|
const placeholder = PlaceholderExtension;
|
|
525
709
|
const tiptapLink = TiptapLink.configure({
|
|
526
710
|
HTMLAttributes: {
|
|
527
|
-
class: cls(
|
|
528
|
-
"text-gray-600 dark:text-slate-300 underline underline-offset-[3px] hover:text-primary transition-colors cursor-pointer"
|
|
529
|
-
)
|
|
711
|
+
class: cls("text-surface-700 dark:text-surface-accent-200 underline underline-offset-[3px] hover:text-primary transition-colors cursor-pointer")
|
|
530
712
|
}
|
|
531
713
|
});
|
|
532
714
|
const taskList = TaskList.configure({
|
|
@@ -545,38 +727,39 @@ const horizontalRule = Horizontal.configure({
|
|
|
545
727
|
class: cls("mt-4 mb-6 border-t", defaultBorderMixin)
|
|
546
728
|
}
|
|
547
729
|
});
|
|
730
|
+
const bulletList = BulletList.configure({
|
|
731
|
+
HTMLAttributes: {
|
|
732
|
+
class: cls("list-disc list-outside leading-3 -mt-2")
|
|
733
|
+
}
|
|
734
|
+
});
|
|
735
|
+
const orderedList = OrderedList.configure({
|
|
736
|
+
HTMLAttributes: {
|
|
737
|
+
class: cls("list-decimal list-outside leading-3 -mt-2")
|
|
738
|
+
}
|
|
739
|
+
});
|
|
740
|
+
const listItem = ListItem.configure({
|
|
741
|
+
HTMLAttributes: {
|
|
742
|
+
class: cls("leading-normal -mb-2")
|
|
743
|
+
}
|
|
744
|
+
});
|
|
745
|
+
const blockquote = Blockquote.configure({
|
|
746
|
+
HTMLAttributes: {
|
|
747
|
+
class: cls("border-l-4 border-primary")
|
|
748
|
+
}
|
|
749
|
+
});
|
|
750
|
+
const codeBlock = CodeBlock.configure({
|
|
751
|
+
HTMLAttributes: {
|
|
752
|
+
class: cls("rounded bg-blue-50 dark:bg-surface-700 border p-5 font-mono font-medium", defaultBorderMixin)
|
|
753
|
+
}
|
|
754
|
+
});
|
|
755
|
+
const code = Code.configure({
|
|
756
|
+
HTMLAttributes: {
|
|
757
|
+
class: cls("rounded-md bg-surface-accent-50 dark:bg-surface-700 px-1.5 py-1 font-mono font-medium"),
|
|
758
|
+
spellcheck: "false"
|
|
759
|
+
}
|
|
760
|
+
});
|
|
548
761
|
const starterKit = StarterKit.configure({
|
|
549
|
-
|
|
550
|
-
HTMLAttributes: {
|
|
551
|
-
class: cls("list-disc list-outside leading-3 -mt-2")
|
|
552
|
-
}
|
|
553
|
-
},
|
|
554
|
-
orderedList: {
|
|
555
|
-
HTMLAttributes: {
|
|
556
|
-
class: cls("list-decimal list-outside leading-3 -mt-2")
|
|
557
|
-
}
|
|
558
|
-
},
|
|
559
|
-
listItem: {
|
|
560
|
-
HTMLAttributes: {
|
|
561
|
-
class: cls("leading-normal -mb-2")
|
|
562
|
-
}
|
|
563
|
-
},
|
|
564
|
-
blockquote: {
|
|
565
|
-
HTMLAttributes: {
|
|
566
|
-
class: cls("border-l-4 border-primary")
|
|
567
|
-
}
|
|
568
|
-
},
|
|
569
|
-
codeBlock: {
|
|
570
|
-
HTMLAttributes: {
|
|
571
|
-
class: cls("rounded bg-blue-50 dark:bg-gray-700 border p-5 font-mono font-medium", defaultBorderMixin)
|
|
572
|
-
}
|
|
573
|
-
},
|
|
574
|
-
code: {
|
|
575
|
-
HTMLAttributes: {
|
|
576
|
-
class: cls("rounded-md bg-slate-50 dark:bg-gray-700 px-1.5 py-1 font-mono font-medium"),
|
|
577
|
-
spellcheck: "false"
|
|
578
|
-
}
|
|
579
|
-
},
|
|
762
|
+
document: false,
|
|
580
763
|
horizontalRule: false,
|
|
581
764
|
dropcursor: {
|
|
582
765
|
color: "#DBEAFE",
|
|
@@ -584,27 +767,42 @@ const starterKit = StarterKit.configure({
|
|
|
584
767
|
},
|
|
585
768
|
gapcursor: false
|
|
586
769
|
});
|
|
587
|
-
async function onFileRead(
|
|
588
|
-
const {
|
|
770
|
+
async function onFileRead(view, readerEvent, pos, upload, image) {
|
|
771
|
+
const {
|
|
772
|
+
schema
|
|
773
|
+
} = view.state;
|
|
774
|
+
const plugin = view.state.plugins.find((p) => p.key === ImagePluginKey.key);
|
|
775
|
+
if (!plugin) {
|
|
776
|
+
console.error("Image plugin not found");
|
|
777
|
+
return;
|
|
778
|
+
}
|
|
589
779
|
let decorationSet = plugin.getState(view.state);
|
|
590
780
|
const placeholder2 = document.createElement("div");
|
|
591
781
|
const imageElement = document.createElement("img");
|
|
592
|
-
imageElement.setAttribute("class", "opacity-40 rounded-lg border
|
|
782
|
+
imageElement.setAttribute("class", "opacity-40 rounded-lg border " + defaultBorderMixin);
|
|
593
783
|
imageElement.src = readerEvent.target?.result;
|
|
594
784
|
placeholder2.appendChild(imageElement);
|
|
595
785
|
const deco = Decoration.widget(pos, placeholder2);
|
|
596
786
|
decorationSet = decorationSet?.add(view.state.doc, [deco]);
|
|
597
|
-
view.dispatch(view.state.tr.setMeta(plugin, {
|
|
787
|
+
view.dispatch(view.state.tr.setMeta(plugin, {
|
|
788
|
+
decorationSet
|
|
789
|
+
}));
|
|
598
790
|
const src = await upload(image);
|
|
599
|
-
console.
|
|
600
|
-
const imageNode = schema.nodes.image.create({
|
|
791
|
+
console.debug("Uploaded image", src);
|
|
792
|
+
const imageNode = schema.nodes.image.create({
|
|
793
|
+
src
|
|
794
|
+
});
|
|
601
795
|
const tr = view.state.tr.replaceWith(pos, pos, imageNode);
|
|
602
796
|
decorationSet = decorationSet?.remove([deco]);
|
|
603
|
-
tr.setMeta(plugin, {
|
|
797
|
+
tr.setMeta(plugin, {
|
|
798
|
+
decorationSet
|
|
799
|
+
});
|
|
604
800
|
view.dispatch(tr);
|
|
605
801
|
}
|
|
606
|
-
const
|
|
802
|
+
const ImagePluginKey = new PluginKey("imagePlugin");
|
|
803
|
+
const createDropImagePlugin = (upload) => {
|
|
607
804
|
const plugin = new Plugin({
|
|
805
|
+
key: ImagePluginKey,
|
|
608
806
|
state: {
|
|
609
807
|
// Initialize the plugin state with an empty DecorationSet
|
|
610
808
|
init: () => DecorationSet.empty,
|
|
@@ -620,20 +818,25 @@ const dropImagePlugin = (upload) => {
|
|
|
620
818
|
props: {
|
|
621
819
|
handleDOMEvents: {
|
|
622
820
|
drop: (view, event) => {
|
|
623
|
-
console.log("drop event", event);
|
|
624
821
|
if (!event.dataTransfer?.files || event.dataTransfer?.files.length === 0) {
|
|
625
822
|
return false;
|
|
626
823
|
}
|
|
627
824
|
event.preventDefault();
|
|
628
825
|
const files = Array.from(event.dataTransfer.files);
|
|
629
826
|
const images = files.filter((file) => /image/i.test(file.type));
|
|
630
|
-
if (images.length === 0)
|
|
827
|
+
if (images.length === 0) {
|
|
828
|
+
console.log("No images found in dropped files");
|
|
829
|
+
return false;
|
|
830
|
+
}
|
|
631
831
|
images.forEach((image) => {
|
|
632
|
-
const position = view.posAtCoords({
|
|
832
|
+
const position = view.posAtCoords({
|
|
833
|
+
left: event.clientX,
|
|
834
|
+
top: event.clientY
|
|
835
|
+
});
|
|
633
836
|
if (!position) return;
|
|
634
837
|
const reader = new FileReader();
|
|
635
838
|
reader.onload = async (readerEvent) => {
|
|
636
|
-
await onFileRead(
|
|
839
|
+
await onFileRead(view, readerEvent, position.pos, upload, image);
|
|
637
840
|
};
|
|
638
841
|
reader.readAsDataURL(image);
|
|
639
842
|
});
|
|
@@ -643,16 +846,14 @@ const dropImagePlugin = (upload) => {
|
|
|
643
846
|
handlePaste(view, event, slice) {
|
|
644
847
|
const items2 = Array.from(event.clipboardData?.items || []);
|
|
645
848
|
const pos = view.state.selection.from;
|
|
646
|
-
console.log("pos", pos);
|
|
647
849
|
let anyImageFound = false;
|
|
648
850
|
items2.forEach((item) => {
|
|
649
851
|
const image = item.getAsFile();
|
|
650
|
-
console.log("image", image);
|
|
651
852
|
if (image) {
|
|
652
853
|
anyImageFound = true;
|
|
653
854
|
const reader = new FileReader();
|
|
654
855
|
reader.onload = async (readerEvent) => {
|
|
655
|
-
await onFileRead(
|
|
856
|
+
await onFileRead(view, readerEvent, pos, upload, image);
|
|
656
857
|
};
|
|
657
858
|
reader.readAsDataURL(image);
|
|
658
859
|
}
|
|
@@ -677,10 +878,10 @@ const dropImagePlugin = (upload) => {
|
|
|
677
878
|
});
|
|
678
879
|
return plugin;
|
|
679
880
|
};
|
|
680
|
-
const createImageExtension = (
|
|
881
|
+
const createImageExtension = (dropImagePlugin) => {
|
|
681
882
|
return TiptapImage.extend({
|
|
682
883
|
addProseMirrorPlugins() {
|
|
683
|
-
return [dropImagePlugin
|
|
884
|
+
return [dropImagePlugin];
|
|
684
885
|
}
|
|
685
886
|
}).configure({
|
|
686
887
|
allowBase64: true,
|
|
@@ -693,9 +894,16 @@ const CustomKeymap = Extension.create({
|
|
|
693
894
|
name: "CustomKeymap",
|
|
694
895
|
addCommands() {
|
|
695
896
|
return {
|
|
696
|
-
selectTextWithinNodeBoundaries: () => ({
|
|
697
|
-
|
|
698
|
-
|
|
897
|
+
selectTextWithinNodeBoundaries: () => ({
|
|
898
|
+
editor,
|
|
899
|
+
commands
|
|
900
|
+
}) => {
|
|
901
|
+
const {
|
|
902
|
+
state
|
|
903
|
+
} = editor;
|
|
904
|
+
const {
|
|
905
|
+
tr
|
|
906
|
+
} = state;
|
|
699
907
|
const startNodePos = tr.selection.$from.start();
|
|
700
908
|
const endNodePos = tr.selection.$to.end();
|
|
701
909
|
return commands.setTextSelection({
|
|
@@ -707,9 +915,15 @@ const CustomKeymap = Extension.create({
|
|
|
707
915
|
},
|
|
708
916
|
addKeyboardShortcuts() {
|
|
709
917
|
return {
|
|
710
|
-
"Mod-a": ({
|
|
711
|
-
|
|
712
|
-
|
|
918
|
+
"Mod-a": ({
|
|
919
|
+
editor
|
|
920
|
+
}) => {
|
|
921
|
+
const {
|
|
922
|
+
state
|
|
923
|
+
} = editor;
|
|
924
|
+
const {
|
|
925
|
+
tr
|
|
926
|
+
} = state;
|
|
713
927
|
const startSelectionPos = tr.selection.from;
|
|
714
928
|
const endSelectionPos = tr.selection.to;
|
|
715
929
|
const startNodePos = tr.selection.$from.start();
|
|
@@ -724,20 +938,76 @@ const CustomKeymap = Extension.create({
|
|
|
724
938
|
};
|
|
725
939
|
}
|
|
726
940
|
});
|
|
727
|
-
function
|
|
728
|
-
|
|
941
|
+
function serializeForClipboard(view, slice) {
|
|
942
|
+
view.someProp("transformCopied", (f) => {
|
|
943
|
+
slice = f(slice, view);
|
|
944
|
+
});
|
|
945
|
+
const context = [];
|
|
946
|
+
let {
|
|
947
|
+
content,
|
|
948
|
+
openStart,
|
|
949
|
+
openEnd
|
|
950
|
+
} = slice;
|
|
951
|
+
while (openStart > 1 && openEnd > 1 && content.childCount == 1 && content.firstChild.childCount == 1) {
|
|
952
|
+
openStart--;
|
|
953
|
+
openEnd--;
|
|
954
|
+
const node = content.firstChild;
|
|
955
|
+
context.push(node.type.name, node.attrs != node.type.defaultAttrs ? node.attrs : null);
|
|
956
|
+
content = node.content;
|
|
957
|
+
}
|
|
958
|
+
const serializer = view.someProp("clipboardSerializer") || DOMSerializer.fromSchema(view.state.schema);
|
|
959
|
+
const doc = detachedDoc(), wrap = doc.createElement("div");
|
|
960
|
+
wrap.appendChild(serializer.serializeFragment(content, {
|
|
961
|
+
document: doc
|
|
962
|
+
}));
|
|
963
|
+
let firstChild = wrap.firstChild, needsWrap, wrappers = 0;
|
|
964
|
+
while (firstChild && firstChild.nodeType == 1 && (needsWrap = wrapMap[firstChild.nodeName.toLowerCase()])) {
|
|
965
|
+
for (let i = needsWrap.length - 1; i >= 0; i--) {
|
|
966
|
+
const wrapper = doc.createElement(needsWrap[i]);
|
|
967
|
+
while (wrap.firstChild) wrapper.appendChild(wrap.firstChild);
|
|
968
|
+
wrap.appendChild(wrapper);
|
|
969
|
+
wrappers++;
|
|
970
|
+
}
|
|
971
|
+
firstChild = wrap.firstChild;
|
|
972
|
+
}
|
|
973
|
+
if (firstChild && firstChild.nodeType == 1) firstChild.setAttribute("data-pm-slice", `${openStart} ${openEnd}${wrappers ? ` -${wrappers}` : ""} ${JSON.stringify(context)}`);
|
|
974
|
+
const text = view.someProp("clipboardTextSerializer", (f) => f(slice, view)) || slice.content.textBetween(0, slice.content.size, "\n\n");
|
|
729
975
|
return {
|
|
730
|
-
|
|
731
|
-
|
|
976
|
+
dom: wrap,
|
|
977
|
+
text,
|
|
978
|
+
slice
|
|
979
|
+
};
|
|
980
|
+
}
|
|
981
|
+
const wrapMap = {
|
|
982
|
+
thead: ["table"],
|
|
983
|
+
tbody: ["table"],
|
|
984
|
+
tfoot: ["table"],
|
|
985
|
+
caption: ["table"],
|
|
986
|
+
colgroup: ["table"],
|
|
987
|
+
col: ["table", "colgroup"],
|
|
988
|
+
tr: ["table", "tbody"],
|
|
989
|
+
td: ["table", "tbody", "tr"],
|
|
990
|
+
th: ["table", "tbody", "tr"]
|
|
991
|
+
};
|
|
992
|
+
let _detachedDoc = null;
|
|
993
|
+
function detachedDoc() {
|
|
994
|
+
return _detachedDoc || (_detachedDoc = document.implementation.createHTMLDocument("title"));
|
|
995
|
+
}
|
|
996
|
+
function absoluteRect(element) {
|
|
997
|
+
const data = element.getBoundingClientRect();
|
|
998
|
+
let ancestor = element.parentElement;
|
|
999
|
+
while (ancestor && window.getComputedStyle(ancestor).position === "static") {
|
|
1000
|
+
ancestor = ancestor.parentElement;
|
|
1001
|
+
}
|
|
1002
|
+
const ancestorRect = ancestor?.getBoundingClientRect();
|
|
1003
|
+
return {
|
|
1004
|
+
top: data.top - (ancestorRect?.top ?? 0),
|
|
1005
|
+
left: data.left - (ancestorRect?.left ?? 0),
|
|
732
1006
|
width: data.width
|
|
733
1007
|
};
|
|
734
1008
|
}
|
|
735
1009
|
function nodeDOMAtCoords(coords) {
|
|
736
|
-
return document.elementsFromPoint(coords.x, coords.y).find(
|
|
737
|
-
(elem) => elem.parentElement?.matches?.(".ProseMirror") || elem.matches(
|
|
738
|
-
["li", "p:not(:first-child)", "pre", "blockquote", "h1, h2, h3, h4, h5, h6"].join(", ")
|
|
739
|
-
)
|
|
740
|
-
);
|
|
1010
|
+
return document.elementsFromPoint(coords.x, coords.y).find((elem) => elem.parentElement?.matches?.(".ProseMirror") || elem.matches(["li", "p:not(:first-child)", "pre", "blockquote", "h1, h2, h3, h4, h5, h6"].join(", ")));
|
|
741
1011
|
}
|
|
742
1012
|
function nodePosAtDOM(node, view, options) {
|
|
743
1013
|
const boundingRect = node.getBoundingClientRect();
|
|
@@ -759,13 +1029,19 @@ function DragHandle(options) {
|
|
|
759
1029
|
if (nodePos == null || nodePos < 0) return;
|
|
760
1030
|
view.dispatch(view.state.tr.setSelection(NodeSelection.create(view.state.doc, nodePos)));
|
|
761
1031
|
const slice = view.state.selection.content();
|
|
762
|
-
const {
|
|
1032
|
+
const {
|
|
1033
|
+
dom,
|
|
1034
|
+
text
|
|
1035
|
+
} = serializeForClipboard(view, slice);
|
|
763
1036
|
event.dataTransfer.clearData();
|
|
764
1037
|
event.dataTransfer.setData("text/html", dom.innerHTML);
|
|
765
1038
|
event.dataTransfer.setData("text/plain", text);
|
|
766
1039
|
event.dataTransfer.effectAllowed = "copyMove";
|
|
767
1040
|
event.dataTransfer.setDragImage(node, 0, 0);
|
|
768
|
-
view.dragging = {
|
|
1041
|
+
view.dragging = {
|
|
1042
|
+
slice,
|
|
1043
|
+
move: event.ctrlKey
|
|
1044
|
+
};
|
|
769
1045
|
}
|
|
770
1046
|
function handleClick(event, view) {
|
|
771
1047
|
view.focus();
|
|
@@ -790,7 +1066,7 @@ function DragHandle(options) {
|
|
|
790
1066
|
dragHandleElement.classList.remove("hide");
|
|
791
1067
|
}
|
|
792
1068
|
}
|
|
793
|
-
return new Plugin
|
|
1069
|
+
return new Plugin({
|
|
794
1070
|
view: (view) => {
|
|
795
1071
|
dragHandleElement = document.createElement("div");
|
|
796
1072
|
dragHandleElement.draggable = true;
|
|
@@ -806,8 +1082,6 @@ function DragHandle(options) {
|
|
|
806
1082
|
view?.dom?.parentElement?.appendChild(dragHandleElement);
|
|
807
1083
|
return {
|
|
808
1084
|
destroy: () => {
|
|
809
|
-
dragHandleElement?.remove?.();
|
|
810
|
-
dragHandleElement = null;
|
|
811
1085
|
}
|
|
812
1086
|
};
|
|
813
1087
|
},
|
|
@@ -863,301 +1137,843 @@ function DragHandle(options) {
|
|
|
863
1137
|
const DragAndDrop = Extension.create({
|
|
864
1138
|
name: "dragAndDrop",
|
|
865
1139
|
addProseMirrorPlugins() {
|
|
866
|
-
return [
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
})
|
|
870
|
-
];
|
|
1140
|
+
return [DragHandle({
|
|
1141
|
+
dragHandleWidth: 24
|
|
1142
|
+
})];
|
|
871
1143
|
}
|
|
872
1144
|
});
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
}
|
|
880
|
-
const
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
1145
|
+
function buildDecorationSet(highlight, doc) {
|
|
1146
|
+
const decorations = [];
|
|
1147
|
+
if (highlight) {
|
|
1148
|
+
decorations.push(Decoration.inline(highlight.from, highlight.to, {
|
|
1149
|
+
class: "dark:bg-surface-accent-700 bg-surface-accent-300"
|
|
1150
|
+
}));
|
|
1151
|
+
}
|
|
1152
|
+
const decorationSet = DecorationSet.create(doc, decorations);
|
|
1153
|
+
return decorationSet;
|
|
1154
|
+
}
|
|
1155
|
+
const HighlightDecorationExtension = (initialHighlight) => Extension.create({
|
|
1156
|
+
name: "highlightDecoration",
|
|
1157
|
+
addOptions() {
|
|
1158
|
+
return {
|
|
1159
|
+
pluginKey: new PluginKey("highlightDecoration"),
|
|
1160
|
+
highlight: initialHighlight
|
|
1161
|
+
};
|
|
1162
|
+
},
|
|
1163
|
+
addProseMirrorPlugins() {
|
|
1164
|
+
const pluginKey = this.options.pluginKey;
|
|
1165
|
+
return [new Plugin({
|
|
1166
|
+
key: pluginKey,
|
|
1167
|
+
state: {
|
|
1168
|
+
init: (_, {
|
|
1169
|
+
doc
|
|
1170
|
+
}) => {
|
|
1171
|
+
const highlight = this.options.highlight;
|
|
1172
|
+
const decorationSet = highlight && doc ? buildDecorationSet(highlight, doc) : DecorationSet.empty;
|
|
1173
|
+
return {
|
|
1174
|
+
decorationSet,
|
|
1175
|
+
highlight
|
|
1176
|
+
};
|
|
1177
|
+
},
|
|
1178
|
+
apply(transaction, oldState) {
|
|
1179
|
+
const action = transaction.getMeta(pluginKey);
|
|
1180
|
+
const highlight = action?.range;
|
|
1181
|
+
if (action?.type === "highlightDecoration") {
|
|
1182
|
+
const doc = transaction.doc;
|
|
1183
|
+
const {
|
|
1184
|
+
remove
|
|
1185
|
+
} = action;
|
|
1186
|
+
if (remove) {
|
|
1187
|
+
return {
|
|
1188
|
+
decorationSet: DecorationSet.empty
|
|
1189
|
+
};
|
|
1190
|
+
}
|
|
1191
|
+
const decorationSet = buildDecorationSet(highlight, doc);
|
|
1192
|
+
return {
|
|
1193
|
+
decorationSet,
|
|
1194
|
+
highlight
|
|
1195
|
+
};
|
|
1196
|
+
} else {
|
|
1197
|
+
return oldState;
|
|
887
1198
|
}
|
|
888
1199
|
}
|
|
889
|
-
|
|
1200
|
+
},
|
|
1201
|
+
props: {
|
|
1202
|
+
decorations(state) {
|
|
1203
|
+
const autocompleteState = this.getState(state);
|
|
1204
|
+
if (autocompleteState?.decorationSet) {
|
|
1205
|
+
return autocompleteState.decorationSet;
|
|
1206
|
+
} else {
|
|
1207
|
+
return DecorationSet.empty;
|
|
1208
|
+
}
|
|
1209
|
+
}
|
|
1210
|
+
}
|
|
1211
|
+
})];
|
|
1212
|
+
},
|
|
1213
|
+
addCommands() {
|
|
1214
|
+
return {
|
|
1215
|
+
toggleAutocompleteHighlight: (range) => ({
|
|
1216
|
+
state,
|
|
1217
|
+
dispatch
|
|
1218
|
+
}) => {
|
|
1219
|
+
const {
|
|
1220
|
+
selection
|
|
1221
|
+
} = state;
|
|
1222
|
+
const pos = selection.from;
|
|
1223
|
+
if (!dispatch) return false;
|
|
1224
|
+
const pluginKey = this.options.pluginKey;
|
|
1225
|
+
const tr = state.tr.setMeta(pluginKey, {
|
|
1226
|
+
pos,
|
|
1227
|
+
type: "highlightDecoration",
|
|
1228
|
+
remove: false,
|
|
1229
|
+
range
|
|
1230
|
+
});
|
|
1231
|
+
dispatch(tr);
|
|
1232
|
+
return true;
|
|
1233
|
+
},
|
|
1234
|
+
removeAutocompleteHighlight: () => ({
|
|
1235
|
+
state,
|
|
1236
|
+
dispatch
|
|
1237
|
+
}) => {
|
|
1238
|
+
if (!dispatch) return false;
|
|
1239
|
+
const pluginKey = this.options.pluginKey;
|
|
1240
|
+
const tr = state.tr.setMeta(pluginKey, {
|
|
1241
|
+
pos: 0,
|
|
1242
|
+
// We can pass any position as it will remove the entire decoration set
|
|
1243
|
+
type: "highlightDecoration",
|
|
1244
|
+
remove: true
|
|
1245
|
+
});
|
|
1246
|
+
dispatch(tr);
|
|
1247
|
+
return true;
|
|
890
1248
|
}
|
|
1249
|
+
};
|
|
1250
|
+
}
|
|
1251
|
+
});
|
|
1252
|
+
const CommandPluginKey = new PluginKey("slash-command");
|
|
1253
|
+
const SlashCommand = Node.create({
|
|
1254
|
+
name: "command",
|
|
1255
|
+
addOptions() {
|
|
1256
|
+
return {
|
|
1257
|
+
HTMLAttributes: {},
|
|
1258
|
+
renderText({
|
|
1259
|
+
options,
|
|
1260
|
+
node
|
|
1261
|
+
}) {
|
|
1262
|
+
return `${options.suggestion.char}${node.attrs.label ?? node.attrs.id}`;
|
|
1263
|
+
},
|
|
1264
|
+
deleteTriggerWithBackspace: false,
|
|
1265
|
+
renderHTML({
|
|
1266
|
+
options,
|
|
1267
|
+
node
|
|
1268
|
+
}) {
|
|
1269
|
+
return ["span", mergeAttributes(this.HTMLAttributes, options.HTMLAttributes), `${options.suggestion.char}${node.attrs.label ?? node.attrs.id}`];
|
|
1270
|
+
},
|
|
1271
|
+
suggestion: {
|
|
1272
|
+
char: "/",
|
|
1273
|
+
pluginKey: CommandPluginKey,
|
|
1274
|
+
command: ({
|
|
1275
|
+
editor,
|
|
1276
|
+
range,
|
|
1277
|
+
props
|
|
1278
|
+
}) => {
|
|
1279
|
+
const nodeAfter = editor.view.state.selection.$to.nodeAfter;
|
|
1280
|
+
const overrideSpace = nodeAfter?.text?.startsWith(" ");
|
|
1281
|
+
if (overrideSpace) {
|
|
1282
|
+
range.to += 1;
|
|
1283
|
+
}
|
|
1284
|
+
editor.chain().focus().insertContentAt(range, [{
|
|
1285
|
+
type: this.name,
|
|
1286
|
+
attrs: props
|
|
1287
|
+
}, {
|
|
1288
|
+
type: "text",
|
|
1289
|
+
text: " "
|
|
1290
|
+
}]).run();
|
|
1291
|
+
window.getSelection()?.collapseToEnd();
|
|
1292
|
+
},
|
|
1293
|
+
allow: ({
|
|
1294
|
+
state,
|
|
1295
|
+
range
|
|
1296
|
+
}) => {
|
|
1297
|
+
const $from = state.doc.resolve(range.from);
|
|
1298
|
+
const type = state.schema.nodes[this.name];
|
|
1299
|
+
return !!$from.parent.type.contentMatch.matchType(type);
|
|
1300
|
+
}
|
|
1301
|
+
}
|
|
1302
|
+
};
|
|
1303
|
+
},
|
|
1304
|
+
group: "inline",
|
|
1305
|
+
inline: true,
|
|
1306
|
+
selectable: false,
|
|
1307
|
+
atom: true,
|
|
1308
|
+
addAttributes() {
|
|
1309
|
+
return {
|
|
1310
|
+
id: {
|
|
1311
|
+
default: null,
|
|
1312
|
+
parseHTML: (element) => element.getAttribute("data-id"),
|
|
1313
|
+
renderHTML: (attributes) => {
|
|
1314
|
+
if (!attributes.id) {
|
|
1315
|
+
return {};
|
|
1316
|
+
}
|
|
1317
|
+
return {
|
|
1318
|
+
"data-id": attributes.id
|
|
1319
|
+
};
|
|
1320
|
+
}
|
|
1321
|
+
},
|
|
1322
|
+
label: {
|
|
1323
|
+
default: null,
|
|
1324
|
+
parseHTML: (element) => element.getAttribute("data-label"),
|
|
1325
|
+
renderHTML: (attributes) => {
|
|
1326
|
+
if (!attributes.label) {
|
|
1327
|
+
return {};
|
|
1328
|
+
}
|
|
1329
|
+
return {
|
|
1330
|
+
"data-label": attributes.label
|
|
1331
|
+
};
|
|
1332
|
+
}
|
|
1333
|
+
}
|
|
1334
|
+
};
|
|
1335
|
+
},
|
|
1336
|
+
parseHTML() {
|
|
1337
|
+
return [{
|
|
1338
|
+
tag: `span[data-type="${this.name}"]`
|
|
1339
|
+
}];
|
|
1340
|
+
},
|
|
1341
|
+
renderHTML({
|
|
1342
|
+
node,
|
|
1343
|
+
HTMLAttributes
|
|
1344
|
+
}) {
|
|
1345
|
+
if (this.options.renderLabel !== void 0) {
|
|
1346
|
+
console.warn("renderLabel is deprecated use renderText and renderHTML instead");
|
|
1347
|
+
return ["span", mergeAttributes({
|
|
1348
|
+
"data-type": this.name
|
|
1349
|
+
}, this.options.HTMLAttributes, HTMLAttributes), this.options.renderLabel({
|
|
1350
|
+
options: this.options,
|
|
1351
|
+
node
|
|
1352
|
+
})];
|
|
891
1353
|
}
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
1354
|
+
const mergedOptions = {
|
|
1355
|
+
...this.options
|
|
1356
|
+
};
|
|
1357
|
+
mergedOptions.HTMLAttributes = mergeAttributes({
|
|
1358
|
+
"data-type": this.name
|
|
1359
|
+
}, this.options.HTMLAttributes, HTMLAttributes);
|
|
1360
|
+
const html = this.options.renderHTML({
|
|
1361
|
+
options: mergedOptions,
|
|
1362
|
+
node
|
|
1363
|
+
});
|
|
1364
|
+
if (typeof html === "string") {
|
|
1365
|
+
return ["span", mergeAttributes({
|
|
1366
|
+
"data-type": this.name
|
|
1367
|
+
}, this.options.HTMLAttributes, HTMLAttributes), html];
|
|
1368
|
+
}
|
|
1369
|
+
return html;
|
|
1370
|
+
},
|
|
1371
|
+
renderText({
|
|
1372
|
+
node
|
|
1373
|
+
}) {
|
|
1374
|
+
return this.options.renderText({
|
|
1375
|
+
options: this.options,
|
|
1376
|
+
node
|
|
1377
|
+
});
|
|
1378
|
+
},
|
|
1379
|
+
addKeyboardShortcuts() {
|
|
1380
|
+
return {
|
|
1381
|
+
Backspace: () => this.editor.commands.command(({
|
|
1382
|
+
tr,
|
|
1383
|
+
state
|
|
1384
|
+
}) => {
|
|
1385
|
+
let isCommand = false;
|
|
1386
|
+
const {
|
|
1387
|
+
selection
|
|
1388
|
+
} = state;
|
|
1389
|
+
const {
|
|
1390
|
+
empty,
|
|
1391
|
+
anchor
|
|
1392
|
+
} = selection;
|
|
1393
|
+
if (!empty) {
|
|
1394
|
+
return false;
|
|
1395
|
+
}
|
|
1396
|
+
state.doc.nodesBetween(anchor - 1, anchor, (node, pos) => {
|
|
1397
|
+
if (node.type.name === this.name) {
|
|
1398
|
+
isCommand = true;
|
|
1399
|
+
tr.insertText(this.options.deleteTriggerWithBackspace ? "" : this.options.suggestion.char || "", pos, pos + node.nodeSize);
|
|
1400
|
+
return false;
|
|
1401
|
+
}
|
|
1402
|
+
return true;
|
|
1403
|
+
});
|
|
1404
|
+
return isCommand;
|
|
1405
|
+
})
|
|
1406
|
+
};
|
|
1407
|
+
},
|
|
1408
|
+
addProseMirrorPlugins() {
|
|
1409
|
+
return [Suggestion({
|
|
1410
|
+
editor: this.editor,
|
|
1411
|
+
...this.options.suggestion
|
|
1412
|
+
})];
|
|
1413
|
+
}
|
|
1414
|
+
});
|
|
1415
|
+
const suggestion = (ref, {
|
|
1416
|
+
upload,
|
|
1417
|
+
aiController
|
|
1418
|
+
}) => ({
|
|
1419
|
+
items: ({
|
|
1420
|
+
query
|
|
1421
|
+
}) => {
|
|
1422
|
+
const availableSuggestionItems = [...suggestionItems];
|
|
1423
|
+
if (aiController) {
|
|
1424
|
+
availableSuggestionItems.push(autocompleteSuggestionItem);
|
|
1425
|
+
}
|
|
1426
|
+
return availableSuggestionItems.filter((item) => {
|
|
1427
|
+
const inTitle = item.title.toLowerCase().startsWith(query.toLowerCase());
|
|
1428
|
+
if (inTitle) return inTitle;
|
|
1429
|
+
return item.searchTerms?.some((term) => term.toLowerCase().startsWith(query.toLowerCase()));
|
|
1430
|
+
});
|
|
1431
|
+
},
|
|
1432
|
+
render: () => {
|
|
1433
|
+
let component;
|
|
1434
|
+
let containerEl = null;
|
|
1435
|
+
let cleanupAutoUpdate = null;
|
|
1436
|
+
let reference = null;
|
|
1437
|
+
return {
|
|
1438
|
+
onStart: (props) => {
|
|
1439
|
+
component = new ReactRenderer(CommandList, {
|
|
1440
|
+
props: {
|
|
1441
|
+
...props,
|
|
1442
|
+
upload,
|
|
1443
|
+
aiController
|
|
1444
|
+
},
|
|
1445
|
+
editor: props.editor
|
|
1446
|
+
});
|
|
1447
|
+
if (!props.clientRect) {
|
|
1448
|
+
return;
|
|
1449
|
+
}
|
|
1450
|
+
containerEl = document.createElement("div");
|
|
1451
|
+
containerEl.style.position = "fixed";
|
|
1452
|
+
containerEl.style.left = "0px";
|
|
1453
|
+
containerEl.style.top = "0px";
|
|
1454
|
+
containerEl.style.zIndex = "9999";
|
|
1455
|
+
(ref?.current || document.body).appendChild(containerEl);
|
|
1456
|
+
containerEl.appendChild(component.element);
|
|
1457
|
+
reference = {
|
|
1458
|
+
getBoundingClientRect: props.clientRect
|
|
1459
|
+
};
|
|
1460
|
+
cleanupAutoUpdate = autoUpdate(reference, containerEl, () => {
|
|
1461
|
+
if (!reference) return;
|
|
1462
|
+
computePosition(reference, containerEl, {
|
|
1463
|
+
placement: "bottom-start",
|
|
1464
|
+
middleware: [offset(4), flip(), shift()],
|
|
1465
|
+
strategy: "fixed"
|
|
1466
|
+
}).then(({
|
|
1467
|
+
x,
|
|
1468
|
+
y
|
|
1469
|
+
}) => {
|
|
1470
|
+
Object.assign(containerEl.style, {
|
|
1471
|
+
left: `${x}px`,
|
|
1472
|
+
top: `${y}px`,
|
|
1473
|
+
visibility: "visible"
|
|
1474
|
+
});
|
|
1475
|
+
});
|
|
1476
|
+
});
|
|
1477
|
+
},
|
|
1478
|
+
onUpdate(props) {
|
|
1479
|
+
component.updateProps(props);
|
|
1480
|
+
if (!props.clientRect || !containerEl || !reference) {
|
|
1481
|
+
return;
|
|
1482
|
+
}
|
|
1483
|
+
reference.getBoundingClientRect = props.clientRect;
|
|
1484
|
+
computePosition(reference, containerEl, {
|
|
1485
|
+
placement: "bottom-start",
|
|
1486
|
+
middleware: [offset(4), flip(), shift()],
|
|
1487
|
+
strategy: "fixed"
|
|
1488
|
+
}).then(({
|
|
1489
|
+
x,
|
|
1490
|
+
y
|
|
1491
|
+
}) => {
|
|
1492
|
+
Object.assign(containerEl.style, {
|
|
1493
|
+
left: `${x}px`,
|
|
1494
|
+
top: `${y}px`,
|
|
1495
|
+
visibility: "visible"
|
|
1496
|
+
});
|
|
1497
|
+
});
|
|
1498
|
+
},
|
|
1499
|
+
onKeyDown(props) {
|
|
1500
|
+
if (props.event.key === "Escape") {
|
|
1501
|
+
props.event.preventDefault();
|
|
1502
|
+
return true;
|
|
1503
|
+
}
|
|
1504
|
+
return component.ref?.onKeyDown(props);
|
|
1505
|
+
},
|
|
1506
|
+
onExit() {
|
|
1507
|
+
if (cleanupAutoUpdate) cleanupAutoUpdate();
|
|
1508
|
+
if (containerEl && containerEl.parentNode) {
|
|
1509
|
+
containerEl.parentNode.removeChild(containerEl);
|
|
1510
|
+
}
|
|
1511
|
+
containerEl = null;
|
|
1512
|
+
reference = null;
|
|
1513
|
+
component?.destroy();
|
|
933
1514
|
}
|
|
934
|
-
}
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
1515
|
+
};
|
|
1516
|
+
}
|
|
1517
|
+
});
|
|
1518
|
+
const CommandList = forwardRef((props, ref) => {
|
|
1519
|
+
const $ = c(33);
|
|
1520
|
+
const [selectedIndex, setSelectedIndex] = useState(0);
|
|
1521
|
+
const {
|
|
1522
|
+
editor
|
|
1523
|
+
} = useCurrentEditor();
|
|
1524
|
+
let t0;
|
|
1525
|
+
if ($[0] !== editor || $[1] !== props.aiController || $[2] !== props.range || $[3] !== props.upload) {
|
|
1526
|
+
t0 = (item) => {
|
|
1527
|
+
if (!editor) {
|
|
1528
|
+
return;
|
|
942
1529
|
}
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
1530
|
+
item?.command?.({
|
|
1531
|
+
editor,
|
|
1532
|
+
range: props.range,
|
|
1533
|
+
upload: props.upload,
|
|
1534
|
+
aiController: props.aiController
|
|
1535
|
+
});
|
|
1536
|
+
};
|
|
1537
|
+
$[0] = editor;
|
|
1538
|
+
$[1] = props.aiController;
|
|
1539
|
+
$[2] = props.range;
|
|
1540
|
+
$[3] = props.upload;
|
|
1541
|
+
$[4] = t0;
|
|
1542
|
+
} else {
|
|
1543
|
+
t0 = $[4];
|
|
1544
|
+
}
|
|
1545
|
+
const selectItem = t0;
|
|
1546
|
+
let t1;
|
|
1547
|
+
if ($[5] !== props.items.length || $[6] !== selectedIndex) {
|
|
1548
|
+
t1 = () => {
|
|
1549
|
+
setSelectedIndex((selectedIndex + props.items.length - 1) % props.items.length);
|
|
1550
|
+
};
|
|
1551
|
+
$[5] = props.items.length;
|
|
1552
|
+
$[6] = selectedIndex;
|
|
1553
|
+
$[7] = t1;
|
|
1554
|
+
} else {
|
|
1555
|
+
t1 = $[7];
|
|
1556
|
+
}
|
|
1557
|
+
const upHandler = t1;
|
|
1558
|
+
let t2;
|
|
1559
|
+
if ($[8] !== props.items.length || $[9] !== selectedIndex) {
|
|
1560
|
+
t2 = () => {
|
|
1561
|
+
setSelectedIndex((selectedIndex + 1) % props.items.length);
|
|
1562
|
+
};
|
|
1563
|
+
$[8] = props.items.length;
|
|
1564
|
+
$[9] = selectedIndex;
|
|
1565
|
+
$[10] = t2;
|
|
1566
|
+
} else {
|
|
1567
|
+
t2 = $[10];
|
|
1568
|
+
}
|
|
1569
|
+
const downHandler = t2;
|
|
1570
|
+
let t3;
|
|
1571
|
+
if ($[11] !== props.items || $[12] !== selectItem || $[13] !== selectedIndex) {
|
|
1572
|
+
t3 = () => {
|
|
1573
|
+
const item_0 = props.items[selectedIndex];
|
|
1574
|
+
selectItem(item_0);
|
|
1575
|
+
};
|
|
1576
|
+
$[11] = props.items;
|
|
1577
|
+
$[12] = selectItem;
|
|
1578
|
+
$[13] = selectedIndex;
|
|
1579
|
+
$[14] = t3;
|
|
1580
|
+
} else {
|
|
1581
|
+
t3 = $[14];
|
|
1582
|
+
}
|
|
1583
|
+
const enterHandler = t3;
|
|
1584
|
+
let t4;
|
|
1585
|
+
if ($[15] === Symbol.for("react.memo_cache_sentinel")) {
|
|
1586
|
+
t4 = () => setSelectedIndex(0);
|
|
1587
|
+
$[15] = t4;
|
|
1588
|
+
} else {
|
|
1589
|
+
t4 = $[15];
|
|
1590
|
+
}
|
|
1591
|
+
let t5;
|
|
1592
|
+
if ($[16] !== props.items) {
|
|
1593
|
+
t5 = [props.items];
|
|
1594
|
+
$[16] = props.items;
|
|
1595
|
+
$[17] = t5;
|
|
1596
|
+
} else {
|
|
1597
|
+
t5 = $[17];
|
|
1598
|
+
}
|
|
1599
|
+
useEffect(t4, t5);
|
|
1600
|
+
let t6;
|
|
1601
|
+
if ($[18] !== downHandler || $[19] !== enterHandler || $[20] !== upHandler) {
|
|
1602
|
+
t6 = () => ({
|
|
1603
|
+
onKeyDown: (t72) => {
|
|
1604
|
+
const {
|
|
1605
|
+
event
|
|
1606
|
+
} = t72;
|
|
1607
|
+
if (event.key === "ArrowUp") {
|
|
1608
|
+
upHandler();
|
|
1609
|
+
return true;
|
|
1610
|
+
}
|
|
1611
|
+
if (event.key === "ArrowDown") {
|
|
1612
|
+
downHandler();
|
|
1613
|
+
return true;
|
|
1614
|
+
}
|
|
1615
|
+
if (event.key === "Enter") {
|
|
1616
|
+
enterHandler();
|
|
1617
|
+
return true;
|
|
1618
|
+
}
|
|
1619
|
+
return false;
|
|
951
1620
|
}
|
|
952
|
-
}
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
1621
|
+
});
|
|
1622
|
+
$[18] = downHandler;
|
|
1623
|
+
$[19] = enterHandler;
|
|
1624
|
+
$[20] = upHandler;
|
|
1625
|
+
$[21] = t6;
|
|
1626
|
+
} else {
|
|
1627
|
+
t6 = $[21];
|
|
1628
|
+
}
|
|
1629
|
+
useImperativeHandle(ref, t6);
|
|
1630
|
+
let t7;
|
|
1631
|
+
if ($[22] === Symbol.for("react.memo_cache_sentinel")) {
|
|
1632
|
+
t7 = [];
|
|
1633
|
+
$[22] = t7;
|
|
1634
|
+
} else {
|
|
1635
|
+
t7 = $[22];
|
|
1636
|
+
}
|
|
1637
|
+
const itemRefs = useRef(t7);
|
|
1638
|
+
let t8;
|
|
1639
|
+
let t9;
|
|
1640
|
+
if ($[23] !== selectedIndex) {
|
|
1641
|
+
t8 = () => {
|
|
1642
|
+
if (itemRefs.current[selectedIndex]) {
|
|
1643
|
+
itemRefs.current[selectedIndex].scrollIntoView({
|
|
1644
|
+
block: "nearest"
|
|
1645
|
+
});
|
|
960
1646
|
}
|
|
961
|
-
}
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
1647
|
+
};
|
|
1648
|
+
t9 = [selectedIndex];
|
|
1649
|
+
$[23] = selectedIndex;
|
|
1650
|
+
$[24] = t8;
|
|
1651
|
+
$[25] = t9;
|
|
1652
|
+
} else {
|
|
1653
|
+
t8 = $[24];
|
|
1654
|
+
t9 = $[25];
|
|
1655
|
+
}
|
|
1656
|
+
useEffect(t8, t9);
|
|
1657
|
+
let t10;
|
|
1658
|
+
if ($[26] === Symbol.for("react.memo_cache_sentinel")) {
|
|
1659
|
+
t10 = cls("text-surface-900 dark:text-white z-50 max-h-[280px] h-auto w-72 overflow-y-auto rounded-md border bg-white dark:bg-surface-900 px-1 py-2 shadow transition-all", defaultBorderMixin);
|
|
1660
|
+
$[26] = t10;
|
|
1661
|
+
} else {
|
|
1662
|
+
t10 = $[26];
|
|
1663
|
+
}
|
|
1664
|
+
let t11;
|
|
1665
|
+
if ($[27] !== props.items || $[28] !== selectItem || $[29] !== selectedIndex) {
|
|
1666
|
+
t11 = props.items.length ? props.items.map((item_1, index) => /* @__PURE__ */ jsxs("button", { value: item_1.title, ref: (el) => {
|
|
1667
|
+
if (!el) {
|
|
1668
|
+
return;
|
|
969
1669
|
}
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
1670
|
+
itemRefs.current[index] = el;
|
|
1671
|
+
}, onClick: () => selectItem(item_1), tabIndex: index === selectedIndex ? 0 : -1, "aria-selected": index === selectedIndex, className: cls("flex w-full items-center space-x-2 rounded-md px-2 py-1 text-left text-sm hover:bg-blue-50 hover:dark:bg-surface-700 aria-selected:bg-blue-50 aria-selected:dark:bg-surface-700", index === selectedIndex ? "bg-blue-100 dark:bg-surface-accent-950" : ""), children: [
|
|
1672
|
+
/* @__PURE__ */ jsx("div", { className: cls("flex h-10 w-10 items-center justify-center rounded-md border bg-white dark:bg-surface-900", defaultBorderMixin), children: item_1.icon }),
|
|
1673
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
1674
|
+
/* @__PURE__ */ jsx("p", { className: "font-medium", children: item_1.title }),
|
|
1675
|
+
/* @__PURE__ */ jsx("p", { className: "text-xs text-surface-700 dark:text-surface-accent-300", children: item_1.description })
|
|
1676
|
+
] })
|
|
1677
|
+
] }, item_1.title)) : /* @__PURE__ */ jsx("div", { className: "item", children: "No result" });
|
|
1678
|
+
$[27] = props.items;
|
|
1679
|
+
$[28] = selectItem;
|
|
1680
|
+
$[29] = selectedIndex;
|
|
1681
|
+
$[30] = t11;
|
|
1682
|
+
} else {
|
|
1683
|
+
t11 = $[30];
|
|
1684
|
+
}
|
|
1685
|
+
let t12;
|
|
1686
|
+
if ($[31] !== t11) {
|
|
1687
|
+
t12 = /* @__PURE__ */ jsx("div", { className: t10, children: t11 });
|
|
1688
|
+
$[31] = t11;
|
|
1689
|
+
$[32] = t12;
|
|
1690
|
+
} else {
|
|
1691
|
+
t12 = $[32];
|
|
1692
|
+
}
|
|
1693
|
+
return t12;
|
|
1694
|
+
});
|
|
1695
|
+
CommandList.displayName = "CommandList";
|
|
1696
|
+
const autocompleteSuggestionItem = {
|
|
1697
|
+
title: "Autocomplete",
|
|
1698
|
+
description: "Add text based on the context.",
|
|
1699
|
+
searchTerms: ["ai"],
|
|
1700
|
+
icon: /* @__PURE__ */ jsx(AutoFixHighIcon, { size: 18 }),
|
|
1701
|
+
command: async ({
|
|
1702
|
+
editor,
|
|
1703
|
+
range,
|
|
1704
|
+
aiController
|
|
1705
|
+
}) => {
|
|
1706
|
+
if (!aiController) throw Error("No AiController");
|
|
1707
|
+
editor.chain().focus().deleteRange(range).toggleNode("paragraph", "paragraph").run();
|
|
1708
|
+
const {
|
|
1709
|
+
state
|
|
1710
|
+
} = editor;
|
|
1711
|
+
const {
|
|
1712
|
+
from,
|
|
1713
|
+
to
|
|
1714
|
+
} = state.selection;
|
|
1715
|
+
const textBeforeCursor = state.doc.textBetween(0, from, "\n");
|
|
1716
|
+
const textAfterCursor = state.doc.textBetween(to, state.doc.content.size, "\n");
|
|
1717
|
+
let buffer = "";
|
|
1718
|
+
const result = await aiController.autocomplete(textBeforeCursor, textAfterCursor, (delta) => {
|
|
1719
|
+
buffer += delta;
|
|
1720
|
+
if (delta.length !== 0) {
|
|
1721
|
+
editor.chain().focus().toggleLoadingDecoration(buffer).run();
|
|
978
1722
|
}
|
|
979
|
-
}
|
|
980
|
-
{
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
command: ({ editor, range }) => {
|
|
986
|
-
editor.chain().focus().deleteRange(range).toggleOrderedList().run();
|
|
1723
|
+
});
|
|
1724
|
+
editor.chain().focus().insertContent(result, {
|
|
1725
|
+
applyInputRules: false,
|
|
1726
|
+
applyPasteRules: false,
|
|
1727
|
+
parseOptions: {
|
|
1728
|
+
preserveWhitespace: false
|
|
987
1729
|
}
|
|
988
|
-
}
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1730
|
+
}).run();
|
|
1731
|
+
}
|
|
1732
|
+
};
|
|
1733
|
+
const suggestionItems = [{
|
|
1734
|
+
title: "Text",
|
|
1735
|
+
description: "Just start typing with plain text.",
|
|
1736
|
+
searchTerms: ["p", "paragraph"],
|
|
1737
|
+
icon: /* @__PURE__ */ jsx(TextFieldsIcon, { size: 18 }),
|
|
1738
|
+
command: ({
|
|
1739
|
+
editor,
|
|
1740
|
+
range
|
|
1741
|
+
}) => {
|
|
1742
|
+
editor.chain().focus().deleteRange(range).toggleNode("paragraph", "paragraph").run();
|
|
1743
|
+
}
|
|
1744
|
+
}, {
|
|
1745
|
+
title: "To-do List",
|
|
1746
|
+
description: "Track tasks with a to-do list.",
|
|
1747
|
+
searchTerms: ["todo", "task", "list", "check", "checkbox"],
|
|
1748
|
+
icon: /* @__PURE__ */ jsx(CheckBoxIcon, { size: 18 }),
|
|
1749
|
+
command: ({
|
|
1750
|
+
editor,
|
|
1751
|
+
range
|
|
1752
|
+
}) => {
|
|
1753
|
+
editor.chain().focus().deleteRange(range).toggleTaskList().run();
|
|
1754
|
+
}
|
|
1755
|
+
}, {
|
|
1756
|
+
title: "Heading 1",
|
|
1757
|
+
description: "Big section heading.",
|
|
1758
|
+
searchTerms: ["title", "big", "large"],
|
|
1759
|
+
icon: /* @__PURE__ */ jsx(LooksOneIcon, { size: 18 }),
|
|
1760
|
+
command: ({
|
|
1761
|
+
editor,
|
|
1762
|
+
range
|
|
1763
|
+
}) => {
|
|
1764
|
+
editor.chain().focus().deleteRange(range).setNode("heading", {
|
|
1765
|
+
level: 1
|
|
1766
|
+
}).run();
|
|
1767
|
+
}
|
|
1768
|
+
}, {
|
|
1769
|
+
title: "Heading 2",
|
|
1770
|
+
description: "Medium section heading.",
|
|
1771
|
+
searchTerms: ["subtitle", "medium"],
|
|
1772
|
+
icon: /* @__PURE__ */ jsx(LooksTwoIcon, { size: 18 }),
|
|
1773
|
+
command: ({
|
|
1774
|
+
editor,
|
|
1775
|
+
range
|
|
1776
|
+
}) => {
|
|
1777
|
+
editor.chain().focus().deleteRange(range).setNode("heading", {
|
|
1778
|
+
level: 2
|
|
1779
|
+
}).run();
|
|
1780
|
+
}
|
|
1781
|
+
}, {
|
|
1782
|
+
title: "Heading 3",
|
|
1783
|
+
description: "Small section heading.",
|
|
1784
|
+
searchTerms: ["subtitle", "small"],
|
|
1785
|
+
icon: /* @__PURE__ */ jsx(Looks3Icon, { size: 18 }),
|
|
1786
|
+
command: ({
|
|
1787
|
+
editor,
|
|
1788
|
+
range
|
|
1789
|
+
}) => {
|
|
1790
|
+
editor.chain().focus().deleteRange(range).setNode("heading", {
|
|
1791
|
+
level: 3
|
|
1792
|
+
}).run();
|
|
1793
|
+
}
|
|
1794
|
+
}, {
|
|
1795
|
+
title: "Bullet List",
|
|
1796
|
+
description: "Create a simple bullet list.",
|
|
1797
|
+
searchTerms: ["unordered", "point"],
|
|
1798
|
+
icon: /* @__PURE__ */ jsx(FormatListBulletedIcon, { size: 18 }),
|
|
1799
|
+
command: ({
|
|
1800
|
+
editor,
|
|
1801
|
+
range
|
|
1802
|
+
}) => {
|
|
1803
|
+
editor.chain().focus().deleteRange(range).toggleBulletList().run();
|
|
1804
|
+
}
|
|
1805
|
+
}, {
|
|
1806
|
+
title: "Numbered List",
|
|
1807
|
+
description: "Create a list with numbering.",
|
|
1808
|
+
searchTerms: ["ordered"],
|
|
1809
|
+
icon: /* @__PURE__ */ jsx(FormatListNumberedIcon, { size: 18 }),
|
|
1810
|
+
command: ({
|
|
1811
|
+
editor,
|
|
1812
|
+
range
|
|
1813
|
+
}) => {
|
|
1814
|
+
editor.chain().focus().deleteRange(range).toggleOrderedList().run();
|
|
1815
|
+
}
|
|
1816
|
+
}, {
|
|
1817
|
+
title: "Quote",
|
|
1818
|
+
description: "Capture a quote.",
|
|
1819
|
+
searchTerms: ["blockquote"],
|
|
1820
|
+
icon: /* @__PURE__ */ jsx(FormatQuoteIcon, { size: 18 }),
|
|
1821
|
+
command: ({
|
|
1822
|
+
editor,
|
|
1823
|
+
range
|
|
1824
|
+
}) => editor.chain().focus().deleteRange(range).toggleNode("paragraph", "paragraph").toggleBlockquote().run()
|
|
1825
|
+
}, {
|
|
1826
|
+
title: "Code",
|
|
1827
|
+
description: "Capture a code snippet.",
|
|
1828
|
+
searchTerms: ["codeblock"],
|
|
1829
|
+
icon: /* @__PURE__ */ jsx(CodeIcon, { size: 18 }),
|
|
1830
|
+
command: ({
|
|
1831
|
+
editor,
|
|
1832
|
+
range
|
|
1833
|
+
}) => editor.chain().focus().deleteRange(range).toggleCodeBlock().run()
|
|
1834
|
+
}, {
|
|
1835
|
+
title: "Image",
|
|
1836
|
+
description: "Upload an image from your computer.",
|
|
1837
|
+
searchTerms: ["photo", "picture", "media", "upload", "file"],
|
|
1838
|
+
icon: /* @__PURE__ */ jsx(ImageIcon, { size: 18 }),
|
|
1839
|
+
command: ({
|
|
1840
|
+
editor,
|
|
1841
|
+
range,
|
|
1842
|
+
upload
|
|
1843
|
+
}) => {
|
|
1844
|
+
editor.chain().focus().deleteRange(range).run();
|
|
1845
|
+
const input = document.createElement("input");
|
|
1846
|
+
input.type = "file";
|
|
1847
|
+
input.accept = "image/*";
|
|
1848
|
+
input.onchange = async () => {
|
|
1849
|
+
if (input.files?.length) {
|
|
1850
|
+
const file = input.files[0];
|
|
1851
|
+
if (!file) return;
|
|
1852
|
+
const pos = editor.view.state.selection.from;
|
|
1853
|
+
const fileList = input.files;
|
|
1854
|
+
const files = Array.from(fileList);
|
|
1855
|
+
const images = files.filter((file2) => /image/i.test(file2.type));
|
|
1856
|
+
if (images.length === 0) {
|
|
1857
|
+
console.log("No images found in uploaded files");
|
|
1858
|
+
return false;
|
|
1859
|
+
}
|
|
1860
|
+
const view = editor.view;
|
|
1861
|
+
images.forEach((image) => {
|
|
1862
|
+
const reader = new FileReader();
|
|
1863
|
+
reader.onload = async (readerEvent) => {
|
|
1864
|
+
await onFileRead(view, readerEvent, pos, upload, image);
|
|
1865
|
+
};
|
|
1866
|
+
reader.readAsDataURL(image);
|
|
1867
|
+
});
|
|
1021
1868
|
}
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
// updatedImage,
|
|
1050
|
-
taskList,
|
|
1051
|
-
taskItem,
|
|
1052
|
-
horizontalRule,
|
|
1053
|
-
slashCommand
|
|
1054
|
-
];
|
|
1869
|
+
return true;
|
|
1870
|
+
};
|
|
1871
|
+
input.click();
|
|
1872
|
+
}
|
|
1873
|
+
}];
|
|
1874
|
+
const proseClasses = {
|
|
1875
|
+
"sm": "prose-sm",
|
|
1876
|
+
"base": "prose-base",
|
|
1877
|
+
"lg": "prose-lg"
|
|
1878
|
+
};
|
|
1879
|
+
const canUseDOM = Boolean(typeof window !== "undefined" && window.document && window.document.createElement);
|
|
1880
|
+
const FireCMSEditor = ({
|
|
1881
|
+
content,
|
|
1882
|
+
onJsonContentChange,
|
|
1883
|
+
onHtmlContentChange,
|
|
1884
|
+
onMarkdownContentChange,
|
|
1885
|
+
version,
|
|
1886
|
+
textSize = "base",
|
|
1887
|
+
highlight,
|
|
1888
|
+
handleImageUpload,
|
|
1889
|
+
aiController,
|
|
1890
|
+
disabled
|
|
1891
|
+
}) => {
|
|
1892
|
+
const ref = React.useRef(null);
|
|
1893
|
+
const editorRef = React.useRef(null);
|
|
1894
|
+
const imagePlugin = createDropImagePlugin(handleImageUpload);
|
|
1895
|
+
const imageExtension = useMemo(() => createImageExtension(imagePlugin), []);
|
|
1055
1896
|
const [openNode, setOpenNode] = useState(false);
|
|
1056
1897
|
const [openLink, setOpenLink] = useState(false);
|
|
1057
1898
|
useInjectStyles("Editor", cssStyles);
|
|
1058
|
-
const
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1899
|
+
const deferredHighlight = useDeferredValue(highlight);
|
|
1900
|
+
useEffect(() => {
|
|
1901
|
+
if (version === void 0) return;
|
|
1902
|
+
if (version > -1 && editorRef.current) {
|
|
1903
|
+
editorRef.current?.commands.setContent(content ?? "");
|
|
1904
|
+
}
|
|
1905
|
+
}, [version]);
|
|
1906
|
+
useEffect(() => {
|
|
1907
|
+
editorRef?.current?.setEditable(!disabled);
|
|
1908
|
+
}, [disabled]);
|
|
1909
|
+
useEffect(() => {
|
|
1910
|
+
if (version === void 0) return;
|
|
1911
|
+
if (editorRef.current && version > 0) {
|
|
1912
|
+
const chain = editorRef.current.chain();
|
|
1913
|
+
if (deferredHighlight) {
|
|
1914
|
+
chain.focus().toggleAutocompleteHighlight(deferredHighlight).run();
|
|
1915
|
+
} else {
|
|
1916
|
+
chain.focus().removeAutocompleteHighlight().run();
|
|
1917
|
+
}
|
|
1918
|
+
}
|
|
1919
|
+
}, [deferredHighlight?.from, deferredHighlight?.to]);
|
|
1920
|
+
const firstUpdateRef = React.useRef(true);
|
|
1062
1921
|
const onEditorUpdate = (editor) => {
|
|
1063
1922
|
editorRef.current = editor;
|
|
1923
|
+
if (firstUpdateRef.current) {
|
|
1924
|
+
firstUpdateRef.current = false;
|
|
1925
|
+
return;
|
|
1926
|
+
}
|
|
1064
1927
|
if (onMarkdownContentChange) {
|
|
1065
|
-
|
|
1928
|
+
const markdown = editorRef.current.storage.markdown.getMarkdown();
|
|
1929
|
+
onMarkdownContentChange?.(addLineBreakAfterImages(markdown));
|
|
1066
1930
|
}
|
|
1067
1931
|
if (onJsonContentChange) {
|
|
1068
|
-
|
|
1932
|
+
const jsonContent = removeClassesFromJson(editor.getJSON());
|
|
1933
|
+
onJsonContentChange(jsonContent);
|
|
1069
1934
|
}
|
|
1070
1935
|
if (onHtmlContentChange) {
|
|
1071
|
-
|
|
1936
|
+
onHtmlContentChange?.(editor.getHTML());
|
|
1072
1937
|
}
|
|
1073
1938
|
};
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
},
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
},
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
className: "relative min-h-[500px] w-full bg-white dark:bg-gray-950 rounded-lg",
|
|
1093
|
-
children: /* @__PURE__ */ jsxs(
|
|
1094
|
-
EditorProvider,
|
|
1095
|
-
{
|
|
1096
|
-
content: initialContent,
|
|
1097
|
-
extensions,
|
|
1098
|
-
editorProps: {
|
|
1099
|
-
...defaultEditorProps,
|
|
1100
|
-
attributes: {
|
|
1101
|
-
class: "prose-lg prose-headings:font-title font-default focus:outline-none max-w-full p-12"
|
|
1102
|
-
}
|
|
1103
|
-
},
|
|
1104
|
-
onUpdate: ({ editor }) => {
|
|
1105
|
-
console.debug("Editor updated");
|
|
1106
|
-
onEditorUpdate(editor);
|
|
1107
|
-
},
|
|
1108
|
-
children: [
|
|
1109
|
-
/* @__PURE__ */ jsxs(
|
|
1110
|
-
EditorCommand,
|
|
1111
|
-
{
|
|
1112
|
-
className: cls("text-gray-900 dark:text-white z-50 h-auto max-h-[330px] w-72 overflow-y-auto rounded-md border bg-white dark:bg-gray-900 px-1 py-2 shadow transition-all", defaultBorderMixin),
|
|
1113
|
-
children: [
|
|
1114
|
-
/* @__PURE__ */ jsx(EditorCommandEmpty, { className: "px-2 text-gray-700 dark:text-slate-300", children: "No results" }),
|
|
1115
|
-
suggestionItems.map((item) => /* @__PURE__ */ jsxs(
|
|
1116
|
-
EditorCommandItem,
|
|
1117
|
-
{
|
|
1118
|
-
value: item.title,
|
|
1119
|
-
onCommand: (val) => item?.command?.(val),
|
|
1120
|
-
className: "flex w-full items-center space-x-2 rounded-md px-2 py-1 text-left text-sm hover:bg-blue-50 hover:dark:bg-gray-700 aria-selected:bg-blue-50 aria-selected:dark:bg-gray-700",
|
|
1121
|
-
children: [
|
|
1122
|
-
/* @__PURE__ */ jsx(
|
|
1123
|
-
"div",
|
|
1124
|
-
{
|
|
1125
|
-
className: cls("flex h-10 w-10 items-center justify-center rounded-md border bg-white dark:bg-gray-900", defaultBorderMixin),
|
|
1126
|
-
children: item.icon
|
|
1127
|
-
}
|
|
1128
|
-
),
|
|
1129
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
1130
|
-
/* @__PURE__ */ jsx("p", { className: "font-medium", children: item.title }),
|
|
1131
|
-
/* @__PURE__ */ jsx("p", { className: "text-xs text-gray-700 dark:text-slate-300", children: item.description })
|
|
1132
|
-
] })
|
|
1133
|
-
]
|
|
1134
|
-
},
|
|
1135
|
-
item.title
|
|
1136
|
-
))
|
|
1137
|
-
]
|
|
1138
|
-
}
|
|
1139
|
-
),
|
|
1140
|
-
/* @__PURE__ */ jsxs(
|
|
1141
|
-
EditorBubble,
|
|
1142
|
-
{
|
|
1143
|
-
tippyOptions: {
|
|
1144
|
-
placement: "top"
|
|
1145
|
-
},
|
|
1146
|
-
className: cls("flex w-fit max-w-[90vw] h-10 overflow-hidden rounded border bg-white dark:bg-gray-900 shadow", defaultBorderMixin),
|
|
1147
|
-
children: [
|
|
1148
|
-
/* @__PURE__ */ jsx(NodeSelector, { open: openNode, onOpenChange: setOpenNode }),
|
|
1149
|
-
/* @__PURE__ */ jsx(Separator, { orientation: "vertical" }),
|
|
1150
|
-
/* @__PURE__ */ jsx(LinkSelector, { open: openLink, onOpenChange: setOpenLink }),
|
|
1151
|
-
/* @__PURE__ */ jsx(Separator, { orientation: "vertical" }),
|
|
1152
|
-
/* @__PURE__ */ jsx(TextButtons, {})
|
|
1153
|
-
]
|
|
1154
|
-
}
|
|
1155
|
-
)
|
|
1156
|
-
]
|
|
1157
|
-
}
|
|
1158
|
-
)
|
|
1939
|
+
const proseClass = proseClasses[textSize];
|
|
1940
|
+
const extensions = useMemo(() => [starterKit, Document.extend({}), HighlightDecorationExtension(highlight), TextLoadingDecorationExtension, Underline, Bold, TextStyleKit, Italic, Strike, Color, Highlight.configure({
|
|
1941
|
+
multicolor: true
|
|
1942
|
+
}), Heading, CustomKeymap, DragAndDrop, placeholder, tiptapLink, imageExtension, taskList, taskItem, Markdown.configure({
|
|
1943
|
+
html: true
|
|
1944
|
+
}), horizontalRule, bulletList, orderedList, listItem, blockquote, codeBlock, code, SlashCommand.configure({
|
|
1945
|
+
HTMLAttributes: {
|
|
1946
|
+
class: "mention"
|
|
1947
|
+
},
|
|
1948
|
+
suggestion: suggestion(ref, {
|
|
1949
|
+
upload: handleImageUpload,
|
|
1950
|
+
aiController
|
|
1951
|
+
})
|
|
1952
|
+
})], []);
|
|
1953
|
+
return /* @__PURE__ */ jsx("div", { ref, className: "relative min-h-[300px] w-full", children: /* @__PURE__ */ jsx(EditorProvider, { content: content ?? "", extensions, immediatelyRender: canUseDOM, editorProps: {
|
|
1954
|
+
editable: () => !disabled,
|
|
1955
|
+
attributes: {
|
|
1956
|
+
class: cls(proseClass, "prose-headings:font-title font-default focus:outline-none max-w-full p-12")
|
|
1159
1957
|
}
|
|
1160
|
-
|
|
1958
|
+
}, onCreate: ({
|
|
1959
|
+
editor: editor_0
|
|
1960
|
+
}) => {
|
|
1961
|
+
editorRef.current = editor_0;
|
|
1962
|
+
editor_0.setEditable(!disabled);
|
|
1963
|
+
}, onUpdate: ({
|
|
1964
|
+
editor: editor_1
|
|
1965
|
+
}) => {
|
|
1966
|
+
onEditorUpdate(editor_1);
|
|
1967
|
+
}, children: /* @__PURE__ */ jsxs(EditorBubble, { options: {
|
|
1968
|
+
placement: "top",
|
|
1969
|
+
offset: 6
|
|
1970
|
+
}, className: cls("flex w-fit max-w-[90vw] h-10 overflow-hidden rounded border bg-white dark:bg-surface-900 shadow", defaultBorderMixin), children: [
|
|
1971
|
+
/* @__PURE__ */ jsx(NodeSelector, { portalContainer: ref.current, open: openNode, onOpenChange: setOpenNode }),
|
|
1972
|
+
/* @__PURE__ */ jsx(Separator, { orientation: "vertical" }),
|
|
1973
|
+
/* @__PURE__ */ jsx(LinkSelector, { open: openLink, onOpenChange: setOpenLink }),
|
|
1974
|
+
/* @__PURE__ */ jsx(Separator, { orientation: "vertical" }),
|
|
1975
|
+
/* @__PURE__ */ jsx(TextButtons, {})
|
|
1976
|
+
] }) }) });
|
|
1161
1977
|
};
|
|
1162
1978
|
function addLineBreakAfterImages(markdown) {
|
|
1163
1979
|
const imageRegex = /!\[.*?\]\(.*?\)/g;
|
|
@@ -1165,7 +1981,9 @@ function addLineBreakAfterImages(markdown) {
|
|
|
1165
1981
|
`);
|
|
1166
1982
|
}
|
|
1167
1983
|
const cssStyles = `
|
|
1168
|
-
|
|
1984
|
+
.ProseMirror {
|
|
1985
|
+
box-shadow: none !important;
|
|
1986
|
+
}
|
|
1169
1987
|
.ProseMirror .is-editor-empty:first-child::before {
|
|
1170
1988
|
content: attr(data-placeholder);
|
|
1171
1989
|
float: left;
|
|
@@ -1188,6 +2006,7 @@ const cssStyles = `
|
|
|
1188
2006
|
}
|
|
1189
2007
|
|
|
1190
2008
|
.is-empty {
|
|
2009
|
+
cursor: text;
|
|
1191
2010
|
color: rgb(100 116 139); //500
|
|
1192
2011
|
}
|
|
1193
2012
|
|
|
@@ -1205,6 +2024,7 @@ const cssStyles = `
|
|
|
1205
2024
|
&.ProseMirror-selectednode {
|
|
1206
2025
|
outline: 3px solid #5abbf7;
|
|
1207
2026
|
filter: brightness(90%);
|
|
2027
|
+
box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000) !important;
|
|
1208
2028
|
}
|
|
1209
2029
|
}
|
|
1210
2030
|
|
|
@@ -1232,7 +2052,7 @@ ul[data-type="taskList"] li > label {
|
|
|
1232
2052
|
}
|
|
1233
2053
|
|
|
1234
2054
|
&:active {
|
|
1235
|
-
background-color: rgb(71 85 105)
|
|
2055
|
+
background-color: rgb(71 85 105);
|
|
1236
2056
|
}
|
|
1237
2057
|
}
|
|
1238
2058
|
}
|
|
@@ -1299,7 +2119,7 @@ ul[data-type="taskList"] li[data-checked="true"] > div > p {
|
|
|
1299
2119
|
}
|
|
1300
2120
|
|
|
1301
2121
|
.ProseMirror:not(.dragging) .ProseMirror-selectednode {
|
|
1302
|
-
outline: none !important;
|
|
2122
|
+
// outline: none !important;
|
|
1303
2123
|
background-color: rgb(219 234 254); // blue 100
|
|
1304
2124
|
transition: background-color 0.2s;
|
|
1305
2125
|
box-shadow: none;
|
|
@@ -1309,19 +2129,23 @@ ul[data-type="taskList"] li[data-checked="true"] > div > p {
|
|
|
1309
2129
|
background-color: rgb(51 65 85); // 700
|
|
1310
2130
|
}
|
|
1311
2131
|
|
|
2132
|
+
.prose-base table p {
|
|
2133
|
+
margin: 0;
|
|
2134
|
+
}
|
|
2135
|
+
|
|
1312
2136
|
.drag-handle {
|
|
1313
|
-
position:
|
|
2137
|
+
position: absolute;
|
|
1314
2138
|
opacity: 1;
|
|
1315
2139
|
transition: opacity ease-in 0.2s;
|
|
1316
2140
|
border-radius: 0.25rem;
|
|
1317
2141
|
|
|
1318
|
-
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 10' style='fill: rgba(128, 128, 128, 0.9)'%3E%3Cpath d='M3,2 C2.44771525,2 2,1.55228475 2,1 C2,0.44771525 2.44771525,0 3,0 C3.55228475,0 4,0.44771525 4,1 C4,1.55228475 3.55228475,2 3,2 Z M3,6 C2.44771525,6 2,5.55228475 2,5 C2,4.44771525 2.44771525,4 3,4 C3.55228475,4 4,4.44771525 4,5 C4,5.55228475 3.55228475,6 3,6 Z M3,10 C2.44771525,10 2,9.55228475 2,9 C2,8.44771525 2.44771525,8 3,8 C3.55228475,8 4,8.44771525 4,9 C4,9.55228475 3.55228475,10 3,10 Z M7,2 C6.44771525,2 6,1.55228475 6,1 C6,0.44771525 6.44771525,0 7,0 C7.55228475,0 8,0.44771525 8,1 C8,1.55228475 7.55228475,2 7,2 Z M7,6 C6.44771525,6 6,5.55228475 6,5 C6,4.44771525 6.44771525,4 7,4 C7.55228475,4 8,4.44771525 8,5 C8,5.55228475 7.55228475,6 7,6 Z M7,10 C6.44771525,10 6,9.55228475 6,9 C6,8.44771525 6.44771525,8 7,8 C7
|
|
2142
|
+
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 10' style='fill: rgba(128, 128, 128, 0.9)'%3E%3Cpath d='M3,2 C2.44771525,2 2,1.55228475 2,1 C2,0.44771525 2.44771525,0 3,0 C3.55228475,0 4,0.44771525 4,1 C4,1.55228475 3.55228475,2 3,2 Z M3,6 C2.44771525,6 2,5.55228475 2,5 C2,4.44771525 2.44771525,4 3,4 C3.55228475,4 4,4.44771525 4,5 C4,5.55228475 3.55228475,6 3,6 Z M3,10 C2.44771525,10 2,9.55228475 2,9 C2,8.44771525 2.44771525,8 3,8 C3.55228475,8 4,8.44771525 4,9 C4,9.55228475 3.55228475,10 3,10 Z M7,2 C6.44771525,2 6,1.55228475 6,1 C6,0.44771525 6.44771525,0 7,0 C7.55228475,0 8,0.44771525 8,1 C8,1.55228475 7.55228475,2 7,2 Z M7,6 C6.44771525,6 6,5.55228475 6,5 C6,4.44771525 6.44771525,4 7,4 C7.55228475,4 8,4.44771525 8,5 C8,5.55228475 7.55228475,6 7,6 Z M7,10 C6.44771525,10 6,9.55228475 6,9 C6,8.44771525 6.44771525,8 7,8 C7,8.44771525 7,9 7,9 C7,9.55228475 7,10 7,10 Z'%3E%3C/path%3E%3C/svg%3E");
|
|
1319
2143
|
background-size: calc(0.5em + 0.375rem) calc(0.5em + 0.375rem);
|
|
1320
2144
|
background-repeat: no-repeat;
|
|
1321
2145
|
background-position: center;
|
|
1322
2146
|
width: 1.2rem;
|
|
1323
2147
|
height: 1.5rem;
|
|
1324
|
-
z-index:
|
|
2148
|
+
z-index: 100;
|
|
1325
2149
|
cursor: grab;
|
|
1326
2150
|
|
|
1327
2151
|
&:hover {
|