@mpdev_ab/document-creator 0.1.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.
Files changed (34) hide show
  1. package/dist/dev/App.vue.d.ts +2 -0
  2. package/dist/dev/main.d.ts +0 -0
  3. package/dist/document-creator.css +1 -0
  4. package/dist/document-creator.js +1906 -0
  5. package/dist/document-creator.umd.cjs +1 -0
  6. package/dist/index.d.ts +2 -0
  7. package/dist/src/components/DocumentEditor.vue.d.ts +89 -0
  8. package/dist/src/components/image/ImageResizePopover.vue.d.ts +92 -0
  9. package/dist/src/components/image/ImageUploadButton.vue.d.ts +21 -0
  10. package/dist/src/components/table/TablePopoverMenu.vue.d.ts +6 -0
  11. package/dist/src/components/templates/LoadTemplateModal.vue.d.ts +21 -0
  12. package/dist/src/components/templates/SaveTemplateModal.vue.d.ts +21 -0
  13. package/dist/src/components/toolbar/AlignmentButtons.vue.d.ts +8 -0
  14. package/dist/src/components/toolbar/ColorPicker.vue.d.ts +10 -0
  15. package/dist/src/components/toolbar/EditorToolbar.vue.d.ts +25 -0
  16. package/dist/src/components/toolbar/FontFamilyPicker.vue.d.ts +8 -0
  17. package/dist/src/components/toolbar/FontSizePicker.vue.d.ts +8 -0
  18. package/dist/src/components/toolbar/HeadingPicker.vue.d.ts +8 -0
  19. package/dist/src/components/toolbar/LineHeightPicker.vue.d.ts +8 -0
  20. package/dist/src/components/toolbar/LinkButton.vue.d.ts +11 -0
  21. package/dist/src/components/toolbar/TableGridPicker.vue.d.ts +10 -0
  22. package/dist/src/components/toolbar/ToolbarButton.vue.d.ts +28 -0
  23. package/dist/src/components/toolbar/ToolbarDivider.vue.d.ts +2 -0
  24. package/dist/src/components/toolbar/ToolbarDropdown.vue.d.ts +30 -0
  25. package/dist/src/components/toolbar/VideoEmbedButton.vue.d.ts +10 -0
  26. package/dist/src/composables/useDocumentEditor.d.ts +11 -0
  27. package/dist/src/composables/useTemplateApi.d.ts +19 -0
  28. package/dist/src/extensions/base64-image.d.ts +1 -0
  29. package/dist/src/extensions/font-size.d.ts +10 -0
  30. package/dist/src/extensions/line-height.d.ts +10 -0
  31. package/dist/src/extensions/video.d.ts +11 -0
  32. package/dist/src/index.d.ts +3 -0
  33. package/dist/src/types/index.d.ts +45 -0
  34. package/package.json +58 -0
