@meenainwal/rich-text-editor 1.2.0 → 1.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/inkflow-editor.mjs +228 -222
- package/dist/rich-text-editor.css +1 -1
- package/dist/ui/Toolbar.d.ts +1 -0
- package/package.json +1 -1
package/dist/inkflow-editor.mjs
CHANGED
|
@@ -34,8 +34,8 @@ class b {
|
|
|
34
34
|
try {
|
|
35
35
|
const n = this.getNodeByPath(t.startPath, e), i = this.getNodeByPath(t.endPath, e);
|
|
36
36
|
if (n && i) {
|
|
37
|
-
const
|
|
38
|
-
|
|
37
|
+
const s = document.createRange();
|
|
38
|
+
s.setStart(n, Math.min(t.startOffset, n.textContent?.length || 0)), s.setEnd(i, Math.min(t.endOffset, i.textContent?.length || 0)), this.restoreSelection(s);
|
|
39
39
|
}
|
|
40
40
|
} catch (n) {
|
|
41
41
|
console.warn("Failed to restore selection path:", n);
|
|
@@ -45,8 +45,8 @@ class b {
|
|
|
45
45
|
const n = [];
|
|
46
46
|
let i = e;
|
|
47
47
|
for (; i !== t && i.parentElement; ) {
|
|
48
|
-
const
|
|
49
|
-
n.unshift(
|
|
48
|
+
const s = Array.from(i.parentElement.childNodes).indexOf(i);
|
|
49
|
+
n.unshift(s), i = i.parentElement;
|
|
50
50
|
}
|
|
51
51
|
return n;
|
|
52
52
|
}
|
|
@@ -132,11 +132,11 @@ class y {
|
|
|
132
132
|
const t = this.editor.selection.getRange();
|
|
133
133
|
if (t && this.activeContainer.contains(t.commonAncestorContainer)) {
|
|
134
134
|
e.preventDefault();
|
|
135
|
-
const n = this.activeContainer.querySelector("img"), i = n?.getAttribute("data-image-id"),
|
|
136
|
-
|
|
135
|
+
const n = this.activeContainer.querySelector("img"), i = n?.getAttribute("data-image-id"), s = n?.src, o = this.editor.getOptions();
|
|
136
|
+
o.onImageDelete && o.onImageDelete(i || void 0, s), i && o.imageEndpoints?.delete && fetch(o.imageEndpoints.delete, {
|
|
137
137
|
method: "DELETE",
|
|
138
138
|
headers: { "Content-Type": "application/json" },
|
|
139
|
-
body: JSON.stringify({ id: i, url:
|
|
139
|
+
body: JSON.stringify({ id: i, url: s })
|
|
140
140
|
}).catch((a) => console.error("Failed to notify server of image deletion", a)), this.activeContainer.remove(), this.activeContainer = null, this.editor.el.dispatchEvent(new Event("input", { bubbles: !0 }));
|
|
141
141
|
}
|
|
142
142
|
}
|
|
@@ -160,8 +160,8 @@ class y {
|
|
|
160
160
|
handleResize(e) {
|
|
161
161
|
if (!this.activeContainer || !this.isResizing) return;
|
|
162
162
|
const t = this.activeContainer.querySelector("img"), n = e.clientX - this.startX, i = e.clientY - this.startY;
|
|
163
|
-
let
|
|
164
|
-
this.currentHandle?.includes("right") ?
|
|
163
|
+
let s = this.startWidth, o = this.startHeight;
|
|
164
|
+
this.currentHandle?.includes("right") ? s = this.startWidth + n : this.currentHandle?.includes("left") ? s = this.startWidth - n : this.currentHandle?.includes("bottom") ? s = this.startWidth + i * this.aspectRatio : this.currentHandle?.includes("top") && (s = this.startWidth - i * this.aspectRatio), o = s / this.aspectRatio, s > 50 && s < this.editor.el.clientWidth && (t.style.width = `${s}px`, t.style.height = `${o}px`);
|
|
165
165
|
}
|
|
166
166
|
stopResize() {
|
|
167
167
|
this.isResizing = !1, this.currentHandle = null, document.body.style.cursor = "", this.editor.el.dispatchEvent(new Event("input", { bubbles: !0 }));
|
|
@@ -220,7 +220,7 @@ const w = {
|
|
|
220
220
|
title: "Redo",
|
|
221
221
|
command: "redo",
|
|
222
222
|
icon: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 7v6h-6"></path><path d="M3 17a9 9 0 0 1 9-9 9 9 0 0 1 6 2.3l3 2.7"></path></svg>'
|
|
223
|
-
},
|
|
223
|
+
}, L = {
|
|
224
224
|
type: "select",
|
|
225
225
|
title: "Heading",
|
|
226
226
|
command: "formatBlock",
|
|
@@ -234,7 +234,7 @@ const w = {
|
|
|
234
234
|
{ label: "Heading 5", value: "H5" },
|
|
235
235
|
{ label: "Heading 6", value: "H6" }
|
|
236
236
|
]
|
|
237
|
-
},
|
|
237
|
+
}, k = {
|
|
238
238
|
type: "select",
|
|
239
239
|
title: "Font",
|
|
240
240
|
command: "fontFamily",
|
|
@@ -347,12 +347,12 @@ const w = {
|
|
|
347
347
|
title: "Bulleted List",
|
|
348
348
|
command: "insertUnorderedList",
|
|
349
349
|
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><line x1="3" y1="6" x2="3.01" y2="6"></line><line x1="3" y1="12" x2="3.01" y2="12"></line><line x1="3" y1="18" x2="3.01" y2="18"></line></svg>'
|
|
350
|
-
},
|
|
350
|
+
}, B = {
|
|
351
351
|
type: "button",
|
|
352
352
|
title: "Numbered List",
|
|
353
353
|
command: "insertOrderedList",
|
|
354
354
|
icon: '<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>'
|
|
355
|
-
},
|
|
355
|
+
}, O = {
|
|
356
356
|
type: "button",
|
|
357
357
|
title: "Outdent",
|
|
358
358
|
command: "outdent",
|
|
@@ -367,12 +367,12 @@ const w = {
|
|
|
367
367
|
title: "Horizontal Rule",
|
|
368
368
|
command: "insertHorizontalRule",
|
|
369
369
|
icon: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="5" y1="12" x2="19" y2="12"></line></svg>'
|
|
370
|
-
},
|
|
370
|
+
}, q = {
|
|
371
371
|
type: "button",
|
|
372
372
|
title: "Clear Formatting",
|
|
373
373
|
command: "removeFormat",
|
|
374
374
|
icon: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4 7V4h16v3"></path><path d="M5 20h6"></path><path d="M13 4 8 20"></path><path d="m15 15 5 5"></path><path d="m20 15-5 5"></path></svg>'
|
|
375
|
-
},
|
|
375
|
+
}, W = {
|
|
376
376
|
type: "button",
|
|
377
377
|
title: "Insert Emoji",
|
|
378
378
|
command: "insertEmoji",
|
|
@@ -396,8 +396,8 @@ const w = {
|
|
|
396
396
|
{ ...w, id: "undo" },
|
|
397
397
|
{ ...x, id: "redo" },
|
|
398
398
|
m,
|
|
399
|
-
{ ...
|
|
400
|
-
{ ...
|
|
399
|
+
{ ...L, id: "heading" },
|
|
400
|
+
{ ...k, id: "font-family" },
|
|
401
401
|
{ ...C, id: "font-size" },
|
|
402
402
|
{ ...S, id: "line-height" },
|
|
403
403
|
m,
|
|
@@ -415,16 +415,16 @@ const w = {
|
|
|
415
415
|
{ ...D, id: "align-justify" },
|
|
416
416
|
m,
|
|
417
417
|
{ ...z, id: "bullet-list" },
|
|
418
|
-
{ ...
|
|
419
|
-
{ ...
|
|
418
|
+
{ ...B, id: "ordered-list" },
|
|
419
|
+
{ ...O, id: "outdent" },
|
|
420
420
|
{ ...U, id: "indent" },
|
|
421
421
|
m,
|
|
422
422
|
{ ...F, id: "horizontal-rule" },
|
|
423
|
-
{ ...
|
|
423
|
+
{ ...W, id: "emoji" },
|
|
424
424
|
{ ..._, id: "link" },
|
|
425
425
|
{ ...$, id: "image" },
|
|
426
426
|
{ ...V, id: "table" },
|
|
427
|
-
{ ...
|
|
427
|
+
{ ...q, id: "clear-formatting" }
|
|
428
428
|
];
|
|
429
429
|
class g {
|
|
430
430
|
container;
|
|
@@ -433,55 +433,55 @@ class g {
|
|
|
433
433
|
dark;
|
|
434
434
|
theme;
|
|
435
435
|
fields;
|
|
436
|
-
constructor(e, t, n, i,
|
|
437
|
-
this.fields = t, this.onConfirm = n, this.onClose = i, this.theme =
|
|
436
|
+
constructor(e, t, n, i, s, o) {
|
|
437
|
+
this.fields = t, this.onConfirm = n, this.onClose = i, this.theme = s, this.dark = o, this.container = this.createModalElement(e, t), this.setupEvents();
|
|
438
438
|
}
|
|
439
439
|
createModalElement(e, t) {
|
|
440
440
|
const n = document.createElement("div");
|
|
441
441
|
n.classList.add("te-modal"), this.theme && this.applyTheme(n, this.theme), this.dark && n.classList.add("te-dark");
|
|
442
442
|
const i = document.createElement("div");
|
|
443
443
|
i.classList.add("te-modal-header"), i.textContent = e, n.appendChild(i);
|
|
444
|
-
const
|
|
445
|
-
|
|
444
|
+
const s = document.createElement("div");
|
|
445
|
+
s.classList.add("te-modal-body"), t.forEach((l) => {
|
|
446
446
|
const d = document.createElement("div");
|
|
447
447
|
d.classList.add("te-modal-field");
|
|
448
448
|
const c = document.createElement("label");
|
|
449
449
|
c.setAttribute("for", l.id), c.textContent = l.label;
|
|
450
450
|
const h = document.createElement("input");
|
|
451
|
-
h.type = l.type, h.id = l.id, h.classList.add("te-modal-input"), l.placeholder && (h.placeholder = l.placeholder), l.defaultValue && (h.value = l.defaultValue), l.min && (h.min = l.min), l.max && (h.max = l.max), d.appendChild(c), d.appendChild(h),
|
|
452
|
-
}), n.appendChild(
|
|
453
|
-
const
|
|
454
|
-
|
|
451
|
+
h.type = l.type, h.id = l.id, h.classList.add("te-modal-input"), l.placeholder && (h.placeholder = l.placeholder), l.defaultValue && (h.value = l.defaultValue), l.min && (h.min = l.min), l.max && (h.max = l.max), d.appendChild(c), d.appendChild(h), s.appendChild(d);
|
|
452
|
+
}), n.appendChild(s);
|
|
453
|
+
const o = document.createElement("div");
|
|
454
|
+
o.classList.add("te-modal-footer");
|
|
455
455
|
const a = document.createElement("button");
|
|
456
456
|
a.classList.add("te-modal-btn", "te-modal-btn-cancel"), a.textContent = "Cancel";
|
|
457
457
|
const r = document.createElement("button");
|
|
458
|
-
return r.classList.add("te-modal-btn", "te-modal-btn-confirm"), r.textContent = "Insert",
|
|
458
|
+
return r.classList.add("te-modal-btn", "te-modal-btn-confirm"), r.textContent = "Insert", o.appendChild(a), o.appendChild(r), n.appendChild(o), n;
|
|
459
459
|
}
|
|
460
460
|
setupEvents() {
|
|
461
461
|
const e = this.container.querySelector(".te-modal-btn-cancel"), t = this.container.querySelector(".te-modal-btn-confirm");
|
|
462
462
|
e.addEventListener("click", () => this.close()), t.addEventListener("click", () => {
|
|
463
|
-
const
|
|
464
|
-
this.fields.forEach((
|
|
465
|
-
const a = this.container.querySelector(`#${
|
|
466
|
-
o
|
|
467
|
-
}), this.onConfirm(
|
|
463
|
+
const s = {};
|
|
464
|
+
this.fields.forEach((o) => {
|
|
465
|
+
const a = this.container.querySelector(`#${o.id}`);
|
|
466
|
+
s[o.id] = a.value;
|
|
467
|
+
}), this.onConfirm(s), this.close();
|
|
468
468
|
});
|
|
469
|
-
const n = (
|
|
470
|
-
|
|
469
|
+
const n = (s) => {
|
|
470
|
+
s.key === "Escape" && this.close(), s.key === "Enter" && t.click();
|
|
471
471
|
};
|
|
472
472
|
this.container.addEventListener("keydown", n);
|
|
473
|
-
const i = (
|
|
474
|
-
this.container.contains(
|
|
473
|
+
const i = (s) => {
|
|
474
|
+
this.container.contains(s.target) || (this.close(), document.removeEventListener("mousedown", i));
|
|
475
475
|
};
|
|
476
476
|
setTimeout(() => document.addEventListener("mousedown", i), 0);
|
|
477
477
|
}
|
|
478
478
|
show(e) {
|
|
479
479
|
document.body.appendChild(this.container);
|
|
480
480
|
const t = e.getBoundingClientRect(), n = 260;
|
|
481
|
-
let i = t.bottom + window.scrollY + 10,
|
|
482
|
-
|
|
483
|
-
const
|
|
484
|
-
|
|
481
|
+
let i = t.bottom + window.scrollY + 10, s = t.left + window.scrollX;
|
|
482
|
+
s + n > window.innerWidth && (s = window.innerWidth - n - 20), this.container.style.top = `${i}px`, this.container.style.left = `${s}px`;
|
|
483
|
+
const o = this.container.querySelector("input");
|
|
484
|
+
o && o.focus();
|
|
485
485
|
}
|
|
486
486
|
close() {
|
|
487
487
|
this.container.parentElement && (this.container.remove(), this.onClose());
|
|
@@ -507,9 +507,9 @@ class g {
|
|
|
507
507
|
shadowMd: "--te-shadow-md",
|
|
508
508
|
shadowLg: "--te-shadow-lg"
|
|
509
509
|
};
|
|
510
|
-
for (const [i,
|
|
511
|
-
const
|
|
512
|
-
|
|
510
|
+
for (const [i, s] of Object.entries(n)) {
|
|
511
|
+
const o = t[i];
|
|
512
|
+
o && e.style.setProperty(s, o);
|
|
513
513
|
}
|
|
514
514
|
}
|
|
515
515
|
}
|
|
@@ -527,10 +527,10 @@ class G {
|
|
|
527
527
|
e.className = "te-floating-toolbar te-glass", e.style.display = "none", e.style.position = "absolute", e.style.zIndex = "2000";
|
|
528
528
|
const t = ["heading", "bold", "italic", "underline", "strikethrough", "highlight-color", "link", "clear-formatting"];
|
|
529
529
|
return v.filter((i) => i.id && t.includes(i.id)).forEach((i) => {
|
|
530
|
-
const
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
}, e.appendChild(
|
|
530
|
+
const s = document.createElement("button");
|
|
531
|
+
s.className = "te-floating-btn", s.title = i.title, s.innerHTML = i.icon || i.title, s.onclick = (o) => {
|
|
532
|
+
o.preventDefault(), o.stopPropagation(), this.handleCommand(i);
|
|
533
|
+
}, e.appendChild(s);
|
|
534
534
|
}), e;
|
|
535
535
|
}
|
|
536
536
|
handleCommand(e) {
|
|
@@ -558,7 +558,9 @@ class G {
|
|
|
558
558
|
const e = () => {
|
|
559
559
|
setTimeout(() => this.updatePosition(), 50);
|
|
560
560
|
};
|
|
561
|
-
this.editor.el.addEventListener("mouseup", e), this.editor.el.addEventListener("keyup", e),
|
|
561
|
+
this.editor.el.addEventListener("mouseup", e), this.editor.el.addEventListener("keyup", e), this.editor.el.addEventListener("scroll", () => {
|
|
562
|
+
this.isVisible && !this.activeModal && this.hide();
|
|
563
|
+
}, !0), window.addEventListener("mousedown", (t) => {
|
|
562
564
|
!this.container.contains(t.target) && !this.editor.el.contains(t.target) && this.hide();
|
|
563
565
|
}), window.addEventListener("resize", () => {
|
|
564
566
|
this.isVisible && this.updatePosition();
|
|
@@ -575,11 +577,13 @@ class G {
|
|
|
575
577
|
this.hide();
|
|
576
578
|
return;
|
|
577
579
|
}
|
|
578
|
-
const n = t.getBoundingClientRect();
|
|
580
|
+
const n = t.getBoundingClientRect(), s = (this.container.offsetParent || document.documentElement).getBoundingClientRect();
|
|
579
581
|
this.container.style.display = "flex", this.isVisible = !0;
|
|
580
|
-
const
|
|
581
|
-
let
|
|
582
|
-
|
|
582
|
+
const o = this.container.offsetWidth, a = this.container.offsetHeight;
|
|
583
|
+
let r = n.top - s.top - a - 10, l = n.left - s.left + n.width / 2 - o / 2;
|
|
584
|
+
n.top - a - 15 < 0 && (r = n.bottom - s.top + 10);
|
|
585
|
+
const d = 10 - s.left, c = window.innerWidth - 10 - s.left - o;
|
|
586
|
+
l < d && (l = d), l > c && (l = c), this.container.style.top = `${r}px`, this.container.style.left = `${l}px`, this.container.classList.add("te-floating-visible");
|
|
583
587
|
}
|
|
584
588
|
hide() {
|
|
585
589
|
this.container.style.display = "none", this.container.classList.remove("te-floating-visible"), this.isVisible = !1;
|
|
@@ -599,25 +603,25 @@ class f {
|
|
|
599
603
|
return new Promise((n, i) => {
|
|
600
604
|
if (e.size <= t * 1024 * 1024 && e.type === "image/webp")
|
|
601
605
|
return n(e);
|
|
602
|
-
const
|
|
603
|
-
|
|
604
|
-
const
|
|
605
|
-
let a =
|
|
606
|
+
const s = new Image();
|
|
607
|
+
s.src = URL.createObjectURL(e), s.onload = () => {
|
|
608
|
+
const o = document.createElement("canvas");
|
|
609
|
+
let a = s.width, r = s.height;
|
|
606
610
|
const l = 2e3;
|
|
607
|
-
(a > l || r > l) && (a > r ? (r = Math.round(r * l / a), a = l) : (a = Math.round(a * l / r), r = l)),
|
|
608
|
-
const d =
|
|
611
|
+
(a > l || r > l) && (a > r ? (r = Math.round(r * l / a), a = l) : (a = Math.round(a * l / r), r = l)), o.width = a, o.height = r;
|
|
612
|
+
const d = o.getContext("2d");
|
|
609
613
|
if (!d)
|
|
610
614
|
return i(new Error("Failed to get canvas context"));
|
|
611
|
-
d.drawImage(
|
|
615
|
+
d.drawImage(s, 0, 0, a, r), o.toBlob(
|
|
612
616
|
(c) => {
|
|
613
617
|
c ? n(c) : i(new Error("Canvas toBlob failed"));
|
|
614
618
|
},
|
|
615
619
|
"image/webp",
|
|
616
620
|
0.8
|
|
617
621
|
// 80% quality is professional standard
|
|
618
|
-
), URL.revokeObjectURL(
|
|
619
|
-
},
|
|
620
|
-
URL.revokeObjectURL(
|
|
622
|
+
), URL.revokeObjectURL(s.src);
|
|
623
|
+
}, s.onerror = () => {
|
|
624
|
+
URL.revokeObjectURL(s.src), i(new Error("Failed to load image for compression"));
|
|
621
625
|
};
|
|
622
626
|
});
|
|
623
627
|
}
|
|
@@ -630,27 +634,27 @@ class f {
|
|
|
630
634
|
const i = new FormData();
|
|
631
635
|
i.append("file", e, n);
|
|
632
636
|
try {
|
|
633
|
-
const
|
|
637
|
+
const s = await fetch(t.imageEndpoints.upload, {
|
|
634
638
|
method: "POST",
|
|
635
639
|
body: i
|
|
636
640
|
});
|
|
637
|
-
if (
|
|
638
|
-
const
|
|
641
|
+
if (s.ok) {
|
|
642
|
+
const o = await s.json();
|
|
639
643
|
return {
|
|
640
|
-
imageUrl:
|
|
641
|
-
imageId:
|
|
644
|
+
imageUrl: o.imageUrl,
|
|
645
|
+
imageId: o.imageId
|
|
642
646
|
};
|
|
643
647
|
}
|
|
644
648
|
console.warn("Custom upload endpoint returned an error, falling back.");
|
|
645
|
-
} catch (
|
|
646
|
-
console.error("Custom upload failed:",
|
|
649
|
+
} catch (s) {
|
|
650
|
+
console.error("Custom upload failed:", s);
|
|
647
651
|
}
|
|
648
652
|
}
|
|
649
653
|
if (t.cloudinaryFallback) {
|
|
650
|
-
const { cloudName: i, uploadPreset:
|
|
651
|
-
a.append("file", e, n), a.append("upload_preset",
|
|
654
|
+
const { cloudName: i, uploadPreset: s } = t.cloudinaryFallback, o = `https://api.cloudinary.com/v1_1/${i}/image/upload`, a = new FormData();
|
|
655
|
+
a.append("file", e, n), a.append("upload_preset", s);
|
|
652
656
|
try {
|
|
653
|
-
const r = await fetch(
|
|
657
|
+
const r = await fetch(o, {
|
|
654
658
|
method: "POST",
|
|
655
659
|
body: a
|
|
656
660
|
});
|
|
@@ -712,9 +716,9 @@ class K {
|
|
|
712
716
|
shadowMd: "--te-shadow-md",
|
|
713
717
|
shadowLg: "--te-shadow-lg"
|
|
714
718
|
};
|
|
715
|
-
for (const [i,
|
|
716
|
-
const
|
|
717
|
-
|
|
719
|
+
for (const [i, s] of Object.entries(n)) {
|
|
720
|
+
const o = e[i];
|
|
721
|
+
o && t.style.setProperty(s, o);
|
|
718
722
|
}
|
|
719
723
|
}
|
|
720
724
|
/**
|
|
@@ -733,7 +737,12 @@ class K {
|
|
|
733
737
|
}
|
|
734
738
|
checkPlaceholder() {
|
|
735
739
|
if (!this.editableElement) return;
|
|
736
|
-
this.editableElement.textContent?.trim() === "" && !this.editableElement.querySelector("img") && !this.editableElement.querySelector("table") && !this.editableElement.querySelector("ul") && !this.editableElement.querySelector("ol")
|
|
740
|
+
if (this.editableElement.textContent?.trim() === "" && !this.editableElement.querySelector("img") && !this.editableElement.querySelector("table") && !this.editableElement.querySelector("ul") && !this.editableElement.querySelector("ol") && !this.editableElement.querySelector("hr") && !this.editableElement.querySelector("figure") && !this.editableElement.querySelector("blockquote") && !this.editableElement.querySelector("pre")) {
|
|
741
|
+
this.editableElement.classList.add("is-empty");
|
|
742
|
+
const t = this.editableElement.firstElementChild;
|
|
743
|
+
t && (this.editableElement.style.textAlign = t.style.textAlign);
|
|
744
|
+
} else
|
|
745
|
+
this.editableElement.classList.remove("is-empty"), this.editableElement.style.textAlign = "";
|
|
737
746
|
}
|
|
738
747
|
addEventListener(e, t, n, i) {
|
|
739
748
|
e.addEventListener(t, n, i), this.eventListeners.push({ target: e, type: t, handler: n });
|
|
@@ -744,8 +753,8 @@ class K {
|
|
|
744
753
|
t.addedNodes.forEach((n) => {
|
|
745
754
|
if (n.nodeType === Node.ELEMENT_NODE) {
|
|
746
755
|
const i = n;
|
|
747
|
-
i.tagName === "IMG" && !i.closest(".te-image-container") ? this.wrapImage(i) : i.querySelectorAll("img:not(.te-image)").forEach((
|
|
748
|
-
|
|
756
|
+
i.tagName === "IMG" && !i.closest(".te-image-container") ? this.wrapImage(i) : i.querySelectorAll("img:not(.te-image)").forEach((o) => {
|
|
757
|
+
o.closest(".te-image-container") || this.wrapImage(o);
|
|
749
758
|
});
|
|
750
759
|
}
|
|
751
760
|
});
|
|
@@ -765,11 +774,11 @@ class K {
|
|
|
765
774
|
n.classList.add("te-image-container"), n.setAttribute("contenteditable", "false");
|
|
766
775
|
const i = document.createElement("img");
|
|
767
776
|
i.src = e.src, i.alt = e.alt || "", e.width && (i.style.width = `${e.width}px`), e.height && (i.style.height = `${e.height}px`), i.classList.add("te-image");
|
|
768
|
-
const
|
|
769
|
-
if (
|
|
777
|
+
const s = document.createElement("figcaption");
|
|
778
|
+
if (s.classList.add("te-image-caption"), s.setAttribute("contenteditable", "true"), s.setAttribute("data-placeholder", "Type caption..."), ["top-left", "top-right", "bottom-left", "bottom-right"].forEach((a) => {
|
|
770
779
|
const r = document.createElement("div");
|
|
771
780
|
r.classList.add("te-image-resizer", `te-resizer-${a}`), n.appendChild(r);
|
|
772
|
-
}), n.appendChild(i), n.appendChild(
|
|
781
|
+
}), n.appendChild(i), n.appendChild(s), t.replaceChild(n, e), !n.nextElementSibling) {
|
|
773
782
|
const a = document.createElement("p");
|
|
774
783
|
a.innerHTML = "<br>", n.after(a);
|
|
775
784
|
}
|
|
@@ -781,14 +790,14 @@ class K {
|
|
|
781
790
|
if (!t) return;
|
|
782
791
|
e.preventDefault();
|
|
783
792
|
const n = document.createElement("span");
|
|
784
|
-
for (const [
|
|
785
|
-
n.style.setProperty(
|
|
793
|
+
for (const [s, o] of Object.entries(this.pendingStyles))
|
|
794
|
+
n.style.setProperty(s, o);
|
|
786
795
|
n.textContent = t;
|
|
787
796
|
const i = this.selection.getRange();
|
|
788
797
|
if (i) {
|
|
789
798
|
i.deleteContents(), i.insertNode(n);
|
|
790
|
-
const
|
|
791
|
-
|
|
799
|
+
const s = document.createRange();
|
|
800
|
+
s.setStart(n.firstChild, t.length), s.setEnd(n.firstChild, t.length), this.selection.restoreSelection(s), this.pendingStyles = {}, this.editableElement.dispatchEvent(new Event("input", { bubbles: !0 }));
|
|
792
801
|
}
|
|
793
802
|
}
|
|
794
803
|
}), this.addEventListener(this.editableElement, "input", () => {
|
|
@@ -904,7 +913,7 @@ class K {
|
|
|
904
913
|
if (!n) return;
|
|
905
914
|
const i = document.createElement("table");
|
|
906
915
|
i.classList.add("te-table");
|
|
907
|
-
for (let
|
|
916
|
+
for (let o = 0; o < e; o++) {
|
|
908
917
|
const a = document.createElement("tr");
|
|
909
918
|
for (let r = 0; r < t; r++) {
|
|
910
919
|
const l = document.createElement("td");
|
|
@@ -913,10 +922,10 @@ class K {
|
|
|
913
922
|
i.appendChild(a);
|
|
914
923
|
}
|
|
915
924
|
n.deleteContents(), n.insertNode(i);
|
|
916
|
-
const
|
|
917
|
-
if (!
|
|
918
|
-
const
|
|
919
|
-
|
|
925
|
+
const s = i.nextElementSibling;
|
|
926
|
+
if (!s || s.tagName !== "P") {
|
|
927
|
+
const o = document.createElement("p");
|
|
928
|
+
o.innerHTML = "<br>", i.after(o), s && s.tagName === "BR" && s.remove();
|
|
920
929
|
}
|
|
921
930
|
this.editableElement.dispatchEvent(new Event("input", { bubbles: !0 }));
|
|
922
931
|
}
|
|
@@ -929,9 +938,9 @@ class K {
|
|
|
929
938
|
const t = document.createElement("tr");
|
|
930
939
|
t.style.borderBottom = "1px solid var(--te-border-color)";
|
|
931
940
|
const n = e.rows[0].cells.length;
|
|
932
|
-
for (let
|
|
933
|
-
const
|
|
934
|
-
|
|
941
|
+
for (let s = 0; s < n; s++) {
|
|
942
|
+
const o = document.createElement("td");
|
|
943
|
+
o.innerHTML = "<br>", t.appendChild(o);
|
|
935
944
|
}
|
|
936
945
|
const i = this.getSelectedTd();
|
|
937
946
|
i ? i.parentElement?.after(t) : e.appendChild(t), this.editableElement.dispatchEvent(new Event("input", { bubbles: !0 }));
|
|
@@ -944,10 +953,10 @@ class K {
|
|
|
944
953
|
if (e && e.parentElement) {
|
|
945
954
|
const t = e.parentElement, n = t.parentElement;
|
|
946
955
|
if (n.rows.length > 1) {
|
|
947
|
-
const i = t.rowIndex,
|
|
948
|
-
if (t.remove(),
|
|
956
|
+
const i = t.rowIndex, s = n.rows[i + 1] || n.rows[i - 1], o = e.cellIndex;
|
|
957
|
+
if (t.remove(), s && s.cells[o]) {
|
|
949
958
|
const a = document.createRange();
|
|
950
|
-
a.selectNodeContents(
|
|
959
|
+
a.selectNodeContents(s.cells[o]), a.collapse(!0), this.selection.restoreSelection(a);
|
|
951
960
|
}
|
|
952
961
|
this.editableElement.dispatchEvent(new Event("input", { bubbles: !0 }));
|
|
953
962
|
}
|
|
@@ -961,8 +970,8 @@ class K {
|
|
|
961
970
|
if (!e) return;
|
|
962
971
|
const t = this.getSelectedTd(), n = t ? t.cellIndex : -1;
|
|
963
972
|
for (let i = 0; i < e.rows.length; i++) {
|
|
964
|
-
const
|
|
965
|
-
|
|
973
|
+
const s = e.rows[i], o = document.createElement("td");
|
|
974
|
+
o.innerHTML = "<br>", n !== -1 ? s.cells[n].after(o) : s.appendChild(o);
|
|
966
975
|
}
|
|
967
976
|
this.editableElement.dispatchEvent(new Event("input", { bubbles: !0 }));
|
|
968
977
|
}
|
|
@@ -977,11 +986,11 @@ class K {
|
|
|
977
986
|
const n = e.cellIndex;
|
|
978
987
|
if (t.rows[0].cells.length > 1) {
|
|
979
988
|
const i = e.nextElementSibling || e.previousElementSibling;
|
|
980
|
-
for (let
|
|
981
|
-
t.rows[
|
|
989
|
+
for (let s = 0; s < t.rows.length; s++)
|
|
990
|
+
t.rows[s].cells[n].remove();
|
|
982
991
|
if (i) {
|
|
983
|
-
const
|
|
984
|
-
|
|
992
|
+
const s = document.createRange();
|
|
993
|
+
s.selectNodeContents(i), s.collapse(!0), this.selection.restoreSelection(s);
|
|
985
994
|
}
|
|
986
995
|
this.editableElement.dispatchEvent(new Event("input", { bubbles: !0 }));
|
|
987
996
|
}
|
|
@@ -1029,45 +1038,45 @@ class K {
|
|
|
1029
1038
|
return this.pendingStyles[e] = t, n;
|
|
1030
1039
|
if (["line-height"].includes(e))
|
|
1031
1040
|
return this.setBlockStyle(e, t, n);
|
|
1032
|
-
let
|
|
1033
|
-
|
|
1034
|
-
let
|
|
1035
|
-
if (
|
|
1036
|
-
|
|
1041
|
+
let s = n.commonAncestorContainer;
|
|
1042
|
+
s.nodeType === Node.TEXT_NODE && (s = s.parentElement);
|
|
1043
|
+
let o = null;
|
|
1044
|
+
if (s.tagName === "SPAN" && s.children.length === 0 && s.textContent === n.toString())
|
|
1045
|
+
s.style.setProperty(e, t), o = n.cloneRange();
|
|
1037
1046
|
else {
|
|
1038
1047
|
const a = document.createElement("span");
|
|
1039
1048
|
a.style.setProperty(e, t);
|
|
1040
1049
|
try {
|
|
1041
|
-
const r =
|
|
1050
|
+
const r = s.tagName === "SPAN" ? s : null, l = n.extractContents();
|
|
1042
1051
|
this.clearStyleRecursive(l, e), a.appendChild(l), n.insertNode(a), r && r.innerHTML === "" && r.remove();
|
|
1043
1052
|
const d = document.createRange();
|
|
1044
|
-
d.selectNodeContents(a),
|
|
1053
|
+
d.selectNodeContents(a), o = d;
|
|
1045
1054
|
const c = window.getSelection();
|
|
1046
1055
|
c && c.rangeCount > 0 && (c.removeAllRanges(), c.addRange(d));
|
|
1047
1056
|
} catch (r) {
|
|
1048
1057
|
console.warn("Failed to apply style:", r);
|
|
1049
1058
|
}
|
|
1050
1059
|
}
|
|
1051
|
-
return this.editableElement.dispatchEvent(new Event("input", { bubbles: !0 })),
|
|
1060
|
+
return this.editableElement.dispatchEvent(new Event("input", { bubbles: !0 })), o;
|
|
1052
1061
|
}
|
|
1053
1062
|
/**
|
|
1054
1063
|
* Applies a style to the block-level containers within the range.
|
|
1055
1064
|
*/
|
|
1056
1065
|
setBlockStyle(e, t, n) {
|
|
1057
|
-
const i = ["P", "H1", "H2", "H3", "H4", "H5", "H6", "LI", "TD", "TH", "DIV", "BLOCKQUOTE"],
|
|
1066
|
+
const i = ["P", "H1", "H2", "H3", "H4", "H5", "H6", "LI", "TD", "TH", "DIV", "BLOCKQUOTE"], s = /* @__PURE__ */ new Set();
|
|
1058
1067
|
if (Array.from(this.editableElement.querySelectorAll(i.join(","))).forEach((a) => {
|
|
1059
|
-
n.intersectsNode(a) &&
|
|
1060
|
-
}),
|
|
1068
|
+
n.intersectsNode(a) && s.add(a);
|
|
1069
|
+
}), s.size === 0) {
|
|
1061
1070
|
let a = n.commonAncestorContainer;
|
|
1062
1071
|
for (; a && a !== this.editableElement.parentElement; ) {
|
|
1063
1072
|
if (a.nodeType === Node.ELEMENT_NODE && i.includes(a.tagName)) {
|
|
1064
|
-
|
|
1073
|
+
s.add(a);
|
|
1065
1074
|
break;
|
|
1066
1075
|
}
|
|
1067
1076
|
a = a.parentNode;
|
|
1068
1077
|
}
|
|
1069
1078
|
}
|
|
1070
|
-
return
|
|
1079
|
+
return s.forEach((a) => {
|
|
1071
1080
|
a.style.setProperty(e, t);
|
|
1072
1081
|
}), this.editableElement.dispatchEvent(new Event("input", { bubbles: !0 })), n;
|
|
1073
1082
|
}
|
|
@@ -1084,19 +1093,19 @@ class K {
|
|
|
1084
1093
|
!/^https?:\/\//i.test(e) && !/^mailto:/i.test(e) && !e.startsWith("#") && (n ? e = "mailto:" + e : e = "https://" + e);
|
|
1085
1094
|
const i = window.getSelection();
|
|
1086
1095
|
if (i && i.rangeCount > 0) {
|
|
1087
|
-
const
|
|
1088
|
-
if (
|
|
1089
|
-
const
|
|
1090
|
-
|
|
1096
|
+
const s = i.getRangeAt(0);
|
|
1097
|
+
if (s.collapsed) {
|
|
1098
|
+
const o = document.createTextNode(e);
|
|
1099
|
+
s.insertNode(o);
|
|
1091
1100
|
const a = document.createRange();
|
|
1092
|
-
a.selectNodeContents(
|
|
1101
|
+
a.selectNodeContents(o), i.removeAllRanges(), i.addRange(a);
|
|
1093
1102
|
}
|
|
1094
1103
|
}
|
|
1095
1104
|
if (document.execCommand("createLink", !1, e), i && i.rangeCount > 0) {
|
|
1096
|
-
let
|
|
1097
|
-
|
|
1105
|
+
let o = i.getRangeAt(0).commonAncestorContainer;
|
|
1106
|
+
o.nodeType === Node.TEXT_NODE && (o = o.parentElement);
|
|
1098
1107
|
let a = null;
|
|
1099
|
-
|
|
1108
|
+
o.tagName === "A" ? a = o : a = o.querySelector("a"), a && (a.setAttribute("target", "_blank"), a.setAttribute("rel", "noopener noreferrer"));
|
|
1100
1109
|
}
|
|
1101
1110
|
this.editableElement.dispatchEvent(new Event("input", { bubbles: !0 }));
|
|
1102
1111
|
}
|
|
@@ -1107,19 +1116,19 @@ class K {
|
|
|
1107
1116
|
this.focus();
|
|
1108
1117
|
const i = this.selection.getRange();
|
|
1109
1118
|
if (!i) return null;
|
|
1110
|
-
const
|
|
1111
|
-
|
|
1112
|
-
const
|
|
1113
|
-
|
|
1119
|
+
const s = document.createElement("figure");
|
|
1120
|
+
s.classList.add("te-image-container"), s.setAttribute("contenteditable", "false"), n && s.classList.add("is-loading");
|
|
1121
|
+
const o = document.createElement("img");
|
|
1122
|
+
o.src = e, o.classList.add("te-image"), t && o.setAttribute("data-image-id", t);
|
|
1114
1123
|
const a = document.createElement("figcaption");
|
|
1115
1124
|
a.classList.add("te-image-caption"), a.setAttribute("contenteditable", "true"), a.setAttribute("data-placeholder", "Type caption..."), ["top-left", "top-right", "bottom-left", "bottom-right"].forEach((c) => {
|
|
1116
1125
|
const h = document.createElement("div");
|
|
1117
|
-
h.classList.add("te-image-resizer", `te-resizer-${c}`),
|
|
1118
|
-
}),
|
|
1126
|
+
h.classList.add("te-image-resizer", `te-resizer-${c}`), s.appendChild(h);
|
|
1127
|
+
}), s.appendChild(o), s.appendChild(a), i.deleteContents(), i.insertNode(s);
|
|
1119
1128
|
const l = document.createElement("p");
|
|
1120
|
-
l.innerHTML = "<br>",
|
|
1129
|
+
l.innerHTML = "<br>", s.after(l);
|
|
1121
1130
|
const d = document.createRange();
|
|
1122
|
-
return d.setStart(l, 0), d.setEnd(l, 0), this.selection.restoreSelection(d), this.editableElement.dispatchEvent(new Event("input", { bubbles: !0 })), this.save(),
|
|
1131
|
+
return d.setStart(l, 0), d.setEnd(l, 0), this.selection.restoreSelection(d), this.editableElement.dispatchEvent(new Event("input", { bubbles: !0 })), this.save(), s;
|
|
1123
1132
|
}
|
|
1124
1133
|
/**
|
|
1125
1134
|
* Returns the clean and optimized HTML content of the editor.
|
|
@@ -1135,21 +1144,22 @@ class K {
|
|
|
1135
1144
|
let n = null, i = null;
|
|
1136
1145
|
if (t && this.editableElement.contains(t.commonAncestorContainer)) {
|
|
1137
1146
|
n = document.createElement("span"), n.id = "te-selection-start", n.style.display = "none", i = document.createElement("span"), i.id = "te-selection-end", i.style.display = "none";
|
|
1138
|
-
const
|
|
1139
|
-
|
|
1147
|
+
const o = t.cloneRange();
|
|
1148
|
+
o.collapse(!0), o.insertNode(n);
|
|
1140
1149
|
const a = t.cloneRange();
|
|
1141
1150
|
a.collapse(!1), a.insertNode(i);
|
|
1142
1151
|
}
|
|
1143
|
-
const
|
|
1144
|
-
if (
|
|
1145
|
-
this.editableElement.innerHTML =
|
|
1146
|
-
const
|
|
1147
|
-
if (
|
|
1152
|
+
const s = this.normalizeHTML(this.editableElement.innerHTML);
|
|
1153
|
+
if (s !== e || n) {
|
|
1154
|
+
this.editableElement.innerHTML = s;
|
|
1155
|
+
const o = this.editableElement.querySelector("#te-selection-start"), a = this.editableElement.querySelector("#te-selection-end");
|
|
1156
|
+
if (o && a) {
|
|
1148
1157
|
const r = document.createRange();
|
|
1149
|
-
r.setStartAfter(
|
|
1158
|
+
r.setStartAfter(o), r.setEndBefore(a), this.selection.restoreSelection(r);
|
|
1150
1159
|
}
|
|
1151
1160
|
this.editableElement.querySelectorAll("#te-selection-start, #te-selection-end").forEach((r) => r.remove());
|
|
1152
1161
|
}
|
|
1162
|
+
this.checkPlaceholder();
|
|
1153
1163
|
}
|
|
1154
1164
|
normalizationContainer = null;
|
|
1155
1165
|
/**
|
|
@@ -1241,12 +1251,12 @@ class K {
|
|
|
1241
1251
|
a.replaceWith(r);
|
|
1242
1252
|
} else a.innerHTML.trim() === "" && a.remove();
|
|
1243
1253
|
});
|
|
1244
|
-
const
|
|
1245
|
-
|
|
1254
|
+
const o = Array.from(t.querySelectorAll("p"));
|
|
1255
|
+
o.forEach((a) => {
|
|
1246
1256
|
a.innerHTML.trim() === "" && t.childNodes.length > 1 && a !== t.lastElementChild && a.remove();
|
|
1247
1257
|
});
|
|
1248
|
-
for (let a =
|
|
1249
|
-
const r =
|
|
1258
|
+
for (let a = o.length - 1; a >= 0; a--) {
|
|
1259
|
+
const r = o[a], l = r.innerHTML.trim() === "" || r.innerHTML.trim() === "<br>", d = r === t.lastElementChild;
|
|
1250
1260
|
if (l && d && t.children.length > 1)
|
|
1251
1261
|
r.remove();
|
|
1252
1262
|
else
|
|
@@ -1259,23 +1269,23 @@ class K {
|
|
|
1259
1269
|
e.preventDefault();
|
|
1260
1270
|
let t = (e.clipboardData || window.clipboardData).getData("text/plain"), n = (e.clipboardData || window.clipboardData).getData("text/html");
|
|
1261
1271
|
if (e.clipboardData && e.clipboardData.items) {
|
|
1262
|
-
const
|
|
1263
|
-
for (let
|
|
1264
|
-
const a = e.clipboardData.items[
|
|
1272
|
+
const s = [];
|
|
1273
|
+
for (let o = 0; o < e.clipboardData.items.length; o++) {
|
|
1274
|
+
const a = e.clipboardData.items[o];
|
|
1265
1275
|
if (a.type.startsWith("image/")) {
|
|
1266
1276
|
const r = a.getAsFile();
|
|
1267
|
-
r &&
|
|
1277
|
+
r && s.push(r);
|
|
1268
1278
|
}
|
|
1269
1279
|
}
|
|
1270
|
-
if (
|
|
1271
|
-
this.handleFiles(
|
|
1280
|
+
if (s.length > 0) {
|
|
1281
|
+
this.handleFiles(s);
|
|
1272
1282
|
return;
|
|
1273
1283
|
}
|
|
1274
1284
|
}
|
|
1275
1285
|
const i = /<([a-z1-6]+)\b[^>]*>[\s\S]*<\/\1>/i.test(t) || /^\s*<[a-z1-6]+\b[^>]*>/i.test(t);
|
|
1276
1286
|
if (!n && t && i && (n = t.replace(/(\r\n|\n|\r)/gm, " ").replace(/>\s+</g, "><").trim()), n) {
|
|
1277
|
-
const
|
|
1278
|
-
this.execute("insertHTML",
|
|
1287
|
+
const s = this.sanitize(n);
|
|
1288
|
+
this.execute("insertHTML", s);
|
|
1279
1289
|
} else
|
|
1280
1290
|
this.execute("insertText", t);
|
|
1281
1291
|
}
|
|
@@ -1312,18 +1322,18 @@ class K {
|
|
|
1312
1322
|
continue;
|
|
1313
1323
|
}
|
|
1314
1324
|
this.options.onSaving && this.options.onSaving();
|
|
1315
|
-
const
|
|
1316
|
-
i = this.insertImage(
|
|
1317
|
-
const
|
|
1325
|
+
const s = URL.createObjectURL(n);
|
|
1326
|
+
i = this.insertImage(s, void 0, !0);
|
|
1327
|
+
const o = await f.compressImage(n, t), a = URL.createObjectURL(o);
|
|
1318
1328
|
if (i) {
|
|
1319
1329
|
const l = i.querySelector("img");
|
|
1320
1330
|
l && (l.src = a);
|
|
1321
1331
|
}
|
|
1322
|
-
if (
|
|
1332
|
+
if (o.size > t * 1024 * 1024) {
|
|
1323
1333
|
alert(`Image "${n.name}" exceeds the ${t}MB limit even after compression.`), i?.remove();
|
|
1324
1334
|
continue;
|
|
1325
1335
|
}
|
|
1326
|
-
const r = await f.uploadFile(
|
|
1336
|
+
const r = await f.uploadFile(o, this.options);
|
|
1327
1337
|
if (r)
|
|
1328
1338
|
if (i) {
|
|
1329
1339
|
const l = i.querySelector("img");
|
|
@@ -1339,10 +1349,10 @@ class K {
|
|
|
1339
1349
|
h && (h.src = c), i.classList.remove("is-loading");
|
|
1340
1350
|
} else
|
|
1341
1351
|
this.insertImage(c);
|
|
1342
|
-
}, l.readAsDataURL(
|
|
1352
|
+
}, l.readAsDataURL(o);
|
|
1343
1353
|
}
|
|
1344
|
-
} catch (
|
|
1345
|
-
console.error("Image handling failed",
|
|
1354
|
+
} catch (s) {
|
|
1355
|
+
console.error("Image handling failed", s), i?.remove();
|
|
1346
1356
|
} finally {
|
|
1347
1357
|
this.options.onSave && this.save();
|
|
1348
1358
|
}
|
|
@@ -1399,10 +1409,10 @@ class X {
|
|
|
1399
1409
|
return;
|
|
1400
1410
|
}
|
|
1401
1411
|
this.searchInput.value.length > 0 ? this.renderGridItems(e) : ["Smileys", "Symbols", "Hands", "Animals", "Food", "Travel", "Objects", "Activities"].forEach((i) => {
|
|
1402
|
-
const
|
|
1403
|
-
if (
|
|
1404
|
-
const
|
|
1405
|
-
|
|
1412
|
+
const s = e.filter((o) => o.category === i);
|
|
1413
|
+
if (s.length > 0) {
|
|
1414
|
+
const o = document.createElement("div");
|
|
1415
|
+
o.classList.add("te-emoji-category-title"), o.textContent = i, this.emojiGrid.appendChild(o), this.renderGridItems(s);
|
|
1406
1416
|
}
|
|
1407
1417
|
});
|
|
1408
1418
|
}
|
|
@@ -1435,16 +1445,16 @@ class X {
|
|
|
1435
1445
|
shadowMd: "--te-shadow-md",
|
|
1436
1446
|
shadowLg: "--te-shadow-lg"
|
|
1437
1447
|
};
|
|
1438
|
-
for (const [i,
|
|
1439
|
-
const
|
|
1440
|
-
|
|
1448
|
+
for (const [i, s] of Object.entries(n)) {
|
|
1449
|
+
const o = t[i];
|
|
1450
|
+
o && e.style.setProperty(s, o);
|
|
1441
1451
|
}
|
|
1442
1452
|
}
|
|
1443
1453
|
show(e) {
|
|
1444
1454
|
document.body.appendChild(this.container);
|
|
1445
1455
|
const t = e.getBoundingClientRect(), n = 280;
|
|
1446
|
-
let i = t.bottom + window.scrollY + 5,
|
|
1447
|
-
|
|
1456
|
+
let i = t.bottom + window.scrollY + 5, s = t.left + window.scrollX;
|
|
1457
|
+
s + n > window.innerWidth && (s = window.innerWidth - n - 10), this.container.style.top = `${i}px`, this.container.style.left = `${s}px`, this.searchInput.focus();
|
|
1448
1458
|
}
|
|
1449
1459
|
close() {
|
|
1450
1460
|
this.container.parentElement && (this.container.remove(), this.onClose());
|
|
@@ -1462,6 +1472,7 @@ class Y {
|
|
|
1462
1472
|
activeModal = null;
|
|
1463
1473
|
statusEl = null;
|
|
1464
1474
|
boundUpdateActiveStates;
|
|
1475
|
+
itemElements = /* @__PURE__ */ new Map();
|
|
1465
1476
|
constructor(e) {
|
|
1466
1477
|
this.editor = e, this.container = this.createToolbarElement(), this.boundUpdateActiveStates = this.updateActiveStates.bind(this), this.render();
|
|
1467
1478
|
}
|
|
@@ -1471,39 +1482,39 @@ class Y {
|
|
|
1471
1482
|
}
|
|
1472
1483
|
render() {
|
|
1473
1484
|
const e = this.editor.getOptions().toolbarItems, t = [];
|
|
1474
|
-
this.items.forEach((
|
|
1475
|
-
(
|
|
1485
|
+
this.items.forEach((s) => {
|
|
1486
|
+
(s.type === "divider" || s.id && (!e || e.includes(s.id))) && t.push(s);
|
|
1476
1487
|
});
|
|
1477
1488
|
const n = [];
|
|
1478
|
-
t.forEach((
|
|
1479
|
-
if (
|
|
1480
|
-
if (n.length === 0 || n[n.length - 1].type === "divider" || !t.slice(
|
|
1481
|
-
n.push(
|
|
1489
|
+
t.forEach((s, o) => {
|
|
1490
|
+
if (s.type === "divider") {
|
|
1491
|
+
if (n.length === 0 || n[n.length - 1].type === "divider" || !t.slice(o + 1).some((r) => r.type !== "divider")) return;
|
|
1492
|
+
n.push(s);
|
|
1482
1493
|
} else
|
|
1483
|
-
n.push(
|
|
1484
|
-
}), n.forEach((
|
|
1485
|
-
if (
|
|
1486
|
-
this.renderButton(
|
|
1487
|
-
else if (
|
|
1488
|
-
this.renderSelect(
|
|
1489
|
-
else if (
|
|
1490
|
-
this.renderInput(
|
|
1491
|
-
else if (
|
|
1492
|
-
this.renderColorPicker(
|
|
1493
|
-
else if (
|
|
1494
|
-
const
|
|
1495
|
-
|
|
1494
|
+
n.push(s);
|
|
1495
|
+
}), n.forEach((s) => {
|
|
1496
|
+
if (s.type === "button")
|
|
1497
|
+
this.renderButton(s);
|
|
1498
|
+
else if (s.type === "select")
|
|
1499
|
+
this.renderSelect(s);
|
|
1500
|
+
else if (s.type === "input")
|
|
1501
|
+
this.renderInput(s);
|
|
1502
|
+
else if (s.type === "color-picker")
|
|
1503
|
+
this.renderColorPicker(s);
|
|
1504
|
+
else if (s.type === "divider") {
|
|
1505
|
+
const o = document.createElement("div");
|
|
1506
|
+
o.classList.add("te-divider"), this.container.appendChild(o);
|
|
1496
1507
|
}
|
|
1497
1508
|
}), this.editor.getOptions().showStatus !== !1 && this.container.appendChild(this.statusEl), this.editor.el.addEventListener("keyup", this.boundUpdateActiveStates), this.editor.el.addEventListener("mouseup", this.boundUpdateActiveStates);
|
|
1498
1509
|
}
|
|
1499
1510
|
renderButton(e) {
|
|
1500
1511
|
const t = document.createElement("button");
|
|
1501
|
-
t.classList.add("te-button"), t.innerHTML = e.icon || "", t.title = e.title, t.addEventListener("mousedown", (n) => {
|
|
1512
|
+
t.classList.add("te-button"), t.innerHTML = e.icon || "", t.title = e.title, this.itemElements.set(e, t), t.addEventListener("mousedown", (n) => {
|
|
1502
1513
|
if (n.preventDefault(), e.command === "createLink" || e.command === "insertTable") {
|
|
1503
1514
|
const i = window.getSelection();
|
|
1504
1515
|
if (i && i.rangeCount > 0) {
|
|
1505
|
-
const
|
|
1506
|
-
this.editor.el.contains(
|
|
1516
|
+
const s = i.getRangeAt(0);
|
|
1517
|
+
this.editor.el.contains(s.commonAncestorContainer) && (this.savedRange = s.cloneRange());
|
|
1507
1518
|
}
|
|
1508
1519
|
}
|
|
1509
1520
|
if (e.command === "insertEmoji") {
|
|
@@ -1521,8 +1532,8 @@ class Y {
|
|
|
1521
1532
|
}
|
|
1522
1533
|
if (e.command === "insertImage") {
|
|
1523
1534
|
const i = document.createElement("input");
|
|
1524
|
-
i.type = "file", i.accept = "image/*", i.style.display = "none", i.addEventListener("change", (
|
|
1525
|
-
const a =
|
|
1535
|
+
i.type = "file", i.accept = "image/*", i.style.display = "none", i.addEventListener("change", (s) => {
|
|
1536
|
+
const a = s.target.files;
|
|
1526
1537
|
a && a.length > 0 && this.editor.handleFiles(Array.from(a)), document.body.removeChild(i);
|
|
1527
1538
|
}), document.body.appendChild(i), i.click();
|
|
1528
1539
|
return;
|
|
@@ -1546,8 +1557,8 @@ class Y {
|
|
|
1546
1557
|
[{ id: "url", label: "URL", type: "text", placeholder: "https://example.com" }],
|
|
1547
1558
|
(i) => {
|
|
1548
1559
|
if (this.savedRange) {
|
|
1549
|
-
const
|
|
1550
|
-
|
|
1560
|
+
const s = window.getSelection();
|
|
1561
|
+
s && (s.removeAllRanges(), s.addRange(this.savedRange));
|
|
1551
1562
|
}
|
|
1552
1563
|
this.editor.createLink(i.url), this.savedRange = null;
|
|
1553
1564
|
},
|
|
@@ -1571,8 +1582,8 @@ class Y {
|
|
|
1571
1582
|
const a = window.getSelection();
|
|
1572
1583
|
a && (a.removeAllRanges(), a.addRange(this.savedRange));
|
|
1573
1584
|
}
|
|
1574
|
-
let
|
|
1575
|
-
(isNaN(
|
|
1585
|
+
let s = parseInt(i.rows, 10), o = parseInt(i.cols, 10);
|
|
1586
|
+
(isNaN(s) || s < 1) && (s = 1), (isNaN(o) || o < 1) && (o = 1), this.editor.insertTable(s, o), this.savedRange = null;
|
|
1576
1587
|
},
|
|
1577
1588
|
() => {
|
|
1578
1589
|
this.activeModal = null, this.savedRange = null;
|
|
@@ -1589,26 +1600,26 @@ class Y {
|
|
|
1589
1600
|
const t = document.createElement("input");
|
|
1590
1601
|
t.type = "number", t.classList.add("te-input"), t.title = e.title, t.value = e.value || "", t.min = "1", t.max = "100";
|
|
1591
1602
|
const n = () => {
|
|
1592
|
-
const
|
|
1593
|
-
if (
|
|
1594
|
-
const
|
|
1595
|
-
this.editor.el.contains(
|
|
1603
|
+
const s = window.getSelection();
|
|
1604
|
+
if (s && s.rangeCount > 0) {
|
|
1605
|
+
const o = s.getRangeAt(0);
|
|
1606
|
+
this.editor.el.contains(o.commonAncestorContainer) && (this.savedRange = o.cloneRange());
|
|
1596
1607
|
}
|
|
1597
1608
|
};
|
|
1598
1609
|
t.addEventListener("mousedown", n), t.addEventListener("focus", n);
|
|
1599
1610
|
const i = () => {
|
|
1600
|
-
let
|
|
1601
|
-
if (!isNaN(
|
|
1611
|
+
let s = parseInt(t.value, 10);
|
|
1612
|
+
if (!isNaN(s) && (s = Math.max(1, Math.min(100, s)), t.value = s.toString(), e.command === "fontSize")) {
|
|
1602
1613
|
if (this.savedRange) {
|
|
1603
|
-
const
|
|
1604
|
-
|
|
1614
|
+
const o = this.editor.setStyle("font-size", `${s}px`, this.savedRange);
|
|
1615
|
+
o && (this.savedRange = o);
|
|
1605
1616
|
} else
|
|
1606
|
-
this.editor.setStyle("font-size", `${
|
|
1617
|
+
this.editor.setStyle("font-size", `${s}px`);
|
|
1607
1618
|
t.focus();
|
|
1608
1619
|
}
|
|
1609
1620
|
};
|
|
1610
|
-
t.addEventListener("input", i), t.addEventListener("keydown", (
|
|
1611
|
-
|
|
1621
|
+
t.addEventListener("input", i), t.addEventListener("keydown", (s) => {
|
|
1622
|
+
s.key === "Enter" && (i(), this.editor.focus());
|
|
1612
1623
|
}), this.container.appendChild(t);
|
|
1613
1624
|
}
|
|
1614
1625
|
renderSelect(e) {
|
|
@@ -1628,8 +1639,8 @@ class Y {
|
|
|
1628
1639
|
if (t.classList.add("te-color-picker-wrapper"), t.title = e.title, e.icon) {
|
|
1629
1640
|
const i = document.createElement("div");
|
|
1630
1641
|
i.classList.add("te-button", "te-color-icon"), i.innerHTML = e.icon;
|
|
1631
|
-
const
|
|
1632
|
-
|
|
1642
|
+
const s = document.createElement("div");
|
|
1643
|
+
s.classList.add("te-color-indicator"), s.style.backgroundColor = e.value || "#000000", i.appendChild(s), this.itemElements.set(e, i), t.appendChild(i);
|
|
1633
1644
|
}
|
|
1634
1645
|
const n = document.createElement("input");
|
|
1635
1646
|
n.type = "color", n.classList.add("te-color-picker-input"), e.icon || (n.classList.add("te-color-picker"), n.title = e.title), n.value = e.value || "#000000", n.addEventListener("mousedown", () => {
|
|
@@ -1654,14 +1665,9 @@ class Y {
|
|
|
1654
1665
|
return this.container;
|
|
1655
1666
|
}
|
|
1656
1667
|
updateActiveStates() {
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
if (n.type === "button") {
|
|
1661
|
-
const i = e[t++];
|
|
1662
|
-
if (!i) return;
|
|
1663
|
-
n.command && document.queryCommandState(n.command) ? i.classList.add("active") : i.classList.remove("active");
|
|
1664
|
-
}
|
|
1668
|
+
this.items.forEach((e) => {
|
|
1669
|
+
const t = this.itemElements.get(e);
|
|
1670
|
+
t && e.type === "button" && (e.command && document.queryCommandState(e.command) ? t.classList.add("active") : t.classList.remove("active"));
|
|
1665
1671
|
});
|
|
1666
1672
|
}
|
|
1667
1673
|
updateStatus(e, t = !1) {
|
|
@@ -1686,7 +1692,7 @@ class Z extends K {
|
|
|
1686
1692
|
this.toolbar?.updateStatus("Auto saving...", !0), t.onSaving && t.onSaving();
|
|
1687
1693
|
},
|
|
1688
1694
|
onSave: (i) => {
|
|
1689
|
-
const
|
|
1695
|
+
const s = (/* @__PURE__ */ new Date()).toLocaleString([], {
|
|
1690
1696
|
year: "numeric",
|
|
1691
1697
|
month: "short",
|
|
1692
1698
|
day: "numeric",
|
|
@@ -1694,7 +1700,7 @@ class Z extends K {
|
|
|
1694
1700
|
minute: "2-digit",
|
|
1695
1701
|
hour12: !0
|
|
1696
1702
|
});
|
|
1697
|
-
this.toolbar?.updateStatus(`Saved at ${
|
|
1703
|
+
this.toolbar?.updateStatus(`Saved at ${s}`, !1), t.onSave && t.onSave(i);
|
|
1698
1704
|
}
|
|
1699
1705
|
};
|
|
1700
1706
|
if (super(e, n), typeof document > "u" || !e) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
.te-container,.te-emoji-picker,.te-modal,.te-floating-toolbar{--te-primary-color: #6366f1;--te-primary-hover: #4f46e5;--te-bg-app: #f8fafc;--te-bg-editor: #ffffff;--te-toolbar-bg: #ffffff;--te-border-color: #e2e8f0;--te-border-focus: #cbd5e1;--te-text-main: #1e293b;--te-text-muted: #64748b;--te-placeholder: #94a3b8;--te-btn-hover: #f1f5f9;--te-btn-active: #e2e8f0;--te-radius-lg: 12px;--te-radius-md: 8px;--te-radius-sm: 6px;--te-shadow-sm: 0 1px 2px 0 rgb(0 0 0 / .05);--te-shadow-md: 0 4px 6px -1px rgb(0 0 0 / .1), 0 2px 4px -2px rgb(0 0 0 / .1);--te-shadow-lg: 0 10px 15px -3px rgb(0 0 0 / .1), 0 4px 6px -4px rgb(0 0 0 / .1);--te-transition: all .2s cubic-bezier(.4, 0, .2, 1)}.te-container.te-dark,.te-emoji-picker.te-dark,.te-modal.te-dark,.te-floating-toolbar.te-dark{--te-primary-color: #818cf8 !important;--te-primary-hover: #6366f1 !important;--te-bg-app: #0f172a !important;--te-bg-editor: #1e293b !important;--te-toolbar-bg: #1e293b !important;--te-border-color: #334155 !important;--te-border-focus: #475569 !important;--te-text-main: #f8fafc !important;--te-text-muted: #94a3b8 !important;--te-placeholder: #64748b !important;--te-btn-hover: #334155 !important;--te-btn-active: #475569 !important;--te-shadow-sm: 0 1px 2px 0 rgb(0 0 0 / .3) !important;--te-shadow-md: 0 4px 6px -1px rgb(0 0 0 / .5), 0 2px 4px -2px rgb(0 0 0 / .5) !important;--te-shadow-lg: 0 10px 15px -3px rgb(0 0 0 / .5), 0 4px 6px -4px rgb(0 0 0 / .5) !important}.te-container,.te-container *,.te-emoji-picker,.te-emoji-picker *,.te-modal,.te-modal *,.te-floating-toolbar,.te-floating-toolbar *{box-sizing:border-box}.te-container{display:flex;flex-direction:column;height:500px;border:1px solid var(--te-border-color);border-radius:var(--te-radius-lg);background:var(--te-bg-editor);box-shadow:var(--te-shadow-sm);overflow:hidden;font-family:Inter,-apple-system,system-ui,sans-serif;color:var(--te-text-main)!important;transition:var(--te-transition);max-width:100%;position:relative}.te-container:focus-within{border-color:var(--te-primary-color);box-shadow:0 0 0 4px #6366f11a,var(--te-shadow-md)}.te-toolbar{display:flex;flex-wrap:wrap;gap:6px;padding:10px 12px;border-bottom:1px solid var(--te-border-color);background:var(--te-toolbar-bg);align-items:center;-webkit-user-select:none;user-select:none;position:sticky;top:0;z-index:10}.te-divider{width:1px;height:20px;background-color:var(--te-border-color);margin:0 6px}.te-button,.te-select,.te-input{display:flex;align-items:center;justify-content:center;height:32px;border:1px solid transparent;background:transparent;border-radius:var(--te-radius-sm);cursor:pointer;color:var(--te-text-muted);font-size:13px;font-weight:500;transition:var(--te-transition);box-sizing:border-box}.te-button{width:32px;padding:0}.te-button svg{width:16px;height:16px;stroke:currentColor;stroke-width:2.2;fill:none}.te-select{padding:0 24px 0 8px;min-width:120px;appearance:none;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 24 24' stroke='%2364748b'%3E%3Cpath stroke-linecap='round' stroke-linejoin='round' stroke-width='2.5' d='M19 9l-7 7-7-7'%3E%3C/path%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right 6px center;background-size:12px;border:1px solid var(--te-border-color);background-color:var(--te-bg-editor)!important;color:var(--te-text-main)!important}.te-input{width:56px;padding:0 4px;text-align:center;cursor:text;border:1px solid var(--te-border-color);background-color:var(--te-bg-editor)!important;color:var(--te-text-main)!important}.te-color-picker{width:32px;height:32px;padding:4px;border:1px solid var(--te-border-color);border-radius:var(--te-radius-sm);background:var(--te-bg-editor);cursor:pointer;box-sizing:border-box}.te-color-picker:hover{border-color:var(--te-border-focus)}.te-color-picker-wrapper{position:relative;display:inline-flex;width:32px;height:32px;border-radius:var(--te-radius-sm);transition:var(--te-transition)}.te-color-picker-wrapper:hover{background:var(--te-btn-hover)}.te-color-picker-input{position:absolute;top:0;left:0;width:100%;height:100%;opacity:0;cursor:pointer;z-index:2}.te-color-icon{position:relative;width:100%;height:100%;display:flex;align-items:center;justify-content:center;z-index:1}.te-color-indicator{position:absolute;bottom:4px;left:6px;right:6px;height:3px;border-radius:2px;box-shadow:0 1px 1px var(--te-shadow-sm)}.te-emoji-picker{position:absolute;width:280px;height:320px;background:var(--te-bg-editor);border:1px solid var(--te-border-color);border-radius:var(--te-radius-md);box-shadow:var(--te-shadow-lg);display:flex;flex-direction:column;z-index:1000;animation:te-fade-in .2s ease-out}@keyframes te-fade-in{0%{opacity:0;transform:translateY(-10px)}to{opacity:1;transform:translateY(0)}}.te-emoji-header{padding:12px;border-bottom:1px solid var(--te-border-color)}.te-emoji-search{width:100%;padding:8px 12px;border:1px solid var(--te-border-color);border-radius:var(--te-radius-sm);background-color:var(--te-bg-editor)!important;color:var(--te-text-main)!important;font-size:13px;outline:none;transition:var(--te-transition)}.te-emoji-search:focus{border-color:var(--te-primary-color);box-shadow:0 0 0 2px #6366f11a}.te-emoji-body{flex:1;overflow-y:auto;overflow-x:hidden;padding:8px}.te-emoji-grid{display:grid;grid-template-columns:repeat(7,1fr);gap:4px}.te-emoji-category-title{grid-column:span 7;padding:8px 4px 4px;font-size:11px;font-weight:600;color:var(--te-text-muted);text-transform:uppercase;letter-spacing:.05em}.te-emoji-item{width:32px;height:32px;display:flex;align-items:center;justify-content:center;font-size:20px;border:none;background:transparent;cursor:pointer;border-radius:var(--te-radius-sm);transition:var(--te-transition)}.te-emoji-item:hover{background:var(--te-btn-hover);transform:scale(1.1)}.te-emoji-empty{grid-column:span 7;text-align:center;padding:20px;color:var(--te-text-muted);font-size:13px}.te-button:hover{background:var(--te-btn-hover);color:var(--te-text-main)!important}.te-select:hover,.te-input:hover{border-color:var(--te-border-focus)}.te-button.active{background:var(--te-btn-active);color:var(--te-primary-color);border-color:#6366f133}.te-select:focus,.te-input:focus{border-color:var(--te-primary-color);box-shadow:0 0 0 2px #6366f11a;outline:none;background:var(--te-bg-editor);color:var(--te-text-main)!important}.te-content{flex:1;overflow-y:auto;min-height:240px;padding:24px;line-height:1.25;outline:none;font-size:16px;position:relative}.te-content p{margin:0 0 1.25em}.te-content h1,.te-content h2,.te-content h3,.te-content h4,.te-content h5,.te-content h6{color:var(--te-text-main)!important;font-weight:700;margin:1rem 0 .5rem;line-height:1.1}.te-content h1:first-child,.te-content p:first-child{margin-top:0}.te-content h1{font-size:2.25em}.te-content h2{font-size:1.875em}.te-content h3{font-size:1.5em}.te-content h4{font-size:1.25em}.te-content[data-placeholder].is-empty:before{content:attr(data-placeholder);color:var(--te-placeholder);pointer-events:none;position:absolute}.te-image-container{position:relative;display:inline-block;margin:1.5rem 0;max-width:100%;border-radius:var(--te-radius-lg);overflow:visible;transition:box-shadow var(--te-transition-fast);line-height:0}.te-image-container:hover{box-shadow:0 0 0 2px var(--te-primary-color)}.te-image-container.active{box-shadow:0 0 0 2px var(--te-primary-color),var(--te-shadow-lg)}.te-image{display:block;max-width:100%;height:auto;-webkit-user-select:none;user-select:none}.te-image-caption{font-size:.875rem;color:var(--te-text-muted);text-align:center;padding:.75rem;background:var(--te-bg-app);line-height:normal;border-bottom-left-radius:var(--te-radius-lg);border-bottom-right-radius:var(--te-radius-lg)}.te-image-caption:empty:before{content:attr(data-placeholder);color:var(--te-placeholder)}.te-image-resizer{position:absolute;width:10px;height:10px;background:var(--te-primary-color);border:1px solid var(--te-bg-editor);z-index:10;display:none}.te-image-container:hover .te-image-resizer,.te-image-container.active .te-image-resizer{display:block}.te-resizer-top-left{top:-5px;left:-5px;cursor:nwse-resize}.te-resizer-top-right{top:-5px;right:-5px;cursor:nesw-resize}.te-resizer-bottom-left{bottom:-5px;left:-5px;cursor:nesw-resize}.te-resizer-bottom-right{bottom:-5px;right:-5px;cursor:nwse-resize}.te-content.dragover{background:var(--te-btn-hover);outline:2px dashed var(--te-primary-color);outline-offset:-4px}.te-image-container.is-loading{position:relative;overflow:hidden;background:#f1f5f9;min-width:200px;min-height:150px}.te-image-container.is-loading .te-image{opacity:.3;filter:blur(4px);transition:opacity .5s ease,filter .5s ease}.te-image-container.is-loading:after{content:"";position:absolute;top:0;left:0;width:100%;height:100%;background:linear-gradient(90deg,#fff0 0,#fff6,#fff0);animation:te-skeleton-pulse 1.5s infinite}@keyframes te-skeleton-pulse{0%{transform:translate(-100%)}to{transform:translate(100%)}}.te-dark .te-image-container.is-loading{background:#334155}.te-table{width:100%;border-collapse:collapse;margin:1.5rem 0;border:1px solid var(--te-border-color);border-radius:var(--te-radius-md);table-layout:fixed}.te-table td,.te-table th{border:1px solid var(--te-border-color);padding:12px;min-height:44px;vertical-align:top;position:relative;transition:background-color .2s ease;color:var(--te-text-main)}.te-table tr{border-bottom:1px solid var(--te-border-color)}.te-table tr:last-child{border-bottom:none}.te-table td:hover{background-color:var(--te-btn-hover)}.te-table td:focus-within{background-color:var(--te-btn-active);outline:none}.te-dark .te-table,.te-dark .te-table td,.te-dark .te-table th{border-color:#334155}.te-dark .te-table td:hover{background-color:#1e293b}.te-toolbar-loader{width:12px;height:12px;border:1.5px solid var(--te-primary-color);border-bottom-color:transparent;border-radius:50%;display:inline-block;animation:te-spin 1s linear infinite}@keyframes te-spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.te-toolbar-status{display:flex;align-items:center;gap:8px;transition:opacity .3s ease}.te-modal{position:absolute;width:280px;background:#fffc;backdrop-filter:blur(12px) saturate(180%);-webkit-backdrop-filter:blur(12px) saturate(180%);border:1px solid rgba(226,232,240,.7);border-radius:var(--te-radius-lg);box-shadow:0 10px 15px -3px #0000001a,0 4px 6px -4px #0000001a,0 0 0 1px #0000000d;display:flex;flex-direction:column;z-index:1000;animation:te-fade-in .25s cubic-bezier(.4,0,.2,1);padding:20px}.te-dark .te-modal{background:#1e293bcc;border-color:#334155b3;box-shadow:0 20px 25px -5px #0000004d,0 8px 10px -6px #0000004d,0 0 0 1px #ffffff0d}.te-modal-header{font-size:16px;font-weight:700;color:var(--te-text-main);margin-bottom:20px;letter-spacing:-.01em}.te-modal-field{margin-bottom:16px}.te-modal-field label{display:block;font-size:11px;font-weight:700;color:var(--te-text-muted);text-transform:uppercase;margin-bottom:6px;letter-spacing:.05em}.te-modal-input{width:100%;padding:10px 12px;border:1px solid var(--te-border-color);border-radius:var(--te-radius-md);background:var(--te-bg-editor);color:var(--te-text-main);font-size:14px;outline:none;transition:var(--te-transition)}.te-modal-input:focus{border-color:var(--te-primary-color);box-shadow:0 0 0 3px #6366f126;background:var(--te-bg-editor)}.te-modal-footer{display:flex;justify-content:flex-end;gap:12px;margin-top:8px}.te-modal-btn{padding:8px 16px;font-size:13px;font-weight:600;border-radius:var(--te-radius-md);cursor:pointer;transition:var(--te-transition);border:1px solid transparent;display:inline-flex;align-items:center;justify-content:center}.te-modal-btn-cancel{background:transparent;color:var(--te-text-muted);border:1px solid var(--te-border-color)}.te-modal-btn-cancel:hover{background:var(--te-btn-hover);color:var(--te-text-main);border-color:var(--te-border-focus)}.te-modal-btn-confirm{background:var(--te-primary-color);color:#fff;box-shadow:0 4px 6px -1px #6366f133}.te-modal-btn-confirm:hover{background:var(--te-primary-hover);transform:translateY(-1px);box-shadow:0 6px 8px -1px #6366f14d}.te-modal-btn-confirm:active{transform:translateY(0)}.te-floating-toolbar{background:var(--te-bg-editor);border:1px solid var(--te-border-color);border-radius:var(--te-radius-md);padding:4px;box-shadow:var(--te-shadow-lg);display:flex;gap:2px;pointer-events:auto;opacity:0;transform:translateY(10px);transition:opacity .2s ease,transform .2s ease,background .3s ease}.te-floating-toolbar.te-floating-visible{opacity:1;transform:translateY(0)}.te-floating-btn{background:transparent;border:none;cursor:pointer;padding:6px;border-radius:var(--te-radius-sm);color:var(--te-text-muted);display:flex;align-items:center;justify-content:center;transition:all .2s ease}.te-floating-btn:hover{background:var(--te-btn-hover);color:var(--te-text-main)}.te-floating-btn svg{width:18px;height:18px;stroke:currentColor}.te-loader-overlay{position:absolute;inset:0;background:#f1f5f9e6;backdrop-filter:blur(12px) saturate(200%);-webkit-backdrop-filter:blur(12px) saturate(200%);display:flex;flex-direction:column;align-items:center;justify-content:center;z-index:1000;transition:opacity .4s cubic-bezier(.4,0,.2,1),visibility .4s;border-radius:var(--te-radius-lg)}.te-dark .te-loader-overlay{background:#0f172ae6}.te-loader-overlay.hidden{opacity:0;visibility:hidden;pointer-events:none}.te-loader-spinner{width:48px;height:48px;border:4px solid var(--te-border-color);border-top-color:var(--te-primary-color);border-radius:50%;animation:te-spin 1s cubic-bezier(.4,0,.2,1) infinite;margin-bottom:24px;filter:drop-shadow(0 0 10px rgba(99,102,241,.2))}.te-loader-shimmer{width:140px;height:4px;background:var(--te-border-color);border-radius:2px;overflow:hidden;position:relative}.te-loader-shimmer:after{content:"";position:absolute;top:0;left:0;width:100%;height:100%;background:linear-gradient(90deg,#6366f100 0,#6366f166,#6366f100);animation:te-skeleton-pulse 1.5s infinite}.te-loader-text{font-size:13px;font-weight:600;color:var(--te-text-muted);letter-spacing:.02em;margin-top:12px}
|
|
1
|
+
.te-container,.te-emoji-picker,.te-modal,.te-floating-toolbar{--te-primary-color: #6366f1;--te-primary-hover: #4f46e5;--te-bg-app: #f8fafc;--te-bg-editor: #ffffff;--te-toolbar-bg: #ffffff;--te-border-color: #e2e8f0;--te-border-focus: #cbd5e1;--te-text-main: #1e293b;--te-text-muted: #64748b;--te-placeholder: #94a3b8;--te-btn-hover: #f1f5f9;--te-btn-active: #e2e8f0;--te-radius-lg: 12px;--te-radius-md: 8px;--te-radius-sm: 6px;--te-shadow-sm: 0 1px 2px 0 rgb(0 0 0 / .05);--te-shadow-md: 0 4px 6px -1px rgb(0 0 0 / .1), 0 2px 4px -2px rgb(0 0 0 / .1);--te-shadow-lg: 0 10px 15px -3px rgb(0 0 0 / .1), 0 4px 6px -4px rgb(0 0 0 / .1);--te-transition: all .2s cubic-bezier(.4, 0, .2, 1)}.te-container.te-dark,.te-emoji-picker.te-dark,.te-modal.te-dark,.te-floating-toolbar.te-dark{--te-primary-color: #818cf8 !important;--te-primary-hover: #6366f1 !important;--te-bg-app: #0f172a !important;--te-bg-editor: #1e293b !important;--te-toolbar-bg: #1e293b !important;--te-border-color: #334155 !important;--te-border-focus: #475569 !important;--te-text-main: #f8fafc !important;--te-text-muted: #94a3b8 !important;--te-placeholder: #64748b !important;--te-btn-hover: #334155 !important;--te-btn-active: #475569 !important;--te-shadow-sm: 0 1px 2px 0 rgb(0 0 0 / .3) !important;--te-shadow-md: 0 4px 6px -1px rgb(0 0 0 / .5), 0 2px 4px -2px rgb(0 0 0 / .5) !important;--te-shadow-lg: 0 10px 15px -3px rgb(0 0 0 / .5), 0 4px 6px -4px rgb(0 0 0 / .5) !important}.te-container,.te-container *,.te-emoji-picker,.te-emoji-picker *,.te-modal,.te-modal *,.te-floating-toolbar,.te-floating-toolbar *{box-sizing:border-box}.te-container{display:flex;flex-direction:column;height:500px;border:1px solid var(--te-border-color);border-radius:var(--te-radius-lg);background:var(--te-bg-editor);box-shadow:var(--te-shadow-sm);overflow:hidden;font-family:Inter,-apple-system,system-ui,sans-serif;color:var(--te-text-main)!important;transition:var(--te-transition);max-width:100%;position:relative}.te-container:focus-within{border-color:var(--te-primary-color);box-shadow:0 0 0 4px #6366f11a,var(--te-shadow-md)}.te-toolbar{display:flex;flex-wrap:wrap;gap:6px;padding:10px 12px;border-bottom:1px solid var(--te-border-color);background:var(--te-toolbar-bg);align-items:center;-webkit-user-select:none;user-select:none;position:sticky;top:0;z-index:10}.te-divider{width:1px;height:20px;background-color:var(--te-border-color);margin:0 6px}.te-button,.te-select,.te-input{display:flex;align-items:center;justify-content:center;height:32px;border:1px solid transparent;background:transparent;border-radius:var(--te-radius-sm);cursor:pointer;color:var(--te-text-muted);font-size:13px;font-weight:500;transition:var(--te-transition);box-sizing:border-box}.te-button{width:32px;padding:0}.te-button svg{width:16px;height:16px;stroke:currentColor;stroke-width:2.2;fill:none}.te-select{padding:0 24px 0 8px;min-width:120px;appearance:none;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 24 24' stroke='%2364748b'%3E%3Cpath stroke-linecap='round' stroke-linejoin='round' stroke-width='2.5' d='M19 9l-7 7-7-7'%3E%3C/path%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right 6px center;background-size:12px;border:1px solid var(--te-border-color);background-color:var(--te-bg-editor)!important;color:var(--te-text-main)!important}.te-input{width:56px;padding:0 4px;text-align:center;cursor:text;border:1px solid var(--te-border-color);background-color:var(--te-bg-editor)!important;color:var(--te-text-main)!important}.te-color-picker{width:32px;height:32px;padding:4px;border:1px solid var(--te-border-color);border-radius:var(--te-radius-sm);background:var(--te-bg-editor);cursor:pointer;box-sizing:border-box}.te-color-picker:hover{border-color:var(--te-border-focus)}.te-color-picker-wrapper{position:relative;display:inline-flex;width:32px;height:32px;border-radius:var(--te-radius-sm);transition:var(--te-transition)}.te-color-picker-wrapper:hover{background:var(--te-btn-hover)}.te-color-picker-input{position:absolute;top:0;left:0;width:100%;height:100%;opacity:0;cursor:pointer;z-index:2}.te-color-icon{position:relative;width:100%;height:100%;display:flex;align-items:center;justify-content:center;z-index:1}.te-color-indicator{position:absolute;bottom:4px;left:6px;right:6px;height:3px;border-radius:2px;box-shadow:0 1px 1px var(--te-shadow-sm)}.te-emoji-picker{position:absolute;width:280px;height:320px;background:var(--te-bg-editor);border:1px solid var(--te-border-color);border-radius:var(--te-radius-md);box-shadow:var(--te-shadow-lg);display:flex;flex-direction:column;z-index:1000;animation:te-fade-in .2s ease-out}@keyframes te-fade-in{0%{opacity:0;transform:translateY(-10px)}to{opacity:1;transform:translateY(0)}}.te-emoji-header{padding:12px;border-bottom:1px solid var(--te-border-color)}.te-emoji-search{width:100%;padding:8px 12px;border:1px solid var(--te-border-color);border-radius:var(--te-radius-sm);background-color:var(--te-bg-editor)!important;color:var(--te-text-main)!important;font-size:13px;outline:none;transition:var(--te-transition)}.te-emoji-search:focus{border-color:var(--te-primary-color);box-shadow:0 0 0 2px #6366f11a}.te-emoji-body{flex:1;overflow-y:auto;overflow-x:hidden;padding:8px}.te-emoji-grid{display:grid;grid-template-columns:repeat(7,1fr);gap:4px}.te-emoji-category-title{grid-column:span 7;padding:8px 4px 4px;font-size:11px;font-weight:600;color:var(--te-text-muted);text-transform:uppercase;letter-spacing:.05em}.te-emoji-item{width:32px;height:32px;display:flex;align-items:center;justify-content:center;font-size:20px;border:none;background:transparent;cursor:pointer;border-radius:var(--te-radius-sm);transition:var(--te-transition)}.te-emoji-item:hover{background:var(--te-btn-hover);transform:scale(1.1)}.te-emoji-empty{grid-column:span 7;text-align:center;padding:20px;color:var(--te-text-muted);font-size:13px}.te-button:hover{background:var(--te-btn-hover);color:var(--te-text-main)!important}.te-select:hover,.te-input:hover{border-color:var(--te-border-focus)}.te-button.active{background:var(--te-btn-active);color:var(--te-primary-color);border-color:#6366f133}.te-select:focus,.te-input:focus{border-color:var(--te-primary-color);box-shadow:0 0 0 2px #6366f11a;outline:none;background:var(--te-bg-editor);color:var(--te-text-main)!important}.te-content{flex:1;overflow-y:auto;min-height:240px;padding:24px;line-height:1.25;outline:none;font-size:16px;position:relative}.te-content p{margin:0 0 1.25em}.te-content h1,.te-content h2,.te-content h3,.te-content h4,.te-content h5,.te-content h6{color:var(--te-text-main)!important;font-weight:700;margin:1rem 0 .5rem;line-height:1.1}.te-content h1:first-child,.te-content p:first-child{margin-top:0}.te-content h1{font-size:2.25em}.te-content h2{font-size:1.875em}.te-content h3{font-size:1.5em}.te-content h4{font-size:1.25em}.te-content[data-placeholder].is-empty:before{content:attr(data-placeholder);color:var(--te-placeholder);pointer-events:none;position:absolute;left:24px;right:24px;text-align:inherit;white-space:pre-wrap;overflow:hidden}.te-image-container{position:relative;display:inline-block;margin:1.5rem 0;max-width:100%;border-radius:var(--te-radius-lg);overflow:visible;transition:box-shadow var(--te-transition-fast);line-height:0}.te-image-container:hover{box-shadow:0 0 0 2px var(--te-primary-color)}.te-image-container.active{box-shadow:0 0 0 2px var(--te-primary-color),var(--te-shadow-lg)}.te-image{display:block;max-width:100%;height:auto;-webkit-user-select:none;user-select:none}.te-image-caption{font-size:.875rem;color:var(--te-text-muted);text-align:center;padding:.75rem;background:var(--te-bg-app);line-height:normal;border-bottom-left-radius:var(--te-radius-lg);border-bottom-right-radius:var(--te-radius-lg)}.te-image-caption:empty:before{content:attr(data-placeholder);color:var(--te-placeholder)}.te-image-resizer{position:absolute;width:10px;height:10px;background:var(--te-primary-color);border:1px solid var(--te-bg-editor);z-index:10;display:none}.te-image-container:hover .te-image-resizer,.te-image-container.active .te-image-resizer{display:block}.te-resizer-top-left{top:-5px;left:-5px;cursor:nwse-resize}.te-resizer-top-right{top:-5px;right:-5px;cursor:nesw-resize}.te-resizer-bottom-left{bottom:-5px;left:-5px;cursor:nesw-resize}.te-resizer-bottom-right{bottom:-5px;right:-5px;cursor:nwse-resize}.te-content.dragover{background:var(--te-btn-hover);outline:2px dashed var(--te-primary-color);outline-offset:-4px}.te-image-container.is-loading{position:relative;overflow:hidden;background:#f1f5f9;min-width:200px;min-height:150px}.te-image-container.is-loading .te-image{opacity:.3;filter:blur(4px);transition:opacity .5s ease,filter .5s ease}.te-image-container.is-loading:after{content:"";position:absolute;top:0;left:0;width:100%;height:100%;background:linear-gradient(90deg,#fff0 0,#fff6,#fff0);animation:te-skeleton-pulse 1.5s infinite}@keyframes te-skeleton-pulse{0%{transform:translate(-100%)}to{transform:translate(100%)}}.te-dark .te-image-container.is-loading{background:#334155}.te-table{width:100%;border-collapse:collapse;margin:1.5rem 0;border:1px solid var(--te-border-color);border-radius:var(--te-radius-md);table-layout:fixed}.te-table td,.te-table th{border:1px solid var(--te-border-color);padding:12px;min-height:44px;vertical-align:top;position:relative;transition:background-color .2s ease;color:var(--te-text-main)}.te-table tr{border-bottom:1px solid var(--te-border-color)}.te-table tr:last-child{border-bottom:none}.te-table td:hover{background-color:var(--te-btn-hover)}.te-table td:focus-within{background-color:var(--te-btn-active);outline:none}.te-dark .te-table,.te-dark .te-table td,.te-dark .te-table th{border-color:#334155}.te-dark .te-table td:hover{background-color:#1e293b}.te-toolbar-loader{width:12px;height:12px;border:1.5px solid var(--te-primary-color);border-bottom-color:transparent;border-radius:50%;display:inline-block;animation:te-spin 1s linear infinite}@keyframes te-spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.te-toolbar-status{display:flex;align-items:center;gap:8px;transition:opacity .3s ease}.te-modal{position:absolute;width:280px;background:#fffc;backdrop-filter:blur(12px) saturate(180%);-webkit-backdrop-filter:blur(12px) saturate(180%);border:1px solid rgba(226,232,240,.7);border-radius:var(--te-radius-lg);box-shadow:0 10px 15px -3px #0000001a,0 4px 6px -4px #0000001a,0 0 0 1px #0000000d;display:flex;flex-direction:column;z-index:1000;animation:te-fade-in .25s cubic-bezier(.4,0,.2,1);padding:20px}.te-dark .te-modal{background:#1e293bcc;border-color:#334155b3;box-shadow:0 20px 25px -5px #0000004d,0 8px 10px -6px #0000004d,0 0 0 1px #ffffff0d}.te-modal-header{font-size:16px;font-weight:700;color:var(--te-text-main);margin-bottom:20px;letter-spacing:-.01em}.te-modal-field{margin-bottom:16px}.te-modal-field label{display:block;font-size:11px;font-weight:700;color:var(--te-text-muted);text-transform:uppercase;margin-bottom:6px;letter-spacing:.05em}.te-modal-input{width:100%;padding:10px 12px;border:1px solid var(--te-border-color);border-radius:var(--te-radius-md);background:var(--te-bg-editor);color:var(--te-text-main);font-size:14px;outline:none;transition:var(--te-transition)}.te-modal-input:focus{border-color:var(--te-primary-color);box-shadow:0 0 0 3px #6366f126;background:var(--te-bg-editor)}.te-modal-footer{display:flex;justify-content:flex-end;gap:12px;margin-top:8px}.te-modal-btn{padding:8px 16px;font-size:13px;font-weight:600;border-radius:var(--te-radius-md);cursor:pointer;transition:var(--te-transition);border:1px solid transparent;display:inline-flex;align-items:center;justify-content:center}.te-modal-btn-cancel{background:transparent;color:var(--te-text-muted);border:1px solid var(--te-border-color)}.te-modal-btn-cancel:hover{background:var(--te-btn-hover);color:var(--te-text-main);border-color:var(--te-border-focus)}.te-modal-btn-confirm{background:var(--te-primary-color);color:#fff;box-shadow:0 4px 6px -1px #6366f133}.te-modal-btn-confirm:hover{background:var(--te-primary-hover);transform:translateY(-1px);box-shadow:0 6px 8px -1px #6366f14d}.te-modal-btn-confirm:active{transform:translateY(0)}.te-floating-toolbar{background:var(--te-bg-editor);border:1px solid var(--te-border-color);border-radius:var(--te-radius-md);padding:4px;box-shadow:var(--te-shadow-lg);display:flex;gap:2px;pointer-events:auto;opacity:0;transform:translateY(10px);transition:opacity .2s ease,transform .2s ease,background .3s ease}.te-floating-toolbar.te-floating-visible{opacity:1;transform:translateY(0)}.te-floating-btn{background:transparent;border:none;cursor:pointer;padding:6px;border-radius:var(--te-radius-sm);color:var(--te-text-muted);display:flex;align-items:center;justify-content:center;transition:all .2s ease}.te-floating-btn:hover{background:var(--te-btn-hover);color:var(--te-text-main)}.te-floating-btn svg{width:18px;height:18px;stroke:currentColor}.te-loader-overlay{position:absolute;inset:0;background:#f1f5f9e6;backdrop-filter:blur(12px) saturate(200%);-webkit-backdrop-filter:blur(12px) saturate(200%);display:flex;flex-direction:column;align-items:center;justify-content:center;z-index:1000;transition:opacity .4s cubic-bezier(.4,0,.2,1),visibility .4s;border-radius:var(--te-radius-lg)}.te-dark .te-loader-overlay{background:#0f172ae6}.te-loader-overlay.hidden{opacity:0;visibility:hidden;pointer-events:none}.te-loader-spinner{width:48px;height:48px;border:4px solid var(--te-border-color);border-top-color:var(--te-primary-color);border-radius:50%;animation:te-spin 1s cubic-bezier(.4,0,.2,1) infinite;margin-bottom:24px;filter:drop-shadow(0 0 10px rgba(99,102,241,.2))}.te-loader-shimmer{width:140px;height:4px;background:var(--te-border-color);border-radius:2px;overflow:hidden;position:relative}.te-loader-shimmer:after{content:"";position:absolute;top:0;left:0;width:100%;height:100%;background:linear-gradient(90deg,#6366f100 0,#6366f166,#6366f100);animation:te-skeleton-pulse 1.5s infinite}.te-loader-text{font-size:13px;font-weight:600;color:var(--te-text-muted);letter-spacing:.02em;margin-top:12px}
|
package/dist/ui/Toolbar.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@meenainwal/rich-text-editor",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.1",
|
|
4
4
|
"description": "A premium, lightweight, and framework-agnostic WYSIWYG rich text editor with a sophisticated Slate & Indigo design. Highly customizable and optimized for React, Next.js, and Vanilla TypeScript.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"files": [
|