@kms-ngx-ui/presentational 20.4.0 → 20.4.2

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.
@@ -47,14 +47,15 @@ import * as i5 from 'ngx-mat-select-search';
47
47
  import { NgxMatSelectSearchModule } from 'ngx-mat-select-search';
48
48
  import { MatTooltipModule } from '@angular/material/tooltip';
49
49
  import * as i1$8 from '@ngx-translate/core';
50
- import { TranslateModule } from '@ngx-translate/core';
50
+ import { TranslateService, TranslateModule } from '@ngx-translate/core';
51
51
  import { autoUpdate, computePosition, shift, offset, arrow, flip } from '@floating-ui/dom';
52
52
  import { Subject, takeUntil as takeUntil$1, isObservable, merge } from 'rxjs';
53
+ import { toSignal } from '@angular/core/rxjs-interop';
54
+ import { startWith, takeUntil, filter } from 'rxjs/operators';
53
55
  import { trigger, state, style } from '@angular/animations';
54
56
  import { register } from 'swiper/element/bundle';
55
57
  import { isEmpty } from 'lodash';
56
58
  import moment from 'moment';
57
- import { takeUntil, filter } from 'rxjs/operators';
58
59
 
59
60
  class KmsUiPresentationalComponent {
60
61
  constructor() { }
@@ -715,6 +716,251 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
715
716
  }]
716
717
  }] });
717
718
 
