@xiriframework/xiri-ng 0.2.49 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  import { DomSanitizer } from '@angular/platform-browser';
2
2
  import * as i0 from '@angular/core';
3
- import { inject, Pipe, input, computed, Directive, ElementRef, ChangeDetectorRef, Input, Component, Injectable, output, numberAttribute, signal, afterRenderEffect, booleanAttribute, viewChild, DestroyRef, effect, forwardRef, PLATFORM_ID, Service, untracked, Injector, afterNextRender, ViewEncapsulation, linkedSignal, ChangeDetectionStrategy, NgZone, makeEnvironmentProviders } from '@angular/core';
3
+ import { inject, Pipe, input, computed, Directive, ElementRef, ChangeDetectorRef, Input, Component, PLATFORM_ID, signal, effect, Service, output, numberAttribute, afterRenderEffect, booleanAttribute, viewChild, Injectable, DestroyRef, forwardRef, untracked, Injector, afterNextRender, ViewEncapsulation, linkedSignal, ChangeDetectionStrategy, NgZone, makeEnvironmentProviders } from '@angular/core';
4
4
  import { DefaultUrlSerializer, RouterLink, Router, NavigationEnd } from '@angular/router';
5
5
  import { takeUntilDestroyed, toSignal, rxResource } from '@angular/core/rxjs-interop';
6
6
  import * as i1 from '@angular/forms';
@@ -20,6 +20,8 @@ import { MatCheckbox } from '@angular/material/checkbox';
20
20
  import { MatRadioButton, MatRadioGroup } from '@angular/material/radio';
21
21
  import { fromUnixTime, format, transpose } from 'date-fns';
22
22
  import { tz } from '@date-fns/tz';
23
+ import { de } from 'date-fns/locale/de';
24
+ import { enGB } from 'date-fns/locale/en-GB';
23
25
  import { MatDatepickerInput, MatDatepickerToggle, MatDatepickerToggleIcon, MatDatepicker, MatDateRangeInput, MatStartDate, MatEndDate, MatDateRangePicker } from '@angular/material/datepicker';
24
26
  import { MatTree, MatTreeNestedDataSource, MatTreeNode, MatTreeNodeToggle, MatTreeNodePadding, MatTreeNodeDef } from '@angular/material/tree';
25
27
  import { SelectionModel } from '@angular/cdk/collections';
@@ -31,8 +33,6 @@ import { NgxMatSelectSearchModule } from 'ngx-mat-select-search';
31
33
  import { ENTER, COMMA, ESCAPE } from '@angular/cdk/keycodes';
32
34
  import { MatAutocompleteTrigger, MatAutocomplete } from '@angular/material/autocomplete';
33
35
  import { MatChipGrid, MatChipRow, MatChipRemove, MatChipInput, MatChipSet, MatChip } from '@angular/material/chips';
34
- import { de } from 'date-fns/locale/de';
35
- import { enGB } from 'date-fns/locale/en-GB';
36
36
  import { MatTableDataSource, MatTable, MatColumnDef, MatHeaderCellDef, MatHeaderCell, MatCellDef, MatCell, MatHeaderRowDef, MatHeaderRow, MatRowDef, MatRow, MatFooterRow, MatFooterRowDef, MatFooterCell, MatFooterCellDef } from '@angular/material/table';
37
37
  import { MatTooltip } from '@angular/material/tooltip';
38
38
  import { MatDialogRef, MAT_DIALOG_DATA, MatDialogTitle, MatDialogContent, MatDialogActions, MatDialog } from '@angular/material/dialog';
@@ -682,16 +682,94 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImpor
682
682
  type: Input
683
683
  }] } });
684
684
 
