your personal website on atproto - mirror
blento.app
1import { Node, mergeAttributes } from '@tiptap/core';
2import { SvelteNodeViewRenderer } from 'svelte-tiptap';
3
4import ImageUploadComponent from './ImageUploadComponent.svelte';
5
6export type UploadFunction = (
7 file: File,
8 onProgress?: (event: { progress: number }) => void,
9 abortSignal?: AbortSignal
10) => Promise<string>;
11
12export interface ImageUploadNodeOptions {
13 /**
14 * Acceptable file types for upload.
15 * @default 'image/*'
16 */
17 accept?: string;
18 /**
19 * Maximum number of files that can be uploaded.
20 * @default 1
21 */
22 limit?: number;
23 /**
24 * Maximum file size in bytes (0 for unlimited).
25 * @default 0
26 */
27 maxSize?: number;
28
29 /**
30 * Preview image URL.
31 */
32 preview?: string;
33 /**
34 * Function to handle the upload process.
35 */
36 upload?: UploadFunction;
37 /**
38 * Callback for upload errors.
39 */
40 onError?: (error: Error) => void;
41 /**
42 * Callback for successful uploads.
43 */
44 onSuccess?: (url: string) => void;
45}
46
47declare module '@tiptap/core' {
48 interface Commands<ReturnType> {
49 imageUpload: {
50 setImageUploadNode: (options?: ImageUploadNodeOptions) => ReturnType;
51 };
52 }
53}
54
55export const ImageUploadNode = Node.create<ImageUploadNodeOptions>({
56 name: 'imageUpload',
57 group: 'block',
58 atom: true,
59 draggable: true,
60 selectable: false,
61 inline: false,
62
63 addAttributes() {
64 return {
65 accept: {
66 default: this.options.accept
67 },
68 limit: {
69 default: this.options.limit
70 },
71 maxSize: {
72 default: this.options.maxSize
73 },
74 preview: {
75 default: this.options.preview
76 }
77 };
78 },
79
80 addOptions() {
81 return {
82 accept: 'image/*',
83 limit: 1,
84 maxSize: 0,
85 upload: undefined,
86 onError: undefined,
87 onSuccess: undefined
88 };
89 },
90
91 addCommands() {
92 return {
93 setImageUploadNode:
94 (options = {}) =>
95 ({ commands }) => {
96 return commands.insertContent({
97 type: this.name,
98 attrs: options
99 });
100 }
101 };
102 },
103
104 parseHTML() {
105 return [{ tag: 'div[data-type="image-upload"]' }];
106 },
107
108 renderHTML({ HTMLAttributes }) {
109 return ['div', mergeAttributes({ 'data-type': 'image-upload' }, HTMLAttributes)];
110 },
111
112 addNodeView() {
113 return SvelteNodeViewRenderer(ImageUploadComponent);
114 }
115});