@libs-ui/components-inputs-quill 0.2.305 → 0.2.306-3

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.
@@ -557,6 +557,7 @@ const linkDefault = () => {
557
557
  };
558
558
  };
559
559
 
560
+ /* eslint-disable @typescript-eslint/no-explicit-any */
560
561
  class LibsUiComponentsInputsQuillComponent {
561
562
  qlEditorElement = signal(undefined);
562
563
  timeoutScrollToSelectionWithElementScrollHeightAuto = signal(undefined);
@@ -577,8 +578,8 @@ class LibsUiComponentsInputsQuillComponent {
577
578
  showMoreAction = signal(false);
578
579
  link = signal(linkDefault());
579
580
  toolbarOptionsConfig = signal([]);
580
- displayShowMoreToolbar = computed(() => this.toolbarOptionsConfig().some(item => item.display === false));
581
- displaySkeleton = computed(() => this.toolbarOptionsConfig().every(item => item.display === undefined));
581
+ displayShowMoreToolbar = computed(() => this.toolbarOptionsConfig().some((item) => item.display === false));
582
+ displaySkeleton = computed(() => this.toolbarOptionsConfig().every((item) => item.display === undefined));
582
583
  timeCalculationToolBar = signal(undefined);
583
584
  popoverFunctionControl = signal(undefined);
584
585
  quill = signal(undefined);
@@ -589,8 +590,8 @@ class LibsUiComponentsInputsQuillComponent {
589
590
  onDestroy = new Subject();
590
591
  dynamicComponentService = inject(LibsUiDynamicComponentService);
591
592
  translate = inject(TranslateService);
592
- isShowToolBar = input(true, { transform: val => val ?? true });
593
- isToolbarPositionFixed = input(false, { transform: val => val ?? false });
593
+ isShowToolBar = input(true, { transform: (val) => val ?? true });
594
+ isToolbarPositionFixed = input(false, { transform: (val) => val ?? false });
594
595
  classIncludeToolbar = input('');
595
596
  stylesIncludeToolbar = input();
596
597
  toolbarConfig = input();
@@ -642,11 +643,14 @@ class LibsUiComponentsInputsQuillComponent {
642
643
  constructor() {
643
644
  effect(() => {
644
645
  setTimeout(() => {
645
- const classes = `${this.classInclude() || ''} h-full w-full`.split(' ').map(item => item.trim()).filter(item => item);
646
+ const classes = `${this.classInclude() || ''} h-full w-full`
647
+ .split(' ')
648
+ .map((item) => item.trim())
649
+ .filter((item) => item);
646
650
  this.getQlEditorElement()?.classList.add(...classes);
647
651
  }, this.timeDelayInit() + 10);
648
652
  });
649
- effect((() => {
653
+ effect(() => {
650
654
  const type = this.toolbarConfig()?.type || 'default';
651
655
  const hasIconImage = this.uploadImageConfig().showIcon ?? false;
652
656
  const hasIconPersonalize = !!this.templateToolBarPersonalize();
@@ -655,7 +659,7 @@ class LibsUiComponentsInputsQuillComponent {
655
659
  this.cdr.detectChanges();
656
660
  this.calculatorToolbar();
657
661
  });
658
- }));
662
+ });
659
663
  }
660
664
  ngOnInit() {
661
665
  this.outFunctionsControl.emit({
@@ -676,7 +680,7 @@ class LibsUiComponentsInputsQuillComponent {
676
680
  this.scrollToSelectionWithElementScrollHeightAuto(range.indexSelect);
677
681
  return;
678
682
  },
679
- reCalculatorToolbar: this.calculatorToolbar.bind(this)
683
+ reCalculatorToolbar: this.calculatorToolbar.bind(this),
680
684
  });
681
685
  }
682
686
  async ngAfterViewInit() {
@@ -707,7 +711,73 @@ class LibsUiComponentsInputsQuillComponent {
707
711
  const icons = Quill.import('ui/icons');
708
712
  const italic = Quill.import('formats/italic');
709
713
  const bold = Quill.import('formats/bold');
710
- size.whitelist = ['8px', '9px', '10px', '11px', '12px', '13px', '14px', '15px', '16px', '17px', '18px', '19px', '20px', '21px', '22px', '23px', '24px', '25px', '26px', '27px', '28px', '29px', '30px', '31px', '32px', '33px', '34px', '35px', '36px', '37px', '38px', '39px', '40px', '41px', '42px', '43px', '44px', '45px', '46px', '47px', '48px', '49px', '50px', '51px', '52px', '53px', '54px', '55px', '56px', '57px', '58px', '59px', '60px', '61px', '62px', '63px', '64px', '65px', '66px', '67px', '68px', '69px', '70px', '71px', '72px'];
714
+ size.whitelist = [
715
+ '8px',
716
+ '9px',
717
+ '10px',
718
+ '11px',
719
+ '12px',
720
+ '13px',
721
+ '14px',
722
+ '15px',
723
+ '16px',
724
+ '17px',
725
+ '18px',
726
+ '19px',
727
+ '20px',
728
+ '21px',
729
+ '22px',
730
+ '23px',
731
+ '24px',
732
+ '25px',
733
+ '26px',
734
+ '27px',
735
+ '28px',
736
+ '29px',
737
+ '30px',
738
+ '31px',
739
+ '32px',
740
+ '33px',
741
+ '34px',
742
+ '35px',
743
+ '36px',
744
+ '37px',
745
+ '38px',
746
+ '39px',
747
+ '40px',
748
+ '41px',
749
+ '42px',
750
+ '43px',
751
+ '44px',
752
+ '45px',
753
+ '46px',
754
+ '47px',
755
+ '48px',
756
+ '49px',
757
+ '50px',
758
+ '51px',
759
+ '52px',
760
+ '53px',
761
+ '54px',
762
+ '55px',
763
+ '56px',
764
+ '57px',
765
+ '58px',
766
+ '59px',
767
+ '60px',
768
+ '61px',
769
+ '62px',
770
+ '63px',
771
+ '64px',
772
+ '65px',
773
+ '66px',
774
+ '67px',
775
+ '68px',
776
+ '69px',
777
+ '70px',
778
+ '71px',
779
+ '72px',
780
+ ];
711
781
  italic.tagName = 'i';
712
782
  bold.tagName = 'b';
713
783
  Quill.register(bold, true);
@@ -717,40 +787,42 @@ class LibsUiComponentsInputsQuillComponent {
717
787
  Quill.register(QuillDivBlot, true);
718
788
  Quill.register(alignStyle, true);
719
789
  Quill.register(QuillMentionBlot, true);
720
- this.blotsRegister()?.forEach(item => {
790
+ this.blotsRegister()?.forEach((item) => {
721
791
  Quill.register(item.component, true);
722
792
  });
723
793
  Quill.register({ 'formats/indent': indentStyle }, true);
724
- fromEvent(this.quillEditorEl()?.nativeElement, 'contextmenu').pipe(takeUntil(this.onDestroy)).subscribe(e => this.outContextMenu.emit(e));
725
- iconList().forEach(element => set(icons, element.key, `<span class="${element.icon} hover:text-[var(--libs-ui-color-light-1)] text-[16px] text-[#6a7383]"></span>`));
794
+ fromEvent(this.quillEditorEl()?.nativeElement, 'contextmenu')
795
+ .pipe(takeUntil(this.onDestroy))
796
+ .subscribe((e) => this.outContextMenu.emit(e));
797
+ iconList().forEach((element) => set(icons, element.key, `<span class="${element.icon} hover:text-[var(--libs-ui-color-light-1)] text-[16px] text-[#6a7383]"></span>`));
726
798
  this.quill.set(new Quill(this.quillEditorEl()?.nativeElement, {
727
799
  modules: {
728
800
  toolbar: {
729
801
  container: this.quillOptionEl()?.nativeElement,
730
- handlers: this.handlers()
802
+ handlers: this.handlers(),
731
803
  },
732
804
  clipboard: {
733
- matchVisual: false
805
+ matchVisual: false,
734
806
  },
735
807
  history: {
736
808
  delay: 1000,
737
809
  maxStack: 100,
738
- userOnly: false
810
+ userOnly: false,
739
811
  },
740
812
  keyboard: {
741
813
  bindings: {
742
814
  enter: {
743
815
  key: 13,
744
- handler: () => this.showMention() ? false : true
745
- }
746
- }
747
- }
816
+ handler: () => (this.showMention() ? false : true),
817
+ },
818
+ },
819
+ },
748
820
  },
749
821
  readOnly: this.readonly(),
750
822
  placeholder: this.translate.instant(this.placeholder()),
751
823
  theme: 'snow',
752
824
  bounds: this.heightAuto() ? this.wrapperEditorEl()?.nativeElement : this.quillEditorEl()?.nativeElement,
753
- scrollingContainer: this.heightAuto() ? this.wrapperEditorEl()?.nativeElement : null
825
+ scrollingContainer: this.heightAuto() ? this.wrapperEditorEl()?.nativeElement : null,
754
826
  }));
755
827
  this.quill()?.keyboard.addBinding({ key: 'Backspace' }, this.noPreventEmbedDeletion.bind(this));
756
828
  this.quill()?.keyboard.addBinding({ key: 'Delete' }, this.noPreventEmbedDeletion.bind(this));
@@ -761,8 +833,7 @@ class LibsUiComponentsInputsQuillComponent {
761
833
  if (editorRoot && this.blockUndoRedoKeyboard()) {
762
834
  const keydownHandler = (e) => {
763
835
  const isUndo = (e.key === 'z' || e.key === 'Z') && (e.ctrlKey || e.metaKey) && !e.shiftKey;
764
- const isRedo = ((e.key === 'z' || e.key === 'Z') && (e.ctrlKey || e.metaKey) && e.shiftKey) ||
765
- ((e.key === 'y' || e.key === 'Y') && e.ctrlKey);
836
+ const isRedo = ((e.key === 'z' || e.key === 'Z') && (e.ctrlKey || e.metaKey) && e.shiftKey) || ((e.key === 'y' || e.key === 'Y') && e.ctrlKey);
766
837
  if (isUndo || isRedo) {
767
838
  e.preventDefault();
768
839
  e.stopPropagation();
@@ -779,27 +850,33 @@ class LibsUiComponentsInputsQuillComponent {
779
850
  if (!this.quill())
780
851
  return false;
781
852
  const delta = this.quill()?.getContents(range.index, 1);
782
- if (delta?.ops.some(option => this.blotsRegister()?.find(item => get(option.insert, item.component['blotName']) && item.ignoreDelete))) {
853
+ if (delta?.ops.some((option) => this.blotsRegister()?.find((item) => get(option.insert, item.component['blotName']) && item.ignoreDelete))) {
783
854
  return false; // Ngăn không cho Quill xử lý xóa
784
855
  }
785
856
  return true;
786
857
  }
787
858
  setHandlerFunction() {
788
- this.handlers.update(item => ({ ...item, image: this.handlerShowUploadImage.bind(this), emoji: () => { return; } }));
859
+ this.handlers.update((item) => ({
860
+ ...item,
861
+ image: this.handlerShowUploadImage.bind(this),
862
+ emoji: () => {
863
+ return;
864
+ },
865
+ }));
789
866
  let link = false;
790
867
  const handlersExpand = this.handlersExpand();
791
868
  if (handlersExpand && handlersExpand.length) {
792
- handlersExpand.forEach(element => {
869
+ handlersExpand.forEach((element) => {
793
870
  if (element.title && element.action) {
794
871
  if (element.title === 'link') {
795
872
  link = true;
796
873
  }
797
- this.handlers.update(item => ({ ...item, [element.title]: element.action }));
874
+ this.handlers.update((item) => ({ ...item, [element.title]: element.action }));
798
875
  }
799
876
  });
800
877
  }
801
878
  if (!link) {
802
- this.handlers.update(item => ({ ...item, link: this.handleShowUploadLink.bind(this), unLink: this.handlerUnInsertLink.bind(this) }));
879
+ this.handlers.update((item) => ({ ...item, link: this.handleShowUploadLink.bind(this), unLink: this.handlerUnInsertLink.bind(this) }));
803
880
  }
804
881
  }
805
882
  adjustIndexForImages(index) {
@@ -827,7 +904,6 @@ class LibsUiComponentsInputsQuillComponent {
827
904
  adjustTextIndex(content);
828
905
  return imageCount;
829
906
  }
830
- ;
831
907
  handlerSelectionChange() {
832
908
  this.quill()?.on('selection-change', (range, oldRange, source) => {
833
909
  if (this.readonly()) {
@@ -850,7 +926,7 @@ class LibsUiComponentsInputsQuillComponent {
850
926
  quill: this.quill(),
851
927
  range,
852
928
  oldRange,
853
- source
929
+ source,
854
930
  });
855
931
  if (range.length === 0 && format?.link && source === 'user') {
856
932
  const selection = document.getSelection();
@@ -885,8 +961,8 @@ class LibsUiComponentsInputsQuillComponent {
885
961
  url: linkNode.href,
886
962
  range: {
887
963
  index: rangeIndex + countImage,
888
- length: linkText.length
889
- }
964
+ length: linkText.length,
965
+ },
890
966
  });
891
967
  this.popoverFunctionControl()?.showPopover(linkNode);
892
968
  }, 250);
@@ -915,7 +991,7 @@ class LibsUiComponentsInputsQuillComponent {
915
991
  this.quill()?.on('text-change', (event) => {
916
992
  this.outTextChange.emit({
917
993
  quill: this.quill(),
918
- delta: event
994
+ delta: event,
919
995
  });
920
996
  setTimeout(() => {
921
997
  if (event?.ops[1]?.insert === '\n') {
@@ -974,7 +1050,7 @@ class LibsUiComponentsInputsQuillComponent {
974
1050
  return;
975
1051
  }
976
1052
  this.insertLink(linkEdit.title, linkEdit.link);
977
- }
1053
+ },
978
1054
  });
979
1055
  return;
980
1056
  }
@@ -986,7 +1062,7 @@ class LibsUiComponentsInputsQuillComponent {
986
1062
  this.timeCalculationToolBar.set(setTimeout(() => {
987
1063
  const toolbarWidth = this.toolbarItemsEl().nativeElement.offsetWidth || 0;
988
1064
  let totalWidth = 32 + 28;
989
- this.toolbarOptionsConfig.update(configs => {
1065
+ this.toolbarOptionsConfig.update((configs) => {
990
1066
  configs.forEach((item, index) => {
991
1067
  item.display = true;
992
1068
  totalWidth += item.width;
@@ -1146,9 +1222,9 @@ class LibsUiComponentsInputsQuillComponent {
1146
1222
  { selector: '.ql-font-Helvetica', style: 'font-family: Helvetica' },
1147
1223
  { selector: '.libs-ui-quill-format-image', style: 'max-width: 100%; height: auto', overrideStyle: true },
1148
1224
  { selector: '.libs-ui-quill-mention', style: 'font-weight: 600;-moz-osx-font-smoothing: grayscale;-webkit-font-smoothing: antialiased; color: #7239EA', overrideStyle: true },
1149
- { selector: 'blockquote', style: 'border-left: 4px solid #ccc; margin-bottom: 5px; margin-top: 5px; padding-left: 16px', overrideStyle: true }
1225
+ { selector: 'blockquote', style: 'border-left: 4px solid #ccc; margin-bottom: 5px; margin-top: 5px; padding-left: 16px', overrideStyle: true },
1150
1226
  ];
1151
- this.blotsRegister()?.forEach(item => {
1227
+ this.blotsRegister()?.forEach((item) => {
1152
1228
  styleArray.push({ selector: `.${item.className}`, style: item.style, overrideStyle: true });
1153
1229
  });
1154
1230
  styleArray.forEach((item) => {
@@ -1161,7 +1237,7 @@ class LibsUiComponentsInputsQuillComponent {
1161
1237
  // Fixbug issue: https://admin-cv.mobio.vn/issues/49092
1162
1238
  let styleExist = element.getAttribute('style');
1163
1239
  if (styleExist) {
1164
- ['font-family: Arial', 'font-family: sans-serif', 'font-family: serif', 'font-family: monospace', 'font-family: Helvetica'].forEach(font => {
1240
+ ['font-family: Arial', 'font-family: sans-serif', 'font-family: serif', 'font-family: monospace', 'font-family: Helvetica'].forEach((font) => {
1165
1241
  styleExist = (styleExist?.includes(`${font};`) ? styleExist?.replace(`${font};`, '') : styleExist?.replace(font, ''));
1166
1242
  });
1167
1243
  }
@@ -1212,7 +1288,7 @@ class LibsUiComponentsInputsQuillComponent {
1212
1288
  if (!links?.length) {
1213
1289
  return;
1214
1290
  }
1215
- links.forEach(link => {
1291
+ links.forEach((link) => {
1216
1292
  if (!link || (this.uploadImageConfig().onlyAcceptImageHttpsLink && (link instanceof ArrayBuffer || !new RegExp(patternUrl()).test(link)))) {
1217
1293
  return;
1218
1294
  }
@@ -1247,7 +1323,7 @@ class LibsUiComponentsInputsQuillComponent {
1247
1323
  this.quill()?.format('size', `${size}px`);
1248
1324
  }
1249
1325
  handlerValueChange(value) {
1250
- this.size.update(item => ({ ...item, value: value }));
1326
+ this.size.update((item) => ({ ...item, value: value }));
1251
1327
  this.quill()?.format('size', `${this.size().value}px`);
1252
1328
  }
1253
1329
  handleSelectAlign(event) {
@@ -1260,7 +1336,7 @@ class LibsUiComponentsInputsQuillComponent {
1260
1336
  }
1261
1337
  handlerChangeShowMoreAction(event) {
1262
1338
  event.stopPropagation();
1263
- this.showMoreAction.update(item => !item);
1339
+ this.showMoreAction.update((item) => !item);
1264
1340
  }
1265
1341
  scrollToSelectionWithElementScrollHeightAuto(index) {
1266
1342
  clearTimeout(this.timeoutScrollToSelectionWithElementScrollHeightAuto());
@@ -1289,7 +1365,10 @@ class LibsUiComponentsInputsQuillComponent {
1289
1365
  if (!html) {
1290
1366
  return '';
1291
1367
  }
1292
- return html.replace(/^\s*<p><br><\/p>/, '').replace(/<div><br><\/div>/gi, '').replace(/[\u200B-\u200D\uFEFF]/g, '');
1368
+ return html
1369
+ .replace(/^\s*<p><br><\/p>/, '')
1370
+ .replace(/<div><br><\/div>/gi, '')
1371
+ .replace(/[\u200B-\u200D\uFEFF]/g, '');
1293
1372
  }
1294
1373
  handleSelectHeader(event) {
1295
1374
  this.headerSelected.set(event);
@@ -1309,13 +1388,19 @@ class LibsUiComponentsInputsQuillComponent {
1309
1388
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: LibsUiComponentsInputsQuillComponent, decorators: [{
1310
1389
  type: Component,
1311
1390
  args: [{ selector: 'libs_ui-components-inputs-quill', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [
1312
- TranslateModule, NgTemplateOutlet,
1313
- LibsUiComponentsInputsMentionDirective, LibsUiComponentsScrollOverlayDirective,
1314
- LibsUiComponentsLabelComponent, LibsUiComponentsDropdownComponent,
1315
- LibsUiComponentsPopoverComponent, LibsUiComponentsButtonsSelectColorComponent,
1316
- LibsUiComponentsInputsValidComponent, LibsUiComponentsEmojiComponent,
1317
- LibsUiComponentsButtonsButtonComponent, LibsUiComponentsSpinnerComponent,
1318
- LibsUiComponentsSkeletonComponent
1391
+ TranslateModule,
1392
+ NgTemplateOutlet,
1393
+ LibsUiComponentsInputsMentionDirective,
1394
+ LibsUiComponentsScrollOverlayDirective,
1395
+ LibsUiComponentsLabelComponent,
1396
+ LibsUiComponentsDropdownComponent,
1397
+ LibsUiComponentsPopoverComponent,
1398
+ LibsUiComponentsButtonsSelectColorComponent,
1399
+ LibsUiComponentsInputsValidComponent,
1400
+ LibsUiComponentsEmojiComponent,
1401
+ LibsUiComponentsButtonsButtonComponent,
1402
+ LibsUiComponentsSpinnerComponent,
1403
+ LibsUiComponentsSkeletonComponent,
1319
1404
  ], template: "<div class=\"flex flex-col w-full h-full\">\n @if (label(); as label) {\n <libs_ui-components-label [classInclude]=\"label.classInclude\"\n [required]=\"label.required\"\n [labelLeft]=\"label.labelLeft\" />\n }\n <div #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 #editor\n class=\"libs-ui-quill\"\n [attr.showError]=\"messageError() && showErrorBorder() && onlyShowErrorBorderInContent()\"\n [class.!hidden]=\"!display()\">\n <div #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 #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 #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 class=\"toolbar h-full w-full shrink-0\"\n #toolbarItems>\n @if (displaySkeleton()) {\n <libs_ui-components-skeleton class=\"w-full h-full\"\n [config]=\"{\n rows: [{\n item:{classIncludeItem:'!rounded-none',}\n }]\n }\" />\n }\n <div class=\"ql-formats items-center px-[16px] py-[4px]\">\n @for (option of toolbarOptionsConfig(); track option) {\n <div 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 [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 [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 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\n<ng-template #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 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 LibsUiComponentsPopoverDirective\n [config]=\"{content: 'i18n_redo', zIndex: zIndex()}\"\n class=\"ql-redo\"></button>\n </div>\n }\n @if (option.type === 'fontFamily') {\n <div 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 [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 [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 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 [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\n 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 [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 [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 [zIndex]=\"zIndex()\"\n [direction]=\"'top'\"\n [externalContent]=\"true\"\n [customOptions]=\"{\n showAlpha:true,\n\n }\"\n [applyNow]=\"false\"\n (outColorChange)=\"setStyle('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 </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 [zIndex]=\"zIndex()\"\n [direction]=\"'top'\"\n [externalContent]=\"true\"\n [applyNow]=\"false\"\n [customOptions]=\"{\n showAlpha:true,\n }\"\n (outColorChange)=\"setStyle('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 </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 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 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 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 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\n 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 [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 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 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 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 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 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 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 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 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 [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 [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 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 [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 [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-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"] }]
1320
1405
  }], ctorParameters: () => [] });
1321
1406