nexheal-lib 0.0.26 → 0.0.28

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.
@@ -1495,6 +1495,358 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.3", ngImpor
1495
1495
  args: ['checkboxContainer']
1496
1496
  }] } });
1497
1497
 
1498
+ class ClickOutsideDirective {
1499
+ clickOutside = new EventEmitter();
1500
+ host = inject(ElementRef);
1501
+ document = inject(DOCUMENT);
1502
+ destroyRef = inject(DestroyRef);
1503
+ constructor() {
1504
+ fromEvent(this.document, 'click')
1505
+ .pipe(takeUntilDestroyed(this.destroyRef))
1506
+ .subscribe((event) => {
1507
+ const clickedInside = this.host.nativeElement.contains(event.target);
1508
+ if (!clickedInside) {
1509
+ this.clickOutside.emit(event);
1510
+ }
1511
+ });
1512
+ }
1513
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.3", ngImport: i0, type: ClickOutsideDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
1514
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.1.3", type: ClickOutsideDirective, isStandalone: true, selector: "[clickOutside]", outputs: { clickOutside: "clickOutside" }, ngImport: i0 });
1515
+ }
1516
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.3", ngImport: i0, type: ClickOutsideDirective, decorators: [{
1517
+ type: Directive,
1518
+ args: [{
1519
+ selector: '[clickOutside]',
1520
+ standalone: true,
1521
+ }]
1522
+ }], ctorParameters: () => [], propDecorators: { clickOutside: [{
1523
+ type: Output
1524
+ }] } });
1525
+
1526
+ class ColorPicker {
1527
+ title;
1528
+ required = false;
1529
+ customClass = "";
1530
+ inline = false;
1531
+ format = "rgb";
1532
+ defaultColor = "#ff0000";
1533
+ disabled = false;
1534
+ readonly = false;
1535
+ onChange = new EventEmitter();
1536
+ blurEvent = new EventEmitter();
1537
+ // current colour as HSB (the picker works in HSB space)
1538
+ h = 0;
1539
+ s = 100;
1540
+ b = 100;
1541
+ overlayVisible = false;
1542
+ value = null;
1543
+ dragMode = null;
1544
+ dragEl = null;
1545
+ moveListener = null;
1546
+ upListener = null;
1547
+ onChangeFn = () => { };
1548
+ onTouchedFn = () => { };
1549
+ ngOnDestroy() {
1550
+ this.unbindDragListeners();
1551
+ }
1552
+ // ---- ControlValueAccessor ----
1553
+ writeValue(value) {
1554
+ this.value = value ?? null;
1555
+ if (value == null || value === "") {
1556
+ this.setFromHex(this.defaultColor);
1557
+ return;
1558
+ }
1559
+ if (typeof value === "string") {
1560
+ this.setFromHex(value);
1561
+ }
1562
+ else if ("r" in value) {
1563
+ const hsb = this.rgbToHsb(value.r, value.g, value.b);
1564
+ this.h = hsb.h;
1565
+ this.s = hsb.s;
1566
+ this.b = hsb.b;
1567
+ }
1568
+ else if ("h" in value) {
1569
+ this.h = value.h;
1570
+ this.s = value.s;
1571
+ this.b = value.b;
1572
+ }
1573
+ }
1574
+ registerOnChange(fn) {
1575
+ this.onChangeFn = fn;
1576
+ }
1577
+ registerOnTouched(fn) {
1578
+ this.onTouchedFn = fn;
1579
+ }
1580
+ setDisabledState(isDisabled) {
1581
+ this.disabled = isDisabled;
1582
+ if (isDisabled) {
1583
+ this.close();
1584
+ }
1585
+ }
1586
+ // ---- Template bindings ----
1587
+ /** Background of the saturation/brightness box: the pure hue at full S/B. */
1588
+ get hueBackground() {
1589
+ const c = this.hsbToRgb(this.h, 100, 100);
1590
+ return `rgb(${c.r}, ${c.g}, ${c.b})`;
1591
+ }
1592
+ /** Hex of the currently selected colour (used for the preview swatch + hex field). */
1593
+ get previewColor() {
1594
+ const c = this.hsbToRgb(this.h, this.s, this.b);
1595
+ return this.rgbToHex(c.r, c.g, c.b);
1596
+ }
1597
+ get satHandleLeft() {
1598
+ return this.s;
1599
+ }
1600
+ get briHandleTop() {
1601
+ return 100 - this.b;
1602
+ }
1603
+ get hueHandleTop() {
1604
+ return (this.h / 360) * 100;
1605
+ }
1606
+ // ---- Open / close ----
1607
+ toggle() {
1608
+ if (this.disabled || this.readonly)
1609
+ return;
1610
+ this.overlayVisible ? this.close() : this.open();
1611
+ }
1612
+ open() {
1613
+ if (this.disabled || this.readonly)
1614
+ return;
1615
+ this.overlayVisible = true;
1616
+ }
1617
+ close() {
1618
+ if (!this.overlayVisible)
1619
+ return;
1620
+ this.overlayVisible = false;
1621
+ this.onTouchedFn();
1622
+ this.blurEvent.emit();
1623
+ }
1624
+ // ---- Dragging on the saturation/brightness box and hue strip ----
1625
+ onSelectorDown(event) {
1626
+ if (this.disabled || this.readonly)
1627
+ return;
1628
+ event.preventDefault();
1629
+ this.dragMode = "selector";
1630
+ this.dragEl = event.currentTarget;
1631
+ this.handleDrag(event);
1632
+ this.bindDragListeners();
1633
+ }
1634
+ onHueDown(event) {
1635
+ if (this.disabled || this.readonly)
1636
+ return;
1637
+ event.preventDefault();
1638
+ this.dragMode = "hue";
1639
+ this.dragEl = event.currentTarget;
1640
+ this.handleDrag(event);
1641
+ this.bindDragListeners();
1642
+ }
1643
+ bindDragListeners() {
1644
+ this.unbindDragListeners();
1645
+ this.moveListener = (e) => this.handleDrag(e);
1646
+ this.upListener = () => {
1647
+ this.unbindDragListeners();
1648
+ this.onTouchedFn();
1649
+ };
1650
+ document.addEventListener("mousemove", this.moveListener);
1651
+ document.addEventListener("mouseup", this.upListener);
1652
+ document.addEventListener("touchmove", this.moveListener, { passive: false });
1653
+ document.addEventListener("touchend", this.upListener);
1654
+ }
1655
+ unbindDragListeners() {
1656
+ if (this.moveListener) {
1657
+ document.removeEventListener("mousemove", this.moveListener);
1658
+ document.removeEventListener("touchmove", this.moveListener);
1659
+ }
1660
+ if (this.upListener) {
1661
+ document.removeEventListener("mouseup", this.upListener);
1662
+ document.removeEventListener("touchend", this.upListener);
1663
+ }
1664
+ this.moveListener = null;
1665
+ this.upListener = null;
1666
+ this.dragMode = null;
1667
+ this.dragEl = null;
1668
+ }
1669
+ handleDrag(event) {
1670
+ if (!this.dragEl)
1671
+ return;
1672
+ if (this.isTouch(event) && event.cancelable)
1673
+ event.preventDefault();
1674
+ const point = this.getPoint(event);
1675
+ const rect = this.dragEl.getBoundingClientRect();
1676
+ if (!rect.width || !rect.height)
1677
+ return;
1678
+ if (this.dragMode === "selector") {
1679
+ const x = this.clamp(point.x - rect.left, 0, rect.width);
1680
+ const y = this.clamp(point.y - rect.top, 0, rect.height);
1681
+ this.s = Math.round((x / rect.width) * 100);
1682
+ this.b = Math.round(100 - (y / rect.height) * 100);
1683
+ }
1684
+ else if (this.dragMode === "hue") {
1685
+ const y = this.clamp(point.y - rect.top, 0, rect.height);
1686
+ this.h = Math.min(359, Math.round((y / rect.height) * 360));
1687
+ }
1688
+ this.emitChange();
1689
+ }
1690
+ // ---- helpers ----
1691
+ emitChange() {
1692
+ const out = this.getValueToEmit();
1693
+ this.value = out;
1694
+ this.onChangeFn(out);
1695
+ this.onChange.emit(out);
1696
+ }
1697
+ getValueToEmit() {
1698
+ if (this.format === "hsb") {
1699
+ return { h: this.h, s: this.s, b: this.b };
1700
+ }
1701
+ const rgb = this.hsbToRgb(this.h, this.s, this.b);
1702
+ if (this.format === "rgb") {
1703
+ return rgb;
1704
+ }
1705
+ return this.rgbToHex(rgb.r, rgb.g, rgb.b);
1706
+ }
1707
+ setFromHex(hex) {
1708
+ const rgb = this.hexToRgb(hex);
1709
+ if (!rgb)
1710
+ return;
1711
+ const hsb = this.rgbToHsb(rgb.r, rgb.g, rgb.b);
1712
+ this.h = hsb.h;
1713
+ this.s = hsb.s;
1714
+ this.b = hsb.b;
1715
+ }
1716
+ isTouch(event) {
1717
+ return typeof TouchEvent !== "undefined" && event instanceof TouchEvent;
1718
+ }
1719
+ getPoint(event) {
1720
+ if (this.isTouch(event)) {
1721
+ const touch = event.touches[0] ?? event.changedTouches[0];
1722
+ return { x: touch.clientX, y: touch.clientY };
1723
+ }
1724
+ return { x: event.clientX, y: event.clientY };
1725
+ }
1726
+ clamp(value, min, max) {
1727
+ return Math.max(min, Math.min(max, value));
1728
+ }
1729
+ // ---- colour space conversions ----
1730
+ hsbToRgb(h, s, br) {
1731
+ const sat = s / 100;
1732
+ const val = br / 100;
1733
+ const c = val * sat;
1734
+ const x = c * (1 - Math.abs(((h / 60) % 2) - 1));
1735
+ const m = val - c;
1736
+ let r = 0, g = 0, b = 0;
1737
+ if (h < 60) {
1738
+ r = c;
1739
+ g = x;
1740
+ b = 0;
1741
+ }
1742
+ else if (h < 120) {
1743
+ r = x;
1744
+ g = c;
1745
+ b = 0;
1746
+ }
1747
+ else if (h < 180) {
1748
+ r = 0;
1749
+ g = c;
1750
+ b = x;
1751
+ }
1752
+ else if (h < 240) {
1753
+ r = 0;
1754
+ g = x;
1755
+ b = c;
1756
+ }
1757
+ else if (h < 300) {
1758
+ r = x;
1759
+ g = 0;
1760
+ b = c;
1761
+ }
1762
+ else {
1763
+ r = c;
1764
+ g = 0;
1765
+ b = x;
1766
+ }
1767
+ return {
1768
+ r: Math.round((r + m) * 255),
1769
+ g: Math.round((g + m) * 255),
1770
+ b: Math.round((b + m) * 255),
1771
+ };
1772
+ }
1773
+ rgbToHsb(r, g, b) {
1774
+ const rr = r / 255, gg = g / 255, bb = b / 255;
1775
+ const max = Math.max(rr, gg, bb);
1776
+ const min = Math.min(rr, gg, bb);
1777
+ const d = max - min;
1778
+ let h = 0;
1779
+ if (d !== 0) {
1780
+ if (max === rr)
1781
+ h = ((gg - bb) / d) % 6;
1782
+ else if (max === gg)
1783
+ h = (bb - rr) / d + 2;
1784
+ else
1785
+ h = (rr - gg) / d + 4;
1786
+ h = Math.round(h * 60);
1787
+ if (h < 0)
1788
+ h += 360;
1789
+ }
1790
+ const s = max === 0 ? 0 : Math.round((d / max) * 100);
1791
+ const br = Math.round(max * 100);
1792
+ return { h, s, b: br };
1793
+ }
1794
+ hexToRgb(hex) {
1795
+ if (!hex)
1796
+ return null;
1797
+ let h = hex.trim().replace(/^#/, "");
1798
+ if (h.length === 3) {
1799
+ h = h.split("").map((c) => c + c).join("");
1800
+ }
1801
+ if (!/^[0-9a-fA-F]{6}$/.test(h))
1802
+ return null;
1803
+ const num = parseInt(h, 16);
1804
+ return { r: (num >> 16) & 255, g: (num >> 8) & 255, b: num & 255 };
1805
+ }
1806
+ rgbToHex(r, g, b) {
1807
+ const toHex = (n) => n.toString(16).padStart(2, "0");
1808
+ return `#${toHex(r)}${toHex(g)}${toHex(b)}`;
1809
+ }
1810
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.3", ngImport: i0, type: ColorPicker, deps: [], target: i0.ɵɵFactoryTarget.Component });
1811
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.3", type: ColorPicker, isStandalone: true, selector: "color-picker", inputs: { title: "title", required: "required", customClass: "customClass", inline: "inline", format: "format", defaultColor: "defaultColor", disabled: "disabled", readonly: "readonly" }, outputs: { onChange: "onChange", blurEvent: "blurEvent" }, providers: [
1812
+ {
1813
+ provide: NG_VALUE_ACCESSOR,
1814
+ useExisting: forwardRef(() => ColorPicker),
1815
+ multi: true,
1816
+ },
1817
+ ], ngImport: i0, template: "<div class=\"form-group color-picker\" [ngClass]=\"customClass\" [class.readonly]=\"readonly\" [class.disabled]=\"disabled\"\n (clickOutside)=\"close()\">\n @if (title) {\n <label class=\"inp-label\" [ngClass]=\"{ 'required': required }\">{{ title }}</label>\n }\n\n @if (!inline) {\n <button #trigger type=\"button\" class=\"cp-preview\" [style.backgroundColor]=\"previewColor\" [disabled]=\"disabled\"\n (click)=\"toggle()\" [attr.aria-label]=\"'Selected color ' + previewColor\"></button>\n }\n\n @if (inline || overlayVisible) {\n <div class=\"cp-panel\" [class.cp-inline]=\"inline\">\n <div class=\"cp-content\">\n <div #selector class=\"cp-selector\" [style.background]=\"hueBackground\" (mousedown)=\"onSelectorDown($event)\"\n (touchstart)=\"onSelectorDown($event)\">\n <div class=\"cp-selector-white\"></div>\n <div class=\"cp-selector-black\"></div>\n <div class=\"cp-selector-handle\" [style.left.%]=\"satHandleLeft\" [style.top.%]=\"briHandleTop\"></div>\n </div>\n <div #hue class=\"cp-hue\" (mousedown)=\"onHueDown($event)\" (touchstart)=\"onHueDown($event)\">\n <div class=\"cp-hue-handle\" [style.top.%]=\"hueHandleTop\"></div>\n </div>\n </div>\n </div>\n }\n</div>\n", styles: [".form-group.color-picker{position:relative}.form-group.color-picker .cp-preview{width:2rem;height:2rem;padding:0;cursor:pointer;border-radius:4px;border:1px solid #d0d3da;transition:box-shadow .15s ease-in-out}.form-group.color-picker .cp-preview:focus-visible{outline:none;box-shadow:0 0 0 2px #3399ff80}.form-group.color-picker.disabled .cp-preview{cursor:not-allowed;opacity:.6}.form-group.color-picker.readonly .cp-preview{cursor:default;pointer-events:none}.form-group.color-picker .cp-panel{top:calc(100% + 4px);left:0;z-index:1000;position:absolute;padding:.5rem;border-radius:4px;background:#fff;box-shadow:0 2px 4px -1px #0003,0 4px 5px #00000024,0 1px 10px #0000001f}.form-group.color-picker .cp-panel.cp-inline{position:static;box-shadow:none;padding:0;border:1px solid #e7e7e7}.form-group.color-picker .cp-content{gap:8px;display:flex;align-items:stretch}.form-group.color-picker .cp-selector{width:150px;height:150px;position:relative;cursor:crosshair;border-radius:3px;touch-action:none;overflow:hidden}.form-group.color-picker .cp-selector-white,.form-group.color-picker .cp-selector-black{inset:0;position:absolute;pointer-events:none}.form-group.color-picker .cp-selector-white{background:linear-gradient(to right,#fff,#fff0)}.form-group.color-picker .cp-selector-black{background:linear-gradient(to top,#000,#0000)}.form-group.color-picker .cp-selector-handle{width:12px;height:12px;position:absolute;border-radius:50%;pointer-events:none;border:2px solid #ffffff;transform:translate(-50%,-50%);box-shadow:0 0 1px 1px #0006}.form-group.color-picker .cp-hue{width:16px;height:150px;position:relative;cursor:pointer;border-radius:3px;touch-action:none;background:linear-gradient(to bottom,red,#ff0 17%,#0f0 33%,#0ff,#00f 67%,#f0f 83%,red)}.form-group.color-picker .cp-hue-handle{left:-2px;right:-2px;height:4px;position:absolute;pointer-events:none;border:1px solid #ffffff;transform:translateY(-50%);box-shadow:0 0 1px 1px #0006}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: ClickOutsideDirective, selector: "[clickOutside]", outputs: ["clickOutside"] }] });
1818
+ }
1819
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.3", ngImport: i0, type: ColorPicker, decorators: [{
1820
+ type: Component,
1821
+ args: [{ selector: "color-picker", standalone: true, imports: [CommonModule, ClickOutsideDirective], providers: [
1822
+ {
1823
+ provide: NG_VALUE_ACCESSOR,
1824
+ useExisting: forwardRef(() => ColorPicker),
1825
+ multi: true,
1826
+ },
1827
+ ], template: "<div class=\"form-group color-picker\" [ngClass]=\"customClass\" [class.readonly]=\"readonly\" [class.disabled]=\"disabled\"\n (clickOutside)=\"close()\">\n @if (title) {\n <label class=\"inp-label\" [ngClass]=\"{ 'required': required }\">{{ title }}</label>\n }\n\n @if (!inline) {\n <button #trigger type=\"button\" class=\"cp-preview\" [style.backgroundColor]=\"previewColor\" [disabled]=\"disabled\"\n (click)=\"toggle()\" [attr.aria-label]=\"'Selected color ' + previewColor\"></button>\n }\n\n @if (inline || overlayVisible) {\n <div class=\"cp-panel\" [class.cp-inline]=\"inline\">\n <div class=\"cp-content\">\n <div #selector class=\"cp-selector\" [style.background]=\"hueBackground\" (mousedown)=\"onSelectorDown($event)\"\n (touchstart)=\"onSelectorDown($event)\">\n <div class=\"cp-selector-white\"></div>\n <div class=\"cp-selector-black\"></div>\n <div class=\"cp-selector-handle\" [style.left.%]=\"satHandleLeft\" [style.top.%]=\"briHandleTop\"></div>\n </div>\n <div #hue class=\"cp-hue\" (mousedown)=\"onHueDown($event)\" (touchstart)=\"onHueDown($event)\">\n <div class=\"cp-hue-handle\" [style.top.%]=\"hueHandleTop\"></div>\n </div>\n </div>\n </div>\n }\n</div>\n", styles: [".form-group.color-picker{position:relative}.form-group.color-picker .cp-preview{width:2rem;height:2rem;padding:0;cursor:pointer;border-radius:4px;border:1px solid #d0d3da;transition:box-shadow .15s ease-in-out}.form-group.color-picker .cp-preview:focus-visible{outline:none;box-shadow:0 0 0 2px #3399ff80}.form-group.color-picker.disabled .cp-preview{cursor:not-allowed;opacity:.6}.form-group.color-picker.readonly .cp-preview{cursor:default;pointer-events:none}.form-group.color-picker .cp-panel{top:calc(100% + 4px);left:0;z-index:1000;position:absolute;padding:.5rem;border-radius:4px;background:#fff;box-shadow:0 2px 4px -1px #0003,0 4px 5px #00000024,0 1px 10px #0000001f}.form-group.color-picker .cp-panel.cp-inline{position:static;box-shadow:none;padding:0;border:1px solid #e7e7e7}.form-group.color-picker .cp-content{gap:8px;display:flex;align-items:stretch}.form-group.color-picker .cp-selector{width:150px;height:150px;position:relative;cursor:crosshair;border-radius:3px;touch-action:none;overflow:hidden}.form-group.color-picker .cp-selector-white,.form-group.color-picker .cp-selector-black{inset:0;position:absolute;pointer-events:none}.form-group.color-picker .cp-selector-white{background:linear-gradient(to right,#fff,#fff0)}.form-group.color-picker .cp-selector-black{background:linear-gradient(to top,#000,#0000)}.form-group.color-picker .cp-selector-handle{width:12px;height:12px;position:absolute;border-radius:50%;pointer-events:none;border:2px solid #ffffff;transform:translate(-50%,-50%);box-shadow:0 0 1px 1px #0006}.form-group.color-picker .cp-hue{width:16px;height:150px;position:relative;cursor:pointer;border-radius:3px;touch-action:none;background:linear-gradient(to bottom,red,#ff0 17%,#0f0 33%,#0ff,#00f 67%,#f0f 83%,red)}.form-group.color-picker .cp-hue-handle{left:-2px;right:-2px;height:4px;position:absolute;pointer-events:none;border:1px solid #ffffff;transform:translateY(-50%);box-shadow:0 0 1px 1px #0006}\n"] }]
1828
+ }], propDecorators: { title: [{
1829
+ type: Input
1830
+ }], required: [{
1831
+ type: Input
1832
+ }], customClass: [{
1833
+ type: Input
1834
+ }], inline: [{
1835
+ type: Input
1836
+ }], format: [{
1837
+ type: Input
1838
+ }], defaultColor: [{
1839
+ type: Input
1840
+ }], disabled: [{
1841
+ type: Input
1842
+ }], readonly: [{
1843
+ type: Input
1844
+ }], onChange: [{
1845
+ type: Output
1846
+ }], blurEvent: [{
1847
+ type: Output
1848
+ }] } });
1849
+
1498
1850
  class InputControl {
1499
1851
  type = "text";
1500
1852
  title;
@@ -1732,34 +2084,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.3", ngImpor
1732
2084
  type: Input
1733
2085
  }] } });