719
+ /**
720
+ * Pre-translated strings the library injects into the consumer's
721
+ * @ngx-translate store under the `uiPresentational.*` namespace.
722
+ *
723
+ * Structure:
724
+ * <locale>.<feature>.<key> → string
725
+ *
726
+ * Add a new feature by introducing a sibling object next to
727
+ * `validatorMessages` / `dateInput` (same shape across all locales).
728
+ */
729
+ const KMS_LIB_MESSAGES = {
730
+ en: {
731
+ validatorMessages: {
732
+ required: 'This field is required.',
733
+ minlength: 'Minimum {{requiredLength}} characters required.',
734
+ maxlength: 'Maximum {{requiredLength}} characters allowed.',
735
+ min: 'Value must be at least {{min}}.',
736
+ max: 'Value must be at most {{max}}.',
737
+ email: 'Please enter a valid email address.',
738
+ pattern: 'The value does not match the required format.',
739
+ whitespaceOnly: 'Must not contain only whitespace.',
740
+ specialCharsOnly: 'Must contain at least one letter or number.',
741
+ },
742
+ dateInput: {
743
+ startDate: 'Start date',
744
+ endDate: 'End date',
745
+ },
746
+ },
747
+ 'en-uk': {
748
+ validatorMessages: {
749
+ required: 'This field is required.',
750
+ minlength: 'Minimum {{requiredLength}} characters required.',
751
+ maxlength: 'Maximum {{requiredLength}} characters allowed.',
752
+ min: 'Value must be at least {{min}}.',
753
+ max: 'Value must be at most {{max}}.',
754
+ email: 'Please enter a valid email address.',
755
+ pattern: 'The value does not match the required format.',
756
+ whitespaceOnly: 'Must not contain only whitespace.',
757
+ specialCharsOnly: 'Must contain at least one letter or number.',
758
+ },
759
+ dateInput: {
760
+ startDate: 'Start date',
761
+ endDate: 'End date',
762
+ },
763
+ },
764
+ de: {
765
+ validatorMessages: {
766
+ required: 'Dieses Feld ist erforderlich.',
767
+ minlength: 'Mindestens {{requiredLength}} Zeichen erforderlich.',
768
+ maxlength: 'Maximal {{requiredLength}} Zeichen erlaubt.',
769
+ min: 'Der Wert muss mindestens {{min}} betragen.',
770
+ max: 'Der Wert darf h\u00f6chstens {{max}} betragen.',
771
+ email: 'Bitte geben Sie eine g\u00fcltige E-Mail-Adresse ein.',
772
+ pattern: 'Der Wert entspricht nicht dem erforderlichen Format.',
773
+ whitespaceOnly: 'Darf nicht nur aus Leerzeichen bestehen.',
774
+ specialCharsOnly: 'Muss mindestens einen Buchstaben oder eine Zahl enthalten.',
775
+ },
776
+ dateInput: {
777
+ startDate: 'Startdatum',
778
+ endDate: 'Enddatum',
779
+ },
780
+ },
781
+ 'de-de': {
782
+ validatorMessages: {
783
+ required: 'Dieses Feld ist erforderlich.',
784
+ minlength: 'Mindestens {{requiredLength}} Zeichen erforderlich.',
785
+ maxlength: 'Maximal {{requiredLength}} Zeichen erlaubt.',
786
+ min: 'Der Wert muss mindestens {{min}} betragen.',
787
+ max: 'Der Wert darf h\u00f6chstens {{max}} betragen.',
788
+ email: 'Bitte geben Sie eine g\u00fcltige E-Mail-Adresse ein.',
789
+ pattern: 'Der Wert entspricht nicht dem erforderlichen Format.',
790
+ whitespaceOnly: 'Darf nicht nur aus Leerzeichen bestehen.',
791
+ specialCharsOnly: 'Muss mindestens einen Buchstaben oder eine Zahl enthalten.',
792
+ },
793
+ dateInput: {
794
+ startDate: 'Startdatum',
795
+ endDate: 'Enddatum',
796
+ },
797
+ },
798
+ 'de-ch': {
799
+ validatorMessages: {
800
+ required: 'Dieses Feld ist erforderlich.',
801
+ minlength: 'Mindestens {{requiredLength}} Zeichen erforderlich.',
802
+ maxlength: 'Maximal {{requiredLength}} Zeichen erlaubt.',
803
+ min: 'Der Wert muss mindestens {{min}} betragen.',
804
+ max: 'Der Wert darf h\u00f6chstens {{max}} betragen.',
805
+ email: 'Bitte geben Sie eine g\u00fcltige E-Mail-Adresse ein.',
806
+ pattern: 'Der Wert entspricht nicht dem erforderlichen Format.',
807
+ whitespaceOnly: 'Darf nicht nur aus Leerzeichen bestehen.',
808
+ specialCharsOnly: 'Muss mindestens einen Buchstaben oder eine Zahl enthalten.',
809
+ },
810
+ dateInput: {
811
+ startDate: 'Startdatum',
812
+ endDate: 'Enddatum',
813
+ },
814
+ },
815
+ 'cs-cz': {
816
+ validatorMessages: {
817
+ required: 'Toto pole je povinn\u00e9.',
818
+ minlength: 'Vy\u017eaduje se minim\u00e1ln\u011b {{requiredLength}} znak\u016f.',
819
+ maxlength: 'Maxim\u00e1ln\u011b {{requiredLength}} znak\u016f je povoleno.',
820
+ min: 'Hodnota mus\u00ed b\u00fdt alespo\u0148 {{min}}.',
821
+ max: 'Hodnota mus\u00ed b\u00fdt nejv\u00fd\u0161e {{max}}.',
822
+ email: 'Zadejte pros\u00edm platnou e-mailovou adresu.',
823
+ pattern: 'Hodnota neodpov\u00edd\u00e1 po\u017eadovan\u00e9mu form\u00e1tu.',
824
+ whitespaceOnly: 'Nesm\u00ed obsahovat pouze mezery.',
825
+ specialCharsOnly: 'Mus\u00ed obsahovat alespo\u0148 jedno p\u00edsmeno nebo \u010d\u00edslo.',
826
+ },
827
+ dateInput: {
828
+ startDate: 'Datum za\u010d\u00e1tku',
829
+ endDate: 'Datum konce',
830
+ },
831
+ },
832
+ 'es-es': {
833
+ validatorMessages: {
834
+ required: 'Este campo es obligatorio.',
835
+ minlength: 'Se requieren al menos {{requiredLength}} caracteres.',
836
+ maxlength: 'Se permiten como m\u00e1ximo {{requiredLength}} caracteres.',
837
+ min: 'El valor debe ser al menos {{min}}.',
838
+ max: 'El valor debe ser como m\u00e1ximo {{max}}.',
839
+ email: 'Introduzca una direcci\u00f3n de correo electr\u00f3nico v\u00e1lida.',
840
+ pattern: 'El valor no coincide con el formato requerido.',
841
+ whitespaceOnly: 'No debe contener solo espacios en blanco.',
842
+ specialCharsOnly: 'Debe contener al menos una letra o un n\u00famero.',
843
+ },
844
+ dateInput: {
845
+ startDate: 'Fecha de inicio',
846
+ endDate: 'Fecha de fin',
847
+ },
848
+ },
849
+ 'fr-fr': {
850
+ validatorMessages: {
851
+ required: 'Ce champ est obligatoire.',
852
+ minlength: 'Au moins {{requiredLength}} caract\u00e8res requis.',
853
+ maxlength: 'Maximum {{requiredLength}} caract\u00e8res autoris\u00e9s.',
854
+ min: "La valeur doit \u00eatre d'au moins {{min}}.",
855
+ max: 'La valeur doit \u00eatre au maximum {{max}}.',
856
+ email: 'Veuillez saisir une adresse e-mail valide.',
857
+ pattern: 'La valeur ne correspond pas au format requis.',
858
+ whitespaceOnly: 'Ne doit pas contenir uniquement des espaces.',
859
+ specialCharsOnly: 'Doit contenir au moins une lettre ou un chiffre.',
860
+ },
861
+ dateInput: {
862
+ startDate: 'Date de d\u00e9but',
863
+ endDate: 'Date de fin',
864
+ },
865
+ },
866
+ 'it-it': {
867
+ validatorMessages: {
868
+ required: 'Questo campo \u00e8 obbligatorio.',
869
+ minlength: 'Sono richiesti almeno {{requiredLength}} caratteri.',
870
+ maxlength: 'Sono consentiti al massimo {{requiredLength}} caratteri.',
871
+ min: 'Il valore deve essere almeno {{min}}.',
872
+ max: 'Il valore deve essere al massimo {{max}}.',
873
+ email: 'Inserisci un indirizzo e-mail valido.',
874
+ pattern: 'Il valore non corrisponde al formato richiesto.',
875
+ whitespaceOnly: 'Non deve contenere solo spazi.',
876
+ specialCharsOnly: 'Deve contenere almeno una lettera o un numero.',
877
+ },
878
+ dateInput: {
879
+ startDate: 'Data di inizio',
880
+ endDate: 'Data di fine',
881
+ },
882
+ },
883
+ 'nl-nl': {
884
+ validatorMessages: {
885
+ required: 'Dit veld is verplicht.',
886
+ minlength: 'Minimaal {{requiredLength}} tekens vereist.',
887
+ maxlength: 'Maximaal {{requiredLength}} tekens toegestaan.',
888
+ min: 'De waarde moet ten minste {{min}} zijn.',
889
+ max: 'De waarde mag maximaal {{max}} zijn.',
890
+ email: 'Voer een geldig e-mailadres in.',
891
+ pattern: 'De waarde komt niet overeen met het vereiste formaat.',
892
+ whitespaceOnly: 'Mag niet alleen spaties bevatten.',
893
+ specialCharsOnly: 'Moet ten minste \u00e9\u00e9n letter of cijfer bevatten.',
894
+ },
895
+ dateInput: {
896
+ startDate: 'Startdatum',
897
+ endDate: 'Einddatum',
898
+ },
899
+ },
900
+ 'pt-pt': {
901
+ validatorMessages: {
902
+ required: 'Este campo \u00e9 obrigat\u00f3rio.',
903
+ minlength: 'M\u00ednimo de {{requiredLength}} caracteres necess\u00e1rio.',
904
+ maxlength: 'M\u00e1ximo de {{requiredLength}} caracteres permitido.',
905
+ min: 'O valor deve ser pelo menos {{min}}.',
906
+ max: 'O valor deve ser no m\u00e1ximo {{max}}.',
907
+ email: 'Introduza um endere\u00e7o de e-mail v\u00e1lido.',
908
+ pattern: 'O valor n\u00e3o corresponde ao formato necess\u00e1rio.',
909
+ whitespaceOnly: 'N\u00e3o pode conter apenas espa\u00e7os em branco.',
910
+ specialCharsOnly: 'Deve conter pelo menos uma letra ou um n\u00famero.',
911
+ },
912
+ dateInput: {
913
+ startDate: 'Data de in\u00edcio',
914
+ endDate: 'Data de fim',
915
+ },
916
+ },
917
+ 'sk-sk': {
918
+ validatorMessages: {
919
+ required: 'Toto pole je povinn\u00e9.',
920
+ minlength: 'Vy\u017eaduje sa minim\u00e1lne {{requiredLength}} znakov.',
921
+ maxlength: 'Maxim\u00e1lne {{requiredLength}} znakov je povolen\u00fdch.',
922
+ min: 'Hodnota mus\u00ed by\u0165 aspo\u0148 {{min}}.',
923
+ max: 'Hodnota mus\u00ed by\u0165 najviac {{max}}.',
924
+ email: 'Zadajte platn\u00fa e-mailov\u00fa adresu.',
925
+ pattern: 'Hodnota nezodpoved\u00e1 po\u017eadovan\u00e9mu form\u00e1tu.',
926
+ whitespaceOnly: 'Nesmie obsahova\u0165 iba medzery.',
927
+ specialCharsOnly: 'Mus\u00ed obsahova\u0165 aspo\u0148 jedno p\u00edsmeno alebo \u010d\u00edslo.',
928
+ },
929
+ dateInput: {
930
+ startDate: 'D\u00e1tum za\u010diatku',
931
+ endDate: 'D\u00e1tum konca',
932
+ },
933
+ },
934
+ };
935
+ /**
936
+ * Resolve the message bundle for `lang` with locale fallback:
937
+ * exact (`de-de`) → primary (`de`) → English default.
938
+ */
939
+ function resolveKmsLibMessages(lang) {
940
+ const key = lang.toLowerCase();
941
+ return (KMS_LIB_MESSAGES[key] ??
942
+ KMS_LIB_MESSAGES[key.split('-')[0]] ??
943
+ KMS_LIB_MESSAGES['en']);
944
+ }
945
+ /**
946
+ * Merge the library's pre-translated strings into the consumer's
947
+ * @ngx-translate store for a given language.
948
+ *
949
+ * Implementation note: the consumer's HTTP loader calls
950
+ * `setTranslation()` *without* merge, which overwrites the store —
951
+ * this helper merges library strings back on top. Call from a
952
+ * `translate.onLangChange` subscription so the merge re-runs after
953
+ * each (re)load.
954
+ *
955
+ * We intentionally do NOT merge upfront for all languages, because
956
+ * that would make ngx-translate skip the HTTP loader (it thinks
957
+ * translations are already cached), breaking the app's own
958
+ * translations.
959
+ */
960
+ function mergeKmsLibMessages(translate, lang) {
961
+ translate.setTranslation(lang, { uiPresentational: resolveKmsLibMessages(lang) }, true);
962
+ }
963
+
718
964
  /**
719
965
  * @copyright KMS GmbH
720
966
  */
