@kopexa/tiptap 17.2.0 → 17.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/dist/{chunk-E5NW3MJZ.mjs → chunk-3ZPLSXTZ.mjs} +3 -3
  2. package/dist/{chunk-7SRL3P4B.mjs → chunk-5QFCLKHL.mjs} +7 -7
  3. package/dist/{chunk-NEHW62L7.mjs → chunk-6552DQWB.mjs} +2 -2
  4. package/dist/{chunk-5GFFTVMZ.mjs → chunk-DSBJFMHK.mjs} +4 -28
  5. package/dist/chunk-EAAQE5ZV.mjs +283 -0
  6. package/dist/chunk-HTJ2RXOG.mjs +32 -0
  7. package/dist/{chunk-LMCQMSW2.mjs → chunk-KYLBKQ2E.mjs} +12 -154
  8. package/dist/chunk-N3JE67CS.mjs +81 -0
  9. package/dist/{chunk-UU6JK5HX.mjs → chunk-SSJMKQ5G.mjs} +33 -20
  10. package/dist/chunk-Z365KVQY.mjs +34 -0
  11. package/dist/extensions/image/image-view.d.mts +3 -3
  12. package/dist/extensions/image/image-view.d.ts +3 -3
  13. package/dist/extensions/image/image-view.js +13 -181
  14. package/dist/extensions/image/image-view.mjs +2 -2
  15. package/dist/extensions/image/index.d.mts +12 -49
  16. package/dist/extensions/image/index.d.ts +12 -49
  17. package/dist/extensions/image/index.js +18 -231
  18. package/dist/extensions/image/index.mjs +3 -3
  19. package/dist/extensions/image/messages.d.mts +2 -30
  20. package/dist/extensions/image/messages.d.ts +2 -30
  21. package/dist/extensions/image/messages.js +4 -32
  22. package/dist/extensions/image/messages.mjs +1 -1
  23. package/dist/extensions/image-upload/image-upload-view.d.mts +12 -0
  24. package/dist/extensions/image-upload/image-upload-view.d.ts +12 -0
  25. package/dist/extensions/image-upload/image-upload-view.js +338 -0
  26. package/dist/extensions/image-upload/image-upload-view.mjs +12 -0
  27. package/dist/extensions/image-upload/index.d.mts +46 -0
  28. package/dist/extensions/image-upload/index.d.ts +46 -0
  29. package/dist/extensions/image-upload/index.js +414 -0
  30. package/dist/extensions/image-upload/index.mjs +16 -0
  31. package/dist/extensions/image-upload/messages.d.mts +32 -0
  32. package/dist/extensions/image-upload/messages.d.ts +32 -0
  33. package/dist/extensions/image-upload/messages.js +61 -0
  34. package/dist/extensions/image-upload/messages.mjs +7 -0
  35. package/dist/extensions/math/index.mjs +1 -1
  36. package/dist/hooks/use-create-editor.js +562 -393
  37. package/dist/hooks/use-create-editor.mjs +13 -10
  38. package/dist/index.d.mts +4 -1
  39. package/dist/index.d.ts +4 -1
  40. package/dist/index.js +956 -785
  41. package/dist/index.mjs +39 -33
  42. package/dist/presets/basic/editor-header.mjs +14 -14
  43. package/dist/presets/basic/index.js +953 -784
  44. package/dist/presets/basic/index.mjs +32 -29
  45. package/dist/ui/slash-dropdown-menu/index.js +2 -2
  46. package/dist/ui/slash-dropdown-menu/index.mjs +4 -4
  47. package/dist/ui/slash-dropdown-menu/slash-dropdown-menu.js +2 -2
  48. package/dist/ui/slash-dropdown-menu/slash-dropdown-menu.mjs +2 -2
  49. package/dist/ui/slash-dropdown-menu/use-slash-dropdown-menu.js +2 -2
  50. package/dist/ui/slash-dropdown-menu/use-slash-dropdown-menu.mjs +1 -1
  51. package/package.json +25 -24
  52. package/dist/chunk-WAAH3NLG.mjs +0 -77
  53. package/dist/{chunk-QAE2D4KV.mjs → chunk-FDPXD6VC.mjs} +11 -11
@@ -1,13 +1,13 @@
1
1
  "use client";
