@libs-ui/components-inputs-quill 0.2.350-0 → 0.2.351-0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
- import { NgTemplateOutlet, NgStyle } from '@angular/common';
1
+ import { NgTemplateOutlet } from '@angular/common';
2
2
  import * as i0 from '@angular/core';
3
- import { signal, input, output, ChangeDetectionStrategy, Component, computed, inject, model, viewChild, ChangeDetectorRef, effect, untracked, DestroyRef } from '@angular/core';
3
+ import { signal, input, output, ChangeDetectionStrategy, Component, computed, inject, model, viewChild, ChangeDetectorRef, effect, untracked } from '@angular/core';
4
4
  import { LibsUiComponentsButtonsButtonComponent } from '@libs-ui/components-buttons-button';
5
5
  import { LibsUiComponentsButtonsSelectColorComponent } from '@libs-ui/components-buttons-select-color';
6
6
  import { LibsUiComponentsDropdownComponent } from '@libs-ui/components-dropdown';
@@ -14,18 +14,15 @@ import { LibsUiComponentsSkeletonComponent } from '@libs-ui/components-skeleton'
14
14
  import { LibsUiComponentsSpinnerComponent } from '@libs-ui/components-spinner';
15
15
  import { LibsUiDynamicComponentService } from '@libs-ui/services-dynamic-component';
16
16
  import { LibsUiNotificationService } from '@libs-ui/services-notification';
17
- import { patternUrl, convertFileToBase64_ObjectUrl, decodeEscapeHtml, get, set, isNil, xssFilter, ERROR_MESSAGE_EMPTY_VALID, ERROR_MESSAGE_MIN_LENGTH, ERROR_MESSAGE_MAX_LENGTH, getLabelBySizeFile, setStylesElement, UtilsKeyCodeConstant, isNearWhite, patterProtocolUrl } from '@libs-ui/utils';
17
+ import { patternUrl, convertFileToBase64_ObjectUrl, decodeEscapeHtml, get, set, isNil, xssFilter, ERROR_MESSAGE_EMPTY_VALID, ERROR_MESSAGE_MIN_LENGTH, ERROR_MESSAGE_MAX_LENGTH, getLabelBySizeFile } from '@libs-ui/utils';
18
18
  import * as i1 from '@ngx-translate/core';
19
19
  import { TranslateService, TranslateModule } from '@ngx-translate/core';
20
20
  import Quill from 'quill';
21
- import { Subject, lastValueFrom as lastValueFrom$1, timer as timer$1, fromEvent, takeUntil, merge } from 'rxjs';
21
+ import { Subject, lastValueFrom as lastValueFrom$1, timer as timer$1, fromEvent, takeUntil } from 'rxjs';
22
22
  import { LibsUiComponentsModalComponent } from '@libs-ui/components-modal';
23
23
  import { returnListObject } from '@libs-ui/services-http-request';
24
24
  import { lastValueFrom } from 'rxjs/internal/lastValueFrom';
25
25
  import { timer } from 'rxjs/internal/observable/timer';
26
- import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
27
- import Quill2x, { Delta } from 'quill2x';
28
- import ResizeModule from '@ssumo/quill-resize-module';
29
26
 
30
27
  class LibsUiComponentsInputsQuillLinkComponent {
31
28
  dataLink = signal({ title: '', link: '' });
@@ -139,7 +136,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
139
136
  }] });
140
137
 
141
138
  let quill = null;
142
- let timeout$1 = undefined;
139
+ let timeout = undefined;
143
140
  let timeout2 = undefined;