@@ -2163,6 +2409,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
2163
2409
  let nextId$1 = 0;
2164
2410
  class DateInputComponent {
2165
2411
  constructor() {
2412
+ this.translate = inject(TranslateService, { optional: true });
2166
2413
  this.Color = Color;
2167
2414
  this.IconSizePx = IconSizePx;
2168
2415
  this.dateChange = output();
@@ -2187,6 +2434,16 @@ class DateInputComponent {
2187
2434
  end: new FormControl(null),
2188
2435
  });
2189
2436
  this.computedStartView = computed(() => this.monthPicker() ? 'year' : this.startView(), ...(ngDevMode ? [{ debugName: "computedStartView" }] : []));
2437
+ /**
2438
+ * Tracks the active language so aria-label signals re-evaluate on
2439
+ * runtime language changes. `undefined` when TranslateService is not
2440
+ * provided (date-input used outside KmsUiPresentationalModule).
2441
+ */
2442
+ this.activeLang = this.translate
2443
+ ? toSignal(this.translate.onLangChange.pipe(startWith({ lang: this.translate.currentLang })), { initialValue: { lang: this.translate.currentLang } })
2444
+ : signal(undefined);
2445
+ this.startDateAriaLabel = computed(() => this.resolveLabel('startDate', 'Start date'), ...(ngDevMode ? [{ debugName: "startDateAriaLabel" }] : []));
2446
+ this.endDateAriaLabel = computed(() => this.resolveLabel('endDate', 'End date'), ...(ngDevMode ? [{ debugName: "endDateAriaLabel" }] : []));
2190
2447
  this.disabledEffect = effect(() => {
2191
2448
  const disabled = this.isDisabled();
2192
2449
  if (disabled) {
@@ -2207,6 +2464,17 @@ class DateInputComponent {
2207
2464
  this.onChange = () => { };
2208
2465
  this.onTouched = () => { };
2209
2466
  }
2467
+ resolveLabel(key, fallback) {
2468
+ // Read activeLang so this computed re-runs on language change
2469
+ // (translate.instant is not signal-aware on its own).
2470
+ this.activeLang();
2471
+ if (!this.translate) {
2472
+ return fallback;
2473
+ }
2474
+ const fullKey = `uiPresentational.dateInput.${key}`;
2475
+ const translated = this.translate.instant(fullKey);
2476
+ return translated && translated !== fullKey ? translated : fallback;
2477
+ }
2210
2478
  onDateChanged(date) {
2211
2479
  this.value.set(date);
2212
2480
  this.innerControl.setValue(date, { emitEvent: false });
@@ -2254,7 +2522,7 @@ class DateInputComponent {
2254
2522
  useExisting: forwardRef(() => DateInputComponent),
2255
2523
  multi: true,
2256
2524
  },
2257
- ], ngImport: i0, template: "@if (mode() === 'date') {\n<mat-form-field class=\"kms-date-input__form-field\">\n <mat-label>{{ label() }}</mat-label>\n <input\n [id]=\"inputId\"\n matInput\n [matDatepicker]=\"picker\"\n [formControl]=\"innerControl\"\n [placeholder]=\"placeholder()\"\n [required]=\"required()\"\n [min]=\"minDate()\"\n [max]=\"maxDate()\"\n [errorStateMatcher]=\"errorStateMatcher\"\n [attr.aria-required]=\"required()\"\n [attr.aria-invalid]=\"errorMessage() ? true : null\"\n [attr.aria-describedby]=\"\n (hint() ? hintId : '') + (errorMessage() ? ' ' + errorId : '') || null\n \"\n (dateChange)=\"onDateChanged($event.value)\"\n (blur)=\"onTouched()\"\n (click)=\"picker.open()\"\n (keyup)=\"\n ($event.key === 'Enter' || $event.key === 'Space') && picker.open()\n \"\n />\n <mat-datepicker\n #picker\n [startView]=\"computedStartView()\"\n (monthSelected)=\"onMonthSelected($event, picker)\"\n ></mat-datepicker>\n <mat-datepicker-toggle matIconSuffix [for]=\"picker\">\n <kms-icon\n class=\"kms-date-input__icon\"\n icon=\"calendar\"\n [color]=\"Color.SECONDARY\"\n [size]=\"IconSizePx.XS\"\n matDatepickerToggleIcon\n ></kms-icon>\n </mat-datepicker-toggle>\n @if (hint()) {\n <mat-hint [id]=\"hintId\">{{ hint() }}</mat-hint>\n }\n <mat-error [id]=\"errorId\" role=\"alert\">{{ errorMessage() }}</mat-error>\n</mat-form-field>\n} @if (mode() === 'range') {\n<mat-form-field class=\"kms-date-input__form-field\">\n <mat-label>{{ label() }}</mat-label>\n <mat-date-range-input\n [rangePicker]=\"rangePicker\"\n [min]=\"minDate()\"\n [max]=\"maxDate()\"\n (click)=\"rangePicker.open()\"\n (keyup)=\"\n ($event.key === 'Enter' || $event.key === 'Space') && rangePicker.open()\n \"\n >\n <input\n matStartDate\n [formControl]=\"rangeGroup.controls.start\"\n [placeholder]=\"placeholder() || 'Start date'\"\n [required]=\"required()\"\n [attr.aria-required]=\"required()\"\n [attr.aria-invalid]=\"errorMessage() ? true : null\"\n [attr.aria-describedby]=\"\n (hint() ? hintId : '') + (errorMessage() ? ' ' + errorId : '') || null\n \"\n (dateChange)=\"onRangeChanged()\"\n (blur)=\"onTouched()\"\n />\n <input\n matEndDate\n [formControl]=\"rangeGroup.controls.end\"\n placeholder=\"End date\"\n (dateChange)=\"onRangeChanged()\"\n (blur)=\"onTouched()\"\n />\n </mat-date-range-input>\n <mat-date-range-picker #rangePicker></mat-date-range-picker>\n <mat-datepicker-toggle matIconSuffix [for]=\"rangePicker\">\n <kms-icon\n class=\"kms-date-input__icon\"\n icon=\"calendar\"\n [color]=\"Color.SECONDARY\"\n [size]=\"IconSizePx.XS\"\n matDatepickerToggleIcon\n ></kms-icon>\n </mat-datepicker-toggle>\n @if (hint()) {\n <mat-hint [id]=\"hintId\">{{ hint() }}</mat-hint>\n }\n <mat-error [id]=\"errorId\" role=\"alert\">{{ errorMessage() }}</mat-error>\n</mat-form-field>\n}\n", styles: [""], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i2$1.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2$1.MatLabel, selector: "mat-label" }, { kind: "directive", type: i2$1.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "directive", type: i2$1.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "directive", type: i2$1.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i3$2.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatDatepickerModule }, { kind: "component", type: i4.MatDatepicker, selector: "mat-datepicker", exportAs: ["matDatepicker"] }, { kind: "directive", type: i4.MatDatepickerInput, selector: "input[matDatepicker]", inputs: ["matDatepicker", "min", "max", "matDatepickerFilter"], exportAs: ["matDatepickerInput"] }, { kind: "component", type: i4.MatDatepickerToggle, selector: "mat-datepicker-toggle", inputs: ["for", "tabIndex", "aria-label", "disabled", "disableRipple"], exportAs: ["matDatepickerToggle"] }, { kind: "directive", type: i4.MatDatepickerToggleIcon, selector: "[matDatepickerToggleIcon]" }, { kind: "component", type: i4.MatDateRangeInput, selector: "mat-date-range-input", inputs: ["rangePicker", "required", "dateFilter", "min", "max", "disabled", "separator", "comparisonStart", "comparisonEnd"], exportAs: ["matDateRangeInput"] }, { kind: "directive", type: i4.MatStartDate, selector: "input[matStartDate]", outputs: ["dateChange", "dateInput"] }, { kind: "directive", type: i4.MatEndDate, selector: "input[matEndDate]", outputs: ["dateChange", "dateInput"] }, { kind: "component", type: i4.MatDateRangePicker, selector: "mat-date-range-picker", exportAs: ["matDateRangePicker"] }, { kind: "component", type: IconComponent, selector: "kms-icon", inputs: ["icon", "iconClass", "size", "dontUseSprite", "color"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2525
+ ], ngImport: i0, template: "@if (mode() === 'date') {\n<mat-form-field class=\"kms-date-input__form-field\">\n <mat-label>{{ label() }}</mat-label>\n <input\n [id]=\"inputId\"\n matInput\n [matDatepicker]=\"picker\"\n [formControl]=\"innerControl\"\n [placeholder]=\"placeholder()\"\n [required]=\"required()\"\n [min]=\"minDate()\"\n [max]=\"maxDate()\"\n [errorStateMatcher]=\"errorStateMatcher\"\n [attr.aria-required]=\"required()\"\n [attr.aria-invalid]=\"errorMessage() ? true : null\"\n [attr.aria-describedby]=\"\n (hint() ? hintId : '') + (errorMessage() ? ' ' + errorId : '') || null\n \"\n (dateChange)=\"onDateChanged($event.value)\"\n (blur)=\"onTouched()\"\n (click)=\"picker.open()\"\n (keyup)=\"\n ($event.key === 'Enter' || $event.key === 'Space') && picker.open()\n \"\n />\n <mat-datepicker\n #picker\n [startView]=\"computedStartView()\"\n (monthSelected)=\"onMonthSelected($event, picker)\"\n ></mat-datepicker>\n <mat-datepicker-toggle matIconSuffix [for]=\"picker\">\n <kms-icon\n class=\"kms-date-input__icon\"\n icon=\"calendar\"\n [color]=\"Color.SECONDARY\"\n [size]=\"IconSizePx.XS\"\n matDatepickerToggleIcon\n ></kms-icon>\n </mat-datepicker-toggle>\n @if (hint()) {\n <mat-hint [id]=\"hintId\">{{ hint() }}</mat-hint>\n }\n <mat-error [id]=\"errorId\" role=\"alert\">{{ errorMessage() }}</mat-error>\n</mat-form-field>\n} @if (mode() === 'range') {\n<mat-form-field class=\"kms-date-input__form-field\">\n <mat-label>{{ label() }}</mat-label>\n <mat-date-range-input\n [rangePicker]=\"rangePicker\"\n [min]=\"minDate()\"\n [max]=\"maxDate()\"\n (click)=\"rangePicker.open()\"\n (keyup)=\"\n ($event.key === 'Enter' || $event.key === 'Space') && rangePicker.open()\n \"\n >\n <input\n matStartDate\n [formControl]=\"rangeGroup.controls.start\"\n [placeholder]=\"placeholder() || startDateAriaLabel()\"\n [attr.aria-label]=\"startDateAriaLabel()\"\n [required]=\"required()\"\n [attr.aria-required]=\"required()\"\n [attr.aria-invalid]=\"errorMessage() ? true : null\"\n [attr.aria-describedby]=\"\n (hint() ? hintId : '') + (errorMessage() ? ' ' + errorId : '') || null\n \"\n (dateChange)=\"onRangeChanged()\"\n (blur)=\"onTouched()\"\n />\n <input\n matEndDate\n [formControl]=\"rangeGroup.controls.end\"\n [placeholder]=\"endDateAriaLabel()\"\n [attr.aria-label]=\"endDateAriaLabel()\"\n [attr.aria-required]=\"required()\"\n [attr.aria-invalid]=\"errorMessage() ? true : null\"\n [attr.aria-describedby]=\"\n (hint() ? hintId : '') + (errorMessage() ? ' ' + errorId : '') || null\n \"\n (dateChange)=\"onRangeChanged()\"\n (blur)=\"onTouched()\"\n />\n </mat-date-range-input>\n <mat-date-range-picker #rangePicker></mat-date-range-picker>\n <mat-datepicker-toggle matIconSuffix [for]=\"rangePicker\">\n <kms-icon\n class=\"kms-date-input__icon\"\n icon=\"calendar\"\n [color]=\"Color.SECONDARY\"\n [size]=\"IconSizePx.XS\"\n matDatepickerToggleIcon\n ></kms-icon>\n </mat-datepicker-toggle>\n @if (hint()) {\n <mat-hint [id]=\"hintId\">{{ hint() }}</mat-hint>\n }\n <mat-error [id]=\"errorId\" role=\"alert\">{{ errorMessage() }}</mat-error>\n</mat-form-field>\n}\n", styles: [""], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i2$1.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2$1.MatLabel, selector: "mat-label" }, { kind: "directive", type: i2$1.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "directive", type: i2$1.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "directive", type: i2$1.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i3$2.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatDatepickerModule }, { kind: "component", type: i4.MatDatepicker, selector: "mat-datepicker", exportAs: ["matDatepicker"] }, { kind: "directive", type: i4.MatDatepickerInput, selector: "input[matDatepicker]", inputs: ["matDatepicker", "min", "max", "matDatepickerFilter"], exportAs: ["matDatepickerInput"] }, { kind: "component", type: i4.MatDatepickerToggle, selector: "mat-datepicker-toggle", inputs: ["for", "tabIndex", "aria-label", "disabled", "disableRipple"], exportAs: ["matDatepickerToggle"] }, { kind: "directive", type: i4.MatDatepickerToggleIcon, selector: "[matDatepickerToggleIcon]" }, { kind: "component", type: i4.MatDateRangeInput, selector: "mat-date-range-input", inputs: ["rangePicker", "required", "dateFilter", "min", "max", "disabled", "separator", "comparisonStart", "comparisonEnd"], exportAs: ["matDateRangeInput"] }, { kind: "directive", type: i4.MatStartDate, selector: "input[matStartDate]", outputs: ["dateChange", "dateInput"] }, { kind: "directive", type: i4.MatEndDate, selector: "input[matEndDate]", outputs: ["dateChange", "dateInput"] }, { kind: "component", type: i4.MatDateRangePicker, selector: "mat-date-range-picker", exportAs: ["matDateRangePicker"] }, { kind: "component", type: IconComponent, selector: "kms-icon", inputs: ["icon", "iconClass", "size", "dontUseSprite", "color"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2258
2526
  }
2259
2527
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DateInputComponent, decorators: [{
2260
2528
  type: Component,
@@ -2270,7 +2538,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
2270
2538
  useExisting: forwardRef(() => DateInputComponent),
2271
2539
  multi: true,
2272
2540
  },
2273
- ], template: "@if (mode() === 'date') {\n<mat-form-field class=\"kms-date-input__form-field\">\n <mat-label>{{ label() }}</mat-label>\n <input\n [id]=\"inputId\"\n matInput\n [matDatepicker]=\"picker\"\n [formControl]=\"innerControl\"\n [placeholder]=\"placeholder()\"\n [required]=\"required()\"\n [min]=\"minDate()\"\n [max]=\"maxDate()\"\n [errorStateMatcher]=\"errorStateMatcher\"\n [attr.aria-required]=\"required()\"\n [attr.aria-invalid]=\"errorMessage() ? true : null\"\n [attr.aria-describedby]=\"\n (hint() ? hintId : '') + (errorMessage() ? ' ' + errorId : '') || null\n \"\n (dateChange)=\"onDateChanged($event.value)\"\n (blur)=\"onTouched()\"\n (click)=\"picker.open()\"\n (keyup)=\"\n ($event.key === 'Enter' || $event.key === 'Space') && picker.open()\n \"\n />\n <mat-datepicker\n #picker\n [startView]=\"computedStartView()\"\n (monthSelected)=\"onMonthSelected($event, picker)\"\n ></mat-datepicker>\n <mat-datepicker-toggle matIconSuffix [for]=\"picker\">\n <kms-icon\n class=\"kms-date-input__icon\"\n icon=\"calendar\"\n [color]=\"Color.SECONDARY\"\n [size]=\"IconSizePx.XS\"\n matDatepickerToggleIcon\n ></kms-icon>\n </mat-datepicker-toggle>\n @if (hint()) {\n <mat-hint [id]=\"hintId\">{{ hint() }}</mat-hint>\n }\n <mat-error [id]=\"errorId\" role=\"alert\">{{ errorMessage() }}</mat-error>\n</mat-form-field>\n} @if (mode() === 'range') {\n<mat-form-field class=\"kms-date-input__form-field\">\n <mat-label>{{ label() }}</mat-label>\n <mat-date-range-input\n [rangePicker]=\"rangePicker\"\n [min]=\"minDate()\"\n [max]=\"maxDate()\"\n (click)=\"rangePicker.open()\"\n (keyup)=\"\n ($event.key === 'Enter' || $event.key === 'Space') && rangePicker.open()\n \"\n >\n <input\n matStartDate\n [formControl]=\"rangeGroup.controls.start\"\n [placeholder]=\"placeholder() || 'Start date'\"\n [required]=\"required()\"\n [attr.aria-required]=\"required()\"\n [attr.aria-invalid]=\"errorMessage() ? true : null\"\n [attr.aria-describedby]=\"\n (hint() ? hintId : '') + (errorMessage() ? ' ' + errorId : '') || null\n \"\n (dateChange)=\"onRangeChanged()\"\n (blur)=\"onTouched()\"\n />\n <input\n matEndDate\n [formControl]=\"rangeGroup.controls.end\"\n placeholder=\"End date\"\n (dateChange)=\"onRangeChanged()\"\n (blur)=\"onTouched()\"\n />\n </mat-date-range-input>\n <mat-date-range-picker #rangePicker></mat-date-range-picker>\n <mat-datepicker-toggle matIconSuffix [for]=\"rangePicker\">\n <kms-icon\n class=\"kms-date-input__icon\"\n icon=\"calendar\"\n [color]=\"Color.SECONDARY\"\n [size]=\"IconSizePx.XS\"\n matDatepickerToggleIcon\n ></kms-icon>\n </mat-datepicker-toggle>\n @if (hint()) {\n <mat-hint [id]=\"hintId\">{{ hint() }}</mat-hint>\n }\n <mat-error [id]=\"errorId\" role=\"alert\">{{ errorMessage() }}</mat-error>\n</mat-form-field>\n}\n" }]
2541
+ ], template: "@if (mode() === 'date') {\n<mat-form-field class=\"kms-date-input__form-field\">\n <mat-label>{{ label() }}</mat-label>\n <input\n [id]=\"inputId\"\n matInput\n [matDatepicker]=\"picker\"\n [formControl]=\"innerControl\"\n [placeholder]=\"placeholder()\"\n [required]=\"required()\"\n [min]=\"minDate()\"\n [max]=\"maxDate()\"\n [errorStateMatcher]=\"errorStateMatcher\"\n [attr.aria-required]=\"required()\"\n [attr.aria-invalid]=\"errorMessage() ? true : null\"\n [attr.aria-describedby]=\"\n (hint() ? hintId : '') + (errorMessage() ? ' ' + errorId : '') || null\n \"\n (dateChange)=\"onDateChanged($event.value)\"\n (blur)=\"onTouched()\"\n (click)=\"picker.open()\"\n (keyup)=\"\n ($event.key === 'Enter' || $event.key === 'Space') && picker.open()\n \"\n />\n <mat-datepicker\n #picker\n [startView]=\"computedStartView()\"\n (monthSelected)=\"onMonthSelected($event, picker)\"\n ></mat-datepicker>\n <mat-datepicker-toggle matIconSuffix [for]=\"picker\">\n <kms-icon\n class=\"kms-date-input__icon\"\n icon=\"calendar\"\n [color]=\"Color.SECONDARY\"\n [size]=\"IconSizePx.XS\"\n matDatepickerToggleIcon\n ></kms-icon>\n </mat-datepicker-toggle>\n @if (hint()) {\n <mat-hint [id]=\"hintId\">{{ hint() }}</mat-hint>\n }\n <mat-error [id]=\"errorId\" role=\"alert\">{{ errorMessage() }}</mat-error>\n</mat-form-field>\n} @if (mode() === 'range') {\n<mat-form-field class=\"kms-date-input__form-field\">\n <mat-label>{{ label() }}</mat-label>\n <mat-date-range-input\n [rangePicker]=\"rangePicker\"\n [min]=\"minDate()\"\n [max]=\"maxDate()\"\n (click)=\"rangePicker.open()\"\n (keyup)=\"\n ($event.key === 'Enter' || $event.key === 'Space') && rangePicker.open()\n \"\n >\n <input\n matStartDate\n [formControl]=\"rangeGroup.controls.start\"\n [placeholder]=\"placeholder() || startDateAriaLabel()\"\n [attr.aria-label]=\"startDateAriaLabel()\"\n [required]=\"required()\"\n [attr.aria-required]=\"required()\"\n [attr.aria-invalid]=\"errorMessage() ? true : null\"\n [attr.aria-describedby]=\"\n (hint() ? hintId : '') + (errorMessage() ? ' ' + errorId : '') || null\n \"\n (dateChange)=\"onRangeChanged()\"\n (blur)=\"onTouched()\"\n />\n <input\n matEndDate\n [formControl]=\"rangeGroup.controls.end\"\n [placeholder]=\"endDateAriaLabel()\"\n [attr.aria-label]=\"endDateAriaLabel()\"\n [attr.aria-required]=\"required()\"\n [attr.aria-invalid]=\"errorMessage() ? true : null\"\n [attr.aria-describedby]=\"\n (hint() ? hintId : '') + (errorMessage() ? ' ' + errorId : '') || null\n \"\n (dateChange)=\"onRangeChanged()\"\n (blur)=\"onTouched()\"\n />\n </mat-date-range-input>\n <mat-date-range-picker #rangePicker></mat-date-range-picker>\n <mat-datepicker-toggle matIconSuffix [for]=\"rangePicker\">\n <kms-icon\n class=\"kms-date-input__icon\"\n icon=\"calendar\"\n [color]=\"Color.SECONDARY\"\n [size]=\"IconSizePx.XS\"\n matDatepickerToggleIcon\n ></kms-icon>\n </mat-datepicker-toggle>\n @if (hint()) {\n <mat-hint [id]=\"hintId\">{{ hint() }}</mat-hint>\n }\n <mat-error [id]=\"errorId\" role=\"alert\">{{ errorMessage() }}</mat-error>\n</mat-form-field>\n}\n" }]
2274
2542
  }], propDecorators: { dateChange: [{ type: i0.Output, args: ["dateChange"] }], rangeChange: [{ type: i0.Output, args: ["rangeChange"] }], mode: [{ type: i0.Input, args: [{ isSignal: true, alias: "mode", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], errorMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorMessage", required: false }] }], minDate: [{ type: i0.Input, args: [{ isSignal: true, alias: "minDate", required: false }] }], maxDate: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxDate", required: false }] }], monthPicker: [{ type: i0.Input, args: [{ isSignal: true, alias: "monthPicker", required: false }] }], startView: [{ type: i0.Input, args: [{ isSignal: true, alias: "startView", required: false }] }] } });
