@sd-angular/core 19.0.0-beta.3 → 19.0.0-beta.4

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.
Files changed (44) hide show
  1. package/components/document-builder/src/document-builder.config.d.ts +21 -0
  2. package/components/document-builder/src/document-builder.utils.d.ts +10 -0
  3. package/fesm2022/sd-angular-core-components-document-builder.mjs +336 -124
  4. package/fesm2022/sd-angular-core-components-document-builder.mjs.map +1 -1
  5. package/fesm2022/sd-angular-core-components-table.mjs +4 -4
  6. package/fesm2022/sd-angular-core-components-table.mjs.map +1 -1
  7. package/fesm2022/sd-angular-core-components-workflow.mjs +23 -23
  8. package/fesm2022/sd-angular-core-components-workflow.mjs.map +1 -1
  9. package/fesm2022/sd-angular-core-forms-autocomplete.mjs +22 -2
  10. package/fesm2022/sd-angular-core-forms-autocomplete.mjs.map +1 -1
  11. package/fesm2022/sd-angular-core-forms-date.mjs +13 -3
  12. package/fesm2022/sd-angular-core-forms-date.mjs.map +1 -1
  13. package/fesm2022/sd-angular-core-forms-input-number.mjs +17 -3
  14. package/fesm2022/sd-angular-core-forms-input-number.mjs.map +1 -1
  15. package/fesm2022/sd-angular-core-forms-input.mjs +18 -6
  16. package/fesm2022/sd-angular-core-forms-input.mjs.map +1 -1
  17. package/fesm2022/sd-angular-core-forms-radio.mjs +15 -2
  18. package/fesm2022/sd-angular-core-forms-radio.mjs.map +1 -1
  19. package/fesm2022/sd-angular-core-forms-select.mjs +13 -2
  20. package/fesm2022/sd-angular-core-forms-select.mjs.map +1 -1
  21. package/fesm2022/sd-angular-core-forms-textarea.mjs +9 -2
  22. package/fesm2022/sd-angular-core-forms-textarea.mjs.map +1 -1
  23. package/fesm2022/sd-angular-core-modules-auth.mjs +5 -5
  24. package/fesm2022/sd-angular-core-modules-auth.mjs.map +1 -1
  25. package/fesm2022/sd-angular-core-modules-layout.mjs +1 -1
  26. package/fesm2022/sd-angular-core-modules-layout.mjs.map +1 -1
  27. package/fesm2022/sd-angular-core-services-confirm.mjs +1 -1
  28. package/fesm2022/sd-angular-core-services-confirm.mjs.map +1 -1
  29. package/fesm2022/sd-angular-core-utilities-extensions.mjs +66 -1
  30. package/fesm2022/sd-angular-core-utilities-extensions.mjs.map +1 -1
  31. package/fesm2022/sd-angular-core-utilities-models.mjs +2 -2
  32. package/fesm2022/sd-angular-core-utilities-models.mjs.map +1 -1
  33. package/forms/autocomplete/src/autocomplete.component.d.ts +5 -1
  34. package/forms/date/src/date.component.d.ts +4 -1
  35. package/forms/input/src/input.component.d.ts +6 -4
  36. package/forms/input-number/src/input-number.component.d.ts +4 -1
  37. package/forms/radio/src/radio.component.d.ts +5 -1
  38. package/forms/select/src/select.component.d.ts +5 -1
  39. package/forms/textarea/src/textarea.component.d.ts +3 -1
  40. package/modules/auth/guards/portal.guard.d.ts +3 -3
  41. package/package.json +63 -63
  42. package/utilities/extensions/index.d.ts +1 -0
  43. package/utilities/extensions/src/color.extension.d.ts +20 -0
  44. package/utilities/models/src/pattern.model.d.ts +2 -2
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Cấu hình màu cho Document Builder
3
+ * Bảng màu tập trung và cấu hình cho việc lựa chọn màu nhất quán
4
+ */
5
+ import { ColorPickerConfig, FontColorConfig, FontSizeConfig, HeadingConfig } from 'ckeditor5';
6
+ /**
7
+ * Trả về bảng màu chung được sử dụng trong tất cả tính năng của document builder
8
+ * @returns Mảng các tùy chọn màu được định sẵn với giá trị hex và label
9
+ */
10
+ export declare function getPresetColors(): FontColorConfig['colors'];
11
+ /**
12
+ * Trả về cấu hình bộ chọn màu với định dạng hex
13
+ * @returns Đối tượng cấu hình bộ chọn màu
14
+ */
15
+ export declare function getColorPickerConfig(): ColorPickerConfig;
16
+ /**
17
+ * Trả về cấu hình kích thước font cho document builder
18
+ * @returns Mảng các tùy chọn kích thước font được định sẵn
19
+ */
20
+ export declare function getFontSizeOptions(): FontSizeConfig['options'];
21
+ export declare function getHeadingOptions(): HeadingConfig['options'];
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Document Builder Utilities
3
+ * Các hàm tiện ích cho document builder
4
+ */
5
+ /**
6
+ * Chuẩn hóa nội dung bằng cách chuyển đổi tất cả màu HSL và RGB sang hex
7
+ * @param content - Nội dung HTML cần chuẩn hóa
8
+ * @returns Nội dung đã được chuẩn hóa với màu hex
9
+ */
10
+ export declare function normalize(content: string): string;
@@ -4,9 +4,8 @@ import { CommonModule } from '@angular/common';
4
4
  import * as i1 from '@ckeditor/ckeditor5-angular';
5
5
  import { CKEditorModule } from '@ckeditor/ckeditor5-angular';
6
6
  import { Plugin, ButtonView, ClassicEditor, Essentials, Paragraph, Bold, Italic, Underline, FontSize, FontColor, FontBackgroundColor, Alignment, Widget, toWidget, GeneralHtmlSupport, FontFamily, Heading, List, Table, TableToolbar, TableProperties, TableCellProperties, TableColumnResize, PasteFromOffice, PageBreak, Undo, Subscript, Superscript, Image, ImageUpload, ImageToolbar, ImageCaption, ImageResize, ImageStyle } from 'ckeditor5';
7
- import { SdResolveMaybeAsync } from '@sd-angular/core/utilities';
8
- import { SdUtilities } from '@sd-angular/core/utilities/extensions';
9
7
  import { Subscription, Subject, throttleTime } from 'rxjs';
8
+ import { SdResolveMaybeAsync, hslToHex, rgbToHex, SdUtilities } from '@sd-angular/core/utilities';
10
9
 
