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.
- package/fesm2022/nexheal-lib.mjs +355 -31
- package/fesm2022/nexheal-lib.mjs.map +1 -1
- package/index.d.ts +69 -1
- package/package.json +1 -1
package/fesm2022/nexheal-lib.mjs
CHANGED
|
@@ -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
|