nexheal-lib 0.0.11 → 0.0.12

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.
@@ -28,28 +28,12 @@ class AutocompleteControl {
28
28
  addNewItemClicked = new EventEmitter();
29
29
  blurEvent = new EventEmitter();
30
30
  optionPatched = new EventEmitter();
31
- loadAllOnOpen = false;
32
31
  readonly = false;
33
32
  _disabled = false;
34
33
  _options = [];
35
34
  set options(value) {
36
35
  this._options = value || [];
37
36
  this.processValueBuffer();
38
- if (this.hasFocus && this.isDropdownOpen) {
39
- const val = this.inputControl.value || "";
40
- if (val === "" && this.loadAllOnOpen) {
41
- this.filteredSuggestions = [...this._options];
42
- }
43
- else if (val !== "") {
44
- const filterValue = val.toString().toLowerCase();
45
- this.filteredSuggestions = this._options.filter((suggestion) => suggestion[this.optionDisplayProperty]?.toLowerCase().includes(filterValue));
46
- }
47
- this.highlightedIndex = this.filteredSuggestions.length > 0 ? 0 : null;
48
- setTimeout(() => {
49
- if (this.popperInstance)
50
- this.popperInstance.update();
51
- }, 0);
52
- }
53
37
  }
54
38
  get options() {
55
39
  return this._options;
@@ -96,13 +80,7 @@ class AutocompleteControl {
96
80
  this.search.emit(filterValue);
97
81
  }
98
82
  else {
99
- if (this.loadAllOnOpen && this.hasFocus) {
100
- this.filterSuggestions("");
101
- this.search.emit("");
102
- }
103
- else {
104
- this.isDropdownOpen = false;
105
- }
83
+ this.isDropdownOpen = false;
106
84
  }
107
85
  });
108
86
  }
@@ -175,18 +153,8 @@ class AutocompleteControl {
175
153
  return;
176
154
  }
177
155
  if (value === "") {
178
- if (this.loadAllOnOpen) {
179
- this.filteredSuggestions = [...this.options];
180
- this.highlightedIndex = this.filteredSuggestions.length > 0 ? 0 : null;
181
- this.isDropdownOpen = true;
182
- setTimeout(() => {
183
- this.createPopperInstance();
184
- }, 0);
185
- }
186
- else {
187
- this.filteredSuggestions = [];
188
- this.isDropdownOpen = false;
189
- }
156
+ this.filteredSuggestions = [];
157
+ this.isDropdownOpen = false;
190
158
  return;
191
159
  }
192
160
  const filterValue = value.toString().toLowerCase();
