@firecms/editor 3.0.0-canary.9 → 3.0.0-canary.91

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,342 +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, 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;
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)
232
- return null;
233
- 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() ?? {
234
291
  name: "Multiple"
235
292
  };
236
- return /* @__PURE__ */ s(
237
- Q,
293
+ return /* @__PURE__ */ jsx(
294
+ Popover,
238
295
  {
239
296
  sideOffset: 5,
240
297
  align: "start",
241
298
  className: "w-48 p-1",
242
- trigger: /* @__PURE__ */ b(
243
- w,
299
+ trigger: /* @__PURE__ */ jsxs(
300
+ Button,
244
301
  {
245
302
  variant: "text",
246
303
  className: "gap-2 rounded-none",
247
304
  color: "text",
248
305
  children: [
249
- /* @__PURE__ */ s("span", { className: "whitespace-nowrap text-sm", children: r.name }),
250
- /* @__PURE__ */ s(Ue, { size: "small" })
306
+ /* @__PURE__ */ jsx("span", { className: "whitespace-nowrap text-sm", children: activeItem.name }),
307
+ /* @__PURE__ */ jsx(ExpandMoreIcon, { size: "small" })
251
308
  ]
252
309
  }
253
310
  ),
254
- modal: !0,
255
- open: e,
256
- onOpenChange: o,
257
- children: q.map((a, c) => /* @__PURE__ */ b(
258
- F,
311
+ modal: true,
312
+ open,
313
+ onOpenChange,
314
+ children: items.map((item, index) => /* @__PURE__ */ jsxs(
315
+ EditorBubbleItem,
259
316
  {
260
- onSelect: (n) => {
261
- a.command(n), o(!1);
317
+ onSelect: (editor2) => {
318
+ item.command(editor2);
319
+ onOpenChange(false);
262
320
  },
263
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",
264
322
  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 })
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 })
268
326
  ] }),
269
- r.name === a.name && /* @__PURE__ */ s(V, { size: "smallest" })
327
+ activeItem.name === item.name && /* @__PURE__ */ jsx(CheckIcon, { size: "smallest" })
270
328
  ]
271
329
  },
272
- c
330
+ index
273
331
  ))
274
332
  }
275
333
  );
276
334
  };
