@firecms/editor 3.0.0-canary.80 → 3.0.0-canary.82

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,340 +1,407 @@
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, cls 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;
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import React, { forwardRef, useRef, useEffect, useMemo, useState } from "react";
3
+ import TiptapUnderline from "@tiptap/extension-underline";
4
+ import TextStyle from "@tiptap/extension-text-style";
5
+ import { Color } from "@tiptap/extension-color";
6
+ import { Markdown } from "tiptap-markdown";
7
+ import Highlight from "@tiptap/extension-highlight";
8
+ import { useCurrentEditor, BubbleMenu, isNodeSelection, ReactRenderer, EditorProvider } from "@tiptap/react";
9
+ import { createStore, Provider, atom, useAtom, useSetAtom, useAtomValue } from "jotai";
10
+ import { Slot } from "@radix-ui/react-slot";
11
+ import tunnel from "tunnel-rat";
12
+ import { Command as Command$1, CommandItem, CommandEmpty } from "cmdk";
13
+ import StarterKit from "@tiptap/starter-kit";
14
+ import HorizontalRule from "@tiptap/extension-horizontal-rule";
15
+ import TiptapLink from "@tiptap/extension-link";
16
+ import TiptapImage from "@tiptap/extension-image";
17
+ import Placeholder from "@tiptap/extension-placeholder";
18
+ import { TaskItem } from "@tiptap/extension-task-item";
19
+ import { TaskList } from "@tiptap/extension-task-list";
20
+ import { Extension, InputRule } from "@tiptap/core";
21
+ import Suggestion from "@tiptap/suggestion";
22
+ import tippy from "tippy.js";
23
+ import { Popover, Button, ExpandMoreIcon, CheckIcon, TextFieldsIcon, LooksOneIcon, LooksTwoIcon, Looks3Icon, CheckBoxIcon, FormatListBulletedIcon, FormatListNumberedIcon, FormatQuoteIcon, CodeIcon, cls, DeleteIcon, FormatBoldIcon, FormatItalicIcon, FormatUnderlinedIcon, FormatStrikethroughIcon, defaultBorderMixin, useInjectStyles, Separator, ImageIcon } from "@firecms/ui";
24
+ import { Plugin } from "prosemirror-state";
25
+ import { DecorationSet, Decoration, __serializeForClipboard } from "@tiptap/pm/view";
26
+ import { Plugin as Plugin$1, NodeSelection } from "@tiptap/pm/state";
27
+ const editorStore = createStore();
28
+ const EditorRoot = ({ children }) => {
29
+ return /* @__PURE__ */ jsx(Provider, { store: editorStore, children });
30
+ };
31
+ const EditorBubble = forwardRef(
32
+ ({ children, tippyOptions, ...rest }, ref) => {
33
+ const { editor } = useCurrentEditor();
34
+ const instanceRef = useRef(null);
35
+ useEffect(() => {
36
+ if (!instanceRef.current || !tippyOptions?.placement) return;
37
+ instanceRef.current.setProps({ placement: tippyOptions.placement });
38
+ instanceRef.current.popperInstance?.update();
39
+ }, [tippyOptions?.placement]);
40
+ const bubbleMenuProps = useMemo(() => {
41
+ const shouldShow = ({ editor: editor2, state }) => {
42
+ const { selection } = state;
43
+ const { empty } = selection;
44
+ if (editor2.isActive("image") || empty || isNodeSelection(selection)) {
45
+ return false;
46
+ }
47
+ return true;
48
+ };
49
+ return {
50
+ shouldShow,
51
+ tippyOptions: {
52
+ onCreate: (val) => {
53
+ instanceRef.current = val;
54
+ },
55
+ moveTransition: "transform 0.15s ease-out",
56
+ ...tippyOptions
41
57
  },
42
- moveTransition: "transform 0.15s ease-out",
43
- ...o
44
- },
45
- ...t
46
- }), [t, o]);
47
- return a ? (
58
+ ...rest
59
+ };
60
+ }, [rest, tippyOptions]);
61
+ if (!editor) return null;
62
+ return (
48
63
  //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;
64
+ /* @__PURE__ */ jsx("div", { ref, children: /* @__PURE__ */ jsx(BubbleMenu, { editor, ...bubbleMenuProps, children }) })
65
+ );
51
66
  }
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;
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 });
55
73
  });
56
- F.displayName = "EditorBubbleItem";
57
- const re = Te(), ne = _(""), ae = _(null), et = ({
58
- query: e,
59
- range: o
74
+ EditorBubbleItem.displayName = "EditorBubbleItem";
75
+ const t = tunnel();
76
+ const queryAtom = atom("");
77
+ const rangeAtom = atom(null);
78
+ const EditorCommandOut = ({
79
+ query,
80
+ range
60
81
  }) => {
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
- );
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
+ );
74
100
  }
75
101
  };
76
- return document.addEventListener("keydown", c), () => {
77
- document.removeEventListener("keydown", c);
102
+ document.addEventListener("keydown", onKeyDown);
103
+ return () => {
104
+ document.removeEventListener("keydown", onKeyDown);
78
105
  };
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,
106
+ }, []);
107
+ return /* @__PURE__ */ jsx(t.Out, {});
108
+ };
109
+ const EditorCommand = forwardRef(
110
+ ({ children, className, ...rest }, ref) => {
111
+ const commandListRef = useRef(null);
112
+ const [query, setQuery] = useAtom(queryAtom);
113
+ return /* @__PURE__ */ jsx(t.In, { children: /* @__PURE__ */ jsxs(
114
+ Command$1,
85
115
  {
86
- ref: r,
87
- onKeyDown: (i) => {
88
- i.stopPropagation();
116
+ ref,
117
+ onKeyDown: (e) => {
118
+ e.stopPropagation();
89
119
  },
90
120
  id: "slash-command",
91
- className: o,
92
- ...t,
121
+ className,
122
+ ...rest,
93
123
  children: [
94
- /* @__PURE__ */ s(S.Input, { value: c, onValueChange: n, style: { display: "none" } }),
95
- /* @__PURE__ */ s(S.List, { ref: a, children: e })
124
+ /* @__PURE__ */ jsx(Command$1.Input, { value: query, onValueChange: setQuery, style: { display: "none" } }),
125
+ /* @__PURE__ */ jsx(Command$1.List, { ref: commandListRef, children })
96
126
  ]
97
127
  }
98
128
  ) });
99
129
  }
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 });
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 });
103
136
  });