11
10
  class PageNumberPlugin extends Plugin {
12
11
  init() {
@@ -208,10 +207,15 @@ class CommentPlugin extends Plugin {
208
207
  const editor = this.editor;
209
208
  // --- 1. CONVERSION: MODEL MARKER -> VIEW CSS ---
210
209
  // Biến Marker thành Highlight màu vàng
211
- editor.conversion.for('editingDowncast').markerToHighlight({
212
- model: 'comment', // Khớp với prefix của markerId (ví dụ: comment:12345)
213
- view: {
214
- classes: 'ck-comment-marker', // Class CSS sẽ được gắn vào thẻ <span> bao quanh text
210
+ editor.conversion.for('downcast').markerToHighlight({
211
+ model: 'comment',
212
+ view: data => {
213
+ return {
214
+ classes: 'ck-comment-marker',
215
+ attributes: {
216
+ 'data-comment-id': data.markerName,
217
+ },
218
+ };
215
219
  },
216
220
  });
217
221
  // --- 3. ĐĂNG KÝ UI COMPONENT: 'addCommentBtn' ---
@@ -263,6 +267,29 @@ class CommentPlugin extends Plugin {
263
267
  });
264
268
  return view;
265
269
  });
270
+ // 8. Xử lý sự kiện Copy (Clipboard Output)
271
+ this.listenTo(editor.editing.view.document, 'clipboardOutput', (evt, data) => {
272
+ const content = data.content;
273
+ editor.editing.view.change(writer => {
274
+ // Tạo range bao quanh toàn bộ nội dung clipboard
275
+ const range = writer.createRangeIn(content);
276
+ // Mảng chứa các item cần xử lý
277
+ const itemsToClean = [];
278
+ // 1. Duyệt qua để tìm các thẻ có class ck-comment-marker
279
+ for (const item of range.getItems()) {
280
+ if (item.is('element') && item.hasClass('ck-comment-marker')) {
281
+ itemsToClean.push(item);
282
+ }
283
+ }
284
+ // 2. Thực hiện xóa Class và Attribute
285
+ for (const item of itemsToClean) {
286
+ // Xóa class 'ck-comment-marker'
287
+ writer.removeClass('ck-comment-marker', item);
288
+ // Xóa thuộc tính 'data-comment-id'
289
+ writer.removeAttribute('data-comment-id', item);
290
+ }
291
+ });
292
+ });
266
293
  }
267
294
  }
268
295
 
@@ -483,6 +510,35 @@ class VariablePlugin extends Plugin {
483
510
  }
484
511
  }
485
512
  }, { priority: 'highest' });
513
+ // 8. Xử lý sự kiện Copy (Clipboard Output)
514
+ // Khi copy, thay thế variable bằng text
515
+ this.listenTo(editor.editing.view.document, 'clipboardOutput', (evt, data) => {
516
+ const content = data.content;
517
+ editor.editing.view.change(writer => {
518
+ // Tạo range bao quanh toàn bộ nội dung clipboard
519
+ const range = writer.createRangeIn(content);
520
+ const itemsToReplace = [];
521
+ // Duyệt qua tất cả các phần tử trong clipboard để tìm variable
522
+ for (const item of range.getItems()) {
523
+ // Kiểm tra đúng là thẻ span và có class variable-widget
524
+ if (item.is('element', 'span') && item.hasClass('variable-widget')) {
525
+ itemsToReplace.push(item);
526
+ }
527
+ }
528
+ // Thay thế variable bằng text
529
+ for (const item of itemsToReplace) {
530
+ const displayText = item.getAttribute('data-display');
531
+ if (displayText) {
532
+ // Tạo một node text thuần túy
533
+ const textNode = writer.createText(`{{${displayText}}}`);
534
+ // Chèn text node vào ngay trước widget cũ
535
+ writer.insert(writer.createPositionBefore(item), textNode);
536
+ // Xóa widget cũ đi
537
+ writer.remove(item);
538
+ }
539
+ }
540
+ });
541
+ });
486
542
  }
487
543
  #isSdDocumentBuilderVariableResult = (obj) => {
488
544
  return (obj !== null &&
@@ -597,8 +653,203 @@ class Base64UploadAdapter {
597
653
  }
598
654
  }
599
655
 