2
+ import {
3
+ useSlashDropdownMenu
4
+ } from "./chunk-6552DQWB.mjs";
2
5
  import {
3
6
  SuggestionMenu
4
7
  } from "./chunk-ZYFCSR3E.mjs";
5
8
  import {
6
9
  filterSuggestionItems
7
10
  } from "./chunk-CNVACBGT.mjs";
8
- import {
9
- useSlashDropdownMenu
10
- } from "./chunk-NEHW62L7.mjs";
11
11
 
12
12
  // src/ui/slash-dropdown-menu/slash-dropdown-menu.tsx
13
13
  import { Button } from "@kopexa/button";
@@ -1,19 +1,19 @@
1
1
  "use client";
2
2
  import {
3
3
  SlashDropdownMenu
4
- } from "./chunk-E5NW3MJZ.mjs";
5
- import {
6
- LinkBubble
7
- } from "./chunk-XNDXYI2N.mjs";
4
+ } from "./chunk-3ZPLSXTZ.mjs";
8
5
  import {
9
6
  useScrollToHash
10
7
  } from "./chunk-DZLGLP7R.mjs";
11
8
  import {
12
- EditorHeader
13
- } from "./chunk-QAE2D4KV.mjs";
9
+ LinkBubble
10
+ } from "./chunk-XNDXYI2N.mjs";
14
11
  import {
15
12
  BubbleMenu
16
13
  } from "./chunk-NSYSECKW.mjs";
14
+ import {
15
+ EditorHeader
16
+ } from "./chunk-FDPXD6VC.mjs";
17
17
  import {
18
18
  useUiEditorState
19
19
  } from "./chunk-BXJYNSWQ.mjs";
@@ -22,7 +22,7 @@ import {
22
22
  } from "./chunk-REJEJXOZ.mjs";
23
23
  import {
24
24
  useCreateEditor
25
- } from "./chunk-UU6JK5HX.mjs";
25
+ } from "./chunk-SSJMKQ5G.mjs";
26
26
 
27
27
  // src/presets/basic/index.tsx
28
28
  import {
@@ -349,9 +349,9 @@ Continue writing from where the text above ends. Write ONLY ONE SENTENCE. DONT R
349
349
  },
350
350
  // Upload
351
351
  image: {
352
- check: (editor) => isNodeInSchema("image", editor),
352
+ check: (editor) => isNodeInSchema("imageUpload", editor),
353
353
  action: ({ editor }) => {
354
- editor.chain().focus().setImage({ src: "" }).run();
354
+ editor.chain().focus().setImageUpload().run();
355
355
  }
356
356
  }
357
357
  };
@@ -1,16 +1,8 @@
1
1
  "use client";
2
2
 
3
- // src/extensions/image/messages.ts
3
+ // src/extensions/image-upload/messages.ts
4
4
  import { defineMessages } from "react-intl";