104
- se.displayName = "EditorCommandItem";
105
- const ot = Me, rt = B.create({
137
+ EditorCommandItem.displayName = "EditorCommandItem";
138
+ const EditorCommandEmpty = CommandEmpty;
139
+ const Command = Extension.create({
106
140
  name: "slash-command",
107
141
  addOptions() {
108
142
  return {
109
143
  suggestion: {
110
144
  char: "/",
111
- command: ({ editor: e, range: o, props: t }) => {
112
- t.command({ editor: e, range: o });
145
+ command: ({ editor, range, props }) => {
146
+ props.command({ editor, range });
113
147
  }
114
148
  }
115
149
  };
116
150
  },
117
151
  addProseMirrorPlugins() {
118
152
  return [
119
- ze({
153
+ Suggestion({
120
154
  editor: this.editor,
121
155
  ...this.options.suggestion
122
156
  })
123
157
  ];
124
158
  }
125
- }), nt = () => {
126
- let e = null, o = null;
159
+ });
160
+ const renderItems = () => {
161
+ let component = null;
162
+ let popup = null;
127
163
  return {
128
- onStart: (t) => {
129
- e = new xe(et, {
130
- props: t,
131
- editor: t.editor
132
- }), o = Fe("body", {
133
- getReferenceClientRect: t.clientRect,
164
+ onStart: (props) => {
165
+ component = new ReactRenderer(EditorCommandOut, {
166
+ props,
167
+ editor: props.editor
168
+ });
169
+ popup = tippy("body", {
170
+ getReferenceClientRect: props.clientRect,
134
171
  appendTo: () => document.body,
135
- content: e.element,
136
- showOnCreate: !0,
137
- interactive: !0,
172
+ content: component.element,
173
+ showOnCreate: true,
174
+ interactive: true,
138
175
  trigger: "manual",
139
176
  placement: "bottom-start"
140
177
  });
141
178
  },
142
- onUpdate: (t) => {
143
- e?.updateProps(t), o && o[0].setProps({
144
- getReferenceClientRect: t.clientRect
179
+ onUpdate: (props) => {
180
+ component?.updateProps(props);
181
+ popup && popup[0].setProps({
182
+ getReferenceClientRect: props.clientRect
145
183
  });
146
184
  },
147
- onKeyDown: (t) => t.event.key === "Escape" ? (o?.[0].hide(), !0) : e?.ref?.onKeyDown(t),
185
+ onKeyDown: (props) => {
186
+ if (props.event.key === "Escape") {
187
+ popup?.[0].hide();
188
+ return true;
189
+ }
190
+ return component?.ref?.onKeyDown(props);
191
+ },
148
192
  onExit: () => {
149
- o?.[0].destroy(), e?.destroy();
193
+ popup?.[0].destroy();
194
+ component?.destroy();
150
195
  }
151
196
  };
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({
197
+ };
198
+ const createSuggestionItems = (items2) => items2;
199
+ const PlaceholderExtension = Placeholder.configure({
200
+ placeholder: ({ node }) => {
201
+ if (node.type.name === "heading") {
202
+ return `Heading ${node.attrs.level}`;
203
+ }
204
+ return "Press '/' for commands";
205
+ },
206
+ includeChildren: true
207
+ });
208
+ const Horizontal = HorizontalRule.extend({
156
209
  addInputRules() {
157
210
  return [
158
- new Be({
211
+ new InputRule({
159
212
  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)
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)
165
221
  );
166
222
  }
167
223
  })
168
224
  ];
169
225
  }
170
- }), q = [
226
+ });
227
+ const items = [
171
228
  {
172
229
  name: "Text",
173
- icon: X,
174
- command: (e) => e?.chain().focus().toggleNode("paragraph", "paragraph").run(),
230
+ icon: TextFieldsIcon,
231
+ command: (editor) => editor?.chain().focus().toggleNode("paragraph", "paragraph").run(),
175
232
  // 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
233
+ isActive: (editor) => (editor?.isActive("paragraph") && !editor?.isActive("bulletList") && !editor?.isActive("orderedList")) ?? false
177
234
  },
178
235
  {
179
236
  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
237
+ icon: LooksOneIcon,
238
+ command: (editor) => editor?.chain().focus().toggleHeading({ level: 1 }).run(),
239
+ isActive: (editor) => editor?.isActive("heading", { level: 1 }) ?? false
183
240
  },
184
241
  {
185
242
  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
243
+ icon: LooksTwoIcon,
244
+ command: (editor) => editor?.chain().focus().toggleHeading({ level: 2 }).run(),
245
+ isActive: (editor) => editor?.isActive("heading", { level: 2 }) ?? false
189
246
  },
190
247
  {
191
248
  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
249
+ icon: Looks3Icon,
250
+ command: (editor) => editor?.chain().focus().toggleHeading({ level: 3 }).run(),
251
+ isActive: (editor) => editor?.isActive("heading", { level: 3 }) ?? false
195
252
  },
196
253
  {
197
254
  name: "To-do List",
198
- icon: j,
199
- command: (e) => e?.chain().focus().toggleTaskList().run(),
200
- isActive: (e) => e?.isActive("taskItem") ?? !1
255
+ icon: CheckBoxIcon,
256
+ command: (editor) => editor?.chain().focus().toggleTaskList().run(),
257
+ isActive: (editor) => editor?.isActive("taskItem") ?? false
201
258
  },
202
259
  {
203
260
  name: "Bullet List",
204
- icon: ee,
205
- command: (e) => e?.chain().focus().toggleBulletList().run(),
206
- isActive: (e) => e?.isActive("bulletList") ?? !1
261
+ icon: FormatListBulletedIcon,
262
+ command: (editor) => editor?.chain().focus().toggleBulletList().run(),
263
+ isActive: (editor) => editor?.isActive("bulletList") ?? false
207
264
  },
208
265
  {
209
266
  name: "Numbered List",
210
- icon: te,
211
- command: (e) => e?.chain().focus().toggleOrderedList().run(),
212
- isActive: (e) => e?.isActive("orderedList") ?? !1
267
+ icon: FormatListNumberedIcon,
268
+ command: (editor) => editor?.chain().focus().toggleOrderedList().run(),
269
+ isActive: (editor) => editor?.isActive("orderedList") ?? false
213
270
  },
214
271
  {
215
272
  name: "Quote",
216
- icon: oe,
217
- command: (e) => e?.chain().focus().toggleNode("paragraph", "paragraph").toggleBlockquote().run(),
218
- isActive: (e) => e?.isActive("blockquote") ?? !1
273
+ icon: FormatQuoteIcon,
274
+ command: (editor) => editor?.chain().focus().toggleNode("paragraph", "paragraph").toggleBlockquote().run(),
275
+ isActive: (editor) => editor?.isActive("blockquote") ?? false
219
276
  },
220
277
  {
221
278
  name: "Code",
222
- icon: z,
223
- command: (e) => e?.chain().focus().toggleCodeBlock().run(),
224
- isActive: (e) => e?.isActive("codeBlock") ?? !1
279
+ icon: CodeIcon,
280
+ command: (editor) => editor?.chain().focus().toggleCodeBlock().run(),
281
+ isActive: (editor) => editor?.isActive("codeBlock") ?? false
225
282
  }
226
- ], ct = ({
227
- open: e,
228
- onOpenChange: o
283
+ ];
284
+ const NodeSelector = ({
285
+ open,
286
+ onOpenChange
229
287
  }) => {
230
- const { editor: t } = y();
231
- if (!t) return null;
232
- const r = q.filter((a) => a.isActive(t)).pop() ?? {
288
+ const { editor } = useCurrentEditor();
289
+ if (!editor) return null;
290
+ const activeItem = items.filter((item) => item.isActive(editor)).pop() ?? {
233
291
  name: "Multiple"
234
292
  };
235
- return /* @__PURE__ */ s(
236
- Q,
293
+ return /* @__PURE__ */ jsx(
294
+ Popover,
237
295
  {
238
296
  sideOffset: 5,
239
297
  align: "start",
240
298
  className: "w-48 p-1",
241
- trigger: /* @__PURE__ */ b(
242
- w,
299
+ trigger: /* @__PURE__ */ jsxs(
300
+ Button,
243
301
  {
244
302
  variant: "text",
245
303
  className: "gap-2 rounded-none",
246
304
  color: "text",
247
305
  children: [
248
- /* @__PURE__ */ s("span", { className: "whitespace-nowrap text-sm", children: r.name }),
249
- /* @__PURE__ */ s(Ue, { size: "small" })
306
+ /* @__PURE__ */ jsx("span", { className: "whitespace-nowrap text-sm", children: activeItem.name }),
307
+ /* @__PURE__ */ jsx(ExpandMoreIcon, { size: "small" })
250
308
  ]
251
309
  }
252
310
  ),
253
- modal: !0,
254
- open: e,
255
- onOpenChange: o,
256
- children: q.map((a, c) => /* @__PURE__ */ b(
257
- F,
311
+ modal: true,
312
+ open,
313
+ onOpenChange,
314
+ children: items.map((item, index) => /* @__PURE__ */ jsxs(
315
+ EditorBubbleItem,
258
316
  {
259
- onSelect: (n) => {
260
- a.command(n), o(!1);
317
+ onSelect: (editor2) => {
318
+ item.command(editor2);
319
+ onOpenChange(false);
261
320
  },
262
321
  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",
263
322
  children: [
264
- /* @__PURE__ */ b("div", { className: "flex items-center space-x-2", children: [
265
- /* @__PURE__ */ s(a.icon, { size: "smallest" }),
266
- /* @__PURE__ */ s("span", { children: a.name })
323
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center space-x-2", children: [
324
+ /* @__PURE__ */ jsx(item.icon, { size: "smallest" }),
325
+ /* @__PURE__ */ jsx("span", { children: item.name })
267
326
  ] }),
268
- r.name === a.name && /* @__PURE__ */ s(V, { size: "smallest" })
327
+ activeItem.name === item.name && /* @__PURE__ */ jsx(CheckIcon, { size: "smallest" })
269
328
  ]
270
329
  },
271
- c
330
+ index
272
331
  ))
273
332
  }
274
333
  );
275
334
  };
276
- function lt(e) {
335
+ function isValidUrl(url) {
277
336
  try {
278
- return new URL(e), !0;
279
- } catch {
280
- return !1;
337
+ new URL(url);
338
+ return true;
339
+ } catch (e) {
340
+ return false;
281
341
  }
282
342
  }
283
- function dt(e) {
284
- if (lt(e)) return e;
343
+ function getUrlFromString(str) {
344
+ if (isValidUrl(str)) return str;
285
345
  try {
286
- return e.includes(".") && !e.includes(" ") ? new URL(`https://${e}`).toString() : null;
287
- } catch {
346
+ if (str.includes(".") && !str.includes(" ")) {
347
+ return new URL(`https://${str}`).toString();
348
+ }
349
+ return null;
350
+ } catch (e) {
288
351
  return null;
289
352
  }
290
353
  }
291
- const ut = ({
292
- open: e,
293
- onOpenChange: o
354
+ const LinkSelector = ({
355
+ open,
356
+ onOpenChange
294
357
  }) => {
295
- const t = D(null), { editor: r } = y();
296
- return C(() => {
297
- t.current && t.current?.focus();
298
- }), r ? /* @__PURE__ */ s(
299
- Q,
358
+ const inputRef = useRef(null);
359
+ const { editor } = useCurrentEditor();
360
+ useEffect(() => {
361
+ inputRef.current && inputRef.current?.focus();
362
+ });
363
+ if (!editor) return null;
364
+ return /* @__PURE__ */ jsx(
365
+ Popover,
300
366
  {
301
- modal: !0,
302
- open: e,
303
- onOpenChange: o,
304
- trigger: /* @__PURE__ */ s(
305
- w,
367
+ modal: true,
368
+ open,
369
+ onOpenChange,
370
+ trigger: /* @__PURE__ */ jsx(
371
+ Button,
306
372
  {
307
373
  variant: "text",
308
374
  className: "gap-2 rounded-none",
309
375
  color: "text",
310
- children: /* @__PURE__ */ s("p", { className: g("underline decoration-stone-400 underline-offset-4", {
311
- "text-blue-500": r.isActive("link")
376
+ children: /* @__PURE__ */ jsx("p", { className: cls("underline decoration-stone-400 underline-offset-4", {
377
+ "text-blue-500": editor.isActive("link")
312
378
  }), children: "Link" })
313
379
  }
314
380
  ),
315
- children: /* @__PURE__ */ b(
381
+ children: /* @__PURE__ */ jsxs(
316
382
  "form",
317
383
  {
318
- onSubmit: (a) => {
319
- const c = a.currentTarget;
320
- a.preventDefault();
321
- const n = c[0], i = dt(n.value);
322
- i && r.chain().focus().setLink({ href: i }).run();
384
+ onSubmit: (e) => {
385
+ const target = e.currentTarget;
386
+ e.preventDefault();
387
+ const input = target[0];
388
+ const url = getUrlFromString(input.value);
389
+ url && editor.chain().focus().setLink({ href: url }).run();
323
390
  },
324
391
  className: "flex p-1",
325
392
  children: [
326
- /* @__PURE__ */ s(
393
+ /* @__PURE__ */ jsx(
327
394
  "input",
328
395
  {
329
- ref: t,
330
- autoFocus: e,
396
+ ref: inputRef,
397
+ autoFocus: open,
331
398
  placeholder: "Paste a link",
332
- defaultValue: r.getAttributes("link").href || "",
399
+ defaultValue: editor.getAttributes("link").href || "",
333
400
  className: "text-gray-900 dark:text-white flex-grow bg-transparent p-1 text-sm outline-none"
334
401
  }
335
402
  ),
336
- r.getAttributes("link").href ? /* @__PURE__ */ s(
337
- w,
403
+ editor.getAttributes("link").href ? /* @__PURE__ */ jsx(
404
+ Button,
338
405
  {
339
406
  size: "small",
340
407
  variant: "text",
@@ -342,375 +409,485 @@ const ut = ({
342
409
  color: "text",
343
410
  className: "flex items-center",
344
411
  onClick: () => {
345
- r.chain().focus().unsetLink().run();
412
+ editor.chain().focus().unsetLink().run();
346
413
  },
347
- children: /* @__PURE__ */ s(Ke, { size: "small" })
414
+ children: /* @__PURE__ */ jsx(DeleteIcon, { size: "small" })
348
415
  }
349
- ) : /* @__PURE__ */ s(
350
- w,
416
+ ) : /* @__PURE__ */ jsx(
417
+ Button,
351
418
  {
352
419
  size: "small",
353
420
  variant: "text",
354
- children: /* @__PURE__ */ s(V, { size: "small" })
421
+ children: /* @__PURE__ */ jsx(CheckIcon, { size: "small" })
355
422
  }
356
423
  )
357
424
  ]
358
425
  }
359
426
  )
360
427
  }
361
- ) : null;
362
- }, mt = () => {
363
- const { editor: e } = y();
364
- return e ? /* @__PURE__ */ s("div", { className: "flex", children: [
428
+ );
429
+ };
430
+ const TextButtons = () => {
431
+ const { editor } = useCurrentEditor();
432
+ if (!editor) return null;
433
+ const items2 = [
365
434
  {
366
435
  name: "bold",
367
- isActive: (t) => t?.isActive("bold") ?? !1,
368
- command: (t) => t?.chain().focus().toggleBold().run(),
369
- icon: $e
436
+ isActive: (editor2) => editor2?.isActive("bold") ?? false,
437
+ command: (editor2) => editor2?.chain().focus().toggleBold().run(),
438
+ icon: FormatBoldIcon
370
439
  },
371
440
  {
372
441
  name: "italic",
373
- isActive: (t) => t?.isActive("italic") ?? !1,
374
- command: (t) => t?.chain().focus().toggleItalic().run(),
375
- icon: qe
442
+ isActive: (editor2) => editor2?.isActive("italic") ?? false,
443
+ command: (editor2) => editor2?.chain().focus().toggleItalic().run(),
444
+ icon: FormatItalicIcon
376
445
  },
377
446
  {
378
447
  name: "underline",
379
- isActive: (t) => t?.isActive("underline") ?? !1,
380
- command: (t) => t?.chain().focus().toggleUnderline().run(),
381
- icon: We
448
+ isActive: (editor2) => editor2?.isActive("underline") ?? false,
449
+ command: (editor2) => editor2?.chain().focus().toggleUnderline().run(),
450
+ icon: FormatUnderlinedIcon
382
451
  },
383
452
  {
384
453
  name: "strike",
385
- isActive: (t) => t?.isActive("strike") ?? !1,
386
- command: (t) => t?.chain().focus().toggleStrike().run(),
387
- icon: Oe
454
+ isActive: (editor2) => editor2?.isActive("strike") ?? false,
455
+ command: (editor2) => editor2?.chain().focus().toggleStrike().run(),
456
+ icon: FormatStrikethroughIcon
388
457
  },
389
458
  {
390
459
  name: "code",
391
- isActive: (t) => t?.isActive("code") ?? !1,
392
- command: (t) => t?.chain().focus().toggleCode().run(),
393
- icon: z
460
+ isActive: (editor2) => editor2?.isActive("code") ?? false,
461
+ command: (editor2) => editor2?.chain().focus().toggleCode().run(),
462
+ icon: CodeIcon
394
463
  }
395
- ].map((t, r) => /* @__PURE__ */ s(
396
- F,
464
+ ];
465
+ return /* @__PURE__ */ jsx("div", { className: "flex", children: items2.map((item, index) => /* @__PURE__ */ jsx(
466
+ EditorBubbleItem,
397
467
  {
398
- onSelect: (a) => {
399
- t.command(a);
468
+ onSelect: (editor2) => {
469
+ item.command(editor2);
400
470
  },
401
- children: /* @__PURE__ */ s(
402
- w,
471
+ children: /* @__PURE__ */ jsx(
472
+ Button,
403
473
  {
404
474
  size: "small",
405
475
  color: "text",
406
476
  className: "gap-2 rounded-none h-full",
407
477
  variant: "text",
408
- children: /* @__PURE__ */ s(
409
- t.icon,
478
+ children: /* @__PURE__ */ jsx(
479
+ item.icon,
410
480
  {
411
- className: g({
412
- "text-inherit": !t.isActive(e),
413
- "text-blue-500": t.isActive(e)
481
+ className: cls({
482
+ "text-inherit": !item.isActive(editor),
483
+ "text-blue-500": item.isActive(editor)
414
484
  })
415
485
  }
416
486
  )
417
487
  }
418
488
  )
419
489
  },
420
- r
421
- )) }) : null;
490
+ index
491
+ )) });
422
492
  };
423
- function R(e, o, t, r = 300) {
424
- const a = L.useRef(!1), c = () => {
425
- o(), a.current = !1;
426
- }, n = L.useRef(void 0);
427
- L.useEffect(
428
- () => (a.current = !0, clearTimeout(n.current), n.current = setTimeout(c, r), () => {
429
- }),
430
- [t, e]
493
+ function useDebouncedCallback(value, callback, immediate, timeoutMs = 300) {
494
+ const pendingUpdate = React.useRef(false);
495
+ const performUpdate = () => {
496
+ callback();
497
+ pendingUpdate.current = false;
498
+ };
499
+ const handlerRef = React.useRef(void 0);
500
+ React.useEffect(
501
+ () => {
502
+ pendingUpdate.current = true;
503
+ clearTimeout(handlerRef.current);
504
+ handlerRef.current = setTimeout(performUpdate, timeoutMs);
505
+ return () => {
506
+ };
507
+ },
508
+ [immediate, value]
431
509
  );
432
510
  }
433
- function H(e) {
434
- 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) => {
435
- e[o] = H(e[o]);
436
- })), e);
511
+ function removeClassesFromJson(jsonObj) {
512
+ if (Array.isArray(jsonObj)) {
513
+ return jsonObj.map((item) => removeClassesFromJson(item));
514
+ } else if (typeof jsonObj === "object" && jsonObj !== null) {
515
+ if (jsonObj.attrs && typeof jsonObj.attrs === "object" && "class" in jsonObj.attrs) {
516
+ delete jsonObj.attrs.class;
517
+ }
518
+ Object.keys(jsonObj).forEach((key) => {
519
+ jsonObj[key] = removeClassesFromJson(jsonObj[key]);
520
+ });
521
+ }
522
+ return jsonObj;
437
523
  }
438
- const gt = st, pt = Re.configure({
524
+ const placeholder = PlaceholderExtension;
525
+ const tiptapLink = TiptapLink.configure({
439
526
  HTMLAttributes: {
440
- class: g(
527
+ class: cls(
441
528
  "text-gray-600 dark:text-slate-300 underline underline-offset-[3px] hover:text-primary transition-colors cursor-pointer"
442
529
  )
443
530
  }
444
- }), ft = De.configure({
531
+ });
532
+ const taskList = TaskList.configure({
445
533
  HTMLAttributes: {
446
- class: g("not-prose")
534
+ class: cls("not-prose")
447
535
  }
448
- }), ht = He.configure({
536
+ });
537
+ const taskItem = TaskItem.configure({
449
538
  HTMLAttributes: {
450
- class: g("flex items-start my-4")
539
+ class: cls("flex items-start my-4")
451
540
  },
452
- nested: !0
453
- }), bt = it.configure({
541
+ nested: true
542
+ });
543
+ const horizontalRule = Horizontal.configure({
454
544
  HTMLAttributes: {
455
- class: g("mt-4 mb-6 border-t", x)
545
+ class: cls("mt-4 mb-6 border-t", defaultBorderMixin)
456
546
  }
457
- }), kt = Ne.configure({
547
+ });
548
+ const starterKit = StarterKit.configure({
458
549
  bulletList: {
459
550
  HTMLAttributes: {
460
- class: g("list-disc list-outside leading-3 -mt-2")
551
+ class: cls("list-disc list-outside leading-3 -mt-2")
461
552
  }
462
553
  },
463
554
  orderedList: {
464
555
  HTMLAttributes: {
465
- class: g("list-decimal list-outside leading-3 -mt-2")
556
+ class: cls("list-decimal list-outside leading-3 -mt-2")
466
557
  }
467
558
  },
468
559
  listItem: {
469
560
  HTMLAttributes: {
470
- class: g("leading-normal -mb-2")
561
+ class: cls("leading-normal -mb-2")
471
562
  }
472
563
  },
473
564
  blockquote: {
474
565
  HTMLAttributes: {
475
- class: g("border-l-4 border-primary")
566
+ class: cls("border-l-4 border-primary")
476
567
  }
477
568
  },
478
569
  codeBlock: {
479
570
  HTMLAttributes: {
480
- class: g("rounded bg-blue-50 dark:bg-gray-700 border p-5 font-mono font-medium", x)
571
+ class: cls("rounded bg-blue-50 dark:bg-gray-700 border p-5 font-mono font-medium", defaultBorderMixin)
481
572
  }
482
573
  },
483
574
  code: {
484
575
  HTMLAttributes: {
485
- class: g("rounded-md bg-slate-50 dark:bg-gray-700 px-1.5 py-1 font-mono font-medium"),
576
+ class: cls("rounded-md bg-slate-50 dark:bg-gray-700 px-1.5 py-1 font-mono font-medium"),
486
577
  spellcheck: "false"
487
578
  }
488
579
  },
489
- horizontalRule: !1,
580
+ horizontalRule: false,
490
581
  dropcursor: {
491
582
  color: "#DBEAFE",
492
583
  width: 4
493
584
  },
494
- gapcursor: !1
585
+ gapcursor: false
495
586
  });
496
- async function W(e, o, t, r, a, c) {
497
- const { schema: n } = o.state;
498
- let i = e.getState(o.state);
499
- const d = document.createElement("div"), u = document.createElement("img");
500
- u.setAttribute("class", "opacity-40 rounded-lg border border-stone-200"), u.src = t.target?.result, d.appendChild(u);
501
- const p = Xe.widget(r, d);
502
- i = i?.add(o.state.doc, [p]), o.dispatch(o.state.tr.setMeta(e, { decorationSet: i }));
503
- const h = await a(c);
504
- console.log("uploaded image", h);
505
- const f = n.nodes.image.create({ src: h }), A = o.state.tr.replaceWith(r, r, f);
506
- i = i?.remove([p]), A.setMeta(e, { decorationSet: i }), o.dispatch(A);
587
+ async function onFileRead(plugin, view, readerEvent, pos, upload, image) {
588
+ const { schema } = view.state;
589
+ let decorationSet = plugin.getState(view.state);
590
+ const placeholder2 = document.createElement("div");
591
+ const imageElement = document.createElement("img");
592
+ imageElement.setAttribute("class", "opacity-40 rounded-lg border border-stone-200");
593
+ imageElement.src = readerEvent.target?.result;
594
+ placeholder2.appendChild(imageElement);
595
+ const deco = Decoration.widget(pos, placeholder2);
596
+ decorationSet = decorationSet?.add(view.state.doc, [deco]);
597
+ view.dispatch(view.state.tr.setMeta(plugin, { decorationSet }));
598
+ const src = await upload(image);
599
+ console.log("uploaded image", src);
600
+ const imageNode = schema.nodes.image.create({ src });
601
+ const tr = view.state.tr.replaceWith(pos, pos, imageNode);
602
+ decorationSet = decorationSet?.remove([deco]);
603
+ tr.setMeta(plugin, { decorationSet });
604
+ view.dispatch(tr);
507
605
  }
508
- const xt = (e) => {
509
- const o = new Qe({
606
+ const dropImagePlugin = (upload) => {
607
+ const plugin = new Plugin({
510
608
  state: {
511
609
  // Initialize the plugin state with an empty DecorationSet
512
- init: () => Ve.empty,
610
+ init: () => DecorationSet.empty,
513
611
  // Apply transactions to update the state
514
- apply: (t, r) => {
515
- const a = t.getMeta(o);
516
- return a && a.decorationSet ? a.decorationSet : r.map(t.mapping, t.doc);
612
+ apply: (tr, old) => {
613
+ const meta = tr.getMeta(plugin);
614
+ if (meta && meta.decorationSet) {
615
+ return meta.decorationSet;
616
+ }
617
+ return old.map(tr.mapping, tr.doc);
517
618
  }
518
619
  },
519
620
  props: {
520
621
  handleDOMEvents: {
521
- drop: (t, r) => {
522
- if (console.log("drop event", r), !r.dataTransfer?.files || r.dataTransfer?.files.length === 0)
523
- return !1;
524
- r.preventDefault();
525
- const c = Array.from(r.dataTransfer.files).filter((n) => /image/i.test(n.type));
526
- return c.length === 0 ? !1 : (c.forEach((n) => {
527
- const i = t.posAtCoords({ left: r.clientX, top: r.clientY });
528
- if (!i) return;
529
- const d = new FileReader();
530
- d.onload = async (u) => {
531
- await W(o, t, u, i.pos, e, n);
532
- }, d.readAsDataURL(n);
533
- }), !0);
622
+ drop: (view, event) => {
623
+ console.log("drop event", event);
624
+ if (!event.dataTransfer?.files || event.dataTransfer?.files.length === 0) {
625
+ return false;
626
+ }
627
+ event.preventDefault();
628
+ const files = Array.from(event.dataTransfer.files);
629
+ const images = files.filter((file) => /image/i.test(file.type));
630
+ if (images.length === 0) return false;
631
+ images.forEach((image) => {
632
+ const position = view.posAtCoords({ left: event.clientX, top: event.clientY });
633
+ if (!position) return;
634
+ const reader = new FileReader();
635
+ reader.onload = async (readerEvent) => {
636
+ await onFileRead(plugin, view, readerEvent, position.pos, upload, image);
637
+ };
638
+ reader.readAsDataURL(image);
639
+ });
640
+ return true;
534
641
  }
535
642
  },
536
- handlePaste(t, r, a) {
537
- const c = Array.from(r.clipboardData?.items || []), n = t.state.selection.from;
538
- console.log("pos", n);
539
- let i = !1;
540
- return c.forEach((d) => {
541
- const u = d.getAsFile();
542
- if (console.log("image", u), u) {
543
- i = !0;
544
- const p = new FileReader();
545
- p.onload = async (h) => {
546
- await W(o, t, h, n, e, u);
547
- }, p.readAsDataURL(u);
643
+ handlePaste(view, event, slice) {
644
+ const items2 = Array.from(event.clipboardData?.items || []);
645
+ const pos = view.state.selection.from;
646
+ console.log("pos", pos);
647
+ let anyImageFound = false;
648
+ items2.forEach((item) => {
649
+ const image = item.getAsFile();
650
+ console.log("image", image);
651
+ if (image) {
652
+ anyImageFound = true;
653
+ const reader = new FileReader();
654
+ reader.onload = async (readerEvent) => {
655
+ await onFileRead(plugin, view, readerEvent, pos, upload, image);
656
+ };
657
+ reader.readAsDataURL(image);
548
658
  }
549
- }), i;
659
+ });
660
+ return anyImageFound;
550
661
  },
551
- decorations(t) {
552
- return o.getState(t);
662
+ decorations(state) {
663
+ return plugin.getState(state);
553
664
  }
554
665
  },
555
- view(t) {
666
+ view(editorView) {
556
667
  return {
557
- update(r, a) {
558
- const c = o.getState(a), n = o.getState(r.state);
559
- c !== n && r.updateState(r.state);
668
+ update(view, prevState) {
669
+ const prevDecos = plugin.getState(prevState);
670
+ const newDecos = plugin.getState(view.state);
671
+ if (prevDecos !== newDecos) {
672
+ view.updateState(view.state);
673
+ }
560
674
  }
561
675
  };
562
676
  }
563
677
  });
564
- return o;
565
- }, yt = (e) => Ie.extend({
566
- addProseMirrorPlugins() {
567
- return [xt(e)];
568
- }
569
- }).configure({
570
- allowBase64: !0,
571
- HTMLAttributes: {
572
- class: g("rounded-lg border", x)
573
- }
574
- }), vt = B.create({
678
+ return plugin;
679
+ };
680
+ const createImageExtension = (uploadFn) => {
681
+ return TiptapImage.extend({
682
+ addProseMirrorPlugins() {
683
+ return [dropImagePlugin(uploadFn)];
684
+ }
685
+ }).configure({
686
+ allowBase64: true,
687
+ HTMLAttributes: {
688
+ class: cls("rounded-lg border", defaultBorderMixin)
689
+ }
690
+ });
691
+ };
692
+ const CustomKeymap = Extension.create({
575
693
  name: "CustomKeymap",
576
694
  addCommands() {
577
695
  return {
578
- selectTextWithinNodeBoundaries: () => ({ editor: e, commands: o }) => {
579
- const { state: t } = e, { tr: r } = t, a = r.selection.$from.start(), c = r.selection.$to.end();
580
- return o.setTextSelection({
581
- from: a,
582
- to: c
696
+ selectTextWithinNodeBoundaries: () => ({ editor, commands }) => {
697
+ const { state } = editor;
698
+ const { tr } = state;
699
+ const startNodePos = tr.selection.$from.start();
700
+ const endNodePos = tr.selection.$to.end();
701
+ return commands.setTextSelection({
702
+ from: startNodePos,
703
+ to: endNodePos
583
704
  });
584
705
  }
585
706
  };
586
707
  },
587
708
  addKeyboardShortcuts() {
588
709
  return {
589
- "Mod-a": ({ editor: e }) => {
590
- 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();
591
- return r > c || a < n ? (e.chain().selectTextWithinNodeBoundaries().run(), !0) : !1;
710
+ "Mod-a": ({ editor }) => {
711
+ const { state } = editor;
712
+ const { tr } = state;
713
+ const startSelectionPos = tr.selection.from;
714
+ const endSelectionPos = tr.selection.to;
715
+ const startNodePos = tr.selection.$from.start();
716
+ const endNodePos = tr.selection.$to.end();
717
+ const isCurrentTextSelectionNotExtendedToNodeBoundaries = startSelectionPos > startNodePos || endSelectionPos < endNodePos;
718
+ if (isCurrentTextSelectionNotExtendedToNodeBoundaries) {
719
+ editor.chain().selectTextWithinNodeBoundaries().run();
720
+ return true;
721
+ }
722
+ return false;
592
723
  }
593
724
  };
594
725
  }
595
726
  });
596
- function Ct(e) {
597
- const o = e.getBoundingClientRect();
727
+ function absoluteRect(node) {
728
+ const data = node.getBoundingClientRect();
598
729
  return {
599
- top: o.top,
600
- left: o.left,
601
- width: o.width
730
+ top: data.top,
731
+ left: data.left,
732
+ width: data.width
602
733
  };
603
734
  }
604
- function I(e) {
605
- return document.elementsFromPoint(e.x, e.y).find(
606
- (o) => o.parentElement?.matches?.(".ProseMirror") || o.matches(
735
+ function nodeDOMAtCoords(coords) {
736
+ return document.elementsFromPoint(coords.x, coords.y).find(
737
+ (elem) => elem.parentElement?.matches?.(".ProseMirror") || elem.matches(
607
738
  ["li", "p:not(:first-child)", "pre", "blockquote", "h1, h2, h3, h4, h5, h6"].join(", ")
608
739
  )
609
740
  );
610
741
  }
611
- function O(e, o, t) {
612
- const r = e.getBoundingClientRect();
613
- return o.posAtCoords({
614
- left: r.left + 50 + t.dragHandleWidth,
615
- top: r.top + 1
742
+ function nodePosAtDOM(node, view, options) {
743
+ const boundingRect = node.getBoundingClientRect();
744
+ return view.posAtCoords({
745
+ left: boundingRect.left + 50 + options.dragHandleWidth,
746
+ top: boundingRect.top + 1
616
747
  })?.inside;
617
748
  }
618
- function wt(e) {
619
- function o(n, i) {
620
- if (i.focus(), !n.dataTransfer) return;
621
- const d = I({
622
- x: n.clientX + 50 + e.dragHandleWidth,
623
- y: n.clientY
749
+ function DragHandle(options) {
750
+ function handleDragStart(event, view) {
751
+ view.focus();
752
+ if (!event.dataTransfer) return;
753
+ const node = nodeDOMAtCoords({
754
+ x: event.clientX + 50 + options.dragHandleWidth,
755
+ y: event.clientY
624
756
  });
625
- if (!(d instanceof Element)) return;
626
- const u = O(d, i, e);
627
- if (u == null || u < 0) return;
628
- i.dispatch(i.state.tr.setSelection($.create(i.state.doc, u)));
629
- const p = i.state.selection.content(), { dom: h, text: f } = Ye(i, p);
630
- 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 };
757
+ if (!(node instanceof Element)) return;
758
+ const nodePos = nodePosAtDOM(node, view, options);
759
+ if (nodePos == null || nodePos < 0) return;
760
+ view.dispatch(view.state.tr.setSelection(NodeSelection.create(view.state.doc, nodePos)));
761
+ const slice = view.state.selection.content();
762
+ const { dom, text } = __serializeForClipboard(view, slice);
763
+ event.dataTransfer.clearData();
764
+ event.dataTransfer.setData("text/html", dom.innerHTML);
765
+ event.dataTransfer.setData("text/plain", text);
766
+ event.dataTransfer.effectAllowed = "copyMove";
767
+ event.dataTransfer.setDragImage(node, 0, 0);
768
+ view.dragging = { slice, move: event.ctrlKey };
631
769
  }
632
- function t(n, i) {
633
- i.focus(), i.dom.classList.remove("dragging");
634
- const d = I({
635
- x: n.clientX + 50 + e.dragHandleWidth,
636
- y: n.clientY
770
+ function handleClick(event, view) {
771
+ view.focus();
772
+ view.dom.classList.remove("dragging");
773
+ const node = nodeDOMAtCoords({
774
+ x: event.clientX + 50 + options.dragHandleWidth,
775
+ y: event.clientY
637
776
  });
638
- if (!(d instanceof Element)) return;
639
- const u = O(d, i, e);
640
- u && i.dispatch(i.state.tr.setSelection($.create(i.state.doc, u)));
777
+ if (!(node instanceof Element)) return;
778
+ const nodePos = nodePosAtDOM(node, view, options);
779
+ if (!nodePos) return;
780
+ view.dispatch(view.state.tr.setSelection(NodeSelection.create(view.state.doc, nodePos)));
641
781
  }
642
- let r = null;
643
- function a() {
644
- r && r.classList.add("hide");
782
+ let dragHandleElement = null;
783
+ function hideDragHandle() {
784
+ if (dragHandleElement) {
785
+ dragHandleElement.classList.add("hide");
786
+ }
645
787
  }
646
- function c() {
647
- r && r.classList.remove("hide");
788
+ function showDragHandle() {
789
+ if (dragHandleElement) {
790
+ dragHandleElement.classList.remove("hide");
791
+ }
648
792
  }
649
- return new Je({
650
- view: (n) => (r = document.createElement("div"), r.draggable = !0, r.dataset.dragHandle = "", r.classList.add("drag-handle"), r.addEventListener("dragstart", (i) => {
651
- o(i, n);
652
- }), r.addEventListener("click", (i) => {
653
- t(i, n);
654
- }), a(), n?.dom?.parentElement?.appendChild(r), {
655
- destroy: () => {
656
- r?.remove?.(), r = null;
657
- }
658
- }),
793
+ return new Plugin$1({
794
+ view: (view) => {
795
+ dragHandleElement = document.createElement("div");
796
+ dragHandleElement.draggable = true;
797
+ dragHandleElement.dataset.dragHandle = "";
798
+ dragHandleElement.classList.add("drag-handle");
799
+ dragHandleElement.addEventListener("dragstart", (e) => {
800
+ handleDragStart(e, view);
801
+ });
802
+ dragHandleElement.addEventListener("click", (e) => {
803
+ handleClick(e, view);
804
+ });
805
+ hideDragHandle();
806
+ view?.dom?.parentElement?.appendChild(dragHandleElement);
807
+ return {
808
+ destroy: () => {
809
+ dragHandleElement?.remove?.();
810
+ dragHandleElement = null;
811
+ }
812
+ };
813
+ },
659
814
  props: {
660
815
  handleDOMEvents: {
661
- mousemove: (n, i) => {
662
- if (!n.editable)
816
+ mousemove: (view, event) => {
817
+ if (!view.editable) {
663
818
  return;
664
- const d = I({
665
- x: i.clientX + 50 + e.dragHandleWidth,
666
- y: i.clientY
819
+ }
820
+ const node = nodeDOMAtCoords({
821
+ x: event.clientX + 50 + options.dragHandleWidth,
822
+ y: event.clientY
667
823
  });
668
- if (!(d instanceof Element)) {
669
- a();
824
+ if (!(node instanceof Element)) {
825
+ hideDragHandle();
670
826
  return;
671
827
  }
672
- const u = window.getComputedStyle(d), p = parseInt(u.lineHeight, 10), h = parseInt(u.paddingTop, 10), f = Ct(d);
673
- 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());
828
+ const compStyle = window.getComputedStyle(node);
829
+ const lineHeight = parseInt(compStyle.lineHeight, 10);
830
+ const paddingTop = parseInt(compStyle.paddingTop, 10);
831
+ const rect = absoluteRect(node);
832
+ rect.top += (lineHeight - 24) / 2;
833
+ rect.top += paddingTop;
834
+ if (node.matches("ul:not([data-type=taskList]) li, ol li")) {
835
+ rect.left -= options.dragHandleWidth;
836
+ }
837
+ rect.width = options.dragHandleWidth;
838
+ if (!dragHandleElement) return;
839
+ dragHandleElement.style.left = `${rect.left - rect.width}px`;
840
+ dragHandleElement.style.top = `${rect.top}px`;
841
+ showDragHandle();
674
842
  },
675
843
  keydown: () => {
676
- a();
844
+ hideDragHandle();
677
845
  },
678
846
  mousewheel: () => {
679
- a();
847
+ hideDragHandle();
680
848
  },
681
849
  // dragging class is used for CSS
682
- dragstart: (n) => {
683
- n.dom.classList.add("dragging");
850
+ dragstart: (view) => {
851
+ view.dom.classList.add("dragging");
684
852
  },
685
- drop: (n) => {
686
- n.dom.classList.remove("dragging");
853
+ drop: (view) => {
854
+ view.dom.classList.remove("dragging");
687
855
  },
688
- dragend: (n) => {
689
- n.dom.classList.remove("dragging");
856
+ dragend: (view) => {
857
+ view.dom.classList.remove("dragging");
690
858
  }
691
859
  }
692
860
  }
693
861
  });
694
862
  }
695
- const At = B.create({
863
+ const DragAndDrop = Extension.create({
696
864
  name: "dragAndDrop",
697
865
  addProseMirrorPlugins() {
698
866
  return [
699
- wt({
867
+ DragHandle({
700
868
  dragHandleWidth: 24
701
869
  })
702
870
  ];
703
871
  }
704
- }), eo = ({
705
- handleImageUpload: e,
706
- initialContent: o,
707
- onJsonContentChange: t,
708
- onHtmlContentChange: r,
709
- onMarkdownContentChange: a
872
+ });
873
+ const FireCMSEditor = ({
874
+ handleImageUpload,
875
+ initialContent,
876
+ onJsonContentChange,
877
+ onHtmlContentChange,
878
+ onMarkdownContentChange
710
879
  }) => {
711
- const c = {
880
+ const defaultEditorProps = {
712
881
  handleDOMEvents: {
713
- keydown: (l, m) => !!(["ArrowUp", "ArrowDown", "Enter"].includes(m.key) && document.querySelector("#slash-command"))
882
+ keydown: (_view, event) => {
883
+ if (["ArrowUp", "ArrowDown", "Enter"].includes(event.key)) {
884
+ const slashCommand2 = document.querySelector("#slash-command");
885
+ if (slashCommand2) {
886
+ return true;
887
+ }
888
+ }
889
+ return false;
890
+ }
714
891
  }
715
892
  // handlePaste: (view, event) => {
716
893
  // if (event.clipboardData && event.clipboardData.files && event.clipboardData.files[0]) {
@@ -744,205 +921,235 @@ const At = B.create({
744
921
  // }
745
922
  // return false;
746
923
  // }
747
- }, n = at([
924
+ };
925
+ const suggestionItems = createSuggestionItems([
748
926
  {
749
927
  title: "Text",
750
928
  description: "Just start typing with plain text.",
751
929
  searchTerms: ["p", "paragraph"],
752
- icon: /* @__PURE__ */ s(X, { size: 18 }),
753
- command: ({ editor: l, range: m }) => {
754
- l.chain().focus().deleteRange(m).toggleNode("paragraph", "paragraph").run();
930
+ icon: /* @__PURE__ */ jsx(TextFieldsIcon, { size: 18 }),
931
+ command: ({ editor, range }) => {
932
+ editor.chain().focus().deleteRange(range).toggleNode("paragraph", "paragraph").run();
755
933
  }
756
934
  },
757
935
  {
758
936
  title: "To-do List",
759
937
  description: "Track tasks with a to-do list.",
760
938
  searchTerms: ["todo", "task", "list", "check", "checkbox"],
761
- icon: /* @__PURE__ */ s(j, { size: 18 }),
762
- command: ({ editor: l, range: m }) => {
763
- l.chain().focus().deleteRange(m).toggleTaskList().run();
939
+ icon: /* @__PURE__ */ jsx(CheckBoxIcon, { size: 18 }),
940
+ command: ({ editor, range }) => {
941
+ editor.chain().focus().deleteRange(range).toggleTaskList().run();
764
942
  }
765
943
  },
766
944
  {
767
945
  title: "Heading 1",
768
946
  description: "Big section heading.",
769
947
  searchTerms: ["title", "big", "large"],
770
- icon: /* @__PURE__ */ s(Y, { size: 18 }),
771
- command: ({ editor: l, range: m }) => {
772
- l.chain().focus().deleteRange(m).setNode("heading", { level: 1 }).run();
948
+ icon: /* @__PURE__ */ jsx(LooksOneIcon, { size: 18 }),
949
+ command: ({ editor, range }) => {
950
+ editor.chain().focus().deleteRange(range).setNode("heading", { level: 1 }).run();
773
951
  }
774
952
  },
775
953
  {
776
954
  title: "Heading 2",
777
955
  description: "Medium section heading.",
778
956
  searchTerms: ["subtitle", "medium"],
779
- icon: /* @__PURE__ */ s(J, { size: 18 }),
780
- command: ({ editor: l, range: m }) => {
781
- l.chain().focus().deleteRange(m).setNode("heading", { level: 2 }).run();
957
+ icon: /* @__PURE__ */ jsx(LooksTwoIcon, { size: 18 }),
958
+ command: ({ editor, range }) => {
959
+ editor.chain().focus().deleteRange(range).setNode("heading", { level: 2 }).run();
782
960
  }
783
961
  },
784
962
  {
785
963
  title: "Heading 3",
786
964
  description: "Small section heading.",
787
965
  searchTerms: ["subtitle", "small"],
788
- icon: /* @__PURE__ */ s(G, { size: 18 }),
789
- command: ({ editor: l, range: m }) => {
790
- l.chain().focus().deleteRange(m).setNode("heading", { level: 3 }).run();
966
+ icon: /* @__PURE__ */ jsx(Looks3Icon, { size: 18 }),
967
+ command: ({ editor, range }) => {
968
+ editor.chain().focus().deleteRange(range).setNode("heading", { level: 3 }).run();
791
969
  }
792
970
  },
793
971
  {
794
972
  title: "Bullet List",
795
973
  description: "Create a simple bullet list.",
796
974
  searchTerms: ["unordered", "point"],
797
- icon: /* @__PURE__ */ s(ee, { size: 18 }),
798
- command: ({ editor: l, range: m }) => {
799
- l.chain().focus().deleteRange(m).toggleBulletList().run();
975
+ icon: /* @__PURE__ */ jsx(FormatListBulletedIcon, { size: 18 }),
976
+ command: ({ editor, range }) => {
977
+ editor.chain().focus().deleteRange(range).toggleBulletList().run();
800
978
  }
801
979
  },
802
980
  {
803
981
  title: "Numbered List",
804
982
  description: "Create a list with numbering.",
805
983
  searchTerms: ["ordered"],
806
- icon: /* @__PURE__ */ s(te, { size: 18 }),
807
- command: ({ editor: l, range: m }) => {
808
- l.chain().focus().deleteRange(m).toggleOrderedList().run();
984
+ icon: /* @__PURE__ */ jsx(FormatListNumberedIcon, { size: 18 }),
985
+ command: ({ editor, range }) => {
986
+ editor.chain().focus().deleteRange(range).toggleOrderedList().run();
809
987
  }
810
988
  },
811
989
  {
812
990
  title: "Quote",
813
991
  description: "Capture a quote.",
814
992
  searchTerms: ["blockquote"],
815
- icon: /* @__PURE__ */ s(oe, { size: 18 }),
816
- command: ({ editor: l, range: m }) => l.chain().focus().deleteRange(m).toggleNode("paragraph", "paragraph").toggleBlockquote().run()
993
+ icon: /* @__PURE__ */ jsx(FormatQuoteIcon, { size: 18 }),
994
+ command: ({ editor, range }) => editor.chain().focus().deleteRange(range).toggleNode("paragraph", "paragraph").toggleBlockquote().run()
817
995
  },
818
996
  {
819
997
  title: "Code",
820
998
  description: "Capture a code snippet.",
821
999
  searchTerms: ["codeblock"],
822
- icon: /* @__PURE__ */ s(z, { size: 18 }),
823
- command: ({ editor: l, range: m }) => l.chain().focus().deleteRange(m).toggleCodeBlock().run()
1000
+ icon: /* @__PURE__ */ jsx(CodeIcon, { size: 18 }),
1001
+ command: ({ editor, range }) => editor.chain().focus().deleteRange(range).toggleCodeBlock().run()
824
1002
  },
825
1003
  {
826
1004
  title: "Image",
827
1005
  description: "Upload an image from your computer.",
828
1006
  searchTerms: ["photo", "picture", "media"],
829
- icon: /* @__PURE__ */ s(_e, { size: 18 }),
830
- command: ({ editor: l, range: m }) => {
831
- l.chain().focus().deleteRange(m).run();
832
- const k = document.createElement("input");
833
- k.type = "file", k.accept = "image/*", k.onchange = async () => {
834
- if (k.files?.length) {
835
- if (!k.files[0]) return;
836
- l.view.state.selection.from;
1007
+ icon: /* @__PURE__ */ jsx(ImageIcon, { size: 18 }),
1008
+ command: ({ editor, range }) => {
1009
+ editor.chain().focus().deleteRange(range).run();
1010
+ const input = document.createElement("input");
1011
+ input.type = "file";
1012
+ input.accept = "image/*";
1013
+ input.onchange = async () => {
1014
+ if (input.files?.length) {
1015
+ const file = input.files[0];
1016
+ if (!file) return;
1017
+ editor.view.state.selection.from;
837
1018
  }
838
- }, k.click();
1019
+ };
1020
+ input.click();
839
1021
  }
840
1022
  }
841
- ]), i = rt.configure({
1023
+ ]);
1024
+ const slashCommand = Command.configure({
842
1025
  suggestion: {
843
- items: () => n,
844
- render: nt
1026
+ items: () => suggestionItems,
1027
+ render: renderItems
845
1028
  }
846
- }), d = Z(() => yt(e), []), u = [
847
- me,
848
- ge,
849
- pe,
850
- he.configure({
851
- multicolor: !0
1029
+ });
1030
+ const imageExtension = useMemo(() => createImageExtension(handleImageUpload), []);
1031
+ const extensions = [
1032
+ TiptapUnderline,
1033
+ TextStyle,
1034
+ Color,
1035
+ Highlight.configure({
1036
+ multicolor: true
852
1037
  }),
853
- fe.configure({
854
- html: !1,
855
- transformCopiedText: !0
1038
+ Markdown.configure({
1039
+ html: false,
1040
+ transformCopiedText: true
856
1041
  }),
857
- vt,
858
- At,
859
- kt,
860
- gt,
861
- pt,
1042
+ CustomKeymap,
1043
+ DragAndDrop,
1044
+ starterKit,
1045
+ placeholder,
1046
+ tiptapLink,
862
1047
  // tiptapImage,
863
- d,
1048
+ imageExtension,
864
1049
  // updatedImage,
865
- ft,
866
- ht,
867
- bt,
868
- i
869
- ], [p, h] = v(!1), [f, A] = v(!1);
870
- Ze("Editor", Tt);
871
- const E = L.useRef(null), [ie, ce] = v(null), [M, le] = v(null), [N, de] = v(null), ue = (l) => {
872
- E.current = l, a && ce(l.storage.markdown.getMarkdown()), t && le(H(l.getJSON())), r && de(l.getHTML());
1050
+ taskList,
1051
+ taskItem,
1052
+ horizontalRule,
1053
+ slashCommand
1054
+ ];
1055
+ const [openNode, setOpenNode] = useState(false);
1056
+ const [openLink, setOpenLink] = useState(false);
1057
+ useInjectStyles("Editor", cssStyles);
1058
+ const editorRef = React.useRef(null);
1059
+ const [markdownContent, setMarkdownContent] = useState(null);
1060
+ const [jsonContent, setJsonContent] = useState(null);
1061
+ const [htmlContent, setHtmlContent] = useState(null);
1062
+ const onEditorUpdate = (editor) => {
1063
+ editorRef.current = editor;
1064
+ if (onMarkdownContentChange) {
1065
+ setMarkdownContent(editor.storage.markdown.getMarkdown());
1066
+ }
1067
+ if (onJsonContentChange) {
1068
+ setJsonContent(removeClassesFromJson(editor.getJSON()));
1069
+ }
1070
+ if (onHtmlContentChange) {
1071
+ setHtmlContent(editor.getHTML());
1072
+ }
873
1073
  };
874
- return R(ie, () => {
875
- if (E.current) {
876
- const l = E.current.storage.markdown.getMarkdown();
877
- a?.(Lt(l));
1074
+ useDebouncedCallback(markdownContent, () => {
1075
+ if (editorRef.current) {
1076
+ const markdown = editorRef.current.storage.markdown.getMarkdown();
1077
+ onMarkdownContentChange?.(addLineBreakAfterImages(markdown));
878
1078
  }
879
- }, !1, 500), R(M, () => {
880
- M && t?.(M);
881
- }, !1, 500), R(N, () => {
882
- N && r?.(N);
883
- }, !1, 500), o ? /* @__PURE__ */ s("div", { className: "relative w-full p-8", children: /* @__PURE__ */ s(Ge, { children: /* @__PURE__ */ s(
1079
+ }, false, 500);
1080
+ useDebouncedCallback(jsonContent, () => {
1081
+ if (jsonContent)
1082
+ onJsonContentChange?.(jsonContent);
1083
+ }, false, 500);
1084
+ useDebouncedCallback(htmlContent, () => {
1085
+ if (htmlContent)
1086
+ onHtmlContentChange?.(htmlContent);
1087
+ }, false, 500);
1088
+ if (!initialContent) return null;
1089
+ return /* @__PURE__ */ jsx("div", { className: "relative w-full p-8", children: /* @__PURE__ */ jsx(EditorRoot, { children: /* @__PURE__ */ jsx(
884
1090
  "div",
885
1091
  {
886
1092
  className: "relative min-h-[500px] w-full bg-white dark:bg-gray-950 rounded-lg",
887
- children: /* @__PURE__ */ b(
888
- ye,
1093
+ children: /* @__PURE__ */ jsxs(
1094
+ EditorProvider,
889
1095
  {
890
- content: o,
891
- extensions: u,
1096
+ content: initialContent,
1097
+ extensions,
892
1098
  editorProps: {
893
- ...c,
1099
+ ...defaultEditorProps,
894
1100
  attributes: {
895
1101
  class: "prose-lg prose-headings:font-title font-default focus:outline-none max-w-full p-12"
896
1102
  }
897
1103
  },
898
- onUpdate: ({ editor: l }) => {
899
- console.debug("Editor updated"), ue(l);
1104
+ onUpdate: ({ editor }) => {
1105
+ console.debug("Editor updated");
1106
+ onEditorUpdate(editor);
900
1107
  },
901
1108
  children: [
902
- /* @__PURE__ */ b(
903
- tt,
1109
+ /* @__PURE__ */ jsxs(
1110
+ EditorCommand,
904
1111
  {
905
- 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),
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),
906
1113
  children: [
907
- /* @__PURE__ */ s(ot, { className: "px-2 text-gray-700 dark:text-slate-300", children: "No results" }),
908
- n.map((l) => /* @__PURE__ */ b(
909
- se,
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,
910
1117
  {
911
- value: l.title,
912
- onCommand: (m) => l?.command?.(m),
1118
+ value: item.title,
1119
+ onCommand: (val) => item?.command?.(val),
913
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",
914
1121
  children: [
915
- /* @__PURE__ */ s(
1122
+ /* @__PURE__ */ jsx(
916
1123
  "div",
917
1124
  {
918
- className: g("flex h-10 w-10 items-center justify-center rounded-md border bg-white dark:bg-gray-900", x),
919
- children: l.icon
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
920
1127
  }
921
1128
  ),
922
- /* @__PURE__ */ b("div", { children: [
923
- /* @__PURE__ */ s("p", { className: "font-medium", children: l.title }),
924
- /* @__PURE__ */ s("p", { className: "text-xs text-gray-700 dark:text-slate-300", children: l.description })
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 })
925
1132
  ] })
926
1133
  ]
927
1134
  },
928
- l.title
1135
+ item.title
929
1136
  ))
930
1137
  ]
931
1138
  }
932
1139
  ),
933
- /* @__PURE__ */ b(
934
- je,
1140
+ /* @__PURE__ */ jsxs(
1141
+ EditorBubble,
935
1142
  {
936
1143
  tippyOptions: {
937
1144
  placement: "top"
938
1145
  },
939
- className: g("flex w-fit max-w-[90vw] h-10 overflow-hidden rounded border bg-white dark:bg-gray-900 shadow", x),
1146
+ className: cls("flex w-fit max-w-[90vw] h-10 overflow-hidden rounded border bg-white dark:bg-gray-900 shadow", defaultBorderMixin),
940
1147
  children: [
941
- /* @__PURE__ */ s(ct, { open: p, onOpenChange: h }),
942
- /* @__PURE__ */ s(K, { orientation: "vertical" }),
943
- /* @__PURE__ */ s(ut, { open: f, onOpenChange: A }),
944
- /* @__PURE__ */ s(K, { orientation: "vertical" }),
945
- /* @__PURE__ */ s(mt, {})
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, {})
946
1153
  ]
947
1154
  }
948
1155
  )
@@ -950,14 +1157,14 @@ const At = B.create({
950
1157
  }
951
1158
  )
952
1159
  }
953
- ) }) }) : null;
1160
+ ) }) });
954
1161
  };
955
- function Lt(e) {
956
- const o = /!\[.*?\]\(.*?\)/g;
957
- return e.replace(o, (t) => `${t}
1162
+ function addLineBreakAfterImages(markdown) {
1163
+ const imageRegex = /!\[.*?\]\(.*?\)/g;
1164
+ return markdown.replace(imageRegex, (match) => `${match}
958
1165
  `);
959
1166
  }
960
- const Tt = `
1167
+ const cssStyles = `
961
1168
 
962
1169
  .ProseMirror .is-editor-empty:first-child::before {
963
1170
  content: attr(data-placeholder);
@@ -1149,6 +1356,6 @@ ul[data-type="taskList"] li[data-checked="true"] > div > p {
1149
1356
  }
1150
1357
  `;
1151
1358
  export {
1152
- eo as FireCMSEditor
1359
+ FireCMSEditor
1153
1360
  };
1154
1361
  //# sourceMappingURL=index.es.js.map