@firecms/editor 3.0.0-canary.23 → 3.0.0-canary.231

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