@ldquocc/dynamic-form 0.0.2 → 0.0.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.
@@ -1,11 +1,11 @@
1
- import * as i0 from '@angular/core';
2
- import { InjectionToken, inject, Injectable, signal, untracked, input, computed, Input, Directive, effect, forwardRef, Component, EventEmitter, output, Output } from '@angular/core';
3
1
  import * as i1 from '@angular/forms';
4
2
  import { FormsModule, ReactiveFormsModule, FormControl, Validators, FormGroup, NG_VALUE_ACCESSOR } from '@angular/forms';
5
3
  import { of, delay, Subject, takeUntil, finalize, Observable, debounceTime, distinctUntilChanged } from 'rxjs';
6
4
  import * as i1$2 from '@angular/common';
7
5
  import { CommonModule, CurrencyPipe } from '@angular/common';
8
6
  import { RouterModule } from '@angular/router';
7
+ import * as i0 from '@angular/core';
8
+ import { InjectionToken, inject, Injectable, signal, untracked, input, computed, Input, Directive, effect, forwardRef, Component, EventEmitter, output, Output } from '@angular/core';
9
9
  import * as i3$3 from 'ng-zorro-antd/form';
10
10
  import { NzFormModule } from 'ng-zorro-antd/form';
11
11
  import { isEqual } from 'lodash-es';
@@ -42,14 +42,6 @@ import { NzGridModule } from 'ng-zorro-antd/grid';
42
42
  import * as i4$2 from 'ng-zorro-antd/collapse';
43
43
  import { NzCollapseModule } from 'ng-zorro-antd/collapse';
44
44
 
45
- var FormModeEnum;
46
- (function (FormModeEnum) {
47
- FormModeEnum["Add"] = "add";
48
- FormModeEnum["Edit"] = "edit";
49
- FormModeEnum["View"] = "view";
50
- FormModeEnum["Design"] = "design";
51
- })(FormModeEnum || (FormModeEnum = {}));
52
-
53
45
  // Core Angular modules (cần thiết ở hầu hết các component).
54
46
  const CORE_MODULES = [CommonModule];
55
47
  // Form handling (thường dùng với Reactive)
@@ -568,6 +560,241 @@ class DateRangeField extends BaseDateField {
568
560
  }
569
561
  }
570
562
 