277
- function lt(e) {
335
+ function isValidUrl(url) {
278
336
  try {
279
- return new URL(e), !0;
280
- } catch {
281
- return !1;
337
+ new URL(url);
338
+ return true;
339
+ } catch (e) {
340
+ return false;
282
341
  }
283
342
  }
284
- function dt(e) {
285
- if (lt(e))
286
- return e;
343
+ function getUrlFromString(str) {
344
+ if (isValidUrl(str)) return str;
287
345
  try {
288
- return e.includes(".") && !e.includes(" ") ? new URL(`https://${e}`).toString() : null;
289
- } catch {
346
+ if (str.includes(".") && !str.includes(" ")) {
347
+ return new URL(`https://${str}`).toString();
348
+ }
349
+ return null;
350
+ } catch (e) {
290
351
  return null;
291
352
  }
292
353
  }
293
- const ut = ({
294
- open: e,
295
- onOpenChange: o
354
+ const LinkSelector = ({
355
+ open,
356
+ onOpenChange
296
357
  }) => {
297
- const t = D(null), { editor: r } = y();
298
- return C(() => {
299
- t.current && t.current?.focus();
300
- }), r ? /* @__PURE__ */ s(
301
- 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,
302
366
  {
303
- modal: !0,
304
- open: e,
305
- onOpenChange: o,
306
- trigger: /* @__PURE__ */ s(
307
- w,
367
+ modal: true,
368
+ open,
369
+ onOpenChange,
370
+ trigger: /* @__PURE__ */ jsx(
371
+ Button,
308
372
  {
309
373
  variant: "text",
310
374
  className: "gap-2 rounded-none",
311
375
  color: "text",
312
- children: /* @__PURE__ */ s("p", { className: g("underline decoration-stone-400 underline-offset-4", {
313
- "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")
314
378
  }), children: "Link" })
315
379
  }
316
380
  ),
317
- children: /* @__PURE__ */ b(
381
+ children: /* @__PURE__ */ jsxs(
318
382
  "form",
319
383
  {
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();
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();
325
390
  },
326
391
  className: "flex p-1",
327
392
  children: [
328
- /* @__PURE__ */ s(
393
+ /* @__PURE__ */ jsx(
329
394
  "input",
330
395
  {
331
- ref: t,
332
- autoFocus: e,
396
+ ref: inputRef,
397
+ autoFocus: open,
333
398
  placeholder: "Paste a link",
334
- defaultValue: r.getAttributes("link").href || "",
399
+ defaultValue: editor.getAttributes("link").href || "",
335
400
  className: "text-gray-900 dark:text-white flex-grow bg-transparent p-1 text-sm outline-none"
336
401
  }
337
402
  ),
338
- r.getAttributes("link").href ? /* @__PURE__ */ s(
339
- w,
403
+ editor.getAttributes("link").href ? /* @__PURE__ */ jsx(
404
+ Button,
340
405
  {
341
406
  size: "small",
342
407
  variant: "text",
@@ -344,381 +409,485 @@ const ut = ({
344
409
  color: "text",
345
410
  className: "flex items-center",
346
411
  onClick: () => {
347
- r.chain().focus().unsetLink().run();
412
+ editor.chain().focus().unsetLink().run();
348
413
  },
349
- children: /* @__PURE__ */ s(Ke, { size: "small" })
414
+ children: /* @__PURE__ */ jsx(DeleteIcon, { size: "small" })
350
415
  }
351
- ) : /* @__PURE__ */ s(
352
- w,
416
+ ) : /* @__PURE__ */ jsx(
417
+ Button,
353
418
  {
354
419
  size: "small",
355
420
  variant: "text",
356
- children: /* @__PURE__ */ s(V, { size: "small" })
421
+ children: /* @__PURE__ */ jsx(CheckIcon, { size: "small" })
357
422
  }
358
423
  )
359
424
  ]
360
425
  }
361
426
  )
362
427
  }
363
- ) : null;
364
- }, mt = () => {
365
- const { editor: e } = y();
366
- 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 = [
367
434
  {
368
435
  name: "bold",
369
- isActive: (t) => t?.isActive("bold") ?? !1,
370
- command: (t) => t?.chain().focus().toggleBold().run(),
371
- icon: $e
436
+ isActive: (editor2) => editor2?.isActive("bold") ?? false,
437
+ command: (editor2) => editor2?.chain().focus().toggleBold().run(),
438
+ icon: FormatBoldIcon
372
439
  },
373
440
  {
374
441
  name: "italic",
375
- isActive: (t) => t?.isActive("italic") ?? !1,
376
- command: (t) => t?.chain().focus().toggleItalic().run(),
377
- icon: qe
442
+ isActive: (editor2) => editor2?.isActive("italic") ?? false,
443
+ command: (editor2) => editor2?.chain().focus().toggleItalic().run(),
444
+ icon: FormatItalicIcon
378
445
  },
379
446
  {
380
447
  name: "underline",
381
- isActive: (t) => t?.isActive("underline") ?? !1,
382
- command: (t) => t?.chain().focus().toggleUnderline().run(),
383
- icon: We
448
+ isActive: (editor2) => editor2?.isActive("underline") ?? false,
449
+ command: (editor2) => editor2?.chain().focus().toggleUnderline().run(),
450
+ icon: FormatUnderlinedIcon
384
451
  },
385
452
  {
386
453
  name: "strike",
387
- isActive: (t) => t?.isActive("strike") ?? !1,
388
- command: (t) => t?.chain().focus().toggleStrike().run(),
389
- icon: Oe
454
+ isActive: (editor2) => editor2?.isActive("strike") ?? false,
455
+ command: (editor2) => editor2?.chain().focus().toggleStrike().run(),
456
+ icon: FormatStrikethroughIcon
390
457
  },
391
458
  {
392
459
  name: "code",
393
- isActive: (t) => t?.isActive("code") ?? !1,
394
- command: (t) => t?.chain().focus().toggleCode().run(),
395
- icon: z
460
+ isActive: (editor2) => editor2?.isActive("code") ?? false,
461
+ command: (editor2) => editor2?.chain().focus().toggleCode().run(),
462
+ icon: CodeIcon
396
463
  }
397
- ].map((t, r) => /* @__PURE__ */ s(
398
- F,
464
+ ];
465
+ return /* @__PURE__ */ jsx("div", { className: "flex", children: items2.map((item, index) => /* @__PURE__ */ jsx(
466
+ EditorBubbleItem,
399
467
  {
400
- onSelect: (a) => {
401
- t.command(a);
468
+ onSelect: (editor2) => {
469
+ item.command(editor2);
402
470
  },
403
- children: /* @__PURE__ */ s(
404
- w,
471
+ children: /* @__PURE__ */ jsx(
472
+ Button,
405
473
  {
406
474
  size: "small",
407
475
  color: "text",
408
476
  className: "gap-2 rounded-none h-full",
409
477
  variant: "text",
410
- children: /* @__PURE__ */ s(
411
- t.icon,
478
+ children: /* @__PURE__ */ jsx(
479
+ item.icon,
412
480
  {
413
- className: g({
414
- "text-inherit": !t.isActive(e),
415
- "text-blue-500": t.isActive(e)
481
+ className: cls({
482
+ "text-inherit": !item.isActive(editor),
483
+ "text-blue-500": item.isActive(editor)
416
484
  })
417
485
  }
418
486
  )
419
487
  }
420
488
  )
421
489
  },
422
- r
423
- )) }) : null;
490
+ index
491
+ )) });
424
492
  };
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]
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]
434
509
  );
435
510
  }
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);
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;
440
523
  }
441
- const gt = st, pt = Re.configure({
524
+ const placeholder = PlaceholderExtension;
525
+ const tiptapLink = TiptapLink.configure({
442
526
  HTMLAttributes: {
443
- class: g(
527
+ class: cls(
444
528
  "text-gray-600 dark:text-slate-300 underline underline-offset-[3px] hover:text-primary transition-colors cursor-pointer"
445
529
  )
446
530
  }
447
- }), ft = De.configure({
531
+ });
532
+ const taskList = TaskList.configure({
448
533
  HTMLAttributes: {
449
- class: g("not-prose")
534
+ class: cls("not-prose")
450
535
  }
451
- }), ht = He.configure({
536
+ });
537
+ const taskItem = TaskItem.configure({
452
538
  HTMLAttributes: {
453
- class: g("flex items-start my-4")
539
+ class: cls("flex items-start my-4")
454
540
  },
455
- nested: !0
456
- }), bt = it.configure({
541
+ nested: true
542
+ });
543
+ const horizontalRule = Horizontal.configure({
457
544
  HTMLAttributes: {
458
- class: g("mt-4 mb-6 border-t", x)
545
+ class: cls("mt-4 mb-6 border-t", defaultBorderMixin)
459
546
  }
460
- }), kt = Ne.configure({
547
+ });
548
+ const starterKit = StarterKit.configure({
461
549
  bulletList: {
462
550
  HTMLAttributes: {
463
- class: g("list-disc list-outside leading-3 -mt-2")
551
+ class: cls("list-disc list-outside leading-3 -mt-2")
464
552
  }
465
553
  },
466
554
  orderedList: {
467
555
  HTMLAttributes: {
468
- class: g("list-decimal list-outside leading-3 -mt-2")
556
+ class: cls("list-decimal list-outside leading-3 -mt-2")
469
557
  }
470
558
  },
471
559
  listItem: {
472
560
  HTMLAttributes: {
473
- class: g("leading-normal -mb-2")
561
+ class: cls("leading-normal -mb-2")
474
562
  }
475
563
  },
476
564
  blockquote: {
477
565
  HTMLAttributes: {
478
- class: g("border-l-4 border-primary")
566
+ class: cls("border-l-4 border-primary")
479
567
  }
480
568
  },
481
569
  codeBlock: {
482
570
  HTMLAttributes: {
483
- 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)
484
572
  }
485
573
  },
486
574
  code: {
487
575
  HTMLAttributes: {
488
- 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"),
489
577
  spellcheck: "false"
490
578
  }
491
579
  },
492
- horizontalRule: !1,
580
+ horizontalRule: false,
493
581
  dropcursor: {
494
582
  color: "#DBEAFE",
495
583
  width: 4
496
584
  },
497
- gapcursor: !1
585
+ gapcursor: false
498
586
  });
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);
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);
510
605
  }
511
- const xt = (e) => {
512
- const o = new Qe({
606
+ const dropImagePlugin = (upload) => {
607
+ const plugin = new Plugin({
513
608
  state: {
514
609
  // Initialize the plugin state with an empty DecorationSet
515
- init: () => Ve.empty,
610
+ init: () => DecorationSet.empty,
516
611
  // 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);
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);
520
618
  }
521
619
  },
522
620
  props: {
523
621
  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);
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;
538
641
  }
539
642
  },
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);
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);
552
658
  }
553
- }), i;
659
+ });
660
+ return anyImageFound;
554
661
  },