5
5
  var messages = defineMessages({
6
- loading: {
7
- id: "editor.image.loading",
8
- defaultMessage: "Loading image..."
9
- },
10
- error: {
11
- id: "editor.image.error",
12
- defaultMessage: "Failed to load image"
13
- },
14
6
  upload_error: {
15
7
  id: "editor.image.upload_error",
16
8
  defaultMessage: "Failed to upload image"
@@ -27,30 +19,14 @@ var messages = defineMessages({
27
19
  id: "editor.image.upload_hint",
28
20
  defaultMessage: "PNG, JPG, GIF, WebP, SVG"
29
21
  },
30
- alt_text: {
31
- id: "editor.image.alt_text",
32
- defaultMessage: "Alt text"
33
- },
34
- alt_placeholder: {
35
- id: "editor.image.alt_placeholder",
36
- defaultMessage: "Describe the image..."
22
+ click_to_retry: {
23
+ id: "editor.image.click_to_retry",
24
+ defaultMessage: "Click to try again"
37
25
  },
38
26
  files_not_supported: {
39
27
  id: "editor.image.files_not_supported",
40
28
  defaultMessage: "File upload is not configured"
41
29
  },
42
- file_too_large: {
43
- id: "editor.image.file_too_large",
44
- defaultMessage: "File is too large (max {maxSize})"
45
- },
46
- invalid_type: {
47
- id: "editor.image.invalid_type",
48
- defaultMessage: "Invalid file type"
49
- },
50
- retry: {
51
- id: "editor.image.retry",
52
- defaultMessage: "Retry"
53
- },
54
30
  remove: {
55
31
  id: "editor.image.remove",
56
32
  defaultMessage: "Remove"
@@ -0,0 +1,283 @@
1
+ "use client";
2
+ import {
3
+ messages
4
+ } from "./chunk-DSBJFMHK.mjs";
5
+ import {
6
+ useEditorFile
7
+ } from "./chunk-VRQ6OSAZ.mjs";
8
+
9
+ // src/extensions/image-upload/image-upload-view.tsx
10
+ import { IconButton } from "@kopexa/button";
11
+ import {
12
+ AlertCircleIcon,
13
+ ImageIcon,
14
+ TrashIcon,
15
+ UploadIcon
16
+ } from "@kopexa/icons";
17
+ import { imagePlaceholder } from "@kopexa/theme";
18
+ import {
19
+ NodeViewWrapper,
20
+ useEditorState
21
+ } from "@tiptap/react";
22
+ import { useCallback, useMemo, useRef, useState } from "react";
23
+ import { useIntl } from "react-intl";
24
+ import { jsx, jsxs } from "react/jsx-runtime";
25
+ function ImageUploadNodeView({ editor, node, getPos }) {
26
+ const intl = useIntl();
27
+ const fileHandler = useEditorFile();
28
+ const isEditable = useEditorState({
29
+ editor,
30
+ selector: ({ editor: e }) => {
31
+ var _a;
32
+ return (_a = e == null ? void 0 : e.isEditable) != null ? _a : false;
33
+ }
34
+ });
35
+ const [uploadState, setUploadState] = useState("idle");
36
+ const [uploadProgress, setUploadProgress] = useState(0);
37
+ const [isDragOver, setIsDragOver] = useState(false);
38
+ const fileInputRef = useRef(null);
39
+ const handleRemove = useCallback(() => {
40
+ const pos = getPos();
41
+ if (pos === void 0) return;
42
+ editor.commands.deleteRange({
43
+ from: pos,
44
+ to: pos + node.nodeSize
45
+ });
46
+ }, [editor, getPos, node.nodeSize]);
47
+ const handleFileSelect = useCallback(
48
+ async (file) => {
49
+ if (!fileHandler) return;
50
+ const pos = getPos();
51
+ if (pos === void 0) return;
52
+ setUploadState("uploading");
53
+ setUploadProgress(0);
54
+ try {
55
+ const ref = await fileHandler.upload(file, (percent) => {
56
+ setUploadProgress(percent);
57
+ });
58
+ const currentPos = getPos();
59
+ if (currentPos === void 0) return;
60
+ editor.chain().focus().deleteRange({ from: currentPos, to: currentPos + node.nodeSize }).insertContentAt(currentPos, {
61
+ type: "image",
62
+ attrs: {
63
+ src: ref,
64
+ alt: file.name.replace(/\.[^/.]+$/, ""),
65
+ title: file.name.replace(/\.[^/.]+$/, "")
66
+ }
67
+ }).run();
68
+ } catch (error) {
69
+ console.error("[ImageUpload] Upload failed:", error);
70
+ setUploadState("error");
71
+ setUploadProgress(0);
72
+ }
73
+ },
74
+ [fileHandler, editor, getPos, node.nodeSize]
75
+ );
76
+ const handleInputChange = useCallback(
77
+ (e) => {
78
+ var _a;
79
+ const file = (_a = e.target.files) == null ? void 0 : _a[0];
80
+ if (file) {
81
+ handleFileSelect(file);
82
+ }
83
+ e.target.value = "";
84
+ },
85
+ [handleFileSelect]
86
+ );
87
+ const handleDrop = useCallback(
88
+ (e) => {
89
+ e.preventDefault();
90
+ e.stopPropagation();
91
+ setIsDragOver(false);
92
+ const file = e.dataTransfer.files[0];
93
+ if (file == null ? void 0 : file.type.startsWith("image/")) {
94
+ handleFileSelect(file);
95
+ }
96
+ },
97
+ [handleFileSelect]
98
+ );
99
+ const handleDragOver = useCallback((e) => {
100
+ e.preventDefault();
101
+ e.stopPropagation();
102
+ }, []);
103
+ const handleDragEnter = useCallback((e) => {
104
+ e.preventDefault();
105
+ e.stopPropagation();
106
+ setIsDragOver(true);
107
+ }, []);
108
+ const handleDragLeave = useCallback((e) => {
109
+ e.preventDefault();
110
+ e.stopPropagation();
111
+ if (!e.currentTarget.contains(e.relatedTarget)) {
112
+ setIsDragOver(false);
113
+ }
114
+ }, []);
115
+ const handleClick = useCallback(() => {
116
+ var _a;
117
+ if (uploadState === "idle" || uploadState === "error") {
118
+ (_a = fileInputRef.current) == null ? void 0 : _a.click();
119
+ }
120
+ }, [uploadState]);
121
+ const styles = useMemo(
122
+ () => imagePlaceholder({
123
+ size: "md",
124
+ variant: isDragOver ? "default" : void 0
125
+ }),
126
+ [isDragOver]
127
+ );
128
+ const errorStyles = useMemo(
129
+ () => imagePlaceholder({ size: "md", variant: "error" }),
130
+ []
131
+ );
132
+ const uploadingStyles = useMemo(
133
+ () => imagePlaceholder({ size: "md", variant: "uploading" }),
134
+ []
135
+ );
136
+ const disabledStyles = useMemo(
137
+ () => imagePlaceholder({ size: "md", variant: "disabled" }),
138
+ []
139
+ );
140
+ if (!fileHandler) {
141
+ return /* @__PURE__ */ jsx(NodeViewWrapper, { className: "my-4", "data-type": "image-upload", children: /* @__PURE__ */ jsx("div", { className: disabledStyles.root(), children: /* @__PURE__ */ jsxs("div", { className: disabledStyles.content(), children: [
142
+ /* @__PURE__ */ jsx(ImageIcon, { className: disabledStyles.icon() }),
143
+ /* @__PURE__ */ jsx("span", { className: disabledStyles.text(), children: intl.formatMessage(messages.files_not_supported) }),
144
+ isEditable && /* @__PURE__ */ jsx(
145
+ IconButton,
146
+ {
147
+ size: "sm",
148
+ variant: "ghost",
149
+ onClick: handleRemove,
150
+ "aria-label": intl.formatMessage(messages.remove),
151
+ children: /* @__PURE__ */ jsx(TrashIcon, { className: "size-4" })
152
+ }
153
+ )
154
+ ] }) }) });
155
+ }
156
+ if (uploadState === "uploading") {
157
+ return /* @__PURE__ */ jsx(NodeViewWrapper, { className: "my-4", "data-type": "image-upload", children: /* @__PURE__ */ jsx("div", { className: uploadingStyles.root(), children: /* @__PURE__ */ jsxs("div", { className: uploadingStyles.content(), children: [
158
+ /* @__PURE__ */ jsxs("div", { className: "relative size-12", children: [
159
+ /* @__PURE__ */ jsxs(
160
+ "svg",
161
+ {
162
+ className: "size-12 -rotate-90",
163
+ viewBox: "0 0 36 36",
164
+ "aria-hidden": "true",
165
+ children: [
166
+ /* @__PURE__ */ jsx(
167
+ "circle",
168
+ {
169
+ cx: "18",
170
+ cy: "18",
171
+ r: "16",
172
+ fill: "none",
173
+ className: "stroke-muted",
174
+ strokeWidth: "2"
175
+ }
176
+ ),
177
+ /* @__PURE__ */ jsx(
178
+ "circle",
179
+ {
180
+ cx: "18",
181
+ cy: "18",
182
+ r: "16",
183
+ fill: "none",
184
+ className: "stroke-primary",
185
+ strokeWidth: "2",
186
+ strokeDasharray: 100,
187
+ strokeDashoffset: 100 - uploadProgress,
188
+ strokeLinecap: "round"
189
+ }
190
+ )
191
+ ]
192
+ }
193
+ ),
194
+ /* @__PURE__ */ jsxs("span", { className: "absolute inset-0 flex items-center justify-center text-xs font-medium", children: [
195
+ uploadProgress,
196
+ "%"
197
+ ] })
198
+ ] }),
199
+ /* @__PURE__ */ jsx("span", { className: uploadingStyles.text(), children: intl.formatMessage(messages.uploading) })
200
+ ] }) }) });
201
+ }
202
+ if (uploadState === "error") {
203
+ return /* @__PURE__ */ jsx(NodeViewWrapper, { className: "my-4", "data-type": "image-upload", children: /* @__PURE__ */ jsxs("div", { className: errorStyles.root(), onClick: handleClick, children: [
204
+ /* @__PURE__ */ jsxs("div", { className: errorStyles.content(), children: [
205
+ /* @__PURE__ */ jsx(AlertCircleIcon, { className: errorStyles.icon() }),
206
+ /* @__PURE__ */ jsx("span", { className: errorStyles.text(), children: intl.formatMessage(messages.upload_error) }),
207
+ /* @__PURE__ */ jsx("span", { className: errorStyles.hint(), children: intl.formatMessage(messages.click_to_retry) })
208
+ ] }),
209
+ /* @__PURE__ */ jsx(
210
+ "input",
211
+ {
212
+ ref: fileInputRef,
213
+ type: "file",
214
+ accept: "image/*",
215
+ className: "hidden",
216
+ onChange: handleInputChange
217
+ }
218
+ ),
219
+ isEditable && /* @__PURE__ */ jsx(
220
+ IconButton,
221
+ {
222
+ size: "sm",
223
+ variant: "ghost",
224
+ className: errorStyles.removeButton(),
225
+ onClick: (e) => {
226
+ e.stopPropagation();
227
+ handleRemove();
228
+ },
229
+ "aria-label": intl.formatMessage(messages.remove),
230
+ children: /* @__PURE__ */ jsx(TrashIcon, { className: "size-3.5" })
231
+ }
232
+ )
233
+ ] }) });
234
+ }
235
+ return /* @__PURE__ */ jsx(NodeViewWrapper, { className: "my-4", "data-type": "image-upload", children: /* @__PURE__ */ jsxs(
236
+ "div",
237
+ {
238
+ className: `${styles.root()} ${isDragOver ? "border-primary bg-primary/10" : ""}`,
239
+ onClick: handleClick,
240
+ onDrop: handleDrop,
241
+ onDragOver: handleDragOver,
242
+ onDragEnter: handleDragEnter,
243
+ onDragLeave: handleDragLeave,
244
+ children: [
245
+ /* @__PURE__ */ jsxs("div", { className: styles.content(), children: [
246
+ /* @__PURE__ */ jsx(UploadIcon, { className: styles.icon() }),
247
+ /* @__PURE__ */ jsx("span", { className: styles.text(), children: intl.formatMessage(messages.upload_placeholder) }),
248
+ /* @__PURE__ */ jsx("span", { className: styles.hint(), children: intl.formatMessage(messages.upload_hint) })
249
+ ] }),
250
+ /* @__PURE__ */ jsx(
251
+ "input",
252
+ {
253
+ ref: fileInputRef,
254
+ type: "file",
255
+ accept: "image/*",
256
+ className: "hidden",
257
+ onChange: handleInputChange
258
+ }
259
+ ),
260
+ isEditable && /* @__PURE__ */ jsx(
261
+ IconButton,
262
+ {
263
+ size: "sm",
264
+ variant: "ghost",
265
+ className: styles.removeButton(),
266
+ onClick: (e) => {
267
+ e.stopPropagation();
268
+ handleRemove();
269
+ },
270
+ "aria-label": intl.formatMessage(messages.remove),
271
+ children: /* @__PURE__ */ jsx(TrashIcon, { className: "size-3.5" })
272
+ }
273
+ )
274
+ ]
275
+ }
276
+ ) });
277
+ }
278
+ var image_upload_view_default = ImageUploadNodeView;
279
+
280
+ export {
281
+ ImageUploadNodeView,
282
+ image_upload_view_default
283
+ };
@@ -0,0 +1,32 @@
1
+ "use client";
2
+ import {
3
+ ImageNodeView
4
+ } from "./chunk-KYLBKQ2E.mjs";
5
+
6
+ // src/extensions/image/index.ts
7
+ import { Image as TiptapImage } from "@tiptap/extension-image";
8
+ import { ReactNodeViewRenderer } from "@tiptap/react";
9
+ var ImageNode = TiptapImage.extend({
10
+ addAttributes() {
11
+ var _a;
12
+ return {
13
+ ...(_a = this.parent) == null ? void 0 : _a.call(this),
14
+ // Upload state for drag & drop / paste uploads
15
+ uploadState: {
16
+ default: null,
17
+ rendered: false
18
+ },
19
+ uploadProgress: {
20
+ default: null,
21
+ rendered: false
22
+ }
23
+ };
24
+ },
25
+ addNodeView() {
26
+ return ReactNodeViewRenderer(ImageNodeView);
27
+ }
28
+ });
29
+
30
+ export {
31
+ ImageNode
32
+ };
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
  import {
3
3
  messages
4
- } from "./chunk-5GFFTVMZ.mjs";
4
+ } from "./chunk-Z365KVQY.mjs";
5
5
  import {
6
6
  useEditorFile
7
7
  } from "./chunk-VRQ6OSAZ.mjs";
@@ -11,23 +11,21 @@ import { IconButton } from "@kopexa/button";
11
11
  import {
12
12
  AlertCircleIcon,
13
13
  ArrowCounterClockwiseIcon,
14
- ImageIcon,
15
- TrashIcon,
16
- UploadIcon
14
+ TrashIcon
17
15
  } from "@kopexa/icons";
18
16
  import { imagePlaceholder } from "@kopexa/theme";
19
17
  import {
20
18
  NodeViewWrapper,
21
19
  useEditorState
22
20
  } from "@tiptap/react";
23
- import { useCallback, useEffect, useMemo, useRef, useState } from "react";
21
+ import { useCallback, useEffect, useMemo, useState } from "react";
24
22
  import { useIntl } from "react-intl";
25
23
  import { jsx, jsxs } from "react/jsx-runtime";
26
24
  function ImageNodeView({ editor, node, getPos }) {
27
25
  var _a;
28
26
  const intl = useIntl();
29
27
  const fileHandler = useEditorFile();
30
- const attrs = node.attrs;
28
+ const { src, alt, title, uploadState, uploadProgress } = node.attrs;
31
29
  const isEditable = useEditorState({
32
30
  editor,
33
31
  selector: ({ editor: e }) => {
@@ -35,7 +33,6 @@ function ImageNodeView({ editor, node, getPos }) {
35
33
  return (_a2 = e == null ? void 0 : e.isEditable) != null ? _a2 : false;
36
34
  }
37
35
  });
38
- const { src, alt, title, uploadState, uploadProgress } = attrs;
39
36
  const [resolvedUrl, setResolvedUrl] = useState(null);
40
37
  const [resolveState, setResolveState] = useState("idle");
41
38
  const needsResolve = (_a = fileHandler == null ? void 0 : fileHandler.isReference(src)) != null ? _a : false;
@@ -47,7 +44,8 @@ function ImageNodeView({ editor, node, getPos }) {
47
44
  return;
48
45
  }
49
46
  if (!fileHandler) {
50
- setResolveState("error");
47
+ setResolvedUrl(src);
48
+ setResolveState("resolved");
51
49
  return;
52
50
  }
53
51
  setResolveState("loading");
@@ -73,156 +71,16 @@ function ImageNodeView({ editor, node, getPos }) {
73
71
  to: pos + node.nodeSize
74
72
  });
75
73
  }, [editor, getPos, node.nodeSize]);
76
- const fileInputRef = useRef(null);
77
- const handleFileSelect = useCallback(
78
- async (file) => {
79
- if (!fileHandler) return;
80
- const pos = getPos();
81
- if (pos === void 0) return;
82
- editor.view.dispatch(
83
- editor.state.tr.setNodeMarkup(pos, void 0, {
84
- ...attrs,
85
- uploadState: "uploading",
86
- uploadProgress: 0
87
- })
88
- );
89
- try {
90
- const ref = await fileHandler.upload(file, (percent) => {
91
- const currentPos = getPos();
92
- if (currentPos === void 0) return;
93
- editor.view.dispatch(
94
- editor.state.tr.setNodeMarkup(currentPos, void 0, {
95
- ...attrs,
96
- uploadState: "uploading",
97
- uploadProgress: percent
98
- })
99
- );
100
- });
101
- const finalPos = getPos();
102
- if (finalPos === void 0) return;
103
- editor.view.dispatch(
104
- editor.state.tr.setNodeMarkup(finalPos, void 0, {
105
- src: ref,
106
- uploadState: null,
107
- uploadProgress: null
108
- })
109
- );
110
- } catch {
111
- const errorPos = getPos();
112
- if (errorPos === void 0) return;
113
- editor.view.dispatch(
114
- editor.state.tr.setNodeMarkup(errorPos, void 0, {
115
- ...attrs,
116
- uploadState: "error",
117
- uploadProgress: null
118
- })
119
- );
120
- }
121
- },
122
- [fileHandler, editor, getPos, attrs]
123
- );
124
- const handleInputChange = useCallback(
125
- (e) => {
126
- var _a2;
127
- const file = (_a2 = e.target.files) == null ? void 0 : _a2[0];
128
- if (file) {
129
- handleFileSelect(file);
130
- }
131
- },
132
- [handleFileSelect]
133
- );
134
- const handleDrop = useCallback(
135
- (e) => {
136
- e.preventDefault();
137
- e.stopPropagation();
138
- const file = e.dataTransfer.files[0];
139
- if (file == null ? void 0 : file.type.startsWith("image/")) {
140
- handleFileSelect(file);
141
- }
142
- },
143
- [handleFileSelect]
144
- );
145
- const handleDragOver = useCallback((e) => {
146
- e.preventDefault();
147
- e.stopPropagation();
148
- }, []);
149
- const styles = useMemo(() => imagePlaceholder({ size: "md" }), []);
150
74
  const errorStyles = useMemo(
151
75
  () => imagePlaceholder({ size: "md", variant: "error" }),
152
76
  []
153
77
  );
154
- const uploadingStyles = useMemo(
78
+ const loadingStyles = useMemo(
155
79
  () => imagePlaceholder({ size: "md", variant: "uploading" }),
156
80
  []
157
81
  );
158
- const disabledStyles = useMemo(
159
- () => imagePlaceholder({ size: "md", variant: "disabled" }),
160
- []
161
- );
162
- const isEmpty = !src;
163
- if (isEmpty && !uploadState) {
164
- if (!fileHandler) {
165
- return /* @__PURE__ */ jsx(NodeViewWrapper, { className: "my-4", "data-type": "image", children: /* @__PURE__ */ jsx("div", { className: disabledStyles.root(), children: /* @__PURE__ */ jsxs("div", { className: disabledStyles.content(), children: [
166
- /* @__PURE__ */ jsx(ImageIcon, { className: disabledStyles.icon() }),
167
- /* @__PURE__ */ jsx("span", { className: disabledStyles.text(), children: intl.formatMessage(messages.files_not_supported) }),
168
- isEditable && /* @__PURE__ */ jsx(
169
- IconButton,
170
- {
171
- size: "sm",
172
- variant: "ghost",
173
- onClick: handleRemove,
174
- "aria-label": intl.formatMessage(messages.remove),
175
- children: /* @__PURE__ */ jsx(TrashIcon, { className: "size-4" })
176
- }
177
- )
178
- ] }) }) });
179
- }
180
- return /* @__PURE__ */ jsx(NodeViewWrapper, { className: "my-4", "data-type": "image", children: /* @__PURE__ */ jsxs(
181
- "div",
182
- {
183
- className: styles.root(),
184
- onClick: () => {
185
- var _a2;
186
- return (_a2 = fileInputRef.current) == null ? void 0 : _a2.click();
187
- },
188
- onDrop: handleDrop,
189
- onDragOver: handleDragOver,
190
- children: [
191
- /* @__PURE__ */ jsxs("div", { className: styles.content(), children: [
192
- /* @__PURE__ */ jsx(UploadIcon, { className: styles.icon() }),
193
- /* @__PURE__ */ jsx("span", { className: styles.text(), children: intl.formatMessage(messages.upload_placeholder) }),
194
- /* @__PURE__ */ jsx("span", { className: styles.hint(), children: intl.formatMessage(messages.upload_hint) })
195
- ] }),
196
- /* @__PURE__ */ jsx(
197
- "input",
198
- {
199
- ref: fileInputRef,
200
- type: "file",
201
- accept: "image/*",
202
- className: "hidden",
203
- onChange: handleInputChange
204
- }
205
- ),
206
- isEditable && /* @__PURE__ */ jsx(
207
- IconButton,
208
- {
209
- size: "sm",
210
- variant: "ghost",
211
- className: styles.removeButton(),
212
- onClick: (e) => {
213
- e.stopPropagation();
214
- handleRemove();
215
- },
216
- "aria-label": intl.formatMessage(messages.remove),
217
- children: /* @__PURE__ */ jsx(TrashIcon, { className: "size-3.5" })
218
- }
219
- )
220
- ]
221
- }
222
- ) });
223
- }
224
82
  if (uploadState === "uploading") {
225
- return /* @__PURE__ */ jsx(NodeViewWrapper, { className: "my-4", "data-type": "image", children: /* @__PURE__ */ jsx("div", { className: uploadingStyles.root(), children: /* @__PURE__ */ jsxs("div", { className: uploadingStyles.content(), children: [
83
+ return /* @__PURE__ */ jsx(NodeViewWrapper, { className: "my-4", "data-type": "image", children: /* @__PURE__ */ jsx("div", { className: loadingStyles.root(), children: /* @__PURE__ */ jsxs("div", { className: loadingStyles.content(), children: [
226
84
  /* @__PURE__ */ jsxs("div", { className: "relative size-12", children: [
227
85
  /* @__PURE__ */ jsxs(
228
86
  "svg",
@@ -264,14 +122,14 @@ function ImageNodeView({ editor, node, getPos }) {
264
122
  "%"
265
123
  ] })
266
124
  ] }),
267
- /* @__PURE__ */ jsx("span", { className: uploadingStyles.text(), children: intl.formatMessage(messages.uploading) })
125
+ /* @__PURE__ */ jsx("span", { className: loadingStyles.text(), children: intl.formatMessage(messages.uploading) })
268
126
  ] }) }) });
269
127
  }
270
128
  if (uploadState === "error") {
271
129
  return /* @__PURE__ */ jsx(NodeViewWrapper, { className: "my-4", "data-type": "image", children: /* @__PURE__ */ jsx("div", { className: errorStyles.root(), children: /* @__PURE__ */ jsxs("div", { className: errorStyles.content(), children: [
272
130
  /* @__PURE__ */ jsx(AlertCircleIcon, { className: errorStyles.icon() }),
273
131
  /* @__PURE__ */ jsx("span", { className: errorStyles.text(), children: intl.formatMessage(messages.upload_error) }),
274
- isEditable && /* @__PURE__ */ jsx("div", { className: "flex gap-2", children: /* @__PURE__ */ jsx(
132
+ isEditable && /* @__PURE__ */ jsx(
275
133
  IconButton,
276
134
  {
277
135
  size: "sm",
@@ -280,11 +138,11 @@ function ImageNodeView({ editor, node, getPos }) {
280
138
  "aria-label": intl.formatMessage(messages.remove),
281
139
  children: /* @__PURE__ */ jsx(TrashIcon, { className: "size-4" })
282
140
  }
283
- ) })
141
+ )
284
142
  ] }) }) });
285
143
  }
286
144
  if (resolveState === "loading") {
287
- return /* @__PURE__ */ jsx(NodeViewWrapper, { className: "my-4", "data-type": "image", children: /* @__PURE__ */ jsx("div", { className: `${uploadingStyles.root()} animate-pulse`, children: /* @__PURE__ */ jsx("span", { className: uploadingStyles.text(), children: intl.formatMessage(messages.loading) }) }) });
145
+ return /* @__PURE__ */ jsx(NodeViewWrapper, { className: "my-4", "data-type": "image", children: /* @__PURE__ */ jsx("div", { className: `${loadingStyles.root()} animate-pulse`, children: /* @__PURE__ */ jsx("span", { className: loadingStyles.text(), children: intl.formatMessage(messages.loading) }) }) });
288
146
  }
289
147
  if (resolveState === "error") {
290
148
  return /* @__PURE__ */ jsx(NodeViewWrapper, { className: "my-4", "data-type": "image", children: /* @__PURE__ */ jsx("div", { className: errorStyles.root(), children: /* @__PURE__ */ jsxs("div", { className: errorStyles.content(), children: [