1734
2086
 
1735
- class ClickOutsideDirective {
1736
- clickOutside = new EventEmitter();
1737
- host = inject(ElementRef);
1738
- document = inject(DOCUMENT);
1739
- destroyRef = inject(DestroyRef);
1740
- constructor() {
1741
- fromEvent(this.document, 'click')
1742
- .pipe(takeUntilDestroyed(this.destroyRef))
1743
- .subscribe((event) => {
1744
- const clickedInside = this.host.nativeElement.contains(event.target);
1745
- if (!clickedInside) {
1746
- this.clickOutside.emit(event);
1747
- }
1748
- });
1749
- }
1750
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.3", ngImport: i0, type: ClickOutsideDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
1751
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.1.3", type: ClickOutsideDirective, isStandalone: true, selector: "[clickOutside]", outputs: { clickOutside: "clickOutside" }, ngImport: i0 });
1752
- }
1753
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.3", ngImport: i0, type: ClickOutsideDirective, decorators: [{
1754
- type: Directive,
1755
- args: [{
1756
- selector: '[clickOutside]',
1757
- standalone: true,
1758
- }]
1759
- }], ctorParameters: () => [], propDecorators: { clickOutside: [{
1760
- type: Output
1761
- }] } });
1762
-
1763
2087
  class MultiselectControl {
1764
2088
  cdRef;
1765
2089
  subscription = new Subscription();
@@ -2897,7 +3221,7 @@ class TextEditor {
2897
3221
  useExisting: forwardRef(() => TextEditor),
2898
3222
  multi: true,
2899
3223
  },
2900
- ], viewQueries: [{ propertyName: "editorRef", first: true, predicate: ["editor"], descendants: true }], ngImport: i0, template: "<div class=\"text-editor\" [ngClass]=\"{'readonly': readonly || disabled}\">\r\n <div class=\"toolbar\" *ngIf=\"!readonly && !disabled\">\r\n <div class=\"toolbar-items\">\r\n <button type=\"button\" (click)=\"applyInlineStyle('bold')\" tooltip=\"Bold\">\r\n <i class=\"he he-bold\"></i>\r\n </button>\r\n <button type=\"button\" (click)=\"applyInlineStyle('italic')\" tooltip=\"italic\">\r\n <i class=\"he he-italics\"></i>\r\n </button>\r\n <button type=\"button\" (click)=\"applyInlineStyle('underline')\" tooltip=\"Underline\">\r\n <i class=\"he he-underline\"></i>\r\n </button>\r\n </div>\r\n <div class=\"toolbar-items\" *ngIf=\"header\">\r\n <button type=\"button\" (click)=\"applyBlockFormat('h1')\" tooltip=\"Header 1\">\r\n <i class=\"he he-heading-1\"></i>\r\n </button>\r\n <button type=\"button\" (click)=\"applyBlockFormat('h2')\" tooltip=\"Header 2\">\r\n <i class=\"he he-heading-2\"></i>\r\n </button>\r\n </div>\r\n <div class=\"toolbar-items more-gap\">\r\n <div class=\"input-wrap\" tooltip=\"Text Color\">\r\n <i class=\"he he-text-drop\"></i>\r\n <input type=\"color\" (change)=\"applyColor($event)\" />\r\n </div>\r\n <div class=\"input-wrap\" tooltip=\"Background Color\">\r\n <i class=\"he he-background-drop\"></i>\r\n <input type=\"color\" (change)=\"applyHighlight($event)\" />\r\n </div>\r\n </div>\r\n <div class=\"toolbar-items\">\r\n <button type=\"button\" (click)=\"setAlignment('left')\" tooltip=\"Justify Left\">\r\n <i class=\"he he-left-align\"></i>\r\n </button>\r\n <button type=\"button\" (click)=\"setAlignment('center')\" tooltip=\"Justify Center\">\r\n <i class=\"he he-center-align\"></i>\r\n </button>\r\n <button type=\"button\" (click)=\"setAlignment('right')\" tooltip=\"Justify Right\">\r\n <i class=\"he he-right-align\"></i>\r\n </button>\r\n <button type=\"button\" (click)=\"setAlignment('justify')\" tooltip=\"Justify Full\">\r\n <i class=\"he he-justify\"></i>\r\n </button>\r\n </div>\r\n <div class=\"toolbar-items\">\r\n <button type=\"button\" (click)=\"indent()\" tooltip=\"Indent\">\r\n <i class=\"he he-text-indent-left\"></i>\r\n </button>\r\n <button type=\"button\" (click)=\"outdent()\" tooltip=\"Outdent\">\r\n <i class=\"he he-text-indent-right\"></i>\r\n </button>\r\n </div>\r\n <div class=\"toolbar-items\" *ngIf=\"media\">\r\n <button type=\"button\" (click)=\"applyList('ul')\" tooltip=\"Unordered list\">\r\n <i class=\"he he-unordered-list\"></i>\r\n </button>\r\n <button type=\"button\" (click)=\"applyList('ol')\" tooltip=\"Ordered list\">\r\n <i class=\"he he-ordered-list\"></i>\r\n </button>\r\n </div>\r\n <div class=\"toolbar-items\" *ngIf=\"link\">\r\n <button type=\"button\" (click)=\"createLink()\" tooltip=\"Link\">\r\n <i class=\"he he-link\"></i>\r\n </button>\r\n <button type=\"button\" (click)=\"insertImage()\" tooltip=\"Image\">\r\n <i class=\"he he-image\"></i>\r\n </button>\r\n </div>\r\n <div class=\"toolbar-items\">\r\n <button type=\"button\" (click)=\"undo()\" tooltip=\"Undo\">\r\n <i class=\"he he-undo\"></i>\r\n </button>\r\n <button type=\"button\" (click)=\"redo()\" tooltip=\"Redo\">\r\n <i class=\"he he-redo\"></i>\r\n </button>\r\n </div>\r\n <div class=\"toolbar-items\">\r\n <button type=\"button\" (click)=\"clearFormatting()\" tooltip=\"Clear Formatting\">\r\n <i class=\"he he-text-clear-format\"></i>\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <div #editor class=\"editor-content\" [attr.contenteditable]=\"(readonly || disabled) ? 'false' : 'true'\" (input)=\"onInput()\" (blur)=\"onTouched()\"\r\n [attr.data-placeholder]=\"placeholder\">\r\n </div>\r\n\r\n <!-- Custom Modal for Link/Image URL -->\r\n <div class=\"editor-modal-overlay\" *ngIf=\"showModal\" (click)=\"cancelModal()\">\r\n <div class=\"editor-modal\" (click)=\"$event.stopPropagation()\">\r\n <div class=\"editor-modal-header\">\r\n <span>{{ modalType === 'link' ? 'Insert Link' : 'Insert Image' }}</span>\r\n <button type=\"button\" class=\"editor-modal-close\" (click)=\"cancelModal()\">\r\n <i class=\"he he-close\"></i>\r\n </button>\r\n </div>\r\n <div class=\"editor-modal-body\">\r\n <div class=\"url-row\" *ngFor=\"let url of modalUrls; let i = index; trackBy: trackByIndex\">\r\n <input type=\"text\" class=\"url-input\"\r\n [ngModel]=\"modalUrls[i]\"\r\n (ngModelChange)=\"modalUrls[i] = $event\"\r\n [placeholder]=\"modalType === 'link' ? 'https://example.com' : 'https://example.com/image.png'\" />\r\n <button type=\"button\" class=\"url-remove-btn\" *ngIf=\"modalUrls.length > 1\" (click)=\"removeUrlRow(i)\" title=\"Remove\">\r\n <i class=\"he he-close\"></i>\r\n </button>\r\n </div>\r\n <button type=\"button\" class=\"url-add-btn\" (click)=\"addUrlRow()\">\r\n + Add more\r\n </button>\r\n </div>\r\n <div class=\"editor-modal-footer\">\r\n <button type=\"button\" class=\"modal-btn cancel-btn\" (click)=\"cancelModal()\">Cancel</button>\r\n <button type=\"button\" class=\"modal-btn confirm-btn\" (click)=\"confirmModal()\">Insert</button>\r\n </div>\r\n </div>\r\n </div>\r\n</div>\r\n", styles: [".text-editor{border:1px solid #ccc}.text-editor .toolbar{gap:.75rem;display:flex;flex-wrap:wrap;background:#f8f8f8;padding:.75rem;border-bottom:1px solid #cccccc}.text-editor .toolbar .toolbar-items{height:18px;display:flex;flex-wrap:wrap;align-items:center;padding-right:.75rem;border-right:1px solid #969090}.text-editor .toolbar .toolbar-items button,.text-editor .toolbar .toolbar-items .input-wrap{cursor:pointer;min-width:25px;min-height:20px}.text-editor .toolbar .toolbar-items button:hover i,.text-editor .toolbar .toolbar-items .input-wrap:hover i{color:#000}.text-editor .toolbar .toolbar-items button{border:0;display:grid;place-items:center;background:transparent}.text-editor .toolbar .toolbar-items button:hover{background:#eee}.text-editor .toolbar .toolbar-items .input-wrap{gap:2px;display:flex;cursor:pointer;align-items:center;flex-direction:column;justify-content:center}.text-editor .toolbar .toolbar-items .input-wrap input[type=color]{width:80%;padding:0;height:2px;border:none;cursor:inherit}.text-editor .toolbar .toolbar-items i{font-size:13px;color:#3c4148}.text-editor .toolbar .toolbar-items i.he-bold{font-weight:600}.text-editor .toolbar .toolbar-items i.he-underline{font-size:14px}.text-editor .toolbar .toolbar-items i.he-text-drop{font-size:12px}.text-editor .toolbar .toolbar-items i.he-background-drop{top:-1px;font-size:12px}.text-editor .toolbar .toolbar-items i.he-heading-1,.text-editor .toolbar .toolbar-items i.he-link,.text-editor .toolbar .toolbar-items i.he-left-align,.text-editor .toolbar .toolbar-items i.he-center-align,.text-editor .toolbar .toolbar-items i.he-right-align,.text-editor .toolbar .toolbar-items i.he-justify{font-size:16px}.text-editor .toolbar .toolbar-items i.he-text-indent-left,.text-editor .toolbar .toolbar-items i.he-text-indent-right{font-size:17px}.text-editor .toolbar .toolbar-items i.he-heading-2{top:1px;font-size:16px}.text-editor .toolbar .toolbar-items i.he-unordered-list,.text-editor .toolbar .toolbar-items i.he-ordered-list{top:-1px;font-size:20px}.text-editor .toolbar .toolbar-items i.he-image{font-size:15px;font-weight:600}.text-editor .toolbar .toolbar-items i.he-redo,.text-editor .toolbar .toolbar-items i.he-undo{top:-1px;font-size:14px}.text-editor .toolbar .toolbar-items.more-gap{gap:5px}.text-editor .toolbar .toolbar-items:last-child{border-right:0}.text-editor .editor-content{outline:none;min-height:200px;position:relative;background:#fff;padding:.75rem}.text-editor .editor-content[data-placeholder]:empty:before{content:attr(data-placeholder);color:#aaa;pointer-events:none;position:absolute;left:.75rem;top:.75rem}.text-editor .editor-modal-overlay{position:fixed;top:0;left:0;width:100%;height:100%;background:#00000073;display:flex;align-items:center;justify-content:center;z-index:10000}.text-editor .editor-modal{background:#fff;border-radius:8px;box-shadow:0 8px 32px #0003;min-width:420px;max-width:520px;width:100%;animation:modalFadeIn .2s ease}@keyframes modalFadeIn{0%{opacity:0;transform:translateY(-10px)}to{opacity:1;transform:translateY(0)}}.text-editor .editor-modal-header{display:flex;align-items:center;justify-content:space-between;padding:14px 18px;border-bottom:1px solid #e8e8e8}.text-editor .editor-modal-header span{font-size:15px;font-weight:600;color:#1a1a1a}.text-editor .editor-modal-close{background:none;border:none;cursor:pointer;padding:4px;border-radius:4px;display:grid;place-items:center}.text-editor .editor-modal-close i{font-size:14px;color:#666}.text-editor .editor-modal-close:hover{background:#f0f0f0}.text-editor .editor-modal-close:hover i{color:#333}.text-editor .editor-modal-body{padding:16px 18px}.text-editor .editor-modal-body .url-row{display:flex;align-items:center;gap:8px;margin-bottom:10px}.text-editor .editor-modal-body .url-input{flex:1;padding:8px 12px;border:1px solid #d0d0d0;border-radius:6px;font-size:13px;color:#333;outline:none;transition:border-color .2s}.text-editor .editor-modal-body .url-input:focus{border-color:#007bff;box-shadow:0 0 0 2px #007bff26}.text-editor .editor-modal-body .url-input::placeholder{color:#aaa}.text-editor .editor-modal-body .url-remove-btn{background:none;border:1px solid #e0e0e0;border-radius:6px;cursor:pointer;padding:6px 8px;display:grid;place-items:center;transition:all .15s}.text-editor .editor-modal-body .url-remove-btn i{font-size:11px;color:#999}.text-editor .editor-modal-body .url-remove-btn:hover{background:#fff0f0;border-color:#faa}.text-editor .editor-modal-body .url-remove-btn:hover i{color:#e04040}.text-editor .editor-modal-body .url-add-btn{background:none;border:1px dashed #c0c0c0;border-radius:6px;cursor:pointer;padding:6px 14px;font-size:12px;color:#007bff;transition:all .15s;width:100%}.text-editor .editor-modal-body .url-add-btn:hover{background:#f0f8ff;border-color:#007bff}.text-editor .editor-modal-footer{display:flex;justify-content:flex-end;gap:10px;padding:12px 18px;border-top:1px solid #e8e8e8}.text-editor .editor-modal-footer .modal-btn{padding:7px 20px;border-radius:6px;font-size:13px;font-weight:500;cursor:pointer;transition:all .15s;border:1px solid transparent}.text-editor .editor-modal-footer .cancel-btn{background:#f5f5f5;color:#555;border-color:#ddd}.text-editor .editor-modal-footer .cancel-btn:hover{background:#eaeaea}.text-editor .editor-modal-footer .confirm-btn{background:#007bff;color:#fff}.text-editor .editor-modal-footer .confirm-btn:hover{background:#0069d9}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }] });
3224
+ ], viewQueries: [{ propertyName: "editorRef", first: true, predicate: ["editor"], descendants: true }], ngImport: i0, template: "<div class=\"text-editor\" [ngClass]=\"{'readonly': readonly || disabled}\">\n <div class=\"toolbar\" *ngIf=\"!readonly && !disabled\">\n <div class=\"toolbar-items\">\n <button type=\"button\" (mousedown)=\"$event.preventDefault()\" (click)=\"applyInlineStyle('bold')\" title=\"Bold\">\n <i class=\"he he-bold\"></i>\n </button>\n <button type=\"button\" (mousedown)=\"$event.preventDefault()\" (click)=\"applyInlineStyle('italic')\" title=\"Italic\">\n <i class=\"he he-italics\"></i>\n </button>\n <button type=\"button\" (mousedown)=\"$event.preventDefault()\" (click)=\"applyInlineStyle('underline')\" title=\"Underline\">\n <i class=\"he he-underline\"></i>\n </button>\n </div>\n <div class=\"toolbar-items\" *ngIf=\"header\">\n <button type=\"button\" (mousedown)=\"$event.preventDefault()\" (click)=\"applyBlockFormat('h1')\" title=\"Header 1\">\n <i class=\"he he-heading-1\"></i>\n </button>\n <button type=\"button\" (mousedown)=\"$event.preventDefault()\" (click)=\"applyBlockFormat('h2')\" title=\"Header 2\">\n <i class=\"he he-heading-2\"></i>\n </button>\n </div>\n <div class=\"toolbar-items more-gap\">\n <div class=\"input-wrap\" title=\"Text Color\" (mousedown)=\"$event.preventDefault()\">\n <i class=\"he he-text-drop\"></i>\n <input type=\"color\" (input)=\"applyColor($event)\" />\n </div>\n <div class=\"input-wrap\" title=\"Background Color\" (mousedown)=\"$event.preventDefault()\">\n <i class=\"he he-background-drop\"></i>\n <input type=\"color\" (input)=\"applyHighlight($event)\" />\n </div>\n </div>\n <div class=\"toolbar-items\">\n <button type=\"button\" (mousedown)=\"$event.preventDefault()\" (click)=\"setAlignment('left')\" title=\"Justify Left\">\n <i class=\"he he-left-align\"></i>\n </button>\n <button type=\"button\" (mousedown)=\"$event.preventDefault()\" (click)=\"setAlignment('center')\" title=\"Justify Center\">\n <i class=\"he he-center-align\"></i>\n </button>\n <button type=\"button\" (mousedown)=\"$event.preventDefault()\" (click)=\"setAlignment('right')\" title=\"Justify Right\">\n <i class=\"he he-right-align\"></i>\n </button>\n <button type=\"button\" (mousedown)=\"$event.preventDefault()\" (click)=\"setAlignment('justify')\" title=\"Justify Full\">\n <i class=\"he he-justify\"></i>\n </button>\n </div>\n <div class=\"toolbar-items\">\n <button type=\"button\" (mousedown)=\"$event.preventDefault()\" (click)=\"indent()\" title=\"Indent\">\n <i class=\"he he-text-indent-left\"></i>\n </button>\n <button type=\"button\" (mousedown)=\"$event.preventDefault()\" (click)=\"outdent()\" title=\"Outdent\">\n <i class=\"he he-text-indent-right\"></i>\n </button>\n </div>\n <div class=\"toolbar-items\" *ngIf=\"media\">\n <button type=\"button\" (mousedown)=\"$event.preventDefault()\" (click)=\"applyList('ul')\" title=\"Unordered list\">\n <i class=\"he he-unordered-list\"></i>\n </button>\n <button type=\"button\" (mousedown)=\"$event.preventDefault()\" (click)=\"applyList('ol')\" title=\"Ordered list\">\n <i class=\"he he-ordered-list\"></i>\n </button>\n </div>\n <div class=\"toolbar-items\" *ngIf=\"link\">\n <button type=\"button\" (mousedown)=\"$event.preventDefault()\" (click)=\"createLink()\" title=\"Link\">\n <i class=\"he he-link\"></i>\n </button>\n <button type=\"button\" (mousedown)=\"$event.preventDefault()\" (click)=\"insertImage()\" title=\"Image\">\n <i class=\"he he-image\"></i>\n </button>\n </div>\n <div class=\"toolbar-items\">\n <button type=\"button\" (mousedown)=\"$event.preventDefault()\" (click)=\"undo()\" title=\"Undo\">\n <i class=\"he he-undo\"></i>\n </button>\n <button type=\"button\" (mousedown)=\"$event.preventDefault()\" (click)=\"redo()\" title=\"Redo\">\n <i class=\"he he-redo\"></i>\n </button>\n </div>\n <div class=\"toolbar-items\">\n <button type=\"button\" (mousedown)=\"$event.preventDefault()\" (click)=\"clearFormatting()\" title=\"Clear Formatting\">\n <i class=\"he he-text-clear-format\"></i>\n </button>\n </div>\n </div>\n\n <div #editor class=\"editor-content\" [attr.contenteditable]=\"(readonly || disabled) ? 'false' : 'true'\" (input)=\"onInput()\" (blur)=\"onTouched()\"\n [attr.data-placeholder]=\"placeholder\">\n </div>\n\n <!-- Custom Modal for Link/Image URL -->\n <div class=\"editor-modal-overlay\" *ngIf=\"showModal\" (click)=\"cancelModal()\">\n <div class=\"editor-modal\" (click)=\"$event.stopPropagation()\">\n <div class=\"editor-modal-header\">\n <span>{{ modalType === 'link' ? 'Insert Link' : 'Insert Image' }}</span>\n <button type=\"button\" class=\"editor-modal-close\" (click)=\"cancelModal()\">\n <i class=\"he he-close\"></i>\n </button>\n </div>\n <div class=\"editor-modal-body\">\n <div class=\"url-row\" *ngFor=\"let url of modalUrls; let i = index; trackBy: trackByIndex\">\n <input type=\"text\" class=\"url-input\"\n [ngModel]=\"modalUrls[i]\"\n (ngModelChange)=\"modalUrls[i] = $event\"\n [placeholder]=\"modalType === 'link' ? 'https://example.com' : 'https://example.com/image.png'\" />\n <button type=\"button\" class=\"url-remove-btn\" *ngIf=\"modalUrls.length > 1\" (click)=\"removeUrlRow(i)\" title=\"Remove\">\n <i class=\"he he-close\"></i>\n </button>\n </div>\n <button type=\"button\" class=\"url-add-btn\" (click)=\"addUrlRow()\">\n + Add more\n </button>\n </div>\n <div class=\"editor-modal-footer\">\n <button type=\"button\" class=\"modal-btn cancel-btn\" (click)=\"cancelModal()\">Cancel</button>\n <button type=\"button\" class=\"modal-btn confirm-btn\" (click)=\"confirmModal()\">Insert</button>\n </div>\n </div>\n </div>\n</div>\n", styles: [".text-editor{border:1px solid #ccc}.text-editor .toolbar{gap:.75rem;display:flex;flex-wrap:wrap;background:#f8f8f8;padding:.75rem;border-bottom:1px solid #cccccc}.text-editor .toolbar .toolbar-items{height:18px;display:flex;flex-wrap:wrap;align-items:center;padding-right:.75rem;border-right:1px solid #969090}.text-editor .toolbar .toolbar-items button,.text-editor .toolbar .toolbar-items .input-wrap{cursor:pointer;min-width:25px;min-height:20px}.text-editor .toolbar .toolbar-items button:hover i,.text-editor .toolbar .toolbar-items .input-wrap:hover i{color:#000}.text-editor .toolbar .toolbar-items button{border:0;display:grid;place-items:center;background:transparent}.text-editor .toolbar .toolbar-items button:hover{background:#eee}.text-editor .toolbar .toolbar-items .input-wrap{gap:2px;display:flex;cursor:pointer;align-items:center;flex-direction:column;justify-content:center}.text-editor .toolbar .toolbar-items .input-wrap input[type=color]{width:80%;padding:0;height:2px;border:none;cursor:inherit}.text-editor .toolbar .toolbar-items i{font-size:13px;color:#3c4148}.text-editor .toolbar .toolbar-items i.he-bold{font-weight:600}.text-editor .toolbar .toolbar-items i.he-underline{font-size:14px}.text-editor .toolbar .toolbar-items i.he-text-drop{font-size:12px}.text-editor .toolbar .toolbar-items i.he-background-drop{top:-1px;font-size:12px}.text-editor .toolbar .toolbar-items i.he-heading-1,.text-editor .toolbar .toolbar-items i.he-link,.text-editor .toolbar .toolbar-items i.he-left-align,.text-editor .toolbar .toolbar-items i.he-center-align,.text-editor .toolbar .toolbar-items i.he-right-align,.text-editor .toolbar .toolbar-items i.he-justify{font-size:16px}.text-editor .toolbar .toolbar-items i.he-text-indent-left,.text-editor .toolbar .toolbar-items i.he-text-indent-right{font-size:17px}.text-editor .toolbar .toolbar-items i.he-heading-2{top:1px;font-size:16px}.text-editor .toolbar .toolbar-items i.he-unordered-list,.text-editor .toolbar .toolbar-items i.he-ordered-list{top:-1px;font-size:20px}.text-editor .toolbar .toolbar-items i.he-image{font-size:15px;font-weight:600}.text-editor .toolbar .toolbar-items i.he-redo,.text-editor .toolbar .toolbar-items i.he-undo{top:-1px;font-size:14px}.text-editor .toolbar .toolbar-items.more-gap{gap:5px}.text-editor .toolbar .toolbar-items:last-child{border-right:0}.text-editor .editor-content{outline:none;min-height:200px;position:relative;background:#fff;padding:.75rem}.text-editor .editor-content[data-placeholder]:empty:before{content:attr(data-placeholder);color:#aaa;pointer-events:none;position:absolute;left:.75rem;top:.75rem}.text-editor .editor-modal-overlay{position:fixed;top:0;left:0;width:100%;height:100%;background:#00000073;display:flex;align-items:center;justify-content:center;z-index:10000}.text-editor .editor-modal{background:#fff;border-radius:8px;box-shadow:0 8px 32px #0003;width:420px;max-width:90vw;animation:modalFadeIn .2s ease}@keyframes modalFadeIn{0%{opacity:0;transform:translateY(-10px)}to{opacity:1;transform:translateY(0)}}.text-editor .editor-modal-header{display:flex;align-items:center;justify-content:space-between;padding:14px 18px;border-bottom:1px solid #e8e8e8}.text-editor .editor-modal-header span{font-size:15px;font-weight:600;color:#1a1a1a}.text-editor .editor-modal-close{background:none;border:none;cursor:pointer;padding:4px;border-radius:4px;display:grid;place-items:center}.text-editor .editor-modal-close i{font-size:14px;color:#666}.text-editor .editor-modal-close:hover{background:#f0f0f0}.text-editor .editor-modal-close:hover i{color:#333}.text-editor .editor-modal-body{padding:16px 18px}.text-editor .editor-modal-body .url-row{display:flex;align-items:center;gap:8px;margin-bottom:10px}.text-editor .editor-modal-body .url-input{flex:1;padding:8px 12px;border:1px solid #d0d0d0;border-radius:6px;font-size:13px;color:#333;outline:none;transition:border-color .2s}.text-editor .editor-modal-body .url-input:focus{border-color:#007bff;box-shadow:0 0 0 2px #007bff26}.text-editor .editor-modal-body .url-input::placeholder{color:#aaa}.text-editor .editor-modal-body .url-remove-btn{background:none;border:1px solid #e0e0e0;border-radius:6px;cursor:pointer;padding:6px 8px;display:grid;place-items:center;transition:all .15s}.text-editor .editor-modal-body .url-remove-btn i{font-size:11px;color:#999}.text-editor .editor-modal-body .url-remove-btn:hover{background:#fff0f0;border-color:#faa}.text-editor .editor-modal-body .url-remove-btn:hover i{color:#e04040}.text-editor .editor-modal-body .url-add-btn{background:none;border:1px dashed #c0c0c0;border-radius:6px;cursor:pointer;padding:6px 14px;font-size:12px;color:#007bff;transition:all .15s;width:100%}.text-editor .editor-modal-body .url-add-btn:hover{background:#f0f8ff;border-color:#007bff}.text-editor .editor-modal-footer{display:flex;justify-content:flex-end;gap:10px;padding:12px 18px;border-top:1px solid #e8e8e8}.text-editor .editor-modal-footer .modal-btn{padding:7px 20px;border-radius:6px;font-size:13px;font-weight:500;cursor:pointer;transition:all .15s;border:1px solid transparent}.text-editor .editor-modal-footer .cancel-btn{background:#f5f5f5;color:#555;border-color:#ddd}.text-editor .editor-modal-footer .cancel-btn:hover{background:#eaeaea}.text-editor .editor-modal-footer .confirm-btn{background:#007bff;color:#fff}.text-editor .editor-modal-footer .confirm-btn:hover{background:#0069d9}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }] });
2901
3225
  }