555
- decorations(t) {
556
- return o.getState(t);
662
+ decorations(state) {
663
+ return plugin.getState(state);
557
664
  }
558
665
  },
559
- view(t) {
666
+ view(editorView) {
560
667
  return {
561
- update(r, a) {
562
- const c = o.getState(a), n = o.getState(r.state);
563
- 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
+ }
564
674
  }
565
675
  };
566
676
  }
567
677
  });
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({
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({
579
693
  name: "CustomKeymap",
580
694
  addCommands() {
581
695
  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
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
587
704
  });
588
705
  }
589
706
  };
590
707
  },
591
708
  addKeyboardShortcuts() {
592
709
  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;
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;
596
723
  }
597
724
  };
598
725
  }
599
726
  });
600
- function Ct(e) {
601
- const o = e.getBoundingClientRect();
727
+ function absoluteRect(node) {
728
+ const data = node.getBoundingClientRect();
602
729
  return {
603
- top: o.top,
604
- left: o.left,
605
- width: o.width
730
+ top: data.top,
731
+ left: data.left,
732
+ width: data.width
606
733
  };
607
734
  }
608
- function I(e) {
609
- return document.elementsFromPoint(e.x, e.y).find(
610
- (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(
611
738
  ["li", "p:not(:first-child)", "pre", "blockquote", "h1, h2, h3, h4, h5, h6"].join(", ")
612
739
  )
613
740
  );
614
741
  }
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
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
620
747
  })?.inside;
