tiptap-editor-custom-stg 1.0.0

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.js ADDED
@@ -0,0 +1,1336 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/index.ts
31
+ var index_exports = {};
32
+ __export(index_exports, {
33
+ BackgroundColor: () => BackgroundColor,
34
+ FONT_FAMILIES: () => FONT_FAMILIES,
35
+ FONT_SIZES: () => FONT_SIZES,
36
+ FontSize: () => FontSize,
37
+ IMAGE_MIME_TYPES: () => IMAGE_MIME_TYPES,
38
+ TIPTAP_COLORS: () => TIPTAP_COLORS,
39
+ TiptapEditor: () => TiptapEditor_default,
40
+ createTiptapExtensions: () => createTiptapExtensions
41
+ });
42
+ module.exports = __toCommonJS(index_exports);
43
+
44
+ // src/TiptapEditor.tsx
45
+ var import_react = __toESM(require("react"));
46
+ var import_react2 = require("@tiptap/react");
47
+
48
+ // src/extensions.ts
49
+ var import_starter_kit = __toESM(require("@tiptap/starter-kit"));
50
+ var import_extension_image = __toESM(require("@tiptap/extension-image"));
51
+ var import_extension_link = __toESM(require("@tiptap/extension-link"));
52
+ var import_extension_underline = __toESM(require("@tiptap/extension-underline"));
53
+ var import_extension_text_style3 = require("@tiptap/extension-text-style");
54
+ var import_extension_font_family = __toESM(require("@tiptap/extension-font-family"));
55
+ var import_extension_color = require("@tiptap/extension-color");
56
+ var import_extension_superscript = __toESM(require("@tiptap/extension-superscript"));
57
+ var import_extension_subscript = __toESM(require("@tiptap/extension-subscript"));
58
+ var import_extension_text_align = __toESM(require("@tiptap/extension-text-align"));
59
+ var import_extension_placeholder = __toESM(require("@tiptap/extension-placeholder"));
60
+ var import_extension_table = require("@tiptap/extension-table");
61
+ var import_extension_table_row = require("@tiptap/extension-table-row");
62
+ var import_extension_table_header = __toESM(require("@tiptap/extension-table-header"));
63
+ var import_extension_table_cell = require("@tiptap/extension-table-cell");
64
+
65
+ // src/fontSize.ts
66
+ var import_core = require("@tiptap/core");
67
+ var import_extension_text_style = require("@tiptap/extension-text-style");
68
+ var FontSize = import_core.Extension.create({
69
+ name: "fontSize",
70
+ addOptions() {
71
+ return {
72
+ types: ["textStyle"]
73
+ };
74
+ },
75
+ addGlobalAttributes() {
76
+ return [
77
+ {
78
+ types: this.options.types,
79
+ attributes: {
80
+ fontSize: {
81
+ default: null,
82
+ parseHTML: (element) => element.style.fontSize.replace(/['"]+/g, ""),
83
+ renderHTML: (attributes) => {
84
+ if (!attributes.fontSize) {
85
+ return {};
86
+ }
87
+ return {
88
+ style: `font-size: ${attributes.fontSize}`
89
+ };
90
+ }
91
+ }
92
+ }
93
+ }
94
+ ];
95
+ },
96
+ addCommands() {
97
+ return {
98
+ setFontSize: (fontSize) => ({ chain }) => {
99
+ const mapping = {
100
+ "tiny": "0.7em",
101
+ "small": "0.85em",
102
+ "big": "1.4em",
103
+ "huge": "1.8em"
104
+ };
105
+ const value = mapping[fontSize] || fontSize;
106
+ return chain().setMark("textStyle", { fontSize: value }).run();
107
+ },
108
+ unsetFontSize: () => ({ chain }) => {
109
+ return chain().setMark("textStyle", { fontSize: null }).removeEmptyTextStyle().run();
110
+ }
111
+ };
112
+ }
113
+ });
114
+
115
+ // src/backgroundColor.ts
116
+ var import_core2 = require("@tiptap/core");
117
+ var import_extension_text_style2 = require("@tiptap/extension-text-style");
118
+ var BackgroundColor = import_core2.Extension.create({
119
+ name: "backgroundColor",
120
+ addOptions() {
121
+ return {
122
+ types: ["textStyle"]
123
+ };
124
+ },
125
+ addGlobalAttributes() {
126
+ return [
127
+ {
128
+ types: this.options.types,
129
+ attributes: {
130
+ backgroundColor: {
131
+ default: null,
132
+ parseHTML: (element) => element.style.backgroundColor.replace(/['"]+/g, ""),
133
+ renderHTML: (attributes) => {
134
+ if (!attributes.backgroundColor) {
135
+ return {};
136
+ }
137
+ return {
138
+ style: `background-color: ${attributes.backgroundColor}`
139
+ };
140
+ }
141
+ }
142
+ }
143
+ }
144
+ ];
145
+ },
146
+ addCommands() {
147
+ return {
148
+ setBackgroundColor: (backgroundColor) => ({ chain }) => {
149
+ return chain().setMark("textStyle", { backgroundColor }).run();
150
+ },
151
+ unsetBackgroundColor: () => ({ chain }) => {
152
+ return chain().setMark("textStyle", { backgroundColor: null }).removeEmptyTextStyle().run();
153
+ }
154
+ };
155
+ }
156
+ });
157
+
158
+ // src/extensions.ts
159
+ var createTiptapExtensions = (placeholder = "Enter content here...") => [
160
+ import_starter_kit.default.configure({
161
+ heading: { levels: [1, 2, 3, 4, 5, 6] }
162
+ }),
163
+ import_extension_link.default.configure({
164
+ openOnClick: false,
165
+ autolink: true,
166
+ HTMLAttributes: { rel: "noopener noreferrer" }
167
+ }),
168
+ import_extension_underline.default,
169
+ import_extension_image.default.configure({ inline: false, allowBase64: false }),
170
+ import_extension_text_style3.TextStyle,
171
+ FontSize,
172
+ BackgroundColor,
173
+ import_extension_font_family.default,
174
+ import_extension_color.Color,
175
+ import_extension_superscript.default,
176
+ import_extension_subscript.default,
177
+ import_extension_text_align.default.configure({ types: ["heading", "paragraph"] }),
178
+ import_extension_placeholder.default.configure({ placeholder }),
179
+ import_extension_table.Table.configure({
180
+ resizable: true,
181
+ HTMLAttributes: {
182
+ class: "tiptap-table"
183
+ }
184
+ }),
185
+ import_extension_table_row.TableRow,
186
+ import_extension_table_header.default,
187
+ import_extension_table_cell.TableCell
188
+ ];
189
+
190
+ // src/utils.ts
191
+ async function uploadFileToCOS(file, docNum, onUploadFile, receiveStatus, elementId, onLoadingChange, suppressStatusChange = false, maxFileSizeMB = 50) {
192
+ const maxFileSizeBytes = maxFileSizeMB * 1024 * 1024;
193
+ if (file.size > maxFileSizeBytes) {
194
+ throw new Error(`${file.name} attachment too large (Max ${maxFileSizeMB}M)`);
195
+ }
196
+ receiveStatus && elementId && receiveStatus(elementId, true);
197
+ if (!suppressStatusChange) onLoadingChange == null ? void 0 : onLoadingChange(true);
198
+ try {
199
+ const url = await onUploadFile(file, docNum);
200
+ if (!url) throw new Error("Upload failed: no URL returned");
201
+ return url;
202
+ } finally {
203
+ if (!suppressStatusChange) onLoadingChange == null ? void 0 : onLoadingChange(false);
204
+ receiveStatus && elementId && receiveStatus(elementId, false);
205
+ }
206
+ }
207
+
208
+ // src/constants.ts
209
+ var TIPTAP_COLORS = [
210
+ "#000000",
211
+ "#4d4d4d",
212
+ "#999999",
213
+ "#e6e6e6",
214
+ "#ffffff",
215
+ "#e64d3d",
216
+ "#eb9120",
217
+ "#f3da35",
218
+ "#7ed822",
219
+ "#00d924",
220
+ "#1abc9c",
221
+ "#32dada",
222
+ "#3498db",
223
+ "#2980b9",
224
+ "#a290e4"
225
+ ];
226
+ var FONT_FAMILIES = [
227
+ { label: "Default", value: "" },
228
+ { label: "Arial", value: "Arial" },
229
+ { label: "Courier New", value: "Courier New" },
230
+ { label: "Georgia", value: "Georgia" },
231
+ { label: "Lucida Sans Unicode", value: "Lucida Sans Unicode" },
232
+ { label: "Tahoma", value: "Tahoma" },
233
+ { label: "Times New Roman", value: "Times New Roman" },
234
+ { label: "Trebuchet MS", value: "Trebuchet MS" },
235
+ { label: "Verdana", value: "Verdana" }
236
+ ];
237
+ var FONT_SIZES = [
238
+ { label: "Tiny", value: "tiny" },
239
+ { label: "Small", value: "small" },
240
+ { label: "Default", value: "" },
241
+ { label: "Big", value: "big" },
242
+ { label: "Huge", value: "huge" }
243
+ ];
244
+ var IMAGE_MIME_TYPES = [
245
+ "image/png",
246
+ "image/jpeg",
247
+ "image/jpg",
248
+ "image/gif",
249
+ "image/webp",
250
+ "image/bmp"
251
+ ];
252
+
253
+ // src/Icons.tsx
254
+ var import_jsx_runtime = require("react/jsx-runtime");
255
+ var LucideSvg = ({ children }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", xmlns: "http://www.w3.org/2000/svg", children });
256
+ var UndoIcon = () => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(LucideSvg, { children: [
257
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M3 7v6h6" }),
258
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M21 17a9 9 0 0 0-9-9 9 9 0 0 0-6 2.3L3 13" })
259
+ ] });
260
+ var RedoIcon = () => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(LucideSvg, { children: [
261
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M21 7v6h-6" }),
262
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M3 17a9 9 0 0 1 9-9 9 9 0 0 1 6 2.3l3 2.7" })
263
+ ] });
264
+ var BulletListIcon = () => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(LucideSvg, { children: [
265
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "8", y1: "6", x2: "21", y2: "6" }),
266
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "8", y1: "12", x2: "21", y2: "12" }),
267
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "8", y1: "18", x2: "21", y2: "18" }),
268
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "3", y1: "6", x2: "3.01", y2: "6" }),
269
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "3", y1: "12", x2: "3.01", y2: "12" }),
270
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "3", y1: "18", x2: "3.01", y2: "18" })
271
+ ] });
272
+ var OrderedListIcon = () => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(LucideSvg, { children: [
273
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "10", y1: "6", x2: "21", y2: "6" }),
274
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "10", y1: "12", x2: "21", y2: "12" }),
275
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "10", y1: "18", x2: "21", y2: "18" }),
276
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M4 6h1v4" }),
277
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M4 10h2" }),
278
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M6 18H4c0-1 2-2 2-3s-1-1.5-2-1" })
279
+ ] });
280
+ var BlockquoteIcon = () => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(LucideSvg, { children: [
281
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M17 6H3" }),
282
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M21 12H8" }),
283
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M21 18H8" }),
284
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M3 12v6" })
285
+ ] });
286
+ var BoldIcon = () => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(LucideSvg, { children: [
287
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M14 12a4 4 0 0 0 0-8H6v8" }),
288
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M15 20a4 4 0 0 0 0-8H6v8Z" })
289
+ ] });
290
+ var ItalicIcon = () => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(LucideSvg, { children: [
291
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "19", y1: "4", x2: "10", y2: "4" }),
292
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "14", y1: "20", x2: "5", y2: "20" }),
293
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "15", y1: "4", x2: "9", y2: "20" })
294
+ ] });
295
+ var StrikeIcon = () => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(LucideSvg, { children: [
296
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M16 4H9a3 3 0 0 0-2.83 4" }),
297
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M14 12a4 4 0 0 1 0 8H6" }),
298
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "4", y1: "12", x2: "20", y2: "12" })
299
+ ] });
300
+ var UnderlineIcon = () => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(LucideSvg, { children: [
301
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M6 4v6a6 6 0 0 0 12 0V4" }),
302
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "4", y1: "20", x2: "20", y2: "20" })
303
+ ] });
304
+ var CodeIcon = () => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(LucideSvg, { children: [
305
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("polyline", { points: "16 18 22 12 16 6" }),
306
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("polyline", { points: "8 6 2 12 8 18" })
307
+ ] });
308
+ var HighlightIcon = () => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(LucideSvg, { children: [
309
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "m9 11-6 6v3h9l3-3" }),
310
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "m22 12-4.6 4.6a2 2 0 0 1-2.8 0l-5.2-5.2a2 2 0 0 1 0-2.8L14 4" })
311
+ ] });
312
+ var LinkIcon = () => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(LucideSvg, { children: [
313
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71" }),
314
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71" })
315
+ ] });
316
+ var ImageIcon = () => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(LucideSvg, { children: [
317
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("rect", { width: "18", height: "18", x: "3", y: "3", rx: "2", ry: "2" }),
318
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("circle", { cx: "9", cy: "9", r: "2" }),
319
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21" })
320
+ ] });
321
+ var AlignLeftIcon = () => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(LucideSvg, { children: [
322
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "21", y1: "6", x2: "3", y2: "6" }),
323
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "15", y1: "12", x2: "3", y2: "12" }),
324
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "17", y1: "18", x2: "3", y2: "18" })
325
+ ] });
326
+ var AlignCenterIcon = () => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(LucideSvg, { children: [
327
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "21", y1: "6", x2: "3", y2: "6" }),
328
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "21", y1: "12", x2: "3", y2: "12" }),
329
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "21", y1: "18", x2: "3", y2: "18" }),
330
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "17", y1: "12", x2: "7", y2: "12" })
331
+ ] });
332
+ var AlignRightIcon = () => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(LucideSvg, { children: [
333
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "21", y1: "6", x2: "3", y2: "6" }),
334
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "21", y1: "12", x2: "9", y2: "12" }),
335
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "21", y1: "18", x2: "7", y2: "18" })
336
+ ] });
337
+ var TableIcon = () => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(LucideSvg, { children: [
338
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M3 3h18v18H3z" }),
339
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M3 9h18" }),
340
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M3 15h18" }),
341
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M9 3v18" }),
342
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M15 3v18" })
343
+ ] });
344
+ var AddRowBeforeIcon = () => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(LucideSvg, { children: [
345
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M3 13v5a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-5" }),
346
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M3 9h18" }),
347
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M12 2v8" }),
348
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "m9 5 3-3 3 3" })
349
+ ] });
350
+ var AddRowAfterIcon = () => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(LucideSvg, { children: [
351
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M3 11V6a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2v5" }),
352
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M3 15h18" }),
353
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M12 22v-8" }),
354
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "m9 19 3 3 3-3" })
355
+ ] });
356
+ var DeleteRowIcon = () => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(LucideSvg, { children: [
357
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M3 11V6a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2v5" }),
358
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M3 15h18" }),
359
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "18", y1: "20", x2: "12", y2: "20" })
360
+ ] });
361
+ var AddColBeforeIcon = () => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(LucideSvg, { children: [
362
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M13 3h5a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2h-5" }),
363
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M9 3v18" }),
364
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M2 12h8" }),
365
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "m5 9-3 3 3 3" })
366
+ ] });
367
+ var AddColAfterIcon = () => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(LucideSvg, { children: [
368
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M11 3H6a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h5" }),
369
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M15 3v18" }),
370
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M22 12h-8" }),
371
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "m19 9 3 3-3 3" })
372
+ ] });
373
+ var DeleteColIcon = () => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(LucideSvg, { children: [
374
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M11 3H6a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h5" }),
375
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M15 3v18" }),
376
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "20", y1: "18", x2: "20", y2: "12" })
377
+ ] });
378
+ var MergeCellsIcon = () => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(LucideSvg, { children: [
379
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M15 3v18" }),
380
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M3 9h18" }),
381
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M3 15h18" }),
382
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M9 3v18" })
383
+ ] });
384
+ var SplitCellIcon = () => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(LucideSvg, { children: [
385
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M3 3h18v18H3z" }),
386
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M3 9h18" }),
387
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M3 15h18" }),
388
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M9 3v18" }),
389
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M15 3v18" })
390
+ ] });
391
+ var DeleteTableIcon = () => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(LucideSvg, { children: [
392
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M3 3h18v18H3z" }),
393
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M3 9h18" }),
394
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M3 15h18" }),
395
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M9 3v18" }),
396
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M15 3v18" }),
397
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "18", y1: "18", x2: "12", y2: "12" })
398
+ ] });
399
+ var ClearIcon = () => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(LucideSvg, { children: [
400
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M18 6L6 18" }),
401
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M6 6l12 12" })
402
+ ] });
403
+ var SubmitIcon = () => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(LucideSvg, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("polyline", { points: "20 6 9 17 4 12" }) });
404
+ var AttachIcon = () => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(LucideSvg, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "m21.44 11.05-9.19 9.19a6 6 0 0 1-8.49-8.49l9.19-9.19a4 4 0 0 1 5.66 5.66l-9.2 9.19a2 2 0 0 1-2.82-2.82l8.49-8.48" }) });
405
+ var FontSizeIcon = () => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", xmlns: "http://www.w3.org/2000/svg", children: [
406
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "m3 7 5-5 5 5" }),
407
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M8 2v10" }),
408
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "m21 17-5 5-5-5" }),
409
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M16 12v10" }),
410
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M3 13h18" })
411
+ ] });
412
+ var FontFamilyIcon = () => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(LucideSvg, { children: [
413
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("polyline", { points: "4 7 4 4 20 4 20 7" }),
414
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "9", y1: "20", x2: "15", y2: "20" }),
415
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "12", y1: "4", x2: "12", y2: "20" })
416
+ ] });
417
+ var TextColorIcon = () => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(LucideSvg, { children: [
418
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M4 20h16" }),
419
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "m6 16 6-12 6 12" }),
420
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M8 12h8" })
421
+ ] });
422
+ var EraserIcon = () => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(LucideSvg, { children: [
423
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "m7 21-4.3-4.3c-1-1-1-2.5 0-3.4l9.9-9.9c1-1 2.5-1 3.4 0l4.4 4.4c1 1 1 2.5 0 3.4L10.8 21z" }),
424
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "m22 21h-8" }),
425
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "m5 11 9 9" })
426
+ ] });
427
+
428
+ // src/ToolbarGroups.tsx
429
+ var import_jsx_runtime2 = require("react/jsx-runtime");
430
+ var HistoryGroup = ({ editor, isReadOnly }) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
431
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
432
+ "button",
433
+ {
434
+ title: "Undo",
435
+ onClick: () => editor.chain().focus().undo().run(),
436
+ onMouseDown: (e) => e.preventDefault(),
437
+ disabled: isReadOnly || !editor.can().undo(),
438
+ "aria-label": "Undo",
439
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(UndoIcon, {})
440
+ }
441
+ ),
442
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
443
+ "button",
444
+ {
445
+ title: "Redo",
446
+ onClick: () => editor.chain().focus().redo().run(),
447
+ onMouseDown: (e) => e.preventDefault(),
448
+ disabled: isReadOnly || !editor.can().redo(),
449
+ "aria-label": "Redo",
450
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(RedoIcon, {})
451
+ }
452
+ )
453
+ ] });
454
+ var FontGroup = ({ editor, isReadOnly, showMenu, onToggle, onClose }) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { position: "relative", display: "inline-flex" }, children: [
455
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
456
+ "button",
457
+ {
458
+ title: "Font family",
459
+ onClick: onToggle,
460
+ onMouseDown: (e) => e.preventDefault(),
461
+ disabled: isReadOnly,
462
+ className: `toolbar-button-dropdown ${showMenu ? "is-active" : ""}`,
463
+ "aria-label": "Font family selection",
464
+ children: [
465
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(FontFamilyIcon, {}),
466
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { className: "dropdown-arrow", viewBox: "0 0 24 24", width: "10", height: "10", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M7 10l5 5 5-5z", fill: "currentColor" }) })
467
+ ]
468
+ }
469
+ ),
470
+ showMenu && !isReadOnly && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "tiptap-font-menu", children: FONT_FAMILIES.map((font) => {
471
+ const isActive = editor.getAttributes("textStyle").fontFamily === font.value;
472
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
473
+ "button",
474
+ {
475
+ className: `font-option ${isActive ? "is-active" : ""}`,
476
+ style: { fontFamily: font.value || "inherit" },
477
+ onClick: () => {
478
+ if (font.value) {
479
+ editor.chain().focus().setFontFamily(font.value).run();
480
+ } else {
481
+ editor.chain().focus().unsetFontFamily().run();
482
+ }
483
+ onClose();
484
+ },
485
+ children: font.label
486
+ },
487
+ font.label
488
+ );
489
+ }) })
490
+ ] });
491
+ var FontSizeGroup = ({ editor, isReadOnly, showMenu, onToggle, onClose }) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { position: "relative", display: "inline-flex" }, children: [
492
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
493
+ "button",
494
+ {
495
+ title: "Font size",
496
+ onClick: onToggle,
497
+ onMouseDown: (e) => e.preventDefault(),
498
+ disabled: isReadOnly,
499
+ className: `toolbar-button-dropdown ${showMenu ? "is-active" : ""}`,
500
+ "aria-label": "Font size selection",
501
+ children: [
502
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(FontSizeIcon, {}),
503
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { className: "dropdown-arrow", viewBox: "0 0 24 24", width: "10", height: "10", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M7 10l5 5 5-5z", fill: "currentColor" }) })
504
+ ]
505
+ }
506
+ ),
507
+ showMenu && !isReadOnly && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "tiptap-font-menu", children: FONT_SIZES.map((size) => {
508
+ const currentSize = editor.getAttributes("textStyle").fontSize;
509
+ const mapping = {
510
+ "tiny": "0.7em",
511
+ "small": "0.85em",
512
+ "big": "1.4em",
513
+ "huge": "1.8em"
514
+ };
515
+ const targetValue = mapping[size.value] || size.value || null;
516
+ const isActive = !currentSize && !size.value || currentSize === targetValue;
517
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
518
+ "button",
519
+ {
520
+ className: `font-option ${isActive ? "is-active" : ""}`,
521
+ onClick: () => {
522
+ if (size.value) {
523
+ editor.chain().focus().setFontSize(size.value).run();
524
+ } else {
525
+ editor.chain().focus().unsetFontSize().run();
526
+ }
527
+ onClose();
528
+ },
529
+ children: size.label
530
+ },
531
+ size.label
532
+ );
533
+ }) })
534
+ ] });
535
+ var TextColorGroup = ({ editor, isReadOnly, showMenu, onToggle, onClose }) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { position: "relative", display: "inline-flex" }, children: [
536
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
537
+ "button",
538
+ {
539
+ title: "Text color",
540
+ onClick: onToggle,
541
+ onMouseDown: (e) => e.preventDefault(),
542
+ disabled: isReadOnly,
543
+ className: `toolbar-button-dropdown ${showMenu ? "is-active" : ""}`,
544
+ "aria-label": "Text color picker",
545
+ children: [
546
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(TextColorIcon, {}),
547
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { className: "dropdown-arrow", viewBox: "0 0 24 24", width: "10", height: "10", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M7 10l5 5 5-5z", fill: "currentColor" }) })
548
+ ]
549
+ }
550
+ ),
551
+ showMenu && !isReadOnly && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "tiptap-color-picker", children: [
552
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
553
+ "button",
554
+ {
555
+ className: "color-remove-btn",
556
+ onClick: () => {
557
+ editor.chain().focus().unsetColor().run();
558
+ onClose();
559
+ },
560
+ children: [
561
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(EraserIcon, {}),
562
+ " Remove color"
563
+ ]
564
+ }
565
+ ),
566
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "color-grid", children: TIPTAP_COLORS.map((color) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
567
+ "button",
568
+ {
569
+ className: `color-swatch ${editor.isActive("textStyle", { color }) ? "is-active" : ""}`,
570
+ style: { backgroundColor: color },
571
+ onClick: () => {
572
+ editor.chain().focus().setColor(color).run();
573
+ onClose();
574
+ }
575
+ },
576
+ color
577
+ )) })
578
+ ] })
579
+ ] });
580
+ var HighlightGroup = ({ editor, isReadOnly, showMenu, onToggle, onClose }) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { position: "relative", display: "inline-flex" }, children: [
581
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
582
+ "button",
583
+ {
584
+ title: "Highlight",
585
+ onClick: onToggle,
586
+ onMouseDown: (e) => e.preventDefault(),
587
+ disabled: isReadOnly,
588
+ className: `toolbar-button-dropdown ${showMenu ? "is-active" : ""}`,
589
+ "aria-label": "Background color picker",
590
+ children: [
591
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(HighlightIcon, {}),
592
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { className: "dropdown-arrow", viewBox: "0 0 24 24", width: "10", height: "10", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M7 10l5 5 5-5z", fill: "currentColor" }) })
593
+ ]
594
+ }
595
+ ),
596
+ showMenu && !isReadOnly && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "tiptap-color-picker", children: [
597
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
598
+ "button",
599
+ {
600
+ className: "color-remove-btn",
601
+ onClick: () => {
602
+ editor.chain().focus().unsetBackgroundColor().run();
603
+ onClose();
604
+ },
605
+ children: [
606
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(EraserIcon, {}),
607
+ " Remove color"
608
+ ]
609
+ }
610
+ ),
611
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "color-grid", children: TIPTAP_COLORS.map((color) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
612
+ "button",
613
+ {
614
+ className: `color-swatch ${editor.isActive("textStyle", { backgroundColor: color }) ? "is-active" : ""}`,
615
+ style: { backgroundColor: color },
616
+ onClick: () => {
617
+ editor.chain().focus().setBackgroundColor(color).run();
618
+ onClose();
619
+ }
620
+ },
621
+ color
622
+ )) })
623
+ ] })
624
+ ] });
625
+ var ListGroup = ({ editor, isReadOnly }) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
626
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
627
+ "button",
628
+ {
629
+ title: "Bullet list",
630
+ onClick: () => editor.chain().focus().toggleBulletList().run(),
631
+ onMouseDown: (e) => e.preventDefault(),
632
+ disabled: isReadOnly,
633
+ className: editor.isActive("bulletList") ? "is-active" : "",
634
+ "aria-label": "Bullet list",
635
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(BulletListIcon, {})
636
+ }
637
+ ),
638
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
639
+ "button",
640
+ {
641
+ title: "Ordered list",
642
+ onClick: () => editor.chain().focus().toggleOrderedList().run(),
643
+ onMouseDown: (e) => e.preventDefault(),
644
+ disabled: isReadOnly,
645
+ className: editor.isActive("orderedList") ? "is-active" : "",
646
+ "aria-label": "Ordered list",
647
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(OrderedListIcon, {})
648
+ }
649
+ ),
650
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
651
+ "button",
652
+ {
653
+ title: "Blockquote",
654
+ onClick: () => editor.chain().focus().toggleBlockquote().run(),
655
+ onMouseDown: (e) => e.preventDefault(),
656
+ disabled: isReadOnly,
657
+ className: editor.isActive("blockquote") ? "is-active" : "",
658
+ "aria-label": "Blockquote",
659
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(BlockquoteIcon, {})
660
+ }
661
+ )
662
+ ] });
663
+ var InlineGroup = ({ editor, isReadOnly }) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
664
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
665
+ "button",
666
+ {
667
+ title: "Bold",
668
+ onClick: () => editor.chain().focus().toggleBold().run(),
669
+ onMouseDown: (e) => e.preventDefault(),
670
+ disabled: isReadOnly,
671
+ className: editor.isActive("bold") ? "is-active" : "",
672
+ "aria-label": "Bold",
673
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(BoldIcon, {})
674
+ }
675
+ ),
676
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
677
+ "button",
678
+ {
679
+ title: "Italic",
680
+ onClick: () => editor.chain().focus().toggleItalic().run(),
681
+ onMouseDown: (e) => e.preventDefault(),
682
+ disabled: isReadOnly,
683
+ className: editor.isActive("italic") ? "is-active" : "",
684
+ "aria-label": "Italic",
685
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ItalicIcon, {})
686
+ }
687
+ ),
688
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
689
+ "button",
690
+ {
691
+ title: "Strikethrough",
692
+ onClick: () => editor.chain().focus().toggleStrike().run(),
693
+ onMouseDown: (e) => e.preventDefault(),
694
+ disabled: isReadOnly,
695
+ className: editor.isActive("strike") ? "is-active" : "",
696
+ "aria-label": "Strikethrough",
697
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(StrikeIcon, {})
698
+ }
699
+ ),
700
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
701
+ "button",
702
+ {
703
+ title: "Underline",
704
+ onClick: () => editor.chain().focus().toggleUnderline().run(),
705
+ onMouseDown: (e) => e.preventDefault(),
706
+ disabled: isReadOnly,
707
+ className: editor.isActive("underline") ? "is-active" : "",
708
+ "aria-label": "Underline",
709
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(UnderlineIcon, {})
710
+ }
711
+ ),
712
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
713
+ "button",
714
+ {
715
+ title: "Code",
716
+ onClick: () => editor.chain().focus().toggleCode().run(),
717
+ onMouseDown: (e) => e.preventDefault(),
718
+ disabled: isReadOnly,
719
+ className: editor.isActive("code") ? "is-active" : "",
720
+ "aria-label": "Inline code",
721
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(CodeIcon, {})
722
+ }
723
+ )
724
+ ] });
725
+ var LinkGroup = ({ editor, isReadOnly, showMenu, onToggle, onClose, linkUrl, onLinkUrlChange, onSubmit }) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { position: "relative", display: "inline-flex" }, children: [
726
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
727
+ "button",
728
+ {
729
+ title: "Insert link",
730
+ onClick: onToggle,
731
+ onMouseDown: (e) => e.preventDefault(),
732
+ disabled: isReadOnly,
733
+ className: editor.isActive("link") ? "is-active" : "",
734
+ "aria-label": "Insert link",
735
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(LinkIcon, {})
736
+ }
737
+ ),
738
+ showMenu && !isReadOnly && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "tiptap-link-menu", children: [
739
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
740
+ "input",
741
+ {
742
+ type: "url",
743
+ placeholder: "Paste a link...",
744
+ value: linkUrl,
745
+ onChange: (e) => onLinkUrlChange(e.target.value),
746
+ onKeyDown: (e) => {
747
+ if (e.key === "Enter") onSubmit();
748
+ if (e.key === "Escape") onClose();
749
+ },
750
+ autoFocus: true
751
+ }
752
+ ),
753
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { onClick: onSubmit, title: "Apply", className: "link-submit-btn", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(SubmitIcon, {}) }),
754
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
755
+ "button",
756
+ {
757
+ onClick: () => {
758
+ editor.chain().focus().extendMarkRange("link").unsetLink().run();
759
+ onClose();
760
+ },
761
+ title: "Unlink",
762
+ className: "link-clear-btn",
763
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ClearIcon, {})
764
+ }
765
+ )
766
+ ] })
767
+ ] });
768
+ var AlignmentGroup = ({ editor, isReadOnly }) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
769
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
770
+ "button",
771
+ {
772
+ title: "Align left",
773
+ onClick: () => editor.chain().focus().setTextAlign("left").run(),
774
+ onMouseDown: (e) => e.preventDefault(),
775
+ disabled: isReadOnly,
776
+ className: editor.isActive({ textAlign: "left" }) ? "is-active" : "",
777
+ "aria-label": "Align left",
778
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(AlignLeftIcon, {})
779
+ }
780
+ ),
781
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
782
+ "button",
783
+ {
784
+ title: "Align center",
785
+ onClick: () => editor.chain().focus().setTextAlign("center").run(),
786
+ onMouseDown: (e) => e.preventDefault(),
787
+ disabled: isReadOnly,
788
+ className: editor.isActive({ textAlign: "center" }) ? "is-active" : "",
789
+ "aria-label": "Align center",
790
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(AlignCenterIcon, {})
791
+ }
792
+ ),
793
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
794
+ "button",
795
+ {
796
+ title: "Align right",
797
+ onClick: () => editor.chain().focus().setTextAlign("right").run(),
798
+ onMouseDown: (e) => e.preventDefault(),
799
+ disabled: isReadOnly,
800
+ className: editor.isActive({ textAlign: "right" }) ? "is-active" : "",
801
+ "aria-label": "Align right",
802
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(AlignRightIcon, {})
803
+ }
804
+ )
805
+ ] });
806
+ var TableGroup = ({ editor, isReadOnly, showMenu, onToggle, onClose, tableHoverSize, onGridHover }) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { position: "relative", display: "inline-flex" }, children: [
807
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
808
+ "button",
809
+ {
810
+ title: "Table",
811
+ onClick: onToggle,
812
+ onMouseDown: (e) => e.preventDefault(),
813
+ disabled: isReadOnly,
814
+ className: `toolbar-button-dropdown ${editor.isActive("table") ? "is-active" : ""}`,
815
+ "aria-label": "Table options",
816
+ children: [
817
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(TableIcon, {}),
818
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { className: "dropdown-arrow", viewBox: "0 0 24 24", width: "10", height: "10", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M7 10l5 5 5-5z", fill: "currentColor" }) })
819
+ ]
820
+ }
821
+ ),
822
+ showMenu && !isReadOnly && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "tiptap-table-menu", children: !editor.isActive("table") ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
823
+ "div",
824
+ {
825
+ className: "table-grid-picker-wrapper",
826
+ onMouseLeave: () => onGridHover(0, 0),
827
+ children: [
828
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "table-grid-picker", children: [...Array(10)].map((_, r) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "grid-row", children: [...Array(10)].map((_2, c) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
829
+ "div",
830
+ {
831
+ className: `grid-cell ${r + 1 <= tableHoverSize.rows && c + 1 <= tableHoverSize.cols ? "is-active" : ""}`,
832
+ onMouseEnter: () => onGridHover(r + 1, c + 1),
833
+ onClick: () => {
834
+ editor.chain().focus().insertTable({ rows: r + 1, cols: c + 1, withHeaderRow: true }).run();
835
+ onClose();
836
+ onGridHover(0, 0);
837
+ }
838
+ },
839
+ c
840
+ )) }, r)) }),
841
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "table-grid-label", children: tableHoverSize.rows > 0 ? `${tableHoverSize.rows} x ${tableHoverSize.cols}` : "Square Grid" })
842
+ ]
843
+ }
844
+ ) : /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "table-menu-grid", children: [
845
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { onClick: () => editor.chain().focus().addColumnBefore().run(), title: "Add column before", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(AddColBeforeIcon, {}) }),
846
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { onClick: () => editor.chain().focus().addColumnAfter().run(), title: "Add column after", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(AddColAfterIcon, {}) }),
847
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { onClick: () => editor.chain().focus().deleteColumn().run(), title: "Delete column", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(DeleteColIcon, {}) }),
848
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { onClick: () => editor.chain().focus().addRowBefore().run(), title: "Add row before", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(AddRowBeforeIcon, {}) }),
849
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { onClick: () => editor.chain().focus().addRowAfter().run(), title: "Add row after", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(AddRowAfterIcon, {}) }),
850
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { onClick: () => editor.chain().focus().deleteRow().run(), title: "Delete row", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(DeleteRowIcon, {}) }),
851
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { onClick: () => editor.chain().focus().mergeCells().run(), title: "Merge cells", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(MergeCellsIcon, {}) }),
852
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { onClick: () => editor.chain().focus().splitCell().run(), title: "Split cell", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(SplitCellIcon, {}) }),
853
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { onClick: () => {
854
+ editor.chain().focus().deleteTable().run();
855
+ onClose();
856
+ }, className: "danger", title: "Delete table", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(DeleteTableIcon, {}) })
857
+ ] }) })
858
+ ] });
859
+ var InsertGroup = ({ isReadOnly, onImageClick, onAttachClick }) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
860
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
861
+ "button",
862
+ {
863
+ title: "Insert image",
864
+ onClick: onImageClick,
865
+ onMouseDown: (e) => e.preventDefault(),
866
+ disabled: isReadOnly,
867
+ "aria-label": "Insert image",
868
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ImageIcon, {})
869
+ }
870
+ ),
871
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
872
+ "button",
873
+ {
874
+ title: "Attach file",
875
+ onClick: onAttachClick,
876
+ onMouseDown: (e) => e.preventDefault(),
877
+ disabled: isReadOnly,
878
+ "aria-label": "Attach file",
879
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(AttachIcon, {})
880
+ }
881
+ )
882
+ ] });
883
+
884
+ // src/TiptapEditor.tsx
885
+ var import_jsx_runtime3 = require("react/jsx-runtime");
886
+ var TiptapEditor = ({
887
+ elementId,
888
+ content,
889
+ editMode,
890
+ docNum,
891
+ receiveData,
892
+ receiveStatus,
893
+ onUploadFile,
894
+ onAlert,
895
+ onLoadingChange,
896
+ onRegisterReset,
897
+ maxFileSizeMB = 50,
898
+ placeholder = "Enter content here...",
899
+ toolbarConfig
900
+ }) => {
901
+ const alertFn = onAlert || ((msg) => window.alert(msg));
902
+ const loadingChangeFn = onLoadingChange || (() => {
903
+ });
904
+ const isReadOnly = !editMode;
905
+ const containerRef = (0, import_react.useRef)(null);
906
+ const imageInputRef = (0, import_react.useRef)(null);
907
+ const attachInputRef = (0, import_react.useRef)(null);
908
+ const [showHighlightMenu, setShowHighlightMenu] = import_react.default.useState(false);
909
+ const [showTextColorMenu, setShowTextColorMenu] = import_react.default.useState(false);
910
+ const [showFontMenu, setShowFontMenu] = import_react.default.useState(false);
911
+ const [showFontSizeMenu, setShowFontSizeMenu] = import_react.default.useState(false);
912
+ const [showLinkMenu, setShowLinkMenu] = import_react.default.useState(false);
913
+ const [showTableMenu, setShowTableMenu] = import_react.default.useState(false);
914
+ const [tableHoverSize, setTableHoverSize] = import_react.default.useState({ rows: 0, cols: 0 });
915
+ const [linkUrl, setLinkUrl] = import_react.default.useState("");
916
+ const initializedRef = (0, import_react.useRef)(false);
917
+ const lastEmittedContentRef = (0, import_react.useRef)(content || "");
918
+ const lastUpdateTimestampRef = (0, import_react.useRef)(0);
919
+ const activeUploadsRef = (0, import_react.useRef)(0);
920
+ const closeAllMenus = import_react.default.useCallback(() => {
921
+ setShowHighlightMenu(false);
922
+ setShowTextColorMenu(false);
923
+ setShowFontMenu(false);
924
+ setShowFontSizeMenu(false);
925
+ setShowLinkMenu(false);
926
+ setShowTableMenu(false);
927
+ }, []);
928
+ import_react.default.useEffect(() => {
929
+ const handleClickOutside = (event) => {
930
+ if (containerRef.current && !containerRef.current.contains(event.target)) {
931
+ closeAllMenus();
932
+ }
933
+ };
934
+ document.addEventListener("mousedown", handleClickOutside);
935
+ return () => {
936
+ document.removeEventListener("mousedown", handleClickOutside);
937
+ };
938
+ }, [closeAllMenus]);
939
+ const editor = (0, import_react2.useEditor)({
940
+ immediatelyRender: false,
941
+ extensions: createTiptapExtensions(placeholder),
942
+ content: content || "",
943
+ editable: editMode,
944
+ onFocus: () => {
945
+ closeAllMenus();
946
+ },
947
+ onSelectionUpdate: () => {
948
+ closeAllMenus();
949
+ },
950
+ editorProps: {
951
+ // Handle clipboard paste - support pasting images (e.g. screenshots)
952
+ handlePaste: (view, event) => {
953
+ if (!editMode) return false;
954
+ const clipboardData = event.clipboardData;
955
+ if (!clipboardData) return false;
956
+ const items = Array.from(clipboardData.items);
957
+ const imageItems = items.filter((item) => item.kind === "file" && IMAGE_MIME_TYPES.includes(item.type));
958
+ if (imageItems.length > 0) {
959
+ event.preventDefault();
960
+ if (!onUploadFile) {
961
+ alertFn("Upload function not provided");
962
+ return true;
963
+ }
964
+ activeUploadsRef.current += 1;
965
+ loadingChangeFn(true);
966
+ Promise.all(
967
+ imageItems.map((item) => {
968
+ const file = item.getAsFile();
969
+ if (!file) return Promise.resolve();
970
+ return uploadFileToCOS(
971
+ file,
972
+ docNum,
973
+ onUploadFile,
974
+ receiveStatus,
975
+ elementId,
976
+ loadingChangeFn,
977
+ true,
978
+ maxFileSizeMB
979
+ ).then((url) => {
980
+ view.dispatch(
981
+ view.state.tr.replaceSelectionWith(
982
+ view.state.schema.nodes.image.create({ src: url, alt: file.name })
983
+ )
984
+ );
985
+ }).catch((err) => {
986
+ alertFn(err.message || "Image upload failed");
987
+ });
988
+ })
989
+ ).finally(() => {
990
+ activeUploadsRef.current -= 1;
991
+ loadingChangeFn(false);
992
+ if (activeUploadsRef.current === 0) {
993
+ const html = editor == null ? void 0 : editor.getHTML();
994
+ if (html) {
995
+ lastEmittedContentRef.current = html;
996
+ receiveData && receiveData(elementId, html);
997
+ }
998
+ }
999
+ });
1000
+ return true;
1001
+ }
1002
+ return false;
1003
+ }
1004
+ },
1005
+ onUpdate: ({ editor: editor2 }) => {
1006
+ const html = editor2.getHTML();
1007
+ lastEmittedContentRef.current = html;
1008
+ lastUpdateTimestampRef.current = Date.now();
1009
+ if (activeUploadsRef.current === 0) {
1010
+ receiveData && receiveData(elementId, html);
1011
+ }
1012
+ }
1013
+ });
1014
+ (0, import_react.useEffect)(() => {
1015
+ if (!editor) return;
1016
+ if (!initializedRef.current) {
1017
+ initializedRef.current = true;
1018
+ if (content && content !== editor.getHTML()) {
1019
+ editor.commands.setContent(content || "", false);
1020
+ lastEmittedContentRef.current = content;
1021
+ }
1022
+ return;
1023
+ }
1024
+ if (Date.now() - lastUpdateTimestampRef.current < 150) {
1025
+ return;
1026
+ }
1027
+ if (editor.isFocused) {
1028
+ return;
1029
+ }
1030
+ if (content === lastEmittedContentRef.current) {
1031
+ return;
1032
+ }
1033
+ if (content !== editor.getHTML()) {
1034
+ editor.commands.setContent(content || "", false);
1035
+ lastEmittedContentRef.current = content || "";
1036
+ }
1037
+ }, [content, editor]);
1038
+ (0, import_react.useEffect)(() => {
1039
+ if (!editor) return;
1040
+ editor.setEditable(editMode);
1041
+ }, [editMode, editor]);
1042
+ (0, import_react.useEffect)(() => {
1043
+ if (!editor || !onRegisterReset) return;
1044
+ const handleReset = (newContent) => {
1045
+ editor.commands.setContent(newContent || "", false);
1046
+ };
1047
+ const unregister = onRegisterReset(handleReset);
1048
+ return () => {
1049
+ unregister && unregister();
1050
+ };
1051
+ }, [editor, onRegisterReset]);
1052
+ const handleImageFileChange = (0, import_react.useCallback)(
1053
+ async (e) => {
1054
+ const files = Array.from(e.target.files || []);
1055
+ if (files.length === 0 || !editor) return;
1056
+ e.target.value = "";
1057
+ if (!onUploadFile) {
1058
+ alertFn("Upload function not provided");
1059
+ return;
1060
+ }
1061
+ activeUploadsRef.current += 1;
1062
+ loadingChangeFn(true);
1063
+ try {
1064
+ await Promise.all(
1065
+ files.map(async (file) => {
1066
+ const url = await uploadFileToCOS(
1067
+ file,
1068
+ docNum,
1069
+ onUploadFile,
1070
+ receiveStatus,
1071
+ elementId,
1072
+ loadingChangeFn,
1073
+ true,
1074
+ maxFileSizeMB
1075
+ );
1076
+ editor.chain().focus().setImage({ src: url, alt: file.name }).run();
1077
+ })
1078
+ );
1079
+ } catch (err) {
1080
+ alertFn(err.message || "Image upload failed");
1081
+ } finally {
1082
+ activeUploadsRef.current -= 1;
1083
+ loadingChangeFn(false);
1084
+ if (activeUploadsRef.current === 0) {
1085
+ const html = editor.getHTML();
1086
+ lastEmittedContentRef.current = html;
1087
+ receiveData && receiveData(elementId, html);
1088
+ }
1089
+ }
1090
+ },
1091
+ [editor, docNum, receiveStatus, elementId, receiveData, onUploadFile, alertFn, loadingChangeFn, maxFileSizeMB]
1092
+ );
1093
+ const handleAttachFileChange = (0, import_react.useCallback)(
1094
+ async (e) => {
1095
+ const files = Array.from(e.target.files || []);
1096
+ if (files.length === 0 || !editor) return;
1097
+ e.target.value = "";
1098
+ if (!onUploadFile) {
1099
+ alertFn("Upload function not provided");
1100
+ return;
1101
+ }
1102
+ activeUploadsRef.current += 1;
1103
+ loadingChangeFn(true);
1104
+ try {
1105
+ await Promise.all(
1106
+ files.map(async (file) => {
1107
+ const url = await uploadFileToCOS(
1108
+ file,
1109
+ docNum,
1110
+ onUploadFile,
1111
+ receiveStatus,
1112
+ elementId,
1113
+ loadingChangeFn,
1114
+ true,
1115
+ maxFileSizeMB
1116
+ );
1117
+ editor.chain().focus().insertContent(
1118
+ `<a href="${url}" target="_blank" rel="noopener noreferrer" data-attachment="true">${file.name}</a>&nbsp;`
1119
+ ).run();
1120
+ })
1121
+ );
1122
+ } catch (err) {
1123
+ alertFn(err.message || "Attachment upload failed");
1124
+ } finally {
1125
+ activeUploadsRef.current -= 1;
1126
+ loadingChangeFn(false);
1127
+ if (activeUploadsRef.current === 0) {
1128
+ const html = editor.getHTML();
1129
+ lastEmittedContentRef.current = html;
1130
+ receiveData && receiveData(elementId, html);
1131
+ }
1132
+ }
1133
+ },
1134
+ [editor, docNum, receiveStatus, elementId, receiveData, onUploadFile, alertFn, loadingChangeFn, maxFileSizeMB]
1135
+ );
1136
+ const handleLinkClick = (0, import_react.useCallback)(() => {
1137
+ if (!editor || isReadOnly) return;
1138
+ const nextState = !showLinkMenu;
1139
+ closeAllMenus();
1140
+ if (nextState) {
1141
+ const previousUrl = editor.getAttributes("link").href;
1142
+ setLinkUrl(previousUrl || "");
1143
+ }
1144
+ setShowLinkMenu(nextState);
1145
+ }, [editor, isReadOnly, showLinkMenu, closeAllMenus]);
1146
+ const submitLink = (0, import_react.useCallback)(() => {
1147
+ if (!editor) return;
1148
+ if (linkUrl === null || linkUrl.trim() === "") {
1149
+ editor.chain().focus().extendMarkRange("link").unsetLink().run();
1150
+ } else {
1151
+ const formattedUrl = /^https?:\/\//.test(linkUrl) ? linkUrl : `https://${linkUrl}`;
1152
+ editor.chain().focus().extendMarkRange("link").setLink({ href: formattedUrl }).run();
1153
+ }
1154
+ setShowLinkMenu(false);
1155
+ }, [editor, linkUrl]);
1156
+ if (!editor) return null;
1157
+ const getHiddenInputs = () => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
1158
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1159
+ "input",
1160
+ {
1161
+ ref: imageInputRef,
1162
+ type: "file",
1163
+ accept: "image/*",
1164
+ multiple: true,
1165
+ className: "tiptap-hidden-input",
1166
+ onChange: handleImageFileChange
1167
+ }
1168
+ ),
1169
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1170
+ "input",
1171
+ {
1172
+ ref: attachInputRef,
1173
+ type: "file",
1174
+ accept: "*/*",
1175
+ multiple: true,
1176
+ className: "tiptap-hidden-input",
1177
+ onChange: handleAttachFileChange
1178
+ }
1179
+ )
1180
+ ] });
1181
+ const defaultGroups = [
1182
+ "history",
1183
+ "font",
1184
+ "fontSize",
1185
+ "textColor",
1186
+ "highlight",
1187
+ "list",
1188
+ "alignment",
1189
+ "table",
1190
+ "inline",
1191
+ "link",
1192
+ "insert"
1193
+ ];
1194
+ const toolbarGroups = (toolbarConfig == null ? void 0 : toolbarConfig.groups) || defaultGroups;
1195
+ const showDividers = (toolbarConfig == null ? void 0 : toolbarConfig.showDividers) !== void 0 ? toolbarConfig.showDividers : true;
1196
+ const getToolbar = () => {
1197
+ const toolbarComponents = {
1198
+ history: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(HistoryGroup, { editor, isReadOnly }),
1199
+ font: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1200
+ FontGroup,
1201
+ {
1202
+ editor,
1203
+ isReadOnly,
1204
+ showMenu: showFontMenu,
1205
+ onToggle: () => {
1206
+ const nextState = !showFontMenu;
1207
+ closeAllMenus();
1208
+ setShowFontMenu(nextState);
1209
+ },
1210
+ onClose: () => setShowFontMenu(false)
1211
+ }
1212
+ ),
1213
+ fontSize: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1214
+ FontSizeGroup,
1215
+ {
1216
+ editor,
1217
+ isReadOnly,
1218
+ showMenu: showFontSizeMenu,
1219
+ onToggle: () => {
1220
+ const nextState = !showFontSizeMenu;
1221
+ closeAllMenus();
1222
+ setShowFontSizeMenu(nextState);
1223
+ },
1224
+ onClose: () => setShowFontSizeMenu(false)
1225
+ }
1226
+ ),
1227
+ textColor: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1228
+ TextColorGroup,
1229
+ {
1230
+ editor,
1231
+ isReadOnly,
1232
+ showMenu: showTextColorMenu,
1233
+ onToggle: () => {
1234
+ const nextState = !showTextColorMenu;
1235
+ closeAllMenus();
1236
+ setShowTextColorMenu(nextState);
1237
+ },
1238
+ onClose: () => setShowTextColorMenu(false)
1239
+ }
1240
+ ),
1241
+ highlight: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1242
+ HighlightGroup,
1243
+ {
1244
+ editor,
1245
+ isReadOnly,
1246
+ showMenu: showHighlightMenu,
1247
+ onToggle: () => {
1248
+ const nextState = !showHighlightMenu;
1249
+ closeAllMenus();
1250
+ setShowHighlightMenu(nextState);
1251
+ },
1252
+ onClose: () => setShowHighlightMenu(false)
1253
+ }
1254
+ ),
1255
+ list: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ListGroup, { editor, isReadOnly }),
1256
+ alignment: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(AlignmentGroup, { editor, isReadOnly }),
1257
+ table: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1258
+ TableGroup,
1259
+ {
1260
+ editor,
1261
+ isReadOnly,
1262
+ showMenu: showTableMenu,
1263
+ onToggle: () => !isReadOnly && setShowTableMenu(!showTableMenu),
1264
+ onClose: () => setShowTableMenu(false),
1265
+ tableHoverSize,
1266
+ onGridHover: (rows, cols) => setTableHoverSize({ rows, cols })
1267
+ }
1268
+ ),
1269
+ inline: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(InlineGroup, { editor, isReadOnly }),
1270
+ link: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1271
+ LinkGroup,
1272
+ {
1273
+ editor,
1274
+ isReadOnly,
1275
+ showMenu: showLinkMenu,
1276
+ onToggle: handleLinkClick,
1277
+ onClose: () => setShowLinkMenu(false),
1278
+ linkUrl,
1279
+ onLinkUrlChange: setLinkUrl,
1280
+ onSubmit: submitLink
1281
+ }
1282
+ ),
1283
+ insert: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1284
+ InsertGroup,
1285
+ {
1286
+ editor,
1287
+ isReadOnly,
1288
+ onImageClick: () => {
1289
+ var _a;
1290
+ return !isReadOnly && ((_a = imageInputRef.current) == null ? void 0 : _a.click());
1291
+ },
1292
+ onAttachClick: () => {
1293
+ var _a;
1294
+ return !isReadOnly && ((_a = attachInputRef.current) == null ? void 0 : _a.click());
1295
+ }
1296
+ }
1297
+ )
1298
+ };
1299
+ const toolbarItems = toolbarGroups.map((group, index) => {
1300
+ const component = toolbarComponents[group];
1301
+ if (!component) return null;
1302
+ const divider = showDividers && index > 0 ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "toolbar-divider" }) : null;
1303
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_react.default.Fragment, { children: [
1304
+ divider,
1305
+ component
1306
+ ] }, group);
1307
+ }).filter(Boolean);
1308
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1309
+ "div",
1310
+ {
1311
+ className: `tiptap-toolbar${isReadOnly ? " toolbar-disabled" : ""}`,
1312
+ role: "toolbar",
1313
+ "aria-label": "Editor toolbar",
1314
+ children: toolbarItems
1315
+ }
1316
+ );
1317
+ };
1318
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { id: elementId, className: `tiptap-editor-wrapper${isReadOnly ? " read-only" : ""}`, ref: containerRef, children: [
1319
+ getHiddenInputs(),
1320
+ getToolbar(),
1321
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { onMouseDown: closeAllMenus, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react2.EditorContent, { editor }) })
1322
+ ] });
1323
+ };
1324
+ var TiptapEditor_default = TiptapEditor;
1325
+ // Annotate the CommonJS export names for ESM import in node:
1326
+ 0 && (module.exports = {
1327
+ BackgroundColor,
1328
+ FONT_FAMILIES,
1329
+ FONT_SIZES,
1330
+ FontSize,
1331
+ IMAGE_MIME_TYPES,
1332
+ TIPTAP_COLORS,
1333
+ TiptapEditor,
1334
+ createTiptapExtensions
1335
+ });
1336
+ //# sourceMappingURL=index.js.map