685
- class XiriDateService {
685
+ const deValidationMessages = {
686
+ required: 'Pflichtfeld – bitte ausfüllen',
687
+ invalidFormat: 'Bitte ein gültiges Format eingeben',
688
+ invalidEmail: 'Bitte eine gültige E-Mail-Adresse eingeben',
689
+ valueRequired: 'Bitte einen Wert angeben',
690
+ minLength: min => `Mindestens ${min} Zeichen erforderlich`,
691
+ maxLength: max => `Maximal ${max} Zeichen erlaubt`,
692
+ minNumber: min => `Mindestens ${min} erforderlich`,
693
+ maxNumber: max => `Maximal ${max} erlaubt`,
694
+ minDate: date => `Datum darf nicht vor ${date} liegen`,
695
+ maxDate: date => `Datum darf nicht nach ${date} liegen`,
696
+ minDateRange: date => `Startdatum muss nach ${date} liegen`,
697
+ maxDateRange: date => `Enddatum muss vor ${date} liegen`,
698
+ minSelection: min => `Mindestens ${min} Einträge auswählen`,
699
+ maxSelection: max => `Maximal ${max} Einträge auswählen`,
700
+ };
701
+ const enValidationMessages = {
702
+ required: 'Required field',
703
+ invalidFormat: 'Please enter a valid format',
704
+ invalidEmail: 'Please enter a valid email address',
705
+ valueRequired: 'Please provide a value',
706
+ minLength: min => `At least ${min} characters required`,
707
+ maxLength: max => `Maximum ${max} characters allowed`,
708
+ minNumber: min => `Minimum value is ${min}`,
709
+ maxNumber: max => `Maximum value is ${max}`,
710
+ minDate: date => `Date must not be before ${date}`,
711
+ maxDate: date => `Date must not be after ${date}`,
712
+ minDateRange: date => `Start date must be after ${date}`,
713
+ maxDateRange: date => `End date must be before ${date}`,
714
+ minSelection: min => `Select at least ${min} items`,
715
+ maxSelection: max => `Select at most ${max} items`,
716
+ };
717
+ class XiriLocaleService {
686
718
  constructor() {
719
+ this.platformId = inject(PLATFORM_ID);
720
+ this.isBrowser = isPlatformBrowser(this.platformId);
721
+ this.dateAdapter = inject(DateAdapter, { optional: true });
722
+ // Registry aller bekannten Sprachen — de/en eingebaut, weitere per registerLanguage().
723
+ this.registry = new Map([
724
+ ['de', { localeString: 'de-DE', dateFnsLocale: de, validationMessages: deValidationMessages }],
725
+ ['en', { localeString: 'en-GB', dateFnsLocale: enGB, validationMessages: enValidationMessages }],
726
+ ]);
727
+ this._language = signal('de', /* @ts-ignore */
728
+ ...(ngDevMode ? [{ debugName: "_language" }] : /* istanbul ignore next */ []));
729
+ this.language = this._language.asReadonly();
730
+ this.localeString = computed(() => this.registry.get(this._language())?.localeString ?? 'de-DE', /* @ts-ignore */
731
+ ...(ngDevMode ? [{ debugName: "localeString" }] : /* istanbul ignore next */ []));
732
+ // Aktives date-fns-Locale (für Datums-Formatierung + Datepicker). Undefined bei Text-only-Sprache.
733
+ this.dateFnsLocale = computed(() => this.registry.get(this._language())?.dateFnsLocale, /* @ts-ignore */
734
+ ...(ngDevMode ? [{ debugName: "dateFnsLocale" }] : /* istanbul ignore next */ []));
735
+ // Zeitzone für alle Unix<->Local-Umrechnungen (locale-nahe Präsentations-Info, analog Go-uicontext).
687
736
  this.currentTimezone = 'Europe/Vienna';
688
- this.dateAdapter = inject(DateAdapter);
737
+ const stored = this.readStoredLanguage();
738
+ // Nur wiederherstellen, wenn die Sprache bekannt ist (de/en oder bereits registriert).
739
+ if (stored && this.registry.has(stored))
740
+ this._language.set(stored);
741
+ // Material-Datepicker-Locale (Picker-UI) an die Sprache angleichen — reine Frontend-Interaktion.
742
+ // Ohne bereitgestellten DateAdapter (Text-only-Formular) oder ohne date-fns-Locale wird übersprungen.
743
+ effect(() => {
744
+ const locale = this.dateFnsLocale();
745
+ if (locale)
746
+ this.dateAdapter?.setLocale(locale);
747
+ });
748
+ }
749
+ // Sprache registrieren/überschreiben. Vor setLanguage() bzw. dem ersten Formular-Render aufrufen (App-Init).
750
+ registerLanguage(code, def) {
751
+ this.registry.set(code, def);
752
+ // Über Reload persistierte Custom-Sprache einklinken, sobald sie (nach)registriert wird —
753
+ // der Konstruktor kennt beim Restore nur de/en.
754
+ if (this.readStoredLanguage() === code)
755
+ this._language.set(code);
756
+ }
757
+ setLanguage(lang) {
758
+ if (!this.registry.has(lang)) {
759
+ console.warn(`XiriLocaleService: unbekannte Sprache '${lang}' – zuerst registerLanguage() aufrufen.`);
760
+ return;
761
+ }
762
+ this._language.set(lang);
763
+ this.storeLanguage(lang);
689
764
  }
690
- setTimezone(tz) {
691
- this.currentTimezone = tz;
765
+ // Validierungs-Fehlertexte der aktiven Sprache; Fallback de, falls (unerwartet) nicht vorhanden.
766
+ validationMessagesFor() {
767
+ return this.registry.get(this._language())?.validationMessages
768
+ ?? this.registry.get('de').validationMessages;
692
769
  }
693
- setLocale(localeString, locale) {
694
- this.dateAdapter.setLocale(locale);
770
+ // ── Zeitzone + Datums-/Zahlen-Formatierung (locale-abhängig) ─────────────────────────────
771
+ setTimezone(timezone) {
772
+ this.currentTimezone = timezone;
695
773
  }
696
774
  unixToLocal(stime) {
697
775
  if (stime === null || stime === undefined)
@@ -700,28 +778,64 @@ class XiriDateService {
700
778
  }
701
779
  unixToStringDateTime(stime) {
702
780
  const date = this.unixToLocal(stime);
703
- return date === null ? '' : format(date, 'yyyy-MM-dd HH:mm');
781
+ return date === null ? '' : format(date, 'yyyy-MM-dd HH:mm', { locale: this.dateFnsLocale() });
704
782
  }
705
783
  unixToStringDate(stime) {
706
784
  const date = this.unixToLocal(stime);
707
- return date === null ? '' : format(date, 'd. LLL.');
785
+ // Kein Punkt hinter LLL: die Interpunktion des Monatskürzels bringt das jeweilige Locale
786
+ // selbst mit (de/fr: 'Mär.'/'juil.', en: 'Jul' ohne) — ein fixer Punkt gäbe sonst '18. Mär..'.
787
+ return date === null ? '' : format(date, 'd. LLL', { locale: this.dateFnsLocale() });
708
788
  }
709
789
  unixToStringDateYear(stime) {
710
790
  const date = this.unixToLocal(stime);
711
- return date === null ? '' : format(date, 'd. LLL. yy');
791
+ return date === null ? '' : format(date, 'd. LLL yy', { locale: this.dateFnsLocale() });
712
792
  }
713
793
  dateToUnix(date) {
714
794
  return Math.floor(transpose(date, tz(this.currentTimezone)).getTime() / 1000);
715
795
  }
716
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: XiriDateService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
717
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: XiriDateService, providedIn: 'root' }); }
796
+ formatNumber(value, webformat) {
797
+ if (value === null || value === undefined)
798
+ return '';
799
+ const digits = webformat === 'integer'
800
+ ? 0
801
+ : /^float\d+$/.test(webformat ?? '')
802
+ ? Number(webformat.slice(5))
803
+ : undefined;
804
+ const options = { style: 'decimal' };
805
+ if (digits !== undefined) {
806
+ options.minimumFractionDigits = digits;
807
+ options.maximumFractionDigits = digits;
808
+ }
809
+ return new Intl.NumberFormat(this.localeString(), options).format(value);
810
+ }
811
+ // localStorage-Zugriff abgesichert: im SSR nicht vorhanden, in jsdom-Tests ggf. undefined,
812
+ // im Private-Mode wirft es SecurityError. In all diesen Fällen still ohne Persistenz weiterlaufen.
813
+ readStoredLanguage() {
814
+ if (!this.isBrowser)
815
+ return null;
816
+ try {
817
+ return localStorage.getItem('xiri-language');
818
+ }
819
+ catch {
820
+ return null;
821
+ }
822
+ }
823
+ storeLanguage(lang) {
824
+ if (!this.isBrowser)
825
+ return;
826
+ try {
827
+ localStorage.setItem('xiri-language', lang);
828
+ }
829
+ catch {
830
+ // Persistenz nicht verfügbar (Private-Mode o. Ä.) — Sprachwechsel gilt trotzdem für die Session.
831
+ }
832
+ }
833
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: XiriLocaleService, deps: [], target: i0.ɵɵFactoryTarget.Service }); }
834
+ static { this.ɵprov = i0.ɵɵngDeclareService({ minVersion: "22.0.0", version: "22.0.7", ngImport: i0, type: XiriLocaleService }); }
718
835
  }