621
748
  }
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
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
629
756
  });
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 };
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 };
638
769
  }
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
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
644
776
  });
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)));
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)));
649
781
  }
650
- let r = null;
651
- function a() {
652
- r && r.classList.add("hide");
782
+ let dragHandleElement = null;
783
+ function hideDragHandle() {
784
+ if (dragHandleElement) {
785
+ dragHandleElement.classList.add("hide");
786
+ }
653
787
  }
654
- function c() {
655
- r && r.classList.remove("hide");
788
+ function showDragHandle() {
789
+ if (dragHandleElement) {
790
+ dragHandleElement.classList.remove("hide");
791
+ }
656
792
  }
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
- }),
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
+ },
667
814
  props: {
668
815
  handleDOMEvents: {
669
- mousemove: (n, i) => {
670
- if (!n.editable)
816
+ mousemove: (view, event) => {
817
+ if (!view.editable) {
671
818
  return;
672
- const d = I({
673
- x: i.clientX + 50 + e.dragHandleWidth,
674
- y: i.clientY
819
+ }
820
+ const node = nodeDOMAtCoords({
821
+ x: event.clientX + 50 + options.dragHandleWidth,
822
+ y: event.clientY
675
823
  });
676
- if (!(d instanceof Element)) {
677
- a();
824
+ if (!(node instanceof Element)) {
825
+ hideDragHandle();
678
826
  return;
679
827
  }
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());
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();
682
842
  },
683
843
  keydown: () => {
684
- a();
844
+ hideDragHandle();
685
845
  },
686
846
  mousewheel: () => {
687
- a();
847
+ hideDragHandle();
688
848
  },
689
849
  // dragging class is used for CSS
690
- dragstart: (n) => {
691
- n.dom.classList.add("dragging");
850
+ dragstart: (view) => {
851
+ view.dom.classList.add("dragging");
692
852
  },
693
- drop: (n) => {
694
- n.dom.classList.remove("dragging");
853
+ drop: (view) => {
854
+ view.dom.classList.remove("dragging");
695
855
  },
696
- dragend: (n) => {
697
- n.dom.classList.remove("dragging");
856
+ dragend: (view) => {
857
+ view.dom.classList.remove("dragging");
698
858
  }
699
859
  }
700
860
  }
701
861
  });
702
862
  }
703
- const At = B.create({
863
+ const DragAndDrop = Extension.create({
704
864
  name: "dragAndDrop",
705
865
  addProseMirrorPlugins() {
706
866
  return [
707
- wt({
867
+ DragHandle({
708
868
  dragHandleWidth: 24
709
869
  })
710
870
  ];
711
871
  }
712
- }), eo = ({
713
- handleImageUpload: e,
714
- initialContent: o,
715
- onJsonContentChange: t,
716
- onHtmlContentChange: r,
717
- onMarkdownContentChange: a
872
+ });
873
+ const FireCMSEditor = ({
874
+ handleImageUpload,
875
+ initialContent,
876
+ onJsonContentChange,
877
+ onHtmlContentChange,
878
+ onMarkdownContentChange
718
879
  }) => {
719
- const c = {
880
+ const defaultEditorProps = {
720
881
  handleDOMEvents: {
721
- 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
+ }
722
891
  }
723
892
  // handlePaste: (view, event) => {
724
893
  // if (event.clipboardData && event.clipboardData.files && event.clipboardData.files[0]) {
@@ -752,206 +921,235 @@ const At = B.create({
752
921
  // }
753
922
  // return false;
754
923
  // }
755
- }, n = at([
924
+ };
925
+ const suggestionItems = createSuggestionItems([
756
926
  {
757
927
  title: "Text",
758
928
  description: "Just start typing with plain text.",
759
929
  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();
930
+ icon: /* @__PURE__ */ jsx(TextFieldsIcon, { size: 18 }),
931
+ command: ({ editor, range }) => {
932
+ editor.chain().focus().deleteRange(range).toggleNode("paragraph", "paragraph").run();
763
933
  }
764
934
  },
765
935
  {
766
936
  title: "To-do List",
767
937
  description: "Track tasks with a to-do list.",
768
938
  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();
939
+ icon: /* @__PURE__ */ jsx(CheckBoxIcon, { size: 18 }),
940
+ command: ({ editor, range }) => {
941
+ editor.chain().focus().deleteRange(range).toggleTaskList().run();
772
942
  }
773
943
  },
774
944
  {
775
945
  title: "Heading 1",
776
946
  description: "Big section heading.",
777
947
  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();
948
+ icon: /* @__PURE__ */ jsx(LooksOneIcon, { size: 18 }),
949
+ command: ({ editor, range }) => {
950
+ editor.chain().focus().deleteRange(range).setNode("heading", { level: 1 }).run();
781
951
  }
782
952
  },
783
953
  {
784
954
  title: "Heading 2",
785
955
  description: "Medium section heading.",
786
956
  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();
957
+ icon: /* @__PURE__ */ jsx(LooksTwoIcon, { size: 18 }),
958
+ command: ({ editor, range }) => {
959
+ editor.chain().focus().deleteRange(range).setNode("heading", { level: 2 }).run();
790
960
  }
791
961
  },
792
962
  {
793
963
  title: "Heading 3",
794
964
  description: "Small section heading.",
795
965
  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();
966
+ icon: /* @__PURE__ */ jsx(Looks3Icon, { size: 18 }),
967
+ command: ({ editor, range }) => {
968
+ editor.chain().focus().deleteRange(range).setNode("heading", { level: 3 }).run();
799
969
  }
800
970
  },
801
971
  {
802
972
  title: "Bullet List",
803
973
  description: "Create a simple bullet list.",
804
974
  searchTerms: ["unordered", "point"],
805
- icon: /* @__PURE__ */ s(ee, { size: 18 }),
806
- command: ({ editor: l, range: m }) => {
807
- 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();
808
978
  }
809
979
  },
810
980
  {
811
981
  title: "Numbered List",
812
982
  description: "Create a list with numbering.",
813
983
  searchTerms: ["ordered"],
814
- icon: /* @__PURE__ */ s(te, { size: 18 }),
815
- command: ({ editor: l, range: m }) => {
816
- 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();
817
987
  }
818
988
  },
819
989
  {
820
990
  title: "Quote",
821
991
  description: "Capture a quote.",
822
992
  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()
993
+ icon: /* @__PURE__ */ jsx(FormatQuoteIcon, { size: 18 }),
994
+ command: ({ editor, range }) => editor.chain().focus().deleteRange(range).toggleNode("paragraph", "paragraph").toggleBlockquote().run()
825
995
  },
826
996
  {
827
997
  title: "Code",
828
998
  description: "Capture a code snippet.",
829
999
  searchTerms: ["codeblock"],
830
- icon: /* @__PURE__ */ s(z, { size: 18 }),
831
- 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()
832
1002
  },
833
1003
  {
834
1004
  title: "Image",
835
1005
  description: "Upload an image from your computer.",
836
1006
  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;
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;
846
1018
  }
847
- }, k.click();
1019
+ };
1020
+ input.click();
848
1021
  }
849
1022
  }
850
- ]), i = rt.configure({
1023
+ ]);
1024
+ const slashCommand = Command.configure({
851
1025
  suggestion: {
852
- items: () => n,
853
- render: nt
1026
+ items: () => suggestionItems,
1027
+ render: renderItems
854
1028
  }
855
- }), d = Z(() => yt(e), []), u = [
856
- me,
857
- ge,
858
- pe,
859
- he.configure({
860
- multicolor: !0
1029
+ });
1030
+ const imageExtension = useMemo(() => createImageExtension(handleImageUpload), []);
1031
+ const extensions = [
1032
+ TiptapUnderline,
1033
+ TextStyle,
1034
+ Color,
1035
+ Highlight.configure({
1036
+ multicolor: true
861
1037
  }),
862
- fe.configure({
863
- html: !1,
864
- transformCopiedText: !0
1038
+ Markdown.configure({
1039
+ html: false,
1040
+ transformCopiedText: true
865
1041
  }),
866
- vt,
867
- At,
868
- kt,
869
- gt,
870
- pt,
1042
+ CustomKeymap,
1043
+ DragAndDrop,
1044
+ starterKit,
1045
+ placeholder,
1046
+ tiptapLink,
871
1047
  // tiptapImage,
872
- d,
1048
+ imageExtension,
873
1049
  // 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());
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
+ }
882
1073
  };
883
- return R(ie, () => {
884
- if (E.current) {
885
- const l = E.current.storage.markdown.getMarkdown();
886
- a?.(Lt(l));
1074
+ useDebouncedCallback(markdownContent, () => {
1075
+ if (editorRef.current) {
1076
+ const markdown = editorRef.current.storage.markdown.getMarkdown();
1077
+ onMarkdownContentChange?.(addLineBreakAfterImages(markdown));
887
1078
  }
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(
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(
893
1090
  "div",
894
1091
  {
895
1092
  className: "relative min-h-[500px] w-full bg-white dark:bg-gray-950 rounded-lg",
896
- children: /* @__PURE__ */ b(
897
- ye,
1093
+ children: /* @__PURE__ */ jsxs(
1094
+ EditorProvider,
898
1095
  {
899
- content: o,
900
- extensions: u,
1096
+ content: initialContent,
1097
+ extensions,
901
1098
  editorProps: {
902
- ...c,
1099
+ ...defaultEditorProps,
903
1100
  attributes: {
904
1101
  class: "prose-lg prose-headings:font-title font-default focus:outline-none max-w-full p-12"
905
1102
  }
906
1103
  },
907
- onUpdate: ({ editor: l }) => {
908
- console.log("editor updated"), ue(l);
1104
+ onUpdate: ({ editor }) => {
1105
+ console.debug("Editor updated");
1106
+ onEditorUpdate(editor);
909
1107
  },
910
1108
  children: [
911
- /* @__PURE__ */ b(
912
- tt,
1109
+ /* @__PURE__ */ jsxs(
1110
+ EditorCommand,
913
1111
  {
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),
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),
915
1113
  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,
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,
919
1117
  {
920
- value: l.title,
921
- onCommand: (m) => l?.command?.(m),
1118
+ value: item.title,
1119
+ onCommand: (val) => item?.command?.(val),
922
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",
923
1121
  children: [
924
- /* @__PURE__ */ s(
1122
+ /* @__PURE__ */ jsx(
925
1123
  "div",
926
1124
  {
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
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
929
1127
  }
930
1128
  ),
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 })
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 })
934
1132
  ] })
935
1133
  ]
936
1134
  },
937
- l.title
1135
+ item.title
938
1136
  ))
939
1137
  ]
940
1138
  }
941
1139
  ),
942
- /* @__PURE__ */ b(
943
- je,
1140
+ /* @__PURE__ */ jsxs(
1141
+ EditorBubble,
944
1142
  {
945
1143
  tippyOptions: {
946
1144
  placement: "top"
947
1145
  },
948
- 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),
949
1147
  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, {})
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, {})
955
1153
  ]
956
1154
  }
957
1155
  )
@@ -959,14 +1157,14 @@ const At = B.create({
959
1157
  }
960
1158
  )
961
1159
  }
962
- ) }) }) : null;
1160
+ ) }) });
963
1161
  };
964
- function Lt(e) {
965
- const o = /!\[.*?\]\(.*?\)/g;
966
- return e.replace(o, (t) => `${t}
1162
+ function addLineBreakAfterImages(markdown) {
1163
+ const imageRegex = /!\[.*?\]\(.*?\)/g;
1164
+ return markdown.replace(imageRegex, (match) => `${match}
967
1165
  `);
968
1166
  }
969
- const Tt = `
1167
+ const cssStyles = `
970
1168
 
971
1169
  .ProseMirror .is-editor-empty:first-child::before {
972
1170
  content: attr(data-placeholder);
@@ -1158,6 +1356,6 @@ ul[data-type="taskList"] li[data-checked="true"] > div > p {
1158
1356
  }
1159
1357
  `;
1160
1358
  export {
1161
- eo as FireCMSEditor
1359
+ FireCMSEditor
1162
1360
  };
1163
1361
  //# sourceMappingURL=index.es.js.map