@meenainwal/rich-text-editor 1.1.0 → 1.2.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.
@@ -1,1383 +0,0 @@
1
- class h {
2
- /**
3
- * Returns the current selection object.
4
- */
5
- getSelection() {
6
- return window.getSelection();
7
- }
8
- /**
9
- * Returns the first range of the current selection.
10
- */
11
- getRange() {
12
- const e = this.getSelection();
13
- return !e || e.rangeCount === 0 ? null : e.getRangeAt(0);
14
- }
15
- /**
16
- * Saves the current selection range.
17
- */
18
- saveSelection() {
19
- const e = this.getRange();
20
- return e ? e.cloneRange() : null;
21
- }
22
- /**
23
- * Restores a previously saved range.
24
- */
25
- restoreSelection(e) {
26
- if (!e) return;
27
- const t = this.getSelection();
28
- t && (t.removeAllRanges(), t.addRange(e));
29
- }
30
- /**
31
- * Checks if the selection is within a specific element.
32
- */
33
- isSelectionInElement(e) {
34
- const t = this.getRange();
35
- return t ? e.contains(t.commonAncestorContainer) : !1;
36
- }
37
- /**
38
- * Clears the current selection.
39
- */
40
- clearSelection() {
41
- const e = this.getSelection();
42
- e && e.removeAllRanges();
43
- }
44
- }
45
- class y {
46
- editor;
47
- activeContainer = null;
48
- isResizing = !1;
49
- startX = 0;
50
- startY = 0;
51
- startWidth = 0;
52
- startHeight = 0;
53
- currentHandle = null;
54
- aspectRatio = 1;
55
- constructor(e) {
56
- this.editor = e, this.setupListeners();
57
- }
58
- setupListeners() {
59
- const e = this.editor.el;
60
- e.addEventListener("mousedown", (t) => {
61
- const i = t.target;
62
- if (i.classList.contains("te-image-resizer")) {
63
- t.preventDefault(), t.stopPropagation();
64
- const n = i.closest(".te-image-container");
65
- n && (this.selectImage(n), this.startResize(t, i));
66
- return;
67
- }
68
- const o = i.closest(".te-image-container");
69
- o ? this.selectImage(o) : this.deselectImage();
70
- }), window.addEventListener("mousemove", (t) => {
71
- this.isResizing && this.handleResize(t);
72
- }), window.addEventListener("mouseup", () => {
73
- this.isResizing && this.stopResize();
74
- }), e.addEventListener("keydown", (t) => {
75
- (t.key === "Backspace" || t.key === "Delete") && this.activeContainer && (t.preventDefault(), this.activeContainer.remove(), this.activeContainer = null, this.editor.el.dispatchEvent(new Event("input", { bubbles: !0 })));
76
- });
77
- }
78
- selectImage(e) {
79
- this.activeContainer && this.activeContainer.classList.remove("active"), this.activeContainer = e, this.activeContainer.classList.add("active");
80
- }
81
- deselectImage() {
82
- this.activeContainer && (this.activeContainer.classList.remove("active"), this.activeContainer = null);
83
- }
84
- startResize(e, t) {
85
- if (!this.activeContainer) return;
86
- this.isResizing = !0, this.currentHandle = Array.from(t.classList).find((o) => o.startsWith("te-resizer-"))?.replace("te-resizer-", "") || null;
87
- const i = this.activeContainer.querySelector("img");
88
- this.startX = e.clientX, this.startY = e.clientY, this.startWidth = i.clientWidth, this.startHeight = i.clientHeight, this.aspectRatio = this.startWidth / this.startHeight, document.body.style.cursor = window.getComputedStyle(t).cursor;
89
- }
90
- handleResize(e) {
91
- if (!this.activeContainer || !this.isResizing) return;
92
- const t = this.activeContainer.querySelector("img"), i = e.clientX - this.startX, o = e.clientY - this.startY;
93
- let n = this.startWidth, a = this.startHeight;
94
- this.currentHandle?.includes("right") ? n = this.startWidth + i : this.currentHandle?.includes("left") ? n = this.startWidth - i : this.currentHandle?.includes("bottom") ? n = this.startWidth + o * this.aspectRatio : this.currentHandle?.includes("top") && (n = this.startWidth - o * this.aspectRatio), a = n / this.aspectRatio, n > 50 && n < this.editor.el.clientWidth && (t.style.width = `${n}px`, t.style.height = `${a}px`);
95
- }
96
- stopResize() {
97
- this.isResizing = !1, this.currentHandle = null, document.body.style.cursor = "", this.editor.el.dispatchEvent(new Event("input", { bubbles: !0 }));
98
- }
99
- }
100
- class u {
101
- stack = [];
102
- index = -1;
103
- maxDepth = 50;
104
- constructor(e) {
105
- e !== void 0 && this.record(e);
106
- }
107
- /**
108
- * Records a new state in the history stack.
109
- * Clears any "redo" states if we record a new action.
110
- */
111
- record(e) {
112
- this.index >= 0 && this.stack[this.index].html === e || (this.index < this.stack.length - 1 && (this.stack = this.stack.slice(0, this.index + 1)), this.stack.push({ html: e }), this.index++, this.stack.length > this.maxDepth && (this.stack.shift(), this.index--));
113
- }
114
- /**
115
- * Returns the previous state if available.
116
- */
117
- undo() {
118
- return this.index > 0 ? (this.index--, this.stack[this.index].html) : null;
119
- }
120
- /**
121
- * Returns the next state if available.
122
- */
123
- redo() {
124
- return this.index < this.stack.length - 1 ? (this.index++, this.stack[this.index].html) : null;
125
- }
126
- /**
127
- * Checks if undo is possible.
128
- */
129
- canUndo() {
130
- return this.index > 0;
131
- }
132
- /**
133
- * Checks if redo is possible.
134
- */
135
- canRedo() {
136
- return this.index < this.stack.length - 1;
137
- }
138
- }
139
- class p {
140
- container;
141
- editableElement;
142
- selection;
143
- imageManager;
144
- history;
145
- options;
146
- saveTimeout = null;
147
- historyTimeout = null;
148
- pendingStyles = {};
149
- constructor(e, t = {}) {
150
- if (this.options = t, this.container = e, typeof document > "u" || !e) {
151
- this.editableElement = {}, this.selection = {}, this.imageManager = {}, this.history = {};
152
- return;
153
- }
154
- this.container.classList.add("te-container"), this.options.dark && this.container.classList.add("te-dark"), this.editableElement = this.createEditableElement(), this.selection = new h(), this.imageManager = new y(this), this.history = new u(this.editableElement.innerHTML), this.setupInputHandlers(), this.setupImageObserver(), this.container.appendChild(this.editableElement), this.options.autofocus && this.focus(), this.options.theme && this.applyTheme(this.options.theme), document.execCommand("defaultParagraphSeparator", !1, "p");
155
- }
156
- /**
157
- * Applies custom theme variables to the editor container.
158
- */
159
- applyTheme(e) {
160
- const t = this.container, i = {
161
- primaryColor: "--te-primary-color",
162
- primaryHover: "--te-primary-hover",
163
- bgApp: "--te-bg-app",
164
- bgEditor: "--te-bg-editor",
165
- toolbarBg: "--te-toolbar-bg",
166
- borderColor: "--te-border-color",
167
- borderFocus: "--te-border-focus",
168
- textMain: "--te-text-main",
169
- textMuted: "--te-text-muted",
170
- placeholder: "--te-placeholder",
171
- btnHover: "--te-btn-hover",
172
- btnActive: "--te-btn-active",
173
- radiusLg: "--te-radius-lg",
174
- radiusMd: "--te-radius-md",
175
- radiusSm: "--te-radius-sm",
176
- shadowSm: "--te-shadow-sm",
177
- shadowMd: "--te-shadow-md",
178
- shadowLg: "--te-shadow-lg"
179
- };
180
- for (const [o, n] of Object.entries(i)) {
181
- const a = e[o];
182
- a && t.style.setProperty(n, a);
183
- }
184
- }
185
- /**
186
- * Toggles dark mode on the editor.
187
- */
188
- setDarkMode(e) {
189
- this.options.dark = e, e ? this.container.classList.add("te-dark") : this.container.classList.remove("te-dark");
190
- }
191
- setupImageObserver() {
192
- new MutationObserver((t) => {
193
- t.forEach((i) => {
194
- i.addedNodes.forEach((o) => {
195
- if (o.nodeType === Node.ELEMENT_NODE) {
196
- const n = o;
197
- n.tagName === "IMG" && !n.closest(".te-image-container") ? this.wrapImage(n) : n.querySelectorAll("img:not(.te-image)").forEach((s) => {
198
- s.closest(".te-image-container") || this.wrapImage(s);
199
- });
200
- }
201
- });
202
- });
203
- }).observe(this.editableElement, {
204
- childList: !0,
205
- subtree: !0
206
- });
207
- }
208
- /**
209
- * Wraps a raw <img> element in the interactive container
210
- */
211
- wrapImage(e) {
212
- const t = e.parentElement;
213
- if (!t) return;
214
- const i = document.createElement("figure");
215
- i.classList.add("te-image-container"), i.setAttribute("contenteditable", "false");
216
- const o = document.createElement("img");
217
- o.src = e.src, o.alt = e.alt || "", e.width && (o.style.width = `${e.width}px`), e.height && (o.style.height = `${e.height}px`), o.classList.add("te-image");
218
- const n = document.createElement("figcaption");
219
- if (n.classList.add("te-image-caption"), n.setAttribute("contenteditable", "true"), n.setAttribute("data-placeholder", "Type caption..."), ["top-left", "top-right", "bottom-left", "bottom-right"].forEach((s) => {
220
- const r = document.createElement("div");
221
- r.classList.add("te-image-resizer", `te-resizer-${s}`), i.appendChild(r);
222
- }), i.appendChild(o), i.appendChild(n), t.replaceChild(i, e), !i.nextElementSibling) {
223
- const s = document.createElement("p");
224
- s.innerHTML = "<br>", i.after(s);
225
- }
226
- }
227
- setupInputHandlers() {
228
- this.editableElement.addEventListener("beforeinput", (e) => {
229
- if (e.inputType === "insertText" && Object.keys(this.pendingStyles).length > 0) {
230
- const t = e.data;
231
- if (!t) return;
232
- e.preventDefault();
233
- const i = document.createElement("span");
234
- for (const [n, a] of Object.entries(this.pendingStyles))
235
- i.style.setProperty(n, a);
236
- i.textContent = t;
237
- const o = this.selection.getRange();
238
- if (o) {
239
- o.deleteContents(), o.insertNode(i);
240
- const n = document.createRange();
241
- n.setStart(i.firstChild, t.length), n.setEnd(i.firstChild, t.length), this.selection.restoreSelection(n), this.pendingStyles = {}, this.editableElement.dispatchEvent(new Event("input", { bubbles: !0 }));
242
- }
243
- }
244
- }), document.addEventListener("selectionchange", () => {
245
- const e = window.getSelection();
246
- e && e.rangeCount > 0 && (e.getRangeAt(0).collapsed || (this.pendingStyles = {}));
247
- }), this.editableElement.addEventListener("dragover", (e) => {
248
- e.preventDefault(), e.dataTransfer.dropEffect = "copy", this.editableElement.classList.add("dragover");
249
- }), this.editableElement.addEventListener("dragleave", () => {
250
- this.editableElement.classList.remove("dragover");
251
- }), this.editableElement.addEventListener("drop", (e) => {
252
- e.preventDefault(), this.editableElement.classList.remove("dragover");
253
- const t = e.dataTransfer?.files;
254
- if (t && t.length > 0)
255
- for (let i = 0; i < t.length; i++) {
256
- const o = t[i];
257
- if (o.type.startsWith("image/")) {
258
- const n = new FileReader();
259
- n.onload = (a) => {
260
- const s = a.target?.result;
261
- this.insertImage(s);
262
- }, n.readAsDataURL(o);
263
- }
264
- }
265
- }), this.editableElement.addEventListener("paste", (e) => {
266
- const t = e.clipboardData;
267
- if (!t) return;
268
- if (t.items)
269
- for (let n = 0; n < t.items.length; n++) {
270
- const a = t.items[n];
271
- if (a.type.startsWith("image/")) {
272
- const s = a.getAsFile();
273
- if (s) {
274
- e.preventDefault();
275
- const r = new FileReader();
276
- r.onload = (l) => {
277
- const c = l.target?.result;
278
- this.insertImage(c);
279
- }, r.readAsDataURL(s);
280
- return;
281
- }
282
- }
283
- }
284
- const i = t.getData("text/plain"), o = /<([a-z1-6]+)\b[^>]*>[\s\S]*<\/\1>/i.test(i) || /^\s*<[a-z1-6]+\b[^>]*>/i.test(i);
285
- if (i && o) {
286
- const n = i.replace(/(\r\n|\n|\r)/gm, " ").replace(/>\s+</g, "><").trim();
287
- e.preventDefault(), this.execute("insertHTML", n);
288
- return;
289
- }
290
- }), this.editableElement.addEventListener("input", () => {
291
- this.handleInput();
292
- }), this.editableElement.addEventListener("keydown", (e) => {
293
- (e.ctrlKey || e.metaKey) && e.key.toLowerCase() === "z" ? (e.preventDefault(), e.shiftKey ? this.redo() : this.undo()) : (e.ctrlKey || e.metaKey) && e.key.toLowerCase() === "y" && (e.preventDefault(), this.redo());
294
- });
295
- }
296
- handleInput() {
297
- this.options.onSaving && this.options.onSaving(), this.scheduleHistoryRecord(), this.scheduleAutoSave(), this.options.onChange && this.options.onChange(this.editableElement.innerHTML);
298
- }
299
- scheduleHistoryRecord() {
300
- this.historyTimeout && clearTimeout(this.historyTimeout), this.historyTimeout = setTimeout(() => {
301
- this.history.record(this.editableElement.innerHTML);
302
- }, 500);
303
- }
304
- scheduleAutoSave() {
305
- this.saveTimeout && clearTimeout(this.saveTimeout);
306
- const e = this.options.autoSaveInterval || 1e3;
307
- this.saveTimeout = setTimeout(() => {
308
- this.save();
309
- }, e);
310
- }
311
- save() {
312
- this.options.onSave && this.options.onSave(this.editableElement.innerHTML);
313
- }
314
- undo() {
315
- const e = this.history.undo();
316
- e !== null && (this.editableElement.innerHTML = e, this.triggerChange());
317
- }
318
- redo() {
319
- const e = this.history.redo();
320
- e !== null && (this.editableElement.innerHTML = e, this.triggerChange());
321
- }
322
- triggerChange() {
323
- this.editableElement.dispatchEvent(new Event("input", { bubbles: !0 }));
324
- }
325
- createEditableElement() {
326
- const e = document.createElement("div");
327
- return e.setAttribute("contenteditable", "true"), e.setAttribute("role", "textbox"), e.setAttribute("spellcheck", "true"), e.classList.add("te-content"), this.options.placeholder && e.setAttribute("data-placeholder", this.options.placeholder), e.style.minHeight = "150px", e.style.outline = "none", e.style.padding = "1rem", e.innerHTML === "" && (e.innerHTML = "<p><br></p>"), e;
328
- }
329
- /**
330
- * Focuses the editor.
331
- */
332
- focus() {
333
- this.editableElement.focus();
334
- }
335
- /**
336
- * Executes a command on the current selection.
337
- */
338
- execute(e, t = null) {
339
- this.focus(), document.execCommand(e, !1, t ?? void 0), this.editableElement.dispatchEvent(new Event("input", { bubbles: !0 }));
340
- }
341
- /**
342
- * Inserts a table at the current selection.
343
- */
344
- insertTable(e = 3, t = 3) {
345
- this.focus();
346
- const i = this.selection.getRange();
347
- if (!i) return;
348
- const o = document.createElement("table");
349
- o.classList.add("te-table");
350
- for (let a = 0; a < e; a++) {
351
- const s = document.createElement("tr");
352
- for (let r = 0; r < t; r++) {
353
- const l = document.createElement("td");
354
- l.innerHTML = "<br>", s.appendChild(l);
355
- }
356
- o.appendChild(s);
357
- }
358
- i.deleteContents(), i.insertNode(o);
359
- const n = o.nextElementSibling;
360
- if (!n || n.tagName !== "P") {
361
- const a = document.createElement("p");
362
- a.innerHTML = "<br>", o.after(a), n && n.tagName === "BR" && n.remove();
363
- }
364
- this.editableElement.dispatchEvent(new Event("input", { bubbles: !0 }));
365
- }
366
- /**
367
- * Adds a row to the currently selected table.
368
- */
369
- addRow() {
370
- const e = this.getSelectedTable();
371
- if (!e) return;
372
- const t = document.createElement("tr");
373
- t.style.borderBottom = "1px solid var(--te-border-color)";
374
- const i = e.rows[0].cells.length;
375
- for (let n = 0; n < i; n++) {
376
- const a = document.createElement("td");
377
- a.innerHTML = "<br>", t.appendChild(a);
378
- }
379
- const o = this.getSelectedTd();
380
- o ? o.parentElement?.after(t) : e.appendChild(t), this.editableElement.dispatchEvent(new Event("input", { bubbles: !0 }));
381
- }
382
- /**
383
- * Deletes the currently selected row.
384
- */
385
- deleteRow() {
386
- const e = this.getSelectedTd();
387
- if (e && e.parentElement) {
388
- const t = e.parentElement;
389
- t.parentElement.rows.length > 1 && (t.remove(), this.editableElement.dispatchEvent(new Event("input", { bubbles: !0 })));
390
- }
391
- }
392
- /**
393
- * Adds a column to the currently selected table.
394
- */
395
- addColumn() {
396
- const e = this.getSelectedTable();
397
- if (!e) return;
398
- const t = this.getSelectedTd(), i = t ? t.cellIndex : -1;
399
- for (let o = 0; o < e.rows.length; o++) {
400
- const n = e.rows[o], a = document.createElement("td");
401
- a.innerHTML = "<br>", i !== -1 ? n.cells[i].after(a) : n.appendChild(a);
402
- }
403
- this.editableElement.dispatchEvent(new Event("input", { bubbles: !0 }));
404
- }
405
- /**
406
- * Deletes the currently selected column.
407
- */
408
- deleteColumn() {
409
- const e = this.getSelectedTd();
410
- if (!e) return;
411
- const t = this.getSelectedTable();
412
- if (!t) return;
413
- const i = e.cellIndex;
414
- if (t.rows[0].cells.length > 1) {
415
- for (let o = 0; o < t.rows.length; o++)
416
- t.rows[o].cells[i].remove();
417
- this.editableElement.dispatchEvent(new Event("input", { bubbles: !0 }));
418
- }
419
- }
420
- getSelectedTd() {
421
- const e = window.getSelection();
422
- if (!e || e.rangeCount === 0) return null;
423
- let t = e.anchorNode;
424
- for (; t && t !== this.editableElement; ) {
425
- if (t.nodeName === "TD") return t;
426
- t = t.parentNode;
427
- }
428
- return null;
429
- }
430
- getSelectedTable() {
431
- const e = this.getSelectedTd();
432
- return e ? e.closest("table") : null;
433
- }
434
- /**
435
- * Recursively removes a style property from all elements in a fragment.
436
- */
437
- clearStyleRecursive(e, t) {
438
- const i = document.createTreeWalker(e, NodeFilter.SHOW_ELEMENT);
439
- let o = i.nextNode();
440
- for (; o; )
441
- o.style.getPropertyValue(t) && o.style.removeProperty(t), o = i.nextNode();
442
- }
443
- /**
444
- * Applies an inline style to the selection.
445
- * This is used for properties like font-size (px) and font-family
446
- * where execCommand is outdated or limited.
447
- */
448
- setStyle(e, t, i) {
449
- if (e === "font-size" && t.endsWith("px"), !i) {
450
- const a = window.getSelection();
451
- if (!a || a.rangeCount === 0) return null;
452
- i = a.getRangeAt(0);
453
- }
454
- if (i.collapsed)
455
- return this.pendingStyles[e] = t, i;
456
- let o = i.commonAncestorContainer;
457
- o.nodeType === Node.TEXT_NODE && (o = o.parentElement);
458
- let n = null;
459
- if (o.tagName === "SPAN" && o.children.length === 0 && o.textContent === i.toString())
460
- o.style.setProperty(e, t), n = i.cloneRange();
461
- else {
462
- const a = document.createElement("span");
463
- a.style.setProperty(e, t);
464
- try {
465
- const s = o.tagName === "SPAN" ? o : null, r = i.extractContents();
466
- this.clearStyleRecursive(r, e), a.appendChild(r), i.insertNode(a), s && s.innerHTML === "" && s.remove();
467
- const l = document.createRange();
468
- l.selectNodeContents(a), n = l;
469
- const c = window.getSelection();
470
- c && c.rangeCount > 0 && (c.removeAllRanges(), c.addRange(l));
471
- } catch (s) {
472
- console.warn("Failed to apply style:", s);
473
- }
474
- }
475
- return this.editableElement.dispatchEvent(new Event("input", { bubbles: !0 })), n;
476
- }
477
- /**
478
- * Creates a link at the current selection.
479
- * Ensures the link opens in a new tab with proper security attributes.
480
- */
481
- createLink(e) {
482
- this.focus(), !/^https?:\/\//i.test(e) && !/^mailto:/i.test(e) && !e.startsWith("#") && (e = "https://" + e), document.execCommand("createLink", !1, e);
483
- const t = window.getSelection();
484
- if (t && t.rangeCount > 0) {
485
- let o = t.getRangeAt(0).commonAncestorContainer;
486
- o.nodeType === Node.TEXT_NODE && (o = o.parentElement);
487
- let n = null;
488
- o.tagName === "A" ? n = o : n = o.querySelector("a"), n && (n.setAttribute("target", "_blank"), n.setAttribute("rel", "noopener noreferrer"));
489
- }
490
- this.editableElement.dispatchEvent(new Event("input", { bubbles: !0 }));
491
- }
492
- /**
493
- * Inserts an image at the current selection.
494
- */
495
- insertImage(e) {
496
- this.focus();
497
- const t = this.selection.getRange();
498
- if (!t) return;
499
- const i = document.createElement("figure");
500
- i.classList.add("te-image-container"), i.setAttribute("contenteditable", "false");
501
- const o = document.createElement("img");
502
- o.src = e, o.classList.add("te-image");
503
- const n = document.createElement("figcaption");
504
- n.classList.add("te-image-caption"), n.setAttribute("contenteditable", "true"), n.setAttribute("data-placeholder", "Type caption..."), ["top-left", "top-right", "bottom-left", "bottom-right"].forEach((l) => {
505
- const c = document.createElement("div");
506
- c.classList.add("te-image-resizer", `te-resizer-${l}`), i.appendChild(c);
507
- }), i.appendChild(o), i.appendChild(n), t.deleteContents(), t.insertNode(i);
508
- const s = document.createElement("p");
509
- s.innerHTML = "<br>", i.after(s);
510
- const r = document.createRange();
511
- r.setStart(s, 0), r.setEnd(s, 0), this.selection.restoreSelection(r), this.editableElement.dispatchEvent(new Event("input", { bubbles: !0 }));
512
- }
513
- /**
514
- * Returns the clean HTML content of the editor.
515
- */
516
- getHTML() {
517
- return this.editableElement.innerHTML;
518
- }
519
- /**
520
- * Sets the HTML content of the editor.
521
- */
522
- setHTML(e) {
523
- this.editableElement.innerHTML = e;
524
- }
525
- /**
526
- * Internal access to the editable element.
527
- */
528
- get el() {
529
- return this.editableElement;
530
- }
531
- /**
532
- * Returns the editor options.
533
- */
534
- getOptions() {
535
- return this.options;
536
- }
537
- }
538
- const v = {
539
- type: "button",
540
- title: "Undo",
541
- command: "undo",
542
- icon: '<svg viewBox="0 0 24 24"><path d="M9 14L4 9l5-5"></path><path d="M20 20v-7a4 4 0 0 0-4-4H4"></path></svg>'
543
- }, b = {
544
- type: "button",
545
- title: "Redo",
546
- command: "redo",
547
- icon: '<svg viewBox="0 0 24 24"><path d="M15 14l5-5-5-5"></path><path d="M4 20v-7a4 4 0 0 1 4-4h12"></path></svg>'
548
- }, j = {
549
- type: "select",
550
- title: "Heading",
551
- command: "formatBlock",
552
- options: [
553
- { label: "Paragraph", value: "P" },
554
- { label: "Heading 1", value: "H1" },
555
- { label: "Heading 2", value: "H2" },
556
- { label: "Heading 3", value: "H3" },
557
- { label: "Heading 4", value: "H4" },
558
- { label: "Heading 5", value: "H5" },
559
- { label: "Heading 6", value: "H6" }
560
- ]
561
- }, f = {
562
- type: "select",
563
- title: "Font",
564
- command: "fontFamily",
565
- options: [
566
- { label: "Inter", value: "'Inter', sans-serif" },
567
- { label: "Arial", value: "Arial, sans-serif" },
568
- { label: "Georgia", value: "Georgia, serif" },
569
- { label: "Courier", value: "'Courier New', monospace" },
570
- { label: "Times New Roman", value: "'Times New Roman', serif" },
571
- { label: "Verdana", value: "Verdana, sans-serif" },
572
- { label: "Tahoma", value: "Tahoma, sans-serif" },
573
- { label: "Roboto", value: "'Roboto', sans-serif" },
574
- { label: "Open Sans", value: "'Open Sans', sans-serif" },
575
- { label: "Montserrat", value: "'Montserrat', sans-serif" },
576
- { label: "Lato", value: "'Lato', sans-serif" },
577
- { label: "Poppins", value: "'Poppins', sans-serif" },
578
- { label: "Oswald", value: "'Oswald', sans-serif" },
579
- { label: "Playfair Display", value: "'Playfair Display', serif" },
580
- { label: "Merriweather", value: "'Merriweather', serif" }
581
- ]
582
- }, w = {
583
- type: "input",
584
- title: "Size (px)",
585
- command: "fontSize",
586
- placeholder: "Size",
587
- value: "16"
588
- }, E = {
589
- type: "select",
590
- title: "Line Height",
591
- command: "lineHeight",
592
- options: [
593
- { label: "Normal", value: "normal" },
594
- { label: "0.5", value: "0.5" },
595
- { label: "1.0", value: "1.0" },
596
- { label: "1.15", value: "1.15" },
597
- { label: "1.5", value: "1.5" },
598
- { label: "2.0", value: "2.0" },
599
- { label: "2.5", value: "2.5" },
600
- { label: "3.0", value: "3.0" },
601
- { label: "3.5", value: "3.5" },
602
- { label: "4.0", value: "4.0" },
603
- { label: "4.5", value: "4.5" },
604
- { label: "5.0", value: "5.0" },
605
- { label: "5.5", value: "5.5" },
606
- { label: "6.0", value: "6.0" },
607
- { label: "6.5", value: "6.5" },
608
- { label: "7.0", value: "7.0" },
609
- { label: "7.5", value: "7.5" },
610
- { label: "8.0", value: "8.0" },
611
- { label: "8.5", value: "8.5" },
612
- { label: "9.0", value: "9.0" },
613
- { label: "9.5", value: "9.5" },
614
- { label: "10.0", value: "10.0" }
615
- ],
616
- value: "normal"
617
- }, S = {
618
- type: "button",
619
- title: "Bold",
620
- command: "bold",
621
- icon: '<svg viewBox="0 0 24 24"><path d="M6 4h8a4 4 0 0 1 4 4 4 4 0 0 1-4 4H6z"></path><path d="M6 12h9a4 4 0 0 1 4 4 4 4 0 0 1-4 4H6z"></path></svg>'
622
- }, x = {
623
- type: "button",
624
- title: "Italic",
625
- command: "italic",
626
- icon: '<svg viewBox="0 0 24 24"><line x1="19" y1="4" x2="10" y2="4"></line><line x1="14" y1="20" x2="5" y2="20"></line><line x1="15" y1="4" x2="9" y2="20"></line></svg>'
627
- }, k = {
628
- type: "button",
629
- title: "Underline",
630
- command: "underline",
631
- icon: '<svg viewBox="0 0 24 24"><path d="M6 3v7a6 6 0 0 0 6 6 6 6 0 0 0 6-6V3"></path><line x1="4" y1="21" x2="20" y2="21"></line></svg>'
632
- }, L = {
633
- type: "button",
634
- title: "Strikethrough",
635
- command: "strikeThrough",
636
- icon: '<svg viewBox="0 0 24 24"><line x1="5" y1="12" x2="19" y2="12"></line><path d="M16 4.9C15.1 4.3 13.9 4 12.6 4c-3.1 0-5.6 1.8-5.6 4s1.8 3.3 4.4 3.8"></path><path d="M7 19.1c.9.6 2.1.9 3.4.9 3.1 0 5.6-1.8 5.6-4s-1.8-3.3-4.4-3.8"></path></svg>'
637
- }, A = {
638
- type: "color-picker",
639
- title: "Text Color",
640
- command: "foreColor",
641
- icon: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4 20h16"/><path d="m6 16 6-12 6 12"/><path d="M8 12h8"/></svg>',
642
- value: "#1e293b"
643
- }, C = {
644
- type: "color-picker",
645
- title: "Highlight Color",
646
- command: "backColor",
647
- icon: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m9 11-6 6v3h9l3-3"/><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"/></svg>',
648
- value: "#ffffff"
649
- }, T = {
650
- type: "button",
651
- title: "Align Left",
652
- command: "justifyLeft",
653
- icon: '<svg viewBox="0 0 24 24"><line x1="17" y1="10" x2="3" y2="10"></line><line x1="21" y1="6" x2="3" y2="6"></line><line x1="21" y1="14" x2="3" y2="14"></line><line x1="17" y1="18" x2="3" y2="18"></line></svg>'
654
- }, H = {
655
- type: "button",
656
- title: "Align Center",
657
- command: "justifyCenter",
658
- icon: '<svg viewBox="0 0 24 24"><line x1="18" y1="10" x2="6" y2="10"></line><line x1="21" y1="6" x2="3" y2="6"></line><line x1="21" y1="14" x2="3" y2="14"></line><line x1="18" y1="18" x2="6" y2="18"></line></svg>'
659
- }, F = {
660
- type: "button",
661
- title: "Align Right",
662
- command: "justifyRight",
663
- icon: '<svg viewBox="0 0 24 24"><line x1="21" y1="10" x2="7" y2="10"></line><line x1="21" y1="6" x2="3" y2="6"></line><line x1="21" y1="14" x2="3" y2="14"></line><line x1="21" y1="18" x2="7" y2="18"></line></svg>'
664
- }, R = {
665
- type: "button",
666
- title: "Justify",
667
- command: "justifyFull",
668
- icon: '<svg viewBox="0 0 24 24"><line x1="21" y1="10" x2="3" y2="10"></line><line x1="21" y1="6" x2="3" y2="6"></line><line x1="21" y1="14" x2="3" y2="14"></line><line x1="21" y1="18" x2="3" y2="18"></line></svg>'
669
- }, M = {
670
- type: "button",
671
- title: "Bulleted List",
672
- command: "insertUnorderedList",
673
- icon: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="8" y1="6" x2="21" y2="6"></line><line x1="8" y1="12" x2="21" y2="12"></line><line x1="8" y1="18" x2="21" y2="18"></line><circle cx="3" cy="6" r="1" fill="currentColor"></circle><circle cx="3" cy="12" r="1" fill="currentColor"></circle><circle cx="3" cy="18" r="1" fill="currentColor"></circle></svg>'
674
- }, I = {
675
- type: "button",
676
- title: "Numbered List",
677
- command: "insertOrderedList",
678
- icon: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="10" y1="6" x2="21" y2="6"></line><line x1="10" y1="12" x2="21" y2="12"></line><line x1="10" y1="18" x2="21" y2="18"></line><path d="M4 6h1v4"></path><path d="M4 10h2"></path><path d="M6 18H4c0-1 2-2 2-3s-1-1.5-2-1"></path></svg>'
679
- }, O = {
680
- type: "button",
681
- title: "Outdent",
682
- command: "outdent",
683
- icon: '<svg viewBox="0 0 24 24"><polyline points="15 18 9 12 15 6"></polyline><line x1="21" y1="12" x2="9" y2="12"></line><line x1="21" y1="6" x2="3" y2="6"></line><line x1="21" y1="18" x2="3" y2="18"></line></svg>'
684
- }, z = {
685
- type: "button",
686
- title: "Indent",
687
- command: "indent",
688
- icon: '<svg viewBox="0 0 24 24"><polyline points="9 18 15 12 9 6"></polyline><line x1="3" y1="12" x2="15" y2="12"></line><line x1="3" y1="6" x2="21" y2="6"></line><line x1="3" y1="18" x2="21" y2="18"></line></svg>'
689
- }, B = {
690
- type: "button",
691
- title: "Horizontal Rule",
692
- command: "insertHorizontalRule",
693
- icon: '<svg viewBox="0 0 24 24"><line x1="5" y1="12" x2="19" y2="12"></line></svg>'
694
- }, N = {
695
- type: "button",
696
- title: "Clear Formatting",
697
- command: "removeFormat",
698
- icon: '<svg viewBox="0 0 24 24"><path d="M17.41 15.41L12 10l-5.41 5.41L5.17 14l5.41-5.41L5.17 3.17 6.59 1.76 12 7.17l5.41-5.41 1.41 1.41-5.41 5.41 5.41 5.41-1.41 1.42z"></path></svg>'
699
- }, P = {
700
- type: "button",
701
- title: "Insert Emoji",
702
- command: "insertEmoji",
703
- icon: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"></circle><path d="M8 14s1.5 2 4 2 4-2 4-2"></path><line x1="9" y1="9" x2="9.01" y2="9"></line><line x1="15" y1="9" x2="15.01" y2="9"></line></svg>'
704
- }, D = {
705
- type: "button",
706
- title: "Insert Link",
707
- command: "createLink",
708
- icon: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path></svg>'
709
- }, W = {
710
- type: "button",
711
- title: "Insert Image",
712
- command: "insertImage",
713
- icon: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="18" height="18" rx="2" ry="2"></rect><circle cx="8.5" cy="8.5" r="1.5"></circle><polyline points="21 15 16 10 5 21"></polyline></svg>'
714
- }, G = {
715
- type: "button",
716
- command: "insertTable",
717
- title: "Insert Table",
718
- icon: '<svg viewBox="0 0 24 24" width="18" height="18"><path fill="currentColor" d="M3 3h18v18H3V3m2 2v4h4V5H5m6 0v4h4V5h-4m6 0v4h2V5h-2M5 11v4h4v-4H5m6 0v4h4v-4h-4m6 0v4h2v-4h-2M5 17v2h4v-2H5m6 0v2h4v-2h-4m6 0v2h2v-2h-2Z"/></svg>'
719
- }, d = { type: "divider", title: "" }, $ = [
720
- { ...v, id: "undo" },
721
- { ...b, id: "redo" },
722
- d,
723
- { ...j, id: "heading" },
724
- { ...f, id: "font-family" },
725
- { ...w, id: "font-size" },
726
- { ...E, id: "line-height" },
727
- d,
728
- { ...S, id: "bold" },
729
- { ...x, id: "italic" },
730
- { ...k, id: "underline" },
731
- { ...L, id: "strikethrough" },
732
- d,
733
- { ...A, id: "text-color" },
734
- { ...C, id: "highlight-color" },
735
- d,
736
- { ...T, id: "align-left" },
737
- { ...H, id: "align-center" },
738
- { ...F, id: "align-right" },
739
- { ...R, id: "align-justify" },
740
- d,
741
- { ...M, id: "bullet-list" },
742
- { ...I, id: "ordered-list" },
743
- { ...O, id: "outdent" },
744
- { ...z, id: "indent" },
745
- d,
746
- { ...B, id: "horizontal-rule" },
747
- { ...P, id: "emoji" },
748
- { ...D, id: "link" },
749
- { ...W, id: "image" },
750
- { ...G, id: "table" },
751
- { ...N, id: "clear-formatting" }
752
- ], g = [
753
- // Smileys & Emotion
754
- { emoji: "😀", name: "grinning", category: "Smileys" },
755
- { emoji: "😃", name: "smiley", category: "Smileys" },
756
- { emoji: "😄", name: "smile", category: "Smileys" },
757
- { emoji: "😁", name: "grin", category: "Smileys" },
758
- { emoji: "😆", name: "laughing", category: "Smileys" },
759
- { emoji: "😅", name: "sweat smile", category: "Smileys" },
760
- { emoji: "🤣", name: "rofl", category: "Smileys" },
761
- { emoji: "😂", name: "joy", category: "Smileys" },
762
- { emoji: "🙂", name: "slight smile", category: "Smileys" },
763
- { emoji: "🙃", name: "upside down", category: "Smileys" },
764
- { emoji: "😉", name: "wink", category: "Smileys" },
765
- { emoji: "😊", name: "blush", category: "Smileys" },
766
- { emoji: "😇", name: "innocent", category: "Smileys" },
767
- { emoji: "🥰", name: "smiling face with hearts", category: "Smileys" },
768
- { emoji: "😍", name: "heart eyes", category: "Smileys" },
769
- { emoji: "🤩", name: "star struck", category: "Smileys" },
770
- { emoji: "😘", name: "kissing heart", category: "Smileys" },
771
- { emoji: "😗", name: "kissing", category: "Smileys" },
772
- { emoji: "😚", name: "kissing closed eyes", category: "Smileys" },
773
- { emoji: "😋", name: "yum", category: "Smileys" },
774
- { emoji: "😛", name: "stuck out tongue", category: "Smileys" },
775
- { emoji: "😜", name: "stuck out tongue winking eye", category: "Smileys" },
776
- { emoji: "🤪", name: "zany face", category: "Smileys" },
777
- { emoji: "🤨", name: "raised eyebrow", category: "Smileys" },
778
- { emoji: "🧐", name: "monocle", category: "Smileys" },
779
- { emoji: "🤓", name: "nerd", category: "Smileys" },
780
- { emoji: "😎", name: "sunglasses", category: "Smileys" },
781
- { emoji: "🥳", name: "partying face", category: "Smileys" },
782
- { emoji: "😏", name: "smirk", category: "Smileys" },
783
- { emoji: "😒", name: "unamused", category: "Smileys" },
784
- { emoji: "😞", name: "disappointed", category: "Smileys" },
785
- { emoji: "😔", name: "pensive", category: "Smileys" },
786
- { emoji: "😟", name: "worried", category: "Smileys" },
787
- { emoji: "😕", name: "confused", category: "Smileys" },
788
- { emoji: "😫", name: "tired", category: "Smileys" },
789
- { emoji: "🥵", name: "hot face", category: "Smileys" },
790
- { emoji: "🥶", name: "cold face", category: "Smileys" },
791
- { emoji: "😳", name: "flushed", category: "Smileys" },
792
- { emoji: "😱", name: "scream", category: "Smileys" },
793
- { emoji: "🤢", name: "nauseated", category: "Smileys" },
794
- { emoji: "🤮", name: "vomiting", category: "Smileys" },
795
- { emoji: "🤬", name: "cursing", category: "Smileys" },
796
- { emoji: "🤫", name: "shushing", category: "Smileys" },
797
- { emoji: "🤔", name: "thinking", category: "Smileys" },
798
- { emoji: "🤗", name: "hugs", category: "Smileys" },
799
- { emoji: "🥱", name: "yawn", category: "Smileys" },
800
- { emoji: "😴", name: "sleeping", category: "Smileys" },
801
- { emoji: "🤤", name: "drooling", category: "Smileys" },
802
- { emoji: "😵", name: "dizzy", category: "Smileys" },
803
- { emoji: "🤐", name: "zipper mouth", category: "Smileys" },
804
- { emoji: "🥴", name: "woozy", category: "Smileys" },
805
- { emoji: "🤒", name: "fever", category: "Smileys" },
806
- { emoji: "🤕", name: "bandage", category: "Smileys" },
807
- { emoji: "🤡", name: "clown", category: "Smileys" },
808
- { emoji: "👻", name: "ghost", category: "Smileys" },
809
- { emoji: "👽", name: "alien", category: "Smileys" },
810
- { emoji: "👾", name: "robot", category: "Smileys" },
811
- { emoji: "💩", name: "poop", category: "Smileys" },
812
- // Hearts & Symbols
813
- { emoji: "❤️", name: "heart", category: "Symbols" },
814
- { emoji: "🧡", name: "orange heart", category: "Symbols" },
815
- { emoji: "💛", name: "yellow heart", category: "Symbols" },
816
- { emoji: "💚", name: "green heart", category: "Symbols" },
817
- { emoji: "💙", name: "blue heart", category: "Symbols" },
818
- { emoji: "💜", name: "purple heart", category: "Symbols" },
819
- { emoji: "🖤", name: "black heart", category: "Symbols" },
820
- { emoji: "🤍", name: "white heart", category: "Symbols" },
821
- { emoji: "🤎", name: "brown heart", category: "Symbols" },
822
- { emoji: "💔", name: "broken heart", category: "Symbols" },
823
- { emoji: "❣️", name: "heart exclamation", category: "Symbols" },
824
- { emoji: "💕", name: "two hearts", category: "Symbols" },
825
- { emoji: "💞", name: "revolving hearts", category: "Symbols" },
826
- { emoji: "✨", name: "sparkles", category: "Symbols" },
827
- { emoji: "🔥", name: "fire", category: "Symbols" },
828
- { emoji: "⭐", name: "star", category: "Symbols" },
829
- { emoji: "🌟", name: "glowing star", category: "Symbols" },
830
- { emoji: "✅", name: "check", category: "Symbols" },
831
- { emoji: "❌", name: "cross", category: "Symbols" },
832
- { emoji: "💯", name: "hundred", category: "Symbols" },
833
- { emoji: "💢", name: "anger", category: "Symbols" },
834
- { emoji: "💥", name: "collision", category: "Symbols" },
835
- { emoji: "💫", name: "dizzy symbol", category: "Symbols" },
836
- { emoji: "💦", name: "sweat drops", category: "Symbols" },
837
- { emoji: "💨", name: "dash", category: "Symbols" },
838
- // Hand Gestures
839
- { emoji: "👍", name: "thumbs up", category: "Hands" },
840
- { emoji: "👎", name: "thumbs down", category: "Hands" },
841
- { emoji: "👌", name: "ok", category: "Hands" },
842
- { emoji: "✌️", name: "victory", category: "Hands" },
843
- { emoji: "🤞", name: "fingers crossed", category: "Hands" },
844
- { emoji: "🤟", name: "rock on", category: "Hands" },
845
- { emoji: "🤘", name: "horns", category: "Hands" },
846
- { emoji: "🤙", name: "call me", category: "Hands" },
847
- { emoji: "👈", name: "point left", category: "Hands" },
848
- { emoji: "👉", name: "point right", category: "Hands" },
849
- { emoji: "👆", name: "point up", category: "Hands" },
850
- { emoji: "👇", name: "point down", category: "Hands" },
851
- { emoji: "🖐️", name: "hand splayed", category: "Hands" },
852
- { emoji: "✋", name: "raised hand", category: "Hands" },
853
- { emoji: "🖖", name: "vulcan salute", category: "Hands" },
854
- { emoji: "👋", name: "wave", category: "Hands" },
855
- { emoji: "👏", name: "clap", category: "Hands" },
856
- { emoji: "🙌", name: "hands up", category: "Hands" },
857
- { emoji: "👐", name: "open hands", category: "Hands" },
858
- { emoji: "🤲", name: "palms up", category: "Hands" },
859
- { emoji: "🤝", name: "handshake", category: "Hands" },
860
- { emoji: "🙏", name: "pray", category: "Hands" },
861
- { emoji: "💪", name: "flex", category: "Hands" },
862
- { emoji: "✍️", name: "writing", category: "Hands" },
863
- { emoji: "🤳", name: "selfie", category: "Hands" },
864
- // Animals & Nature
865
- { emoji: "🐶", name: "dog", category: "Animals" },
866
- { emoji: "🐱", name: "cat", category: "Animals" },
867
- { emoji: "🐭", name: "mouse", category: "Animals" },
868
- { emoji: "🐹", name: "hamster", category: "Animals" },
869
- { emoji: "🐰", name: "rabbit", category: "Animals" },
870
- { emoji: "🦊", name: "fox", category: "Animals" },
871
- { emoji: "🐻", name: "bear", category: "Animals" },
872
- { emoji: "🐼", name: "panda", category: "Animals" },
873
- { emoji: "🐨", name: "koala", category: "Animals" },
874
- { emoji: "🐯", name: "tiger", category: "Animals" },
875
- { emoji: "🦁", name: "lion", category: "Animals" },
876
- { emoji: "🐮", name: "cow", category: "Animals" },
877
- { emoji: "🐷", name: "pig", category: "Animals" },
878
- { emoji: "🐸", name: "frog", category: "Animals" },
879
- { emoji: "🐵", name: "monkey", category: "Animals" },
880
- { emoji: "🐔", name: "chicken", category: "Animals" },
881
- { emoji: "🐧", name: "penguin", category: "Animals" },
882
- { emoji: "🐦", name: "bird", category: "Animals" },
883
- { emoji: "🐤", name: "chick", category: "Animals" },
884
- { emoji: "🦆", name: "duck", category: "Animals" },
885
- { emoji: "🦅", name: "eagle", category: "Animals" },
886
- { emoji: "🦉", name: "owl", category: "Animals" },
887
- { emoji: "🦇", name: "bat", category: "Animals" },
888
- { emoji: "🦄", name: "unicorn", category: "Animals" },
889
- { emoji: "🐝", name: "bee", category: "Animals" },
890
- { emoji: "🦋", name: "butterfly", category: "Animals" },
891
- { emoji: "🐌", name: "snail", category: "Animals" },
892
- { emoji: "🐞", name: "ladybeetle", category: "Animals" },
893
- { emoji: "🐢", name: "turtle", category: "Animals" },
894
- { emoji: "🐍", name: "snake", category: "Animals" },
895
- { emoji: "🐙", name: "octopus", category: "Animals" },
896
- { emoji: "🐬", name: "dolphin", category: "Animals" },
897
- { emoji: "🐳", name: "whale", category: "Animals" },
898
- { emoji: "🐟", name: "fish", category: "Animals" },
899
- { emoji: "🦓", name: "zebra", category: "Animals" },
900
- { emoji: "🦒", name: "giraffe", category: "Animals" },
901
- { emoji: "🐘", name: "elephant", category: "Animals" },
902
- { emoji: "🦏", name: "rhino", category: "Animals" },
903
- { emoji: "🐪", name: "camel", category: "Animals" },
904
- { emoji: "🐒", name: "monkey", category: "Animals" },
905
- // Food & Drink
906
- { emoji: "🍎", name: "apple", category: "Food" },
907
- { emoji: "🍐", name: "pear", category: "Food" },
908
- { emoji: "🍊", name: "tangerine", category: "Food" },
909
- { emoji: "🍋", name: "lemon", category: "Food" },
910
- { emoji: "🍌", name: "banana", category: "Food" },
911
- { emoji: "🍉", name: "watermelon", category: "Food" },
912
- { emoji: "🍇", name: "grapes", category: "Food" },
913
- { emoji: "🍓", name: "strawberry", category: "Food" },
914
- { emoji: "🍒", name: "cherries", category: "Food" },
915
- { emoji: "🍑", name: "peach", category: "Food" },
916
- { emoji: "🥭", name: "mango", category: "Food" },
917
- { emoji: "🍍", name: "pineapple", category: "Food" },
918
- { emoji: "🥥", name: "coconut", category: "Food" },
919
- { emoji: "🥝", name: "kiwi", category: "Food" },
920
- { emoji: "🍅", name: "tomato", category: "Food" },
921
- { emoji: "🥑", name: "avocado", category: "Food" },
922
- { emoji: "🍆", name: "eggplant", category: "Food" },
923
- { emoji: "🥔", name: "potato", category: "Food" },
924
- { emoji: "🥕", name: "carrot", category: "Food" },
925
- { emoji: "🌽", name: "corn", category: "Food" },
926
- { emoji: "🌶️", name: "hot pepper", category: "Food" },
927
- { emoji: "🥦", name: "broccoli", category: "Food" },
928
- { emoji: "🍄", name: "mushroom", category: "Food" },
929
- { emoji: "🥜", name: "peanuts", category: "Food" },
930
- { emoji: "🍞", name: "bread", category: "Food" },
931
- { emoji: "🥐", name: "croissant", category: "Food" },
932
- { emoji: "🥯", name: "bagel", category: "Food" },
933
- { emoji: "🥞", name: "pancakes", category: "Food" },
934
- { emoji: "🧀", name: "cheese", category: "Food" },
935
- { emoji: "🍖", name: "meat", category: "Food" },
936
- { emoji: "🍗", name: "poultry leg", category: "Food" },
937
- { emoji: "🥓", name: "bacon", category: "Food" },
938
- { emoji: "🍔", name: "hamburger", category: "Food" },
939
- { emoji: "🍟", name: "fries", category: "Food" },
940
- { emoji: "🍕", name: "pizza", category: "Food" },
941
- { emoji: "🌭", name: "hot dog", category: "Food" },
942
- { emoji: "🥪", name: "sandwich", category: "Food" },
943
- { emoji: "🌮", name: "taco", category: "Food" },
944
- { emoji: "🌯", name: "burrito", category: "Food" },
945
- { emoji: "🍳", name: "egg", category: "Food" },
946
- { emoji: "🍲", name: "stew", category: "Food" },
947
- { emoji: "🥣", name: "bowl", category: "Food" },
948
- { emoji: "🥗", name: "salad", category: "Food" },
949
- { emoji: "🍿", name: "popcorn", category: "Food" },
950
- { emoji: "🍱", name: "bento", category: "Food" },
951
- { emoji: "🍣", name: "sushi", category: "Food" },
952
- { emoji: "🍤", name: "shrimp", category: "Food" },
953
- { emoji: "🍦", name: "ice cream", category: "Food" },
954
- { emoji: "🍧", name: "shaved ice", category: "Food" },
955
- { emoji: "🍨", name: "ice cream", category: "Food" },
956
- { emoji: "🍩", name: "donut", category: "Food" },
957
- { emoji: "🍪", name: "cookie", category: "Food" },
958
- { emoji: "🎂", name: "cake", category: "Food" },
959
- { emoji: "🍰", name: "shortcake", category: "Food" },
960
- { emoji: "🧁", name: "cupcake", category: "Food" },
961
- { emoji: "🥧", name: "pie", category: "Food" },
962
- { emoji: "🍫", name: "chocolate", category: "Food" },
963
- { emoji: "🍬", name: "candy", category: "Food" },
964
- { emoji: "🍭", name: "lollipop", category: "Food" },
965
- { emoji: "🍮", name: "custard", category: "Food" },
966
- { emoji: "🍯", name: "honey", category: "Food" },
967
- { emoji: "🍼", name: "baby bottle", category: "Food" },
968
- { emoji: "🥛", name: "milk", category: "Food" },
969
- { emoji: "☕", name: "coffee", category: "Food" },
970
- { emoji: "🍵", name: "tea", category: "Food" },
971
- { emoji: "🍶", name: "sake", category: "Food" },
972
- { emoji: "🍾", name: "champagne", category: "Food" },
973
- { emoji: "🍷", name: "wine", category: "Food" },
974
- { emoji: "🍸", name: "cocktail", category: "Food" },
975
- { emoji: "🍹", name: "tropical drink", category: "Food" },
976
- { emoji: "🍺", name: "beer", category: "Food" },
977
- { emoji: "🍻", name: "beers", category: "Food" },
978
- { emoji: "🥃", name: "tumbler glass", category: "Food" },
979
- { emoji: "🥤", name: "soda", category: "Food" },
980
- // Travel & Places
981
- { emoji: "🚗", name: "car", category: "Travel" },
982
- { emoji: "🚕", name: "taxi", category: "Travel" },
983
- { emoji: "🚙", name: "bus", category: "Travel" },
984
- { emoji: "🚌", name: "trolleybus", category: "Travel" },
985
- { emoji: "🏎️", name: "racing car", category: "Travel" },
986
- { emoji: "🚓", name: "police car", category: "Travel" },
987
- { emoji: "🚑", name: "ambulance", category: "Travel" },
988
- { emoji: "🚒", name: "fire engine", category: "Travel" },
989
- { emoji: "🚐", name: "minibus", category: "Travel" },
990
- { emoji: "🚚", name: "truck", category: "Travel" },
991
- { emoji: "🚛", name: "articulated lorry", category: "Travel" },
992
- { emoji: "🚜", name: "tractor", category: "Travel" },
993
- { emoji: "🚲", name: "bicycle", category: "Travel" },
994
- { emoji: "🛵", name: "scooter", category: "Travel" },
995
- { emoji: "🏍️", name: "motorcycle", category: "Travel" },
996
- { emoji: "🚄", name: "bullet train", category: "Travel" },
997
- { emoji: "🚆", name: "train", category: "Travel" },
998
- { emoji: "✈️", name: "airplane", category: "Travel" },
999
- { emoji: "🚀", name: "rocket", category: "Travel" },
1000
- { emoji: "🛸", name: "ufo", category: "Travel" },
1001
- { emoji: "🚁", name: "helicopter", category: "Travel" },
1002
- { emoji: "🚢", name: "ship", category: "Travel" },
1003
- { emoji: "⛵", name: "sailboat", category: "Travel" },
1004
- { emoji: "⚓", name: "anchor", category: "Travel" },
1005
- { emoji: "⛽", name: "fuel pump", category: "Travel" },
1006
- { emoji: "🚦", name: "traffic light", category: "Travel" },
1007
- // Objects & Tools
1008
- { emoji: "💻", name: "laptop", category: "Objects" },
1009
- { emoji: "📱", name: "mobile", category: "Objects" },
1010
- { emoji: "☎️", name: "telephone", category: "Objects" },
1011
- { emoji: "⌨️", name: "keyboard", category: "Objects" },
1012
- { emoji: "🖥️", name: "desktop", category: "Objects" },
1013
- { emoji: "🖨️", name: "printer", category: "Objects" },
1014
- { emoji: "📸", name: "camera", category: "Objects" },
1015
- { emoji: "🎥", name: "video camera", category: "Objects" },
1016
- { emoji: "📺", name: "tv", category: "Objects" },
1017
- { emoji: "📻", name: "radio", category: "Objects" },
1018
- { emoji: "⏰", name: "alarm clock", category: "Objects" },
1019
- { emoji: "💡", name: "light bulb", category: "Objects" },
1020
- { emoji: "🔦", name: "flashlight", category: "Objects" },
1021
- { emoji: "🕯️", name: "candle", category: "Objects" },
1022
- { emoji: "🔨", name: "hammer", category: "Objects" },
1023
- { emoji: "🔧", name: "wrench", category: "Objects" },
1024
- { emoji: "🔩", name: "nut and bolt", category: "Objects" },
1025
- { emoji: "🔫", name: "water pistol", category: "Objects" },
1026
- { emoji: "💸", name: "money", category: "Objects" },
1027
- { emoji: "💵", name: "dollar bill", category: "Objects" },
1028
- { emoji: "💳", name: "credit card", category: "Objects" },
1029
- { emoji: "💎", name: "gem", category: "Objects" },
1030
- { emoji: "⚖️", name: "balance scale", category: "Objects" },
1031
- { emoji: "🔗", name: "link", category: "Objects" },
1032
- { emoji: "⛓️", name: "chains", category: "Objects" },
1033
- { emoji: "💉", name: "syringe", category: "Objects" },
1034
- { emoji: "💊", name: "pill", category: "Objects" },
1035
- { emoji: "🚪", name: "door", category: "Objects" },
1036
- { emoji: "🛏️", name: "bed", category: "Objects" },
1037
- { emoji: "🛋️", name: "couch", category: "Objects" },
1038
- { emoji: "🚿", name: "shower", category: "Objects" },
1039
- { emoji: "🛁", name: "bathtub", category: "Objects" },
1040
- { emoji: "🔑", name: "key", category: "Objects" },
1041
- { emoji: "🧹", name: "broom", category: "Objects" },
1042
- // Activities & Hobbies
1043
- { emoji: "⚽", name: "soccer", category: "Activities" },
1044
- { emoji: "🏀", name: "basketball", category: "Activities" },
1045
- { emoji: "🏈", name: "football", category: "Activities" },
1046
- { emoji: "⚾", name: "baseball", category: "Activities" },
1047
- { emoji: "🎾", name: "tennis", category: "Activities" },
1048
- { emoji: "🏐", name: "volleyball", category: "Activities" },
1049
- { emoji: "🏉", name: "rugby", category: "Activities" },
1050
- { emoji: "🎱", name: "pool", category: "Activities" },
1051
- { emoji: "⛳", name: "golf", category: "Activities" },
1052
- { emoji: "🪁", name: "kite", category: "Activities" },
1053
- { emoji: "🏹", name: "bow and arrow", category: "Activities" },
1054
- { emoji: "🎣", name: "fishing", category: "Activities" },
1055
- { emoji: "🥊", name: "boxing", category: "Activities" },
1056
- { emoji: "🥋", name: "martial arts", category: "Activities" },
1057
- { emoji: "⛸️", name: "ice skate", category: "Activities" },
1058
- { emoji: "🎿", name: "ski", category: "Activities" },
1059
- { emoji: "🏂", name: "snowboard", category: "Activities" },
1060
- { emoji: "🏋️", name: "weightlifter", category: "Activities" },
1061
- { emoji: "🤺", name: "fencing", category: "Activities" },
1062
- { emoji: "🤼", name: "wrestling", category: "Activities" },
1063
- { emoji: "🤸", name: "cartwheel", category: "Activities" },
1064
- { emoji: "🏆", name: "trophy", category: "Activities" },
1065
- { emoji: "🏅", name: "medal", category: "Activities" },
1066
- { emoji: "🥇", name: "first place", category: "Activities" },
1067
- { emoji: "🎟️", name: "ticket", category: "Activities" },
1068
- { emoji: "🎮", name: "video game", category: "Activities" },
1069
- { emoji: "🎲", name: "die", category: "Activities" },
1070
- { emoji: "♟️", name: "chess", category: "Activities" },
1071
- { emoji: "🎹", name: "piano", category: "Activities" },
1072
- { emoji: "🎸", name: "guitar", category: "Activities" },
1073
- { emoji: "🎺", name: "trumpet", category: "Activities" },
1074
- { emoji: "🎻", name: "violin", category: "Activities" },
1075
- { emoji: "🥁", name: "drum", category: "Activities" },
1076
- { emoji: "🎭", name: "performing arts", category: "Activities" },
1077
- { emoji: "🎨", name: "artist palette", category: "Activities" },
1078
- { emoji: "🎬", name: "clapper board", category: "Activities" },
1079
- { emoji: "🎤", name: "microphone", category: "Activities" },
1080
- { emoji: "🎧", name: "headphone", category: "Activities" }
1081
- ];
1082
- class q {
1083
- container;
1084
- searchInput;
1085
- emojiGrid;
1086
- onSelect;
1087
- onClose;
1088
- theme;
1089
- dark;
1090
- constructor(e, t, i, o) {
1091
- this.onSelect = e, this.onClose = t, this.theme = i, this.dark = o, this.container = this.createPickerElement(), this.searchInput = this.container.querySelector(".te-emoji-search"), this.emojiGrid = this.container.querySelector(".te-emoji-grid"), this.setupEvents(), this.renderEmojis(g);
1092
- }
1093
- createPickerElement() {
1094
- const e = document.createElement("div");
1095
- return e.classList.add("te-emoji-picker"), this.theme && this.applyTheme(e, this.theme), this.dark && e.classList.add("te-dark"), e.innerHTML = `
1096
- <div class="te-emoji-header">
1097
- <input type="text" class="te-emoji-search" placeholder="Search emoji...">
1098
- </div>
1099
- <div class="te-emoji-body">
1100
- <div class="te-emoji-grid"></div>
1101
- </div>
1102
- `, e;
1103
- }
1104
- setupEvents() {
1105
- this.searchInput.addEventListener("mousedown", (t) => t.stopPropagation()), this.searchInput.addEventListener("click", (t) => t.stopPropagation()), this.searchInput.addEventListener("input", () => {
1106
- const t = this.searchInput.value.toLowerCase(), i = g.filter(
1107
- (o) => o.name.toLowerCase().includes(t) || o.category.toLowerCase().includes(t)
1108
- );
1109
- this.renderEmojis(i);
1110
- });
1111
- const e = (t) => {
1112
- this.container.contains(t.target) || (this.close(), document.removeEventListener("mousedown", e));
1113
- };
1114
- setTimeout(() => document.addEventListener("mousedown", e), 0);
1115
- }
1116
- renderEmojis(e) {
1117
- if (this.emojiGrid.innerHTML = "", e.length === 0) {
1118
- this.emojiGrid.innerHTML = '<div class="te-emoji-empty">No emoji found</div>';
1119
- return;
1120
- }
1121
- this.searchInput.value.length > 0 ? this.renderGridItems(e) : ["Smileys", "Symbols", "Hands", "Animals", "Food", "Travel", "Objects", "Activities"].forEach((o) => {
1122
- const n = e.filter((a) => a.category === o);
1123
- if (n.length > 0) {
1124
- const a = document.createElement("div");
1125
- a.classList.add("te-emoji-category-title"), a.textContent = o, this.emojiGrid.appendChild(a), this.renderGridItems(n);
1126
- }
1127
- });
1128
- }
1129
- renderGridItems(e) {
1130
- e.forEach((t) => {
1131
- const i = document.createElement("button");
1132
- i.type = "button", i.classList.add("te-emoji-item"), i.textContent = t.emoji, i.title = t.name, i.addEventListener("click", () => {
1133
- this.onSelect(t.emoji), this.close();
1134
- }), this.emojiGrid.appendChild(i);
1135
- });
1136
- }
1137
- applyTheme(e, t) {
1138
- const i = {
1139
- primaryColor: "--te-primary-color",
1140
- primaryHover: "--te-primary-hover",
1141
- bgApp: "--te-bg-app",
1142
- bgEditor: "--te-bg-editor",
1143
- toolbarBg: "--te-toolbar-bg",
1144
- borderColor: "--te-border-color",
1145
- borderFocus: "--te-border-focus",
1146
- textMain: "--te-text-main",
1147
- textMuted: "--te-text-muted",
1148
- placeholder: "--te-placeholder",
1149
- btnHover: "--te-btn-hover",
1150
- btnActive: "--te-btn-active",
1151
- radiusLg: "--te-radius-lg",
1152
- radiusMd: "--te-radius-md",
1153
- radiusSm: "--te-radius-sm",
1154
- shadowSm: "--te-shadow-sm",
1155
- shadowMd: "--te-shadow-md",
1156
- shadowLg: "--te-shadow-lg"
1157
- };
1158
- for (const [o, n] of Object.entries(i)) {
1159
- const a = t[o];
1160
- a && e.style.setProperty(n, a);
1161
- }
1162
- }
1163
- show(e) {
1164
- document.body.appendChild(this.container);
1165
- const t = e.getBoundingClientRect(), i = 280;
1166
- let o = t.bottom + window.scrollY + 5, n = t.left + window.scrollX;
1167
- n + i > window.innerWidth && (n = window.innerWidth - i - 10), this.container.style.top = `${o}px`, this.container.style.left = `${n}px`, this.searchInput.focus();
1168
- }
1169
- close() {
1170
- this.container.parentElement && (this.container.remove(), this.onClose());
1171
- }
1172
- get el() {
1173
- return this.container;
1174
- }
1175
- }
1176
- class U {
1177
- editor;
1178
- container;
1179
- savedRange = null;
1180
- items = $;
1181
- activePicker = null;
1182
- statusEl = null;
1183
- constructor(e) {
1184
- this.editor = e, this.container = this.createToolbarElement(), this.render();
1185
- }
1186
- createToolbarElement() {
1187
- const e = document.createElement("div");
1188
- return e.classList.add("te-toolbar"), this.statusEl = document.createElement("div"), this.statusEl.classList.add("te-toolbar-status"), this.statusEl.style.marginLeft = "auto", this.statusEl.style.display = "flex", this.statusEl.style.alignItems = "center", this.statusEl.style.gap = "6px", this.statusEl.style.fontSize = "12px", this.statusEl.style.color = "var(--te-text-muted)", this.statusEl.style.paddingRight = "12px", e;
1189
- }
1190
- render() {
1191
- const e = this.editor.getOptions().toolbarItems, t = [];
1192
- this.items.forEach((n) => {
1193
- (n.type === "divider" || n.id && (!e || e.includes(n.id))) && t.push(n);
1194
- });
1195
- const i = [];
1196
- t.forEach((n, a) => {
1197
- if (n.type === "divider") {
1198
- if (i.length === 0 || i[i.length - 1].type === "divider" || !t.slice(a + 1).some((r) => r.type !== "divider")) return;
1199
- i.push(n);
1200
- } else
1201
- i.push(n);
1202
- }), i.forEach((n) => {
1203
- if (n.type === "button")
1204
- this.renderButton(n);
1205
- else if (n.type === "select")
1206
- this.renderSelect(n);
1207
- else if (n.type === "input")
1208
- this.renderInput(n);
1209
- else if (n.type === "color-picker")
1210
- this.renderColorPicker(n);
1211
- else if (n.type === "divider") {
1212
- const a = document.createElement("div");
1213
- a.classList.add("te-divider"), this.container.appendChild(a);
1214
- }
1215
- }), this.editor.getOptions().showStatus !== !1 && this.container.appendChild(this.statusEl), this.editor.el.addEventListener("keyup", () => this.updateActiveStates()), this.editor.el.addEventListener("mouseup", () => this.updateActiveStates());
1216
- }
1217
- renderButton(e) {
1218
- const t = document.createElement("button");
1219
- t.classList.add("te-button"), t.innerHTML = e.icon || "", t.title = e.title, t.addEventListener("mousedown", (i) => {
1220
- if (i.preventDefault(), e.command === "insertEmoji") {
1221
- this.activePicker ? this.activePicker.close() : (this.activePicker = new q(
1222
- (o) => {
1223
- this.editor.execute("insertText", o);
1224
- },
1225
- () => {
1226
- this.activePicker = null;
1227
- },
1228
- this.editor.getOptions().theme,
1229
- this.editor.getOptions().dark
1230
- ), this.activePicker.show(t));
1231
- return;
1232
- }
1233
- if (e.command === "createLink") {
1234
- const o = window.prompt("Enter the URL");
1235
- o && this.editor.createLink(o);
1236
- return;
1237
- }
1238
- if (e.command === "insertImage") {
1239
- const o = document.createElement("input");
1240
- o.type = "file", o.accept = "image/*", o.style.display = "none", o.addEventListener("change", (n) => {
1241
- const s = n.target.files?.[0];
1242
- if (s) {
1243
- const r = new FileReader();
1244
- r.onload = (l) => {
1245
- const c = l.target?.result;
1246
- this.editor.insertImage(c);
1247
- }, r.readAsDataURL(s);
1248
- }
1249
- document.body.removeChild(o);
1250
- }), document.body.appendChild(o), o.click();
1251
- return;
1252
- }
1253
- if (e.command === "insertTable") {
1254
- const o = window.prompt("Enter number of rows", "3"), n = window.prompt("Enter number of columns", "3");
1255
- o && n && this.editor.insertTable(parseInt(o, 10), parseInt(n, 10));
1256
- return;
1257
- }
1258
- if (["addRow", "deleteRow", "addColumn", "deleteColumn"].includes(e.command || "")) {
1259
- const o = e.command;
1260
- this.editor[o]();
1261
- return;
1262
- }
1263
- e.command && this.editor.execute(e.command, e.value || null), this.updateActiveStates();
1264
- }), this.container.appendChild(t);
1265
- }
1266
- renderInput(e) {
1267
- const t = document.createElement("input");
1268
- t.type = "number", t.classList.add("te-input"), t.title = e.title, t.value = e.value || "", t.min = "1", t.max = "100";
1269
- const i = () => {
1270
- const n = window.getSelection();
1271
- if (n && n.rangeCount > 0) {
1272
- const a = n.getRangeAt(0);
1273
- this.editor.el.contains(a.commonAncestorContainer) && (this.savedRange = a.cloneRange());
1274
- }
1275
- };
1276
- t.addEventListener("mousedown", i), t.addEventListener("focus", i);
1277
- const o = () => {
1278
- let n = parseInt(t.value, 10);
1279
- if (!isNaN(n) && (n = Math.max(1, Math.min(100, n)), t.value = n.toString(), e.command === "fontSize")) {
1280
- if (this.savedRange) {
1281
- const a = this.editor.setStyle("font-size", `${n}px`, this.savedRange);
1282
- a && (this.savedRange = a);
1283
- } else
1284
- this.editor.setStyle("font-size", `${n}px`);
1285
- t.focus();
1286
- }
1287
- };
1288
- t.addEventListener("input", o), t.addEventListener("keydown", (n) => {
1289
- n.key === "Enter" && (o(), this.editor.focus());
1290
- }), this.container.appendChild(t);
1291
- }
1292
- renderSelect(e) {
1293
- const t = document.createElement("select");
1294
- t.classList.add("te-select"), t.title = e.title, e.options && e.options.forEach((i) => {
1295
- const o = document.createElement("option");
1296
- o.value = i.value, o.textContent = i.label, t.appendChild(o);
1297
- }), t.addEventListener("change", () => {
1298
- const i = t.value;
1299
- this.savedRange && this.editor.selection.restoreSelection(this.savedRange), e.command === "formatBlock" ? this.editor.execute(e.command, i) : e.command === "fontFamily" ? this.editor.setStyle("font-family", i) : e.command === "lineHeight" && this.editor.setStyle("line-height", i), this.editor.focus();
1300
- }), t.addEventListener("mousedown", () => {
1301
- this.savedRange = this.editor.selection.saveSelection();
1302
- }), this.container.appendChild(t);
1303
- }
1304
- renderColorPicker(e) {
1305
- const t = document.createElement("div");
1306
- if (t.classList.add("te-color-picker-wrapper"), t.title = e.title, e.icon) {
1307
- const o = document.createElement("div");
1308
- o.classList.add("te-button", "te-color-icon"), o.innerHTML = e.icon;
1309
- const n = document.createElement("div");
1310
- n.classList.add("te-color-indicator"), n.style.backgroundColor = e.value || "#000000", o.appendChild(n), t.appendChild(o);
1311
- }
1312
- const i = document.createElement("input");
1313
- i.type = "color", i.classList.add("te-color-picker-input"), e.icon || (i.classList.add("te-color-picker"), i.title = e.title), i.value = e.value || "#000000", i.addEventListener("mousedown", () => {
1314
- this.savedRange = this.editor.selection.saveSelection();
1315
- }), i.addEventListener("input", () => {
1316
- if (e.icon) {
1317
- const o = t.querySelector(".te-color-indicator");
1318
- o && (o.style.backgroundColor = i.value);
1319
- }
1320
- }), i.addEventListener("change", () => {
1321
- this.savedRange && this.editor.selection.restoreSelection(this.savedRange), e.command && this.editor.execute(e.command, i.value), this.editor.focus();
1322
- }), t.appendChild(i), this.container.appendChild(e.icon ? t : i);
1323
- }
1324
- get el() {
1325
- return this.container;
1326
- }
1327
- updateActiveStates() {
1328
- const e = this.container.querySelectorAll(".te-button");
1329
- let t = 0;
1330
- this.items.forEach((i) => {
1331
- if (i.type === "button") {
1332
- const o = e[t++];
1333
- i.command && document.queryCommandState(i.command) ? o.classList.add("active") : o.classList.remove("active");
1334
- }
1335
- });
1336
- }
1337
- updateStatus(e, t = !1) {
1338
- if (!this.statusEl || this.editor.getOptions().showStatus === !1) return;
1339
- if (this.statusEl.innerHTML = "", t) {
1340
- const o = document.createElement("div");
1341
- o.classList.add("te-toolbar-loader"), this.statusEl.appendChild(o);
1342
- }
1343
- const i = document.createElement("span");
1344
- i.textContent = e, this.statusEl.appendChild(i);
1345
- }
1346
- }
1347
- class V extends p {
1348
- toolbar;
1349
- constructor(e, t = {}) {
1350
- const i = {
1351
- ...t,
1352
- onSaving: () => {
1353
- this.toolbar?.updateStatus("Auto saving...", !0), t.onSaving && t.onSaving();
1354
- },
1355
- onSave: (o) => {
1356
- const n = (/* @__PURE__ */ new Date()).toLocaleString([], {
1357
- year: "numeric",
1358
- month: "short",
1359
- day: "numeric",
1360
- hour: "2-digit",
1361
- minute: "2-digit",
1362
- hour12: !0
1363
- });
1364
- this.toolbar?.updateStatus(`Saved at ${n}`, !1), t.onSave && t.onSave(o);
1365
- }
1366
- };
1367
- if (super(e, i), typeof document > "u" || !e) {
1368
- this.toolbar = {};
1369
- return;
1370
- }
1371
- this.toolbar = new U(this), this.container.insertBefore(this.toolbar.el, this.editableElement), i.showStatus !== !1 && this.toolbar.updateStatus("All changes saved", !1);
1372
- }
1373
- getToolbar() {
1374
- return this.toolbar;
1375
- }
1376
- }
1377
- export {
1378
- p as CoreEditor,
1379
- u as HistoryManager,
1380
- h as SelectionManager,
1381
- V as TestEditor,
1382
- U as Toolbar
1383
- };