@@ -216,13 +184,6 @@ class AutocompleteControl {
216
184
  // events
217
185
  onFocus() {
218
186
  this.hasFocus = true;
219
- if (this.readonly)
220
- return;
221
- if (this.loadAllOnOpen) {
222
- const val = this.inputControl.value || "";
223
- this.filterSuggestions(val);
224
- this.search.emit(val);
225
- }
226
187
  }
227
188
  onBlur() {
228
189
  this.blurEvent.emit();
@@ -343,7 +304,7 @@ class AutocompleteControl {
343
304
  this.optionSelected.emit(this.selectedItems);
344
305
  }
345
306
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.3", ngImport: i0, type: AutocompleteControl, deps: [], target: i0.ɵɵFactoryTarget.Component });
346
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.3", type: AutocompleteControl, isStandalone: true, selector: "autocomplete-control", inputs: { title: "title", required: "required", placeholder: "placeholder", customClass: "customClass", clearVal: "clearVal", field: "field", error: "error", errorMessage: "errorMessage", autocomplete: "autocomplete", inputLoader: "inputLoader", isAddNewItem: "isAddNewItem", optionDisplayProperty: "optionDisplayProperty", loadAllOnOpen: "loadAllOnOpen", readonly: "readonly", options: "options", disabled: "disabled" }, outputs: { optionSelected: "optionSelected", search: "search", selectionCleared: "selectionCleared", addNewItemClicked: "addNewItemClicked", blurEvent: "blurEvent", optionPatched: "optionPatched" }, providers: [
307
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.3", type: AutocompleteControl, isStandalone: true, selector: "autocomplete-control", inputs: { title: "title", required: "required", placeholder: "placeholder", customClass: "customClass", clearVal: "clearVal", field: "field", error: "error", errorMessage: "errorMessage", autocomplete: "autocomplete", inputLoader: "inputLoader", isAddNewItem: "isAddNewItem", optionDisplayProperty: "optionDisplayProperty", readonly: "readonly", options: "options", disabled: "disabled" }, outputs: { optionSelected: "optionSelected", search: "search", selectionCleared: "selectionCleared", addNewItemClicked: "addNewItemClicked", blurEvent: "blurEvent", optionPatched: "optionPatched" }, providers: [
347
308
  {
348
309
  provide: NG_VALUE_ACCESSOR,
349
310
  useExisting: AutocompleteControl,
@@ -396,8 +357,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.3", ngImpor
396
357
  type: Output
397
358
  }], optionPatched: [{
398
359
  type: Output
399
- }], loadAllOnOpen: [{
400
- type: Input
401
360
  }], readonly: [{
402
361
  type: Input
403
362
  }], options: [{
@@ -427,7 +386,21 @@ class CalendarControl {
427
386
  timeOnly = false;
428
387
  dateFormat = "dd/MM/yyyy";
429
388
  placeholder = "dd-mm-yyyy";
430
- disabled = false;
389
+ _disabled = false;
390
+ get disabled() {
391
+ return this._disabled;
392
+ }
393
+ set disabled(value) {
394
+ this._disabled = value;
395
+ if (this.inputControl) {
396
+ if (value) {
397
+ this.inputControl.disable({ emitEvent: false });
398
+ }
399
+ else {
400
+ this.inputControl.enable({ emitEvent: false });
401
+ }
402
+ }
403
+ }
431
404
  readonly = false;
432
405
  submitted = false;
433
406
  inputPlaceholder = false;
@@ -2499,24 +2472,41 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.3", ngImpor
2499
2472
  args: ['switchContainer']
2500
2473
  }] } });
2501
2474
 