563
+ // Các patterns regex thường dùng trong ứng dụng
564
+ const PATTERN_PRESETS = {
565
+ alpha: '^[a-zA-Z]+$',
566
+ alphaNumeric: '^[a-zA-Z0-9]+$',
567
+ name: "^[0-9a-zA-Z_ ÀÁÂÃÈÉÊÌÍÒÓÔÕÙÚĂĐĨŨƠàáâãèéêìíòóôõùúăđĩũơƯĂẠẢẤẦẨẪẬẮẰẲẴẶẸẺẼỀỀỂẾưăạảấầẩẫậắằẳẵặẹẻẽềềểếỄỆỈỊỌỎỐỒỔỖỘỚỜỞỠỢỤỦỨỪễệỉịọỏốồổỗộớờởỡợụủứừỬỮỰỲỴÝỶỸửữựỳỵýỷỹ\\.+,:%&=;s.\\/\\-_'\\()]+$",
568
+ username: '^[a-z0-9_.s]+$',
569
+ regexPostCode: '^[a-zA-Z0-9-s]+$',
570
+ alphaDash: '^[a-zA-Z0-9_-s.]+$',
571
+ alphaVN: '^[a-zA-Z_ ÀÁÂÃÈÉÊÌÍÒÓÔÕÙÚĂĐĨŨƠàáâãèéêìíòóôõùúăđĩũơƯĂẠẢẤẦẨẪẬẮẰẲẴẶẸẺẼỀỀỂẾưăạảấầẩẫậắằẳẵặẹẻẽềềểếỄỆỈỊỌỎỐỒỔỖỘỚỜỞỠỢỤỦỨỪễệỉịọỏốồổỗộớờởỡợụủứừỬỮỰỲỴÝỶỸửữựỳỵýỷỹ\\,s]+$',
572
+ alphaNumericVN: '^[0-9a-zA-Z_ ÀÁÂÃÈÉÊÌÍÒÓÔÕÙÚĂĐĨŨƠàáâãèéêìíòóôõùúăđĩũơƯĂẠẢẤẦẨẪẬẮẰẲẴẶẸẺẼỀỀỂẾưăạảấầẩẫậắằẳẵặẹẻẽềềểếỄỆỈỊỌỎỐỒỔỖỘỚỜỞỠỢỤỦỨỪễệỉịọỏốồổỗộớờởỡợụủứừỬỮỰỲỴÝỶỸửữựỳỵýỷỹ\\s]+$',
573
+ alphaDashVN: "^[0-9a-zA-Z_ ÀÁÂÃÈÉÊÌÍÒÓÔÕÙÚĂĐĨŨƠàáâãèéêìíòóôõùúăđĩũơƯĂẠẢẤẦẨẪẬẮẰẲẴẶẸẺẼỀỀỂẾưăạảấầẩẫậắằẳẵặẹẻẽềềểếỄỆỈỊỌỎỐỒỔỖỘỚỜỞỠỢỤỦỨỪễệỉịọỏốồổỗộớờởỡợụủứừỬỮỰỲỴÝỶỸửữựỳỵýỷỹ\\.+,:%&=;s.\\/\\-_'\\()]+$",
574
+ unitName: '^[a-zA-Z0-9 ÀÁÂÃÈÉÊÌÍÒÓÔÕÙÚĂĐĨŨƠàáâãèéêìíòóôõùúăđĩũơƯĂẠẢẤẦẨẪẬẮẰẲẴẶẸẺẼỀỀỂẾưăạảấầẩẫậắằẳẵặẹẻẽềềểếỄỆỈỊỌỎỐỒỔỖỘỚỜỞỠỢỤỦỨỪễệỉịọỏốồổỗộớờởỡợụủứừỬỮỰỲỴÝỶỸửữựỳỵỷỹs_-]+$',
575
+ date: '([12]\\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[12]\\d|3[01]))',
576
+ time: '(?=[01]\\d|2[0123])=(?=[012345]\\d)=(?=[012345]\\d)',
577
+ dateTime: '[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1]) (2[0-3]|[01][0-9])=[0-5][0-9]=[0-5][0-9]',
578
+ // dateV: "^(0?[1-9]|[12][0-9]|3[01])[\\/](0?[1-9]|1[012])[\\/]\\d{4}$",
579
+ // dateV: /^(0?[1-9]|[12][0-9]|3[01])[\/\-](0?[1-9]|1[012])[\/\-](19|20)\d\d/,
580
+ // dateV: "^([0-2][0-9]|(3)[0-1])(\-)(((0)[0-9])|((1)[0-2]))(\-)\d{4}$",
581
+ dateVN: '^(?=0[1-9]|[12]d|3[01])([/.-])(?=0[1-9]|1[012])\\1(?=19|20)dd$',
582
+ dateTimeVN: '^(0?[1-9]|[12][0-9]|3[01])[\\/](0?[1-9]|1[012])[\\/]\\d{4} (\\d{2})=(\\d{2})=(\\d{2})$',
583
+ dateShortTimeVN: '^(0?[1-9]|[12][0-9]|3[01])[\\/](0?[1-9]|1[012])[\\/]\\d{4} (\\d{2})=(\\d{2})$',
584
+ integer: '^\\-?[0-9]+$',
585
+ decimal: '^\\-?[0-9]*\\.?[0-9]+$',
586
+ ipAddress: '^((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[0-9]{1,2})\\.){3}(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[0-9]{1,2})$',
587
+ base64: '[^a-zA-Z0-9\\/\\+=]',
588
+ citizenId: '^\\d{12}$',
589
+ passport: '^[A-Z0-9]{6,12}$', // Hộ chiếu - 6-12 ký tự (chữ IN HOA và số)
590
+ // dnkhcn: "/^DNKHCN-[A-Z]{2}-d{4}$/",
591
+ // msdn: "/^d{10}$/",
592
+ intergerNotZero: '^[0-9]*[1-9][0-9]*$',
593
+ //link: "(https?=//(?=www.|(?!www))[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9].[^s]{2,}|www.[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9].[^s]{2,}|https?=//(?=www.|(?!www))[a-zA-Z0-9]+.[^s]{2,}|www.[a-zA-Z0-9]+.[^s]{2,})",
594
+ // code: "^['A-Z''0-9''._\\-']*$",
595
+ code: "^['A-Z''0-9''./_\\-\\/\\Đ']*$",
596
+ codeHsda: "^['A-Z''0-9''./_\\-']*$",
597
+ link_location: '(https?://)?([\\da-z.-]+)\\.([a-z.]{2,6})([/\\w .-]*)?(\\?[\\w=&,.%-]*)?',
598
+ link: '(https?://)?([\\da-z.-]+)\\.([a-z.]{2,6})[/\\w .-]*/?',
599
+ //password: "/(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[$@$!%*?&]).{8,}/",
600
+ accountName: '^[a-zA-Z0-9_.]{2,20}$',
601
+ name_or_fullName: '^[a-zA-Z0-9_ÀÁÂÃÈÉÊÌÍÒÓÔÕÙÚĂĐĨŨƠàáâãèéêìíòóôõùúăđĩũơƯĂẠẢẤẦẨẪẬẮẰẲẴẶẸẺẼỀỀỂưăạảấầẩẫậắằẳẵặẹẻẽềềểỄỆỈỊỌỎỐỒỔỖỘỚỜỞỠỢỤỦỨỪễếệỉịọỏốồổỗộớờởỡợụủứừỬỮỰỲỴÝỶỸửữựỳỵỷỹ ]{1,20}$',
602
+ packageName: '^(?:[a-zA-Z]+(?:d*[a-zA-Z_]*)*)(?:.[a-zA-Z]+(?:d*[a-zA-Z_]*)*)+$',
603
+ email: '^[a-z0-9._%+-]+@[a-z0-9.-]+\\.[a-z]{2,4}$',
604
+ passwordRegex: '^(?!.*\\s)(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(?=.*[~`!@#$%^&*()--+={}\\[\\]|\\\\:;"\'<>,.?/_₹]).{8,}$',
605
+ // phoneNumber: "^(\\+84|0)([235789])([0-9]{8,9})\\b",
606
+ phoneNumber: '^(\\+84|0)([235789])([0-9]{8,9})$',
607
+ seqNum: '^(100|[0-9]{1,2})$',
608
+ link_basemap: '(https://www.|http://www.|https://|http://)?[a-zA-Z]{2,}(.[a-zA-Z]{2,})(.[a-zA-Z]{2,})?/[a-zA-Z0-9]{2,}|((https://www.|http://www.|https://|http://)?[a-zA-Z]{2,}(.[a-zA-Z]{2,})(.[a-zA-Z]{2,})?)|(https://www.|http://www.|https://|http://)?[a-zA-Z0-9]{2,}.[a-zA-Z0-9]{2,}.[a-zA-Z0-9]{2,}(.[a-zA-Z0-9]{2,})?',
609
+ alphaDashBreakLineVN: "^[0-9a-zA-Z_ ÀÁÂÃÈÉÊÌÍÒÓÔÕÙÚĂĐĨŨƠàáâãèéêìíòóôõùúăđĩũơƯĂẠẢẤẦẨẪẬẮẰẲẴẶẸẺẼỀỀỂẾưăạảấầẩẫậắằẳẵặẹẻẽềềểếỄỆỈỊỌỎỐỒỔỖỘỚỜỞỠỢỤỦỨỪễệỉịọỏốồổỗộớờởỡợụủứừỬỮỰỲỴÝỶỸửữựỳỵýỷỹ\\.+,:%&=;s.\\/\\-_'\\(\\)\n]+$",
610
+ fax: '^(\\+?\\d{1,4}[\\s-]?)?(\\(?\\d{2,4}\\)?[\\s-]?)?[\\d\\s-]{5,15}$',
611
+ alphaDashNameVN: "^[a-zA-Z_ ÀÁÂÃÈÉÊÌÍÒÓÔÕÙÚĂĐĨŨƠàáâãèéêìíòóôõùúăđĩũơƯĂẠẢẤẦẨẪẬẮẰẲẴẶẸẺẼỀỀỂẾưăạảấầẩẫậắằẳẵặẹẻẽềềểếỄỆỈỊỌỎỐỒỔỖỘỚỜỞỠỢỤỦỨỪễệỉịọỏốồổỗộớờởỡợụủứừỬỮỰỲỴÝỶỸửữựỳỵýỷỹ\.s.\/\-\_'\\(\\)]{2,}$",
612
+ businessCode: '^\\d{10}(-\\d{3})?$',
613
+ };
614
+ // Các error message cho các pattern regex.
615
+ const PATTERN_ERROR_MESSAGES = {
616
+ required: '%s không được để trống!',
617
+ number: '%s phải là số!',
618
+ email: '%s không đúng định dạng địa chỉ Email!',
619
+ minlength: '%s có kích thước tối thiểu %s ký tự!',
620
+ maxlength: '%s có kích thước tối đa %s ký tự!',
621
+ min: '%s phải lớn hơn hoặc bằng %s!',
622
+ max: '%s phải nhỏ hơn hoặc bằng %s!',
623
+ alpha: '%s chỉ chứa ký tự thường và ký tự in hoa không dấu!',
624
+ alphaNumeric: '%s chỉ chứa ký tự thường, ký tự in hoa không dấu và số!',
625
+ name: '%s chỉ chứa ký tự thường, ký tự in hoa có dấu, số, dấu chấm, dấu phẩy, gạch dưới _ hoặc gạch ngang -, dấu ngoặc ()!',
626
+ username: '%s chỉ chứa ký tự thường, số, dấu chấm và dấu gạch dưới _',
627
+ regexPostCode: '%s chỉ chứa ký tự thường, ký tự in hoa không dấu, số, gạch ngang -',
628
+ alphaDash: '%s chỉ chứa ký tự thường, ký tự in hoa không dấu, số, gạch dưới _ hoặc gạch ngang -, dấu ngoặc ()!',
629
+ alphaVN: '%s chỉ chứa ký tự thường và ký tự in hoa có dấu!',
630
+ alphaNumericVN: '%s chỉ chứa ký tự thường, ký tự in hoa có dấu và số!',
631
+ alphaDashVN: '%s chỉ chứa ký tự thường, ký tự in hoa có dấu, số, dấu chấm, dấu phẩy, gạch dưới _ hoặc gạch ngang -, dấu ngoặc ()!',
632
+ alphaDashNameVN: '%s chỉ chứa ký tự thường, ký tự in hoa có dấu và ít nhất 2 ký tự!',
633
+ unitName: '%s chỉ chứa ký tự thường, ký tự in hoa có dấu, số, gạch dưới _ hoặc gạch ngang -',
634
+ date: '%s không đúng định dạng năm tháng ngày (YYYY-MM-DD)!',
635
+ time: '%s không đúng định dạng giờ phút giây (HH:MM:SS)!',
636
+ dateTime: '%s không đúng định dạng năm tháng ngày giờ phút giây (YYYY-MM-DD HH:MM:SS)!',
637
+ dateVN: '%s không đúng định dạng ngày tháng năm (DD/MM/YYYY)!',
638
+ dateTimeVN: '%s không đúng định dạng ngày tháng năm giờ phút giây (DD/MM/YYYY HH:MI:SS)!',
639
+ dateShortTimeVN: '%s không đúng định dạng ngày tháng năm giờ phút (DD/MM/YYYY HH:MI)!',
640
+ integer: '%s phải là số nguyên!',
641
+ decimal: '%s phải là số thập phân!',
642
+ ipAddress: '%s không đúng định dạng địa chỉ IP!',
643
+ base64: '%s không đúng định dạng Base64!',
644
+ intergerNotZero: '%s phải là số nguyên dương khác 0!',
645
+ link_location: '%s không đúng định dạng!',
646
+ link: '%s không đúng định dạng!',
647
+ codeHsda: "%s chỉ chứa các chữ cái in hoa không dấu, số và dấu '.', '_', '-'",
648
+ code: "%s chỉ chứa các chữ cái in hoa không dấu, số và dấu '.', '_', '-', '/'",
649
+ // code: "%s chỉ chứa các chữ cái in hoa,chữ cái thường không dấu, số và dấu '.', '_', '-'",
650
+ accountName: '%s chỉ bao gồm các kí tự từ A-Z, các số từ 0-9 và ít nhất 2 ký tự',
651
+ name_or_fullName: '',
652
+ // pwdErrorTip:
653
+ // "%s phải có ít nhất 8 ký tự. Ít nhất 1 ký tự hoa, số, ký tự thường và ký tự đặc biệt",
654
+ phoneNumber: 'Số điện thoại không hợp lệ (Gợi ý: Số điện thoại phải bắt đầu bằng đầu số 02, 03, 05, 07, 08, 09 hoặc +84 và có độ dài 10-11 ký tự)',
655
+ seqNum: '(Gợi ý: Thứ tự hiển thị phải là dạng số và có giá trị từ 1-100)',
656
+ link_basemap: '%s không đúng định dạng!',
657
+ passwordRegex: '%s phải có ít nhất 8 ký tự. Ít nhất 1 ký tự hoa, ký tự thường, số và ký tự đặc biệt',
658
+ alphaDashBreakLineVN: '%s chỉ chứa ký tự thường, ký tự in hoa có dấu, số, dấu chấm, dấu phẩy, gạch dưới _ hoặc gạch ngang -, dấu ngoặc ()!',
659
+ citizenId: '%s phải đúng định dạng 12 số!',
660
+ businessCode: '',
661
+ };
662
+
663
+ const resolvePattern = (pattern) => {
664
+ if (!pattern)
665
+ return { type: 'unknown', value: '' };
666
+ // Trường hợp là RegExp thực sự
667
+ if (pattern instanceof RegExp)
668
+ return { type: 'regexObject', value: pattern };
669
+ // Trường hợp là tên preset (ưu tiên nếu trùng)
670
+ if (pattern in PATTERN_PRESETS) {
671
+ return { type: 'regexKey', value: PATTERN_PRESETS[pattern] };
672
+ }
673
+ try {
674
+ // Trường hợp là chuỗi regex dạng "^abc$"
675
+ return { type: 'regexString', value: new RegExp(pattern) };
676
+ }
677
+ catch (err) {
678
+ console.warn(`Không thể parse pattern "${pattern}"`, err);
679
+ return { type: 'unknown', value: '' };
680
+ }
681
+ };
682
+
683
+ const DEFAULT_INPUT_VALUE = '';
684
+ /**
685
+ * Interface base chung cho Các dạng Input Field.
686
+ */
687
+ class InputBaseField extends BaseField {
688
+ constructor(init) {
689
+ super(init);
690
+ /**
691
+ * Gán giá trị cho các props cần giá trị mặc định ở Input.
692
+ */
693
+ this.controlType = ControlTypeEnum.Input;
694
+ this.value = DEFAULT_INPUT_VALUE;
695
+ this.initialValue = DEFAULT_INPUT_VALUE;
696
+ this.suffixes = [];
697
+ this.isCurrency = false;
698
+ Object.assign(this, init);
699
+ }
700
+ // Mảng ValidatorFn các validation chung được hỗ trợ sẵn bởi Reactive form của angular cho Input.
701
+ getInputCommonValidators() {
702
+ const validators = this.getCommonValidators();
703
+ if (this.minLength)
704
+ validators.push(Validators.minLength(this.minLength));
705
+ if (this.maxLength)
706
+ validators.push(Validators.maxLength(this.maxLength));
707
+ if (this.pattern) {
708
+ const resolvePatternResult = resolvePattern(this.pattern);
709
+ if (resolvePatternResult?.type !== 'unknown')
710
+ validators.push(Validators.pattern(resolvePatternResult.value));
711
+ }
712
+ return validators;
713
+ }
714
+ // Mảng ValidatorFn các custom validation có thể dùng cho Input.
715
+ getInputCustomValidators() {
716
+ const validators = this.getCustomValidators();
717
+ validators.push(noLeadingSpaceValidator());
718
+ return validators;
719
+ }
720
+ // Tạo Form Control cho Input Field.
721
+ toFormControl() {
722
+ const commonValidators = this.getInputCommonValidators();
723
+ const customValidators = this.getInputCustomValidators();
724
+ return new FormControl(this.value ?? '', [...commonValidators, ...customValidators]);
725
+ }
726
+ // Giá trị mặc định.
727
+ getDefaultValue() {
728
+ return DEFAULT_INPUT_VALUE;
729
+ }
730
+ toFormValue(modelValue) {
731
+ return String(modelValue);
732
+ }
733
+ getErrorMessage(errorKey, errorValue, allFields) {
734
+ if (errorKey === CommonValidaterEnum.Pattern) {
735
+ if (this.pattern)
736
+ return getDefaultPatternErrorMessage(this.label, this.pattern);
737
+ }
738
+ if (errorKey === CommonValidaterEnum.MinLength)
739
+ return getDefaultMinLengthErrorMessage(this.label, errorValue);
740
+ if (errorKey === CommonValidaterEnum.MaxLength)
741
+ return getDefaultMaxLengthErrorMessage(this.label, errorValue);
742
+ if (errorKey === CustomValidaterEnum.LeadingSpace)
743
+ return getLeadingSpaceErrorMessage(this.label);
744
+ return super.getErrorMessage(errorKey, errorValue, allFields);
745
+ }
746
+ }
747
+
748
+ /**
749
+ * Interface của Input Field type là Text.
750
+ */
751
+ class InputTextField extends InputBaseField {
752
+ constructor(init) {
753
+ super(init);
754
+ /**
755
+ * Gán giá trị cho các props cần giá trị mặc định ở Input Text.
756
+ */
757
+ this.type = FieldTypeEnum.InputText;
758
+ Object.assign(this, init);
759
+ }
760
+ // Tạo Form Control cho Input Text Field.
761
+ toFormControl() {
762
+ const commonValidators = this.getInputCommonValidators();
763
+ const customValidators = this.getInputCustomValidators();
764
+ return new FormControl(this.value ?? '', [...commonValidators, ...customValidators]);
765
+ }
766
+ }
767
+
768
+ /**
769
+ * Interface của Input Field type là Password.
770
+ */
771
+ class InputPasswordField extends InputBaseField {
772
+ constructor(init) {
773
+ super(init);
774
+ /**
775
+ * Gán giá trị cho các props cần giá trị mặc định ở Input Password.
776
+ */
777
+ this.type = FieldTypeEnum.InputPassword;
778
+ Object.assign(this, init);
779
+ }
780
+ // Mảng ValidatorFn các validation chung được hỗ trợ sẵn bởi Reactive form của angular cho Input Password.
781
+ getInputPasswordCommonValidators() {
782
+ const validators = this.getInputCommonValidators();
783
+ return validators;
784
+ }
785
+ // Mảng ValidatorFn các validation chung được hỗ trợ sẵn bởi angular cho Input Password.
786
+ getInputPasswordCustomValidators() {
787
+ const validators = this.getInputCustomValidators();
788
+ return validators;
789
+ }
790
+ // Tạo Form Control cho Input Password Field.
791
+ toFormControl() {
792
+ const commonValidators = this.getInputPasswordCommonValidators();
793
+ const customValidators = this.getInputPasswordCustomValidators();
794
+ return new FormControl(this.value ?? '', [...commonValidators, ...customValidators]);
795
+ }
796
+ }
797
+
571
798
  /**
572
799
  * Interface base chung cho Các dạng Input Field.
573
800
  */