2902
3226
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.3", ngImport: i0, type: TextEditor, decorators: [{
2903
3227
  type: Component,
@@ -2907,7 +3231,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.3", ngImpor
2907
3231
  useExisting: forwardRef(() => TextEditor),
2908
3232
  multi: true,
2909
3233
  },
2910
- ], template: "<div class=\"text-editor\" [ngClass]=\"{'readonly': readonly || disabled}\">\r\n <div class=\"toolbar\" *ngIf=\"!readonly && !disabled\">\r\n <div class=\"toolbar-items\">\r\n <button type=\"button\" (click)=\"applyInlineStyle('bold')\" tooltip=\"Bold\">\r\n <i class=\"he he-bold\"></i>\r\n </button>\r\n <button type=\"button\" (click)=\"applyInlineStyle('italic')\" tooltip=\"italic\">\r\n <i class=\"he he-italics\"></i>\r\n </button>\r\n <button type=\"button\" (click)=\"applyInlineStyle('underline')\" tooltip=\"Underline\">\r\n <i class=\"he he-underline\"></i>\r\n </button>\r\n </div>\r\n <div class=\"toolbar-items\" *ngIf=\"header\">\r\n <button type=\"button\" (click)=\"applyBlockFormat('h1')\" tooltip=\"Header 1\">\r\n <i class=\"he he-heading-1\"></i>\r\n </button>\r\n <button type=\"button\" (click)=\"applyBlockFormat('h2')\" tooltip=\"Header 2\">\r\n <i class=\"he he-heading-2\"></i>\r\n </button>\r\n </div>\r\n <div class=\"toolbar-items more-gap\">\r\n <div class=\"input-wrap\" tooltip=\"Text Color\">\r\n <i class=\"he he-text-drop\"></i>\r\n <input type=\"color\" (change)=\"applyColor($event)\" />\r\n </div>\r\n <div class=\"input-wrap\" tooltip=\"Background Color\">\r\n <i class=\"he he-background-drop\"></i>\r\n <input type=\"color\" (change)=\"applyHighlight($event)\" />\r\n </div>\r\n </div>\r\n <div class=\"toolbar-items\">\r\n <button type=\"button\" (click)=\"setAlignment('left')\" tooltip=\"Justify Left\">\r\n <i class=\"he he-left-align\"></i>\r\n </button>\r\n <button type=\"button\" (click)=\"setAlignment('center')\" tooltip=\"Justify Center\">\r\n <i class=\"he he-center-align\"></i>\r\n </button>\r\n <button type=\"button\" (click)=\"setAlignment('right')\" tooltip=\"Justify Right\">\r\n <i class=\"he he-right-align\"></i>\r\n </button>\r\n <button type=\"button\" (click)=\"setAlignment('justify')\" tooltip=\"Justify Full\">\r\n <i class=\"he he-justify\"></i>\r\n </button>\r\n </div>\r\n <div class=\"toolbar-items\">\r\n <button type=\"button\" (click)=\"indent()\" tooltip=\"Indent\">\r\n <i class=\"he he-text-indent-left\"></i>\r\n </button>\r\n <button type=\"button\" (click)=\"outdent()\" tooltip=\"Outdent\">\r\n <i class=\"he he-text-indent-right\"></i>\r\n </button>\r\n </div>\r\n <div class=\"toolbar-items\" *ngIf=\"media\">\r\n <button type=\"button\" (click)=\"applyList('ul')\" tooltip=\"Unordered list\">\r\n <i class=\"he he-unordered-list\"></i>\r\n </button>\r\n <button type=\"button\" (click)=\"applyList('ol')\" tooltip=\"Ordered list\">\r\n <i class=\"he he-ordered-list\"></i>\r\n </button>\r\n </div>\r\n <div class=\"toolbar-items\" *ngIf=\"link\">\r\n <button type=\"button\" (click)=\"createLink()\" tooltip=\"Link\">\r\n <i class=\"he he-link\"></i>\r\n </button>\r\n <button type=\"button\" (click)=\"insertImage()\" tooltip=\"Image\">\r\n <i class=\"he he-image\"></i>\r\n </button>\r\n </div>\r\n <div class=\"toolbar-items\">\r\n <button type=\"button\" (click)=\"undo()\" tooltip=\"Undo\">\r\n <i class=\"he he-undo\"></i>\r\n </button>\r\n <button type=\"button\" (click)=\"redo()\" tooltip=\"Redo\">\r\n <i class=\"he he-redo\"></i>\r\n </button>\r\n </div>\r\n <div class=\"toolbar-items\">\r\n <button type=\"button\" (click)=\"clearFormatting()\" tooltip=\"Clear Formatting\">\r\n <i class=\"he he-text-clear-format\"></i>\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <div #editor class=\"editor-content\" [attr.contenteditable]=\"(readonly || disabled) ? 'false' : 'true'\" (input)=\"onInput()\" (blur)=\"onTouched()\"\r\n [attr.data-placeholder]=\"placeholder\">\r\n </div>\r\n\r\n <!-- Custom Modal for Link/Image URL -->\r\n <div class=\"editor-modal-overlay\" *ngIf=\"showModal\" (click)=\"cancelModal()\">\r\n <div class=\"editor-modal\" (click)=\"$event.stopPropagation()\">\r\n <div class=\"editor-modal-header\">\r\n <span>{{ modalType === 'link' ? 'Insert Link' : 'Insert Image' }}</span>\r\n <button type=\"button\" class=\"editor-modal-close\" (click)=\"cancelModal()\">\r\n <i class=\"he he-close\"></i>\r\n </button>\r\n </div>\r\n <div class=\"editor-modal-body\">\r\n <div class=\"url-row\" *ngFor=\"let url of modalUrls; let i = index; trackBy: trackByIndex\">\r\n <input type=\"text\" class=\"url-input\"\r\n [ngModel]=\"modalUrls[i]\"\r\n (ngModelChange)=\"modalUrls[i] = $event\"\r\n [placeholder]=\"modalType === 'link' ? 'https://example.com' : 'https://example.com/image.png'\" />\r\n <button type=\"button\" class=\"url-remove-btn\" *ngIf=\"modalUrls.length > 1\" (click)=\"removeUrlRow(i)\" title=\"Remove\">\r\n <i class=\"he he-close\"></i>\r\n </button>\r\n </div>\r\n <button type=\"button\" class=\"url-add-btn\" (click)=\"addUrlRow()\">\r\n + Add more\r\n </button>\r\n </div>\r\n <div class=\"editor-modal-footer\">\r\n <button type=\"button\" class=\"modal-btn cancel-btn\" (click)=\"cancelModal()\">Cancel</button>\r\n <button type=\"button\" class=\"modal-btn confirm-btn\" (click)=\"confirmModal()\">Insert</button>\r\n </div>\r\n </div>\r\n </div>\r\n</div>\r\n", styles: [".text-editor{border:1px solid #ccc}.text-editor .toolbar{gap:.75rem;display:flex;flex-wrap:wrap;background:#f8f8f8;padding:.75rem;border-bottom:1px solid #cccccc}.text-editor .toolbar .toolbar-items{height:18px;display:flex;flex-wrap:wrap;align-items:center;padding-right:.75rem;border-right:1px solid #969090}.text-editor .toolbar .toolbar-items button,.text-editor .toolbar .toolbar-items .input-wrap{cursor:pointer;min-width:25px;min-height:20px}.text-editor .toolbar .toolbar-items button:hover i,.text-editor .toolbar .toolbar-items .input-wrap:hover i{color:#000}.text-editor .toolbar .toolbar-items button{border:0;display:grid;place-items:center;background:transparent}.text-editor .toolbar .toolbar-items button:hover{background:#eee}.text-editor .toolbar .toolbar-items .input-wrap{gap:2px;display:flex;cursor:pointer;align-items:center;flex-direction:column;justify-content:center}.text-editor .toolbar .toolbar-items .input-wrap input[type=color]{width:80%;padding:0;height:2px;border:none;cursor:inherit}.text-editor .toolbar .toolbar-items i{font-size:13px;color:#3c4148}.text-editor .toolbar .toolbar-items i.he-bold{font-weight:600}.text-editor .toolbar .toolbar-items i.he-underline{font-size:14px}.text-editor .toolbar .toolbar-items i.he-text-drop{font-size:12px}.text-editor .toolbar .toolbar-items i.he-background-drop{top:-1px;font-size:12px}.text-editor .toolbar .toolbar-items i.he-heading-1,.text-editor .toolbar .toolbar-items i.he-link,.text-editor .toolbar .toolbar-items i.he-left-align,.text-editor .toolbar .toolbar-items i.he-center-align,.text-editor .toolbar .toolbar-items i.he-right-align,.text-editor .toolbar .toolbar-items i.he-justify{font-size:16px}.text-editor .toolbar .toolbar-items i.he-text-indent-left,.text-editor .toolbar .toolbar-items i.he-text-indent-right{font-size:17px}.text-editor .toolbar .toolbar-items i.he-heading-2{top:1px;font-size:16px}.text-editor .toolbar .toolbar-items i.he-unordered-list,.text-editor .toolbar .toolbar-items i.he-ordered-list{top:-1px;font-size:20px}.text-editor .toolbar .toolbar-items i.he-image{font-size:15px;font-weight:600}.text-editor .toolbar .toolbar-items i.he-redo,.text-editor .toolbar .toolbar-items i.he-undo{top:-1px;font-size:14px}.text-editor .toolbar .toolbar-items.more-gap{gap:5px}.text-editor .toolbar .toolbar-items:last-child{border-right:0}.text-editor .editor-content{outline:none;min-height:200px;position:relative;background:#fff;padding:.75rem}.text-editor .editor-content[data-placeholder]:empty:before{content:attr(data-placeholder);color:#aaa;pointer-events:none;position:absolute;left:.75rem;top:.75rem}.text-editor .editor-modal-overlay{position:fixed;top:0;left:0;width:100%;height:100%;background:#00000073;display:flex;align-items:center;justify-content:center;z-index:10000}.text-editor .editor-modal{background:#fff;border-radius:8px;box-shadow:0 8px 32px #0003;min-width:420px;max-width:520px;width:100%;animation:modalFadeIn .2s ease}@keyframes modalFadeIn{0%{opacity:0;transform:translateY(-10px)}to{opacity:1;transform:translateY(0)}}.text-editor .editor-modal-header{display:flex;align-items:center;justify-content:space-between;padding:14px 18px;border-bottom:1px solid #e8e8e8}.text-editor .editor-modal-header span{font-size:15px;font-weight:600;color:#1a1a1a}.text-editor .editor-modal-close{background:none;border:none;cursor:pointer;padding:4px;border-radius:4px;display:grid;place-items:center}.text-editor .editor-modal-close i{font-size:14px;color:#666}.text-editor .editor-modal-close:hover{background:#f0f0f0}.text-editor .editor-modal-close:hover i{color:#333}.text-editor .editor-modal-body{padding:16px 18px}.text-editor .editor-modal-body .url-row{display:flex;align-items:center;gap:8px;margin-bottom:10px}.text-editor .editor-modal-body .url-input{flex:1;padding:8px 12px;border:1px solid #d0d0d0;border-radius:6px;font-size:13px;color:#333;outline:none;transition:border-color .2s}.text-editor .editor-modal-body .url-input:focus{border-color:#007bff;box-shadow:0 0 0 2px #007bff26}.text-editor .editor-modal-body .url-input::placeholder{color:#aaa}.text-editor .editor-modal-body .url-remove-btn{background:none;border:1px solid #e0e0e0;border-radius:6px;cursor:pointer;padding:6px 8px;display:grid;place-items:center;transition:all .15s}.text-editor .editor-modal-body .url-remove-btn i{font-size:11px;color:#999}.text-editor .editor-modal-body .url-remove-btn:hover{background:#fff0f0;border-color:#faa}.text-editor .editor-modal-body .url-remove-btn:hover i{color:#e04040}.text-editor .editor-modal-body .url-add-btn{background:none;border:1px dashed #c0c0c0;border-radius:6px;cursor:pointer;padding:6px 14px;font-size:12px;color:#007bff;transition:all .15s;width:100%}.text-editor .editor-modal-body .url-add-btn:hover{background:#f0f8ff;border-color:#007bff}.text-editor .editor-modal-footer{display:flex;justify-content:flex-end;gap:10px;padding:12px 18px;border-top:1px solid #e8e8e8}.text-editor .editor-modal-footer .modal-btn{padding:7px 20px;border-radius:6px;font-size:13px;font-weight:500;cursor:pointer;transition:all .15s;border:1px solid transparent}.text-editor .editor-modal-footer .cancel-btn{background:#f5f5f5;color:#555;border-color:#ddd}.text-editor .editor-modal-footer .cancel-btn:hover{background:#eaeaea}.text-editor .editor-modal-footer .confirm-btn{background:#007bff;color:#fff}.text-editor .editor-modal-footer .confirm-btn:hover{background:#0069d9}\n"] }]
3234
+ ], template: "<div class=\"text-editor\" [ngClass]=\"{'readonly': readonly || disabled}\">\n <div class=\"toolbar\" *ngIf=\"!readonly && !disabled\">\n <div class=\"toolbar-items\">\n <button type=\"button\" (mousedown)=\"$event.preventDefault()\" (click)=\"applyInlineStyle('bold')\" title=\"Bold\">\n <i class=\"he he-bold\"></i>\n </button>\n <button type=\"button\" (mousedown)=\"$event.preventDefault()\" (click)=\"applyInlineStyle('italic')\" title=\"Italic\">\n <i class=\"he he-italics\"></i>\n </button>\n <button type=\"button\" (mousedown)=\"$event.preventDefault()\" (click)=\"applyInlineStyle('underline')\" title=\"Underline\">\n <i class=\"he he-underline\"></i>\n </button>\n </div>\n <div class=\"toolbar-items\" *ngIf=\"header\">\n <button type=\"button\" (mousedown)=\"$event.preventDefault()\" (click)=\"applyBlockFormat('h1')\" title=\"Header 1\">\n <i class=\"he he-heading-1\"></i>\n </button>\n <button type=\"button\" (mousedown)=\"$event.preventDefault()\" (click)=\"applyBlockFormat('h2')\" title=\"Header 2\">\n <i class=\"he he-heading-2\"></i>\n </button>\n </div>\n <div class=\"toolbar-items more-gap\">\n <div class=\"input-wrap\" title=\"Text Color\" (mousedown)=\"$event.preventDefault()\">\n <i class=\"he he-text-drop\"></i>\n <input type=\"color\" (input)=\"applyColor($event)\" />\n </div>\n <div class=\"input-wrap\" title=\"Background Color\" (mousedown)=\"$event.preventDefault()\">\n <i class=\"he he-background-drop\"></i>\n <input type=\"color\" (input)=\"applyHighlight($event)\" />\n </div>\n </div>\n <div class=\"toolbar-items\">\n <button type=\"button\" (mousedown)=\"$event.preventDefault()\" (click)=\"setAlignment('left')\" title=\"Justify Left\">\n <i class=\"he he-left-align\"></i>\n </button>\n <button type=\"button\" (mousedown)=\"$event.preventDefault()\" (click)=\"setAlignment('center')\" title=\"Justify Center\">\n <i class=\"he he-center-align\"></i>\n </button>\n <button type=\"button\" (mousedown)=\"$event.preventDefault()\" (click)=\"setAlignment('right')\" title=\"Justify Right\">\n <i class=\"he he-right-align\"></i>\n </button>\n <button type=\"button\" (mousedown)=\"$event.preventDefault()\" (click)=\"setAlignment('justify')\" title=\"Justify Full\">\n <i class=\"he he-justify\"></i>\n </button>\n </div>\n <div class=\"toolbar-items\">\n <button type=\"button\" (mousedown)=\"$event.preventDefault()\" (click)=\"indent()\" title=\"Indent\">\n <i class=\"he he-text-indent-left\"></i>\n </button>\n <button type=\"button\" (mousedown)=\"$event.preventDefault()\" (click)=\"outdent()\" title=\"Outdent\">\n <i class=\"he he-text-indent-right\"></i>\n </button>\n </div>\n <div class=\"toolbar-items\" *ngIf=\"media\">\n <button type=\"button\" (mousedown)=\"$event.preventDefault()\" (click)=\"applyList('ul')\" title=\"Unordered list\">\n <i class=\"he he-unordered-list\"></i>\n </button>\n <button type=\"button\" (mousedown)=\"$event.preventDefault()\" (click)=\"applyList('ol')\" title=\"Ordered list\">\n <i class=\"he he-ordered-list\"></i>\n </button>\n </div>\n <div class=\"toolbar-items\" *ngIf=\"link\">\n <button type=\"button\" (mousedown)=\"$event.preventDefault()\" (click)=\"createLink()\" title=\"Link\">\n <i class=\"he he-link\"></i>\n </button>\n <button type=\"button\" (mousedown)=\"$event.preventDefault()\" (click)=\"insertImage()\" title=\"Image\">\n <i class=\"he he-image\"></i>\n </button>\n </div>\n <div class=\"toolbar-items\">\n <button type=\"button\" (mousedown)=\"$event.preventDefault()\" (click)=\"undo()\" title=\"Undo\">\n <i class=\"he he-undo\"></i>\n </button>\n <button type=\"button\" (mousedown)=\"$event.preventDefault()\" (click)=\"redo()\" title=\"Redo\">\n <i class=\"he he-redo\"></i>\n </button>\n </div>\n <div class=\"toolbar-items\">\n <button type=\"button\" (mousedown)=\"$event.preventDefault()\" (click)=\"clearFormatting()\" title=\"Clear Formatting\">\n <i class=\"he he-text-clear-format\"></i>\n </button>\n </div>\n </div>\n\n <div #editor class=\"editor-content\" [attr.contenteditable]=\"(readonly || disabled) ? 'false' : 'true'\" (input)=\"onInput()\" (blur)=\"onTouched()\"\n [attr.data-placeholder]=\"placeholder\">\n </div>\n\n <!-- Custom Modal for Link/Image URL -->\n <div class=\"editor-modal-overlay\" *ngIf=\"showModal\" (click)=\"cancelModal()\">\n <div class=\"editor-modal\" (click)=\"$event.stopPropagation()\">\n <div class=\"editor-modal-header\">\n <span>{{ modalType === 'link' ? 'Insert Link' : 'Insert Image' }}</span>\n <button type=\"button\" class=\"editor-modal-close\" (click)=\"cancelModal()\">\n <i class=\"he he-close\"></i>\n </button>\n </div>\n <div class=\"editor-modal-body\">\n <div class=\"url-row\" *ngFor=\"let url of modalUrls; let i = index; trackBy: trackByIndex\">\n <input type=\"text\" class=\"url-input\"\n [ngModel]=\"modalUrls[i]\"\n (ngModelChange)=\"modalUrls[i] = $event\"\n [placeholder]=\"modalType === 'link' ? 'https://example.com' : 'https://example.com/image.png'\" />\n <button type=\"button\" class=\"url-remove-btn\" *ngIf=\"modalUrls.length > 1\" (click)=\"removeUrlRow(i)\" title=\"Remove\">\n <i class=\"he he-close\"></i>\n </button>\n </div>\n <button type=\"button\" class=\"url-add-btn\" (click)=\"addUrlRow()\">\n + Add more\n </button>\n </div>\n <div class=\"editor-modal-footer\">\n <button type=\"button\" class=\"modal-btn cancel-btn\" (click)=\"cancelModal()\">Cancel</button>\n <button type=\"button\" class=\"modal-btn confirm-btn\" (click)=\"confirmModal()\">Insert</button>\n </div>\n </div>\n </div>\n</div>\n", styles: [".text-editor{border:1px solid #ccc}.text-editor .toolbar{gap:.75rem;display:flex;flex-wrap:wrap;background:#f8f8f8;padding:.75rem;border-bottom:1px solid #cccccc}.text-editor .toolbar .toolbar-items{height:18px;display:flex;flex-wrap:wrap;align-items:center;padding-right:.75rem;border-right:1px solid #969090}.text-editor .toolbar .toolbar-items button,.text-editor .toolbar .toolbar-items .input-wrap{cursor:pointer;min-width:25px;min-height:20px}.text-editor .toolbar .toolbar-items button:hover i,.text-editor .toolbar .toolbar-items .input-wrap:hover i{color:#000}.text-editor .toolbar .toolbar-items button{border:0;display:grid;place-items:center;background:transparent}.text-editor .toolbar .toolbar-items button:hover{background:#eee}.text-editor .toolbar .toolbar-items .input-wrap{gap:2px;display:flex;cursor:pointer;align-items:center;flex-direction:column;justify-content:center}.text-editor .toolbar .toolbar-items .input-wrap input[type=color]{width:80%;padding:0;height:2px;border:none;cursor:inherit}.text-editor .toolbar .toolbar-items i{font-size:13px;color:#3c4148}.text-editor .toolbar .toolbar-items i.he-bold{font-weight:600}.text-editor .toolbar .toolbar-items i.he-underline{font-size:14px}.text-editor .toolbar .toolbar-items i.he-text-drop{font-size:12px}.text-editor .toolbar .toolbar-items i.he-background-drop{top:-1px;font-size:12px}.text-editor .toolbar .toolbar-items i.he-heading-1,.text-editor .toolbar .toolbar-items i.he-link,.text-editor .toolbar .toolbar-items i.he-left-align,.text-editor .toolbar .toolbar-items i.he-center-align,.text-editor .toolbar .toolbar-items i.he-right-align,.text-editor .toolbar .toolbar-items i.he-justify{font-size:16px}.text-editor .toolbar .toolbar-items i.he-text-indent-left,.text-editor .toolbar .toolbar-items i.he-text-indent-right{font-size:17px}.text-editor .toolbar .toolbar-items i.he-heading-2{top:1px;font-size:16px}.text-editor .toolbar .toolbar-items i.he-unordered-list,.text-editor .toolbar .toolbar-items i.he-ordered-list{top:-1px;font-size:20px}.text-editor .toolbar .toolbar-items i.he-image{font-size:15px;font-weight:600}.text-editor .toolbar .toolbar-items i.he-redo,.text-editor .toolbar .toolbar-items i.he-undo{top:-1px;font-size:14px}.text-editor .toolbar .toolbar-items.more-gap{gap:5px}.text-editor .toolbar .toolbar-items:last-child{border-right:0}.text-editor .editor-content{outline:none;min-height:200px;position:relative;background:#fff;padding:.75rem}.text-editor .editor-content[data-placeholder]:empty:before{content:attr(data-placeholder);color:#aaa;pointer-events:none;position:absolute;left:.75rem;top:.75rem}.text-editor .editor-modal-overlay{position:fixed;top:0;left:0;width:100%;height:100%;background:#00000073;display:flex;align-items:center;justify-content:center;z-index:10000}.text-editor .editor-modal{background:#fff;border-radius:8px;box-shadow:0 8px 32px #0003;width:420px;max-width:90vw;animation:modalFadeIn .2s ease}@keyframes modalFadeIn{0%{opacity:0;transform:translateY(-10px)}to{opacity:1;transform:translateY(0)}}.text-editor .editor-modal-header{display:flex;align-items:center;justify-content:space-between;padding:14px 18px;border-bottom:1px solid #e8e8e8}.text-editor .editor-modal-header span{font-size:15px;font-weight:600;color:#1a1a1a}.text-editor .editor-modal-close{background:none;border:none;cursor:pointer;padding:4px;border-radius:4px;display:grid;place-items:center}.text-editor .editor-modal-close i{font-size:14px;color:#666}.text-editor .editor-modal-close:hover{background:#f0f0f0}.text-editor .editor-modal-close:hover i{color:#333}.text-editor .editor-modal-body{padding:16px 18px}.text-editor .editor-modal-body .url-row{display:flex;align-items:center;gap:8px;margin-bottom:10px}.text-editor .editor-modal-body .url-input{flex:1;padding:8px 12px;border:1px solid #d0d0d0;border-radius:6px;font-size:13px;color:#333;outline:none;transition:border-color .2s}.text-editor .editor-modal-body .url-input:focus{border-color:#007bff;box-shadow:0 0 0 2px #007bff26}.text-editor .editor-modal-body .url-input::placeholder{color:#aaa}.text-editor .editor-modal-body .url-remove-btn{background:none;border:1px solid #e0e0e0;border-radius:6px;cursor:pointer;padding:6px 8px;display:grid;place-items:center;transition:all .15s}.text-editor .editor-modal-body .url-remove-btn i{font-size:11px;color:#999}.text-editor .editor-modal-body .url-remove-btn:hover{background:#fff0f0;border-color:#faa}.text-editor .editor-modal-body .url-remove-btn:hover i{color:#e04040}.text-editor .editor-modal-body .url-add-btn{background:none;border:1px dashed #c0c0c0;border-radius:6px;cursor:pointer;padding:6px 14px;font-size:12px;color:#007bff;transition:all .15s;width:100%}.text-editor .editor-modal-body .url-add-btn:hover{background:#f0f8ff;border-color:#007bff}.text-editor .editor-modal-footer{display:flex;justify-content:flex-end;gap:10px;padding:12px 18px;border-top:1px solid #e8e8e8}.text-editor .editor-modal-footer .modal-btn{padding:7px 20px;border-radius:6px;font-size:13px;font-weight:500;cursor:pointer;transition:all .15s;border:1px solid transparent}.text-editor .editor-modal-footer .cancel-btn{background:#f5f5f5;color:#555;border-color:#ddd}.text-editor .editor-modal-footer .cancel-btn:hover{background:#eaeaea}.text-editor .editor-modal-footer .confirm-btn{background:#007bff;color:#fff}.text-editor .editor-modal-footer .confirm-btn:hover{background:#0069d9}\n"] }]
2911
3235
  }], propDecorators: { header: [{
2912
3236
  type: Input
2913
3237
  }], media: [{
@@ -3038,5 +3362,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.3", ngImpor
3038
3362
  * Generated bundle index. Do not edit.
3039
3363
  */
3040
3364
 
3041
- export { AutocompleteControl, CalendarControl, CheckboxControl, InputControl, MultiselectControl, SelectControl, SwitchControl, TextEditor, TextareaControl };
3365
+ export { AutocompleteControl, CalendarControl, CheckboxControl, ColorPicker, InputControl, MultiselectControl, SelectControl, SwitchControl, TextEditor, TextareaControl };
3042
3366
  //# sourceMappingURL=nexheal-lib.mjs.map