@@ -0,0 +1,1906 @@
1
+ import { defineComponent as C, ref as y, computed as H, openBlock as g, createBlock as V, unref as L, normalizeClass as w, withCtx as x, createElementVNode as l, normalizeStyle as D, createElementBlock as p, Fragment as A, renderList as E, toDisplayString as z, withDirectives as F, withKeys as P, vModelText as I, createCommentVNode as B, inject as _, renderSlot as X, onMounted as U, onBeforeUnmount as N, createVNode as h, nextTick as ee, createTextVNode as j, Teleport as Y, withModifiers as K, vModelRadio as J, provide as te, watch as q } from "vue";
2
+ import { nodeViewProps as le, NodeViewWrapper as ne, VueNodeViewRenderer as oe, useEditor as ie, EditorContent as re } from "@tiptap/vue-3";
3
+ import se from "@tiptap/starter-kit";
4
+ import { TextStyle as ae } from "@tiptap/extension-text-style";
5
+ import ue from "@tiptap/extension-font-family";
6
+ import de from "@tiptap/extension-underline";
7
+ import ce from "@tiptap/extension-subscript";
8
+ import me from "@tiptap/extension-superscript";
9
+ import fe from "@tiptap/extension-color";
10
+ import ve from "@tiptap/extension-text-align";
11
+ import ge from "@tiptap/extension-link";
12
+ import he from "@tiptap/extension-placeholder";
13
+ import { Table as pe } from "@tiptap/extension-table";
14
+ import be from "@tiptap/extension-table-row";
15
+ import xe from "@tiptap/extension-table-cell";
16
+ import ye from "@tiptap/extension-table-header";
17
+ import { Extension as Z, Node as ke, mergeAttributes as we } from "@tiptap/core";
18
+ import Ce from "@tiptap/extension-image";
19
+ const $e = Z.create({
20
+ name: "fontSize",
21
+ addOptions() {
22
+ return {
23
+ types: ["textStyle"]
24
+ };
25
+ },
26
+ addGlobalAttributes() {
27
+ return [
28
+ {
29
+ types: this.options.types,
30
+ attributes: {
31
+ fontSize: {
32
+ default: null,
33
+ parseHTML: (e) => {
34
+ var n;
35
+ return ((n = e.style.fontSize) == null ? void 0 : n.replace(/['"]+/g, "")) || null;
36
+ },
37
+ renderHTML: (e) => e.fontSize ? { style: `font-size: ${e.fontSize}` } : {}
38
+ }
39
+ }
40
+ }
41
+ ];
42
+ },
43
+ addCommands() {
44
+ return {
45
+ setFontSize: (e) => ({ chain: n }) => n().setMark("textStyle", { fontSize: e }).run(),
46
+ unsetFontSize: () => ({ chain: e }) => e().setMark("textStyle", { fontSize: null }).removeEmptyTextStyle().run()
47
+ };
48
+ }
49
+ }), Te = Z.create({
50
+ name: "lineHeight",
51
+ addOptions() {
52
+ return {
53
+ types: ["heading", "paragraph"]
54
+ };
55
+ },
56
+ addGlobalAttributes() {
57
+ return [
58
+ {
59
+ types: this.options.types,
60
+ attributes: {
61
+ lineHeight: {
62
+ default: null,
63
+ parseHTML: (e) => e.style.lineHeight || null,
64
+ renderHTML: (e) => e.lineHeight ? { style: `line-height: ${e.lineHeight}` } : {}
65
+ }
66
+ }
67
+ }
68
+ ];
69
+ },
70
+ addCommands() {
71
+ return {
72
+ setLineHeight: (e) => ({ commands: n }) => this.options.types.every(
73
+ (t) => n.updateAttributes(t, { lineHeight: e })
74
+ ),
75
+ unsetLineHeight: () => ({ commands: e }) => this.options.types.every(
76
+ (n) => e.resetAttributes(n, "lineHeight")
77
+ )
78
+ };
79
+ }
80
+ }), Me = ["src", "alt"], Ae = {
81
+ key: 0,
82
+ class: "absolute -top-10 left-0 flex items-center gap-1 bg-white border border-gray-200 rounded shadow-md p-1 z-10"
83
+ }, Se = ["onClick"], Le = /* @__PURE__ */ C({
84
+ __name: "ImageResizePopover",
85
+ props: le,
86
+ setup(e) {
87
+ const n = e, t = y(n.node.attrs.width || ""), c = y(n.node.attrs.alt || ""), o = H(() => {
88
+ const d = {};
89
+ return n.node.attrs.width && (d.width = n.node.attrs.width), n.node.attrs.height && (d.height = n.node.attrs.height), d;
90
+ }), a = H(() => {
91
+ const d = n.node.attrs.align;
92
+ return d === "center" ? "mx-auto block" : d === "right" ? "ml-auto block" : "block";
93
+ });
94
+ function m() {
95
+ const d = n.getPos();
96
+ d != null && n.editor.commands.setNodeSelection(d);
97
+ }
98
+ function i(d) {
99
+ n.updateAttributes({ width: d }), t.value = d;
100
+ }
101
+ function s(d) {
102
+ n.updateAttributes({ align: d });
103
+ }
104
+ function r() {
105
+ n.updateAttributes({ alt: c.value });
106
+ }
107
+ return (d, u) => (g(), V(L(ne), {
108
+ class: w(["relative inline-block", a.value])
109
+ }, {
110
+ default: x(() => [
111
+ l("img", {
112
+ src: d.node.attrs.src,
113
+ alt: d.node.attrs.alt || "",
114
+ style: D(o.value),
115
+ class: w(["cursor-pointer max-w-full", d.selected ? "ring-2 ring-blue-400" : ""]),
116
+ onClick: m
117
+ }, null, 14, Me),
118
+ d.selected ? (g(), p("div", Ae, [
119
+ (g(), p(A, null, E(["25%", "50%", "75%", "100%"], (b) => l("button", {
120
+ key: b,
121
+ class: "px-2 py-0.5 text-xs rounded hover:bg-gray-100",
122
+ onClick: (S) => i(b)
123
+ }, z(b), 9, Se)), 64)),
124
+ F(l("input", {
125
+ "onUpdate:modelValue": u[0] || (u[0] = (b) => t.value = b),
126
+ class: "w-16 border border-gray-300 rounded px-1 py-0.5 text-xs",
127
+ placeholder: "e.g. 100%",
128
+ onKeydown: u[1] || (u[1] = P((b) => i(t.value), ["enter"]))
129
+ }, null, 544), [
130
+ [I, t.value]
131
+ ]),
132
+ u[9] || (u[9] = l("span", { class: "w-px h-4 bg-gray-300 mx-1" }, null, -1)),
133
+ l("button", {
134
+ class: "px-1 py-0.5 text-xs rounded hover:bg-gray-100",
135
+ title: "Align left",
136
+ onClick: u[2] || (u[2] = (b) => s("left"))
137
+ }, [...u[6] || (u[6] = [
138
+ l("svg", {
139
+ class: "w-3 h-3",
140
+ viewBox: "0 0 24 24",
141
+ fill: "none",
142
+ stroke: "currentColor",
143
+ "stroke-width": "2"
144
+ }, [
145
+ l("path", { d: "M3 6h18M3 12h10M3 18h14" })
146
+ ], -1)
147
+ ])]),
148
+ l("button", {
149
+ class: "px-1 py-0.5 text-xs rounded hover:bg-gray-100",
150
+ title: "Align center",
151
+ onClick: u[3] || (u[3] = (b) => s("center"))
152
+ }, [...u[7] || (u[7] = [
153
+ l("svg", {
154
+ class: "w-3 h-3",
155
+ viewBox: "0 0 24 24",
156
+ fill: "none",
157
+ stroke: "currentColor",
158
+ "stroke-width": "2"
159
+ }, [
160
+ l("path", { d: "M3 6h18M7 12h10M5 18h14" })
161
+ ], -1)
162
+ ])]),
163
+ l("button", {
164
+ class: "px-1 py-0.5 text-xs rounded hover:bg-gray-100",
165
+ title: "Align right",
166
+ onClick: u[4] || (u[4] = (b) => s("right"))
167
+ }, [...u[8] || (u[8] = [
168
+ l("svg", {
169
+ class: "w-3 h-3",
170
+ viewBox: "0 0 24 24",
171
+ fill: "none",
172
+ stroke: "currentColor",
173
+ "stroke-width": "2"
174
+ }, [
175
+ l("path", { d: "M3 6h18M11 12h10M7 18h14" })
176
+ ], -1)
177
+ ])]),
178
+ u[10] || (u[10] = l("span", { class: "w-px h-4 bg-gray-300 mx-1" }, null, -1)),
179
+ F(l("input", {
180
+ "onUpdate:modelValue": u[5] || (u[5] = (b) => c.value = b),
181
+ class: "w-20 border border-gray-300 rounded px-1 py-0.5 text-xs",
182
+ placeholder: "Alt text",
183
+ onBlur: r,
184
+ onKeydown: P(r, ["enter"])
185
+ }, null, 544), [
186
+ [I, c.value]
187
+ ])
188
+ ])) : B("", !0)
189
+ ]),
190
+ _: 1
191
+ }, 8, ["class"]));
192
+ }
193
+ }), Be = Ce.extend({
194
+ name: "image",
195
+ addAttributes() {
196
+ var e;
197
+ return {
198
+ ...(e = this.parent) == null ? void 0 : e.call(this),
199
+ width: {
200
+ default: null,
201
+ parseHTML: (n) => n.getAttribute("width") || n.style.width || null,
202
+ renderHTML: (n) => n.width ? { style: `width: ${n.width}` } : {}
203
+ },
204
+ height: {
205
+ default: null,
206
+ parseHTML: (n) => n.getAttribute("height") || n.style.height || null,
207
+ renderHTML: (n) => n.height ? { style: `height: ${n.height}` } : {}
208
+ },
209
+ align: {
210
+ default: null,
211
+ parseHTML: (n) => n.getAttribute("data-align") || null,
212
+ renderHTML: (n) => {
213
+ if (!n.align) return {};
214
+ const t = {
215
+ left: "margin-right: auto",
216
+ center: "margin-left: auto; margin-right: auto",
217
+ right: "margin-left: auto"
218
+ };
219
+ return {
220
+ "data-align": n.align,
221
+ style: `display: block; ${t[n.align] || ""}`
222
+ };
223
+ }
224
+ }
225
+ };
226
+ },
227
+ addNodeView() {
228
+ return oe(Le);
229
+ }
230
+ }).configure({
231
+ allowBase64: !0,
232
+ inline: !1
233
+ }), He = ke.create({
234
+ name: "video",
235
+ group: "block",
236
+ atom: !0,
237
+ addAttributes() {
238
+ return {
239
+ src: { default: null },
240
+ width: { default: "100%" },
241
+ height: { default: "315" },
242
+ frameborder: { default: "0" },
243
+ allowfullscreen: { default: !0 }
244
+ };
245
+ },
246
+ parseHTML() {
247
+ return [{ tag: "iframe[src]" }];
248
+ },
249
+ renderHTML({ HTMLAttributes: e }) {
250
+ return ["div", { class: "video-wrapper" }, ["iframe", we(e)]];
251
+ },
252
+ addCommands() {
253
+ return {
254
+ setVideo: (e) => ({ commands: n }) => n.insertContent({
255
+ type: this.name,
256
+ attrs: e
257
+ })
258
+ };
259
+ }
260
+ }), Ee = {
261
+ toolbar: "bg-white border-b border-gray-200 p-2 flex flex-wrap items-center gap-1",
262
+ toolbarButton: "hover:bg-gray-100 rounded p-1.5 text-gray-600 cursor-pointer",
263
+ toolbarButtonActive: "bg-blue-100 text-blue-600",
264
+ editor: "bg-white min-h-[400px] p-4 prose max-w-none focus:outline-none",
265
+ dropdown: "bg-white border border-gray-200 rounded shadow-lg py-1 z-50",
266
+ modal: "bg-white rounded-lg shadow-xl p-6",
267
+ saveButton: "bg-blue-600 text-white rounded px-4 py-2 hover:bg-blue-700"
268
+ }, ze = {
269
+ maxSize: 5 * 1024 * 1024,
270
+ allowedTypes: ["image/jpeg", "image/png", "image/gif"]
271
+ }, Re = [
272
+ "Arial",
273
+ "Times New Roman",
274
+ "Courier New",
275
+ "Georgia",
276
+ "Verdana",
277
+ "Trebuchet MS",
278
+ "Comic Sans MS",
279
+ "Impact"
280
+ ], Fe = ["8", "10", "12", "14", "16", "18", "20", "24", "28", "32", "36", "48", "72"], Ve = ["1", "1.15", "1.5", "2", "2.5", "3"];
281
+ function Oe(e) {
282
+ const n = y([]), t = y(!1), c = y(null), o = {
283
+ "Content-Type": "application/json",
284
+ ...e.headers
285
+ };
286
+ async function a() {
287
+ t.value = !0, c.value = null;
288
+ try {
289
+ const s = await fetch(e.loadTemplates, { headers: o });
290
+ if (!s.ok) throw new Error(`Failed to load templates: ${s.statusText}`);
291
+ n.value = await s.json();
292
+ } catch (s) {
293
+ const r = s instanceof Error ? s.message : "Unknown error";
294
+ throw c.value = r, s;
295
+ } finally {
296
+ t.value = !1;
297
+ }
298
+ }
299
+ async function m(s) {
300
+ const r = await fetch(e.saveTemplate, {
301
+ method: "POST",
302
+ headers: o,
303
+ body: JSON.stringify(s)
304
+ });
305
+ if (!r.ok) throw new Error(`Failed to save template: ${r.statusText}`);
306
+ return r.json();
307
+ }
308
+ async function i(s) {
309
+ const r = await fetch(`${e.deleteTemplate}/${s}`, {
310
+ method: "DELETE",
311
+ headers: o
312
+ });
313
+ if (!r.ok) throw new Error(`Failed to delete template: ${r.statusText}`);
314
+ }
315
+ return { templates: n, loading: t, error: c, loadTemplates: a, saveTemplate: m, deleteTemplate: i };
316
+ }
317
+ const Q = Symbol("document-editor");
318
+ function tl() {
319
+ const e = _(Q);
320
+ if (!e)
321
+ throw new Error("useDocumentEditor must be used within a DocumentEditor component");
322
+ return {
323
+ editor: e,
324
+ getHTML: () => {
325
+ var n;
326
+ return ((n = e.value) == null ? void 0 : n.getHTML()) ?? "";
327
+ },
328
+ getText: () => {
329
+ var n;
330
+ return ((n = e.value) == null ? void 0 : n.getText()) ?? "";
331
+ },
332
+ setContent: (n) => {
333
+ var t;
334
+ return (t = e.value) == null ? void 0 : t.commands.setContent(n);
335
+ },
336
+ focus: () => {
337
+ var n;
338
+ return (n = e.value) == null ? void 0 : n.commands.focus();
339
+ },
340
+ isEmpty: () => {
341
+ var n;
342
+ return ((n = e.value) == null ? void 0 : n.isEmpty) ?? !0;
343
+ }
344
+ };
345
+ }
346
+ const De = ["title", "disabled"], k = /* @__PURE__ */ C({
347
+ __name: "ToolbarButton",
348
+ props: {
349
+ theme: {},
350
+ title: {},
351
+ isActive: { type: Boolean },
352
+ disabled: { type: Boolean }
353
+ },
354
+ emits: ["click"],
355
+ setup(e) {
356
+ return (n, t) => (g(), p("button", {
357
+ type: "button",
358
+ class: w([e.theme.toolbarButton, e.isActive && e.theme.toolbarButtonActive]),
359
+ title: e.title,
360
+ disabled: e.disabled,
361
+ onClick: t[0] || (t[0] = (c) => n.$emit("click"))
362
+ }, [
363
+ X(n.$slots, "default")
364
+ ], 10, De));
365
+ }
366
+ }), Ie = (e, n) => {
367
+ const t = e.__vccOpts || e;
368
+ for (const [c, o] of n)
369
+ t[c] = o;
370
+ return t;
371
+ }, Ue = {}, Ne = { class: "w-px h-6 bg-gray-300 mx-1" };
372
+ function Pe(e, n) {
373
+ return g(), p("div", Ne);
374
+ }
375
+ const R = /* @__PURE__ */ Ie(Ue, [["render", Pe]]), je = ["title"], G = /* @__PURE__ */ C({
376
+ __name: "ToolbarDropdown",
377
+ props: {
378
+ theme: {},
379
+ label: {},
380
+ title: {}
381
+ },
382
+ setup(e) {
383
+ const n = y(!1), t = y(null);
384
+ function c() {
385
+ n.value = !1;
386
+ }
387
+ function o(a) {
388
+ t.value && !t.value.contains(a.target) && (n.value = !1);
389
+ }
390
+ return U(() => document.addEventListener("click", o)), N(() => document.removeEventListener("click", o)), (a, m) => (g(), p("div", {
391
+ class: "relative",
392
+ ref_key: "dropdownRef",
393
+ ref: t
394
+ }, [
395
+ l("button", {
396
+ type: "button",
397
+ class: w([e.theme.toolbarButton, "flex items-center gap-1 px-2 text-sm"]),
398
+ title: e.title,
399
+ onClick: m[0] || (m[0] = (i) => n.value = !n.value)
400
+ }, [
401
+ l("span", null, z(e.label), 1),
402
+ m[1] || (m[1] = l("svg", {
403
+ class: "w-3 h-3",
404
+ viewBox: "0 0 12 12",
405
+ fill: "currentColor"
406
+ }, [
407
+ l("path", {
408
+ d: "M2 4l4 4 4-4",
409
+ stroke: "currentColor",
410
+ "stroke-width": "1.5",
411
+ fill: "none"
412
+ })
413
+ ], -1))
414
+ ], 10, je),
415
+ n.value ? (g(), p("div", {
416
+ key: 0,
417
+ class: w([e.theme.dropdown, "absolute top-full left-0 mt-1 min-w-[150px] max-h-60 overflow-y-auto"])
418
+ }, [
419
+ X(a.$slots, "default", { close: c })
420
+ ], 2)) : B("", !0)
421
+ ], 512));
422
+ }
423
+ }), Ge = ["onClick"], Ke = /* @__PURE__ */ C({
424
+ __name: "HeadingPicker",
425
+ props: {
426
+ editor: {},
427
+ theme: {}
428
+ },
429
+ setup(e) {
430
+ const n = e, t = [
431
+ { label: "Paragraph", value: "paragraph", class: "text-sm" },
432
+ { label: "Heading 1", value: 1, class: "text-2xl font-bold" },
433
+ { label: "Heading 2", value: 2, class: "text-xl font-bold" },
434
+ { label: "Heading 3", value: 3, class: "text-lg font-bold" },
435
+ { label: "Heading 4", value: 4, class: "text-base font-semibold" },
436
+ { label: "Heading 5", value: 5, class: "text-sm font-semibold" },
437
+ { label: "Heading 6", value: 6, class: "text-xs font-semibold" }
438
+ ];
439
+ function c(m) {
440
+ var i, s;
441
+ return m.value === "paragraph" ? (i = n.editor) == null ? void 0 : i.isActive("paragraph") : (s = n.editor) == null ? void 0 : s.isActive("heading", { level: m.value });
442
+ }
443
+ const o = H(() => {
444
+ const m = t.find((i) => c(i));
445
+ return (m == null ? void 0 : m.label) ?? "Paragraph";
446
+ });
447
+ function a(m) {
448
+ var i, s;
449
+ m.value === "paragraph" ? (i = n.editor) == null || i.chain().focus().setParagraph().run() : (s = n.editor) == null || s.chain().focus().toggleHeading({ level: m.value }).run();
450
+ }
451
+ return (m, i) => (g(), V(G, {
452
+ theme: e.theme,
453
+ label: o.value,
454
+ title: "Block type"
455
+ }, {
456
+ default: x(({ close: s }) => [
457
+ (g(), p(A, null, E(t, (r) => l("button", {
458
+ key: r.value,
459
+ class: w([
460
+ "block w-full text-left px-3 py-1.5 hover:bg-gray-100",
461
+ r.class,
462
+ c(r) ? "bg-gray-50 font-semibold" : ""
463
+ ]),
464
+ onClick: (d) => {
465
+ a(r), s();
466
+ }
467
+ }, z(r.label), 11, Ge)), 64))
468
+ ]),
469
+ _: 1
470
+ }, 8, ["theme", "label"]));
471
+ }
472
+ }), Je = ["onClick"], qe = /* @__PURE__ */ C({
473
+ __name: "FontFamilyPicker",
474
+ props: {
475
+ editor: {},
476
+ theme: {}
477
+ },
478
+ setup(e) {
479
+ const n = e, t = Re, c = H(() => {
480
+ var o;
481
+ for (const a of t)
482
+ if ((o = n.editor) != null && o.isActive("textStyle", { fontFamily: a })) return a;
483
+ return "Font";
484
+ });
485
+ return (o, a) => (g(), V(G, {
486
+ theme: e.theme,
487
+ label: c.value,
488
+ title: "Font family"
489
+ }, {
490
+ default: x(({ close: m }) => [
491
+ (g(!0), p(A, null, E(L(t), (i) => (g(), p("button", {
492
+ key: i,
493
+ style: D({ fontFamily: i }),
494
+ class: w([
495
+ "block w-full text-left px-3 py-1.5 hover:bg-gray-100 text-sm",
496
+ c.value === i ? "bg-gray-50 font-semibold" : ""
497
+ ]),
498
+ onClick: (s) => {
499
+ var r;
500
+ (r = e.editor) == null || r.chain().focus().setFontFamily(i).run(), m();
501
+ }
502
+ }, z(i), 15, Je))), 128))
503
+ ]),
504
+ _: 1
505
+ }, 8, ["theme", "label"]));
506
+ }
507
+ }), We = ["onClick"], Xe = /* @__PURE__ */ C({
508
+ __name: "FontSizePicker",
509
+ props: {
510
+ editor: {},
511
+ theme: {}
512
+ },
513
+ setup(e) {
514
+ const n = e, t = Fe, c = H(() => {
515
+ var o;
516
+ for (const a of t)
517
+ if ((o = n.editor) != null && o.isActive("textStyle", { fontSize: a + "px" })) return a;
518
+ return "";
519
+ });
520
+ return (o, a) => (g(), V(G, {
521
+ theme: e.theme,
522
+ label: c.value || "Size",
523
+ title: "Font size"
524
+ }, {
525
+ default: x(({ close: m }) => [
526
+ (g(!0), p(A, null, E(L(t), (i) => (g(), p("button", {
527
+ key: i,
528
+ class: w([
529
+ "block w-full text-left px-3 py-1.5 hover:bg-gray-100 text-sm",
530
+ c.value === i ? "bg-gray-50 font-semibold" : ""
531
+ ]),
532
+ onClick: (s) => {
533
+ var r;
534
+ (r = e.editor) == null || r.chain().focus().setFontSize(i + "px").run(), m();
535
+ }
536
+ }, z(i), 11, We))), 128))
537
+ ]),
538
+ _: 1
539
+ }, 8, ["theme", "label"]));
540
+ }
541
+ }), Ye = { class: "grid grid-cols-8 gap-1 mb-2" }, Ze = ["title", "onClick"], Qe = { class: "flex items-center gap-2 pt-2 border-t border-gray-100" }, _e = ["value"], et = /* @__PURE__ */ C({
542
+ __name: "ColorPicker",
543
+ props: {
544
+ editor: {},
545
+ theme: {}
546
+ },
547
+ setup(e) {
548
+ const n = e, t = y(!1), c = y(null), o = [
549
+ "#000000",
550
+ "#434343",
551
+ "#666666",
552
+ "#999999",
553
+ "#b7b7b7",
554
+ "#cccccc",
555
+ "#d9d9d9",
556
+ "#ffffff",
557
+ "#980000",
558
+ "#ff0000",
559
+ "#ff9900",
560
+ "#ffff00",
561
+ "#00ff00",
562
+ "#00ffff",
563
+ "#4a86e8",
564
+ "#0000ff",
565
+ "#9900ff",
566
+ "#ff00ff",
567
+ "#e6b8af",
568
+ "#f4cccc",
569
+ "#fce5cd",
570
+ "#fff2cc",
571
+ "#d9ead3",
572
+ "#d0e0e3",
573
+ "#c9daf8",
574
+ "#cfe2f3",
575
+ "#d9d2e9",
576
+ "#ead1dc",
577
+ "#dd7e6b",
578
+ "#ea9999",
579
+ "#f9cb9c",
580
+ "#ffe599",
581
+ "#b6d7a8",
582
+ "#a2c4c9",
583
+ "#a4c2f4",
584
+ "#9fc5e8",
585
+ "#b4a7d6",
586
+ "#d5a6bd"
587
+ ], a = H(() => {
588
+ var s;
589
+ return ((s = n.editor) == null ? void 0 : s.getAttributes("textStyle").color) || "#000000";
590
+ });
591
+ function m(s) {
592
+ var r;
593
+ (r = n.editor) == null || r.chain().focus().setColor(s).run(), t.value = !1;
594
+ }
595
+ function i(s) {
596
+ c.value && !c.value.contains(s.target) && (t.value = !1);
597
+ }
598
+ return U(() => document.addEventListener("click", i)), N(() => document.removeEventListener("click", i)), (s, r) => (g(), p("div", {
599
+ class: "relative",
600
+ ref_key: "pickerRef",
601
+ ref: c
602
+ }, [
603
+ l("button", {
604
+ type: "button",
605
+ class: w([e.theme.toolbarButton, "flex items-center gap-1 px-2"]),
606
+ title: "Font color",
607
+ onClick: r[0] || (r[0] = (d) => t.value = !t.value)
608
+ }, [
609
+ r[2] || (r[2] = l("span", null, "A", -1)),
610
+ l("div", {
611
+ class: "w-4 h-1 rounded",
612
+ style: D({ backgroundColor: a.value })
613
+ }, null, 4)
614
+ ], 2),
615
+ t.value ? (g(), p("div", {
616
+ key: 0,
617
+ class: w([e.theme.dropdown, "absolute top-full left-0 mt-1 p-2 w-48"])
618
+ }, [
619
+ l("div", Ye, [
620
+ (g(), p(A, null, E(o, (d) => l("button", {
621
+ key: d,
622
+ class: "w-5 h-5 rounded border border-gray-200 cursor-pointer hover:scale-110 transition-transform",
623
+ style: D({ backgroundColor: d }),
624
+ title: d,
625
+ onClick: (u) => m(d)
626
+ }, null, 12, Ze)), 64))
627
+ ]),
628
+ l("div", Qe, [
629
+ r[3] || (r[3] = l("label", { class: "text-xs text-gray-500" }, "Custom:", -1)),
630
+ l("input", {
631
+ type: "color",
632
+ value: a.value,
633
+ class: "w-6 h-6 cursor-pointer",
634
+ onInput: r[1] || (r[1] = (d) => m(d.target.value))
635
+ }, null, 40, _e)
636
+ ])
637
+ ], 2)) : B("", !0)
638
+ ], 512));
639
+ }
640
+ }), tt = /* @__PURE__ */ C({
641
+ __name: "AlignmentButtons",
642
+ props: {
643
+ editor: {},
644
+ theme: {}
645
+ },
646
+ setup(e) {
647
+ return (n, t) => {
648
+ var c, o, a, m;
649
+ return g(), p(A, null, [
650
+ h(k, {
651
+ theme: e.theme,
652
+ title: "Align left",
653
+ "is-active": (c = e.editor) == null ? void 0 : c.isActive({ textAlign: "left" }),
654
+ onClick: t[0] || (t[0] = (i) => {
655
+ var s;
656
+ return (s = e.editor) == null ? void 0 : s.chain().focus().setTextAlign("left").run();
657
+ })
658
+ }, {
659
+ default: x(() => [...t[4] || (t[4] = [
660
+ l("svg", {
661
+ class: "w-4 h-4",
662
+ viewBox: "0 0 24 24",
663
+ fill: "none",
664
+ stroke: "currentColor",
665
+ "stroke-width": "2"
666
+ }, [
667
+ l("path", { d: "M3 6h18M3 12h10M3 18h14" })
668
+ ], -1)
669
+ ])]),
670
+ _: 1
671
+ }, 8, ["theme", "is-active"]),
672
+ h(k, {
673
+ theme: e.theme,
674
+ title: "Align center",
675
+ "is-active": (o = e.editor) == null ? void 0 : o.isActive({ textAlign: "center" }),
676
+ onClick: t[1] || (t[1] = (i) => {
677
+ var s;
678
+ return (s = e.editor) == null ? void 0 : s.chain().focus().setTextAlign("center").run();
679
+ })
680
+ }, {
681
+ default: x(() => [...t[5] || (t[5] = [
682
+ l("svg", {
683
+ class: "w-4 h-4",
684
+ viewBox: "0 0 24 24",
685
+ fill: "none",
686
+ stroke: "currentColor",
687
+ "stroke-width": "2"
688
+ }, [
689
+ l("path", { d: "M3 6h18M7 12h10M5 18h14" })
690
+ ], -1)
691
+ ])]),
692
+ _: 1
693
+ }, 8, ["theme", "is-active"]),
694
+ h(k, {
695
+ theme: e.theme,
696
+ title: "Align right",
697
+ "is-active": (a = e.editor) == null ? void 0 : a.isActive({ textAlign: "right" }),
698
+ onClick: t[2] || (t[2] = (i) => {
699
+ var s;
700
+ return (s = e.editor) == null ? void 0 : s.chain().focus().setTextAlign("right").run();
701
+ })
702
+ }, {
703
+ default: x(() => [...t[6] || (t[6] = [
704
+ l("svg", {
705
+ class: "w-4 h-4",
706
+ viewBox: "0 0 24 24",
707
+ fill: "none",
708
+ stroke: "currentColor",
709
+ "stroke-width": "2"
710
+ }, [
711
+ l("path", { d: "M3 6h18M11 12h10M7 18h14" })
712
+ ], -1)
713
+ ])]),
714
+ _: 1
715
+ }, 8, ["theme", "is-active"]),
716
+ h(k, {
717
+ theme: e.theme,
718
+ title: "Justify",
719
+ "is-active": (m = e.editor) == null ? void 0 : m.isActive({ textAlign: "justify" }),
720
+ onClick: t[3] || (t[3] = (i) => {
721
+ var s;
722
+ return (s = e.editor) == null ? void 0 : s.chain().focus().setTextAlign("justify").run();
723
+ })
724
+ }, {
725
+ default: x(() => [...t[7] || (t[7] = [
726
+ l("svg", {
727
+ class: "w-4 h-4",
728
+ viewBox: "0 0 24 24",
729
+ fill: "none",
730
+ stroke: "currentColor",
731
+ "stroke-width": "2"
732
+ }, [
733
+ l("path", { d: "M3 6h18M3 12h18M3 18h18" })
734
+ ], -1)
735
+ ])]),
736
+ _: 1
737
+ }, 8, ["theme", "is-active"])
738
+ ], 64);
739
+ };
740
+ }
741
+ }), lt = ["onClick"], nt = /* @__PURE__ */ C({
742
+ __name: "LineHeightPicker",
743
+ props: {
744
+ editor: {},
745
+ theme: {}
746
+ },
747
+ setup(e) {
748
+ const n = e, t = Ve, c = H(() => {
749
+ var o, a;
750
+ return ((o = n.editor) == null ? void 0 : o.getAttributes("paragraph").lineHeight) || ((a = n.editor) == null ? void 0 : a.getAttributes("heading").lineHeight) || "";
751
+ });
752
+ return (o, a) => (g(), V(G, {
753
+ theme: e.theme,
754
+ label: c.value || "Height",
755
+ title: "Line height"
756
+ }, {
757
+ default: x(({ close: m }) => [
758
+ (g(!0), p(A, null, E(L(t), (i) => (g(), p("button", {
759
+ key: i,
760
+ class: w([
761
+ "block w-full text-left px-3 py-1.5 hover:bg-gray-100 text-sm",
762
+ c.value === i ? "bg-gray-50 font-semibold" : ""
763
+ ]),
764
+ onClick: (s) => {
765
+ var r;
766
+ (r = e.editor) == null || r.chain().focus().setLineHeight(i).run(), m();
767
+ }
768
+ }, z(i), 11, lt))), 128))
769
+ ]),
770
+ _: 1
771
+ }, 8, ["theme", "label"]));
772
+ }
773
+ }), ot = { class: "flex gap-2" }, it = /* @__PURE__ */ C({
774
+ __name: "LinkButton",
775
+ props: {
776
+ editor: {},
777
+ theme: {}
778
+ },
779
+ setup(e) {
780
+ const n = e, t = y(!1), c = y(""), o = y(null), a = y(null);
781
+ function m() {
782
+ var d;
783
+ c.value = ((d = n.editor) == null ? void 0 : d.getAttributes("link").href) || "", t.value = !t.value, t.value && ee(() => {
784
+ var u;
785
+ return (u = a.value) == null ? void 0 : u.focus();
786
+ });
787
+ }
788
+ function i() {
789
+ var d;
790
+ c.value && ((d = n.editor) == null || d.chain().focus().extendMarkRange("link").setLink({ href: c.value }).run()), t.value = !1;
791
+ }
792
+ function s() {
793
+ var d;
794
+ (d = n.editor) == null || d.chain().focus().unsetLink().run(), t.value = !1;
795
+ }
796
+ function r(d) {
797
+ o.value && !o.value.contains(d.target) && (t.value = !1);
798
+ }
799
+ return U(() => document.addEventListener("click", r)), N(() => document.removeEventListener("click", r)), (d, u) => {
800
+ var b, S;
801
+ return g(), p("div", {
802
+ class: "relative",
803
+ ref_key: "linkRef",
804
+ ref: o
805
+ }, [
806
+ h(k, {
807
+ theme: e.theme,
808
+ title: "Link",
809
+ "is-active": (b = e.editor) == null ? void 0 : b.isActive("link"),
810
+ onClick: m
811
+ }, {
812
+ default: x(() => [...u[2] || (u[2] = [
813
+ l("svg", {
814
+ class: "w-4 h-4",
815
+ viewBox: "0 0 24 24",
816
+ fill: "none",
817
+ stroke: "currentColor",
818
+ "stroke-width": "2"
819
+ }, [
820
+ l("path", { d: "M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71" }),
821
+ l("path", { d: "M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71" })
822
+ ], -1)
823
+ ])]),
824
+ _: 1
825
+ }, 8, ["theme", "is-active"]),
826
+ t.value ? (g(), p("div", {
827
+ key: 0,
828
+ class: w([e.theme.dropdown, "absolute top-full left-0 mt-1 p-3 w-72"])
829
+ }, [
830
+ u[3] || (u[3] = l("label", { class: "block text-xs text-gray-500 mb-1" }, "URL", -1)),
831
+ F(l("input", {
832
+ ref_key: "urlInput",
833
+ ref: a,
834
+ "onUpdate:modelValue": u[0] || (u[0] = (v) => c.value = v),
835
+ type: "url",
836
+ placeholder: "https://example.com",
837
+ class: "w-full border border-gray-300 rounded px-2 py-1 text-sm mb-2",
838
+ onKeydown: P(i, ["enter"])
839
+ }, null, 544), [
840
+ [I, c.value]
841
+ ]),
842
+ l("div", ot, [
843
+ l("button", {
844
+ class: "px-3 py-1 text-sm bg-blue-600 text-white rounded hover:bg-blue-700",
845
+ onClick: i
846
+ }, " Apply "),
847
+ (S = e.editor) != null && S.isActive("link") ? (g(), p("button", {
848
+ key: 0,
849
+ class: "px-3 py-1 text-sm bg-red-100 text-red-600 rounded hover:bg-red-200",
850
+ onClick: s
851
+ }, " Remove ")) : B("", !0),
852
+ l("button", {
853
+ class: "px-3 py-1 text-sm text-gray-500 hover:text-gray-700",
854
+ onClick: u[1] || (u[1] = (v) => t.value = !1)
855
+ }, " Cancel ")
856
+ ])
857
+ ], 2)) : B("", !0)
858
+ ], 512);
859
+ };
860
+ }
861
+ }), rt = ["accept"], st = /* @__PURE__ */ C({
862
+ __name: "ImageUploadButton",
863
+ props: {
864
+ editor: {},
865
+ theme: {},
866
+ imageConfig: {}
867
+ },
868
+ emits: ["error"],
869
+ setup(e, { emit: n }) {
870
+ const t = e, c = n, o = y(null), a = H(() => ({
871
+ ...ze,
872
+ ...t.imageConfig
873
+ })), m = H(() => a.value.allowedTypes.join(","));
874
+ function i() {
875
+ var r;
876
+ (r = o.value) == null || r.click();
877
+ }
878
+ function s(r) {
879
+ var S;
880
+ const d = r.target, u = (S = d.files) == null ? void 0 : S[0];
881
+ if (!u) return;
882
+ if (!a.value.allowedTypes.includes(u.type)) {
883
+ c("error", { message: `File type ${u.type} is not allowed`, detail: { allowedTypes: a.value.allowedTypes } }), d.value = "";
884
+ return;
885
+ }
886
+ if (u.size > a.value.maxSize) {
887
+ const v = (a.value.maxSize / 1048576).toFixed(1);
888
+ c("error", { message: `File size exceeds ${v}MB limit`, detail: { maxSize: a.value.maxSize, fileSize: u.size } }), d.value = "";
889
+ return;
890
+ }
891
+ const b = new FileReader();
892
+ b.onload = () => {
893
+ var f;
894
+ const v = b.result;
895
+ (f = t.editor) == null || f.chain().focus().setImage({ src: v }).run();
896
+ }, b.readAsDataURL(u), d.value = "";
897
+ }
898
+ return (r, d) => (g(), p(A, null, [
899
+ h(k, {
900
+ theme: e.theme,
901
+ title: "Insert image",
902
+ onClick: i
903
+ }, {
904
+ default: x(() => [...d[0] || (d[0] = [
905
+ l("svg", {
906
+ class: "w-4 h-4",
907
+ viewBox: "0 0 24 24",
908
+ fill: "none",
909
+ stroke: "currentColor",
910
+ "stroke-width": "2"
911
+ }, [
912
+ l("rect", {
913
+ x: "3",
914
+ y: "3",
915
+ width: "18",
916
+ height: "18",
917
+ rx: "2"
918
+ }),
919
+ l("circle", {
920
+ cx: "8.5",
921
+ cy: "8.5",
922
+ r: "1.5"
923
+ }),
924
+ l("path", { d: "M21 15l-5-5L5 21" })
925
+ ], -1)
926
+ ])]),
927
+ _: 1
928
+ }, 8, ["theme"]),
929
+ l("input", {
930
+ ref_key: "fileInput",
931
+ ref: o,
932
+ type: "file",
933
+ accept: m.value,
934
+ class: "hidden",
935
+ onChange: s
936
+ }, null, 40, rt)
937
+ ], 64));
938
+ }
939
+ }), at = { class: "mb-1 text-xs text-gray-500 text-center" }, ut = ["onMouseenter"], dt = 8, W = 10, ct = /* @__PURE__ */ C({
940
+ __name: "TableGridPicker",
941
+ props: {
942
+ editor: {},
943
+ theme: {}
944
+ },
945
+ setup(e) {
946
+ const n = e, t = y(!1), c = y(0), o = y(0), a = y(null);
947
+ function m(s, r) {
948
+ var d;
949
+ (d = n.editor) == null || d.chain().focus().insertTable({ rows: s, cols: r, withHeaderRow: !0 }).run(), t.value = !1, c.value = 0, o.value = 0;
950
+ }
951
+ function i(s) {
952
+ a.value && !a.value.contains(s.target) && (t.value = !1);
953
+ }
954
+ return U(() => document.addEventListener("click", i)), N(() => document.removeEventListener("click", i)), (s, r) => (g(), p("div", {
955
+ class: "relative",
956
+ ref_key: "pickerRef",
957
+ ref: a
958
+ }, [
959
+ h(k, {
960
+ theme: e.theme,
961
+ title: "Insert table",
962
+ onClick: r[0] || (r[0] = (d) => t.value = !t.value)
963
+ }, {
964
+ default: x(() => [...r[2] || (r[2] = [
965
+ l("svg", {
966
+ class: "w-4 h-4",
967
+ viewBox: "0 0 24 24",
968
+ fill: "none",
969
+ stroke: "currentColor",
970
+ "stroke-width": "2"
971
+ }, [
972
+ l("rect", {
973
+ x: "3",
974
+ y: "3",
975
+ width: "18",
976
+ height: "18",
977
+ rx: "1"
978
+ }),
979
+ l("path", { d: "M3 9h18M3 15h18M9 3v18M15 3v18" })
980
+ ], -1)
981
+ ])]),
982
+ _: 1
983
+ }, 8, ["theme"]),
984
+ t.value ? (g(), p("div", {
985
+ key: 0,
986
+ class: w([e.theme.dropdown, "absolute top-full left-0 mt-1 p-2"])
987
+ }, [
988
+ l("div", at, z(o.value > 0 ? `${o.value} × ${c.value}` : "Select size"), 1),
989
+ l("div", {
990
+ class: "grid gap-0.5",
991
+ style: D({ gridTemplateColumns: `repeat(${W}, 1fr)` })
992
+ }, [
993
+ (g(), p(A, null, E(dt, (d) => (g(), p(A, {
994
+ key: "row-" + d
995
+ }, [
996
+ (g(), p(A, null, E(W, (u) => l("div", {
997
+ key: "cell-" + d + "-" + u,
998
+ class: w(["w-5 h-5 border cursor-pointer", d <= c.value && u <= o.value ? "bg-blue-200 border-blue-300" : "bg-white border-gray-300"]),
999
+ onMouseenter: (b) => {
1000
+ c.value = d, o.value = u;
1001
+ },
1002
+ onClick: r[1] || (r[1] = (b) => m(c.value, o.value))
1003
+ }, null, 42, ut)), 64))
1004
+ ], 64))), 64))
1005
+ ], 4)
1006
+ ], 2)) : B("", !0)
1007
+ ], 512));
1008
+ }
1009
+ }), mt = { class: "flex gap-2" }, ft = /* @__PURE__ */ C({
1010
+ __name: "VideoEmbedButton",
1011
+ props: {
1012
+ editor: {},
1013
+ theme: {}
1014
+ },
1015
+ setup(e) {
1016
+ const n = e, t = y(!1), c = y(""), o = y(null);
1017
+ function a(s) {
1018
+ const r = s.match(/(?:youtube\.com\/watch\?v=|youtu\.be\/)([\w-]+)/);
1019
+ if (r) return `https://www.youtube.com/embed/${r[1]}`;
1020
+ const d = s.match(/vimeo\.com\/(\d+)/);
1021
+ return d ? `https://player.vimeo.com/video/${d[1]}` : s;
1022
+ }
1023
+ function m() {
1024
+ var s;
1025
+ if (c.value) {
1026
+ const r = a(c.value);
1027
+ (s = n.editor) == null || s.chain().focus().setVideo({ src: r }).run();
1028
+ }
1029
+ t.value = !1, c.value = "";
1030
+ }
1031
+ function i(s) {
1032
+ o.value && !o.value.contains(s.target) && (t.value = !1);
1033
+ }
1034
+ return U(() => document.addEventListener("click", i)), N(() => document.removeEventListener("click", i)), (s, r) => (g(), p("div", {
1035
+ class: "relative",
1036
+ ref_key: "videoRef",
1037
+ ref: o
1038
+ }, [
1039
+ h(k, {
1040
+ theme: e.theme,
1041
+ title: "Embed video",
1042
+ onClick: r[0] || (r[0] = (d) => t.value = !t.value)
1043
+ }, {
1044
+ default: x(() => [...r[3] || (r[3] = [
1045
+ l("svg", {
1046
+ class: "w-4 h-4",
1047
+ viewBox: "0 0 24 24",
1048
+ fill: "none",
1049
+ stroke: "currentColor",
1050
+ "stroke-width": "2"
1051
+ }, [
1052
+ l("polygon", { points: "5,3 19,12 5,21" })
1053
+ ], -1)
1054
+ ])]),
1055
+ _: 1
1056
+ }, 8, ["theme"]),
1057
+ t.value ? (g(), p("div", {
1058
+ key: 0,
1059
+ class: w([e.theme.dropdown, "absolute top-full left-0 mt-1 p-3 w-80"])
1060
+ }, [
1061
+ r[4] || (r[4] = l("label", { class: "block text-xs text-gray-500 mb-1" }, "Video URL (YouTube, Vimeo)", -1)),
1062
+ F(l("input", {
1063
+ "onUpdate:modelValue": r[1] || (r[1] = (d) => c.value = d),
1064
+ type: "url",
1065
+ placeholder: "https://www.youtube.com/watch?v=...",
1066
+ class: "w-full border border-gray-300 rounded px-2 py-1 text-sm mb-2",
1067
+ onKeydown: P(m, ["enter"])
1068
+ }, null, 544), [
1069
+ [I, c.value]
1070
+ ]),
1071
+ l("div", mt, [
1072
+ l("button", {
1073
+ class: "px-3 py-1 text-sm bg-blue-600 text-white rounded hover:bg-blue-700",
1074
+ onClick: m
1075
+ }, " Embed "),
1076
+ l("button", {
1077
+ class: "px-3 py-1 text-sm text-gray-500 hover:text-gray-700",
1078
+ onClick: r[2] || (r[2] = (d) => t.value = !1)
1079
+ }, " Cancel ")
1080
+ ])
1081
+ ], 2)) : B("", !0)
1082
+ ], 512));
1083
+ }
1084
+ }), vt = /* @__PURE__ */ C({
1085
+ __name: "EditorToolbar",
1086
+ props: {
1087
+ editor: {},
1088
+ theme: {},
1089
+ imageConfig: {}
1090
+ },
1091
+ emits: ["saveTemplate", "loadTemplate", "save", "error"],
1092
+ setup(e) {
1093
+ return (n, t) => {
1094
+ var c, o, a, m, i, s, r, d, u, b, S;
1095
+ return g(), p("div", {
1096
+ class: w(e.theme.toolbar)
1097
+ }, [
1098
+ h(k, {
1099
+ theme: e.theme,
1100
+ title: "Undo",
1101
+ onClick: t[0] || (t[0] = (v) => {
1102
+ var f;
1103
+ return (f = e.editor) == null ? void 0 : f.chain().focus().undo().run();
1104
+ }),
1105
+ disabled: !((c = e.editor) != null && c.can().undo())
1106
+ }, {
1107
+ default: x(() => [...t[16] || (t[16] = [
1108
+ l("svg", {
1109
+ class: "w-4 h-4",
1110
+ viewBox: "0 0 24 24",
1111
+ fill: "none",
1112
+ stroke: "currentColor",
1113
+ "stroke-width": "2"
1114
+ }, [
1115
+ l("path", { d: "M3 10h10a5 5 0 0 1 0 10H9" }),
1116
+ l("path", { d: "M3 10l4-4M3 10l4 4" })
1117
+ ], -1)
1118
+ ])]),
1119
+ _: 1
1120
+ }, 8, ["theme", "disabled"]),
1121
+ h(k, {
1122
+ theme: e.theme,
1123
+ title: "Redo",
1124
+ onClick: t[1] || (t[1] = (v) => {
1125
+ var f;
1126
+ return (f = e.editor) == null ? void 0 : f.chain().focus().redo().run();
1127
+ }),
1128
+ disabled: !((o = e.editor) != null && o.can().redo())
1129
+ }, {
1130
+ default: x(() => [...t[17] || (t[17] = [
1131
+ l("svg", {
1132
+ class: "w-4 h-4",
1133
+ viewBox: "0 0 24 24",
1134
+ fill: "none",
1135
+ stroke: "currentColor",
1136
+ "stroke-width": "2"
1137
+ }, [
1138
+ l("path", { d: "M21 10H11a5 5 0 0 0 0 10h4" }),
1139
+ l("path", { d: "M21 10l-4-4M21 10l-4 4" })
1140
+ ], -1)
1141
+ ])]),
1142
+ _: 1
1143
+ }, 8, ["theme", "disabled"]),
1144
+ h(R),
1145
+ h(Ke, {
1146
+ editor: e.editor,
1147
+ theme: e.theme
1148
+ }, null, 8, ["editor", "theme"]),
1149
+ h(R),
1150
+ h(qe, {
1151
+ editor: e.editor,
1152
+ theme: e.theme
1153
+ }, null, 8, ["editor", "theme"]),
1154
+ h(Xe, {
1155
+ editor: e.editor,
1156
+ theme: e.theme
1157
+ }, null, 8, ["editor", "theme"]),
1158
+ h(R),
1159
+ h(k, {
1160
+ theme: e.theme,
1161
+ title: "Bold",
1162
+ "is-active": (a = e.editor) == null ? void 0 : a.isActive("bold"),
1163
+ onClick: t[2] || (t[2] = (v) => {
1164
+ var f;
1165
+ return (f = e.editor) == null ? void 0 : f.chain().focus().toggleBold().run();
1166
+ })
1167
+ }, {
1168
+ default: x(() => [...t[18] || (t[18] = [
1169
+ l("svg", {
1170
+ class: "w-4 h-4",
1171
+ viewBox: "0 0 24 24",
1172
+ fill: "none",
1173
+ stroke: "currentColor",
1174
+ "stroke-width": "2"
1175
+ }, [
1176
+ l("path", { d: "M6 4h8a4 4 0 0 1 0 8H6V4zm0 8h9a4.5 4.5 0 0 1 0 9H6v-9z" })
1177
+ ], -1)
1178
+ ])]),
1179
+ _: 1
1180
+ }, 8, ["theme", "is-active"]),
1181
+ h(k, {
1182
+ theme: e.theme,
1183
+ title: "Italic",
1184
+ "is-active": (m = e.editor) == null ? void 0 : m.isActive("italic"),
1185
+ onClick: t[3] || (t[3] = (v) => {
1186
+ var f;
1187
+ return (f = e.editor) == null ? void 0 : f.chain().focus().toggleItalic().run();
1188
+ })
1189
+ }, {
1190
+ default: x(() => [...t[19] || (t[19] = [
1191
+ l("svg", {
1192
+ class: "w-4 h-4",
1193
+ viewBox: "0 0 24 24",
1194
+ fill: "none",
1195
+ stroke: "currentColor",
1196
+ "stroke-width": "2"
1197
+ }, [
1198
+ l("path", { d: "M10 4h4M14 4l-4 16M6 20h4" })
1199
+ ], -1)
1200
+ ])]),
1201
+ _: 1
1202
+ }, 8, ["theme", "is-active"]),
1203
+ h(k, {
1204
+ theme: e.theme,
1205
+ title: "Underline",
1206
+ "is-active": (i = e.editor) == null ? void 0 : i.isActive("underline"),
1207
+ onClick: t[4] || (t[4] = (v) => {
1208
+ var f;
1209
+ return (f = e.editor) == null ? void 0 : f.chain().focus().toggleUnderline().run();
1210
+ })
1211
+ }, {
1212
+ default: x(() => [...t[20] || (t[20] = [
1213
+ l("svg", {
1214
+ class: "w-4 h-4",
1215
+ viewBox: "0 0 24 24",
1216
+ fill: "none",
1217
+ stroke: "currentColor",
1218
+ "stroke-width": "2"
1219
+ }, [
1220
+ l("path", { d: "M6 4v6a6 6 0 0 0 12 0V4M4 20h16" })
1221
+ ], -1)
1222
+ ])]),
1223
+ _: 1
1224
+ }, 8, ["theme", "is-active"]),
1225
+ h(k, {
1226
+ theme: e.theme,
1227
+ title: "Strikethrough",
1228
+ "is-active": (s = e.editor) == null ? void 0 : s.isActive("strike"),
1229
+ onClick: t[5] || (t[5] = (v) => {
1230
+ var f;
1231
+ return (f = e.editor) == null ? void 0 : f.chain().focus().toggleStrike().run();
1232
+ })
1233
+ }, {
1234
+ default: x(() => [...t[21] || (t[21] = [
1235
+ l("svg", {
1236
+ class: "w-4 h-4",
1237
+ viewBox: "0 0 24 24",
1238
+ fill: "none",
1239
+ stroke: "currentColor",
1240
+ "stroke-width": "2"
1241
+ }, [
1242
+ l("path", { d: "M4 12h16M7 5c0 0 1-1 5-1s5 2 5 4-2 3-5 3M7 19c0 0 1 1 5 1s5-2 5-4" })
1243
+ ], -1)
1244
+ ])]),
1245
+ _: 1
1246
+ }, 8, ["theme", "is-active"]),
1247
+ h(k, {
1248
+ theme: e.theme,
1249
+ title: "Subscript",
1250
+ "is-active": (r = e.editor) == null ? void 0 : r.isActive("subscript"),
1251
+ onClick: t[6] || (t[6] = (v) => {
1252
+ var f;
1253
+ return (f = e.editor) == null ? void 0 : f.chain().focus().toggleSubscript().run();
1254
+ })
1255
+ }, {
1256
+ default: x(() => [...t[22] || (t[22] = [
1257
+ l("span", { class: "text-xs font-semibold" }, [
1258
+ j("X"),
1259
+ l("sub", null, "2")
1260
+ ], -1)
1261
+ ])]),
1262
+ _: 1
1263
+ }, 8, ["theme", "is-active"]),
1264
+ h(k, {
1265
+ theme: e.theme,
1266
+ title: "Superscript",
1267
+ "is-active": (d = e.editor) == null ? void 0 : d.isActive("superscript"),
1268
+ onClick: t[7] || (t[7] = (v) => {
1269
+ var f;
1270
+ return (f = e.editor) == null ? void 0 : f.chain().focus().toggleSuperscript().run();
1271
+ })
1272
+ }, {
1273
+ default: x(() => [...t[23] || (t[23] = [
1274
+ l("span", { class: "text-xs font-semibold" }, [
1275
+ j("X"),
1276
+ l("sup", null, "2")
1277
+ ], -1)
1278
+ ])]),
1279
+ _: 1
1280
+ }, 8, ["theme", "is-active"]),
1281
+ h(et, {
1282
+ editor: e.editor,
1283
+ theme: e.theme
1284
+ }, null, 8, ["editor", "theme"]),
1285
+ h(R),
1286
+ h(tt, {
1287
+ editor: e.editor,
1288
+ theme: e.theme
1289
+ }, null, 8, ["editor", "theme"]),
1290
+ h(nt, {
1291
+ editor: e.editor,
1292
+ theme: e.theme
1293
+ }, null, 8, ["editor", "theme"]),
1294
+ h(R),
1295
+ h(k, {
1296
+ theme: e.theme,
1297
+ title: "Bullet list",
1298
+ "is-active": (u = e.editor) == null ? void 0 : u.isActive("bulletList"),
1299
+ onClick: t[8] || (t[8] = (v) => {
1300
+ var f;
1301
+ return (f = e.editor) == null ? void 0 : f.chain().focus().toggleBulletList().run();
1302
+ })
1303
+ }, {
1304
+ default: x(() => [...t[24] || (t[24] = [
1305
+ l("svg", {
1306
+ class: "w-4 h-4",
1307
+ viewBox: "0 0 24 24",
1308
+ fill: "none",
1309
+ stroke: "currentColor",
1310
+ "stroke-width": "2"
1311
+ }, [
1312
+ l("circle", {
1313
+ cx: "4",
1314
+ cy: "6",
1315
+ r: "1.5",
1316
+ fill: "currentColor"
1317
+ }),
1318
+ l("path", { d: "M9 6h12" }),
1319
+ l("circle", {
1320
+ cx: "4",
1321
+ cy: "12",
1322
+ r: "1.5",
1323
+ fill: "currentColor"
1324
+ }),
1325
+ l("path", { d: "M9 12h12" }),
1326
+ l("circle", {
1327
+ cx: "4",
1328
+ cy: "18",
1329
+ r: "1.5",
1330
+ fill: "currentColor"
1331
+ }),
1332
+ l("path", { d: "M9 18h12" })
1333
+ ], -1)
1334
+ ])]),
1335
+ _: 1
1336
+ }, 8, ["theme", "is-active"]),
1337
+ h(k, {
1338
+ theme: e.theme,
1339
+ title: "Numbered list",
1340
+ "is-active": (b = e.editor) == null ? void 0 : b.isActive("orderedList"),
1341
+ onClick: t[9] || (t[9] = (v) => {
1342
+ var f;
1343
+ return (f = e.editor) == null ? void 0 : f.chain().focus().toggleOrderedList().run();
1344
+ })
1345
+ }, {
1346
+ default: x(() => [...t[25] || (t[25] = [
1347
+ l("svg", {
1348
+ class: "w-4 h-4",
1349
+ viewBox: "0 0 24 24",
1350
+ fill: "none",
1351
+ stroke: "currentColor",
1352
+ "stroke-width": "2"
1353
+ }, [
1354
+ l("text", {
1355
+ x: "2",
1356
+ y: "8",
1357
+ "font-size": "7",
1358
+ fill: "currentColor",
1359
+ stroke: "none"
1360
+ }, "1"),
1361
+ l("path", { d: "M9 6h12" }),
1362
+ l("text", {
1363
+ x: "2",
1364
+ y: "14",
1365
+ "font-size": "7",
1366
+ fill: "currentColor",
1367
+ stroke: "none"
1368
+ }, "2"),
1369
+ l("path", { d: "M9 12h12" }),
1370
+ l("text", {
1371
+ x: "2",
1372
+ y: "20",
1373
+ "font-size": "7",
1374
+ fill: "currentColor",
1375
+ stroke: "none"
1376
+ }, "3"),
1377
+ l("path", { d: "M9 18h12" })
1378
+ ], -1)
1379
+ ])]),
1380
+ _: 1
1381
+ }, 8, ["theme", "is-active"]),
1382
+ h(k, {
1383
+ theme: e.theme,
1384
+ title: "Blockquote",
1385
+ "is-active": (S = e.editor) == null ? void 0 : S.isActive("blockquote"),
1386
+ onClick: t[10] || (t[10] = (v) => {
1387
+ var f;
1388
+ return (f = e.editor) == null ? void 0 : f.chain().focus().toggleBlockquote().run();
1389
+ })
1390
+ }, {
1391
+ default: x(() => [...t[26] || (t[26] = [
1392
+ l("svg", {
1393
+ class: "w-4 h-4",
1394
+ viewBox: "0 0 24 24",
1395
+ fill: "currentColor"
1396
+ }, [
1397
+ l("path", {
1398
+ d: "M3 3h8v8H3zM13 3h8v8h-8zM5 11l-2 6h4l2-6zM15 11l-2 6h4l2-6z",
1399
+ opacity: "0.6"
1400
+ })
1401
+ ], -1)
1402
+ ])]),
1403
+ _: 1
1404
+ }, 8, ["theme", "is-active"]),
1405
+ h(k, {
1406
+ theme: e.theme,
1407
+ title: "Horizontal rule",
1408
+ onClick: t[11] || (t[11] = (v) => {
1409
+ var f;
1410
+ return (f = e.editor) == null ? void 0 : f.chain().focus().setHorizontalRule().run();
1411
+ })
1412
+ }, {
1413
+ default: x(() => [...t[27] || (t[27] = [
1414
+ l("svg", {
1415
+ class: "w-4 h-4",
1416
+ viewBox: "0 0 24 24",
1417
+ fill: "none",
1418
+ stroke: "currentColor",
1419
+ "stroke-width": "2"
1420
+ }, [
1421
+ l("path", { d: "M3 12h18" })
1422
+ ], -1)
1423
+ ])]),
1424
+ _: 1
1425
+ }, 8, ["theme"]),
1426
+ h(R),
1427
+ h(it, {
1428
+ editor: e.editor,
1429
+ theme: e.theme
1430
+ }, null, 8, ["editor", "theme"]),
1431
+ h(st, {
1432
+ editor: e.editor,
1433
+ theme: e.theme,
1434
+ "image-config": e.imageConfig,
1435
+ onError: t[12] || (t[12] = (v) => n.$emit("error", v))
1436
+ }, null, 8, ["editor", "theme", "image-config"]),
1437
+ h(ct, {
1438
+ editor: e.editor,
1439
+ theme: e.theme
1440
+ }, null, 8, ["editor", "theme"]),
1441
+ h(ft, {
1442
+ editor: e.editor,
1443
+ theme: e.theme
1444
+ }, null, 8, ["editor", "theme"]),
1445
+ h(R),
1446
+ h(k, {
1447
+ theme: e.theme,
1448
+ title: "Save as template",
1449
+ onClick: t[13] || (t[13] = (v) => n.$emit("saveTemplate"))
1450
+ }, {
1451
+ default: x(() => [...t[28] || (t[28] = [
1452
+ l("svg", {
1453
+ class: "w-4 h-4",
1454
+ viewBox: "0 0 24 24",
1455
+ fill: "none",
1456
+ stroke: "currentColor",
1457
+ "stroke-width": "2"
1458
+ }, [
1459
+ l("path", { d: "M19 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11l5 5v11a2 2 0 0 1-2 2z" }),
1460
+ l("polyline", { points: "17,21 17,13 7,13 7,21" }),
1461
+ l("polyline", { points: "7,3 7,8 15,8" })
1462
+ ], -1)
1463
+ ])]),
1464
+ _: 1
1465
+ }, 8, ["theme"]),
1466
+ h(k, {
1467
+ theme: e.theme,
1468
+ title: "Load template",
1469
+ onClick: t[14] || (t[14] = (v) => n.$emit("loadTemplate"))
1470
+ }, {
1471
+ default: x(() => [...t[29] || (t[29] = [
1472
+ l("svg", {
1473
+ class: "w-4 h-4",
1474
+ viewBox: "0 0 24 24",
1475
+ fill: "none",
1476
+ stroke: "currentColor",
1477
+ "stroke-width": "2"
1478
+ }, [
1479
+ l("path", { d: "M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z" })
1480
+ ], -1)
1481
+ ])]),
1482
+ _: 1
1483
+ }, 8, ["theme"]),
1484
+ h(R),
1485
+ l("button", {
1486
+ class: w(e.theme.saveButton),
1487
+ onClick: t[15] || (t[15] = (v) => n.$emit("save"))
1488
+ }, " Save ", 2)
1489
+ ], 2);
1490
+ };
1491
+ }
1492
+ }), gt = {
1493
+ key: 0,
1494
+ class: "bg-white border border-gray-200 rounded-lg shadow-lg p-2 flex flex-wrap gap-1 mb-1"
1495
+ }, ht = { class: "flex gap-1" }, pt = { class: "flex gap-1" }, bt = { class: "flex gap-1" }, xt = { class: "flex gap-1 items-center" }, yt = /* @__PURE__ */ C({
1496
+ __name: "TablePopoverMenu",
1497
+ props: {
1498
+ editor: {}
1499
+ },
1500
+ setup(e) {
1501
+ const n = e;
1502
+ function t(c) {
1503
+ var o;
1504
+ (o = n.editor) == null || o.chain().focus().setCellAttribute("backgroundColor", c).run();
1505
+ }
1506
+ return (c, o) => {
1507
+ var a;
1508
+ return (a = e.editor) != null && a.isActive("table") ? (g(), p("div", gt, [
1509
+ l("div", ht, [
1510
+ l("button", {
1511
+ class: "px-2 py-1 text-xs rounded hover:bg-gray-100",
1512
+ onClick: o[0] || (o[0] = (m) => {
1513
+ var i;
1514
+ return (i = e.editor) == null ? void 0 : i.chain().focus().addRowBefore().run();
1515
+ })
1516
+ }, " + Row Above "),
1517
+ l("button", {
1518
+ class: "px-2 py-1 text-xs rounded hover:bg-gray-100",
1519
+ onClick: o[1] || (o[1] = (m) => {
1520
+ var i;
1521
+ return (i = e.editor) == null ? void 0 : i.chain().focus().addRowAfter().run();
1522
+ })
1523
+ }, " + Row Below "),
1524
+ l("button", {
1525
+ class: "px-2 py-1 text-xs rounded hover:bg-red-50 text-red-600",
1526
+ onClick: o[2] || (o[2] = (m) => {
1527
+ var i;
1528
+ return (i = e.editor) == null ? void 0 : i.chain().focus().deleteRow().run();
1529
+ })
1530
+ }, " Delete Row ")
1531
+ ]),
1532
+ o[12] || (o[12] = l("span", { class: "w-px h-6 bg-gray-300" }, null, -1)),
1533
+ l("div", pt, [
1534
+ l("button", {
1535
+ class: "px-2 py-1 text-xs rounded hover:bg-gray-100",
1536
+ onClick: o[3] || (o[3] = (m) => {
1537
+ var i;
1538
+ return (i = e.editor) == null ? void 0 : i.chain().focus().addColumnBefore().run();
1539
+ })
1540
+ }, " + Col Left "),
1541
+ l("button", {
1542
+ class: "px-2 py-1 text-xs rounded hover:bg-gray-100",
1543
+ onClick: o[4] || (o[4] = (m) => {
1544
+ var i;
1545
+ return (i = e.editor) == null ? void 0 : i.chain().focus().addColumnAfter().run();
1546
+ })
1547
+ }, " + Col Right "),
1548
+ l("button", {
1549
+ class: "px-2 py-1 text-xs rounded hover:bg-red-50 text-red-600",
1550
+ onClick: o[5] || (o[5] = (m) => {
1551
+ var i;
1552
+ return (i = e.editor) == null ? void 0 : i.chain().focus().deleteColumn().run();
1553
+ })
1554
+ }, " Delete Col ")
1555
+ ]),
1556
+ o[13] || (o[13] = l("span", { class: "w-px h-6 bg-gray-300" }, null, -1)),
1557
+ l("div", bt, [
1558
+ l("button", {
1559
+ class: "px-2 py-1 text-xs rounded hover:bg-gray-100",
1560
+ onClick: o[6] || (o[6] = (m) => {
1561
+ var i;
1562
+ return (i = e.editor) == null ? void 0 : i.chain().focus().mergeCells().run();
1563
+ })
1564
+ }, " Merge "),
1565
+ l("button", {
1566
+ class: "px-2 py-1 text-xs rounded hover:bg-gray-100",
1567
+ onClick: o[7] || (o[7] = (m) => {
1568
+ var i;
1569
+ return (i = e.editor) == null ? void 0 : i.chain().focus().splitCell().run();
1570
+ })
1571
+ }, " Split ")
1572
+ ]),
1573
+ o[14] || (o[14] = l("span", { class: "w-px h-6 bg-gray-300" }, null, -1)),
1574
+ l("button", {
1575
+ class: "px-2 py-1 text-xs rounded hover:bg-gray-100",
1576
+ onClick: o[8] || (o[8] = (m) => {
1577
+ var i;
1578
+ return (i = e.editor) == null ? void 0 : i.chain().focus().toggleHeaderRow().run();
1579
+ })
1580
+ }, " Toggle Header "),
1581
+ l("button", {
1582
+ class: "px-2 py-1 text-xs rounded hover:bg-red-50 text-red-600",
1583
+ onClick: o[9] || (o[9] = (m) => {
1584
+ var i;
1585
+ return (i = e.editor) == null ? void 0 : i.chain().focus().deleteTable().run();
1586
+ })
1587
+ }, " Delete Table "),
1588
+ o[15] || (o[15] = l("span", { class: "w-px h-6 bg-gray-300" }, null, -1)),
1589
+ l("div", xt, [
1590
+ o[11] || (o[11] = l("label", { class: "text-xs text-gray-500" }, "Cell BG:", -1)),
1591
+ l("input", {
1592
+ type: "color",
1593
+ class: "w-5 h-5 cursor-pointer",
1594
+ onInput: o[10] || (o[10] = (m) => t(m.target.value))
1595
+ }, null, 32)
1596
+ ])
1597
+ ])) : B("", !0);
1598
+ };
1599
+ }
1600
+ }), kt = { class: "mb-3" }, wt = { class: "mb-4" }, Ct = { class: "flex gap-4" }, $t = { class: "flex items-center gap-2 text-sm" }, Tt = { class: "flex items-center gap-2 text-sm" }, Mt = { class: "flex justify-end gap-2" }, At = ["disabled"], St = /* @__PURE__ */ C({
1601
+ __name: "SaveTemplateModal",
1602
+ props: {
1603
+ theme: {}
1604
+ },
1605
+ emits: ["save"],
1606
+ setup(e, { expose: n, emit: t }) {
1607
+ const c = t, o = y(!1), a = y(""), m = y("document");
1608
+ function i() {
1609
+ a.value = "", m.value = "document", o.value = !0;
1610
+ }
1611
+ function s() {
1612
+ o.value = !1;
1613
+ }
1614
+ function r() {
1615
+ c("save", { name: a.value.trim(), type: m.value }), s();
1616
+ }
1617
+ return n({ open: i, close: s }), (d, u) => (g(), V(Y, { to: "body" }, [
1618
+ o.value ? (g(), p("div", {
1619
+ key: 0,
1620
+ class: "fixed inset-0 bg-black/50 flex items-center justify-center z-50",
1621
+ onClick: K(s, ["self"])
1622
+ }, [
1623
+ l("div", {
1624
+ class: w([e.theme.modal, "w-96"])
1625
+ }, [
1626
+ u[7] || (u[7] = l("h2", { class: "text-lg font-semibold mb-4" }, "Save as Template", -1)),
1627
+ l("div", kt, [
1628
+ u[3] || (u[3] = l("label", { class: "block text-sm font-medium text-gray-700 mb-1" }, "Template Name", -1)),
1629
+ F(l("input", {
1630
+ "onUpdate:modelValue": u[0] || (u[0] = (b) => a.value = b),
1631
+ type: "text",
1632
+ class: "w-full border border-gray-300 rounded px-3 py-2 text-sm",
1633
+ placeholder: "My Template"
1634
+ }, null, 512), [
1635
+ [I, a.value]
1636
+ ])
1637
+ ]),
1638
+ l("div", wt, [
1639
+ u[6] || (u[6] = l("label", { class: "block text-sm font-medium text-gray-700 mb-1" }, "Type", -1)),
1640
+ l("div", Ct, [
1641
+ l("label", $t, [
1642
+ F(l("input", {
1643
+ "onUpdate:modelValue": u[1] || (u[1] = (b) => m.value = b),
1644
+ type: "radio",
1645
+ value: "document"
1646
+ }, null, 512), [
1647
+ [J, m.value]
1648
+ ]),
1649
+ u[4] || (u[4] = j(" Full Document ", -1))
1650
+ ]),
1651
+ l("label", Tt, [
1652
+ F(l("input", {
1653
+ "onUpdate:modelValue": u[2] || (u[2] = (b) => m.value = b),
1654
+ type: "radio",
1655
+ value: "snippet"
1656
+ }, null, 512), [
1657
+ [J, m.value]
1658
+ ]),
1659
+ u[5] || (u[5] = j(" Snippet ", -1))
1660
+ ])
1661
+ ])
1662
+ ]),
1663
+ l("div", Mt, [
1664
+ l("button", {
1665
+ class: "px-4 py-2 text-sm text-gray-600 hover:text-gray-800",
1666
+ onClick: s
1667
+ }, "Cancel"),
1668
+ l("button", {
1669
+ class: w(e.theme.saveButton),
1670
+ disabled: !a.value.trim(),
1671
+ onClick: r
1672
+ }, "Save", 10, At)
1673
+ ])
1674
+ ], 2)
1675
+ ])) : B("", !0)
1676
+ ]));
1677
+ }
1678
+ }), Lt = {
1679
+ key: 0,
1680
+ class: "text-center py-8 text-gray-500"
1681
+ }, Bt = {
1682
+ key: 1,
1683
+ class: "text-center py-8 text-gray-500"
1684
+ }, Ht = {
1685
+ key: 2,
1686
+ class: "overflow-y-auto flex-1 -mx-6 px-6"
1687
+ }, Et = ["onClick"], zt = { class: "font-medium text-sm" }, Rt = ["onClick"], Ft = /* @__PURE__ */ C({
1688
+ __name: "LoadTemplateModal",
1689
+ props: {
1690
+ theme: {},
1691
+ templates: {},
1692
+ loading: { type: Boolean }
1693
+ },
1694
+ emits: ["select", "delete", "load"],
1695
+ setup(e, { expose: n, emit: t }) {
1696
+ const c = t, o = y(!1);
1697
+ function a() {
1698
+ o.value = !0, c("load");
1699
+ }
1700
+ function m() {
1701
+ o.value = !1;
1702
+ }
1703
+ function i(r) {
1704
+ c("select", r), m();
1705
+ }
1706
+ function s(r) {
1707
+ confirm(`Delete template "${r.name}"?`) && c("delete", r);
1708
+ }
1709
+ return n({ open: a, close: m }), (r, d) => (g(), V(Y, { to: "body" }, [
1710
+ o.value ? (g(), p("div", {
1711
+ key: 0,
1712
+ class: "fixed inset-0 bg-black/50 flex items-center justify-center z-50",
1713
+ onClick: K(m, ["self"])
1714
+ }, [
1715
+ l("div", {
1716
+ class: w([e.theme.modal, "w-[500px] max-h-[80vh] flex flex-col"])
1717
+ }, [
1718
+ d[0] || (d[0] = l("h2", { class: "text-lg font-semibold mb-4" }, "Load Template", -1)),
1719
+ e.loading ? (g(), p("div", Lt, "Loading templates...")) : e.templates.length === 0 ? (g(), p("div", Bt, "No templates found")) : (g(), p("div", Ht, [
1720
+ (g(!0), p(A, null, E(e.templates, (u) => (g(), p("div", {
1721
+ key: u.id,
1722
+ class: "flex items-center justify-between p-3 border border-gray-200 rounded mb-2 hover:bg-gray-50 cursor-pointer group",
1723
+ onClick: (b) => i(u)
1724
+ }, [
1725
+ l("div", null, [
1726
+ l("div", zt, z(u.name), 1),
1727
+ l("span", {
1728
+ class: w(["inline-block text-xs px-2 py-0.5 rounded mt-1", u.type === "document" ? "bg-blue-100 text-blue-700" : "bg-green-100 text-green-700"])
1729
+ }, z(u.type === "document" ? "Document" : "Snippet"), 3)
1730
+ ]),
1731
+ l("button", {
1732
+ class: "text-red-400 hover:text-red-600 opacity-0 group-hover:opacity-100 text-sm px-2",
1733
+ onClick: K((b) => s(u), ["stop"])
1734
+ }, " Delete ", 8, Rt)
1735
+ ], 8, Et))), 128))
1736
+ ])),
1737
+ l("div", { class: "flex justify-end pt-4" }, [
1738
+ l("button", {
1739
+ class: "px-4 py-2 text-sm text-gray-600 hover:text-gray-800",
1740
+ onClick: m
1741
+ }, "Cancel")
1742
+ ])
1743
+ ], 2)
1744
+ ])) : B("", !0)
1745
+ ]));
1746
+ }
1747
+ }), Vt = { class: "border border-gray-200 rounded-lg overflow-hidden" }, ll = /* @__PURE__ */ C({
1748
+ __name: "DocumentEditor",
1749
+ props: {
1750
+ modelValue: {},
1751
+ mode: { default: "document" },
1752
+ templateMeta: {},
1753
+ api: {},
1754
+ image: {},
1755
+ theme: {},
1756
+ placeholder: { default: "" },
1757
+ readonly: { type: Boolean, default: !1 }
1758
+ },
1759
+ emits: ["update:modelValue", "save", "error"],
1760
+ setup(e, { emit: n }) {
1761
+ const t = e, c = n, o = H(() => ({
1762
+ ...Ee,
1763
+ ...t.theme
1764
+ })), a = ie({
1765
+ content: t.modelValue,
1766
+ editable: !t.readonly,
1767
+ extensions: [
1768
+ se,
1769
+ ae,
1770
+ ue,
1771
+ $e,
1772
+ de,
1773
+ ce,
1774
+ me,
1775
+ fe.configure({ types: ["textStyle"] }),
1776
+ ve.configure({ types: ["heading", "paragraph"] }),
1777
+ Te,
1778
+ ge.configure({
1779
+ openOnClick: !1,
1780
+ HTMLAttributes: {
1781
+ target: "_blank",
1782
+ rel: "noopener noreferrer"
1783
+ }
1784
+ }),
1785
+ Be,
1786
+ pe.configure({ resizable: !0 }),
1787
+ be,
1788
+ xe,
1789
+ ye,
1790
+ He,
1791
+ he.configure({
1792
+ placeholder: t.placeholder || "Start typing..."
1793
+ })
1794
+ ],
1795
+ onUpdate: () => {
1796
+ var v;
1797
+ c("update:modelValue", ((v = a.value) == null ? void 0 : v.getHTML()) ?? "");
1798
+ }
1799
+ });
1800
+ te(Q, a), q(() => t.modelValue, (v) => {
1801
+ var f, $;
1802
+ ((f = a.value) == null ? void 0 : f.getHTML()) !== v && (($ = a.value) == null || $.commands.setContent(v, { emitUpdate: !1 }));
1803
+ }), q(() => t.readonly, (v) => {
1804
+ var f;
1805
+ (f = a.value) == null || f.setEditable(!v);
1806
+ });
1807
+ function m(v) {
1808
+ c("error", v);
1809
+ }
1810
+ const i = Oe(t.api), s = y(null), r = y(null);
1811
+ async function d(v) {
1812
+ var f, $, T;
1813
+ try {
1814
+ const M = ((f = a.value) == null ? void 0 : f.getHTML()) ?? "", O = v.type === "snippet" && (($ = a.value) != null && $.state.selection.content()) && ((T = a.value) == null ? void 0 : T.state.selection.content().content.textBetween(0, a.value.state.selection.content().content.size)) || M;
1815
+ await i.saveTemplate({ name: v.name, type: v.type, content: O });
1816
+ } catch (M) {
1817
+ const O = M instanceof Error ? M.message : "Unknown error";
1818
+ c("error", { message: O, detail: M });
1819
+ }
1820
+ }
1821
+ function u(v) {
1822
+ var f, $, T, M;
1823
+ if (v.type === "document") {
1824
+ if (((f = a.value) == null ? void 0 : f.getHTML()) !== "<p></p>" && (($ = a.value) == null ? void 0 : $.getHTML()) !== "" && !confirm("Replace current content with this template?")) return;
1825
+ (T = a.value) == null || T.commands.setContent(v.content);
1826
+ } else
1827
+ (M = a.value) == null || M.commands.insertContent(v.content);
1828
+ }
1829
+ async function b(v) {
1830
+ try {
1831
+ await i.deleteTemplate(v.id), await i.loadTemplates();
1832
+ } catch (f) {
1833
+ const $ = f instanceof Error ? f.message : "Unknown error";
1834
+ c("error", { message: $, detail: f });
1835
+ }
1836
+ }
1837
+ async function S() {
1838
+ var v;
1839
+ try {
1840
+ const f = ((v = a.value) == null ? void 0 : v.getHTML()) ?? "", $ = t.mode === "template" ? t.api.saveTemplate : t.api.saveDocument, T = t.mode === "template" ? { ...t.templateMeta, content: f } : { content: f }, M = await fetch($, {
1841
+ method: "POST",
1842
+ headers: {
1843
+ "Content-Type": "application/json",
1844
+ ...t.api.headers
1845
+ },
1846
+ body: JSON.stringify(T)
1847
+ });
1848
+ if (!M.ok) throw new Error(`Save failed: ${M.statusText}`);
1849
+ const O = await M.json();
1850
+ c("save", O);
1851
+ } catch (f) {
1852
+ const $ = f instanceof Error ? f.message : "Unknown error";
1853
+ c("error", { message: $, detail: f });
1854
+ }
1855
+ }
1856
+ return (v, f) => (g(), p("div", Vt, [
1857
+ t.readonly ? B("", !0) : (g(), p(A, { key: 0 }, [
1858
+ h(vt, {
1859
+ editor: L(a),
1860
+ theme: o.value,
1861
+ "image-config": t.image,
1862
+ onSaveTemplate: f[0] || (f[0] = ($) => {
1863
+ var T;
1864
+ return (T = s.value) == null ? void 0 : T.open();
1865
+ }),
1866
+ onLoadTemplate: f[1] || (f[1] = ($) => {
1867
+ var T;
1868
+ return (T = r.value) == null ? void 0 : T.open();
1869
+ }),
1870
+ onSave: S,
1871
+ onError: m
1872
+ }, null, 8, ["editor", "theme", "image-config"]),
1873
+ h(yt, { editor: L(a) }, null, 8, ["editor"])
1874
+ ], 64)),
1875
+ h(L(re), {
1876
+ editor: L(a),
1877
+ class: w(o.value.editor)
1878
+ }, null, 8, ["editor", "class"]),
1879
+ h(St, {
1880
+ ref_key: "saveTemplateModal",
1881
+ ref: s,
1882
+ theme: o.value,
1883
+ onSave: d
1884
+ }, null, 8, ["theme"]),
1885
+ h(Ft, {
1886
+ ref_key: "loadTemplateModal",
1887
+ ref: r,
1888
+ theme: o.value,
1889
+ templates: L(i).templates.value,
1890
+ loading: L(i).loading.value,
1891
+ onLoad: f[2] || (f[2] = ($) => L(i).loadTemplates()),
1892
+ onSelect: u,
1893
+ onDelete: b
1894
+ }, null, 8, ["theme", "templates", "loading"])
1895
+ ]));
1896
+ }
1897
+ });
1898
+ export {
1899
+ ze as DEFAULT_IMAGE_CONFIG,
1900
+ Ee as DEFAULT_THEME,
1901
+ ll as DocumentEditor,
1902
+ Fe as FONT_SIZES,
1903
+ Ve as LINE_HEIGHTS,
1904
+ Re as WEB_SAFE_FONTS,
1905
+ tl as useDocumentEditor
1906
+ };