144
141
  const listDataAlign = () => {
145
142
  return [
@@ -644,8 +641,8 @@ const getHTMLFromDeltaOfQuill = (delta, options) => {
644
641
  if (replaceBrToDiv) {
645
642
  htmlText = convertHtmlToDivBlocks(htmlText || '');
646
643
  }
647
- clearTimeout(timeout$1);
648
- timeout$1 = setTimeout(() => {
644
+ clearTimeout(timeout);
645
+ timeout = setTimeout(() => {
649
646
  quill = null;
650
647
  }, 10000);
651
648
  return decodeEscapeHtml(htmlText || '');
@@ -760,8 +757,8 @@ class QuillDivBlot extends Block {
760
757
  static tagName = 'div';
761
758
  }
762
759
 
763
- const Embed$1 = Quill.import('blots/embed');
764
- class QuillMentionBlot extends Embed$1 {
760
+ const Embed = Quill.import('blots/embed');
761
+ class QuillMentionBlot extends Embed {
765
762
  static blotName = 'mention';
766
763
  static tagName = 'span';
767
764
  static className = 'libs-ui-quill-mention';
@@ -793,8 +790,8 @@ class QuillMentionBlot extends Embed$1 {
793
790
  }
794
791
  }
795
792
 
796
- const ImageFormat$1 = Quill.import('formats/image');
797
- class CustomImageBlot extends ImageFormat$1 {
793
+ const ImageFormat = Quill.import('formats/image');
794
+ class CustomImageBlot extends ImageFormat {
798
795
  static create(value) {
799
796
  const node = super.create(value);
800
797
  node.classList.add('libs-ui-quill-format-image');
@@ -1620,1444 +1617,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
1620
1617
  ], template: "<div class=\"flex flex-col w-full h-full\">\n @if (label(); as label) {\n <libs_ui-components-label\n [classInclude]=\"label.classInclude\"\n [required]=\"label.required\"\n [labelLeft]=\"label.labelLeft\" />\n }\n <div\n #wrapperEditor\n [attr.heightAuto]=\"heightAuto()\"\n [attr.isToolbarPositionFixed]=\"isToolbarPositionFixed()\"\n class=\"libs-ui-quill-wrapper w-full h-full relative flex flex-col\"\n [class.libs-ui-border-error-general]=\"messageError() && showErrorBorder() && !onlyShowErrorBorderInContent()\"\n [class.rounded-[4px]]=\"messageError() && showErrorBorder() && !onlyShowErrorBorderInContent()\">\n <div\n #editor\n class=\"libs-ui-quill\"\n [attr.showError]=\"messageError() && showErrorBorder() && onlyShowErrorBorderInContent()\"\n [class.!hidden]=\"!display()\">\n <div\n #quillOption\n [class.!top-[-9999px]]=\"!isShowToolBar()\"\n [class.!left-[-9999px]]=\"!isShowToolBar()\"\n [style]=\"stylesIncludeToolbar()\"\n [class.pointer-events-none]=\"readonly() || loadingUploadImage()\"\n class=\"{{ isToolbarPositionFixed() ? 'fixed !z-10 w-[510px] shadow-[0px_4px_16px_0px_rgba(0,20,51,0.10)] rounded-[4px] bg-[#ffffff] libs-ui-quill-toolbar-animation' : '' }} {{ classIncludeToolbar() }} h-[44px] shrink-0\"\n [class.bg-[#f8f9fa]]=\"!readonly() && !loadingUploadImage()\"\n [class.libs-ui-readonly-background]=\"readonly() || loadingUploadImage()\">\n <ng-container *ngTemplateOutlet=\"toolbar\"></ng-container>\n </div>\n <div\n #quillEditor\n LibsUiComponentsInputsMentionDirective\n [timeDelayInit]=\"timeDelayInit() + 50\"\n [mentionConfig]=\"dataConfigMention()\"\n [class.libs-ui-readonly-background]=\"readonly() || loadingUploadImage()\"\n [class.pointer-events-none]=\"loadingUploadImage()\"\n (outToggle)=\"handleToggleMention($event)\"\n (outInsertMention)=\"handlerInsertMention($event)\"></div>\n <ng-container\n #qlEditorScroll\n LibsUiComponentsScrollOverlayDirective\n [ignoreInit]=\"!qlEditorElement()\"\n [elementScroll]=\"qlEditorElement()\" />\n </div>\n @if (template(); as template) {\n <div [class]=\"classIncludeTemplate()\">\n <ng-container *ngTemplateOutlet=\"template\"></ng-container>\n </div>\n }\n @if (loadingUploadImage()) {\n <libs_ui-components-spinner [size]=\"'medium'\" />\n }\n </div>\n @if (messageError() && showErrorLabel()) {\n <div class=\"flex items-center leading-normal mt-[8px]\">\n <span class=\"text-[#ff5454] libs-ui-font-h7r\">{{ messageError() | translate }}</span>\n </div>\n }\n</div>\n\n<ng-template #toolbar>\n <div\n class=\"toolbar h-full w-full shrink-0\"\n #toolbarItems>\n @if (displaySkeleton()) {\n <libs_ui-components-skeleton\n class=\"w-full h-full\"\n [config]=\"{\n rows: [\n {\n item: { classIncludeItem: '!rounded-none' },\n },\n ],\n }\" />\n }\n <div class=\"ql-formats items-center px-[16px] py-[4px]\">\n @for (option of toolbarOptionsConfig(); track option) {\n <div\n class=\"items-center\"\n [class.hidden]=\"!option.display\"\n [class.flex]=\"option.display\">\n <ng-container *ngTemplateOutlet=\"itemTemplate; context: { option, $index, $last }\"></ng-container>\n </div>\n }\n <div class=\"relative\">\n @if (displayShowMoreToolbar()) {\n <libs_ui-components-buttons-button\n [type]=\"showMoreAction() ? 'button-secondary' : 'button-third'\"\n [iconOnlyType]=\"true\"\n [classInclude]=\"'!p-[1px] !h-[20px] ml-[8px]'\"\n [classIconLeft]=\"'libs-ui-icon-move-right rotate-90'\"\n (outClick)=\"handlerChangeShowMoreAction($event)\" />\n }\n <!-- Build toolbar khi click xem th\u00EAm-->\n <div\n [class.hidden]=\"!showMoreAction()\"\n class=\"absolute bg-[#ffffff] shadow-[0px_4px_16px_0px_rgba(0,20,51,0.10)] z-[1] flex items-center pl-[8px] pr-[16px] py-[4px] rounded-[8px] top-[31px] right-[0px]\">\n @for (option of toolbarOptionsConfig(); track option) {\n <div\n class=\"items-center\"\n [class.hidden]=\"option.display !== false\"\n [class.flex]=\"option.display === false\">\n <ng-container *ngTemplateOutlet=\"itemTemplate; context: { option, $index, $last }\"></ng-container>\n </div>\n }\n </div>\n </div>\n </div>\n </div>\n</ng-template>\n\n<ng-template\n #itemTemplate\n let-$index=\"$index\"\n let-$last=\"$last\"\n let-option=\"option\">\n @if (option.type === 'undo') {\n <div [class]=\"option.classInclude || 'mx-[8px]'\">\n <button\n LibsUiComponentsPopoverDirective\n [config]=\"{ content: 'i18n_undo', zIndex: zIndex() }\"\n class=\"ql-undo\"></button>\n </div>\n }\n @if (option.type === 'redo') {\n <div [class]=\"option.classInclude || 'mx-[8px]'\">\n <button\n LibsUiComponentsPopoverDirective\n [config]=\"{ content: 'i18n_redo', zIndex: zIndex() }\"\n class=\"ql-redo\"></button>\n </div>\n }\n @if (option.type === 'fontFamily') {\n <div\n class=\"relative w-[132px] h-full rounded-[4px] libs-ui-border-general {{ option.classInclude || 'mx-[8px]' }}\"\n [class.bg-white]=\"!readonly() && !loadingUploadImage()\">\n <libs_ui-components-dropdown\n [isNgContent]=\"true\"\n [labelPopoverFullWidth]=\"true\"\n [listConfig]=\"listConfigFont()\"\n [listHasButtonUnSelectOption]=\"false\"\n [listHiddenInputSearch]=\"true\"\n [listMaxItemShow]=\"8\"\n [zIndex]=\"1250\"\n (outSelectKey)=\"handleSelectFont($event)\">\n @if (fontSelected(); as fontSelected) {\n <div class=\"flex items-center cursor-pointer py-[7px] libs-ui-font-h5r pl-[16px] pr-[40px]\">\n <libs_ui-components-popover\n [type]=\"'text'\"\n [ignoreStopPropagationEvent]=\"true\"\n [config]=\"{ zIndex: zIndex() }\">\n {{ labelFontSelectedComputed() }}\n </libs_ui-components-popover>\n <i class=\"libs-ui-icon-move-right rotate-90 absolute right-[12px] text-[#6a7383] text-[16px]\"></i>\n </div>\n }\n </libs_ui-components-dropdown>\n </div>\n }\n @if (option.type === 'header') {\n <div\n class=\"relative w-[138px] h-full rounded-[4px] libs-ui-border-general {{ option.classInclude || 'mx-[8px]' }}\"\n [class.bg-white]=\"!readonly() && !loadingUploadImage()\">\n <libs_ui-components-dropdown\n [isNgContent]=\"true\"\n [labelPopoverFullWidth]=\"true\"\n [listConfig]=\"listConfigHeader()\"\n [listHasButtonUnSelectOption]=\"false\"\n [listHiddenInputSearch]=\"true\"\n [listMaxItemShow]=\"8\"\n [zIndex]=\"1250\"\n (outSelectKey)=\"handleSelectHeader($event)\">\n @if (headerSelected(); as headerSelected) {\n <div class=\"flex items-center cursor-pointer py-[7px] libs-ui-font-h5r pl-[16px] pr-[40px] {{ option.classInclude || 'mx-[8px]' }}\">\n <libs_ui-components-popover\n [type]=\"'text'\"\n [ignoreStopPropagationEvent]=\"true\"\n [config]=\"{ zIndex: zIndex() }\">\n {{ labelHeaderSelectedComputed() }}\n </libs_ui-components-popover>\n <i class=\"libs-ui-icon-move-right rotate-90 absolute right-[12px] text-[#6a7383] text-[16px]\"></i>\n </div>\n }\n </libs_ui-components-dropdown>\n </div>\n }\n @if (option.type === 'fontSize') {\n <div class=\"ql-picker {{ option.classInclude || 'mx-[8px]' }}\">\n <libs_ui-components-inputs-valid\n [dataType]=\"'int'\"\n [(item)]=\"size\"\n [fieldNameBind]=\"'value'\"\n [valueUpDownNumber]=\"1\"\n [maxValueNumber]=\"72\"\n [minValueNumber]=\"8\"\n [readonly]=\"readonly() || loadingUploadImage()\"\n [classContainerInput]=\"'w-[72px] h-[32px]'\"\n (outValueChange)=\"handlerValueChange($event)\" />\n </div>\n }\n @if (option.type === 'color') {\n <div class=\"ql-color ql-picker ql-color-picker !flex items-center {{ option.classInclude || 'mx-[8px]' }}\">\n <libs_ui-components-popover [config]=\"{ content: 'i18n_text_color', zIndex: zIndex() }\">\n <libs_ui-components-buttons-select_color\n [zIndex]=\"zIndex()\"\n [direction]=\"'top'\"\n [externalContent]=\"true\"\n [customOptions]=\"{\n showAlpha: true,\n }\"\n [applyNow]=\"false\"\n (outColorChange)=\"setStyle('color', $event)\">\n <div class=\"libs-ui-icon-editor-color-text libs-ui-buttons-select-color text-[#6a7383] text-[16px] hover:text-[var(--libs-ui-color-light-1)]\"></div>\n </libs_ui-components-buttons-select_color>\n </libs_ui-components-popover>\n </div>\n }\n @if (option.type === 'background') {\n <div class=\"ql-background ql-picker ql-color-picker !flex items-center {{ option.classInclude || 'mx-[8px]' }}\">\n <libs_ui-components-popover [config]=\"{ content: 'i18n_background_color', zIndex: zIndex() }\">\n <libs_ui-components-buttons-select_color\n [zIndex]=\"zIndex()\"\n [direction]=\"'top'\"\n [externalContent]=\"true\"\n [applyNow]=\"false\"\n [customOptions]=\"{\n showAlpha: true,\n }\"\n (outColorChange)=\"setStyle('background', $event)\">\n <div class=\"libs-ui-icon-editor-color-background libs-ui-buttons-select-color text-[#6a7383] text-[16px] hover:text-[var(--libs-ui-color-light-1)]\"></div>\n </libs_ui-components-buttons-select_color>\n </libs_ui-components-popover>\n </div>\n }\n @if (option.type === 'bold') {\n <div [class]=\"option.classInclude || 'mx-[8px]'\">\n <button\n LibsUiComponentsPopoverDirective\n [config]=\"{ content: 'i18n_font_weight_bold', zIndex: zIndex() }\"\n class=\"ql-bold\"></button>\n </div>\n }\n @if (option.type === 'italic') {\n <div [class]=\"option.classInclude || 'mx-[8px]'\">\n <button\n LibsUiComponentsPopoverDirective\n [config]=\"{ content: 'i18n_font_style_italic', zIndex: zIndex() }\"\n class=\"ql-italic\"></button>\n </div>\n }\n @if (option.type === 'underline') {\n <div [class]=\"option.classInclude || 'mx-[8px]'\">\n <button\n LibsUiComponentsPopoverDirective\n [config]=\"{ content: 'i18n_text_decoration_underline', zIndex: zIndex() }\"\n class=\"ql-underline\"></button>\n </div>\n }\n @if (option.type === 'strikeThrough') {\n <div [class]=\"option.classInclude || 'mx-[8px]'\">\n <button\n LibsUiComponentsPopoverDirective\n [config]=\"{ content: 'i18n_text_line_through', zIndex: zIndex() }\"\n class=\"ql-strike\"></button>\n </div>\n }\n @if (option.type === 'adjust') {\n <div class=\"relative !flex items-center ql-align ql-picker ql-icon-picker !w-max {{ option.classInclude || 'mx-[8px]' }}\">\n <libs_ui-components-popover [config]=\"{ content: 'i18n_adjust', zIndex: zIndex() }\">\n <libs_ui-components-dropdown\n [isNgContent]=\"true\"\n [ignoreStopPropagationEvent]=\"true\"\n [labelPopoverFullWidth]=\"true\"\n [listConfig]=\"listConfigAlign()\"\n [listHiddenInputSearch]=\"true\"\n [popoverCustomConfig]=\"{ ignoreArrow: true, classInclude: '!w-[32px] overflow-hidden !py-[4px]', position: { mode: 'start', distance: 0 }, paddingLeftItem: false }\"\n [listHasButtonUnSelectOption]=\"false\"\n [listMaxItemShow]=\"8\"\n [zIndex]=\"1250\"\n (outSelectKey)=\"handleSelectAlign($event)\">\n @if (alignSelected(); as alignSelected) {\n <div class=\"flex items-center cursor-pointer\">\n <i [class]=\"iconAlignSelectedComputed()\"></i>\n <i class=\"libs-ui-icon-move-right rotate-90 text-[#6a7383] text-[16px] ml-[4px]\"></i>\n </div>\n }\n </libs_ui-components-dropdown>\n </libs_ui-components-popover>\n </div>\n }\n @if (option.type === 'indentIncrease') {\n <div [class]=\"option.classInclude || 'mx-[8px]'\">\n <button\n LibsUiComponentsPopoverDirective\n [config]=\"{ content: 'i18n_indent_increase', zIndex: zIndex() }\"\n class=\"ql-indent\"\n value=\"+1\"></button>\n </div>\n }\n @if (option.type === 'indentDecrease') {\n <div [class]=\"option.classInclude || 'mx-[8px]'\">\n <button\n LibsUiComponentsPopoverDirective\n [config]=\"{ content: 'i18n_indent_decrease', zIndex: zIndex() }\"\n class=\"ql-indent\"\n value=\"-1\"></button>\n </div>\n }\n @if (option.type === 'listBulleted') {\n <div [class]=\"option.classInclude || 'mx-[8px]'\">\n <button\n LibsUiComponentsPopoverDirective\n [config]=\"{ content: 'i18n_list_bulleted', zIndex: zIndex() }\"\n class=\"ql-list ql-bullet\"\n value=\"bullet\"></button>\n </div>\n }\n @if (option.type === 'listNumbered') {\n <div [class]=\"option.classInclude || 'mx-[8px]'\">\n <button\n LibsUiComponentsPopoverDirective\n [config]=\"{ content: 'i18n_list_numbered', zIndex: zIndex() }\"\n class=\"ql-list ql-ordered\"\n value=\"ordered\"></button>\n </div>\n }\n @if (option.type === 'personalize' && templateToolBarPersonalize(); as templateToolBarPersonalize) {\n <div class=\"flex items-center {{ option.classInclude || 'mx-[8px]' }}\">\n <ng-container *ngTemplateOutlet=\"templateToolBarPersonalize\"></ng-container>\n </div>\n }\n @if (option.type === 'blockquote') {\n <div [class]=\"option.classInclude || 'mx-[8px]'\">\n <button\n LibsUiComponentsPopoverDirective\n [config]=\"{ content: 'i18n_quote', zIndex: zIndex() }\"\n class=\"ql-blockquote\"></button>\n </div>\n }\n @if (option.type === 'link') {\n <div [class]=\"option.classInclude || 'mx-[8px]'\">\n <button\n LibsUiComponentsPopoverDirective\n [config]=\"{ content: 'i18n_insert_link', zIndex: zIndex() }\"\n class=\"ql-link\"></button>\n </div>\n }\n @if (option.type === 'unLink') {\n <div [class]=\"option.classInclude || 'mx-[8px]'\">\n <button\n LibsUiComponentsPopoverDirective\n [config]=\"{ content: 'i18n_unlink', zIndex: zIndex() }\"\n class=\"ql-unLink\"></button>\n </div>\n }\n @if (option.type === 'image') {\n <div [class]=\"option.classInclude || 'mx-[8px]'\">\n <button\n LibsUiComponentsPopoverDirective\n [config]=\"{ content: 'i18n_image', zIndex: zIndex() }\"\n class=\"ql-image\"></button>\n </div>\n }\n @if (option.type === 'emoji') {\n <div [class]=\"option.classInclude || 'mx-[8px]'\">\n <libs_ui-components-emoji\n [zIndex]=\"zIndex()\"\n [isNgContent]=\"true\"\n (outEventEmoji)=\"handlerAddEmoji($event)\">\n <button class=\"ql-emoji\"></button>\n </libs_ui-components-emoji>\n </div>\n }\n @if (option.type === 'line') {\n <div class=\"w-[1px] h-[16px] libs-ui-border-right-general\"></div>\n }\n</ng-template>\n\n<libs_ui-components-popover\n [mode]=\"'click'\"\n [ignoreHiddenPopoverContentWhenMouseLeave]=\"true\"\n [config]=\"{ template: viewLink, whiteTheme: true, ignoreArrow: true, zIndex: zIndex() }\"\n (outEvent)=\"handlerPopoverEvent($event)\"\n (outFunctionsControl)=\"handlerPopoverFunctionControl($event)\" />\n\n<ng-template #viewLink>\n <div class=\"flex justify-between items-center px-[16px] py-[8px] rounded-[8px]\">\n <div\n class=\"w-full min-w-0 libs-ui-font-h5r\"\n [type]=\"'text'\"\n LibsUiComponentsPopoverDirective\n [config]=\"{ content: link().url, zIndex: zIndex() + 1 }\">\n {{ link().url }}\n </div>\n <div class=\"flex items-center ml-[16px]\">\n <libs_ui-components-buttons-button\n [type]=\"'button-link-primary'\"\n [iconOnlyType]=\"true\"\n [classIconLeft]=\"'libs-ui-icon-edit-line'\"\n [classInclude]=\"'!p-0'\"\n (outClick)=\"handlerEdit($event)\" />\n <libs_ui-components-buttons-button\n [type]=\"'button-link-custom'\"\n [buttonCustom]=\"{\n configStepColor: {\n text: '#071631',\n text_hover: '#ee2d41',\n text_active: '#ee2d41',\n text_disable: '071631',\n },\n rootColor: '#071631',\n }\"\n [classInclude]=\"'!p-0 ml-[12px]'\"\n [iconOnlyType]=\"true\"\n [classIconLeft]=\"'libs-ui-icon-link-broken'\"\n (outClick)=\"handlerUnlink($event)\" />\n </div>\n </div>\n</ng-template>\n", styles: ["@-webkit-keyframes animation-move{0%{transform:translateY(-12px)}to{transform:translateY(0)}}@keyframes animation-move{0%{transform:translateY(-12px)}to{transform:translateY(0)}}.libs-ui-quill{height:100%;width:100%;display:flex;flex-direction:column}.libs-ui-quill-toolbar-animation{animation:animation-move .4s ease}.libs-ui-quill-wrapper[heightAuto=true] .libs-ui-quill{height:auto}.libs-ui-quill-wrapper[heightAuto=true] .libs-ui-quill ::ng-deep .ql-container{height:auto}.libs-ui-quill-wrapper[heightAuto=true] .libs-ui-quill ::ng-deep .ql-container .ql-editor{position:relative!important}.libs-ui-quill-wrapper[isToolbarPositionFixed=true] .libs-ui-quill ::ng-deep .ql-container.ql-snow{border:0px!important}.libs-ui-quill-wrapper[isToolbarPositionFixed=false] .libs-ui-quill ::ng-deep .ql-container.ql-snow{border:solid 1px #e6e8ed!important;border-radius:0 0 4px 4px}.libs-ui-quill-wrapper[isToolbarPositionFixed=false] .libs-ui-quill ::ng-deep .ql-toolbar.ql-snow{border:solid 1px #e6e8ed!important;border-radius:4px 4px 0 0;border-bottom:unset!important}.libs-ui-quill-wrapper[isToolbarPositionFixed=false] .libs-ui-quill[showError=true] ::ng-deep .ql-container.ql-snow{border:solid 1px #ee2d41!important}:host ::ng-deep .toolbar,:host ::ng-deep .ql-formats{position:relative;width:100%}:host ::ng-deep .ql-toolbar.ql-snow .ql-formats{display:flex}:host ::ng-deep .ql-container.ql-snow{width:100%;height:100%;position:relative}:host ::ng-deep .ql-editor{font-family:var(--libs-ui-font-family-name),\"Arial, Helvetica, sans-serif\"!important;font-weight:400}:host ::ng-deep .ql-editor b{font-family:var(--libs-ui-font-family-name),\"Arial, Helvetica, sans-serif\"!important;font-weight:600}:host ::ng-deep .ql-toolbar.ql-snow{border:none;border-radius:8px;padding:0}:host ::ng-deep .ql-toolbar.ql-snow .ql-picker-label{color:#071631;border:none!important;margin-top:5px}:host ::ng-deep .ql-toolbar.ql-snow .ql-picker-label:hover{color:var(--libs-ui-color-light-1)!important}:host ::ng-deep .ql-toolbar.ql-snow .ql-picker-label:hover .ql-stroke{stroke:var(--libs-ui-color-light-1)!important}:host ::ng-deep .ql-snow.ql-toolbar .ql-picker-item:hover{color:var(--libs-ui-color-light-1)!important}:host ::ng-deep .ql-snow.ql-toolbar .ql-picker-label.ql-active{color:#071631}:host ::ng-deep .ql-snow.ql-toolbar .ql-picker-label.ql-active .ql-stroke{stroke:#071631}:host ::ng-deep .ql-editor{height:100%;width:100%;position:absolute;line-height:1.42!important}:host ::ng-deep .ql-editor:before{font-family:var(--libs-ui-font-family-name),\"Arial, Helvetica, sans-serif\"!important;color:#9ca2ad!important;font-size:12px}:host ::ng-deep .ql-editor img{height:auto;max-width:100%}:host ::ng-deep .ql-toolbar.ql-snow .ql-picker.ql-expanded .ql-picker-label{border:none!important}:host ::ng-deep .ql-snow .ql-picker.ql-bold{width:36px!important}:host ::ng-deep .ql-active span:before{color:var(--libs-ui-color-light-1)!important}:host ::ng-deep .ql-editor.ql-blank{font-size:11px!important;letter-spacing:.05px;font-family:var(--libs-ui-font-family-name),\"Arial, Helvetica, sans-serif\"!important;line-height:16px}:host ::ng-deep .ql-editor.ql-blank:before{font-style:normal!important;color:#9ca2ad!important}:host ::ng-deep .ql-snow.ql-toolbar .ql-picker-label :hover{color:red!important}:host ::ng-deep .ql-formats{margin-right:12px!important}:host ::ng-deep .ql-formats .ql-size.ql-picker,:host ::ng-deep .ql-formats .ql-header.ql-picker,:host ::ng-deep .ql-formats .ql-font.ql-picker{border:solid 1px #e6e8ed!important;border-radius:4px}:host ::ng-deep .ql-formats .ql-align.ql-picker .ql-picker-label{width:24px}:host ::ng-deep .ql-formats .ql-align.ql-picker .ql-picker-label:hover{color:red!important}:host ::ng-deep .ql-formats .ql-header.ql-picker .ql-picker-label:before{font-size:12px}:host ::ng-deep .ql-picker-item:before{font-size:12px}:host ::ng-deep .ql-picker-label:before{font-size:12px}:host ::ng-deep .ql-snow.ql-toolbar button,:host ::ng-deep .ql-snow .ql-toolbar button{background:none;border:none;cursor:pointer;display:flex;align-items:center;float:none;padding:0;width:inherit}:host ::ng-deep ul{padding-left:1rem!important}:host ::ng-deep li{padding-left:0!important}:host ::ng-deep .ql-tooltip{display:none!important}.ql-picker-options{max-height:130px;overflow-y:auto}.ql-snow .ql-picker.ql-size{border:1px solid #e6e7ea;box-shadow:#00000005 0 1px 3px,#1b1f2326 0 0 0 1px;border-radius:2px}.ql-snow .ql-picker.ql-font{border:1px solid #e6e7ea!important;margin-right:8px;border-radius:4px}.ql-snow .ql-picker.ql-font .ql-picker-options:before{font-size:12px}.ql-snow .ql-picker.ql-font .ql-picker-label:before{font-size:12px}.ql-font-Arial{font-family:Arial}.ql-font-sans-serif{font-family:\"sans-serif\"}.ql-font-Helvetica{font-family:Helvetica}.libs-ui-quill-mention{font-weight:500!important;color:#7239ea;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;font-family:var(--libs-ui-font-family-name),\"Arial, Helvetica, sans-serif\"!important;font-weight:600}.ql-snow .ql-picker.ql-expanded .ql-picker-options{overflow:hidden}.ql-formats{margin-right:0!important}.ql-formats .ql-header{position:relative!important}.ql-formats .ql-header .ql-picker-options{position:absolute!important;top:-151px!important}.ql-formats .ql-font{position:relative!important}.ql-formats .ql-font .ql-picker-options{position:absolute!important;top:-93px!important}.ql-formats .ql-color{position:relative!important}.ql-formats .ql-color .ql-picker-options{position:absolute!important;top:-108px}.ql-formats .ql-background{position:relative!important}.ql-formats .ql-background .ql-picker-options{position:absolute!important;top:-108px}.ql-formats .ql-align{position:relative!important}.ql-formats .ql-align .ql-picker-label{padding:3px 4px!important}.ql-formats .ql-align .ql-picker-options{position:absolute!important;top:-106px}.ql-snow .ql-picker{font-size:12px!important;height:32px;float:none;width:auto}\n"] }]
1621
1618
  }], ctorParameters: () => [] });
1622
1619
 
1623
- /* eslint-disable @typescript-eslint/no-explicit-any */
1624
- const Embed = Quill2x.import('blots/embed');
1625
- class QuillMention2xBlot extends Embed {
1626
- static blotName = 'mention';
1627
- static tagName = 'span';
1628
- static className = 'libs-ui-quill-mention';
1629
- static create(data) {
1630
- const node = super.create();
1631
- node.innerText += data.value;
1632
- node.setAttribute('id', data.id);
1633
- node.setAttribute('feId', data.feId);
1634
- node.setAttribute('value', data.value);
1635
- return node;
1636
- }
1637
- static value(domNode) {
1638
- return {
1639
- id: domNode.getAttribute('id'),
1640
- feId: domNode.getAttribute('feId'),
1641
- value: domNode.getAttribute('value'),
1642
- };
1643
- }
1644
- attach() {
1645
- super.attach();
1646
- if (!this.mounted) {
1647
- this.mounted = true;
1648
- this.clickHandler = this.getClickHandler;
1649
- this.domNode.addEventListener('click', this.clickHandler, false);
1650
- }
1651
- }
1652
- getClickHandler(event) {
1653
- event.stopPropagation();
1654
- }
1655
- }
1656
-
1657
- const ImageFormat = Quill2x.import('formats/image');
1658
- class CustomImage2xBlot extends ImageFormat {
1659
- static create(value) {
1660
- const node = super.create(value);
1661
- node.classList.add('libs-ui-quill-format-image');
1662
- return node;
1663
- }
1664
- formats() {
1665
- return {}; // Tránh Quill tự động thêm thẻ `<span>`
1666
- }
1667
- }
1668
-
1669
- /* eslint-disable @typescript-eslint/no-explicit-any */
1670
- /* eslint-disable @typescript-eslint/no-non-null-assertion */
1671
- let quill2x = null;
1672
- let timeout = undefined;
1673
- let timeout1 = undefined;
1674
- let startCell = null;
1675
- let endCell = null;
1676
- let isSelecting = false;
1677
- //region Function Table
1678
- const createTableSelector = (quill, anchorEl, translate) => {
1679
- // Đóng popup cũ nếu còn tồn tại
1680
- document.querySelectorAll('.manual-table-creator').forEach((el) => el.parentElement?.removeChild(el));
1681
- const popup = document.createElement('div');
1682
- popup.className = 'manual-table-creator';
1683
- popup.style.position = 'absolute';
1684
- popup.style.background = '#fff';
1685
- popup.style.border = '1px solid #ddd';
1686
- popup.style.borderRadius = '6px';
1687
- popup.style.boxShadow = '0 6px 16px rgba(0,0,0,0.12)';
1688
- popup.style.padding = '12px';
1689
- popup.style.zIndex = '10000';
1690
- popup.style.minWidth = '200px';
1691
- setStylesElement(popup, {
1692
- position: 'absolute',
1693
- background: '#fff',
1694
- border: '1px solid #ddd',
1695
- borderRadius: '6px',
1696
- boxShadow: '0 6px 16px rgba(0,0,0,0.12)',
1697
- padding: '12px',
1698
- zIndex: '10000',
1699
- minWidth: '200px',
1700
- });
1701
- const info = document.createElement('div');
1702
- info.textContent = translate.instant('i18n_select_cell');
1703
- setStylesElement(info, {
1704
- fontSize: '12px',
1705
- color: '#333',
1706
- marginBottom: '10px',
1707
- textAlign: 'center',
1708
- fontWeight: '600',
1709
- });
1710
- popup.appendChild(info);
1711
- const grid = document.createElement('div');
1712
- setStylesElement(grid, {
1713
- display: 'grid',
1714
- gridTemplateColumns: 'repeat(8, 18px)',
1715
- gap: '4px',
1716
- });
1717
- const max = 8;
1718
- for (let row = 1; row <= max; row++) {
1719
- for (let col = 1; col <= max; col++) {
1720
- const cell = document.createElement('div');
1721
- cell.style.width = '18px';
1722
- cell.style.height = '18px';
1723
- cell.style.border = '1px solid #e5e7eb';
1724
- cell.style.background = '#fff';
1725
- cell.style.cursor = 'pointer';
1726
- cell.addEventListener('mouseenter', () => {
1727
- info.textContent = `${row} × ${col}`;
1728
- Array.from(grid.children).forEach((el, idx) => {
1729
- const rr = Math.floor(idx / max) + 1;
1730
- const cc = (idx % max) + 1;
1731
- el.style.background = rr <= row && cc <= col ? '#dbeafe' : '#fff';
1732
- el.style.borderColor = rr <= row && cc <= col ? '#93c5fd' : '#e5e7eb';
1733
- });
1734
- });
1735
- cell.addEventListener('click', () => {
1736
- try {
1737
- quill.focus();
1738
- const tableModule = quill.getModule('table');
1739
- if (tableModule && typeof tableModule.insertTable === 'function') {
1740
- tableModule.insertTable(row, col);
1741
- getAllTablesWithSpan(quill);
1742
- }
1743
- }
1744
- finally {
1745
- if (document.body.contains(popup)) {
1746
- document.body.removeChild(popup);
1747
- }
1748
- document.removeEventListener('click', onOutsideClick, true);
1749
- }
1750
- });
1751
- grid.appendChild(cell);
1752
- }
1753
- }
1754
- popup.appendChild(grid);
1755
- const placePopup = () => {
1756
- const rect = anchorEl?.getBoundingClientRect();
1757
- const top = rect ? rect.bottom + window.scrollY + 6 : 100;
1758
- const left = rect ? rect.left + window.scrollX : 100;
1759
- popup.style.top = `${top}px`;
1760
- popup.style.left = `${left}px`;
1761
- };
1762
- const onOutsideClick = (ev) => {
1763
- if (!popup.contains(ev.target)) {
1764
- if (document.body.contains(popup)) {
1765
- document.body.removeChild(popup);
1766
- }
1767
- document.removeEventListener('click', onOutsideClick, true);
1768
- }
1769
- };
1770
- document.body.appendChild(popup);
1771
- placePopup();
1772
- setTimeout(() => document.addEventListener('click', onOutsideClick, true));
1773
- };
1774
- const createContextMenuOptionTable = (quill, translate) => {
1775
- let lastContextIndex = null;
1776
- const closeAnyMenu = () => {
1777
- document.querySelectorAll('.manual-table-menu').forEach((el) => el.parentElement?.removeChild(el));
1778
- };
1779
- const runWithSelection = (fn) => {
1780
- try {
1781
- quill.focus();
1782
- if (typeof lastContextIndex === 'number') {
1783
- quill.setSelection(lastContextIndex, 0, 'silent');
1784
- }
1785
- }
1786
- catch {
1787
- /* no-op: giữ yên nếu không thể set selection */
1788
- }
1789
- fn();
1790
- };
1791
- const createMenuItem = (label, onClick) => {
1792
- const item = document.createElement('div');
1793
- item.textContent = label;
1794
- item.style.padding = '6px 12px';
1795
- item.style.cursor = 'pointer';
1796
- item.addEventListener('click', () => {
1797
- runWithSelection(onClick);
1798
- closeAnyMenu();
1799
- });
1800
- item.addEventListener('mouseenter', () => {
1801
- item.style.background = '#f5f5f5';
1802
- });
1803
- item.addEventListener('mouseleave', () => {
1804
- item.style.background = 'transparent';
1805
- });
1806
- return item;
1807
- };
1808
- const openContextMenu = (pageX, pageY) => {
1809
- closeAnyMenu();
1810
- const menu = document.createElement('div');
1811
- menu.className = 'manual-table-menu';
1812
- menu.style.position = 'absolute';
1813
- menu.style.top = `${pageY}px`;
1814
- menu.style.left = `${pageX}px`;
1815
- menu.style.background = '#fff';
1816
- menu.style.border = '1px solid #ccc';
1817
- menu.style.borderRadius = '4px';
1818
- menu.style.boxShadow = '0 4px 12px rgba(0,0,0,0.2)';
1819
- menu.style.zIndex = '10001';
1820
- menu.style.padding = '4px';
1821
- menu.style.minWidth = '180px';
1822
- const tableModule = quill.getModule('table');
1823
- const safeCall = (method, ...args) => {
1824
- if (method === 'mergeCells') {
1825
- const [startCell, endCell] = args;
1826
- mergeCells(startCell, endCell);
1827
- closeAnyMenu();
1828
- return;
1829
- }
1830
- if (method === 'splitCells') {
1831
- const [startCell] = args;
1832
- splitCells(startCell);
1833
- closeAnyMenu();
1834
- return;
1835
- }
1836
- if (tableModule && typeof tableModule[method] === 'function') {
1837
- tableModule[method](...args);
1838
- getAllTablesWithSpan(quill);
1839
- }
1840
- };
1841
- menu.appendChild(createMenuItem(translate.instant('i18n_add_new_row_above'), () => safeCall('insertRowAbove')));
1842
- menu.appendChild(createMenuItem(translate.instant('i18n_add_new_row_below'), () => safeCall('insertRowBelow')));
1843
- menu.appendChild(createMenuItem(translate.instant('i18n_add_new_column_left'), () => safeCall('insertColumnLeft')));
1844
- menu.appendChild(createMenuItem(translate.instant('i18n_add_new_column_right'), () => safeCall('insertColumnRight')));
1845
- const divider = document.createElement('div');
1846
- divider.style.height = '1px';
1847
- divider.style.background = '#eee';
1848
- divider.style.margin = '4px 0';
1849
- menu.appendChild(divider);
1850
- if (startCell && endCell) {
1851
- const startCellStore = startCell;
1852
- const endCellStore = endCell;
1853
- const colspan = parseInt(startCellStore.getAttribute('colspan') || '1', 10);
1854
- const rowspan = parseInt(startCellStore.getAttribute('rowspan') || '1', 10);
1855
- let totalMenu = 0;
1856
- if (startCell !== endCell) {
1857
- menu.appendChild(createMenuItem(translate.instant('i18n_merge_cells'), () => safeCall('mergeCells', startCellStore, endCellStore)));
1858
- totalMenu++;
1859
- }
1860
- if (startCell === endCell && (colspan > 1 || rowspan > 1)) {
1861
- menu.appendChild(createMenuItem(translate.instant('i18n_split_cells'), () => safeCall('splitCells', startCellStore)));
1862
- totalMenu++;
1863
- }
1864
- if (totalMenu > 0) {
1865
- const divider2 = document.createElement('div');
1866
- divider2.style.height = '1px';
1867
- divider2.style.background = '#eee';
1868
- divider2.style.margin = '4px 0';
1869
- menu.appendChild(divider2);
1870
- }
1871
- }
1872
- menu.appendChild(createMenuItem(translate.instant('i18n_delete_row'), () => safeCall('deleteRow')));
1873
- menu.appendChild(createMenuItem(translate.instant('i18n_delete_column'), () => safeCall('deleteColumn')));
1874
- menu.appendChild(createMenuItem(translate.instant('i18n_delete_table'), () => safeCall('deleteTable')));
1875
- document.body.appendChild(menu);
1876
- const onOutside = (ev) => {
1877
- if (!menu.contains(ev.target) || ev.target.getElementsByTagName('table').length < 0) {
1878
- closeAnyMenu();
1879
- document.removeEventListener('click', onOutside, true);
1880
- }
1881
- };
1882
- setTimeout(() => document.addEventListener('click', onOutside, true));
1883
- const onScroll = () => {
1884
- closeAnyMenu();
1885
- window.removeEventListener('scroll', onScroll, true);
1886
- window.removeEventListener('resize', onScroll, true);
1887
- };
1888
- window.addEventListener('scroll', onScroll, true);
1889
- window.addEventListener('resize', onScroll, true);
1890
- };
1891
- fromEvent(quill.root, 'contextmenu').subscribe((ev) => {
1892
- const target = ev.target;
1893
- const isCell = !!target.closest('td,th,table,.ql-table');
1894
- if (!isCell)
1895
- return;
1896
- ev.preventDefault();
1897
- try {
1898
- // Ưu tiên lấy index từ blot tương ứng node
1899
- const QuillAny = Quill2x;
1900
- const blot = QuillAny?.find?.(target);
1901
- if (blot && typeof blot.offset === 'function') {
1902
- lastContextIndex = blot.offset(quill.scroll);
1903
- }
1904
- else {
1905
- // Fallback: đặt selection hiện tại nếu không xác định được
1906
- const sel = quill.getSelection(true);
1907
- lastContextIndex = sel ? sel.index : 0;
1908
- }
1909
- }
1910
- catch {
1911
- const sel = quill.getSelection(true);
1912
- lastContextIndex = sel ? sel.index : 0;
1913
- }
1914
- quill.focus();
1915
- openContextMenu(ev.pageX, ev.pageY);
1916
- });
1917
- };
1918
- // ===============================
1919
- // Utils: clear và select cells
1920
- // ===============================
1921
- const clearSelection = () => {
1922
- document.querySelectorAll('.selected-cell').forEach((c) => {
1923
- c.classList.remove('selected-cell');
1924
- });
1925
- };
1926
- const selectRangeCells = (start, end) => {
1927
- clearSelection();
1928
- const table = start.closest('table');
1929
- if (!table || table !== end.closest('table'))
1930
- return;
1931
- const rows = Array.from(table.querySelectorAll('tr'));
1932
- const startRow = rows.indexOf(start.parentElement);
1933
- const endRow = rows.indexOf(end.parentElement);
1934
- const minRow = Math.min(startRow, endRow);
1935
- const maxRow = Math.max(startRow, endRow);
1936
- const startCol = Array.from(start.parentElement.children).indexOf(start);
1937
- const endCol = Array.from(end.parentElement.children).indexOf(end);
1938
- const minCol = Math.min(startCol, endCol);
1939
- const maxCol = Math.max(startCol, endCol);
1940
- for (let r = minRow; r <= maxRow; r++) {
1941
- const row = rows[r];
1942
- const cells = Array.from(row.children);
1943
- for (let c = minCol; c <= maxCol; c++) {
1944
- cells[c].classList.add('selected-cell');
1945
- }
1946
- }
1947
- };
1948
- // ===============================
1949
- // Enable selection trên table
1950
- // ===============================
1951
- function enableTableSelection(container) {
1952
- container.addEventListener('mousedown', (e) => {
1953
- const target = e.target;
1954
- if ((target.tagName === 'TD' && e.button !== 2) || (e.button === 2 && !target.classList.contains('selected-cell'))) {
1955
- clearSelection();
1956
- isSelecting = true;
1957
- startCell = target;
1958
- endCell = target;
1959
- selectRangeCells(startCell, endCell);
1960
- }
1961
- });
1962
- container.addEventListener('mousemove', (e) => {
1963
- if (!isSelecting)
1964
- return;
1965
- const target = e.target;
1966
- if (target.tagName === 'TD' && startCell) {
1967
- endCell = target;
1968
- selectRangeCells(startCell, endCell);
1969
- }
1970
- });
1971
- container.addEventListener('mouseup', () => {
1972
- isSelecting = false;
1973
- });
1974
- }
1975
- const onOutside = (ev) => {
1976
- const target = ev.target;
1977
- if (target.tagName !== 'TD' && target.tagName !== 'TR' && target.tagName !== 'TBODY' && target.tagName !== 'THEAD' && target.tagName !== 'TABLE') {
1978
- isSelecting = false;
1979
- startCell = null;
1980
- endCell = null;
1981
- clearSelection();
1982
- }
1983
- };
1984
- document.addEventListener('click', onOutside, true);
1985
- // ===============================
1986
- // Merge cells
1987
- // ===============================
1988
- const mergeCells = (startCell, endCell) => {
1989
- const startCellIndex = startCell.getAttribute('index');
1990
- const endCellIndex = endCell.getAttribute('index');
1991
- const startCellRow = parseInt(startCellIndex?.split('-')[0] || '0', 10);
1992
- const endCellRow = parseInt(endCellIndex?.split('-')[0] || '0', 10);
1993
- const startCellCol = parseInt(startCellIndex?.split('-')[1] || '0', 10);
1994
- const endCellCol = parseInt(endCellIndex?.split('-')[1] || '0', 10);
1995
- const minRow = Math.min(startCellRow, endCellRow);
1996
- const maxRow = Math.max(startCellRow, endCellRow);
1997
- const minCol = Math.min(startCellCol, endCellCol);
1998
- const maxCol = Math.max(startCellCol, endCellCol);
1999
- const rows = startCell.closest('table')?.querySelectorAll('tr');
2000
- rows?.forEach((rowEl, rowIndex) => {
2001
- if (rowIndex < minRow || rowIndex > maxRow)
2002
- return;
2003
- const cells = rowEl.querySelectorAll('td, th');
2004
- cells.forEach((cellEl, colIndex) => {
2005
- if (colIndex < minCol || colIndex > maxCol)
2006
- return;
2007
- if (rowIndex === minRow && colIndex === minCol) {
2008
- cellEl.setAttribute('colspan', String(maxCol - minCol + 1));
2009
- cellEl.setAttribute('rowspan', String(maxRow - minRow + 1));
2010
- return;
2011
- }
2012
- cellEl.classList.add('hidden');
2013
- });
2014
- });
2015
- };
2016
- // ===============================
2017
- // Split cells
2018
- // ===============================
2019
- function splitCells(cellSplit) {
2020
- const index = cellSplit.getAttribute('index');
2021
- let colSpan = parseInt(cellSplit.getAttribute('colspan') || '1', 10);
2022
- let rowSpan = parseInt(cellSplit.getAttribute('rowspan') || '1', 10);
2023
- const totalCellSplit = rowSpan * colSpan;
2024
- let countCellSplit = 0;
2025
- const rowStart = parseInt(index?.split('-')[0] || '0', 10);
2026
- const colStart = parseInt(index?.split('-')[1] || '0', 10);
2027
- const colIncrement = new Set();
2028
- const rowIncrement = new Set();
2029
- const rows = cellSplit.closest('table')?.querySelectorAll('tr');
2030
- rows?.forEach((rowEl, rowIndex) => {
2031
- if (rowIndex < rowStart)
2032
- return;
2033
- const cells = rowEl.querySelectorAll('td, th');
2034
- cells.forEach((cellEl, colIndex) => {
2035
- if (rowIndex < rowStart || colIndex < colStart || rowStart + rowSpan < rowIndex || colStart + colSpan < colIndex || countCellSplit >= totalCellSplit)
2036
- return;
2037
- if (rowIndex === rowStart && colIndex === colStart) {
2038
- countCellSplit++;
2039
- cellEl.setAttribute('colspan', '1');
2040
- cellEl.setAttribute('rowspan', '1');
2041
- return;
2042
- }
2043
- if (!cellEl.classList.contains('hidden')) {
2044
- if (!rowIncrement.has(rowIndex)) {
2045
- rowSpan++;
2046
- }
2047
- if (!colIncrement.has(colIndex)) {
2048
- colSpan++;
2049
- }
2050
- rowIncrement.add(rowIndex);
2051
- colIncrement.add(colIndex);
2052
- return;
2053
- }
2054
- cellEl.classList.remove('hidden');
2055
- countCellSplit++;
2056
- });
2057
- });
2058
- }
2059
- const getAllTablesWithSpan = (quill) => {
2060
- const root = quill.root;
2061
- // Tìm tất cả table trong quill
2062
- const tableEls = root.querySelectorAll('table');
2063
- tableEls.forEach((tableEl) => {
2064
- const rows = tableEl.querySelectorAll('tr');
2065
- rows.forEach((rowEl, rIndex) => {
2066
- rowEl.setAttribute('index', `${rIndex}`);
2067
- const cells = rowEl.querySelectorAll('td, th');
2068
- cells.forEach((cellEl, cIndex) => {
2069
- cellEl.setAttribute('index', `${rIndex}-${cIndex}`);
2070
- const rowspan = parseInt(cellEl.getAttribute('rowspan') || '1', 10);
2071
- const colspan = parseInt(cellEl.getAttribute('colspan') || '1', 10);
2072
- cellEl.setAttribute('rowspan', String(rowspan));
2073
- cellEl.setAttribute('colspan', String(colspan));
2074
- });
2075
- });
2076
- });
2077
- };
2078
- //-------------------------------------------
2079
- let register = false;
2080
- const registerQuill2x = () => {
2081
- if (register)
2082
- return;
2083
- register = true;
2084
- const Quill = Quill2x;
2085
- const size = Quill.import('attributors/style/size');
2086
- const alignStyle = Quill.import('attributors/style/align');
2087
- const italic = Quill.import('formats/italic');
2088
- const bold = Quill.import('formats/bold');
2089
- const icons = Quill.import('ui/icons');
2090
- size.whitelist = fontSizeWhiteList();
2091
- italic.tagName = 'i';
2092
- bold.tagName = 'b';
2093
- Quill.register(bold, true);
2094
- Quill.register(italic, true);
2095
- Quill.register(size, true);
2096
- Quill.register(alignStyle, true);
2097
- Quill.register(QuillMention2xBlot, true);
2098
- Quill.register(CustomImage2xBlot, true);
2099
- Quill.register('modules/resize', ResizeModule);
2100
- [...iconList()].forEach((element) => set(icons, element.key, `<span class="${element.icon} ${element.key === 'unLink' ? 'hover:text-[#ee2d41] ' : 'hover:text-[var(--libs-ui-color-light-1)]'} text-[16px] text-[#6a7383]"></span>`));
2101
- };
2102
- const isEmptyQuill2x = (quill) => {
2103
- const rootElement = quill?.root;
2104
- if (!rootElement)
2105
- return true;
2106
- const html = rootElement.innerHTML.trim();
2107
- return html === '<p><br></p>' || html === '<p></p>' || html === '' || html === '<p><span class="ql-cursor"></span><br></p>' || rootElement.classList.contains('ql-blank');
2108
- };
2109
- const getHTMLFromDeltaOfQuill2x = (delta, options) => {
2110
- if (!delta || !delta.ops || !delta.ops.length) {
2111
- return '';
2112
- }
2113
- if (!quill2x) {
2114
- quill2x = new Quill2x(document.createElement('div'));
2115
- }
2116
- const { replaceNewLineTo = '<br>', replaceTagBRTo, replaceTags, replaceBrToDiv } = options || {};
2117
- if (options?.functionReplaceDelta) {
2118
- options.functionReplaceDelta(delta);
2119
- }
2120
- delta.ops.forEach((op) => {
2121
- if (op.insert) {
2122
- if (typeof op.insert === 'string') {
2123
- if (replaceNewLineTo) {
2124
- op.insert = op.insert.replace(/\n/g, replaceNewLineTo);
2125
- }
2126
- if (replaceTagBRTo) {
2127
- op.insert = op.insert.replace(/<br>/g, replaceTagBRTo);
2128
- }
2129
- if (replaceTags?.length) {
2130
- for (const tag of replaceTags) {
2131
- op.insert = op.insert.replace(new RegExp(`<${tag.tag}>`, 'g'), `<${tag.replaceTo}>`);
2132
- op.insert = op.insert.replace(new RegExp(`</${tag.tag}>`, 'g'), `</${tag.replaceTo}>`);
2133
- }
2134
- }
2135
- }
2136
- }
2137
- });
2138
- quill2x.setContents(delta);
2139
- let htmlText = options?.getRootHtml ? quill2x.root.innerHTML : quill2x.root.firstElementChild?.innerHTML;
2140
- if (replaceBrToDiv) {
2141
- htmlText = convertHtmlToDivBlocks(htmlText || '');
2142
- }
2143
- clearTimeout(timeout);
2144
- timeout = setTimeout(() => {
2145
- quill2x = null;
2146
- }, 10000);
2147
- return decodeEscapeHtml(htmlText || '');
2148
- };
2149
- const getDeltaOfQuill2xFromHTML = async (html) => {
2150
- if (!quill2x) {
2151
- quill2x = new Quill2x(document.createElement('div'));
2152
- }
2153
- quill2x.root.innerHTML = html;
2154
- await lastValueFrom$1(timer$1(1000));
2155
- clearTimeout(timeout1);
2156
- timeout1 = setTimeout(() => {
2157
- quill2x = null;
2158
- }, 10000);
2159
- return quill2x.getContents();
2160
- };
2161
-
2162
- /* eslint-disable @typescript-eslint/no-explicit-any */
2163
- class LibsUiComponentsInputsQuill2xComponent {
2164
- //region Private
2165
- displayEditor = signal(false);
2166
- isPaste = signal(false);
2167
- quill = null;
2168
- addEditLinkComponentRef = signal(undefined);
2169
- uploadImageComponentRef = signal(undefined);
2170
- handlers = signal({
2171
- link: this.handleShowUploadLink.bind(this),
2172
- undo: this.handleUndo.bind(this),
2173
- redo: this.handleRedo.bind(this),
2174
- table: this.handleTable.bind(this),
2175
- image: this.handlerShowUploadImage.bind(this),
2176
- });
2177
- timerSetFontSize = signal(undefined);
2178
- timerCalculatorToolbar = signal(undefined);
2179
- totalRecallCalculatorToolbar = signal(0);
2180
- isCalculatorToolbarSuccess = signal(false);
2181
- showMention = signal(false);
2182
- handlerTextChangeBind = this.handlerTextChange.bind(this);
2183
- handlerSelectionChangeBind = this.handlerSelectionChange.bind(this);
2184
- //endregion
2185
- //region Protected
2186
- borderColor = computed(() => (this.messageError() && this.showErrorBorder() ? ' !border-[var(--libs-ui-color-border-error,#ee2d41)] ' : '!border-[#e5e7eb] '));
2187
- containerClass = computed(() => `quill-container flex flex-col h-full w-full ${get(this.quillCustomConfig(), 'classContainer') || ''}`);
2188
- containerToolbarClass = computed(() => `h-full border-t border-l border-r ${this.ignoreShowBorderErrorToolbar() ? '!border-[#e5e7eb] ' : this.borderColor()}rounded-t-[4px] ${this.readonly() ? ' libs-ui-readonly-background cursor-default pointer-events-none ' : ' '} ${get(this.quillCustomConfig(), 'toolbar.classCustomContainerToolbar') || ''} ${get(this.quillCustomConfig(), 'toolbar.positionFixed') ? ' fixed ' : ' '}`);
2189
- containerEditorClass = computed(() => `${this.displayEditor() ? 'h-full' : 'hidden'} !border ${this.borderColor()} !rounded-b-[4px] ${this.readonly() ? ' libs-ui-readonly-background ' : ' '} ${get(this.quillCustomConfig(), 'editor.classCustomContainerEditor') || ''} ${get(this.quillCustomConfig(), 'toolbar.positionFixed') ? ' rounded-t-[4px] ' : ' '}`);
2190
- showButtonMoreToolbar = computed(() => this.toolbarOptionsConfig().some((item) => item.display === false));
2191
- displaySkeletonToolbar = computed(() => this.toolbarOptionsConfig().every((item) => item.display === undefined));
2192
- labelFontSelectedComputed = computed(() => get(this.fontSelected(), 'item.label') || 'Sans Serif');
2193
- fontSelected = signal(undefined);
2194
- listConfigFont = signal(listConfigFont());
2195
- listConfigHeader = signal(listConfigHeader());
2196
- headerSelected = signal(undefined);
2197
- labelHeaderSelectedComputed = computed(() => get(this.headerSelected(), 'item.label') || 'Normal');
2198
- listConfigAlign = signal(listConfigAlign());
2199
- alignSelected = signal(undefined);
2200
- iconAlignSelectedComputed = computed(() => get(this.alignSelected(), 'item.icon'));
2201
- colorSelected = signal(undefined);
2202
- backgroundSelected = signal(undefined);
2203
- listCheckboxSelected = signal(false);
2204
- adjustSelected = signal(undefined);
2205
- messageError = signal('');
2206
- fontSize = signal({ value: 14 });
2207
- link = signal(linkDefault());
2208
- showMoreAction = signal(false);
2209
- toolbarOptionsConfig = signal([]);
2210
- loadingUploadImage = signal(false);
2211
- uploadImageConfig = input(uploadImageConfigDefault(), { transform: (value) => value || uploadImageConfigDefault() });
2212
- //region Inputs
2213
- displayToolbar = input(true, { transform: (value) => value ?? true });
2214
- placeholder = input('i18n_import_content', { transform: (value) => value || 'i18n_import_content' });
2215
- blotsRegister = input();
2216
- readonly = input(false, { transform: (value) => value ?? false });
2217
- quillCustomConfig = input();
2218
- label = input();
2219
- item = model.required();
2220
- fieldBind = input.required();
2221
- autoUpdateValueWhenTextChange = input(true, { transform: (value) => value ?? true });
2222
- dataConfigMention = input();
2223
- templateToolBarPersonalize = input();
2224
- zIndex = input(1250, { transform: (value) => value ?? 1250 });
2225
- ignoreShowPopupEditLink = input();
2226
- ignoreCommunicateMicroEventPopup = input();
2227
- handlersExpand = input();
2228
- resizeImagePlugin = input();
2229
- fontSizeDefault = input(14, { transform: (value) => value ?? 14 });
2230
- heightEditorContentDefault = input();
2231
- minHeightEditorContentDefault = input();
2232
- maxHeightEditorContentDefault = input();
2233
- removeNearWhiteColorsOnPaste = input(true);
2234
- resize = input('none', { transform: (value) => value ?? 'none' });
2235
- autoFocus = input();
2236
- focusTimerOnInit = input(750, { transform: (value) => value ?? 750 });
2237
- focusBottom = input();
2238
- validRequired = input();
2239
- validMinLength = input();
2240
- validMaxLength = input();
2241
- showErrorLabel = input(true, { transform: (val) => val ?? true });
2242
- showErrorBorder = input(true);
2243
- ignoreShowBorderErrorToolbar = input();
2244
- //endregion
2245
- //region Outputs
2246
- outShowPopupEditLink = output();
2247
- outMessageError = output();
2248
- outBlur = output();
2249
- outFocus = output();
2250
- outChange = output();
2251
- outSelectionChange = output();
2252
- outTextChange = output();
2253
- outContextMenu = output();
2254
- outFunctionsControl = output();
2255
- //endregion
2256
- //region ViewChild
2257
- htmlContainer = viewChild.required('htmlContainer');
2258
- quillBodyContainer = viewChild.required('snowContainer');
2259
- toolbarContainer = viewChild.required('toolbarContainer');
2260
- inputLinkRef = viewChild.required('inputLinkRef');
2261
- //endregion
2262
- //region Inject
2263
- destroyRef = inject(DestroyRef);
2264
- notificationService = inject(LibsUiNotificationService);
2265
- translate = inject(TranslateService);
2266
- cdr = inject(ChangeDetectorRef);
2267
- dynamicComponentService = inject(LibsUiDynamicComponentService);
2268
- //endregion
2269
- constructor() {
2270
- effect(() => {
2271
- if (this.fontSizeDefault()) {
2272
- untracked(() => {
2273
- this.fontSize.set({ value: this.fontSizeDefault() });
2274
- this.handlerValueChangeFontSize();
2275
- });
2276
- }
2277
- });
2278
- effect(() => {
2279
- const elementEditor = this.quillBodyContainer().nativeElement.getElementsByClassName('ql-editor')?.[0];
2280
- if (this.heightEditorContentDefault()) {
2281
- untracked(() => {
2282
- if (elementEditor) {
2283
- elementEditor.style.height = `${this.heightEditorContentDefault()}px`;
2284
- }
2285
- });
2286
- }
2287
- if (this.minHeightEditorContentDefault()) {
2288
- untracked(() => {
2289
- if (elementEditor) {
2290
- elementEditor.style.minHeight = `${this.minHeightEditorContentDefault()}px`;
2291
- }
2292
- });
2293
- }
2294
- if (this.maxHeightEditorContentDefault()) {
2295
- untracked(() => {
2296
- if (elementEditor) {
2297
- elementEditor.style.maxHeight = `${this.maxHeightEditorContentDefault()}px`;
2298
- }
2299
- });
2300
- }
2301
- });
2302
- }
2303
- async ngOnInit() {
2304
- const type = get(this.quillCustomConfig(), 'toolbar.type', 'default');
2305
- const hasIconImage = this.uploadImageConfig().showIcon ?? false;
2306
- const hasIconPersonalize = !!this.templateToolBarPersonalize();
2307
- this.toolbarOptionsConfig.set(get(this.quillCustomConfig(), 'toolbar.options', toolBarOptions(type, hasIconImage, hasIconPersonalize)));
2308
- this.calculatorToolbar();
2309
- registerQuill2x();
2310
- this.blotsRegister()?.forEach((item) => {
2311
- Quill2x.register(item.component, true);
2312
- });
2313
- this.updateHandlerFunction();
2314
- const options = {
2315
- theme: 'snow',
2316
- placeholder: this.translate.instant(this.placeholder()),
2317
- readOnly: this.readonly(),
2318
- modules: {
2319
- toolbar: {
2320
- container: this.toolbarContainer().nativeElement,
2321
- handlers: this.handlers(),
2322
- },
2323
- resize: this.resizeImagePlugin()
2324
- ? {
2325
- locale: {
2326
- altTip: this.translate.instant('i18n_keep_alt_key_to_change_the_ratio_when_changing_the_size'),
2327
- inputTip: this.translate.instant('i18n_press_enter_to_confirm'),
2328
- floatLeft: this.translate.instant('i18n_left_align'),
2329
- floatRight: this.translate.instant('i18n_right_align'),
2330
- center: this.translate.instant('i18n_center_align'),
2331
- restore: this.translate.instant('i18n_restore_to_default'),
2332
- },
2333
- }
2334
- : undefined,
2335
- table: true,
2336
- clipboard: {
2337
- matchers: [
2338
- [Node.TEXT_NODE, (node) => new Delta().insert(node.data)],
2339
- this.removeNearWhiteColorsOnPaste()
2340
- ? [
2341
- Node.ELEMENT_NODE,
2342
- (node, delta) => {
2343
- const style = node.getAttribute('style');
2344
- if (style && this.isPaste()) {
2345
- const newOps = delta.ops.map((op) => {
2346
- if (op.attributes) {
2347
- const newAttrs = { ...op.attributes };
2348
- const color = newAttrs.color;
2349
- const background = newAttrs.background;
2350
- if (color && isNearWhite(color)) {
2351
- delete newAttrs.color;
2352
- }
2353
- if (background && isNearWhite(background)) {
2354
- delete newAttrs.background;
2355
- }
2356
- return { ...op, attributes: Object.keys(newAttrs).length ? newAttrs : undefined };
2357
- }
2358
- return op;
2359
- });
2360
- return new Delta(newOps);
2361
- }
2362
- return delta;
2363
- },
2364
- ]
2365
- : [],
2366
- ],
2367
- },
2368
- keyboard: {
2369
- bindings: {
2370
- backspace: {
2371
- key: UtilsKeyCodeConstant.BACKSPACE,
2372
- handler: (range) => this.noPreventEmbedDeletion(range),
2373
- },
2374
- delete: {
2375
- key: UtilsKeyCodeConstant.DELETE,
2376
- handler: (range) => this.noPreventEmbedDeletion(range),
2377
- },
2378
- enter: {
2379
- key: 13,
2380
- handler: () => (this.showMention() ? false : true),
2381
- },
2382
- },
2383
- },
2384
- history: {
2385
- delay: 2000,
2386
- maxStack: 500,
2387
- userOnly: true,
2388
- },
2389
- },
2390
- };
2391
- this.quill = new Quill2x(this.quillBodyContainer().nativeElement, options);
2392
- this.quill?.on('text-change', this.handlerTextChangeBind);
2393
- this.quill?.on('selection-change', this.handlerSelectionChangeBind);
2394
- fromEvent(this.quill?.root, 'copy').pipe(takeUntilDestroyed(this.destroyRef)).subscribe(this.handlerCopy.bind(this));
2395
- fromEvent(this.quill?.root, 'paste', { capture: true }).pipe(takeUntilDestroyed(this.destroyRef)).subscribe(this.handlerPaste.bind(this));
2396
- fromEvent(this.quillBodyContainer()?.nativeElement, 'contextmenu')
2397
- .pipe(takeUntilDestroyed(this.destroyRef))
2398
- .subscribe((e) => this.outContextMenu.emit(e));
2399
- fromEvent(window, 'resize')
2400
- .pipe(takeUntilDestroyed(this.destroyRef))
2401
- .subscribe(() => this.calculatorToolbar(true));
2402
- this.outFunctionsControl.emit(this.FunctionsControl);
2403
- await this.setContent(this.item()[this.fieldBind()]);
2404
- timer$1(this.autoFocus() ? 0 : 250)
2405
- .pipe(takeUntilDestroyed(this.destroyRef))
2406
- .subscribe(() => this.displayEditor.set(true));
2407
- this.setStyleForContent();
2408
- if (this.autoFocus()) {
2409
- timer$1(this.focusTimerOnInit() + 250)
2410
- .pipe(takeUntilDestroyed(this.destroyRef))
2411
- .subscribe(() => this.focus());
2412
- }
2413
- createContextMenuOptionTable(this.quill, this.translate);
2414
- enableTableSelection(this.quill.root);
2415
- getAllTablesWithSpan(this.quill);
2416
- const rootElement = this.quill?.root;
2417
- if (!rootElement) {
2418
- return;
2419
- }
2420
- merge(fromEvent(rootElement, 'compositionstart'), fromEvent(rootElement, 'compositionend'))
2421
- .pipe(takeUntilDestroyed(this.destroyRef))
2422
- .subscribe((e) => {
2423
- if (e.type === 'compositionstart') {
2424
- rootElement.classList.remove('ql-blank');
2425
- return;
2426
- }
2427
- if (isEmptyQuill2x(this.quill)) {
2428
- rootElement.classList.add('ql-blank');
2429
- return;
2430
- }
2431
- rootElement.classList.remove('ql-blank');
2432
- });
2433
- }
2434
- get FunctionsControl() {
2435
- return {
2436
- quill: () => this.quill,
2437
- checkIsValid: this.validate.bind(this),
2438
- refreshItemValue: this.updateValueByRootQuillHtml.bind(this),
2439
- setContent: this.setContent.bind(this),
2440
- insertText: this.insertText.bind(this),
2441
- insertLink: this.insertLink.bind(this),
2442
- insertImage: this.insertImage.bind(this),
2443
- setFontSize: async (size) => this.quill?.format('size', `${size}px`),
2444
- setColor: async (color) => this.quill?.format('color', color),
2445
- setBackground: async (color) => this.quill?.format('background', color),
2446
- setMessageError: async (message) => this.messageError.set(message),
2447
- reCalculatorToolbar: async () => this.calculatorToolbar(true),
2448
- };
2449
- }
2450
- //region handler Event HTML
2451
- handlerChangeShowMoreAction(event) {
2452
- event.stopPropagation();
2453
- this.showMoreAction.update((showMoreAction) => !showMoreAction);
2454
- }
2455
- handleSelectFont(event) {
2456
- this.fontSelected.set(event);
2457
- this.quill?.format('font', event?.key);
2458
- }
2459
- handleSelectHeader(event) {
2460
- this.headerSelected.set(event);
2461
- this.quill?.format('header', event?.key);
2462
- }
2463
- handlerValueChangeFontSize(event) {
2464
- if (!event || event?.name === 'blur') {
2465
- this.quill?.format('size', `${this.fontSize().value}px`);
2466
- }
2467
- }
2468
- handleSelectAlign(event) {
2469
- this.alignSelected.set(event);
2470
- this.quill?.format('align', event?.key);
2471
- }
2472
- handlerSetFormat(type, data) {
2473
- if (!data.alpha) {
2474
- this.quill?.format(type, undefined);
2475
- return;
2476
- }
2477
- this.quill?.format(type, data.hex);
2478
- }
2479
- handlerInsertEmoji(emoji) {
2480
- this.insertText(emoji, undefined, true);
2481
- }
2482
- handlerUnlink(event) {
2483
- event.stopPropagation();
2484
- const link = this.link();
2485
- this.quill?.formatText(link.range.index, link.range.length, { link: false });
2486
- this.inputLinkRef().FunctionsControl?.removePopoverOverlay();
2487
- }
2488
- handlerEditLink(event) {
2489
- event.stopPropagation();
2490
- const link = this.link();
2491
- if (this.ignoreShowPopupEditLink()) {
2492
- this.outShowPopupEditLink.emit({
2493
- dataLink: link,
2494
- callback: async (linkEdit) => {
2495
- if (link instanceof Object && link.url) {
2496
- this.quill?.deleteText(link.range.index, link.range.length, Quill2x.sources.USER);
2497
- this.quill?.insertText(link.range.index, linkEdit.title, 'link', linkEdit.link);
2498
- return;
2499
- }
2500
- this.insertLink(linkEdit.title, linkEdit.link);
2501
- },
2502
- });
2503
- return;
2504
- }
2505
- this.handleShowUploadLink(link);
2506
- this.inputLinkRef().FunctionsControl?.removePopoverOverlay();
2507
- }
2508
- handleToggleMention(show) {
2509
- this.showMention.set(show);
2510
- }
2511
- handlerInsertMention(data) {
2512
- this.insertMention(data);
2513
- }
2514
- //endregion
2515
- //region Private Method
2516
- //region Quill Methods
2517
- handleTable() {
2518
- const button = this.htmlContainer().nativeElement.querySelector?.('button.ql-table');
2519
- createTableSelector(this.quill, button, this.translate);
2520
- }
2521
- handleUndo() {
2522
- this.quill?.history?.undo();
2523
- }
2524
- handleRedo() {
2525
- this.quill?.history?.redo();
2526
- }
2527
- handlerShowUploadImage() {
2528
- if (this.uploadImageConfig().modeCustom) {
2529
- this.uploadImageComponentRef.set(this.dynamicComponentService.resolveComponentFactory(LibsUiComponentsInputsQuillUploadImageComponent));
2530
- const instance = this.uploadImageComponentRef()?.instance;
2531
- this.uploadImageComponentRef()?.setInput('uploadImageConfig', this.uploadImageConfig());
2532
- this.uploadImageComponentRef()?.setInput('ignoreCommunicateMicroEvent', this.ignoreCommunicateMicroEventPopup());
2533
- instance?.outClose.subscribe((link) => {
2534
- this.dynamicComponentService.remove(this.uploadImageComponentRef());
2535
- if (link) {
2536
- this.insertImage(link);
2537
- }
2538
- });
2539
- this.dynamicComponentService.addToBody(this.uploadImageComponentRef());
2540
- return;
2541
- }
2542
- const input = document.createElement('input');
2543
- input.setAttribute('type', 'file');
2544
- input.setAttribute('accept', 'image/*');
2545
- input.click();
2546
- input.onchange = async () => {
2547
- await this.uploadImagesAndInsert(input?.files);
2548
- };
2549
- }
2550
- async insertText(content, index, focusLastValueInsert) {
2551
- index = index ?? this.quill?.getSelection(true).index;
2552
- if (!isNil(index)) {
2553
- this.quill?.insertText(index, content, Quill2x.sources.USER);
2554
- if (focusLastValueInsert) {
2555
- await lastValueFrom$1(timer$1(0));
2556
- this.quill?.setSelection(index + content.length, 0, Quill2x.sources.USER);
2557
- }
2558
- }
2559
- }
2560
- handlerSelectionChange(range, oldRange, source) {
2561
- if (this.readonly()) {
2562
- return;
2563
- }
2564
- if (range === null && oldRange !== null) {
2565
- this.outBlur.emit();
2566
- return;
2567
- }
2568
- if (range !== null && oldRange === null) {
2569
- this.outFocus.emit();
2570
- return;
2571
- }
2572
- const format = this.updateStateToolbarByFormatInCursor();
2573
- this.outSelectionChange.emit({
2574
- quill: this.quill,
2575
- range,
2576
- oldRange,
2577
- source,
2578
- });
2579
- if (range.length !== 0 || !format?.link || source !== 'user') {
2580
- return;
2581
- }
2582
- const selection = document.getSelection();
2583
- const anchorNode = selection?.anchorNode;
2584
- let linkNode = anchorNode;
2585
- while (linkNode && linkNode.tagName !== 'A') {
2586
- linkNode = linkNode.parentNode;
2587
- }
2588
- if (!linkNode || linkNode.tagName !== 'A') {
2589
- return;
2590
- }
2591
- const linkText = linkNode.innerText;
2592
- const linksIndices = [];
2593
- let indexReturn = -1;
2594
- while (!isNil(indexReturn) && indexReturn < range.index) {
2595
- const textContent = this.quill?.getText();
2596
- const linkIndex = textContent?.indexOf(linkText, linksIndices.length > 0 ? linksIndices[linksIndices.length - 1] + linkText.length : 0);
2597
- if (!isNil(linkIndex)) {
2598
- if (linkIndex !== -1) {
2599
- linksIndices.push(linkIndex);
2600
- indexReturn = linkIndex + linkText.length;
2601
- }
2602
- if (linkIndex === -1) {
2603
- indexReturn = undefined;
2604
- }
2605
- }
2606
- }
2607
- if (linksIndices && linksIndices.length) {
2608
- const rangeIndex = linksIndices[linksIndices.length - 1];
2609
- const countImage = this.adjustIndexForImages(rangeIndex);
2610
- setTimeout(() => {
2611
- this.link.set({
2612
- title: linkText,
2613
- url: linkNode.href,
2614
- range: {
2615
- index: rangeIndex + countImage,
2616
- length: linkText.length,
2617
- },
2618
- });
2619
- this.inputLinkRef().FunctionsControl?.showPopover(linkNode);
2620
- });
2621
- }
2622
- }
2623
- handlerCopy(e) {
2624
- if (!this.quill)
2625
- return;
2626
- const sel = this.quill.getSelection();
2627
- if (!sel || sel.length === 0)
2628
- return;
2629
- e.preventDefault();
2630
- const delta = this.quill.getContents(sel.index, sel.length);
2631
- const html2x = getHTMLFromDeltaOfQuill2x(delta);
2632
- if (e.clipboardData) {
2633
- e.clipboardData.setData('text/html', html2x);
2634
- }
2635
- }
2636
- async handlerPaste(event) {
2637
- this.isPaste.set(true);
2638
- setTimeout(() => this.isPaste.set(false), 0);
2639
- if (!event || !event.clipboardData) {
2640
- return;
2641
- }
2642
- const files = event.clipboardData.files;
2643
- if (!files.length) {
2644
- return;
2645
- }
2646
- event.preventDefault();
2647
- await this.uploadImagesAndInsert(files);
2648
- }
2649
- handlerTextChange(event, _, source) {
2650
- this.outTextChange.emit({
2651
- quill: this.quill,
2652
- delta: event,
2653
- });
2654
- setTimeout(() => {
2655
- this.detectLink(source);
2656
- this.updateStateToolbarByFormatInCursor();
2657
- if (event?.ops[1]?.insert === '\n') {
2658
- const range = { index: event?.ops[0].retain };
2659
- const currentLeaf = this.quill?.getLeaf(range.index)[0];
2660
- const nextLeaf = this.quill?.getLeaf(range.index + 1)[0];
2661
- this.quill?.insertEmbed(range.index, 'break', true, 'user');
2662
- if (nextLeaf === null || currentLeaf.parent !== nextLeaf.parent) {
2663
- this.quill?.insertEmbed(range.index, 'break', true, 'user');
2664
- }
2665
- this.quill?.setSelection((range.index || 0) + 1, 0, Quill2x.sources.SILENT);
2666
- }
2667
- });
2668
- if (!this.autoUpdateValueWhenTextChange()) {
2669
- return;
2670
- }
2671
- this.updateValueByRootQuillHtml();
2672
- }
2673
- //endregion
2674
- updateStateToolbarByFormatInCursor() {
2675
- try {
2676
- const format = this.quill?.getFormat();
2677
- if (format) {
2678
- this.setFontSizeSelected(format);
2679
- this.setFontSelected(format);
2680
- this.setColorSelected(format);
2681
- this.listCheckboxSelected.set(format?.list === 'unchecked' || format?.list === 'checked');
2682
- this.adjustSelected.set(format?.align);
2683
- }
2684
- return format;
2685
- }
2686
- catch (error) {
2687
- console.log(error);
2688
- return undefined;
2689
- }
2690
- }
2691
- async validate() {
2692
- this.messageError.set('');
2693
- const validRequired = this.validRequired();
2694
- const item = this.item();
2695
- const fieldNameBind = this.fieldBind();
2696
- const value = get(item, fieldNameBind);
2697
- if (validRequired && validRequired.isRequired && !this.readonly() && isEmptyQuill2x(this.quill)) {
2698
- this.messageError.set(validRequired.message || ERROR_MESSAGE_EMPTY_VALID);
2699
- this.outMessageError.emit(this.messageError());
2700
- return false;
2701
- }
2702
- const validMinLength = this.validMinLength();
2703
- if (validMinLength && fieldNameBind && value && value.trim().length < validMinLength.length) {
2704
- this.messageError.set(validMinLength.message || ERROR_MESSAGE_MIN_LENGTH);
2705
- this.outMessageError.emit(this.messageError());
2706
- return false;
2707
- }
2708
- const validMaxLength = this.validMaxLength();
2709
- if (validMaxLength && fieldNameBind && value && value.trim().length > this.validMaxLength.length) {
2710
- this.messageError.set(validMaxLength.message || ERROR_MESSAGE_MAX_LENGTH);
2711
- this.outMessageError.emit(this.messageError());
2712
- return false;
2713
- }
2714
- this.outMessageError.emit(this.messageError());
2715
- return true;
2716
- }
2717
- updateHandlerFunction() {
2718
- const handlersExpand = this.handlersExpand();
2719
- if (handlersExpand && handlersExpand.length) {
2720
- handlersExpand.forEach((element) => {
2721
- if (element.title && element.action) {
2722
- this.handlers.update((item) => ({ ...item, [element.title]: element.action }));
2723
- }
2724
- });
2725
- }
2726
- }
2727
- noPreventEmbedDeletion(range) {
2728
- if (!this.quill)
2729
- return false;
2730
- const delta = this.quill?.getContents(range.index, 1);
2731
- if (delta?.ops.some((option) => this.blotsRegister()?.find((item) => get(option.insert, item.component['blotName']) && item.ignoreDelete))) {
2732
- return false; // Ngăn không cho Quill xử lý xóa
2733
- }
2734
- return true;
2735
- }
2736
- setFontSizeSelected(format) {
2737
- const fontSize = format?.size?.toString()?.replace('px', '');
2738
- if (isNaN(parseFloat(fontSize))) {
2739
- this.fontSize.set({ value: this.fontSizeDefault() });
2740
- // this.handlerValueChangeFontSize();
2741
- return;
2742
- }
2743
- this.fontSize.set({ value: parseFloat(fontSize) });
2744
- }
2745
- setFontSelected(format) {
2746
- const font = listFont().find((item) => item.key === format.font);
2747
- if (!font) {
2748
- this.fontSelected.set({ key: '', item: listFont().find((item) => item.key === '') });
2749
- return;
2750
- }
2751
- this.fontSelected.set({ key: format.font, item: font });
2752
- }
2753
- setColorSelected(format) {
2754
- this.colorSelected.set(format?.color);
2755
- this.backgroundSelected.set(format?.background);
2756
- }
2757
- async calculatorToolbar(resetTotalRecall) {
2758
- clearTimeout(this.timerCalculatorToolbar());
2759
- if (resetTotalRecall) {
2760
- this.totalRecallCalculatorToolbar.set(0);
2761
- }
2762
- this.cdr.detectChanges();
2763
- const toolbarWidth = this.toolbarContainer().nativeElement.offsetWidth || 0;
2764
- let totalWidth = 84;
2765
- if (!this.isCalculatorToolbarSuccess() && this.totalRecallCalculatorToolbar() < 10 && toolbarWidth < get(this.quillCustomConfig(), 'toolbar.lessWidthToolbarRecallCalculator', totalWidth)) {
2766
- this.totalRecallCalculatorToolbar.update((val) => val + 1);
2767
- this.timerCalculatorToolbar.set(setTimeout(() => {
2768
- this.calculatorToolbar();
2769
- }, 250));
2770
- return;
2771
- }
2772
- this.isCalculatorToolbarSuccess.set(true);
2773
- this.toolbarOptionsConfig.update((configs) => {
2774
- configs.forEach((item, index) => {
2775
- item.display = true;
2776
- totalWidth += item.width;
2777
- if (item.type === 'line') {
2778
- const nextItemWidth = totalWidth + this.toolbarOptionsConfig()[+index + 1].width;
2779
- const preItem = this.toolbarOptionsConfig()[+index - 1];
2780
- if (nextItemWidth > toolbarWidth && preItem.display === true) {
2781
- item.display = undefined;
2782
- return;
2783
- }
2784
- }
2785
- if (totalWidth > toolbarWidth) {
2786
- item.display = false;
2787
- return;
2788
- }
2789
- });
2790
- return [...configs];
2791
- });
2792
- this.cdr.detectChanges();
2793
- }
2794
- setStyleForContent() {
2795
- const styleArray = [
2796
- { selector: '.ql-font-Arial', style: 'font-family: Arial' },
2797
- { selector: '.ql-font-sans-serif', style: 'font-family: sans-serif' },
2798
- { selector: '.ql-font-serif', style: 'font-family: serif' },
2799
- { selector: '.ql-font-monospace', style: 'font-family: monospace' },
2800
- { selector: '.ql-font-Helvetica', style: 'font-family: Helvetica' },
2801
- { selector: '.libs-ui-quill-format-image', style: 'max-width: 100%; height: auto', overrideStyle: true },
2802
- { selector: '.libs-ui-quill-mention', style: 'font-weight: 600;-moz-osx-font-smoothing: grayscale;-webkit-font-smoothing: antialiased; color: #7239EA', overrideStyle: true },
2803
- { selector: 'blockquote', style: 'border-left: 4px solid #ccc; margin-bottom: 5px; margin-top: 5px; padding-left: 16px', overrideStyle: true },
2804
- ];
2805
- this.blotsRegister()?.forEach((item) => {
2806
- styleArray.push({ selector: `.${item.className}`, style: item.style, overrideStyle: true });
2807
- });
2808
- styleArray.forEach((item) => {
2809
- const elements = this.quill?.root.querySelectorAll(item.selector);
2810
- elements?.forEach((element) => {
2811
- if (item.overrideStyle) {
2812
- element.setAttribute('style', item.style);
2813
- return;
2814
- }
2815
- // Fixbug issue: https://admin-cv.mobio.vn/issues/49092
2816
- let styleExist = element.getAttribute('style');
2817
- if (styleExist) {
2818
- ['font-family: Arial', 'font-family: sans-serif', 'font-family: serif', 'font-family: monospace', 'font-family: Helvetica'].forEach((font) => {
2819
- styleExist = (styleExist?.includes(`${font};`) ? styleExist?.replace(`${font};`, '') : styleExist?.replace(font, ''));
2820
- });
2821
- }
2822
- element.setAttribute('style', styleExist ? `${styleExist}${styleExist[styleExist.length - 1] === ';' ? '' : ';'}${item.style};` : item.style);
2823
- });
2824
- });
2825
- }
2826
- async setContent(content) {
2827
- if (!this.quill) {
2828
- return;
2829
- }
2830
- const contentXssFilter = await xssFilter(this.removeUnwantedPart(content || ''));
2831
- this.quill.clipboard.dangerouslyPasteHTML(contentXssFilter, Quill2x.sources.SILENT);
2832
- this.quill.blur();
2833
- }
2834
- adjustIndexForImages(index) {
2835
- const content = this.quill?.root;
2836
- let imageCount = 0;
2837
- let adjustedIndex = 0;
2838
- const adjustTextIndex = (node) => {
2839
- if (adjustedIndex > index) {
2840
- return;
2841
- }
2842
- if (node.nodeType === Node.TEXT_NODE) {
2843
- adjustedIndex += node.textContent?.length || 0;
2844
- return;
2845
- }
2846
- if (node.nodeType === Node.ELEMENT_NODE && node.nodeName === 'IMG') {
2847
- if (adjustedIndex <= index) {
2848
- imageCount++;
2849
- }
2850
- return;
2851
- }
2852
- if (node.nodeType === Node.ELEMENT_NODE) {
2853
- Array.from(node.childNodes).forEach(adjustTextIndex);
2854
- }
2855
- };
2856
- adjustTextIndex(content);
2857
- return imageCount;
2858
- }
2859
- async uploadImagesAndInsert(files) {
2860
- if (!files) {
2861
- return;
2862
- }
2863
- const maxImageSize = this.uploadImageConfig()?.maxImageSize || 5 * 1024 * 1024;
2864
- const images = Array.from(files).filter((file) => file && file.type.split('/')[0] === 'image' && (!this.uploadImageConfig().maxImageSize || file.size <= maxImageSize));
2865
- if (!images.length) {
2866
- this.notificationService.showCompTypeTextWarning(this.translate.instant('i18n_note_upload_image_volume', { value: getLabelBySizeFile(maxImageSize) }), { timeRemove: 8000 });
2867
- return;
2868
- }
2869
- try {
2870
- this.loadingUploadImage.set(true);
2871
- const indexInsert = this.quill?.getSelection(true).index;
2872
- const links = await this.uploadImageConfig().functionUploadImage?.(images);
2873
- if (!links?.length) {
2874
- return;
2875
- }
2876
- links.forEach((link) => {
2877
- if (!link || (this.uploadImageConfig().onlyAcceptImageHttpsLink && (link instanceof ArrayBuffer || !new RegExp(patternUrl()).test(link)))) {
2878
- return;
2879
- }
2880
- this.insertImage(link, indexInsert);
2881
- });
2882
- }
2883
- catch (error) {
2884
- console.error(error);
2885
- }
2886
- finally {
2887
- this.loadingUploadImage.set(false);
2888
- }
2889
- return;
2890
- }
2891
- async insertImage(content, index) {
2892
- const selection = index ?? this.quill?.getSelection(true).index;
2893
- if (!isNil(selection)) {
2894
- this.quill?.insertEmbed(selection, 'image', content);
2895
- this.quill?.setSelection(selection + 1, 0);
2896
- }
2897
- }
2898
- handlerPopoverEvent(event) {
2899
- setTimeout(() => {
2900
- if (event === 'remove') {
2901
- this.link.set(linkDefault());
2902
- }
2903
- }, 100);
2904
- }
2905
- async insertLink(text, url, index) {
2906
- const selection = this.quill?.getSelection(true);
2907
- const indexInsert = index ?? selection?.index;
2908
- if (selection?.length) {
2909
- this.quill?.deleteText(selection.index, selection.length, Quill2x.sources.USER);
2910
- }
2911
- if (!isNil(indexInsert)) {
2912
- this.quill?.insertText(indexInsert, text, {
2913
- link: url,
2914
- color: false,
2915
- });
2916
- }
2917
- }
2918
- handleShowUploadLink(event) {
2919
- this.addEditLinkComponentRef.set(this.dynamicComponentService.resolveComponentFactory(LibsUiComponentsInputsQuillLinkComponent));
2920
- const instance = this.addEditLinkComponentRef()?.instance;
2921
- const selection = this.quill?.getSelection();
2922
- const textSelected = selection?.length ? this.quill?.getText(selection?.index, selection?.length) : '';
2923
- const data = event;
2924
- this.addEditLinkComponentRef()?.setInput('zIndex', this.zIndex());
2925
- this.addEditLinkComponentRef()?.setInput('title', data?.title || textSelected);
2926
- this.addEditLinkComponentRef()?.setInput('link', data?.url || '');
2927
- this.addEditLinkComponentRef()?.setInput('ignoreCommunicateMicroEvent', this.ignoreCommunicateMicroEventPopup());
2928
- instance?.outSaveLink.subscribe((item) => {
2929
- if (data instanceof Object && data.url) {
2930
- this.quill?.deleteText(data.range.index, data.range.length, Quill2x.sources.USER);
2931
- this.quill?.insertText(data.range.index, item.title, 'link', item.link);
2932
- return;
2933
- }
2934
- this.insertLink(item.title, item.link);
2935
- });
2936
- instance?.outClose.subscribe(() => this.dynamicComponentService.remove(this.addEditLinkComponentRef()));
2937
- this.dynamicComponentService.addToBody(this.addEditLinkComponentRef());
2938
- }
2939
- insertMention(event) {
2940
- const range = this.quill?.getSelection();
2941
- if (!range) {
2942
- return;
2943
- }
2944
- const indexSubtract = this.quill?.getText(range.index - 1, 1)?.includes('@') ? 0 : 1;
2945
- const cursorPos = range.index - indexSubtract;
2946
- const startPosInsert = cursorPos - event.lengthKey;
2947
- this.quill?.deleteText(startPosInsert, event.lengthKey, Quill2x.sources.SILENT);
2948
- this.quill?.insertEmbed(startPosInsert, 'mention', event.data, Quill2x.sources.SILENT);
2949
- this.insertText(' ', startPosInsert + 1);
2950
- if (indexSubtract) {
2951
- this.quill?.deleteText(startPosInsert + 3, 1, Quill2x.sources.SILENT);
2952
- }
2953
- this.quill?.setSelection(startPosInsert + 2, 0, Quill2x.sources.SILENT);
2954
- }
2955
- updateValueByRootQuillHtml() {
2956
- if (!this.quill?.root.getElementsByTagName('img').length && !this.quill?.getText()) {
2957
- set(this.item(), this.fieldBind(), '');
2958
- this.validate();
2959
- this.outChange.emit(get(this.item, this.fieldBind()));
2960
- return;
2961
- }
2962
- this.convertInnerHTMLAndSetValue();
2963
- this.validate();
2964
- this.outChange.emit(get(this.item, this.fieldBind()));
2965
- }
2966
- convertInnerHTMLAndSetValue() {
2967
- this.setStyleForContent();
2968
- set(this.item(), this.fieldBind(), this.removeUnwantedPart(this.quill?.root.innerHTML || ''));
2969
- }
2970
- removeUnwantedPart(html) {
2971
- if (!html) {
2972
- return '';
2973
- }
2974
- return html
2975
- .replace(/^\s*<p><br><\/p>/, '')
2976
- .replace(/<div><br><\/div>/gi, '')
2977
- .replace(/[\u200B-\u200D\uFEFF]/g, '');
2978
- }
2979
- detectLink(source) {
2980
- if (source !== 'user') {
2981
- return;
2982
- }
2983
- const fullText = this.quill?.getText();
2984
- const indexes = this.getIndexUrlMatch(fullText || '');
2985
- if (isNil(fullText) || !indexes.length) {
2986
- return;
2987
- }
2988
- indexes.forEach((item) => {
2989
- const textSelection = this.quill?.getText(item.start, item.end - item.start);
2990
- if (!textSelection) {
2991
- return;
2992
- }
2993
- const indexof = textSelection.search(patterProtocolUrl());
2994
- if (indexof < 0) {
2995
- return;
2996
- }
2997
- this.quill?.formatText(item.start + indexof, item.text.length, { link: item.text, color: false }, Quill2x.sources.SILENT);
2998
- });
2999
- }
3000
- getIndexUrlMatch(fullText) {
3001
- const textMatch = fullText.match(new RegExp(patternUrl().toString().replace('/^', '').replace('$/', ''), 'ig'));
3002
- const indexes = [];
3003
- let index = 0;
3004
- textMatch?.forEach((text) => {
3005
- const indexOfTextMatch = fullText.indexOf(text, index);
3006
- const indexPreCharacter = indexOfTextMatch - 1;
3007
- index = indexOfTextMatch + text.length;
3008
- if (indexOfTextMatch < 0 || !new RegExp(/^[\s]|^[\t]|^[\n]/).test(fullText[indexPreCharacter] || '')) {
3009
- return;
3010
- }
3011
- indexes.push({ start: indexOfTextMatch, end: indexOfTextMatch + text.length, text, preCharacter: fullText[indexPreCharacter] });
3012
- });
3013
- return indexes;
3014
- }
3015
- focus() {
3016
- if (this.focusBottom()) {
3017
- this.quill?.setSelection(this.quill.root.innerHTML.length, 0, Quill2x.sources.SILENT);
3018
- return;
3019
- }
3020
- this.quill?.setSelection(0, 0, Quill2x.sources.SILENT);
3021
- }
3022
- //endregion
3023
- ngOnDestroy() {
3024
- clearTimeout(this.timerSetFontSize());
3025
- clearTimeout(this.timerCalculatorToolbar());
3026
- this.dynamicComponentService.delete(this.addEditLinkComponentRef());
3027
- this.dynamicComponentService.delete(this.uploadImageComponentRef());
3028
- this.quill?.off('text-change', this.handlerTextChangeBind);
3029
- this.quill?.off('selection-change', this.handlerSelectionChangeBind);
3030
- const editorDom = this.quill?.root.parentElement;
3031
- if (editorDom && editorDom.parentElement) {
3032
- editorDom.parentElement.removeChild(editorDom);
3033
- }
3034
- this.quill = null;
3035
- }
3036
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: LibsUiComponentsInputsQuill2xComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
3037
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: LibsUiComponentsInputsQuill2xComponent, isStandalone: true, selector: "libs_ui-components-inputs-quill2x", inputs: { uploadImageConfig: { classPropertyName: "uploadImageConfig", publicName: "uploadImageConfig", isSignal: true, isRequired: false, transformFunction: null }, displayToolbar: { classPropertyName: "displayToolbar", publicName: "displayToolbar", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, blotsRegister: { classPropertyName: "blotsRegister", publicName: "blotsRegister", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, quillCustomConfig: { classPropertyName: "quillCustomConfig", publicName: "quillCustomConfig", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, item: { classPropertyName: "item", publicName: "item", isSignal: true, isRequired: true, transformFunction: null }, fieldBind: { classPropertyName: "fieldBind", publicName: "fieldBind", isSignal: true, isRequired: true, transformFunction: null }, autoUpdateValueWhenTextChange: { classPropertyName: "autoUpdateValueWhenTextChange", publicName: "autoUpdateValueWhenTextChange", isSignal: true, isRequired: false, transformFunction: null }, dataConfigMention: { classPropertyName: "dataConfigMention", publicName: "dataConfigMention", isSignal: true, isRequired: false, transformFunction: null }, templateToolBarPersonalize: { classPropertyName: "templateToolBarPersonalize", publicName: "templateToolBarPersonalize", isSignal: true, isRequired: false, transformFunction: null }, zIndex: { classPropertyName: "zIndex", publicName: "zIndex", isSignal: true, isRequired: false, transformFunction: null }, ignoreShowPopupEditLink: { classPropertyName: "ignoreShowPopupEditLink", publicName: "ignoreShowPopupEditLink", isSignal: true, isRequired: false, transformFunction: null }, ignoreCommunicateMicroEventPopup: { classPropertyName: "ignoreCommunicateMicroEventPopup", publicName: "ignoreCommunicateMicroEventPopup", isSignal: true, isRequired: false, transformFunction: null }, handlersExpand: { classPropertyName: "handlersExpand", publicName: "handlersExpand", isSignal: true, isRequired: false, transformFunction: null }, resizeImagePlugin: { classPropertyName: "resizeImagePlugin", publicName: "resizeImagePlugin", isSignal: true, isRequired: false, transformFunction: null }, fontSizeDefault: { classPropertyName: "fontSizeDefault", publicName: "fontSizeDefault", isSignal: true, isRequired: false, transformFunction: null }, heightEditorContentDefault: { classPropertyName: "heightEditorContentDefault", publicName: "heightEditorContentDefault", isSignal: true, isRequired: false, transformFunction: null }, minHeightEditorContentDefault: { classPropertyName: "minHeightEditorContentDefault", publicName: "minHeightEditorContentDefault", isSignal: true, isRequired: false, transformFunction: null }, maxHeightEditorContentDefault: { classPropertyName: "maxHeightEditorContentDefault", publicName: "maxHeightEditorContentDefault", isSignal: true, isRequired: false, transformFunction: null }, removeNearWhiteColorsOnPaste: { classPropertyName: "removeNearWhiteColorsOnPaste", publicName: "removeNearWhiteColorsOnPaste", isSignal: true, isRequired: false, transformFunction: null }, resize: { classPropertyName: "resize", publicName: "resize", isSignal: true, isRequired: false, transformFunction: null }, autoFocus: { classPropertyName: "autoFocus", publicName: "autoFocus", isSignal: true, isRequired: false, transformFunction: null }, focusTimerOnInit: { classPropertyName: "focusTimerOnInit", publicName: "focusTimerOnInit", isSignal: true, isRequired: false, transformFunction: null }, focusBottom: { classPropertyName: "focusBottom", publicName: "focusBottom", isSignal: true, isRequired: false, transformFunction: null }, validRequired: { classPropertyName: "validRequired", publicName: "validRequired", isSignal: true, isRequired: false, transformFunction: null }, validMinLength: { classPropertyName: "validMinLength", publicName: "validMinLength", isSignal: true, isRequired: false, transformFunction: null }, validMaxLength: { classPropertyName: "validMaxLength", publicName: "validMaxLength", isSignal: true, isRequired: false, transformFunction: null }, showErrorLabel: { classPropertyName: "showErrorLabel", publicName: "showErrorLabel", isSignal: true, isRequired: false, transformFunction: null }, showErrorBorder: { classPropertyName: "showErrorBorder", publicName: "showErrorBorder", isSignal: true, isRequired: false, transformFunction: null }, ignoreShowBorderErrorToolbar: { classPropertyName: "ignoreShowBorderErrorToolbar", publicName: "ignoreShowBorderErrorToolbar", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { item: "itemChange", outShowPopupEditLink: "outShowPopupEditLink", outMessageError: "outMessageError", outBlur: "outBlur", outFocus: "outFocus", outChange: "outChange", outSelectionChange: "outSelectionChange", outTextChange: "outTextChange", outContextMenu: "outContextMenu", outFunctionsControl: "outFunctionsControl" }, viewQueries: [{ propertyName: "htmlContainer", first: true, predicate: ["htmlContainer"], descendants: true, isSignal: true }, { propertyName: "quillBodyContainer", first: true, predicate: ["snowContainer"], descendants: true, isSignal: true }, { propertyName: "toolbarContainer", first: true, predicate: ["toolbarContainer"], descendants: true, isSignal: true }, { propertyName: "inputLinkRef", first: true, predicate: ["inputLinkRef"], descendants: true, isSignal: true }], ngImport: i0, template: "<div\n #htmlContainer\n [class]=\"containerClass()\"\n [style.--resize]=\"resize()\">\n @if (label(); as label) {\n <libs_ui-components-label\n [classInclude]=\"label.classInclude\"\n [required]=\"label.required\"\n [labelLeft]=\"label.labelLeft\" />\n }\n\n <div\n #toolbarContainer\n class=\"relative h-[44px]\"\n [class.hidden]=\"!displayToolbar()\"\n [ngStyle]=\"quillCustomConfig()?.toolbar?.()?.styles?.() || {}\">\n <ng-container *ngTemplateOutlet=\"toolbarTemplate\" />\n </div>\n <div\n #snowContainer\n LibsUiComponentsScrollOverlayDirective\n LibsUiComponentsInputsMentionDirective\n [options]=\"{ ignoreTransparentScrollBarColorDefault: resize() !== 'none' }\"\n [mentionConfig]=\"dataConfigMention()\"\n (outToggle)=\"handleToggleMention($event)\"\n (outInsertMention)=\"handlerInsertMention($event)\"\n [class]=\"containerEditorClass()\"></div>\n @if (messageError() && showErrorLabel()) {\n <div class=\"flex items-center mt-[8px]\">\n <span class=\"text-[#ff5454] libs-ui-font-h7r\">{{ messageError() | translate }}</span>\n </div>\n }\n</div>\n\n<ng-template #toolbarTemplate>\n <div\n [class]=\"containerToolbarClass()\"\n #toolbarItems>\n @if (displaySkeletonToolbar()) {\n <libs_ui-components-skeleton\n class=\"w-full h-full\"\n [config]=\"{\n rows: [\n {\n item: { classIncludeItem: '!rounded-none' },\n },\n ],\n }\" />\n }\n <div class=\"ql-formats items-center px-[16px] py-[4px] !flex\">\n @for (option of toolbarOptionsConfig(); track option) {\n <div\n class=\"items-center\"\n [class.hidden]=\"!option.display\"\n [class.flex]=\"option.display\">\n <ng-container *ngTemplateOutlet=\"itemToolbarTemplate; context: { option, $index, $last }\" />\n </div>\n }\n <div class=\"relative\">\n @if (showButtonMoreToolbar()) {\n <libs_ui-components-buttons-button\n [type]=\"showMoreAction() ? 'button-secondary' : 'button-third'\"\n [iconOnlyType]=\"true\"\n [classInclude]=\"'!p-[1px] !h-[20px] ml-[8px]'\"\n [classIconLeft]=\"'libs-ui-icon-move-right rotate-90'\"\n (outClick)=\"handlerChangeShowMoreAction($event)\" />\n }\n <!-- Build toolbar khi click xem th\u00EAm-->\n <div\n [class.hidden]=\"!showMoreAction()\"\n class=\"absolute bg-[#ffffff] shadow-[0px_4px_16px_0px_rgba(0,20,51,0.10)] z-[1] flex items-center pl-[8px] pr-[16px] py-[4px] rounded-[8px] top-[31px] right-[0px]\">\n @for (option of toolbarOptionsConfig(); track option) {\n <div\n class=\"items-center\"\n [class.hidden]=\"option.display !== false\"\n [class.flex]=\"option.display === false\">\n <ng-container *ngTemplateOutlet=\"itemToolbarTemplate; context: { option, $index, $last }\" />\n </div>\n }\n </div>\n </div>\n </div>\n </div>\n</ng-template>\n\n<ng-template\n #itemToolbarTemplate\n let-$index=\"$index\"\n let-$last=\"$last\"\n let-option=\"option\">\n @if (option.type === 'undo') {\n <div [class]=\"option.classInclude || 'mx-[8px]'\">\n <button\n LibsUiComponentsPopoverDirective\n [config]=\"{ content: 'i18n_undo', zIndex: zIndex() }\"\n class=\"ql-undo\"></button>\n </div>\n }\n @if (option.type === 'redo') {\n <div [class]=\"option.classInclude || 'mx-[8px]'\">\n <button\n LibsUiComponentsPopoverDirective\n [config]=\"{ content: 'i18n_redo', zIndex: zIndex() }\"\n class=\"ql-redo\"></button>\n </div>\n }\n @if (option.type === 'fontFamily') {\n <div\n class=\"relative w-[132px] h-full rounded-[4px] libs-ui-border-general {{ option.classInclude || 'mx-[8px]' }}\"\n [class.bg-white]=\"!readonly() && !loadingUploadImage()\">\n <libs_ui-components-dropdown\n [isNgContent]=\"true\"\n [labelPopoverFullWidth]=\"true\"\n [listConfig]=\"listConfigFont()\"\n [listHasButtonUnSelectOption]=\"false\"\n [listHiddenInputSearch]=\"true\"\n [readonly]=\"readonly()\"\n [zIndex]=\"1250\"\n (outSelectKey)=\"handleSelectFont($event)\">\n @if (fontSelected(); as fontSelected) {\n <div class=\"flex items-center cursor-pointer py-[7px] libs-ui-font-h5r pl-[16px] pr-[40px]\">\n <libs_ui-components-popover\n [type]=\"'text'\"\n [ignoreStopPropagationEvent]=\"true\"\n [config]=\"{ zIndex: zIndex() }\">\n {{ labelFontSelectedComputed() }}\n </libs_ui-components-popover>\n <i class=\"libs-ui-icon-move-right rotate-90 absolute right-[12px] text-[#6a7383] text-[16px]\"></i>\n </div>\n }\n </libs_ui-components-dropdown>\n </div>\n }\n @if (option.type === 'header') {\n <div\n class=\"relative w-[138px] h-full rounded-[4px] libs-ui-border-general {{ option.classInclude || 'mx-[8px]' }}\"\n [class.bg-white]=\"!readonly() && !loadingUploadImage()\">\n <libs_ui-components-dropdown\n [isNgContent]=\"true\"\n [labelPopoverFullWidth]=\"true\"\n [popoverCustomConfig]=\"{ widthByParent: false, width: 200, classInclude: 'h-[254px]', classIncludeOverlayBody: 'h-full', position: { mode: 'start', distance: -8 } }\"\n [listConfig]=\"listConfigHeader()\"\n [listHasButtonUnSelectOption]=\"false\"\n [listHiddenInputSearch]=\"true\"\n [readonly]=\"readonly()\"\n [listMaxItemShow]=\"-1\"\n [zIndex]=\"1250\"\n (outSelectKey)=\"handleSelectHeader($event)\">\n @if (headerSelected(); as headerSelected) {\n <div class=\"flex items-center cursor-pointer py-[7px] libs-ui-font-h5r pl-[16px] pr-[40px] {{ option.classInclude || 'mx-[8px]' }}\">\n <libs_ui-components-popover\n [type]=\"'text'\"\n [ignoreStopPropagationEvent]=\"true\"\n [config]=\"{ zIndex: zIndex() }\">\n {{ labelHeaderSelectedComputed() }}\n </libs_ui-components-popover>\n <i class=\"libs-ui-icon-move-right rotate-90 absolute right-[12px] text-[#6a7383] text-[16px]\"></i>\n </div>\n }\n </libs_ui-components-dropdown>\n </div>\n }\n @if (option.type === 'fontSize') {\n <div class=\" {{ option.classInclude || 'mx-[8px]' }}\">\n <libs_ui-components-inputs-valid\n #inputSizeRef\n [dataType]=\"'int'\"\n [(item)]=\"fontSize\"\n [fieldNameBind]=\"'value'\"\n [valueUpDownNumber]=\"1\"\n [maxValueNumber]=\"72\"\n [minValueNumber]=\"8\"\n [readonly]=\"readonly() || loadingUploadImage()\"\n [classContainerInput]=\"'w-[72px] h-[32px]'\"\n (outChangeValueByButtonUpDown)=\"handlerValueChangeFontSize()\"\n (outFocusAndBlur)=\"handlerValueChangeFontSize($event)\" />\n </div>\n }\n @if (option.type === 'color') {\n <div class=\"ql-color ql-picker ql-color-picker !flex items-center {{ option.classInclude || 'mx-[8px]' }}\">\n <libs_ui-components-popover [config]=\"{ content: 'i18n_text_color', zIndex: zIndex() }\">\n <libs_ui-components-buttons-select_color\n [zIndex]=\"zIndex()\"\n [direction]=\"'top'\"\n [externalContent]=\"true\"\n [customOptions]=\"{\n showAlpha: true,\n }\"\n [applyNow]=\"false\"\n (outColorChangeMultipleType)=\"handlerSetFormat('color', $event)\">\n <div\n class=\"libs-ui-icon-editor-color-text libs-ui-buttons-select-color text-[#6a7383] text-[16px] hover:text-[var(--libs-ui-color-light-1)]\"\n [class.libs-ui-icon-editor-color-text-active]=\"!!colorSelected()\"\n [style.--color-selected]=\"colorSelected()\"></div>\n </libs_ui-components-buttons-select_color>\n </libs_ui-components-popover>\n </div>\n }\n @if (option.type === 'background') {\n <div class=\"ql-background ql-picker ql-color-picker !flex items-center {{ option.classInclude || 'mx-[8px]' }}\">\n <libs_ui-components-popover [config]=\"{ content: 'i18n_background_color', zIndex: zIndex() }\">\n <libs_ui-components-buttons-select_color\n [zIndex]=\"zIndex()\"\n [direction]=\"'top'\"\n [externalContent]=\"true\"\n [applyNow]=\"false\"\n [customOptions]=\"{\n showAlpha: true,\n }\"\n (outColorChangeMultipleType)=\"handlerSetFormat('background', $event)\">\n <div\n class=\"libs-ui-icon-editor-color-background libs-ui-buttons-select-color text-[#6a7383] text-[16px] hover:text-[var(--libs-ui-color-light-1)]\"\n [class.libs-ui-icon-editor-color-background-active]=\"!!backgroundSelected()\"\n [style.--background-selected]=\"backgroundSelected()\"></div>\n </libs_ui-components-buttons-select_color>\n </libs_ui-components-popover>\n </div>\n }\n @if (option.type === 'bold') {\n <div [class]=\"option.classInclude || 'mx-[8px]'\">\n <button\n LibsUiComponentsPopoverDirective\n [config]=\"{ content: 'i18n_font_weight_bold', zIndex: zIndex() }\"\n class=\"ql-bold !flex\"></button>\n </div>\n }\n @if (option.type === 'italic') {\n <div [class]=\"option.classInclude || 'mx-[8px]'\">\n <button\n LibsUiComponentsPopoverDirective\n [config]=\"{ content: 'i18n_font_style_italic', zIndex: zIndex() }\"\n class=\"ql-italic !flex\"></button>\n </div>\n }\n @if (option.type === 'underline') {\n <div [class]=\"option.classInclude || 'mx-[8px]'\">\n <button\n LibsUiComponentsPopoverDirective\n [config]=\"{ content: 'i18n_text_decoration_underline', zIndex: zIndex() }\"\n class=\"ql-underline !flex\"></button>\n </div>\n }\n @if (option.type === 'strikeThrough') {\n <div [class]=\"option.classInclude || 'mx-[8px]'\">\n <button\n LibsUiComponentsPopoverDirective\n [config]=\"{ content: 'i18n_text_line_through', zIndex: zIndex() }\"\n class=\"ql-strike !flex\"></button>\n </div>\n }\n @if (option.type === 'script.sub') {\n <div [class]=\"option.classInclude || 'mx-[8px]'\">\n <button\n LibsUiComponentsPopoverDirective\n [config]=\"{ content: 'i18n_script_sub', zIndex: zIndex() }\"\n class=\"ql-script flex\"\n value=\"sub\"></button>\n </div>\n }\n @if (option.type === 'script.super') {\n <div [class]=\"option.classInclude || 'mx-[8px]'\">\n <button\n LibsUiComponentsPopoverDirective\n [config]=\"{ content: 'i18n_script_super', zIndex: zIndex() }\"\n class=\"ql-script flex\"\n value=\"super\"></button>\n </div>\n }\n @if (option.type === 'adjust') {\n <div class=\"relative !flex items-center ql-align ql-picker ql-icon-picker !w-max {{ option.classInclude || 'mx-[8px]' }}\">\n <libs_ui-components-popover [config]=\"{ content: 'i18n_adjust', zIndex: zIndex() }\">\n <libs_ui-components-dropdown\n [isNgContent]=\"true\"\n [ignoreStopPropagationEvent]=\"true\"\n [labelPopoverFullWidth]=\"true\"\n [listConfig]=\"listConfigAlign()\"\n [listHiddenInputSearch]=\"true\"\n [popoverCustomConfig]=\"{ ignoreArrow: true, classInclude: '!w-[32px] overflow-hidden !py-[4px]', position: { mode: 'start', distance: 0 }, paddingLeftItem: false }\"\n [listHasButtonUnSelectOption]=\"false\"\n [zIndex]=\"zIndex() + 1\"\n [listKeySelected]=\"adjustSelected()\"\n (outSelectKey)=\"handleSelectAlign($event)\">\n @if (alignSelected(); as alignSelected) {\n <div class=\"flex items-center cursor-pointer\">\n <i\n [class]=\"iconAlignSelectedComputed()\"\n [class.text-[var(--libs-ui-color-light-1)]]=\"adjustSelected() !== undefined\"></i>\n <i class=\"libs-ui-icon-move-right rotate-90 text-[#6a7383] text-[16px] ml-[4px]\"></i>\n </div>\n }\n </libs_ui-components-dropdown>\n </libs_ui-components-popover>\n </div>\n }\n @if (option.type === 'indentIncrease') {\n <div [class]=\"option.classInclude || 'mx-[8px]'\">\n <button\n LibsUiComponentsPopoverDirective\n [config]=\"{ content: 'i18n_indent_increase', zIndex: zIndex() }\"\n class=\"ql-indent\"\n value=\"+1\"></button>\n </div>\n }\n @if (option.type === 'indentDecrease') {\n <div [class]=\"option.classInclude || 'mx-[8px]'\">\n <button\n LibsUiComponentsPopoverDirective\n [config]=\"{ content: 'i18n_indent_decrease', zIndex: zIndex() }\"\n class=\"ql-indent\"\n value=\"-1\"></button>\n </div>\n }\n @if (option.type === 'listBulleted') {\n <div [class]=\"option.classInclude || 'mx-[8px]'\">\n <button\n LibsUiComponentsPopoverDirective\n [config]=\"{ content: 'i18n_list_bulleted', zIndex: zIndex() }\"\n class=\"ql-list ql-bullet\"\n value=\"bullet\"></button>\n </div>\n }\n @if (option.type === 'listNumbered') {\n <div [class]=\"option.classInclude || 'mx-[8px]'\">\n <button\n LibsUiComponentsPopoverDirective\n [config]=\"{ content: 'i18n_list_numbered', zIndex: zIndex() }\"\n class=\"ql-list ql-ordered\"\n value=\"ordered\"></button>\n </div>\n }\n @if (option.type === 'listChecked') {\n <div\n [class]=\"option.classInclude || 'mx-[8px]'\"\n [class.ql-active]=\"listCheckboxSelected()\">\n <button\n LibsUiComponentsPopoverDirective\n [config]=\"{ content: 'i18n_list_numbered', zIndex: zIndex() }\"\n class=\"ql-list ql-check\"\n value=\"check\"></button>\n </div>\n }\n @if (option.type === 'personalize' && templateToolBarPersonalize(); as templateToolBarPersonalize) {\n <div class=\"flex items-center {{ option.classInclude || 'mx-[8px]' }}\">\n <ng-container *ngTemplateOutlet=\"templateToolBarPersonalize\"></ng-container>\n </div>\n }\n @if (option.type === 'blockquote') {\n <div [class]=\"option.classInclude || 'mx-[8px]'\">\n <button\n LibsUiComponentsPopoverDirective\n [config]=\"{ content: 'i18n_quote', zIndex: zIndex() }\"\n class=\"ql-blockquote\"></button>\n </div>\n }\n @if (option.type === 'link') {\n <div [class]=\"option.classInclude || 'mx-[8px]'\">\n <button\n LibsUiComponentsPopoverDirective\n [config]=\"{ content: 'i18n_insert_link', zIndex: zIndex() }\"\n class=\"ql-link\"></button>\n </div>\n }\n @if (option.type === 'unLink') {\n <div [class]=\"option.classInclude || 'mx-[8px]'\">\n <button\n LibsUiComponentsPopoverDirective\n [config]=\"{ content: 'i18n_unlink', zIndex: zIndex() }\"\n class=\"ql-unLink\"\n (click)=\"handlerUnlink($event)\"></button>\n </div>\n }\n @if (option.type === 'image') {\n <div [class]=\"option.classInclude || 'mx-[8px]'\">\n <button\n LibsUiComponentsPopoverDirective\n [config]=\"{ content: 'i18n_image', zIndex: zIndex() }\"\n class=\"ql-image\"></button>\n </div>\n }\n @if (option.type === 'video') {\n <div [class]=\"option.classInclude || 'mx-[8px]'\">\n <button\n LibsUiComponentsPopoverDirective\n [config]=\"{ content: 'i18n_video', zIndex: zIndex() }\"\n class=\"ql-video\"></button>\n </div>\n }\n @if (option.type === 'emoji') {\n <div [class]=\"option.classInclude || 'mx-[8px]'\">\n <libs_ui-components-emoji\n [zIndex]=\"zIndex()\"\n [isNgContent]=\"true\"\n (outEventEmoji)=\"handlerInsertEmoji($event)\">\n <button class=\"ql-emoji\"></button>\n </libs_ui-components-emoji>\n </div>\n }\n @if (option.type === 'table') {\n <div [class]=\"option.classInclude || 'mx-[8px]'\">\n <button\n LibsUiComponentsPopoverDirective\n [config]=\"{ content: 'i18n_table', zIndex: zIndex() }\"\n class=\"ql-table\"></button>\n </div>\n }\n @if (option.type === 'line') {\n <div class=\"w-[1px] h-[16px] libs-ui-border-right-general\"></div>\n }\n</ng-template>\n\n<libs_ui-components-popover\n #inputLinkRef\n [mode]=\"'click'\"\n [ignoreHiddenPopoverContentWhenMouseLeave]=\"true\"\n [config]=\"{ template: viewLink, whiteTheme: true, ignoreArrow: true, zIndex: zIndex() }\"\n (outEvent)=\"handlerPopoverEvent($event)\" />\n\n<ng-template #viewLink>\n <div class=\"flex justify-between items-center px-[16px] py-[8px] rounded-[8px]\">\n <div\n class=\"w-full min-w-0 libs-ui-font-h5r\"\n [type]=\"'text'\"\n LibsUiComponentsPopoverDirective\n [config]=\"{ content: link().url, zIndex: zIndex() + 1 }\">\n {{ link().url }}\n </div>\n <div class=\"flex items-center ml-[16px]\">\n <libs_ui-components-buttons-button\n [type]=\"'button-link-primary'\"\n [iconOnlyType]=\"true\"\n [classIconLeft]=\"'libs-ui-icon-edit-line'\"\n [classInclude]=\"'!p-0'\"\n (outClick)=\"handlerEditLink($event)\" />\n <libs_ui-components-buttons-button\n [type]=\"'button-link-custom'\"\n [buttonCustom]=\"{\n configStepColor: {\n text: '#071631',\n text_hover: '#ee2d41',\n text_active: '#ee2d41',\n text_disable: '071631',\n },\n rootColor: '#071631',\n }\"\n [classInclude]=\"'!p-0 ml-[12px]'\"\n [iconOnlyType]=\"true\"\n [classIconLeft]=\"'libs-ui-icon-link-broken'\"\n (outClick)=\"handlerUnlink($event)\" />\n </div>\n </div>\n</ng-template>\n", styles: ["@charset \"UTF-8\";:host ::ng-deep .quill-container .ql-container{font-family:var(--libs-ui-font-family-name),\"Arial\"!important;font-weight:400}:host ::ng-deep .quill-container .ql-container .ql-editor{font-family:var(--libs-ui-font-family-name),\"Arial\"!important;font-weight:400;height:auto;min-height:100%;resize:var(--resize)}:host ::ng-deep .quill-container .ql-container .ql-editor ol,:host ::ng-deep .quill-container .ql-container .ql-editor ul{list-style:none!important;padding-left:0!important;margin-left:0!important}:host ::ng-deep .quill-container .ql-container .ql-editor ol li,:host ::ng-deep .quill-container .ql-container .ql-editor ul li{list-style-type:none!important}:host ::ng-deep .quill-container .ql-container .ql-editor li,:host ::ng-deep .quill-container .ql-container .ql-editor ol li,:host ::ng-deep .quill-container .ql-container .ql-editor ul li,:host ::ng-deep .quill-container .ql-container .ql-editor li[data-list]{counter-reset:none!important;counter-increment:none!important;counter-set:none!important}@supports (counter-set: none){:host ::ng-deep .quill-container .ql-container .ql-editor li[data-list]{counter-set:none!important}}:host ::ng-deep .quill-container .ql-container .ql-editor ol li:not(.ql-direction-rtl){counter-increment:none!important}:host ::ng-deep .quill-container .ql-container .ql-editor ol{counter-reset:my-counter 0!important}:host ::ng-deep .quill-container .ql-container .ql-editor ol>li[data-list=ordered]{counter-increment:my-counter 1!important;position:relative;padding-left:8px}:host ::ng-deep .quill-container .ql-container .ql-editor ol>li[data-list=ordered]:before{content:counter(my-counter) \". \"}:host ::ng-deep .quill-container .ql-container .ql-editor ol li span:before{content:\"\"!important}:host ::ng-deep .quill-container .ql-container .ql-editor ol li[data-list=bullet]:before{content:\"\\2022\"!important}:host ::ng-deep .quill-container .ql-container .ql-editor ol li[data-list=unchecked]:before{content:\"\\2610\"!important}:host ::ng-deep .quill-container .ql-container .ql-editor ol li[data-list=checked]:before{content:\"\\2611\"!important}:host ::ng-deep .quill-container .ql-container .ql-blank:before{font-style:normal!important;font-size:12px!important;color:#9ca2ad!important;font-family:var(--libs-ui-font-family-name),arial!important}:host ::ng-deep .quill-container .ql-active span:before{color:var(--libs-ui-color-light-1)!important}:host ::ng-deep .quill-container .ql-active .ql-fill{fill:var(--libs-ui-color-light-1)!important}:host ::ng-deep .quill-container .ql-script :hover .ql-fill{fill:var(--libs-ui-color-light-1)!important}:host ::ng-deep .quill-container .ql-toolbar{padding:0!important;border:none!important}:host ::ng-deep .quill-container .ql-toolbar button{padding:0!important;height:16px!important;width:16px!important}:host ::ng-deep .quill-container .ql-tooltip{display:none!important}:host ::ng-deep .quill-container #editor-resizer .toolbar{top:0!important;left:0!important;transform:none!important;font-family:var(--libs-ui-font-family-name),\"Arial\"!important;font-weight:400;font-size:12px}:host ::ng-deep .quill-container .libs-ui-icon-editor-color-text-active{color:var(--color-selected)!important}:host ::ng-deep .quill-container .libs-ui-icon-editor-color-background-active{color:var(--background-selected)!important}:host ::ng-deep .quill-container .ql-snow .ql-picker{font-size:12px!important;height:32px;float:none;width:auto}:host ::ng-deep .selected-cell{background-color:#0096ff4d}\n"], dependencies: [{ kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i1.TranslatePipe, name: "translate" }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: LibsUiComponentsDropdownComponent, selector: "libs_ui-components-dropdown", inputs: ["useXssFilter", "popoverElementRefCustom", "classInclude", "ignoreStopPropagationEvent", "flagMouse", "flagMouseContent", "popoverCustomConfig", "isNgContent", "zIndex", "convertItemSelected", "getPopoverItemSelected", "httpRequestDetailItemById", "lengthKeys", "textDisplayWhenNoSelect", "textDisplayWhenMultiSelect", "classIncludeTextDisplayWhenNoSelect", "fieldLabel", "fieldGetLabel", "labelPopoverConfig", "labelPopoverFullWidth", "hasContentUnitRight", "listSearchNoDataTemplateRef", "fieldGetImage", "imageSize", "typeShape", "fieldGetIcon", "fieldGetTextAvatar", "fieldGetColorAvatar", "classAvatarInclude", "getLastTextAfterSpace", "linkImageError", "showError", "showBorderError", "disable", "readonly", "labelConfig", "disableLabel", "listSearchConfig", "isSearchOnline", "listHiddenInputSearch", "listSearchPadding", "listKeySearch", "listDividerClassInclude", "listConfig", "listButtonsOther", "listHasButtonUnSelectOption", "listClickExactly", "listBackgroundCustom", "listMaxItemShow", "listKeySelected", "listMultiKeySelected", "listKeysDisable", "listKeysHidden", "validRequired", "validMaxItemSelected", "changeValidUndefinedResetError", "allowSelectItemMultiple", "focusInputSearch", "onlyEmitDataWhenReset", "resetKeyWhenSelectAllKey", "listConfigHasDivider", "classIncludeIcon", "classIncludeContent", "listIgnoreClassDisableDefaultWhenUseKeysDisableItem", "tabKeyActive", "tabsConfig", "ignoreBorderBottom"], outputs: ["flagMouseChange", "flagMouseContentChange", "lengthKeysChange", "showBorderErrorChange", "listKeySelectedChange", "listMultiKeySelectedChange", "tabKeyActiveChange", "outSelectKey", "outSelectMultiKey", "outFunctionsControl", "outValidEvent", "outChangStageFlagMouse", "outDataChange", "outClickButtonOther", "outShowList", "outChangeTabKeyActive"] }, { kind: "component", type: LibsUiComponentsButtonsButtonComponent, selector: "libs_ui-components-buttons-button", inputs: ["flagMouse", "type", "buttonCustom", "sizeButton", "label", "disable", "isPending", "imageLeft", "classInclude", "classIconLeft", "classIconRight", "classLabel", "iconOnlyType", "popover", "ignoreStopPropagationEvent", "zIndex", "widthLabelPopover", "styleIconLeft", "styleButton", "ignoreFocusWhenInputTab", "ignoreSetClickWhenShowPopover", "ignorePointerEvent", "isActive", "isHandlerEnterDocumentClickButton"], outputs: ["outClick", "outPopoverEvent", "outFunctionsControl"] }, { kind: "component", type: LibsUiComponentsSkeletonComponent, selector: "libs_ui-components-skeleton", inputs: ["config"] }, { kind: "directive", type: LibsUiComponentsScrollOverlayDirective, selector: "[LibsUiComponentsScrollOverlayDirective]", inputs: ["debugMode", "ignoreInit", "classContainer", "options", "elementCheckScrollX", "elementCheckScrollY", "elementScroll"], outputs: ["outScroll", "outScrollX", "outScrollY", "outScrollTop", "outScrollBottom"] }, { kind: "component", type: LibsUiComponentsEmojiComponent, selector: "libs_ui-components-emoji", inputs: ["configPopover", "isNgContent", "zIndex", "modePopoverPosition", "classPopup", "classInclude", "classIconInclude"], outputs: ["outEventEmoji", "outFunctionsControl"] }, { kind: "component", type: LibsUiComponentsPopoverComponent, selector: "libs_ui-components-popover,[LibsUiComponentsPopoverDirective]", inputs: ["debugId", "flagMouse", "type", "mode", "config", "ignoreShowPopover", "elementRefCustom", "initEventInElementRefCustom", "classInclude", "ignoreHiddenPopoverContentWhenMouseLeave", "ignoreStopPropagationEvent", "ignoreCursorPointerModeLikeClick", "isAddContentToParentDocument", "ignoreClickOutside"], outputs: ["outEvent", "outChangStageFlagMouse", "outEventPopoverContent", "outFunctionsControl"] }, { kind: "component", type: LibsUiComponentsInputsValidComponent, selector: "libs_ui-components-inputs-valid", inputs: ["item", "labelConfig", "emitEmptyInDataTypeNumber", "ignoreBlockInputMaxValue", "fieldNameBind", "showCount", "typeComponentSelectItem", "valueComponentSelectItem", "disableComponentSelectItem", "tagInput", "dataType", "typeInput", "modeInput", "resetAutoCompletePassword", "textAreaEnterNotNewLine", "fixedFloat", "acceptNegativeValue", "valueUpDownNumber", "ignoreWidthInput100", "classIncludeInput", "classContainerInput", "readonly", "disable", "noBorder", "backgroundNone", "useColorModeExist", "placeholder", "keepPlaceholderOnly", "classContainerBottomInput", "autoRemoveEmoji", "defaultHeight", "maxHeightTextArea", "minHeightTextArea", "ignoreShowError", "borderError", "iconLeftClass", "popoverContentIconLeft", "iconRightClass", "popoverContentIconRight", "zIndexPopoverContent", "unitsLeft", "configUnitLeft", "keySelectedUnitLeft", "unitsRight", "configUnitRight", "keySelectedUnitRight", "maxValueNumber", "minValueNumber", "ignoreContentLeft", "ignoreContentRight", "isBaselineStyle", "valuePatternShowError", "validPattern", "validRequired", "validMinLength", "validMinValue", "validMaxValue", "validMaxLength", "functionValid", "maxLength", "positionMessageErrorStartInput", "classInclude", "resize", "templateLeftBottomInput", "templateRightBottomInput", "onlyAcceptNegativeValue", "autoAddZeroLessThan10InTypeInt", "maxLengthNumberCount", "classMessageErrorInclude", "ignoreStopPropagationEvent", "ignoreUnitRightClassReadOnly", "paddingRightCustomSpecific", "focusTimeOut", "debounceTimeValidate"], outputs: ["itemChange", "outValueChange", "outSelect", "outIconLeft", "outIconRight", "outClickButtonLabel", "outSwitchEventLabel", "outLabelRightClick", "outEnterInputEvent", "outHeightAreaChange", "outFunctionsControl", "outFocusAndBlur", "outChangeValueByButtonUpDown"] }, { kind: "component", type: LibsUiComponentsButtonsSelectColorComponent, selector: "libs_ui-components-buttons-select_color", inputs: ["zIndex", "customOptions", "externalContent", "direction", "button", "applyNow"], outputs: ["zIndexChange", "outColorChange", "outColorChangeMultipleType"] }, { kind: "component", type: LibsUiComponentsLabelComponent, selector: "libs_ui-components-label", inputs: ["iconPopoverClass", "classInclude", "labelLeft", "labelLeftClass", "labelLeftBehindToggleButton", "popover", "required", "buttonsLeft", "disableButtonsLeft", "buttonsRight", "disableButtonsRight", "labelRight", "labelRightClass", "labelRightRequired", "hasToggle", "toggleSize", "toggleActive", "toggleDisable", "description", "descriptionClass", "buttonsDescription", "disableButtonsDescription", "buttonsDescriptionContainerClass", "onlyShowCount", "zIndexPopover", "timerDestroyPopover", "count", "limitLength"], outputs: ["outClickButton", "outSwitchEvent", "outLabelRightClick", "outLabelLeftClick"] }, { kind: "directive", type: LibsUiComponentsInputsMentionDirective, selector: "[LibsUiComponentsInputsMentionDirective]", inputs: ["timeDelayInit", "mentionConfig", "mentionListTemplate"], outputs: ["outSearchTerm", "outItemSelected", "outToggle", "outInsertMention", "outFunctionControl"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3038
- }
3039
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: LibsUiComponentsInputsQuill2xComponent, decorators: [{
3040
- type: Component,
3041
- args: [{ selector: 'libs_ui-components-inputs-quill2x', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [
3042
- NgStyle,
3043
- TranslateModule,
3044
- NgTemplateOutlet,
3045
- LibsUiComponentsDropdownComponent,
3046
- LibsUiComponentsButtonsButtonComponent,
3047
- LibsUiComponentsSkeletonComponent,
3048
- LibsUiComponentsScrollOverlayDirective,
3049
- LibsUiComponentsEmojiComponent,
3050
- LibsUiComponentsPopoverComponent,
3051
- LibsUiComponentsInputsValidComponent,
3052
- LibsUiComponentsButtonsSelectColorComponent,
3053
- LibsUiComponentsLabelComponent,
3054
- LibsUiComponentsInputsMentionDirective,
3055
- ], template: "<div\n #htmlContainer\n [class]=\"containerClass()\"\n [style.--resize]=\"resize()\">\n @if (label(); as label) {\n <libs_ui-components-label\n [classInclude]=\"label.classInclude\"\n [required]=\"label.required\"\n [labelLeft]=\"label.labelLeft\" />\n }\n\n <div\n #toolbarContainer\n class=\"relative h-[44px]\"\n [class.hidden]=\"!displayToolbar()\"\n [ngStyle]=\"quillCustomConfig()?.toolbar?.()?.styles?.() || {}\">\n <ng-container *ngTemplateOutlet=\"toolbarTemplate\" />\n </div>\n <div\n #snowContainer\n LibsUiComponentsScrollOverlayDirective\n LibsUiComponentsInputsMentionDirective\n [options]=\"{ ignoreTransparentScrollBarColorDefault: resize() !== 'none' }\"\n [mentionConfig]=\"dataConfigMention()\"\n (outToggle)=\"handleToggleMention($event)\"\n (outInsertMention)=\"handlerInsertMention($event)\"\n [class]=\"containerEditorClass()\"></div>\n @if (messageError() && showErrorLabel()) {\n <div class=\"flex items-center mt-[8px]\">\n <span class=\"text-[#ff5454] libs-ui-font-h7r\">{{ messageError() | translate }}</span>\n </div>\n }\n</div>\n\n<ng-template #toolbarTemplate>\n <div\n [class]=\"containerToolbarClass()\"\n #toolbarItems>\n @if (displaySkeletonToolbar()) {\n <libs_ui-components-skeleton\n class=\"w-full h-full\"\n [config]=\"{\n rows: [\n {\n item: { classIncludeItem: '!rounded-none' },\n },\n ],\n }\" />\n }\n <div class=\"ql-formats items-center px-[16px] py-[4px] !flex\">\n @for (option of toolbarOptionsConfig(); track option) {\n <div\n class=\"items-center\"\n [class.hidden]=\"!option.display\"\n [class.flex]=\"option.display\">\n <ng-container *ngTemplateOutlet=\"itemToolbarTemplate; context: { option, $index, $last }\" />\n </div>\n }\n <div class=\"relative\">\n @if (showButtonMoreToolbar()) {\n <libs_ui-components-buttons-button\n [type]=\"showMoreAction() ? 'button-secondary' : 'button-third'\"\n [iconOnlyType]=\"true\"\n [classInclude]=\"'!p-[1px] !h-[20px] ml-[8px]'\"\n [classIconLeft]=\"'libs-ui-icon-move-right rotate-90'\"\n (outClick)=\"handlerChangeShowMoreAction($event)\" />\n }\n <!-- Build toolbar khi click xem th\u00EAm-->\n <div\n [class.hidden]=\"!showMoreAction()\"\n class=\"absolute bg-[#ffffff] shadow-[0px_4px_16px_0px_rgba(0,20,51,0.10)] z-[1] flex items-center pl-[8px] pr-[16px] py-[4px] rounded-[8px] top-[31px] right-[0px]\">\n @for (option of toolbarOptionsConfig(); track option) {\n <div\n class=\"items-center\"\n [class.hidden]=\"option.display !== false\"\n [class.flex]=\"option.display === false\">\n <ng-container *ngTemplateOutlet=\"itemToolbarTemplate; context: { option, $index, $last }\" />\n </div>\n }\n </div>\n </div>\n </div>\n </div>\n</ng-template>\n\n<ng-template\n #itemToolbarTemplate\n let-$index=\"$index\"\n let-$last=\"$last\"\n let-option=\"option\">\n @if (option.type === 'undo') {\n <div [class]=\"option.classInclude || 'mx-[8px]'\">\n <button\n LibsUiComponentsPopoverDirective\n [config]=\"{ content: 'i18n_undo', zIndex: zIndex() }\"\n class=\"ql-undo\"></button>\n </div>\n }\n @if (option.type === 'redo') {\n <div [class]=\"option.classInclude || 'mx-[8px]'\">\n <button\n LibsUiComponentsPopoverDirective\n [config]=\"{ content: 'i18n_redo', zIndex: zIndex() }\"\n class=\"ql-redo\"></button>\n </div>\n }\n @if (option.type === 'fontFamily') {\n <div\n class=\"relative w-[132px] h-full rounded-[4px] libs-ui-border-general {{ option.classInclude || 'mx-[8px]' }}\"\n [class.bg-white]=\"!readonly() && !loadingUploadImage()\">\n <libs_ui-components-dropdown\n [isNgContent]=\"true\"\n [labelPopoverFullWidth]=\"true\"\n [listConfig]=\"listConfigFont()\"\n [listHasButtonUnSelectOption]=\"false\"\n [listHiddenInputSearch]=\"true\"\n [readonly]=\"readonly()\"\n [zIndex]=\"1250\"\n (outSelectKey)=\"handleSelectFont($event)\">\n @if (fontSelected(); as fontSelected) {\n <div class=\"flex items-center cursor-pointer py-[7px] libs-ui-font-h5r pl-[16px] pr-[40px]\">\n <libs_ui-components-popover\n [type]=\"'text'\"\n [ignoreStopPropagationEvent]=\"true\"\n [config]=\"{ zIndex: zIndex() }\">\n {{ labelFontSelectedComputed() }}\n </libs_ui-components-popover>\n <i class=\"libs-ui-icon-move-right rotate-90 absolute right-[12px] text-[#6a7383] text-[16px]\"></i>\n </div>\n }\n </libs_ui-components-dropdown>\n </div>\n }\n @if (option.type === 'header') {\n <div\n class=\"relative w-[138px] h-full rounded-[4px] libs-ui-border-general {{ option.classInclude || 'mx-[8px]' }}\"\n [class.bg-white]=\"!readonly() && !loadingUploadImage()\">\n <libs_ui-components-dropdown\n [isNgContent]=\"true\"\n [labelPopoverFullWidth]=\"true\"\n [popoverCustomConfig]=\"{ widthByParent: false, width: 200, classInclude: 'h-[254px]', classIncludeOverlayBody: 'h-full', position: { mode: 'start', distance: -8 } }\"\n [listConfig]=\"listConfigHeader()\"\n [listHasButtonUnSelectOption]=\"false\"\n [listHiddenInputSearch]=\"true\"\n [readonly]=\"readonly()\"\n [listMaxItemShow]=\"-1\"\n [zIndex]=\"1250\"\n (outSelectKey)=\"handleSelectHeader($event)\">\n @if (headerSelected(); as headerSelected) {\n <div class=\"flex items-center cursor-pointer py-[7px] libs-ui-font-h5r pl-[16px] pr-[40px] {{ option.classInclude || 'mx-[8px]' }}\">\n <libs_ui-components-popover\n [type]=\"'text'\"\n [ignoreStopPropagationEvent]=\"true\"\n [config]=\"{ zIndex: zIndex() }\">\n {{ labelHeaderSelectedComputed() }}\n </libs_ui-components-popover>\n <i class=\"libs-ui-icon-move-right rotate-90 absolute right-[12px] text-[#6a7383] text-[16px]\"></i>\n </div>\n }\n </libs_ui-components-dropdown>\n </div>\n }\n @if (option.type === 'fontSize') {\n <div class=\" {{ option.classInclude || 'mx-[8px]' }}\">\n <libs_ui-components-inputs-valid\n #inputSizeRef\n [dataType]=\"'int'\"\n [(item)]=\"fontSize\"\n [fieldNameBind]=\"'value'\"\n [valueUpDownNumber]=\"1\"\n [maxValueNumber]=\"72\"\n [minValueNumber]=\"8\"\n [readonly]=\"readonly() || loadingUploadImage()\"\n [classContainerInput]=\"'w-[72px] h-[32px]'\"\n (outChangeValueByButtonUpDown)=\"handlerValueChangeFontSize()\"\n (outFocusAndBlur)=\"handlerValueChangeFontSize($event)\" />\n </div>\n }\n @if (option.type === 'color') {\n <div class=\"ql-color ql-picker ql-color-picker !flex items-center {{ option.classInclude || 'mx-[8px]' }}\">\n <libs_ui-components-popover [config]=\"{ content: 'i18n_text_color', zIndex: zIndex() }\">\n <libs_ui-components-buttons-select_color\n [zIndex]=\"zIndex()\"\n [direction]=\"'top'\"\n [externalContent]=\"true\"\n [customOptions]=\"{\n showAlpha: true,\n }\"\n [applyNow]=\"false\"\n (outColorChangeMultipleType)=\"handlerSetFormat('color', $event)\">\n <div\n class=\"libs-ui-icon-editor-color-text libs-ui-buttons-select-color text-[#6a7383] text-[16px] hover:text-[var(--libs-ui-color-light-1)]\"\n [class.libs-ui-icon-editor-color-text-active]=\"!!colorSelected()\"\n [style.--color-selected]=\"colorSelected()\"></div>\n </libs_ui-components-buttons-select_color>\n </libs_ui-components-popover>\n </div>\n }\n @if (option.type === 'background') {\n <div class=\"ql-background ql-picker ql-color-picker !flex items-center {{ option.classInclude || 'mx-[8px]' }}\">\n <libs_ui-components-popover [config]=\"{ content: 'i18n_background_color', zIndex: zIndex() }\">\n <libs_ui-components-buttons-select_color\n [zIndex]=\"zIndex()\"\n [direction]=\"'top'\"\n [externalContent]=\"true\"\n [applyNow]=\"false\"\n [customOptions]=\"{\n showAlpha: true,\n }\"\n (outColorChangeMultipleType)=\"handlerSetFormat('background', $event)\">\n <div\n class=\"libs-ui-icon-editor-color-background libs-ui-buttons-select-color text-[#6a7383] text-[16px] hover:text-[var(--libs-ui-color-light-1)]\"\n [class.libs-ui-icon-editor-color-background-active]=\"!!backgroundSelected()\"\n [style.--background-selected]=\"backgroundSelected()\"></div>\n </libs_ui-components-buttons-select_color>\n </libs_ui-components-popover>\n </div>\n }\n @if (option.type === 'bold') {\n <div [class]=\"option.classInclude || 'mx-[8px]'\">\n <button\n LibsUiComponentsPopoverDirective\n [config]=\"{ content: 'i18n_font_weight_bold', zIndex: zIndex() }\"\n class=\"ql-bold !flex\"></button>\n </div>\n }\n @if (option.type === 'italic') {\n <div [class]=\"option.classInclude || 'mx-[8px]'\">\n <button\n LibsUiComponentsPopoverDirective\n [config]=\"{ content: 'i18n_font_style_italic', zIndex: zIndex() }\"\n class=\"ql-italic !flex\"></button>\n </div>\n }\n @if (option.type === 'underline') {\n <div [class]=\"option.classInclude || 'mx-[8px]'\">\n <button\n LibsUiComponentsPopoverDirective\n [config]=\"{ content: 'i18n_text_decoration_underline', zIndex: zIndex() }\"\n class=\"ql-underline !flex\"></button>\n </div>\n }\n @if (option.type === 'strikeThrough') {\n <div [class]=\"option.classInclude || 'mx-[8px]'\">\n <button\n LibsUiComponentsPopoverDirective\n [config]=\"{ content: 'i18n_text_line_through', zIndex: zIndex() }\"\n class=\"ql-strike !flex\"></button>\n </div>\n }\n @if (option.type === 'script.sub') {\n <div [class]=\"option.classInclude || 'mx-[8px]'\">\n <button\n LibsUiComponentsPopoverDirective\n [config]=\"{ content: 'i18n_script_sub', zIndex: zIndex() }\"\n class=\"ql-script flex\"\n value=\"sub\"></button>\n </div>\n }\n @if (option.type === 'script.super') {\n <div [class]=\"option.classInclude || 'mx-[8px]'\">\n <button\n LibsUiComponentsPopoverDirective\n [config]=\"{ content: 'i18n_script_super', zIndex: zIndex() }\"\n class=\"ql-script flex\"\n value=\"super\"></button>\n </div>\n }\n @if (option.type === 'adjust') {\n <div class=\"relative !flex items-center ql-align ql-picker ql-icon-picker !w-max {{ option.classInclude || 'mx-[8px]' }}\">\n <libs_ui-components-popover [config]=\"{ content: 'i18n_adjust', zIndex: zIndex() }\">\n <libs_ui-components-dropdown\n [isNgContent]=\"true\"\n [ignoreStopPropagationEvent]=\"true\"\n [labelPopoverFullWidth]=\"true\"\n [listConfig]=\"listConfigAlign()\"\n [listHiddenInputSearch]=\"true\"\n [popoverCustomConfig]=\"{ ignoreArrow: true, classInclude: '!w-[32px] overflow-hidden !py-[4px]', position: { mode: 'start', distance: 0 }, paddingLeftItem: false }\"\n [listHasButtonUnSelectOption]=\"false\"\n [zIndex]=\"zIndex() + 1\"\n [listKeySelected]=\"adjustSelected()\"\n (outSelectKey)=\"handleSelectAlign($event)\">\n @if (alignSelected(); as alignSelected) {\n <div class=\"flex items-center cursor-pointer\">\n <i\n [class]=\"iconAlignSelectedComputed()\"\n [class.text-[var(--libs-ui-color-light-1)]]=\"adjustSelected() !== undefined\"></i>\n <i class=\"libs-ui-icon-move-right rotate-90 text-[#6a7383] text-[16px] ml-[4px]\"></i>\n </div>\n }\n </libs_ui-components-dropdown>\n </libs_ui-components-popover>\n </div>\n }\n @if (option.type === 'indentIncrease') {\n <div [class]=\"option.classInclude || 'mx-[8px]'\">\n <button\n LibsUiComponentsPopoverDirective\n [config]=\"{ content: 'i18n_indent_increase', zIndex: zIndex() }\"\n class=\"ql-indent\"\n value=\"+1\"></button>\n </div>\n }\n @if (option.type === 'indentDecrease') {\n <div [class]=\"option.classInclude || 'mx-[8px]'\">\n <button\n LibsUiComponentsPopoverDirective\n [config]=\"{ content: 'i18n_indent_decrease', zIndex: zIndex() }\"\n class=\"ql-indent\"\n value=\"-1\"></button>\n </div>\n }\n @if (option.type === 'listBulleted') {\n <div [class]=\"option.classInclude || 'mx-[8px]'\">\n <button\n LibsUiComponentsPopoverDirective\n [config]=\"{ content: 'i18n_list_bulleted', zIndex: zIndex() }\"\n class=\"ql-list ql-bullet\"\n value=\"bullet\"></button>\n </div>\n }\n @if (option.type === 'listNumbered') {\n <div [class]=\"option.classInclude || 'mx-[8px]'\">\n <button\n LibsUiComponentsPopoverDirective\n [config]=\"{ content: 'i18n_list_numbered', zIndex: zIndex() }\"\n class=\"ql-list ql-ordered\"\n value=\"ordered\"></button>\n </div>\n }\n @if (option.type === 'listChecked') {\n <div\n [class]=\"option.classInclude || 'mx-[8px]'\"\n [class.ql-active]=\"listCheckboxSelected()\">\n <button\n LibsUiComponentsPopoverDirective\n [config]=\"{ content: 'i18n_list_numbered', zIndex: zIndex() }\"\n class=\"ql-list ql-check\"\n value=\"check\"></button>\n </div>\n }\n @if (option.type === 'personalize' && templateToolBarPersonalize(); as templateToolBarPersonalize) {\n <div class=\"flex items-center {{ option.classInclude || 'mx-[8px]' }}\">\n <ng-container *ngTemplateOutlet=\"templateToolBarPersonalize\"></ng-container>\n </div>\n }\n @if (option.type === 'blockquote') {\n <div [class]=\"option.classInclude || 'mx-[8px]'\">\n <button\n LibsUiComponentsPopoverDirective\n [config]=\"{ content: 'i18n_quote', zIndex: zIndex() }\"\n class=\"ql-blockquote\"></button>\n </div>\n }\n @if (option.type === 'link') {\n <div [class]=\"option.classInclude || 'mx-[8px]'\">\n <button\n LibsUiComponentsPopoverDirective\n [config]=\"{ content: 'i18n_insert_link', zIndex: zIndex() }\"\n class=\"ql-link\"></button>\n </div>\n }\n @if (option.type === 'unLink') {\n <div [class]=\"option.classInclude || 'mx-[8px]'\">\n <button\n LibsUiComponentsPopoverDirective\n [config]=\"{ content: 'i18n_unlink', zIndex: zIndex() }\"\n class=\"ql-unLink\"\n (click)=\"handlerUnlink($event)\"></button>\n </div>\n }\n @if (option.type === 'image') {\n <div [class]=\"option.classInclude || 'mx-[8px]'\">\n <button\n LibsUiComponentsPopoverDirective\n [config]=\"{ content: 'i18n_image', zIndex: zIndex() }\"\n class=\"ql-image\"></button>\n </div>\n }\n @if (option.type === 'video') {\n <div [class]=\"option.classInclude || 'mx-[8px]'\">\n <button\n LibsUiComponentsPopoverDirective\n [config]=\"{ content: 'i18n_video', zIndex: zIndex() }\"\n class=\"ql-video\"></button>\n </div>\n }\n @if (option.type === 'emoji') {\n <div [class]=\"option.classInclude || 'mx-[8px]'\">\n <libs_ui-components-emoji\n [zIndex]=\"zIndex()\"\n [isNgContent]=\"true\"\n (outEventEmoji)=\"handlerInsertEmoji($event)\">\n <button class=\"ql-emoji\"></button>\n </libs_ui-components-emoji>\n </div>\n }\n @if (option.type === 'table') {\n <div [class]=\"option.classInclude || 'mx-[8px]'\">\n <button\n LibsUiComponentsPopoverDirective\n [config]=\"{ content: 'i18n_table', zIndex: zIndex() }\"\n class=\"ql-table\"></button>\n </div>\n }\n @if (option.type === 'line') {\n <div class=\"w-[1px] h-[16px] libs-ui-border-right-general\"></div>\n }\n</ng-template>\n\n<libs_ui-components-popover\n #inputLinkRef\n [mode]=\"'click'\"\n [ignoreHiddenPopoverContentWhenMouseLeave]=\"true\"\n [config]=\"{ template: viewLink, whiteTheme: true, ignoreArrow: true, zIndex: zIndex() }\"\n (outEvent)=\"handlerPopoverEvent($event)\" />\n\n<ng-template #viewLink>\n <div class=\"flex justify-between items-center px-[16px] py-[8px] rounded-[8px]\">\n <div\n class=\"w-full min-w-0 libs-ui-font-h5r\"\n [type]=\"'text'\"\n LibsUiComponentsPopoverDirective\n [config]=\"{ content: link().url, zIndex: zIndex() + 1 }\">\n {{ link().url }}\n </div>\n <div class=\"flex items-center ml-[16px]\">\n <libs_ui-components-buttons-button\n [type]=\"'button-link-primary'\"\n [iconOnlyType]=\"true\"\n [classIconLeft]=\"'libs-ui-icon-edit-line'\"\n [classInclude]=\"'!p-0'\"\n (outClick)=\"handlerEditLink($event)\" />\n <libs_ui-components-buttons-button\n [type]=\"'button-link-custom'\"\n [buttonCustom]=\"{\n configStepColor: {\n text: '#071631',\n text_hover: '#ee2d41',\n text_active: '#ee2d41',\n text_disable: '071631',\n },\n rootColor: '#071631',\n }\"\n [classInclude]=\"'!p-0 ml-[12px]'\"\n [iconOnlyType]=\"true\"\n [classIconLeft]=\"'libs-ui-icon-link-broken'\"\n (outClick)=\"handlerUnlink($event)\" />\n </div>\n </div>\n</ng-template>\n", styles: ["@charset \"UTF-8\";:host ::ng-deep .quill-container .ql-container{font-family:var(--libs-ui-font-family-name),\"Arial\"!important;font-weight:400}:host ::ng-deep .quill-container .ql-container .ql-editor{font-family:var(--libs-ui-font-family-name),\"Arial\"!important;font-weight:400;height:auto;min-height:100%;resize:var(--resize)}:host ::ng-deep .quill-container .ql-container .ql-editor ol,:host ::ng-deep .quill-container .ql-container .ql-editor ul{list-style:none!important;padding-left:0!important;margin-left:0!important}:host ::ng-deep .quill-container .ql-container .ql-editor ol li,:host ::ng-deep .quill-container .ql-container .ql-editor ul li{list-style-type:none!important}:host ::ng-deep .quill-container .ql-container .ql-editor li,:host ::ng-deep .quill-container .ql-container .ql-editor ol li,:host ::ng-deep .quill-container .ql-container .ql-editor ul li,:host ::ng-deep .quill-container .ql-container .ql-editor li[data-list]{counter-reset:none!important;counter-increment:none!important;counter-set:none!important}@supports (counter-set: none){:host ::ng-deep .quill-container .ql-container .ql-editor li[data-list]{counter-set:none!important}}:host ::ng-deep .quill-container .ql-container .ql-editor ol li:not(.ql-direction-rtl){counter-increment:none!important}:host ::ng-deep .quill-container .ql-container .ql-editor ol{counter-reset:my-counter 0!important}:host ::ng-deep .quill-container .ql-container .ql-editor ol>li[data-list=ordered]{counter-increment:my-counter 1!important;position:relative;padding-left:8px}:host ::ng-deep .quill-container .ql-container .ql-editor ol>li[data-list=ordered]:before{content:counter(my-counter) \". \"}:host ::ng-deep .quill-container .ql-container .ql-editor ol li span:before{content:\"\"!important}:host ::ng-deep .quill-container .ql-container .ql-editor ol li[data-list=bullet]:before{content:\"\\2022\"!important}:host ::ng-deep .quill-container .ql-container .ql-editor ol li[data-list=unchecked]:before{content:\"\\2610\"!important}:host ::ng-deep .quill-container .ql-container .ql-editor ol li[data-list=checked]:before{content:\"\\2611\"!important}:host ::ng-deep .quill-container .ql-container .ql-blank:before{font-style:normal!important;font-size:12px!important;color:#9ca2ad!important;font-family:var(--libs-ui-font-family-name),arial!important}:host ::ng-deep .quill-container .ql-active span:before{color:var(--libs-ui-color-light-1)!important}:host ::ng-deep .quill-container .ql-active .ql-fill{fill:var(--libs-ui-color-light-1)!important}:host ::ng-deep .quill-container .ql-script :hover .ql-fill{fill:var(--libs-ui-color-light-1)!important}:host ::ng-deep .quill-container .ql-toolbar{padding:0!important;border:none!important}:host ::ng-deep .quill-container .ql-toolbar button{padding:0!important;height:16px!important;width:16px!important}:host ::ng-deep .quill-container .ql-tooltip{display:none!important}:host ::ng-deep .quill-container #editor-resizer .toolbar{top:0!important;left:0!important;transform:none!important;font-family:var(--libs-ui-font-family-name),\"Arial\"!important;font-weight:400;font-size:12px}:host ::ng-deep .quill-container .libs-ui-icon-editor-color-text-active{color:var(--color-selected)!important}:host ::ng-deep .quill-container .libs-ui-icon-editor-color-background-active{color:var(--background-selected)!important}:host ::ng-deep .quill-container .ql-snow .ql-picker{font-size:12px!important;height:32px;float:none;width:auto}:host ::ng-deep .selected-cell{background-color:#0096ff4d}\n"] }]
3056
- }], ctorParameters: () => [] });
3057
-
3058
1620
  /**
3059
1621
  * Generated bundle index. Do not edit.
3060
1622
  */
3061
1623
 
3062
- export { LibsUiComponentsInputsQuill2xComponent, LibsUiComponentsInputsQuillComponent, convertHtmlToDivBlocks, getDeltaOfQuill2xFromHTML, getDeltaOfQuillFromHTML, getHTMLFromDeltaOfQuill, getHTMLFromDeltaOfQuill2x, insertContentWithRange, isEmptyQuill2x, processPasteData };
1624
+ export { LibsUiComponentsInputsQuillComponent, convertHtmlToDivBlocks, getDeltaOfQuillFromHTML, getHTMLFromDeltaOfQuill, insertContentWithRange, processPasteData };
3063
1625
  //# sourceMappingURL=libs-ui-components-inputs-quill.mjs.map