2275
2543
 
2276
2544
  class EnumRadiogroupComponent extends FormControlParentComponent {
@@ -4798,7 +5066,20 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
4798
5066
  }], ctorParameters: () => [], propDecorators: { config: [{ type: i0.Input, args: [{ isSignal: true, alias: "config", required: true }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], formSubmit: [{ type: i0.Output, args: ["formSubmit"] }], formStateChange: [{ type: i0.Output, args: ["formStateChange"] }], formReady: [{ type: i0.Output, args: ["formReady"] }], fieldValueChange: [{ type: i0.Output, args: ["fieldValueChange"] }] } });
4799
5067
 
4800
5068
  class KmsUiPresentationalModule {
4801
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: KmsUiPresentationalModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
5069
+ constructor(translate) {
5070
+ // Merge all bundled library strings (validator messages, date-input
5071
+ // aria-labels, etc.) into ngx-translate under `uiPresentational.*`.
5072
+ // The consumer's HTTP loader overwrites the store on (re)load, so
5073
+ // we re-merge on every language change.
5074
+ const currentLang = translate.currentLang || translate.defaultLang;
5075
+ if (currentLang) {
5076
+ mergeKmsLibMessages(translate, currentLang);
5077
+ }
5078
+ translate.onLangChange.subscribe((event) => {
5079
+ mergeKmsLibMessages(translate, event.lang);
5080
+ });
5081
+ }
5082
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: KmsUiPresentationalModule, deps: [{ token: i1$8.TranslateService }], target: i0.ɵɵFactoryTarget.NgModule }); }
4802
5083
  static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.16", ngImport: i0, type: KmsUiPresentationalModule, declarations: [BackToTopComponent,