719
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: XiriDateService, decorators: [{
720
- type: Injectable,
721
- args: [{
722
- providedIn: 'root'
723
- }]
724
- }] });
836
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: XiriLocaleService, decorators: [{
837
+ type: Service
838
+ }], ctorParameters: () => [] });
725
839
 
726
840
  class XiriFieldMain {
727
841
  constructor() {
@@ -935,7 +1049,7 @@ class XiriDateTimeRangeComponent extends XiriFieldMain {
935
1049
  this.minutes = ['00', '05', '10', '15',
936
1050
  '20', '25', '30', '35',
937
1051
  '40', '45', '50', '55',];
938
- this.dateService = inject(XiriDateService);
1052
+ this.dateService = inject(XiriLocaleService);
939
1053
  this.fb = inject(FormBuilder);
940
1054
  this._id = this._uid;
941
1055
  if (this.ngControl != null)
@@ -1093,7 +1207,7 @@ class XiriDateRangeComponent extends XiriFieldMain {
1093
1207
  this.minDate = null;
1094
1208
  this.maxDate = null;
1095
1209
  this._lastValue = null;
1096
- this.dateService = inject(XiriDateService);
1210
+ this.dateService = inject(XiriLocaleService);
1097
1211
  this.fb = inject(FormBuilder);
1098
1212
  this._id = this._uid;
1099
1213
  if (this.ngControl != null)
@@ -1237,7 +1351,7 @@ class XiriDateComponent extends XiriFieldMain {
1237
1351
  '30', '31', '32', '33', '34', '35', '36', '37', '38', '39',
1238
1352
  '40', '41', '42', '43', '44', '45', '46', '47', '48', '49',
1239
1353
  '50', '51', '52', '53', '54', '55', '56', '57', '58', '59',];
1240
- this.dateService = inject(XiriDateService);
1354
+ this.dateService = inject(XiriLocaleService);
1241
1355
  this.fb = inject(FormBuilder);
1242
1356
  this._id = this._uid;
1243
1357
  if (this.ngControl != null)
@@ -1375,7 +1489,7 @@ class XiriYearMonthComponent extends XiriFieldMain {
1375
1489
  ...(ngDevMode ? [{ debugName: "picker" }] : /* istanbul ignore next */ []));
1376
1490
  this._lastValue = null;
1377
1491
  this.type = 'yearmonth';
1378
- this.dateService = inject(XiriDateService);
1492
+ this.dateService = inject(XiriLocaleService);
1379
1493
  this._id = this._uid;
1380
1494
  if (this.ngControl != null)
1381
1495
  this.ngControl.valueAccessor = this;
@@ -2167,77 +2281,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImpor
2167
2281
  ], template: "<mat-form-field>\n\t@if (field().name) {\n\t\t<mat-label>{{ field().name }}</mat-label>\n\t}\n\t<mat-chip-grid #chipGrid>\n\t\t@for (chip of chips(); track chip) {\n\t\t\t<mat-chip-row (removed)=\"remove(chip)\" [class]=\"chipColor(chip)\">\n\t\t\t\t{{ displayLabel(chip) }}\n\t\t\t\t<button matChipRemove>\n\t\t\t\t\t<mat-icon>cancel</mat-icon>\n\t\t\t\t</button>\n\t\t\t</mat-chip-row>\n\t\t}\n\t</mat-chip-grid>\n\t<input #chipInput\n\t [matChipInputFor]=\"chipGrid\"\n\t [matChipInputSeparatorKeyCodes]=\"separatorKeyCodes\"\n\t [matChipInputAddOnBlur]=\"true\"\n\t (matChipInputTokenEnd)=\"add($event)\"\n\t (input)=\"onInputChange($event)\"\n\t (focus)=\"onFocus()\"\n\t [matAutocomplete]=\"auto\"\n\t [placeholder]=\"field().hint || ''\">\n\t<mat-autocomplete #auto=\"matAutocomplete\" (optionSelected)=\"selected($event)\">\n\t\t@for (option of filteredOptions(); track option.id) {\n\t\t\t<mat-option [value]=\"option\">{{ option.name }}</mat-option>\n\t\t}\n\t</mat-autocomplete>\n</mat-form-field>\n", styles: [":host{display:block;width:100%}mat-form-field{width:100%}\n"] }]
2168
2282
  }], propDecorators: { field: [{ type: i0.Input, args: [{ isSignal: true, alias: "field", required: true }] }], chipInput: [{ type: i0.ViewChild, args: ['chipInput', { isSignal: true }] }] } });