656
+ /**
657
+ * Cấu hình màu cho Document Builder
658
+ * Bảng màu tập trung và cấu hình cho việc lựa chọn màu nhất quán
659
+ */
660
+ /**
661
+ * Trả về bảng màu chung được sử dụng trong tất cả tính năng của document builder
662
+ * @returns Mảng các tùy chọn màu được định sẵn với giá trị hex và label
663
+ */
664
+ function getPresetColors() {
665
+ return [
666
+ { color: '#000000', label: 'Black' },
667
+ { color: '#4D4D4D', label: 'Dim grey' },
668
+ { color: '#999999', label: 'Grey' },
669
+ { color: '#E6E6E6', label: 'Light grey' },
670
+ { color: '#FFFFFF', label: 'White' },
671
+ { color: '#E64D4D', label: 'Red' },
672
+ { color: '#E6994D', label: 'Orange' },
673
+ { color: '#E6E64D', label: 'Yellow' },
674
+ { color: '#99E64D', label: 'Light green' },
675
+ { color: '#4DE64D', label: 'Green' },
676
+ { color: '#4DE699', label: 'Aquamarine' },
677
+ { color: '#4DE6E6', label: 'Turquoise' },
678
+ { color: '#4D99E6', label: 'Light blue' },
679
+ { color: '#4D4DE6', label: 'Blue' },
680
+ { color: '#994DE6', label: 'Purple' },
681
+ ];
682
+ }
683
+ /**
684
+ * Trả về cấu hình bộ chọn màu với định dạng hex
685
+ * @returns Đối tượng cấu hình bộ chọn màu
686
+ */
687
+ function getColorPickerConfig() {
688
+ return {
689
+ format: 'hex',
690
+ };
691
+ }
692
+ /**
693
+ * Trả về cấu hình kích thước font cho document builder
694
+ * @returns Mảng các tùy chọn kích thước font được định sẵn
695
+ */
696
+ function getFontSizeOptions() {
697
+ return [
698
+ {
699
+ title: '9',
700
+ model: '9pt',
701
+ view: {
702
+ name: 'span',
703
+ styles: { 'font-size': '9pt' },
704
+ priority: 7,
705
+ },
706
+ },
707
+ {
708
+ title: '10',
709
+ model: '10pt',
710
+ view: {
711
+ name: 'span',
712
+ styles: { 'font-size': '10pt' },
713
+ priority: 7,
714
+ },
715
+ },
716
+ {
717
+ title: '11',
718
+ model: '11pt',
719
+ view: {
720
+ name: 'span',
721
+ styles: { 'font-size': '11pt' },
722
+ priority: 7,
723
+ },
724
+ },
725
+ {
726
+ title: '12',
727
+ model: '12pt',
728
+ view: {
729
+ name: 'span',
730
+ styles: { 'font-size': '12pt' },
731
+ priority: 7,
732
+ },
733
+ },
734
+ {
735
+ title: '13',
736
+ model: '13pt',
737
+ view: {
738
+ name: 'span',
739
+ styles: { 'font-size': '13pt' },
740
+ priority: 7,
741
+ },
742
+ },
743
+ {
744
+ title: '14',
745
+ model: '14pt',
746
+ view: {
747
+ name: 'span',
748
+ styles: { 'font-size': '14pt' },
749
+ priority: 7,
750
+ },
751
+ },
752
+ {
753
+ title: '16',
754
+ model: '16pt',
755
+ view: {
756
+ name: 'span',
757
+ styles: { 'font-size': '16pt' },
758
+ priority: 7,
759
+ },
760
+ },
761
+ {
762
+ title: '18',
763
+ model: '18pt',
764
+ view: {
765
+ name: 'span',
766
+ styles: { 'font-size': '18pt' },
767
+ priority: 7,
768
+ },
769
+ },
770
+ {
771
+ title: '20',
772
+ model: '20pt',
773
+ view: {
774
+ name: 'span',
775
+ styles: { 'font-size': '20pt' },
776
+ priority: 7,
777
+ },
778
+ },
779
+ {
780
+ title: '24',
781
+ model: '24pt',
782
+ view: {
783
+ name: 'span',
784
+ styles: { 'font-size': '24pt' },
785
+ priority: 7,
786
+ },
787
+ },
788
+ ];
789
+ }
790
+ function getHeadingOptions() {
791
+ return [
792
+ { model: 'paragraph', title: 'Paragraph', class: 'ck-heading_paragraph' },
793
+ { model: 'heading1', view: 'h1', title: 'Heading 1', class: 'ck-heading_heading1' },
794
+ { model: 'heading2', view: 'h2', title: 'Heading 2', class: 'ck-heading_heading2' },
795
+ { model: 'heading3', view: 'h3', title: 'Heading 3', class: 'ck-heading_heading3' },
796
+ ];
797
+ }
798
+
799
+ /**
800
+ * Document Builder Utilities
801
+ * Các hàm tiện ích cho document builder
802
+ */
803
+ /**
804
+ * Chuẩn hóa nội dung bằng cách chuyển đổi tất cả màu HSL và RGB sang hex
805
+ * @param content - Nội dung HTML cần chuẩn hóa
806
+ * @returns Nội dung đã được chuẩn hóa với màu hex
807
+ */
808
+ function normalize(content) {
809
+ let normalized = content;
810
+ // Chuyển đổi HSL sang hex
811
+ const hslRegex = /hsl\(\s*(\d+)\s*,\s*(\d+)%?\s*,\s*(\d+)%?\s*\)/gi;
812
+ normalized = normalized.replace(hslRegex, (match, h, s, l) => {
813
+ try {
814
+ const hue = parseInt(h, 10);
815
+ const saturation = parseInt(s, 10);
816
+ const lightness = parseInt(l, 10);
817
+ // Kiểm tra giá trị hợp lệ
818
+ if (hue >= 0 && hue <= 360 && saturation >= 0 && saturation <= 100 && lightness >= 0 && lightness <= 100) {
819
+ return hslToHex(hue, saturation, lightness);
820
+ }
821
+ }
822
+ catch (error) {
823
+ console.warn('Failed to convert HSL to hex:', error, match);
824
+ }
825
+ return match; // Giữ nguyên nếu không thể chuyển đổi
826
+ });
827
+ // Chuyển đổi RGB sang hex
828
+ const rgbRegex = /rgb\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)/gi;
829
+ normalized = normalized.replace(rgbRegex, (match, r, g, b) => {
830
+ try {
831
+ const red = parseInt(r, 10);
832
+ const green = parseInt(g, 10);
833
+ const blue = parseInt(b, 10);
834
+ if (red >= 0 && red <= 255 && green >= 0 && green <= 255 && blue >= 0 && blue <= 255) {
835
+ return rgbToHex(red, green, blue);
836
+ }
837
+ }
838
+ catch (error) {
839
+ console.warn('Failed to convert RGB to hex:', error, match);
840
+ }
841
+ return match;
842
+ });
843
+ return normalized;
844
+ }
845
+
600
846
  class SdDocumentBuilder {
601
847
  #id = '1212';
848
+ // Shared color palette and configuration
849
+ #sharedColors = getPresetColors();
850
+ #colorPickerConfig = getColorPickerConfig();
851
+ #fontSizeOptions = getFontSizeOptions();
852
+ #headingOptions = getHeadingOptions();
602
853
  option;
603
854
  disabled = false;
604
855
  set _disabled(val) {
@@ -607,6 +858,7 @@ class SdDocumentBuilder {
607
858
  }
608
859
  Editor = ClassicEditor;
609
860
  #editor;
861
+ #idTimeOutScrollHeading = null;
610
862
  // Config
611
863
  config = {
612
864
  getOption: () => this.option,
@@ -685,109 +937,24 @@ class SdDocumentBuilder {
685
937
  toolbar: ['toggleImageCaption', '|', 'imageStyle:inline', 'imageStyle:block', 'imageStyle:side'],
686
938
  },
687
939
  fontSize: {
688
- options: [
689
- // Định nghĩa từng size một cách tường minh
690
- {
691
- title: '9',
692
- model: '9pt',
693
- view: {
694
- name: 'span',
695
- styles: { 'font-size': '9pt' },
696
- priority: 7,
697
- },
698
- },
699
- {
700
- title: '10',
701
- model: '10pt',
702
- view: {
703
- name: 'span',
704
- styles: { 'font-size': '10pt' },
705
- priority: 7,
706
- },
707
- },
708
- {
709
- title: '11',
710
- model: '11pt',
711
- view: {
712
- name: 'span',
713
- styles: { 'font-size': '11pt' },
714
- priority: 7,
715
- },
716
- },
717
- {
718
- title: '12',
719
- model: '12pt',
720
- view: {
721
- name: 'span',
722
- styles: { 'font-size': '12pt' },
723
- priority: 7,
724
- },
725
- },
726
- {
727
- title: '13',
728
- model: '13pt',
729
- view: {
730
- name: 'span',
731
- styles: { 'font-size': '13pt' },
732
- priority: 7,
733
- },
734
- },
735
- {
736
- title: '14',
737
- model: '14pt',
738
- view: {
739
- name: 'span',
740
- styles: { 'font-size': '14pt' },
741
- priority: 7,
742
- },
743
- },
744
- {
745
- title: '16',
746
- model: '16pt',
747
- view: {
748
- name: 'span',
749
- styles: { 'font-size': '16pt' },
750
- priority: 7,
751
- },
752
- },
753
- {
754
- title: '18',
755
- model: '18pt',
756
- view: {
757
- name: 'span',
758
- styles: { 'font-size': '18pt' },
759
- priority: 7,
760
- },
761
- },
762
- {
763
- title: '20',
764
- model: '20pt',
765
- view: {
766
- name: 'span',
767
- styles: { 'font-size': '20pt' },
768
- priority: 7,
769
- },
770
- },
771
- {
772
- title: '24',
773
- model: '24pt',
774
- view: {
775
- name: 'span',
776
- styles: { 'font-size': '24pt' },
777
- priority: 7,
778
- },
779
- },
780
- ],
940
+ options: this.#fontSizeOptions,
781
941
  supportAllValues: false, // Khuyên dùng false để ép user chọn đúng size chuẩn
782
942
  },
943
+ heading: {
944
+ options: this.#headingOptions,
945
+ },
783
946
  // 4. Cấu hình bảng màu (Tùy chọn)
784
947
  fontColor: {
785
- columns: 5,
948
+ // columns: 5,
786
949
  documentColors: 10,
950
+ colorPicker: this.#colorPickerConfig,
951
+ colors: this.#sharedColors,
787
952
  },
788
953
  fontBackgroundColor: {
789
- columns: 5,
954
+ // columns: 5,
790
955
  documentColors: 10,
956
+ colorPicker: this.#colorPickerConfig,
957
+ colors: this.#sharedColors,
791
958
  },
792
959
  table: {
793
960
  contentToolbar: [
@@ -798,6 +965,14 @@ class SdDocumentBuilder {
798
965
  'tableProperties', // <--- Nút chỉnh thuộc tính bảng (Viền, Màu, Width)
799
966
  'tableCellProperties',
800
967
  ],
968
+ tableProperties: {
969
+ borderColors: this.#sharedColors,
970
+ colorPicker: this.#colorPickerConfig,
971
+ },
972
+ tableCellProperties: {
973
+ borderColors: this.#sharedColors,
974
+ colorPicker: this.#colorPickerConfig,
975
+ },
801
976
  },
802
977
  // Quan trọng: Cho phép paste style từ Word nhưng bỏ qua margin/padding
803
978
  htmlSupport: {
@@ -817,12 +992,11 @@ class SdDocumentBuilder {
817
992
  contentChange = new EventEmitter(); // Emit HTML content
818
993
  #subscription = new Subscription();
819
994
  #contentChangeSubject = new Subject();
820
- #editorChangeRxjs = new Subject();
821
995
  ngOnInit() {
822
996
  // https://onemount.atlassian.net/browse/SM-1862
823
997
  // Debounce trong rxjs không hỗ trợ leading -->
824
998
  this.#subscription.add(this.#contentChangeSubject.pipe(throttleTime(500, undefined, { leading: true, trailing: true })).subscribe(content => {
825
- this.contentChange.emit(content);
999
+ this.contentChange.emit(normalize(content));
826
1000
  }));
827
1001
  }
828
1002
  ngOnDestroy() {
@@ -830,6 +1004,12 @@ class SdDocumentBuilder {
830
1004
  }
831
1005
  onReady(editor) {
832
1006
  this.#editor = editor;
1007
+ editor.conversion.for('editingDowncast').markerToHighlight({
1008
+ model: 'highlightMarker',
1009
+ view: {
1010
+ classes: 'ck-heading-highlight',
1011
+ },
1012
+ });
833
1013
  // Setup orientation plugin callback
834
1014
  try {
835
1015
  const orientationPlugin = editor.plugins.get('PageOrientationPlugin');
@@ -863,10 +1043,30 @@ class SdDocumentBuilder {
863
1043
  if (this.disabled) {
864
1044
  // Bật chế độ chỉ đọc với ID khóa
865
1045
  this.#editor.enableReadOnlyMode(this.#id);
1046
+ // Disable page orientation button
1047
+ try {
1048
+ const orientationPlugin = this.#editor.plugins.get('PageOrientationPlugin');
1049
+ if (orientationPlugin && orientationPlugin.buttonView) {
1050
+ orientationPlugin.buttonView.isEnabled = false;
1051
+ }
1052
+ }
1053
+ catch (error) {
1054
+ console.warn('Failed to disable orientation button:', error);
1055
+ }
866
1056
  }
867
1057
  else {
868
1058
  // Tắt chế độ chỉ đọc với ID khóa tương ứng
869
1059
  this.#editor.disableReadOnlyMode(this.#id);
1060
+ // Enable page orientation button
1061
+ try {
1062
+ const orientationPlugin = this.#editor.plugins.get('PageOrientationPlugin');
1063
+ if (orientationPlugin && orientationPlugin.buttonView) {
1064
+ orientationPlugin.buttonView.isEnabled = true;
1065
+ }
1066
+ }
1067
+ catch (error) {
1068
+ console.warn('Failed to enable orientation button:', error);
1069
+ }
870
1070
  }
871
1071
  }
872
1072
  scrollToComment = (markerId) => {
@@ -1041,31 +1241,43 @@ class SdDocumentBuilder {
1041
1241
  scrollToHeading: (id) => {
1042
1242
  if (!this.#editor)
1043
1243
  return;
1044
- // 1. Lấy Model Element từ kho lưu trữ
1045
1244
  const modelElement = this.#headingElementsMap.get(id);
1046
1245
  if (modelElement) {
1047
- const editor = this.#editor;
1048
- const view = editor.editing.view;
1049
- // 2. Chuyển đổi Model Element -> View Element
1050
- // mapper.toViewElement sẽ trả về thẻ HTML ảo (View Element) tương ứng (ví dụ thẻ <h2>)
1051
- const viewElement = editor.editing.mapper.toViewElement(modelElement);
1246
+ this.#editor.model.change(writer => {
1247
+ // Xóa marker
1248
+ if (this.#idTimeOutScrollHeading) {
1249
+ clearTimeout(this.#idTimeOutScrollHeading);
1250
+ }
1251
+ const currentMarker = this.#editor.model.markers.get('highlightMarker');
1252
+ if (currentMarker) {
1253
+ writer.removeMarker(currentMarker);
1254
+ }
1255
+ // Tạo Range bao trùm highlight
1256
+ const range = writer.createRangeOn(modelElement);
1257
+ // Thêm Marker mới
1258
+ writer.addMarker('highlightMarker', {
1259
+ range: range,
1260
+ usingOperation: false,
1261
+ });
1262
+ });
1263
+ // Scroll tới vị trí đó
1264
+ const viewElement = this.#editor.editing.mapper.toViewElement(modelElement);
1052
1265
  if (viewElement) {
1053
- // 3. Từ View Element ảo -> Lấy ra DOM thật (HTMLElement)
1054
- const domElement = view.domConverter.mapViewToDom(viewElement);
1266
+ const domElement = this.#editor.editing.view.domConverter.viewToDom(viewElement);
1055
1267
  if (domElement) {
1056
- // 4. Dùng hàm native của trình duyệt để cuộn
1057
- domElement.scrollIntoView({
1058
- behavior: 'smooth',
1059
- block: 'start',
1060
- inline: 'nearest',
1061
- });
1062
- // 5. (Tùy chọn) Focus và đặt con trỏ vào đó
1063
- view.focus();
1064
- editor.model.change(writer => {
1065
- writer.setSelection(modelElement, 'on');
1066
- });
1268
+ domElement.scrollIntoView({ behavior: 'smooth', block: 'center' });
1067
1269
  }
1068
1270
  }
1271
+ // Tự động tắt marker sau 10 giây
1272
+ this.#idTimeOutScrollHeading = setTimeout(() => {
1273
+ if (this.#editor) {
1274
+ this.#editor.model.change(writer => {
1275
+ const marker = this.#editor.model.markers.get('highlightMarker');
1276
+ if (marker)
1277
+ writer.removeMarker(marker);
1278
+ });
1279
+ }
1280
+ }, 10000);
1069
1281
  }
1070
1282
  else {
1071
1283
  console.warn(`Heading with id ${id} not found.`);
@@ -1423,11 +1635,11 @@ class SdDocumentBuilder {
1423
1635
  // });
1424
1636
  }
1425
1637
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: SdDocumentBuilder, deps: [], target: i0.ɵɵFactoryTarget.Component });
1426
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.17", type: SdDocumentBuilder, isStandalone: true, selector: "sd-document-builder", inputs: { option: "option", _disabled: ["disabled", "_disabled"] }, outputs: { contentChange: "contentChange" }, ngImport: i0, template: "<div class=\"builder-container\">\n <ckeditor\n style=\"width: 100%\"\n [editor]=\"Editor\" \n [config]=\"config\" \n (ready)=\"onReady($event)\"\n [disabled]=\"disabled\">\n </ckeditor>\n</div>", styles: ["@charset \"UTF-8\";.builder-container{background-color:#f3f4f6;height:100%;overflow-y:auto;width:100%;display:flex;flex-direction:column;align-items:center;padding-bottom:20px}:host{display:inline-block}:host ::ng-deep .ck-editor{display:flex;flex-direction:column;align-items:center;width:100%}:host ::ng-deep .ck-editor .ck-editor__top,:host ::ng-deep .ck-editor .ck-editor__main{border:none!important;box-shadow:none!important}:host ::ng-deep .ck-content{background-color:#fff;width:210mm;min-height:1123px;padding:20mm!important;box-sizing:border-box!important;box-shadow:0 10px 15px -3px #0000001a}:host ::ng-deep .ck-content h1,:host ::ng-deep .ck-content h2,:host ::ng-deep .ck-content h3,:host ::ng-deep .ck-content h4,:host ::ng-deep .ck-content h5,:host ::ng-deep .ck-content h6{font-weight:400}:host ::ng-deep .ck-content.ck-focused{outline:none!important;border-color:#d1d5db!important}:host ::ng-deep .ck-content.landscape{width:297mm}:host ::ng-deep .ck-content>*{max-width:100%!important;box-sizing:border-box!important}:host ::ng-deep .ck-content img{max-width:100%!important;height:auto!important;object-fit:contain}:host ::ng-deep .ck-content p{margin-left:0!important;margin-right:0!important;margin-bottom:var(--ck-spacing-large);text-indent:0}:host ::ng-deep .ck-content ul,:host ::ng-deep .ck-content ol{padding-left:20px!important;margin-left:0!important}\n", "@charset \"UTF-8\";:host ::ng-deep .ck-comment-marker{background-color:#ffeb3b80;border-bottom:2px solid #fbc02d;cursor:pointer;transition:background-color .2s}:host ::ng-deep .ck-comment-marker:hover{background-color:#ffeb3bcc}:host ::ng-deep .ck-comment-marker.active-highlight{background-color:#ffeb3b;outline:2px dashed #f57f17}\n", "@charset \"UTF-8\";:host ::ng-deep .variable-widget{background-color:#e3f2fd;color:#1976d2;border:1px solid #90caf9!important;border-radius:4px;padding:2px 6px;font-weight:600;font-family:Segoe UI,Tahoma,Geneva,Verdana,sans-serif;font-size:10px;cursor:default;-webkit-user-select:none;user-select:none;display:inline-block;margin:0 4px;vertical-align:middle;font-size:0}:host ::ng-deep .variable-widget:before{content:attr(data-display);font-size:10px}:host ::ng-deep .variable-widget:hover{background-color:#bbdefb;box-shadow:0 1px 2px #0000001a}:host ::ng-deep .variable-widget.ck-widget_selected{outline:2px solid #2196f3;background-color:#bbdefb}:host ::ng-deep .ck.ck-clipboard-drop-target-line{display:none!important}:host ::ng-deep .ck.ck-content .ck-widget,:host ::ng-deep .ck.ck-content .ck-widget:hover,:host ::ng-deep .ck.ck-content .ck-widget:focus,:host ::ng-deep .ck.ck-content .ck-widget.ck-widget_selected,:host ::ng-deep .ck.ck-content .ck-widget.ck-widget_selected:hover{outline:none!important;box-shadow:none!important}\n", "@charset \"UTF-8\";:host ::ng-deep .ck-editor__editable .ck-widget.table{float:none!important;display:block!important;max-width:100%!important;width:100%!important;margin:0!important;clear:both}:host ::ng-deep .ck-editor__editable table{table-layout:auto!important;width:100%!important;border-collapse:collapse;margin:0!important}:host ::ng-deep .ck-editor__editable table td,:host ::ng-deep .ck-editor__editable table th{word-wrap:break-word;white-space:normal!important;padding:.4em!important}:host ::ng-deep .ck-editor__editable table td img,:host ::ng-deep .ck-editor__editable table th img{max-width:100%;height:auto}\n", "@charset \"UTF-8\";::ng-deep .ck-editor{--ck-font-size-base: 11px !important;--ck-icon-size: 16px !important;--ck-content-font-family: \"Times New Roman\", serif !important;--ck-content-font-size: 13pt;--ck-content-line-height: 1.5;--ck-spacing-small: 2px !important;--ck-spacing-standard: 4px !important;--ck-spacing-large: 8px !important}::ng-deep .ck-editor .ck-editor__top{position:sticky;top:0;z-index:100;width:100%;min-width:600px;margin-bottom:10px}::ng-deep .ck-editor .ck-editor__top .ck-sticky-panel__content{border:none!important}::ng-deep .ck-editor .ck-editor__top .ck-toolbar{background:#fff!important;box-shadow:0 4px 6px -1px #0000001a!important;padding:8px!important}::ng-deep .ck-editor .ck-editor__top .ck-toolbar .ck-toolbar__items{display:flex;justify-content:center;flex-wrap:wrap;align-items:center}::ng-deep .ck-editor .ck-toolbar{min-height:32px!important;padding:2px!important}::ng-deep .ck-editor .ck-button{padding:2px 4px!important;min-height:24px!important}::ng-deep .ck-editor .ck-dropdown__button{min-height:24px!important}::ng-deep .ck.ck-toolbar{background:#f8f9fa!important;border-bottom:1px solid #e0e0e0!important}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: CKEditorModule }, { kind: "component", type: i1.CKEditorComponent, selector: "ckeditor", inputs: ["editor", "config", "data", "tagName", "watchdog", "editorWatchdogConfig", "disableWatchdog", "disableTwoWayDataBinding", "disabled"], outputs: ["ready", "change", "blur", "focus", "error"] }] });
1638
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.17", type: SdDocumentBuilder, isStandalone: true, selector: "sd-document-builder", inputs: { option: "option", _disabled: ["disabled", "_disabled"] }, outputs: { contentChange: "contentChange" }, ngImport: i0, template: "<div class=\"builder-container\">\n <ckeditor\n style=\"width: 100%\"\n [editor]=\"Editor\" \n [config]=\"config\" \n (ready)=\"onReady($event)\"\n [disabled]=\"disabled\">\n </ckeditor>\n</div>", styles: ["@charset \"UTF-8\";.builder-container{background-color:#f3f4f6;height:100%;overflow-y:auto;width:100%;display:flex;flex-direction:column;align-items:center;padding-bottom:20px}:host{display:inline-block}:host ::ng-deep .ck-heading-highlight{background-color:#fef08a;animation:fadeOut 2s 8s forwards}@keyframes fadeOut{0%{background-color:#fef08a}to{background-color:transparent}}:host ::ng-deep .ck-editor{display:flex;flex-direction:column;align-items:center;width:100%}:host ::ng-deep .ck-editor .ck-editor__top,:host ::ng-deep .ck-editor .ck-editor__main{border:none!important;box-shadow:none!important}:host ::ng-deep .ck-content{background-color:#fff;width:210mm;min-height:1123px;padding:20mm!important;box-sizing:border-box!important;box-shadow:0 10px 15px -3px #0000001a}:host ::ng-deep .ck-content h1,:host ::ng-deep .ck-content h2,:host ::ng-deep .ck-content h3,:host ::ng-deep .ck-content h4,:host ::ng-deep .ck-content h5,:host ::ng-deep .ck-content h6{font-weight:400}:host ::ng-deep .ck-content.ck-focused{outline:none!important;border-color:#d1d5db!important}:host ::ng-deep .ck-content.landscape{width:297mm}:host ::ng-deep .ck-content>*{max-width:100%!important;box-sizing:border-box!important}:host ::ng-deep .ck-content img{max-width:100%!important;height:auto!important;object-fit:contain}:host ::ng-deep .ck-content p{margin-left:0!important;margin-right:0!important;margin-bottom:var(--ck-spacing-large);text-indent:0}:host ::ng-deep .ck-content ul,:host ::ng-deep .ck-content ol{padding-left:20px!important;margin-left:0!important}\n", "@charset \"UTF-8\";:host ::ng-deep .ck-comment-marker{background-color:#ffeb3b80;border-bottom:2px solid #fbc02d;cursor:pointer;transition:background-color .2s}:host ::ng-deep .ck-comment-marker:hover{background-color:#ffeb3bcc}:host ::ng-deep .ck-comment-marker.active-highlight{background-color:#ffeb3b;outline:2px dashed #f57f17}\n", "@charset \"UTF-8\";:host ::ng-deep .variable-widget{background-color:#e3f2fd;color:#1976d2;border:1px solid #90caf9!important;border-radius:4px;padding:2px 6px;font-weight:600;font-family:Segoe UI,Tahoma,Geneva,Verdana,sans-serif;font-size:10px;cursor:default;-webkit-user-select:none;user-select:none;display:inline-block;margin:0 4px;vertical-align:middle;font-size:0}:host ::ng-deep .variable-widget:before{content:attr(data-display);font-size:10px}:host ::ng-deep .variable-widget:hover{background-color:#bbdefb;box-shadow:0 1px 2px #0000001a}:host ::ng-deep .variable-widget.ck-widget_selected{outline:2px solid #2196f3;background-color:#bbdefb}:host ::ng-deep .ck.ck-clipboard-drop-target-line{display:none!important}:host ::ng-deep .ck.ck-content .ck-widget,:host ::ng-deep .ck.ck-content .ck-widget:hover,:host ::ng-deep .ck.ck-content .ck-widget:focus,:host ::ng-deep .ck.ck-content .ck-widget.ck-widget_selected,:host ::ng-deep .ck.ck-content .ck-widget.ck-widget_selected:hover{outline:none!important;box-shadow:none!important}\n", "@charset \"UTF-8\";:host ::ng-deep .ck-editor__editable .ck-widget.table{float:none!important;display:block!important;max-width:100%!important;width:100%!important;margin:0!important;clear:both}:host ::ng-deep .ck-editor__editable table{table-layout:auto!important;width:100%!important;border-collapse:collapse;margin:0!important}:host ::ng-deep .ck-editor__editable table td,:host ::ng-deep .ck-editor__editable table th{word-wrap:break-word;white-space:normal!important;padding:.4em!important}:host ::ng-deep .ck-editor__editable table td img,:host ::ng-deep .ck-editor__editable table th img{max-width:100%;height:auto}\n", "@charset \"UTF-8\";::ng-deep .ck-editor{--ck-font-size-base: 11px !important;--ck-icon-size: 16px !important;--ck-content-font-family: \"Times New Roman\", serif !important;--ck-content-font-size: 13pt;--ck-content-line-height: 1.5;--ck-spacing-small: 2px !important;--ck-spacing-standard: 4px !important;--ck-spacing-large: 8px !important}::ng-deep .ck-editor .ck-editor__top{position:sticky;top:0;z-index:100;width:100%;min-width:600px;margin-bottom:10px}::ng-deep .ck-editor .ck-editor__top .ck-sticky-panel__content{border:none!important}::ng-deep .ck-editor .ck-editor__top .ck-toolbar{background:#fff!important;box-shadow:0 4px 6px -1px #0000001a!important;padding:8px!important}::ng-deep .ck-editor .ck-editor__top .ck-toolbar .ck-toolbar__items{display:flex;justify-content:center;flex-wrap:wrap;align-items:center}::ng-deep .ck-editor .ck-toolbar{min-height:32px!important;padding:2px!important}::ng-deep .ck-editor .ck-button{padding:2px 4px!important;min-height:24px!important}::ng-deep .ck-editor .ck-dropdown__button{min-height:24px!important}::ng-deep .ck.ck-toolbar{background:#f8f9fa!important;border-bottom:1px solid #e0e0e0!important}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: CKEditorModule }, { kind: "component", type: i1.CKEditorComponent, selector: "ckeditor", inputs: ["editor", "config", "data", "tagName", "watchdog", "editorWatchdogConfig", "disableWatchdog", "disableTwoWayDataBinding", "disabled"], outputs: ["ready", "change", "blur", "focus", "error"] }] });
1427
1639
  }
1428
1640
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: SdDocumentBuilder, decorators: [{
1429
1641
  type: Component,
1430
- args: [{ selector: 'sd-document-builder', standalone: true, imports: [CommonModule, CKEditorModule], template: "<div class=\"builder-container\">\n <ckeditor\n style=\"width: 100%\"\n [editor]=\"Editor\" \n [config]=\"config\" \n (ready)=\"onReady($event)\"\n [disabled]=\"disabled\">\n </ckeditor>\n</div>", styles: ["@charset \"UTF-8\";.builder-container{background-color:#f3f4f6;height:100%;overflow-y:auto;width:100%;display:flex;flex-direction:column;align-items:center;padding-bottom:20px}:host{display:inline-block}:host ::ng-deep .ck-editor{display:flex;flex-direction:column;align-items:center;width:100%}:host ::ng-deep .ck-editor .ck-editor__top,:host ::ng-deep .ck-editor .ck-editor__main{border:none!important;box-shadow:none!important}:host ::ng-deep .ck-content{background-color:#fff;width:210mm;min-height:1123px;padding:20mm!important;box-sizing:border-box!important;box-shadow:0 10px 15px -3px #0000001a}:host ::ng-deep .ck-content h1,:host ::ng-deep .ck-content h2,:host ::ng-deep .ck-content h3,:host ::ng-deep .ck-content h4,:host ::ng-deep .ck-content h5,:host ::ng-deep .ck-content h6{font-weight:400}:host ::ng-deep .ck-content.ck-focused{outline:none!important;border-color:#d1d5db!important}:host ::ng-deep .ck-content.landscape{width:297mm}:host ::ng-deep .ck-content>*{max-width:100%!important;box-sizing:border-box!important}:host ::ng-deep .ck-content img{max-width:100%!important;height:auto!important;object-fit:contain}:host ::ng-deep .ck-content p{margin-left:0!important;margin-right:0!important;margin-bottom:var(--ck-spacing-large);text-indent:0}:host ::ng-deep .ck-content ul,:host ::ng-deep .ck-content ol{padding-left:20px!important;margin-left:0!important}\n", "@charset \"UTF-8\";:host ::ng-deep .ck-comment-marker{background-color:#ffeb3b80;border-bottom:2px solid #fbc02d;cursor:pointer;transition:background-color .2s}:host ::ng-deep .ck-comment-marker:hover{background-color:#ffeb3bcc}:host ::ng-deep .ck-comment-marker.active-highlight{background-color:#ffeb3b;outline:2px dashed #f57f17}\n", "@charset \"UTF-8\";:host ::ng-deep .variable-widget{background-color:#e3f2fd;color:#1976d2;border:1px solid #90caf9!important;border-radius:4px;padding:2px 6px;font-weight:600;font-family:Segoe UI,Tahoma,Geneva,Verdana,sans-serif;font-size:10px;cursor:default;-webkit-user-select:none;user-select:none;display:inline-block;margin:0 4px;vertical-align:middle;font-size:0}:host ::ng-deep .variable-widget:before{content:attr(data-display);font-size:10px}:host ::ng-deep .variable-widget:hover{background-color:#bbdefb;box-shadow:0 1px 2px #0000001a}:host ::ng-deep .variable-widget.ck-widget_selected{outline:2px solid #2196f3;background-color:#bbdefb}:host ::ng-deep .ck.ck-clipboard-drop-target-line{display:none!important}:host ::ng-deep .ck.ck-content .ck-widget,:host ::ng-deep .ck.ck-content .ck-widget:hover,:host ::ng-deep .ck.ck-content .ck-widget:focus,:host ::ng-deep .ck.ck-content .ck-widget.ck-widget_selected,:host ::ng-deep .ck.ck-content .ck-widget.ck-widget_selected:hover{outline:none!important;box-shadow:none!important}\n", "@charset \"UTF-8\";:host ::ng-deep .ck-editor__editable .ck-widget.table{float:none!important;display:block!important;max-width:100%!important;width:100%!important;margin:0!important;clear:both}:host ::ng-deep .ck-editor__editable table{table-layout:auto!important;width:100%!important;border-collapse:collapse;margin:0!important}:host ::ng-deep .ck-editor__editable table td,:host ::ng-deep .ck-editor__editable table th{word-wrap:break-word;white-space:normal!important;padding:.4em!important}:host ::ng-deep .ck-editor__editable table td img,:host ::ng-deep .ck-editor__editable table th img{max-width:100%;height:auto}\n", "@charset \"UTF-8\";::ng-deep .ck-editor{--ck-font-size-base: 11px !important;--ck-icon-size: 16px !important;--ck-content-font-family: \"Times New Roman\", serif !important;--ck-content-font-size: 13pt;--ck-content-line-height: 1.5;--ck-spacing-small: 2px !important;--ck-spacing-standard: 4px !important;--ck-spacing-large: 8px !important}::ng-deep .ck-editor .ck-editor__top{position:sticky;top:0;z-index:100;width:100%;min-width:600px;margin-bottom:10px}::ng-deep .ck-editor .ck-editor__top .ck-sticky-panel__content{border:none!important}::ng-deep .ck-editor .ck-editor__top .ck-toolbar{background:#fff!important;box-shadow:0 4px 6px -1px #0000001a!important;padding:8px!important}::ng-deep .ck-editor .ck-editor__top .ck-toolbar .ck-toolbar__items{display:flex;justify-content:center;flex-wrap:wrap;align-items:center}::ng-deep .ck-editor .ck-toolbar{min-height:32px!important;padding:2px!important}::ng-deep .ck-editor .ck-button{padding:2px 4px!important;min-height:24px!important}::ng-deep .ck-editor .ck-dropdown__button{min-height:24px!important}::ng-deep .ck.ck-toolbar{background:#f8f9fa!important;border-bottom:1px solid #e0e0e0!important}\n"] }]
1642
+ args: [{ selector: 'sd-document-builder', standalone: true, imports: [CommonModule, CKEditorModule], template: "<div class=\"builder-container\">\n <ckeditor\n style=\"width: 100%\"\n [editor]=\"Editor\" \n [config]=\"config\" \n (ready)=\"onReady($event)\"\n [disabled]=\"disabled\">\n </ckeditor>\n</div>", styles: ["@charset \"UTF-8\";.builder-container{background-color:#f3f4f6;height:100%;overflow-y:auto;width:100%;display:flex;flex-direction:column;align-items:center;padding-bottom:20px}:host{display:inline-block}:host ::ng-deep .ck-heading-highlight{background-color:#fef08a;animation:fadeOut 2s 8s forwards}@keyframes fadeOut{0%{background-color:#fef08a}to{background-color:transparent}}:host ::ng-deep .ck-editor{display:flex;flex-direction:column;align-items:center;width:100%}:host ::ng-deep .ck-editor .ck-editor__top,:host ::ng-deep .ck-editor .ck-editor__main{border:none!important;box-shadow:none!important}:host ::ng-deep .ck-content{background-color:#fff;width:210mm;min-height:1123px;padding:20mm!important;box-sizing:border-box!important;box-shadow:0 10px 15px -3px #0000001a}:host ::ng-deep .ck-content h1,:host ::ng-deep .ck-content h2,:host ::ng-deep .ck-content h3,:host ::ng-deep .ck-content h4,:host ::ng-deep .ck-content h5,:host ::ng-deep .ck-content h6{font-weight:400}:host ::ng-deep .ck-content.ck-focused{outline:none!important;border-color:#d1d5db!important}:host ::ng-deep .ck-content.landscape{width:297mm}:host ::ng-deep .ck-content>*{max-width:100%!important;box-sizing:border-box!important}:host ::ng-deep .ck-content img{max-width:100%!important;height:auto!important;object-fit:contain}:host ::ng-deep .ck-content p{margin-left:0!important;margin-right:0!important;margin-bottom:var(--ck-spacing-large);text-indent:0}:host ::ng-deep .ck-content ul,:host ::ng-deep .ck-content ol{padding-left:20px!important;margin-left:0!important}\n", "@charset \"UTF-8\";:host ::ng-deep .ck-comment-marker{background-color:#ffeb3b80;border-bottom:2px solid #fbc02d;cursor:pointer;transition:background-color .2s}:host ::ng-deep .ck-comment-marker:hover{background-color:#ffeb3bcc}:host ::ng-deep .ck-comment-marker.active-highlight{background-color:#ffeb3b;outline:2px dashed #f57f17}\n", "@charset \"UTF-8\";:host ::ng-deep .variable-widget{background-color:#e3f2fd;color:#1976d2;border:1px solid #90caf9!important;border-radius:4px;padding:2px 6px;font-weight:600;font-family:Segoe UI,Tahoma,Geneva,Verdana,sans-serif;font-size:10px;cursor:default;-webkit-user-select:none;user-select:none;display:inline-block;margin:0 4px;vertical-align:middle;font-size:0}:host ::ng-deep .variable-widget:before{content:attr(data-display);font-size:10px}:host ::ng-deep .variable-widget:hover{background-color:#bbdefb;box-shadow:0 1px 2px #0000001a}:host ::ng-deep .variable-widget.ck-widget_selected{outline:2px solid #2196f3;background-color:#bbdefb}:host ::ng-deep .ck.ck-clipboard-drop-target-line{display:none!important}:host ::ng-deep .ck.ck-content .ck-widget,:host ::ng-deep .ck.ck-content .ck-widget:hover,:host ::ng-deep .ck.ck-content .ck-widget:focus,:host ::ng-deep .ck.ck-content .ck-widget.ck-widget_selected,:host ::ng-deep .ck.ck-content .ck-widget.ck-widget_selected:hover{outline:none!important;box-shadow:none!important}\n", "@charset \"UTF-8\";:host ::ng-deep .ck-editor__editable .ck-widget.table{float:none!important;display:block!important;max-width:100%!important;width:100%!important;margin:0!important;clear:both}:host ::ng-deep .ck-editor__editable table{table-layout:auto!important;width:100%!important;border-collapse:collapse;margin:0!important}:host ::ng-deep .ck-editor__editable table td,:host ::ng-deep .ck-editor__editable table th{word-wrap:break-word;white-space:normal!important;padding:.4em!important}:host ::ng-deep .ck-editor__editable table td img,:host ::ng-deep .ck-editor__editable table th img{max-width:100%;height:auto}\n", "@charset \"UTF-8\";::ng-deep .ck-editor{--ck-font-size-base: 11px !important;--ck-icon-size: 16px !important;--ck-content-font-family: \"Times New Roman\", serif !important;--ck-content-font-size: 13pt;--ck-content-line-height: 1.5;--ck-spacing-small: 2px !important;--ck-spacing-standard: 4px !important;--ck-spacing-large: 8px !important}::ng-deep .ck-editor .ck-editor__top{position:sticky;top:0;z-index:100;width:100%;min-width:600px;margin-bottom:10px}::ng-deep .ck-editor .ck-editor__top .ck-sticky-panel__content{border:none!important}::ng-deep .ck-editor .ck-editor__top .ck-toolbar{background:#fff!important;box-shadow:0 4px 6px -1px #0000001a!important;padding:8px!important}::ng-deep .ck-editor .ck-editor__top .ck-toolbar .ck-toolbar__items{display:flex;justify-content:center;flex-wrap:wrap;align-items:center}::ng-deep .ck-editor .ck-toolbar{min-height:32px!important;padding:2px!important}::ng-deep .ck-editor .ck-button{padding:2px 4px!important;min-height:24px!important}::ng-deep .ck-editor .ck-dropdown__button{min-height:24px!important}::ng-deep .ck.ck-toolbar{background:#f8f9fa!important;border-bottom:1px solid #e0e0e0!important}\n"] }]
1431
1643
  }], propDecorators: { option: [{
1432
1644
  type: Input,
1433
1645
  args: [{ required: true }]