4803
5084
  CheckboxComponent,
4804
5085
  ColorInputComponent,
@@ -5034,7 +5315,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
5034
5315
  providers: [ViewportService],
5035
5316
  schemas: [CUSTOM_ELEMENTS_SCHEMA],
5036
5317
  }]
5037
- }] });
5318
+ }], ctorParameters: () => [{ type: i1$8.TranslateService }] });
5038
5319
 
5039
5320
  class KmsUiPresentationalService {
5040
5321
  constructor() { }
@@ -5075,116 +5356,23 @@ function noSpecialCharsOnly() {
5075
5356
  };
5076
5357
  }
5077
5358
 
5078
- /**
5079
- * Pre-translated validation error messages for all supported locales.
5080
- * Merged into @ngx-translate via `GenericFormModule` constructor under
5081
- * the key path `uiPresentational.validatorMessages.<validatorName>`.
5082
- *
5083
- * Interpolation placeholders (e.g. `{{requiredLength}}`) match the metadata
5084
- * objects Angular validators attach to `ValidationErrors`.
5085
- */
5086
- const KMS_ERROR_MESSAGES = {
5087
- en: {
5088
- required: 'This field is required.',
5089
- minlength: 'Minimum {{requiredLength}} characters required.',
5090
- maxlength: 'Maximum {{requiredLength}} characters allowed.',
5091
- min: 'Value must be at least {{min}}.',
5092
- max: 'Value must be at most {{max}}.',
5093
- email: 'Please enter a valid email address.',
5094
- pattern: 'The value does not match the required format.',
5095
- whitespaceOnly: 'Must not contain only whitespace.',
5096
- specialCharsOnly: 'Must contain at least one letter or number.',
5097
- },
5098
- 'en-uk': {
5099
- required: 'This field is required.',
5100
- minlength: 'Minimum {{requiredLength}} characters required.',
5101
- maxlength: 'Maximum {{requiredLength}} characters allowed.',
5102
- min: 'Value must be at least {{min}}.',
5103
- max: 'Value must be at most {{max}}.',
5104
- email: 'Please enter a valid email address.',
5105
- pattern: 'The value does not match the required format.',
5106
- whitespaceOnly: 'Must not contain only whitespace.',
5107
- specialCharsOnly: 'Must contain at least one letter or number.',
5108
- },
5109
- de: {
5110
- required: 'Dieses Feld ist erforderlich.',
5111
- minlength: 'Mindestens {{requiredLength}} Zeichen erforderlich.',
5112
- maxlength: 'Maximal {{requiredLength}} Zeichen erlaubt.',
5113
- min: 'Der Wert muss mindestens {{min}} betragen.',
5114
- max: 'Der Wert darf h\u00f6chstens {{max}} betragen.',
5115
- email: 'Bitte geben Sie eine g\u00fcltige E-Mail-Adresse ein.',
5116
- pattern: 'Der Wert entspricht nicht dem erforderlichen Format.',
5117
- whitespaceOnly: 'Darf nicht nur aus Leerzeichen bestehen.',
5118
- specialCharsOnly: 'Muss mindestens einen Buchstaben oder eine Zahl enthalten.',
5119
- },
5120
- 'de-de': {
5121
- required: 'Dieses Feld ist erforderlich.',
5122
- minlength: 'Mindestens {{requiredLength}} Zeichen erforderlich.',
5123
- maxlength: 'Maximal {{requiredLength}} Zeichen erlaubt.',
5124
- min: 'Der Wert muss mindestens {{min}} betragen.',
5125
- max: 'Der Wert darf h\u00f6chstens {{max}} betragen.',
5126
- email: 'Bitte geben Sie eine g\u00fcltige E-Mail-Adresse ein.',
5127
- pattern: 'Der Wert entspricht nicht dem erforderlichen Format.',
5128
- whitespaceOnly: 'Darf nicht nur aus Leerzeichen bestehen.',
5129
- specialCharsOnly: 'Muss mindestens einen Buchstaben oder eine Zahl enthalten.',
5130
- },
5131
- 'de-ch': {
5132
- required: 'Dieses Feld ist erforderlich.',
5133
- minlength: 'Mindestens {{requiredLength}} Zeichen erforderlich.',
5134
- maxlength: 'Maximal {{requiredLength}} Zeichen erlaubt.',
5135
- min: 'Der Wert muss mindestens {{min}} betragen.',
5136
- max: 'Der Wert darf h\u00f6chstens {{max}} betragen.',
5137
- email: 'Bitte geben Sie eine g\u00fcltige E-Mail-Adresse ein.',
5138
- pattern: 'Der Wert entspricht nicht dem erforderlichen Format.',
5139
- whitespaceOnly: 'Darf nicht nur aus Leerzeichen bestehen.',
5140
- specialCharsOnly: 'Muss mindestens einen Buchstaben oder eine Zahl enthalten.',
5141
- },
5142
- };
5143
-
5144
5359
  /**
5145
5360
  * Lightweight facade module for the generic-form feature.
5146
5361
  *
5147
5362
  * - Provides `FieldRegistryService` (maps FieldType → library component classes).
5148
- * - Merges pre-translated validation error messages into `@ngx-translate`
5149
- * so that `GenericFormService.resolveErrorMessage()` can look them up.
5150
5363
  *
5151
5364
  * **Does NOT declare any components** — those live in `KmsUiPresentationalModule`
5152
5365
  * to avoid circular AOT imports.
5153
5366
  *
5154
- * Consuming apps import both modules:
5367
+ * Library translations (validator messages, date-input aria-labels, etc.)
5368
+ * are merged centrally by `KmsUiPresentationalModule`. Consuming apps
5369
+ * import both modules:
5155
5370
  * ```ts
5156
5371
  * imports: [KmsUiPresentationalModule, GenericFormModule]
5157
5372
  * ```
5158
5373
  */