2169
2283
 
2170
- class XiriLocaleService {
2171
- constructor() {
2172
- this.platformId = inject(PLATFORM_ID);
2173
- this.isBrowser = isPlatformBrowser(this.platformId);
2174
- this.dateAdapter = inject(DateAdapter, { optional: true });
2175
- this._language = signal('de', /* @ts-ignore */
2176
- ...(ngDevMode ? [{ debugName: "_language" }] : /* istanbul ignore next */ []));
2177
- this.language = this._language.asReadonly();
2178
- this.localeString = computed(() => this._language() === 'en' ? 'en-GB' : 'de-DE', /* @ts-ignore */
2179
- ...(ngDevMode ? [{ debugName: "localeString" }] : /* istanbul ignore next */ []));
2180
- if (this.isBrowser) {
2181
- const stored = localStorage.getItem('xiri-language');
2182
- if (stored === 'de' || stored === 'en')
2183
- this._language.set(stored);
2184
- }
2185
- // Material-Datepicker-Locale (Picker-UI) an die Sprache angleichen — reine Frontend-Interaktion.
2186
- // Ohne bereitgestellten DateAdapter (z. B. Text-only-Formular ohne provideDateFnsAdapter()) gibt es
2187
- // ohnehin keinen Datepicker, daher wird der effect dann übersprungen.
2188
- effect(() => {
2189
- this.dateAdapter?.setLocale(this._language() === 'en' ? enGB : de);
2190
- });
2191
- }
2192
- setLanguage(lang) {
2193
- this._language.set(lang);
2194
- if (this.isBrowser)
2195
- localStorage.setItem('xiri-language', lang);
2196
- }
2197
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: XiriLocaleService, deps: [], target: i0.ɵɵFactoryTarget.Service }); }
2198
- static { this.ɵprov = i0.ɵɵngDeclareService({ minVersion: "22.0.0", version: "22.0.7", ngImport: i0, type: XiriLocaleService }); }
2284
+ function formatValidationDate(localeString, unixSeconds) {
2285
+ return new Intl.DateTimeFormat(localeString).format(new Date(unixSeconds * 1000));
2199
2286
  }