@@ -2641,206 +2868,86 @@ const asyncUsernameValidator = (takenUsernames) => {
2641
2868
  };
2642
2869
  };
2643
2870
  // Không có ký tự đặc biệt.
2644
- const noSpecialCharValidator = () => {
2645
- return (control) => {
2646
- const valid = /^[a-zA-Z0-9]*$/.test(control.value);
2647
- return valid ? null : { noSpecialChar: true };
2648
- };
2649
- };
2650
- // Username không được nằm trong blacklist.
2651
- const usernameBlacklistValidator = (blacklist) => {
2652
- return (control) => {
2653
- return blacklist.includes(control.value) ? { blacklisted: true } : null;
2654
- };
2655
- };
2656
- // Có thuộc mimetypes từ mảng mimetypes được chỉ định hay không?
2657
- const acceptedMimeTypesValidator = (acceptedMimeTypes) => {
2658
- return (control) => {
2659
- const value = control?.value;
2660
- if (value) {
2661
- let fileType = '';
2662
- if (value instanceof File) {
2663
- fileType = value.type;
2664
- }
2665
- if (isValidJSON(value)) {
2666
- const { contentType } = JSON.parse(value)[0] || {};
2667
- if (contentType)
2668
- fileType = contentType;
2669
- }
2670
- if (fileType) {
2671
- if (!acceptedMimeTypes.includes(fileType)) {
2672
- return {
2673
- acceptedMimeTypes: {
2674
- actualValue: fileType,
2675
- requiredValue: `Nằm trong ${acceptedMimeTypes}`,
2676
- },
2677
- };
2678
- }
2679
- }
2680
- }
2681
- return null;
2682
- };
2683
- };
2684
- const maxFileSizeInMBValidator = (maxSizeInMB) => {
2685
- return (control) => {
2686
- const file = control?.value;
2687
- if (file) {
2688
- const fileSizeInMB = formatFileSize(file.size, FileSizeTypeEnum.MB);
2689
- if (fileSizeInMB > maxSizeInMB) {
2690
- return {
2691
- maxSizeInMB: {
2692
- actualValue: fileSizeInMB,
2693
- requiredValue: `Nhỏ hơn ${maxSizeInMB}`,
2694
- },
2695
- };
2696
- }
2697
- }
2698
- return null;
2699
- };
2700
- };
2701
- const reminderCustomRequiredValidator = () => {
2702
- return (control) => {
2703
- const reminderValue = control?.value;
2704
- if (!reminderValue) {
2705
- return {
2706
- reminderCustomRequired: {
2707
- requiredValue: `Giá trị radio và cả từ select hoặc date`,
2708
- },
2709
- };
2710
- }
2711
- if (reminderValue) {
2712
- const { reminderDate } = reminderValue;
2713
- if (!reminderDate) {
2714
- return {
2715
- reminderCustomRequired: {
2716
- actualValue: reminderDate,
2717
- requiredValue: `Giá trị từ select hoặc date`,
2718
- },
2719
- };
2720
- }
2721
- }
2722
- return null;
2723
- };
2724
- };
2725
-
2726
- // Các patterns regex thường dùng trong ứng dụng
2727
- const PATTERN_PRESETS = {
2728
- alpha: '^[a-zA-Z]+$',
2729
- alphaNumeric: '^[a-zA-Z0-9]+$',
2730
- name: "^[0-9a-zA-Z_ ÀÁÂÃÈÉÊÌÍÒÓÔÕÙÚĂĐĨŨƠàáâãèéêìíòóôõùúăđĩũơƯĂẠẢẤẦẨẪẬẮẰẲẴẶẸẺẼỀỀỂẾưăạảấầẩẫậắằẳẵặẹẻẽềềểếỄỆỈỊỌỎỐỒỔỖỘỚỜỞỠỢỤỦỨỪễệỉịọỏốồổỗộớờởỡợụủứừỬỮỰỲỴÝỶỸửữựỳỵýỷỹ\\.+,:%&=;s.\\/\\-_'\\()]+$",
2731
- username: '^[a-z0-9_.s]+$',
2732
- regexPostCode: '^[a-zA-Z0-9-s]+$',
2733
- alphaDash: '^[a-zA-Z0-9_-s.]+$',
2734
- alphaVN: '^[a-zA-Z_ ÀÁÂÃÈÉÊÌÍÒÓÔÕÙÚĂĐĨŨƠàáâãèéêìíòóôõùúăđĩũơƯĂẠẢẤẦẨẪẬẮẰẲẴẶẸẺẼỀỀỂẾưăạảấầẩẫậắằẳẵặẹẻẽềềểếỄỆỈỊỌỎỐỒỔỖỘỚỜỞỠỢỤỦỨỪễệỉịọỏốồổỗộớờởỡợụủứừỬỮỰỲỴÝỶỸửữựỳỵýỷỹ\\,s]+$',
2735
- alphaNumericVN: '^[0-9a-zA-Z_ ÀÁÂÃÈÉÊÌÍÒÓÔÕÙÚĂĐĨŨƠàáâãèéêìíòóôõùúăđĩũơƯĂẠẢẤẦẨẪẬẮẰẲẴẶẸẺẼỀỀỂẾưăạảấầẩẫậắằẳẵặẹẻẽềềểếỄỆỈỊỌỎỐỒỔỖỘỚỜỞỠỢỤỦỨỪễệỉịọỏốồổỗộớờởỡợụủứừỬỮỰỲỴÝỶỸửữựỳỵýỷỹ\\s]+$',
2736
- alphaDashVN: "^[0-9a-zA-Z_ ÀÁÂÃÈÉÊÌÍÒÓÔÕÙÚĂĐĨŨƠàáâãèéêìíòóôõùúăđĩũơƯĂẠẢẤẦẨẪẬẮẰẲẴẶẸẺẼỀỀỂẾưăạảấầẩẫậắằẳẵặẹẻẽềềểếỄỆỈỊỌỎỐỒỔỖỘỚỜỞỠỢỤỦỨỪễệỉịọỏốồổỗộớờởỡợụủứừỬỮỰỲỴÝỶỸửữựỳỵýỷỹ\\.+,:%&=;s.\\/\\-_'\\()]+$",
2737
- unitName: '^[a-zA-Z0-9 ÀÁÂÃÈÉÊÌÍÒÓÔÕÙÚĂĐĨŨƠàáâãèéêìíòóôõùúăđĩũơƯĂẠẢẤẦẨẪẬẮẰẲẴẶẸẺẼỀỀỂẾưăạảấầẩẫậắằẳẵặẹẻẽềềểếỄỆỈỊỌỎỐỒỔỖỘỚỜỞỠỢỤỦỨỪễệỉịọỏốồổỗộớờởỡợụủứừỬỮỰỲỴÝỶỸửữựỳỵỷỹs_-]+$',
2738
- date: '([12]\\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[12]\\d|3[01]))',
2739
- time: '(?=[01]\\d|2[0123])=(?=[012345]\\d)=(?=[012345]\\d)',
2740
- dateTime: '[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1]) (2[0-3]|[01][0-9])=[0-5][0-9]=[0-5][0-9]',
2741
- // dateV: "^(0?[1-9]|[12][0-9]|3[01])[\\/](0?[1-9]|1[012])[\\/]\\d{4}$",
2742
- // dateV: /^(0?[1-9]|[12][0-9]|3[01])[\/\-](0?[1-9]|1[012])[\/\-](19|20)\d\d/,
2743
- // dateV: "^([0-2][0-9]|(3)[0-1])(\-)(((0)[0-9])|((1)[0-2]))(\-)\d{4}$",
2744
- dateVN: '^(?=0[1-9]|[12]d|3[01])([/.-])(?=0[1-9]|1[012])\\1(?=19|20)dd$',
2745
- dateTimeVN: '^(0?[1-9]|[12][0-9]|3[01])[\\/](0?[1-9]|1[012])[\\/]\\d{4} (\\d{2})=(\\d{2})=(\\d{2})$',
2746
- dateShortTimeVN: '^(0?[1-9]|[12][0-9]|3[01])[\\/](0?[1-9]|1[012])[\\/]\\d{4} (\\d{2})=(\\d{2})$',
2747
- integer: '^\\-?[0-9]+$',
2748
- decimal: '^\\-?[0-9]*\\.?[0-9]+$',
2749
- ipAddress: '^((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[0-9]{1,2})\\.){3}(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[0-9]{1,2})$',
2750
- base64: '[^a-zA-Z0-9\\/\\+=]',
2751
- citizenId: '^\\d{12}$',
2752
- passport: '^[A-Z0-9]{6,12}$', // Hộ chiếu - 6-12 ký tự (chữ IN HOA và số)
2753
- // dnkhcn: "/^DNKHCN-[A-Z]{2}-d{4}$/",
2754
- // msdn: "/^d{10}$/",
2755
- intergerNotZero: '^[0-9]*[1-9][0-9]*$',
2756
- //link: "(https?=//(?=www.|(?!www))[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9].[^s]{2,}|www.[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9].[^s]{2,}|https?=//(?=www.|(?!www))[a-zA-Z0-9]+.[^s]{2,}|www.[a-zA-Z0-9]+.[^s]{2,})",
2757
- // code: "^['A-Z''0-9''._\\-']*$",
2758
- code: "^['A-Z''0-9''./_\\-\\/\\Đ']*$",
2759
- codeHsda: "^['A-Z''0-9''./_\\-']*$",
2760
- link_location: '(https?://)?([\\da-z.-]+)\\.([a-z.]{2,6})([/\\w .-]*)?(\\?[\\w=&,.%-]*)?',
2761
- link: '(https?://)?([\\da-z.-]+)\\.([a-z.]{2,6})[/\\w .-]*/?',
2762
- //password: "/(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[$@$!%*?&]).{8,}/",
2763
- accountName: '^[a-zA-Z0-9_.]{2,20}$',
2764
- name_or_fullName: '^[a-zA-Z0-9_ÀÁÂÃÈÉÊÌÍÒÓÔÕÙÚĂĐĨŨƠàáâãèéêìíòóôõùúăđĩũơƯĂẠẢẤẦẨẪẬẮẰẲẴẶẸẺẼỀỀỂưăạảấầẩẫậắằẳẵặẹẻẽềềểỄỆỈỊỌỎỐỒỔỖỘỚỜỞỠỢỤỦỨỪễếệỉịọỏốồổỗộớờởỡợụủứừỬỮỰỲỴÝỶỸửữựỳỵỷỹ ]{1,20}$',
2765
- packageName: '^(?:[a-zA-Z]+(?:d*[a-zA-Z_]*)*)(?:.[a-zA-Z]+(?:d*[a-zA-Z_]*)*)+$',
2766
- email: '^[a-z0-9._%+-]+@[a-z0-9.-]+\\.[a-z]{2,4}$',
2767
- passwordRegex: '^(?!.*\\s)(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(?=.*[~`!@#$%^&*()--+={}\\[\\]|\\\\:;"\'<>,.?/_₹]).{8,}$',
2768
- // phoneNumber: "^(\\+84|0)([235789])([0-9]{8,9})\\b",
2769
- phoneNumber: '^(\\+84|0)([235789])([0-9]{8,9})$',
2770
- seqNum: '^(100|[0-9]{1,2})$',
2771
- link_basemap: '(https://www.|http://www.|https://|http://)?[a-zA-Z]{2,}(.[a-zA-Z]{2,})(.[a-zA-Z]{2,})?/[a-zA-Z0-9]{2,}|((https://www.|http://www.|https://|http://)?[a-zA-Z]{2,}(.[a-zA-Z]{2,})(.[a-zA-Z]{2,})?)|(https://www.|http://www.|https://|http://)?[a-zA-Z0-9]{2,}.[a-zA-Z0-9]{2,}.[a-zA-Z0-9]{2,}(.[a-zA-Z0-9]{2,})?',
2772
- alphaDashBreakLineVN: "^[0-9a-zA-Z_ ÀÁÂÃÈÉÊÌÍÒÓÔÕÙÚĂĐĨŨƠàáâãèéêìíòóôõùúăđĩũơƯĂẠẢẤẦẨẪẬẮẰẲẴẶẸẺẼỀỀỂẾưăạảấầẩẫậắằẳẵặẹẻẽềềểếỄỆỈỊỌỎỐỒỔỖỘỚỜỞỠỢỤỦỨỪễệỉịọỏốồổỗộớờởỡợụủứừỬỮỰỲỴÝỶỸửữựỳỵýỷỹ\\.+,:%&=;s.\\/\\-_'\\(\\)\n]+$",
2773
- fax: '^(\\+?\\d{1,4}[\\s-]?)?(\\(?\\d{2,4}\\)?[\\s-]?)?[\\d\\s-]{5,15}$',
2774
- alphaDashNameVN: "^[a-zA-Z_ ÀÁÂÃÈÉÊÌÍÒÓÔÕÙÚĂĐĨŨƠàáâãèéêìíòóôõùúăđĩũơƯĂẠẢẤẦẨẪẬẮẰẲẴẶẸẺẼỀỀỂẾưăạảấầẩẫậắằẳẵặẹẻẽềềểếỄỆỈỊỌỎỐỒỔỖỘỚỜỞỠỢỤỦỨỪễệỉịọỏốồổỗộớờởỡợụủứừỬỮỰỲỴÝỶỸửữựỳỵýỷỹ\.s.\/\-\_'\\(\\)]{2,}$",
2775
- businessCode: '^\\d{10}(-\\d{3})?$',
2776
- };
2777
- // Các error message cho các pattern regex.
2778
- const PATTERN_ERROR_MESSAGES = {
2779
- required: '%s không được để trống!',
2780
- number: '%s phải là số!',
2781
- email: '%s không đúng định dạng địa chỉ Email!',
2782
- minlength: '%s có kích thước tối thiểu %s ký tự!',
2783
- maxlength: '%s có kích thước tối đa %s ký tự!',
2784
- min: '%s phải lớn hơn hoặc bằng %s!',
2785
- max: '%s phải nhỏ hơn hoặc bằng %s!',
2786
- alpha: '%s chỉ chứa ký tự thường và ký tự in hoa không dấu!',
2787
- alphaNumeric: '%s chỉ chứa ký tự thường, ký tự in hoa không dấu và số!',
2788
- name: '%s chỉ chứa ký tự thường, ký tự in hoa có dấu, số, dấu chấm, dấu phẩy, gạch dưới _ hoặc gạch ngang -, dấu ngoặc ()!',
2789
- username: '%s chỉ chứa ký tự thường, số, dấu chấm và dấu gạch dưới _',
2790
- regexPostCode: '%s chỉ chứa ký tự thường, ký tự in hoa không dấu, số, gạch ngang -',
2791
- alphaDash: '%s chỉ chứa ký tự thường, ký tự in hoa không dấu, số, gạch dưới _ hoặc gạch ngang -, dấu ngoặc ()!',
2792
- alphaVN: '%s chỉ chứa ký tự thường và ký tự in hoa có dấu!',
2793
- alphaNumericVN: '%s chỉ chứa ký tự thường, ký tự in hoa có dấu và số!',
2794
- alphaDashVN: '%s chỉ chứa ký tự thường, ký tự in hoa có dấu, số, dấu chấm, dấu phẩy, gạch dưới _ hoặc gạch ngang -, dấu ngoặc ()!',
2795
- alphaDashNameVN: '%s chỉ chứa ký tự thường, ký tự in hoa có dấu và ít nhất 2 ký tự!',
2796
- unitName: '%s chỉ chứa ký tự thường, ký tự in hoa có dấu, số, gạch dưới _ hoặc gạch ngang -',
2797
- date: '%s không đúng định dạng năm tháng ngày (YYYY-MM-DD)!',
2798
- time: '%s không đúng định dạng giờ phút giây (HH:MM:SS)!',
2799
- dateTime: '%s không đúng định dạng năm tháng ngày giờ phút giây (YYYY-MM-DD HH:MM:SS)!',
2800
- dateVN: '%s không đúng định dạng ngày tháng năm (DD/MM/YYYY)!',
2801
- dateTimeVN: '%s không đúng định dạng ngày tháng năm giờ phút giây (DD/MM/YYYY HH:MI:SS)!',
2802
- dateShortTimeVN: '%s không đúng định dạng ngày tháng năm giờ phút (DD/MM/YYYY HH:MI)!',
2803
- integer: '%s phải là số nguyên!',
2804
- decimal: '%s phải là số thập phân!',
2805
- ipAddress: '%s không đúng định dạng địa chỉ IP!',
2806
- base64: '%s không đúng định dạng Base64!',
2807
- intergerNotZero: '%s phải là số nguyên dương khác 0!',
2808
- link_location: '%s không đúng định dạng!',
2809
- link: '%s không đúng định dạng!',
2810
- codeHsda: "%s chỉ chứa các chữ cái in hoa không dấu, số và dấu '.', '_', '-'",
2811
- code: "%s chỉ chứa các chữ cái in hoa không dấu, số và dấu '.', '_', '-', '/'",
2812
- // code: "%s chỉ chứa các chữ cái in hoa,chữ cái thường không dấu, số và dấu '.', '_', '-'",
2813
- accountName: '%s chỉ bao gồm các kí tự từ A-Z, các số từ 0-9 và ít nhất 2 ký tự',
2814
- name_or_fullName: '',
2815
- // pwdErrorTip:
2816
- // "%s phải có ít nhất 8 ký tự. Ít nhất 1 ký tự hoa, số, ký tự thường và ký tự đặc biệt",
2817
- phoneNumber: 'Số điện thoại không hợp lệ (Gợi ý: Số điện thoại phải bắt đầu bằng đầu số 02, 03, 05, 07, 08, 09 hoặc +84 và có độ dài 10-11 ký tự)',
2818
- seqNum: '(Gợi ý: Thứ tự hiển thị phải là dạng số và có giá trị từ 1-100)',
2819
- link_basemap: '%s không đúng định dạng!',
2820
- passwordRegex: '%s phải có ít nhất 8 ký tự. Ít nhất 1 ký tự hoa, ký tự thường, số và ký tự đặc biệt',
2821
- alphaDashBreakLineVN: '%s chỉ chứa ký tự thường, ký tự in hoa có dấu, số, dấu chấm, dấu phẩy, gạch dưới _ hoặc gạch ngang -, dấu ngoặc ()!',
2822
- citizenId: '%s phải đúng định dạng 12 số!',
2823
- businessCode: '',
2871
+ const noSpecialCharValidator = () => {
2872
+ return (control) => {
2873
+ const valid = /^[a-zA-Z0-9]*$/.test(control.value);
2874
+ return valid ? null : { noSpecialChar: true };
2875
+ };
2824
2876
  };
2825
-
2826
- const resolvePattern = (pattern) => {
2827
- if (!pattern)
2828
- return { type: 'unknown', value: '' };
2829
- // Trường hợp là RegExp thực sự
2830
- if (pattern instanceof RegExp)
2831
- return { type: 'regexObject', value: pattern };
2832
- // Trường hợp là tên preset (ưu tiên nếu trùng)
2833
- if (pattern in PATTERN_PRESETS) {
2834
- return { type: 'regexKey', value: PATTERN_PRESETS[pattern] };
2835
- }
2836
- try {
2837
- // Trường hợp chuỗi regex dạng "^abc$"
2838
- return { type: 'regexString', value: new RegExp(pattern) };
2839
- }
2840
- catch (err) {
2841
- console.warn(`Không thể parse pattern "${pattern}"`, err);
2842
- return { type: 'unknown', value: '' };
2843
- }
2877
+ // Username không được nằm trong blacklist.
2878
+ const usernameBlacklistValidator = (blacklist) => {
2879
+ return (control) => {
2880
+ return blacklist.includes(control.value) ? { blacklisted: true } : null;
2881
+ };
2882
+ };
2883
+ // thuộc mimetypes từ mảng mimetypes được chỉ định hay không?
2884
+ const acceptedMimeTypesValidator = (acceptedMimeTypes) => {
2885
+ return (control) => {
2886
+ const value = control?.value;
2887
+ if (value) {
2888
+ let fileType = '';
2889
+ if (value instanceof File) {
2890
+ fileType = value.type;
2891
+ }
2892
+ if (isValidJSON(value)) {
2893
+ const { contentType } = JSON.parse(value)[0] || {};
2894
+ if (contentType)
2895
+ fileType = contentType;
2896
+ }
2897
+ if (fileType) {
2898
+ if (!acceptedMimeTypes.includes(fileType)) {
2899
+ return {
2900
+ acceptedMimeTypes: {
2901
+ actualValue: fileType,
2902
+ requiredValue: `Nằm trong ${acceptedMimeTypes}`,
2903
+ },
2904
+ };
2905
+ }
2906
+ }
2907
+ }
2908
+ return null;
2909
+ };
2910
+ };
2911
+ const maxFileSizeInMBValidator = (maxSizeInMB) => {
2912
+ return (control) => {
2913
+ const file = control?.value;
2914
+ if (file) {
2915
+ const fileSizeInMB = formatFileSize(file.size, FileSizeTypeEnum.MB);
2916
+ if (fileSizeInMB > maxSizeInMB) {
2917
+ return {
2918
+ maxSizeInMB: {
2919
+ actualValue: fileSizeInMB,
2920
+ requiredValue: `Nhỏ hơn ${maxSizeInMB}`,
2921
+ },
2922
+ };
2923
+ }
2924
+ }
2925
+ return null;
2926
+ };
2927
+ };
2928
+ const reminderCustomRequiredValidator = () => {
2929
+ return (control) => {
2930
+ const reminderValue = control?.value;
2931
+ if (!reminderValue) {
2932
+ return {
2933
+ reminderCustomRequired: {
2934
+ requiredValue: `Giá trị radio và cả từ select hoặc date`,
2935
+ },
2936
+ };
2937
+ }
2938
+ if (reminderValue) {
2939
+ const { reminderDate } = reminderValue;
2940
+ if (!reminderDate) {
2941
+ return {
2942
+ reminderCustomRequired: {
2943
+ actualValue: reminderDate,
2944
+ requiredValue: `Giá trị từ select hoặc date`,
2945
+ },
2946
+ };
2947
+ }
2948
+ }
2949
+ return null;
2950
+ };
2844
2951
  };
2845
2952
 
2846
2953
  const getDefaultPatternErrorMessage = (label, pattern) => {
@@ -2874,6 +2981,14 @@ const getLeadingSpaceErrorMessage = (label) => {
2874
2981
  return `${label || 'Trường này'} không được bắt đầu bằng khoảng trắng`;
2875
2982
  };
2876
2983
 
2984
+ var FormModeEnum;
2985
+ (function (FormModeEnum) {
2986
+ FormModeEnum["Add"] = "add";
2987
+ FormModeEnum["Edit"] = "edit";
2988
+ FormModeEnum["View"] = "view";
2989
+ FormModeEnum["Design"] = "design";
2990
+ })(FormModeEnum || (FormModeEnum = {}));
2991
+
2877
2992
  /**
2878
2993
  * Abstract class chung cho Field.
2879
2994
  */
@@ -2928,119 +3043,23 @@ class BaseField {
2928
3043
  }
2929
3044
  }
2930
3045
 
2931
- const DEFAULT_INPUT_VALUE = '';
2932
- /**
2933
- * Interface base chung cho Các dạng Input Field.
2934
- */
2935
- class InputBaseField extends BaseField {
2936
- constructor(init) {
2937
- super(init);
2938
- /**
2939
- * Gán giá trị cho các props cần giá trị mặc định ở Input.
2940
- */
2941
- this.controlType = ControlTypeEnum.Input;
2942
- this.value = DEFAULT_INPUT_VALUE;
2943
- this.initialValue = DEFAULT_INPUT_VALUE;
2944
- this.suffixes = [];
2945
- this.isCurrency = false;
2946
- Object.assign(this, init);
2947
- }
2948
- // Mảng ValidatorFn các validation chung được hỗ trợ sẵn bởi Reactive form của angular cho Input.
2949
- getInputCommonValidators() {
2950
- const validators = this.getCommonValidators();
2951
- if (this.minLength)
2952
- validators.push(Validators.minLength(this.minLength));
2953
- if (this.maxLength)
2954
- validators.push(Validators.maxLength(this.maxLength));
2955
- if (this.pattern) {
2956
- const resolvePatternResult = resolvePattern(this.pattern);
2957
- if (resolvePatternResult?.type !== 'unknown')
2958
- validators.push(Validators.pattern(resolvePatternResult.value));
2959
- }
2960
- return validators;
2961
- }
2962
- // Mảng ValidatorFn các custom validation có thể dùng cho Input.
2963
- getInputCustomValidators() {
2964
- const validators = this.getCustomValidators();
2965
- validators.push(noLeadingSpaceValidator());
2966
- return validators;
2967
- }
2968
- // Tạo Form Control cho Input Field.
2969
- toFormControl() {
2970
- const commonValidators = this.getInputCommonValidators();
2971
- const customValidators = this.getInputCustomValidators();
2972
- return new FormControl(this.value ?? '', [...commonValidators, ...customValidators]);
2973
- }
2974
- // Giá trị mặc định.
2975
- getDefaultValue() {
2976
- return DEFAULT_INPUT_VALUE;
2977
- }
2978
- toFormValue(modelValue) {
2979
- return String(modelValue);
2980
- }
2981
- getErrorMessage(errorKey, errorValue, allFields) {
2982
- if (errorKey === CommonValidaterEnum.Pattern) {
2983
- if (this.pattern)
2984
- return getDefaultPatternErrorMessage(this.label, this.pattern);
2985
- }
2986
- if (errorKey === CommonValidaterEnum.MinLength)
2987
- return getDefaultMinLengthErrorMessage(this.label, errorValue);
2988
- if (errorKey === CommonValidaterEnum.MaxLength)
2989
- return getDefaultMaxLengthErrorMessage(this.label, errorValue);
2990
- if (errorKey === CustomValidaterEnum.LeadingSpace)
2991
- return getLeadingSpaceErrorMessage(this.label);
2992
- return super.getErrorMessage(errorKey, errorValue, allFields);
2993
- }
2994
- }
2995
-
2996
- /**
2997
- * Interface của Input Field type là Text.
2998
- */
2999
- class InputTextField extends InputBaseField {
3046
+ // Dữ liệu sau khi đã tiến hành xử lý gom nhóm từ fields và groups.
3047
+ class GroupedFields {
3000
3048
  constructor(init) {
3001
- super(init);
3002
- /**
3003
- * Gán giá trị cho các props cần giá trị mặc định ở Input Text.
3004
- */
3005
- this.type = FieldTypeEnum.InputText;
3049
+ this.noGroup = [];
3050
+ this.grouped = [];
3006
3051
  Object.assign(this, init);
3007
3052
  }
3008
- // Tạo Form Control cho Input Text Field.
3009
- toFormControl() {
3010
- const commonValidators = this.getInputCommonValidators();
3011
- const customValidators = this.getInputCustomValidators();
3012
- return new FormControl(this.value ?? '', [...commonValidators, ...customValidators]);
3013
- }
3014
3053
  }
3015
-
3016
- /**
3017
- * Interface của Input Field type là Password.
3018
- */
3019
- class InputPasswordField extends InputBaseField {
3054
+ // Đại diện cho 1 group.
3055
+ class FieldGroup {
3020
3056
  constructor(init) {
3021
- super(init);
3022
- /**
3023
- * Gán giá trị cho các props cần giá trị mặc định ở Input Password.
3024
- */
3025
- this.type = FieldTypeEnum.InputPassword;
3057
+ this.isActive = false;
3058
+ this.showArrow = true;
3059
+ this.disabled = false;
3060
+ this.required = false;
3026
3061
  Object.assign(this, init);
3027
3062
  }
3028
- // Mảng ValidatorFn các validation chung được hỗ trợ sẵn bởi Reactive form của angular cho Input Password.
3029
- getInputPasswordCommonValidators() {
3030
- const validators = this.getInputCommonValidators();
3031
- return validators;
3032
- }
3033
- // Mảng ValidatorFn các validation chung được hỗ trợ sẵn bởi angular cho Input Password.
3034
- getInputPasswordCustomValidators() {
3035
- const validators = this.getInputCustomValidators();
3036
- return validators;
3037
- }
3038
- // Tạo Form Control cho Input Password Field.
3039
- toFormControl() {
3040
- const commonValidators = this.getInputPasswordCommonValidators();
3041
- const customValidators = this.getInputPasswordCustomValidators();
3042
- return new FormControl(this.value ?? '', [...commonValidators, ...customValidators]);
3043
- }
3044
3063
  }
3045
3064
 
3046
3065
  const buildForm = (fields, mode, model) => {
@@ -3100,25 +3119,6 @@ const createSelectPlaceholder = (field) => {
3100
3119
  return `Nhập ${field.key?.toLowerCase()}`;
3101
3120
  };
3102
3121
 
3103
- // Dữ liệu sau khi đã tiến hành xử lý gom nhóm từ fields và groups.
3104
- class GroupedFields {
3105
- constructor(init) {
3106
- this.noGroup = [];
3107
- this.grouped = [];
3108
- Object.assign(this, init);
3109
- }
3110
- }
3111
- // Đại diện cho 1 group.
3112
- class FieldGroup {
3113
- constructor(init) {
3114
- this.isActive = false;
3115
- this.showArrow = true;
3116
- this.disabled = false;
3117
- this.required = false;
3118
- Object.assign(this, init);
3119
- }
3120
- }
3121
-
3122
3122
  const isInputTextField = (field) => {
3123
3123
  return field.controlType === ControlTypeEnum.Input && field.type === FieldTypeEnum.InputText;
3124
3124
  };
@@ -3300,7 +3300,7 @@ class TreeSelectField extends SelectBaseField {
3300
3300
  }
3301
3301
  }
3302
3302
 
3303
- let DynamicFormService$1 = class DynamicFormService {
3303
+ class DynamicFormService {
3304
3304
  constructor() {
3305
3305
  this.formConfigService = inject(FormConfigService);
3306
3306
  /**
@@ -3458,8 +3458,8 @@ let DynamicFormService$1 = class DynamicFormService {
3458
3458
  }
3459
3459
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: DynamicFormService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
3460
3460
  static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: DynamicFormService, providedIn: 'root' }); }
3461
- };
3462
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: DynamicFormService$1, decorators: [{
3461
+ }
3462
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: DynamicFormService, decorators: [{
3463
3463
  type: Injectable,
3464
3464
  args: [{
3465
3465
  providedIn: 'root',
@@ -3667,7 +3667,7 @@ class BaseValueAccessor {
3667
3667
  this.onChange = () => { };
3668
3668
  this.onTouched = () => { };
3669
3669
  this.isDisabled = false;
3670
- this.dFormService = inject(DynamicFormService$1);
3670
+ this.dFormService = inject(DynamicFormService);
3671
3671
  this.formDataService = inject(FormDataService);
3672
3672
  this.fieldService = inject(FieldService);
3673
3673
  }
@@ -6384,13 +6384,13 @@ class DynamicFormComponent {
6384
6384
  trackByField(index, field) {
6385
6385
  return field.key || `field-${index}`;
6386
6386
  }
6387
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: DynamicFormComponent, deps: [{ token: DynamicFormService$1 }], target: i0.ɵɵFactoryTarget.Component }); }
6387
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: DynamicFormComponent, deps: [{ token: DynamicFormService }], target: i0.ɵɵFactoryTarget.Component }); }
6388
6388
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.15", type: DynamicFormComponent, isStandalone: true, selector: "app-dynamic-forms", inputs: { formId: { classPropertyName: "formId", publicName: "formId", isSignal: false, isRequired: false, transformFunction: null }, valueChangesDebounceTime: { classPropertyName: "valueChangesDebounceTime", publicName: "valueChangesDebounceTime", isSignal: false, isRequired: false, transformFunction: null }, fields: { classPropertyName: "fields", publicName: "fields", isSignal: true, isRequired: true, transformFunction: null }, model: { classPropertyName: "model", publicName: "model", isSignal: true, isRequired: false, transformFunction: null }, mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: false, transformFunction: null }, fieldGroups: { classPropertyName: "fieldGroups", publicName: "fieldGroups", isSignal: true, isRequired: false, transformFunction: null }, displayNonGroupedFields: { classPropertyName: "displayNonGroupedFields", publicName: "displayNonGroupedFields", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { formValueChanges: "formValueChanges", formSubmit: "formSubmit", formInvalid: "formInvalid" }, ngImport: i0, template: "@if (formGroup) {\r\n <form [formGroup]=\"formGroup\">\r\n @if (oldFields().length > 0) {\r\n <!-- 1. N\u1EBFu kh\u00F4ng c\u00F3 groups th\u00EC render t\u1EEB fields -->\r\n @if (!fieldGroups() || fieldGroups().length === 0) {\r\n <div nz-row [nzGutter]=\"[12, 0]\">\r\n @for (field of oldFields(); track field?.id) {\r\n @if (!isHiddenField(field)) {\r\n <div\r\n nz-col\r\n [nzXXl]=\"field?.grid?.xxl ?? null\"\r\n [nzXl]=\"field?.grid?.xl ?? null\"\r\n [nzLg]=\"field?.grid?.lg ?? null\"\r\n [nzMd]=\"field?.grid?.md ?? null\"\r\n [nzSm]=\"field?.grid?.sm ?? null\"\r\n [nzXs]=\"field?.grid?.xs ?? null\"\r\n [nzFlex]=\"\r\n !field?.grid?.xs &&\r\n !field?.grid?.sm &&\r\n !field?.grid?.md &&\r\n !field?.grid?.lg &&\r\n !field?.grid?.xl &&\r\n !field?.grid?.xxl\r\n ? '1 0 0'\r\n : null\r\n \"\r\n class=\"field\"\r\n >\r\n <app-dynamic-field\r\n [field]=\"field\"\r\n [fields]=\"oldFields()\"\r\n [mode]=\"mode()\"\r\n [control]=\"formGroup.get(field.key)!\"\r\n [formGroup]=\"formGroup\"\r\n [formId]=\"formId\"\r\n />\r\n </div>\r\n }\r\n }\r\n </div>\r\n }\r\n\r\n <!-- 2. N\u1EBFu c\u00F3 groups th\u00EC render t\u1EEB groupedFields -->\r\n @if (fieldGroups() && fieldGroups().length > 0) {\r\n <!-- C\u00E1c field noGroup -->\r\n @if (groupedFields().noGroup.length > 0 && displayNonGroupedFields()) {\r\n <div nz-row [nzGutter]=\"24\">\r\n @for (field of groupedFields().noGroup; track field?.id) {\r\n @if (!isHiddenField(field)) {\r\n <div\r\n nz-col\r\n [nzXXl]=\"field?.grid?.xxl ?? null\"\r\n [nzXl]=\"field?.grid?.xl ?? null\"\r\n [nzLg]=\"field?.grid?.lg ?? null\"\r\n [nzMd]=\"field?.grid?.md ?? null\"\r\n [nzSm]=\"field?.grid?.sm ?? null\"\r\n [nzXs]=\"field?.grid?.xs ?? null\"\r\n class=\"field\"\r\n >\r\n <app-dynamic-field\r\n [field]=\"field\"\r\n [fields]=\"oldFields()\"\r\n [mode]=\"mode()\"\r\n [control]=\"formGroup.get(field.key)!\"\r\n [formGroup]=\"formGroup\"\r\n [formId]=\"formId\"\r\n />\r\n </div>\r\n }\r\n }\r\n </div>\r\n }\r\n\r\n <!-- Group c\u00E1c field -->\r\n @if (groupedFields().grouped.length > 0) {\r\n <nz-collapse [nzBordered]=\"false\">\r\n @for (groupField of groupedFields().grouped; track groupField.group.code) {\r\n <nz-collapse-panel\r\n [nzHeader]=\"groupField.group.template ?? groupField.group.label\"\r\n [nzActive]=\"groupField.group.isActive\"\r\n [nzShowArrow]=\"groupField.group.showArrow\"\r\n [nzDisabled]=\"groupField.group.disabled\"\r\n [style]=\"collapseCustomStyle\"\r\n class=\"mt-sm\"\r\n >\r\n <div nz-row [nzGutter]=\"24\">\r\n @for (field of groupField.fields; track field?.id) {\r\n @if (!isHiddenField(field)) {\r\n <div\r\n nz-col\r\n [nzXXl]=\"field?.grid?.xxl ?? null\"\r\n [nzXl]=\"field?.grid?.xl ?? null\"\r\n [nzLg]=\"field?.grid?.lg ?? null\"\r\n [nzMd]=\"field?.grid?.md ?? null\"\r\n [nzSm]=\"field?.grid?.sm ?? null\"\r\n [nzXs]=\"field?.grid?.xs ?? null\"\r\n class=\"field\"\r\n >\r\n <app-dynamic-field\r\n [field]=\"field\"\r\n [fields]=\"oldFields()\"\r\n [mode]=\"mode()\"\r\n [control]=\"formGroup.get(field.key)!\"\r\n [formGroup]=\"formGroup\"\r\n [formId]=\"formId\"\r\n />\r\n </div>\r\n }\r\n }\r\n </div>\r\n </nz-collapse-panel>\r\n }\r\n </nz-collapse>\r\n }\r\n }\r\n }\r\n </form>\r\n}\r\n", styles: [":host ::ng-deep .ant-collapse .ant-collapse-item-disabled>.ant-collapse-header,:host ::ng-deep .ant-collapse .ant-collapse-item-disabled>.ant-collapse-header>.arrow{color:#575757;cursor:not-allowed}\n"], dependencies: [{ kind: "ngmodule", type: i1.FormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "ngmodule", type: i1.ReactiveFormsModule }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: NzFormModule }, { kind: "directive", type: i2$3.NzColDirective, selector: "[nz-col],nz-col,nz-form-control,nz-form-label", inputs: ["nzFlex", "nzSpan", "nzOrder", "nzOffset", "nzPush", "nzPull", "nzXs", "nzSm", "nzMd", "nzLg", "nzXl", "nzXXl"], exportAs: ["nzCol"] }, { kind: "directive", type: i2$3.NzRowDirective, selector: "[nz-row],nz-row,nz-form-item", inputs: ["nzAlign", "nzJustify", "nzGutter"], exportAs: ["nzRow"] }, { kind: "ngmodule", type: NzGridModule }, { kind: "ngmodule", type: NzCollapseModule }, { kind: "component", type: i4$2.NzCollapsePanelComponent, selector: "nz-collapse-panel", inputs: ["nzActive", "nzDisabled", "nzShowArrow", "nzExtra", "nzHeader", "nzExpandedIcon"], outputs: ["nzActiveChange"], exportAs: ["nzCollapsePanel"] }, { kind: "component", type: i4$2.NzCollapseComponent, selector: "nz-collapse", inputs: ["nzAccordion", "nzBordered", "nzGhost", "nzExpandIconPosition"], exportAs: ["nzCollapse"] }, { kind: "component", type: DynamicFieldComponent, selector: "app-dynamic-field", inputs: ["field", "fields", "mode", "control", "formGroup", "formId"] }] }); }
6389
6389
  }
6390
6390
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: DynamicFormComponent, decorators: [{
6391
6391
  type: Component,
6392
6392
  args: [{ selector: 'app-dynamic-forms', standalone: true, imports: [...FORM_MODULES, ...ZORRO_MODULES, ...COMPONENTS], template: "@if (formGroup) {\r\n <form [formGroup]=\"formGroup\">\r\n @if (oldFields().length > 0) {\r\n <!-- 1. N\u1EBFu kh\u00F4ng c\u00F3 groups th\u00EC render t\u1EEB fields -->\r\n @if (!fieldGroups() || fieldGroups().length === 0) {\r\n <div nz-row [nzGutter]=\"[12, 0]\">\r\n @for (field of oldFields(); track field?.id) {\r\n @if (!isHiddenField(field)) {\r\n <div\r\n nz-col\r\n [nzXXl]=\"field?.grid?.xxl ?? null\"\r\n [nzXl]=\"field?.grid?.xl ?? null\"\r\n [nzLg]=\"field?.grid?.lg ?? null\"\r\n [nzMd]=\"field?.grid?.md ?? null\"\r\n [nzSm]=\"field?.grid?.sm ?? null\"\r\n [nzXs]=\"field?.grid?.xs ?? null\"\r\n [nzFlex]=\"\r\n !field?.grid?.xs &&\r\n !field?.grid?.sm &&\r\n !field?.grid?.md &&\r\n !field?.grid?.lg &&\r\n !field?.grid?.xl &&\r\n !field?.grid?.xxl\r\n ? '1 0 0'\r\n : null\r\n \"\r\n class=\"field\"\r\n >\r\n <app-dynamic-field\r\n [field]=\"field\"\r\n [fields]=\"oldFields()\"\r\n [mode]=\"mode()\"\r\n [control]=\"formGroup.get(field.key)!\"\r\n [formGroup]=\"formGroup\"\r\n [formId]=\"formId\"\r\n />\r\n </div>\r\n }\r\n }\r\n </div>\r\n }\r\n\r\n <!-- 2. N\u1EBFu c\u00F3 groups th\u00EC render t\u1EEB groupedFields -->\r\n @if (fieldGroups() && fieldGroups().length > 0) {\r\n <!-- C\u00E1c field noGroup -->\r\n @if (groupedFields().noGroup.length > 0 && displayNonGroupedFields()) {\r\n <div nz-row [nzGutter]=\"24\">\r\n @for (field of groupedFields().noGroup; track field?.id) {\r\n @if (!isHiddenField(field)) {\r\n <div\r\n nz-col\r\n [nzXXl]=\"field?.grid?.xxl ?? null\"\r\n [nzXl]=\"field?.grid?.xl ?? null\"\r\n [nzLg]=\"field?.grid?.lg ?? null\"\r\n [nzMd]=\"field?.grid?.md ?? null\"\r\n [nzSm]=\"field?.grid?.sm ?? null\"\r\n [nzXs]=\"field?.grid?.xs ?? null\"\r\n class=\"field\"\r\n >\r\n <app-dynamic-field\r\n [field]=\"field\"\r\n [fields]=\"oldFields()\"\r\n [mode]=\"mode()\"\r\n [control]=\"formGroup.get(field.key)!\"\r\n [formGroup]=\"formGroup\"\r\n [formId]=\"formId\"\r\n />\r\n </div>\r\n }\r\n }\r\n </div>\r\n }\r\n\r\n <!-- Group c\u00E1c field -->\r\n @if (groupedFields().grouped.length > 0) {\r\n <nz-collapse [nzBordered]=\"false\">\r\n @for (groupField of groupedFields().grouped; track groupField.group.code) {\r\n <nz-collapse-panel\r\n [nzHeader]=\"groupField.group.template ?? groupField.group.label\"\r\n [nzActive]=\"groupField.group.isActive\"\r\n [nzShowArrow]=\"groupField.group.showArrow\"\r\n [nzDisabled]=\"groupField.group.disabled\"\r\n [style]=\"collapseCustomStyle\"\r\n class=\"mt-sm\"\r\n >\r\n <div nz-row [nzGutter]=\"24\">\r\n @for (field of groupField.fields; track field?.id) {\r\n @if (!isHiddenField(field)) {\r\n <div\r\n nz-col\r\n [nzXXl]=\"field?.grid?.xxl ?? null\"\r\n [nzXl]=\"field?.grid?.xl ?? null\"\r\n [nzLg]=\"field?.grid?.lg ?? null\"\r\n [nzMd]=\"field?.grid?.md ?? null\"\r\n [nzSm]=\"field?.grid?.sm ?? null\"\r\n [nzXs]=\"field?.grid?.xs ?? null\"\r\n class=\"field\"\r\n >\r\n <app-dynamic-field\r\n [field]=\"field\"\r\n [fields]=\"oldFields()\"\r\n [mode]=\"mode()\"\r\n [control]=\"formGroup.get(field.key)!\"\r\n [formGroup]=\"formGroup\"\r\n [formId]=\"formId\"\r\n />\r\n </div>\r\n }\r\n }\r\n </div>\r\n </nz-collapse-panel>\r\n }\r\n </nz-collapse>\r\n }\r\n }\r\n }\r\n </form>\r\n}\r\n", styles: [":host ::ng-deep .ant-collapse .ant-collapse-item-disabled>.ant-collapse-header,:host ::ng-deep .ant-collapse .ant-collapse-item-disabled>.ant-collapse-header>.arrow{color:#575757;cursor:not-allowed}\n"] }]
6393
- }], ctorParameters: () => [{ type: DynamicFormService$1 }], propDecorators: { formId: [{
6393
+ }], ctorParameters: () => [{ type: DynamicFormService }], propDecorators: { formId: [{
6394
6394
  type: Input
6395
6395
  }], valueChangesDebounceTime: [{
6396
6396
  type: Input
@@ -6398,18 +6398,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImpo
6398
6398
  type: Output
6399
6399
  }] } });
6400
6400
 
6401
- class DynamicFormService {
6402
- constructor() { }
6403
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: DynamicFormService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
6404
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: DynamicFormService, providedIn: 'root' }); }
6405
- }
6406
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: DynamicFormService, decorators: [{
6407
- type: Injectable,
6408
- args: [{
6409
- providedIn: 'root'
6410
- }]
6411
- }], ctorParameters: () => [] });
6412
-
6413
6401
  var TableCellTypeEnum;
6414
6402
  (function (TableCellTypeEnum) {
6415
6403
  TableCellTypeEnum["ACTION"] = "action";
@@ -6455,12 +6443,12 @@ class ReminderOption {
6455
6443
  * Public API Surface of dynamic-form
6456
6444
  */
6457
6445
  // ==========================================
6458
- // 1. MODULE & COMPONENT & SERVICE CHÍNH
6446
+ // 0. BASE FIELD MODELS (CẦN ĐƯỢC EXPORT TRƯỚC ĐỂ TRÁNH LỖI CIRCULAR DEPENDENCY CLASS EXTENDS UNDEFINED)
6459
6447
  // ==========================================
6460
6448
 
6461
6449
  /**
6462
6450
  * Generated bundle index. Do not edit.
6463
6451
  */
6464
6452
 
6465
- export { BaseDateField, BaseField, BaseUploadField, CombineDependTypeEnum, CommonValidaterEnum, ControlTypeEnum, CustomValidaterEnum, DYNAMIC_FORM_CONFIG, DateFieldTypeEnum, DateOptions, DatePickerField, DatePickerOutputValueTypeEnum, DateRangeField, DateRangeOutputValueTypeEnum, DependTypeEnum, DynamicFormComponent, DynamicFormService, FieldGroup, FieldTypeEnum, FileSizeTypeEnum, FormConfigService, FormModeEnum, GroupedFields, InputBaseField, InputFieldTypeEnum, InputPasswordField, InputTextField, MultiSelectField, RadioBaseField, ReminderOption, ReminderTypeRadioField, ReminderValue, SelectBaseField, SelectFieldTypeEnum, SelectOption, SelectOutputValueTypeEnum, SingleSelectField, TableCellTypeEnum, TextareaField, TreeSelectField, UploadFieldTypeEnum, UploadOutputValueTypeEnum, ViewModeEnum };
6453
+ export { BaseDateField, BaseField, BaseUploadField, CombineDependTypeEnum, CommonValidaterEnum, ControlTypeEnum, CustomValidaterEnum, DYNAMIC_FORM_CONFIG, DateFieldTypeEnum, DateOptions, DatePickerField, DatePickerOutputValueTypeEnum, DateRangeField, DateRangeOutputValueTypeEnum, DependTypeEnum, DynamicFormComponent, DynamicFormService, FieldGroup, FieldTypeEnum, FileSizeTypeEnum, FormConfigService, FormDataService, FormModeEnum, GroupedFields, InputBaseField, InputFieldTypeEnum, InputPasswordField, InputTextField, MultiSelectField, RadioBaseField, ReminderOption, ReminderTypeRadioField, ReminderValue, SelectBaseField, SelectFieldTypeEnum, SelectOption, SelectOutputValueTypeEnum, SingleSelectField, TableCellTypeEnum, TextareaField, TreeSelectField, UploadFieldTypeEnum, UploadOutputValueTypeEnum, ViewModeEnum };
6466
6454
  //# sourceMappingURL=ldquocc-dynamic-form.mjs.map