5159
5374
  class GenericFormModule {
5160
- constructor(translate) {
5161
- // Re-merge library error messages whenever the app loads/changes language.
5162
- // The app's HTTP loader calls setTranslation() without merge, which
5163
- // overwrites the store — this subscriber re-merges library messages on top.
5164
- //
5165
- // NOTE: We intentionally do NOT merge upfront for all languages, because
5166
- // that would make ngx-translate skip the HTTP loader (it thinks translations
5167
- // are already cached), breaking the app's own translations.
5168
- // Merge immediately if a language is already active (e.g. APP_INITIALIZER
5169
- // called translate.use() before this module was instantiated).
5170
- const currentLang = translate.currentLang || translate.defaultLang;
5171
- if (currentLang) {
5172
- this.mergeMessages(translate, currentLang);
5173
- }
5174
- translate.onLangChange.subscribe((event) => {
5175
- this.mergeMessages(translate, event.lang);
5176
- });
5177
- }
5178
- mergeMessages(translate, lang) {
5179
- const key = lang.toLowerCase();
5180
- const messages = KMS_ERROR_MESSAGES[key] ??
5181
- KMS_ERROR_MESSAGES[key.split('-')[0]] ??
5182
- KMS_ERROR_MESSAGES['en'];
5183
- if (messages) {
5184
- translate.setTranslation(lang, { uiPresentational: { validatorMessages: messages } }, true);
5185
- }
5186
- }
5187
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: GenericFormModule, deps: [{ token: i1$8.TranslateService }], target: i0.ɵɵFactoryTarget.NgModule }); }
5375
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: GenericFormModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
5188
5376
  static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.16", ngImport: i0, type: GenericFormModule, imports: [TranslateModule] }); }
5189
5377
  static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: GenericFormModule, providers: [FieldRegistryService], imports: [TranslateModule] }); }
5190
5378
  }
@@ -5194,7 +5382,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
5194
5382
  imports: [TranslateModule],
5195
5383
  providers: [FieldRegistryService],
5196
5384
  }]
5197
- }], ctorParameters: () => [{ type: i1$8.TranslateService }] });
5385
+ }] });
5198
5386
 
5199
5387
  /** Form layout mode. Currently only GRID is implemented. */
5200
5388
  var FormLayout;