2475
+ /**
2476
+ * Lightweight rich-text editor built on a `contenteditable` element and the
2477
+ * browser's `document.execCommand` rich-editing API (the de-facto standard for
2478
+ * simple in-browser editors).
2479
+ *
2480
+ * Implemented as a `ControlValueAccessor`, so it works with `[(ngModel)]`,
2481
+ * `formControlName` and `[formControl]`. The emitted value is the editor's
2482
+ * inner HTML string.
2483
+ */
2502
2484
  class TextEditor {
2503
2485
  header = true;
2504
2486
  media = true;
2505
2487
  link = true;
2506
2488
  placeholder = 'Type here...';
2507
2489
  readonly = false;
2490
+ /** Disabled state, set by Reactive Forms through `setDisabledState`. */
2491
+ disabled = false;
2508
2492
  editorRef;
2509
2493
  onChange = () => { };
2510
2494
  onTouch = () => { };
2511
- undoStack = [];
2512
- redoStack = [];
2513
- ngOnInit() { }
2495
+ /** HTML received via `writeValue` before the view (and `editorRef`) is ready. */
2496
+ pendingValue = '';
2497
+ viewInitialized = false;
2498
+ /** Last selection range observed inside the editor (restored before commands). */
2499
+ savedRange = null;
2514
2500
  ngAfterViewInit() {
2515
- this.saveState();
2501
+ this.viewInitialized = true;
2502
+ this.editorRef.nativeElement.innerHTML = this.pendingValue;
2516
2503
  }
2504
+ // ---- ControlValueAccessor ----
2517
2505
  writeValue(value) {
2518
- this.editorRef.nativeElement.innerHTML = value || '';
2519
- this.saveState();
2506
+ this.pendingValue = value ?? '';
2507
+ if (this.viewInitialized && this.editorRef) {
2508
+ this.editorRef.nativeElement.innerHTML = this.pendingValue;
2509
+ }
2520
2510
  }
2521
2511
  registerOnChange(fn) {
2522
2512
  this.onChange = fn;
@@ -2524,256 +2514,126 @@ class TextEditor {
2524
2514
  registerOnTouched(fn) {
2525
2515
  this.onTouch = fn;
2526
2516
  }
2517
+ setDisabledState(isDisabled) {
2518
+ this.disabled = isDisabled;
2519
+ }
2520
+ // ---- Editor events (wired from the template) ----
2527
2521
  onInput() {
2528
- const html = this.editorRef.nativeElement.innerHTML;
2529
- this.onChange(html);
2530
- this.saveState();
2522
+ this.onChange(this.editorRef.nativeElement.innerHTML);
2531
2523
  }
2532
- // events
2533
2524
  onTouched() {
2534
2525
  this.onTouch();
2535
2526
  }
2536
- setDisabledState(isDisabled) {
2537
- this.editorRef.nativeElement.contentEditable = (!isDisabled).toString();
2538
- }
2539
- // ---- Selection & Range Utilities ----
2540
- getSelectionRange() {
2527
+ /** Remember the caret/selection whenever it sits inside the editor. */
2528
+ saveSelection() {
2541
2529
  const selection = window.getSelection();
2542
- if (selection && selection.rangeCount > 0) {
2543
- return selection.getRangeAt(0);
2544
- }
2545
- return null;
2546
- }
2547
- wrapSelection(htmlTag, style) {
2548
- const range = this.getSelectionRange();
2549
- if (!range || range.collapsed)
2550
- return; // no selection
2551
- const selectedText = range.extractContents();
2552
- const el = document.createElement(htmlTag);
2553
- if (style) {
2554
- el.setAttribute('style', style);
2555
- }
2556
- el.appendChild(selectedText);
2557
- range.insertNode(el);
2558
- this.mergeAdjacentSimilarElements(el);
2559
- this.onInput();
2560
- }
2561
- // Merges adjacent spans with the same style to avoid clutter
2562
- mergeAdjacentSimilarElements(el) {
2563
- const parent = el.parentElement;
2564
- if (!parent)
2530
+ if (!selection || selection.rangeCount === 0 || !this.editorRef)
2565
2531
  return;
2566
- const siblings = Array.from(parent.childNodes);
2567
- for (let i = 0; i < siblings.length - 1; i++) {
2568
- const current = siblings[i];
2569
- const next = siblings[i + 1];
2570
- if (current.nodeType === 1 && next?.nodeType === 1) {
2571
- if (current.tagName === next.tagName && current.getAttribute('style') === next.getAttribute('style')) {
2572
- // merge them
2573
- while (next.firstChild) {
2574
- current.appendChild(next.firstChild);
2575
- }
2576
- next.remove();
2577
- }
2578
- }
2532
+ const range = selection.getRangeAt(0);
2533
+ if (this.editorRef.nativeElement.contains(range.commonAncestorContainer)) {
2534
+ this.savedRange = range.cloneRange();
2579
2535
  }
2580
2536
  }
2581
- // ---- Inline Formatting ----
2582
- // applyInlineStyle() toggles inline styles by wrapping selection in a styled span
2583
- applyInlineStyle(styleType) {
2584
- let style = '';
2585
- if (styleType === 'bold')
2586
- style = 'font-weight:bold;';
2587
- else if (styleType === 'italic')
2588
- style = 'font-style:italic;';
2589
- else if (styleType === 'underline')
2590
- style = 'text-decoration:underline;';
2591
- this.wrapSelection('span', style);
2537
+ // ---- Inline formatting ----
2538
+ applyInlineStyle(style) {
2539
+ this.exec(style);
2592
2540
  }
2593
- applyColor(event) {
2594
- const input = event.target;
2595
- const color = input.value;
2596
- // Now `color` is a string and `input` is never null
2597
- this.wrapSelection('span', `color:${color};`);
2541
+ // ---- Block formatting (headings / paragraph) ----
2542
+ applyBlockFormat(block) {
2543
+ this.exec('formatBlock', `<${block}>`);
2598
2544
  }
2599
- applyHighlight(event) {
2600
- const input = event.target;
2601
- const color = input.value;
2602
- this.wrapSelection('span', `background-color:${color};`);
2603
- }
2604
- // ---- Block Formatting (Headings, Paragraph) ----
2605
- // Replaces the parent block element containing selection with a new block type
2606
- applyBlockFormat(blockTag) {
2607
- const range = this.getSelectionRange();
2608
- if (!range)
2609
- return;
2610
- // Find the nearest block element
2611
- let block = this.findBlockAncestor(range.commonAncestorContainer);
2612
- if (!block) {
2613
- // If no block found, wrap the selection in a block
2614
- const wrapper = document.createElement(blockTag);
2615
- wrapper.appendChild(range.extractContents());
2616
- range.insertNode(wrapper);
2617
- }
2618
- else {
2619
- // Replace the block with a new block type
2620
- const newBlock = document.createElement(blockTag);
2621
- // Move children
2622
- while (block.firstChild) {
2623
- newBlock.appendChild(block.firstChild);
2624
- }
2625
- block.replaceWith(newBlock);
2626
- }
2627
- this.onInput();
2545
+ // ---- Lists ----
2546
+ applyList(listType) {
2547
+ this.exec(listType === 'ul' ? 'insertUnorderedList' : 'insertOrderedList');
2628
2548
  }
2629
- findBlockAncestor(node) {
2630
- while (node && node !== this.editorRef.nativeElement) {
2631
- if (this.isBlockElement(node)) {
2632
- return node;
2633
- }
2634
- node = node.parentNode;
2635
- }
2636
- return null;
2549
+ // ---- Indentation ----
2550
+ indent() {
2551
+ this.exec('indent');
2637
2552
  }
2638
- isBlockElement(node) {
2639
- if (node.nodeType !== 1)
2640
- return false;
2641
- const display = window.getComputedStyle(node).display;
2642
- return display === 'block' || display === 'list-item';
2553
+ outdent() {
2554
+ this.exec('outdent');
2643
2555
  }
2644
- // ---- Lists ----
2645
- // Convert selected lines into a list
2646
- applyList(listType) {
2647
- const range = this.getSelectionRange();
2648
- if (!range)
2649
- return;
2650
- const commonBlock = this.findBlockAncestor(range.commonAncestorContainer);
2651
- // Get the text in the selection
2652
- const content = range.extractContents();
2653
- const lines = this.splitContentByLine(content);
2654
- const listEl = document.createElement(listType);
2655
- for (const line of lines) {
2656
- const li = document.createElement('li');
2657
- li.appendChild(line);
2658
- listEl.appendChild(li);
2659
- }
2660
- if (commonBlock) {
2661
- // Insert the list right where the block was or at the selection
2662
- range.insertNode(listEl);
2663
- }
2664
- else {
2665
- // If no common block, just insert at current position
2666
- range.insertNode(listEl);
2667
- }
2668
- this.onInput();
2556
+ // ---- Alignment ----
2557
+ setAlignment(alignment) {
2558
+ const command = {
2559
+ left: 'justifyLeft',
2560
+ center: 'justifyCenter',
2561
+ right: 'justifyRight',
2562
+ justify: 'justifyFull',
2563
+ }[alignment];
2564
+ this.exec(command);
2565
+ }
2566
+ // ---- Color / highlight ----
2567
+ applyColor(event) {
2568
+ this.exec('foreColor', event.target.value, true);
2669
2569
  }
2670
- splitContentByLine(fragment) {
2671
- // A very naive approach: split by <br> or block elements.
2672
- // For advanced logic, detect line breaks more thoroughly.
2673
- const lines = [];
2674
- let currentFrag = document.createDocumentFragment();
2675
- Array.from(fragment.childNodes).forEach((node) => {
2676
- if (node.nodeName === 'BR' || this.isBlockElement(node)) {
2677
- // This node signifies a new line
2678
- lines.push(currentFrag);
2679
- currentFrag = document.createDocumentFragment();
2680
- if (this.isBlockElement(node)) {
2681
- while (node.firstChild) {
2682
- currentFrag.appendChild(node.firstChild);
2683
- }
2684
- lines.push(currentFrag);
2685
- currentFrag = document.createDocumentFragment();
2686
- }
2687
- }
2688
- else {
2689
- currentFrag.appendChild(node);
2690
- }
2691
- });
2692
- if (currentFrag.childNodes.length > 0) {
2693
- lines.push(currentFrag);
2694
- }
2695
- return lines;
2570
+ applyHighlight(event) {
2571
+ this.exec('hiliteColor', event.target.value, true);
2696
2572
  }
2697
- // ---- Links ----
2573
+ // ---- Links / images ----
2698
2574
  createLink() {
2699
2575
  const url = prompt('Enter URL', 'https://');
2700
2576
  if (!url)
2701
2577
  return;
2702
- const range = this.getSelectionRange();
2703
- if (!range || range.collapsed)
2704
- return;
2705
- const selectedContent = range.extractContents();
2706
- const a = document.createElement('a');
2707
- a.href = url;
2708
- a.appendChild(selectedContent);
2709
- range.insertNode(a);
2710
- this.onInput();
2578
+ this.exec('createLink', url);
2711
2579
  }
2712
- // ---- Images ----
2713
2580
  insertImage() {
2714
2581
  const url = prompt('Enter image URL:');
2715
2582
  if (!url)
2716
2583
  return;
2717
- const range = this.getSelectionRange();
2718
- if (!range)
2719
- return;
2720
- const img = document.createElement('img');
2721
- img.src = url;
2722
- range.insertNode(img);
2723
- this.onInput();
2584
+ this.exec('insertImage', url);
2724
2585
  }
2725
- // ---- Alignment ----
2726
- setAlignment(alignment) {
2727
- // Find the block and set text-align
2728
- const range = this.getSelectionRange();
2729
- if (!range)
2730
- return;
2731
- const block = this.findBlockAncestor(range.commonAncestorContainer);
2732
- if (block) {
2733
- block.style.textAlign = alignment;
2734
- this.onInput();
2735
- }
2586
+ // ---- Undo / redo / clear ----
2587
+ undo() {
2588
+ this.exec('undo');
2736
2589
  }
2737
- // ---- Clear Formatting ----
2738
- clearFormatting() {
2739
- const html = this.editorRef.nativeElement.innerText;
2740
- // Convert innerText to a plain <p> block for simplicity
2741
- this.editorRef.nativeElement.innerHTML = `<p>${html}</p>`;
2742
- this.onInput();
2590
+ redo() {
2591
+ this.exec('redo');
2743
2592
  }
2744
- // ---- Undo/Redo ----
2745
- saveState() {
2746
- const currentHtml = this.editorRef.nativeElement.innerHTML;
2747
- if (this.undoStack.length === 0 || this.undoStack[this.undoStack.length - 1].html !== currentHtml) {
2748
- this.undoStack.push({ html: currentHtml });
2749
- this.redoStack = []; // clear redo on new input
2750
- }
2593
+ clearFormatting() {
2594
+ this.exec('removeFormat');
2751
2595
  }
2752
- // clear options
2753
- undo() {
2754
- if (this.undoStack.length > 1) {
2755
- const current = this.undoStack.pop();
2756
- this.redoStack.push(current);
2757
- const previous = this.undoStack[this.undoStack.length - 1];
2758
- this.editorRef.nativeElement.innerHTML = previous.html;
2759
- this.onChange(previous.html);
2760
- }
2596
+ /**
2597
+ * Focus the editor, restore the last selection, run a rich-text command and
2598
+ * propagate the resulting HTML. No-op while readonly/disabled.
2599
+ */
2600
+ exec(command, value, useCss = false) {
2601
+ if (this.disabled || this.readonly)
2602
+ return;
2603
+ this.editorRef.nativeElement.focus();
2604
+ this.restoreSelection();
2605
+ // `useCss` keeps colors as inline styles; semantic tags (<b>, <i>…) otherwise.
2606
+ document.execCommand('styleWithCSS', false, String(useCss));
2607
+ document.execCommand(command, false, value);
2608
+ this.onInput();
2761
2609
  }
2762
- redo() {
2763
- if (this.redoStack.length > 0) {
2764
- const state = this.redoStack.pop();
2765
- this.undoStack.push(state);
2766
- this.editorRef.nativeElement.innerHTML = state.html;
2767
- this.onChange(state.html);
2768
- }
2610
+ restoreSelection() {
2611
+ if (!this.savedRange)
2612
+ return;
2613
+ const selection = window.getSelection();
2614
+ if (!selection)
2615
+ return;
2616
+ selection.removeAllRanges();
2617
+ selection.addRange(this.savedRange);
2769
2618
  }
2770
2619
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.3", ngImport: i0, type: TextEditor, deps: [], target: i0.ɵɵFactoryTarget.Component });
2771
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.3", type: TextEditor, isStandalone: true, selector: "app-text-editor", inputs: { header: "header", media: "media", link: "link", placeholder: "placeholder", readonly: "readonly" }, viewQueries: [{ propertyName: "editorRef", first: true, predicate: ["editor"], descendants: true }], ngImport: i0, template: "<div class=\"text-editor\" [ngClass]=\"{'readonly': readonly}\">\r\n <div class=\"toolbar\" *ngIf=\"!readonly\">\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\" tooltip=\"Indent\">\r\n <i class=\"he he-text-indent-left\"></i>\r\n </button>\r\n <button type=\"button\" 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 ? 'false' : 'true'\" (input)=\"onInput()\" (blur)=\"onTouched()\"\r\n [attr.data-placeholder]=\"placeholder\">\r\n </div>\r\n</div>", 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}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] });
2620
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.3", type: TextEditor, isStandalone: true, selector: "app-text-editor", inputs: { header: "header", media: "media", link: "link", placeholder: "placeholder", readonly: "readonly" }, host: { listeners: { "document:selectionchange": "saveSelection()" } }, providers: [
2621
+ {
2622
+ provide: NG_VALUE_ACCESSOR,
2623
+ useExisting: forwardRef(() => TextEditor),
2624
+ multi: true,
2625
+ },
2626
+ ], 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\" (click)=\"applyInlineStyle('bold')\" tooltip=\"Bold\">\n <i class=\"he he-bold\"></i>\n </button>\n <button type=\"button\" (click)=\"applyInlineStyle('italic')\" tooltip=\"italic\">\n <i class=\"he he-italics\"></i>\n </button>\n <button type=\"button\" (click)=\"applyInlineStyle('underline')\" tooltip=\"Underline\">\n <i class=\"he he-underline\"></i>\n </button>\n </div>\n <div class=\"toolbar-items\" *ngIf=\"header\">\n <button type=\"button\" (click)=\"applyBlockFormat('h1')\" tooltip=\"Header 1\">\n <i class=\"he he-heading-1\"></i>\n </button>\n <button type=\"button\" (click)=\"applyBlockFormat('h2')\" tooltip=\"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\" tooltip=\"Text Color\">\n <i class=\"he he-text-drop\"></i>\n <input type=\"color\" (change)=\"applyColor($event)\" />\n </div>\n <div class=\"input-wrap\" tooltip=\"Background Color\">\n <i class=\"he he-background-drop\"></i>\n <input type=\"color\" (change)=\"applyHighlight($event)\" />\n </div>\n </div>\n <div class=\"toolbar-items\">\n <button type=\"button\" (click)=\"setAlignment('left')\" tooltip=\"Justify Left\">\n <i class=\"he he-left-align\"></i>\n </button>\n <button type=\"button\" (click)=\"setAlignment('center')\" tooltip=\"Justify Center\">\n <i class=\"he he-center-align\"></i>\n </button>\n <button type=\"button\" (click)=\"setAlignment('right')\" tooltip=\"Justify Right\">\n <i class=\"he he-right-align\"></i>\n </button>\n <button type=\"button\" (click)=\"setAlignment('justify')\" tooltip=\"Justify Full\">\n <i class=\"he he-justify\"></i>\n </button>\n </div>\n <div class=\"toolbar-items\">\n <button type=\"button\" (click)=\"indent()\" tooltip=\"Indent\">\n <i class=\"he he-text-indent-left\"></i>\n </button>\n <button type=\"button\" (click)=\"outdent()\" tooltip=\"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\" (click)=\"applyList('ul')\" tooltip=\"Unordered list\">\n <i class=\"he he-unordered-list\"></i>\n </button>\n <button type=\"button\" (click)=\"applyList('ol')\" tooltip=\"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\" (click)=\"createLink()\" tooltip=\"Link\">\n <i class=\"he he-link\"></i>\n </button>\n <button type=\"button\" (click)=\"insertImage()\" tooltip=\"Image\">\n <i class=\"he he-image\"></i>\n </button>\n </div>\n <div class=\"toolbar-items\">\n <button type=\"button\" (click)=\"undo()\" tooltip=\"Undo\">\n <i class=\"he he-undo\"></i>\n </button>\n <button type=\"button\" (click)=\"redo()\" tooltip=\"Redo\">\n <i class=\"he he-redo\"></i>\n </button>\n </div>\n <div class=\"toolbar-items\">\n <button type=\"button\" (click)=\"clearFormatting()\" tooltip=\"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</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}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] });
2772
2627
  }
2773
2628
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.3", ngImport: i0, type: TextEditor, decorators: [{
2774
2629
  type: Component,
2775
- args: [{ selector: 'app-text-editor', imports: [CommonModule,
2776
- ], template: "<div class=\"text-editor\" [ngClass]=\"{'readonly': readonly}\">\r\n <div class=\"toolbar\" *ngIf=\"!readonly\">\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\" tooltip=\"Indent\">\r\n <i class=\"he he-text-indent-left\"></i>\r\n </button>\r\n <button type=\"button\" 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 ? 'false' : 'true'\" (input)=\"onInput()\" (blur)=\"onTouched()\"\r\n [attr.data-placeholder]=\"placeholder\">\r\n </div>\r\n</div>", 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}\n"] }]
2630
+ args: [{ selector: 'app-text-editor', standalone: true, imports: [CommonModule], providers: [
2631
+ {
2632
+ provide: NG_VALUE_ACCESSOR,
2633
+ useExisting: forwardRef(() => TextEditor),
2634
+ multi: true,
2635
+ },
2636
+ ], 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\" (click)=\"applyInlineStyle('bold')\" tooltip=\"Bold\">\n <i class=\"he he-bold\"></i>\n </button>\n <button type=\"button\" (click)=\"applyInlineStyle('italic')\" tooltip=\"italic\">\n <i class=\"he he-italics\"></i>\n </button>\n <button type=\"button\" (click)=\"applyInlineStyle('underline')\" tooltip=\"Underline\">\n <i class=\"he he-underline\"></i>\n </button>\n </div>\n <div class=\"toolbar-items\" *ngIf=\"header\">\n <button type=\"button\" (click)=\"applyBlockFormat('h1')\" tooltip=\"Header 1\">\n <i class=\"he he-heading-1\"></i>\n </button>\n <button type=\"button\" (click)=\"applyBlockFormat('h2')\" tooltip=\"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\" tooltip=\"Text Color\">\n <i class=\"he he-text-drop\"></i>\n <input type=\"color\" (change)=\"applyColor($event)\" />\n </div>\n <div class=\"input-wrap\" tooltip=\"Background Color\">\n <i class=\"he he-background-drop\"></i>\n <input type=\"color\" (change)=\"applyHighlight($event)\" />\n </div>\n </div>\n <div class=\"toolbar-items\">\n <button type=\"button\" (click)=\"setAlignment('left')\" tooltip=\"Justify Left\">\n <i class=\"he he-left-align\"></i>\n </button>\n <button type=\"button\" (click)=\"setAlignment('center')\" tooltip=\"Justify Center\">\n <i class=\"he he-center-align\"></i>\n </button>\n <button type=\"button\" (click)=\"setAlignment('right')\" tooltip=\"Justify Right\">\n <i class=\"he he-right-align\"></i>\n </button>\n <button type=\"button\" (click)=\"setAlignment('justify')\" tooltip=\"Justify Full\">\n <i class=\"he he-justify\"></i>\n </button>\n </div>\n <div class=\"toolbar-items\">\n <button type=\"button\" (click)=\"indent()\" tooltip=\"Indent\">\n <i class=\"he he-text-indent-left\"></i>\n </button>\n <button type=\"button\" (click)=\"outdent()\" tooltip=\"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\" (click)=\"applyList('ul')\" tooltip=\"Unordered list\">\n <i class=\"he he-unordered-list\"></i>\n </button>\n <button type=\"button\" (click)=\"applyList('ol')\" tooltip=\"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\" (click)=\"createLink()\" tooltip=\"Link\">\n <i class=\"he he-link\"></i>\n </button>\n <button type=\"button\" (click)=\"insertImage()\" tooltip=\"Image\">\n <i class=\"he he-image\"></i>\n </button>\n </div>\n <div class=\"toolbar-items\">\n <button type=\"button\" (click)=\"undo()\" tooltip=\"Undo\">\n <i class=\"he he-undo\"></i>\n </button>\n <button type=\"button\" (click)=\"redo()\" tooltip=\"Redo\">\n <i class=\"he he-redo\"></i>\n </button>\n </div>\n <div class=\"toolbar-items\">\n <button type=\"button\" (click)=\"clearFormatting()\" tooltip=\"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</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}\n"] }]
2777
2637
  }], propDecorators: { header: [{
2778
2638
  type: Input
2779
2639
  }], media: [{
@@ -2787,6 +2647,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.3", ngImpor
2787
2647
  }], editorRef: [{
2788
2648
  type: ViewChild,
2789
2649
  args: ['editor']
2650
+ }], saveSelection: [{
2651
+ type: HostListener,
2652
+ args: ['document:selectionchange']
2790
2653
  }] } });
2791
2654
 
2792
2655
  class TextareaControl {