2200
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: XiriLocaleService, decorators: [{
2201
- type: Service
2202
- }], ctorParameters: () => [] });
2203
-
2204
- function formatValidationDate(lang, unixSeconds) {
2205
- return new Intl.DateTimeFormat(lang === 'en' ? 'en-US' : 'de-AT').format(new Date(unixSeconds * 1000));
2206
- }
2207
- const validationMessages = {
2208
- de: {
2209
- required: 'Pflichtfeld – bitte ausfüllen',
2210
- invalidFormat: 'Bitte ein gültiges Format eingeben',
2211
- invalidEmail: 'Bitte eine gültige E-Mail-Adresse eingeben',
2212
- valueRequired: 'Bitte einen Wert angeben',
2213
- minLength: min => `Mindestens ${min} Zeichen erforderlich`,
2214
- maxLength: max => `Maximal ${max} Zeichen erlaubt`,
2215
- minNumber: min => `Mindestens ${min} erforderlich`,
2216
- maxNumber: max => `Maximal ${max} erlaubt`,
2217
- minDate: date => `Datum darf nicht vor ${date} liegen`,
2218
- maxDate: date => `Datum darf nicht nach ${date} liegen`,
2219
- minDateRange: date => `Startdatum muss nach ${date} liegen`,
2220
- maxDateRange: date => `Enddatum muss vor ${date} liegen`,
2221
- minSelection: min => `Mindestens ${min} Einträge auswählen`,
2222
- maxSelection: max => `Maximal ${max} Einträge auswählen`,
2223
- },
2224
- en: {
2225
- required: 'Required field',
2226
- invalidFormat: 'Please enter a valid format',
2227
- invalidEmail: 'Please enter a valid email address',
2228
- valueRequired: 'Please provide a value',
2229
- minLength: min => `At least ${min} characters required`,
2230
- maxLength: max => `Maximum ${max} characters allowed`,
2231
- minNumber: min => `Minimum value is ${min}`,
2232
- maxNumber: max => `Maximum value is ${max}`,
2233
- minDate: date => `Date must not be before ${date}`,
2234
- maxDate: date => `Date must not be after ${date}`,
2235
- minDateRange: date => `Start date must be after ${date}`,
2236
- maxDateRange: date => `End date must be before ${date}`,
2237
- minSelection: min => `Select at least ${min} items`,
2238
- maxSelection: max => `Select at most ${max} items`,
2239
- },
2240
- };
2241
2287
  class XiriFormFieldsComponent {
2242
2288
  constructor() {
2243
2289
  this.formBuilder = inject(UntypedFormBuilder);
@@ -2477,8 +2523,8 @@ class XiriFormFieldsComponent {
2477
2523
  // Sprache wird bei jedem Zugriff auf `message` frisch aus dem Service gelesen (Getter),
2478
2524
  // damit die Fehlertexte bei einem Sprachwechsel ohne Neuaufbau der Validatoren umschalten.
2479
2525
  const localeService = this.localeService;
2480
- const langFor = () => localeService.language();
2481
- const messagesFor = () => validationMessages[langFor()];
2526
+ const messagesFor = () => localeService.validationMessagesFor();
2527
+ const localeStringFor = () => localeService.localeString();
2482
2528
  if (field.min !== undefined) {
2483
2529
  const min = field.min;
2484
2530
  if (field.type == 'number')
@@ -2491,13 +2537,13 @@ class XiriFormFieldsComponent {
2491
2537
  field.validations.push({
2492
2538
  id: 'min',
2493
2539
  validator: Validators.min(min),
2494
- get message() { return messagesFor().minDate(formatValidationDate(langFor(), min)); }
2540
+ get message() { return messagesFor().minDate(formatValidationDate(localeStringFor(), min)); }
2495
2541
  });
2496
2542
  else if (field.type == 'daterange' || field.type == 'datetimerange')
2497
2543
  field.validations.push({
2498
2544
  id: 'min',
2499
2545
  validator: validatorDateRangeStart(min),
2500
- get message() { return messagesFor().minDateRange(formatValidationDate(langFor(), min)); }
2546
+ get message() { return messagesFor().minDateRange(formatValidationDate(localeStringFor(), min)); }
2501
2547
  });
2502
2548
  else if (field.type == 'multiselect' || field.type == 'treeselect')
2503
2549
  field.validations.push({
@@ -2524,13 +2570,13 @@ class XiriFormFieldsComponent {
2524
2570
  field.validations.push({
2525
2571
  id: 'max',
2526
2572
  validator: Validators.max(max),
2527
- get message() { return messagesFor().maxDate(formatValidationDate(langFor(), max)); }
2573
+ get message() { return messagesFor().maxDate(formatValidationDate(localeStringFor(), max)); }
2528
2574
  });
2529
2575
  else if (field.type == 'daterange' || field.type == 'datetimerange')
2530
2576
  field.validations.push({
2531
2577
  id: 'max',
2532
2578
  validator: validatorDateRangeEnd(max),
2533
- get message() { return messagesFor().maxDateRange(formatValidationDate(langFor(), max)); }
2579
+ get message() { return messagesFor().maxDateRange(formatValidationDate(localeStringFor(), max)); }
2534
2580
  });
2535
2581
  else if (field.type == 'multiselect' || field.type == 'treeselect')
2536
2582
  field.validations.push({
@@ -4252,39 +4298,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImpor
4252
4298
  }]
4253
4299
  }], ctorParameters: () => [] });
4254
4300
 
4255
- class XiriNumberService {
4256
- constructor() {
4257
- this.currentLocale = 'de-DE';
4258
- }
4259
- setLocale(locale) {
4260
- this.currentLocale = locale;
4261
- }
4262
- formatNumber(value, webformat) {
4263
- if (value === null || value === undefined) {
4264
- return '';
4265
- }
4266
- const digits = webformat === 'integer'
4267
- ? 0
4268
- : /^float\d+$/.test(webformat ?? '')
4269
- ? Number(webformat.slice(5))
4270
- : undefined;
4271
- const options = { style: 'decimal' };
4272
- if (digits !== undefined) {
4273
- options.minimumFractionDigits = digits;
4274
- options.maximumFractionDigits = digits;
4275
- }
4276
- return new Intl.NumberFormat(this.currentLocale, options).format(value);
4277
- }
4278
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: XiriNumberService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
4279
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: XiriNumberService, providedIn: 'root' }); }
4280
- }
4281
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: XiriNumberService, decorators: [{
4282
- type: Injectable,
4283
- args: [{
4284
- providedIn: 'root'
4285
- }]
4286
- }] });
4287
-
4288
4301
  class XiriEmptyStateComponent {
4289
4302
  constructor() {
4290
4303
  this.settings = input.required(/* @ts-ignore */
@@ -4331,7 +4344,7 @@ class XiriTableComponent {
4331
4344
  this.dataService = inject(XiriDataService);
4332
4345
  this.router = inject(Router);
4333
4346
  this.sessionStorageService = inject(XiriSessionStorageService);
4334
- this.numberService = inject(XiriNumberService);
4347
+ this.numberService = inject(XiriLocaleService);
4335
4348
  this.snackbar = inject(XiriSnackbarService);
4336
4349
  this.responseHandler = inject(XiriResponseHandlerService);
4337
4350
  this.downloadService = inject(XiriDownloadService);
@@ -8309,5 +8322,5 @@ function provideXiriServices(config) {
8309
8322
  * Generated bundle index. Do not edit.
8310
8323
  */
8311
8324
 
8312
- export { COLOR_CSS_VAR, DEFAULT_COMPARE, DEFAULT_PREDICATE, FALLBACK_COLORS, SafehtmlPipe, ThemeService, XiriAlertComponent, XiriBarChartComponent, XiriBreadcrumbComponent, XiriBulletChartComponent, XiriButtonComponent, XiriButtonlineComponent, XiriButtonstyleComponent, XiriCalendarComponent, XiriCalloutComponent, XiriCardComponent, XiriCardlinkComponent, XiriColsDirective, XiriDataService, XiriDataServiceConfig, XiriDateService, XiriDescriptionListComponent, XiriDialogComponent, XiriDividerComponent, XiriDoneComponent, XiriDownloadService, XiriDynComponentComponent, XiriEchartsHostComponent, XiriEmptyStateComponent, XiriErrorComponent, XiriExpansionComponent, XiriFormComponent, XiriFormFieldsComponent, XiriFormService, XiriGanttComponent, XiriGaugeChartComponent, XiriHeaderComponent, XiriHeatmapComponent, XiriImagetextComponent, XiriInfopointComponent, XiriLineChartComponent, XiriLinksComponent, XiriListComponent, XiriLocalStorageService, XiriLocaleService, XiriMultiStatComponent, XiriMultiprogressComponent, XiriNumberService, XiriPageHeaderComponent, XiriPieChartComponent, XiriProgressComponent, XiriQueryComponent, XiriRawTableComponent, XiriResponseHandlerService, XiriSankeyComponent, XiriSearchComponent, XiriSectionComponent, XiriSelectDirective, XiriSessionStorageService, XiriSidenavComponent, XiriSidepanelComponent, XiriSidepanelRef, XiriSidepanelService, XiriSkeletonComponent, XiriSnackbarService, XiriStatComponent, XiriStatGridComponent, XiriStatusComponent, XiriStepperComponent, XiriTableComponent, XiriTabsComponent, XiriTimelineComponent, XiriToolbarComponent, XiriTreeComponent, XiriUrlPipe, colsToClasses, defaultXiriDataServiceConfig, escapeHtml, provideXiriServices, resolveColor };
8325
+ export { COLOR_CSS_VAR, DEFAULT_COMPARE, DEFAULT_PREDICATE, FALLBACK_COLORS, SafehtmlPipe, ThemeService, XiriAlertComponent, XiriBarChartComponent, XiriBreadcrumbComponent, XiriBulletChartComponent, XiriButtonComponent, XiriButtonlineComponent, XiriButtonstyleComponent, XiriCalendarComponent, XiriCalloutComponent, XiriCardComponent, XiriCardlinkComponent, XiriColsDirective, XiriDataService, XiriDataServiceConfig, XiriDescriptionListComponent, XiriDialogComponent, XiriDividerComponent, XiriDoneComponent, XiriDownloadService, XiriDynComponentComponent, XiriEchartsHostComponent, XiriEmptyStateComponent, XiriErrorComponent, XiriExpansionComponent, XiriFormComponent, XiriFormFieldsComponent, XiriFormService, XiriGanttComponent, XiriGaugeChartComponent, XiriHeaderComponent, XiriHeatmapComponent, XiriImagetextComponent, XiriInfopointComponent, XiriLineChartComponent, XiriLinksComponent, XiriListComponent, XiriLocalStorageService, XiriLocaleService, XiriMultiStatComponent, XiriMultiprogressComponent, XiriPageHeaderComponent, XiriPieChartComponent, XiriProgressComponent, XiriQueryComponent, XiriRawTableComponent, XiriResponseHandlerService, XiriSankeyComponent, XiriSearchComponent, XiriSectionComponent, XiriSelectDirective, XiriSessionStorageService, XiriSidenavComponent, XiriSidepanelComponent, XiriSidepanelRef, XiriSidepanelService, XiriSkeletonComponent, XiriSnackbarService, XiriStatComponent, XiriStatGridComponent, XiriStatusComponent, XiriStepperComponent, XiriTableComponent, XiriTabsComponent, XiriTimelineComponent, XiriToolbarComponent, XiriTreeComponent, XiriUrlPipe, colsToClasses, defaultXiriDataServiceConfig, escapeHtml, provideXiriServices, resolveColor };
8313
8326
  //# sourceMappingURL=xiriframework-xiri-ng.mjs.map