@praxisui/dynamic-fields 8.0.0-beta.21 → 8.0.0-beta.23

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,14 +1,14 @@
1
1
  import * as i1$1 from '@angular/forms';
2
2
  import { NgControl, FormControl, Validators, ReactiveFormsModule, NG_VALUE_ACCESSOR, FormGroup, FormArray, FormsModule } from '@angular/forms';
3
3
  import * as i0 from '@angular/core';
4
- import { InjectionToken, inject, DestroyRef, ElementRef, ChangeDetectorRef, Injector, signal, output, computed, Input, Directive, viewChild, effect, EventEmitter, Output, Component, forwardRef, ChangeDetectionStrategy, ViewChild, Injectable, LOCALE_ID, ViewContainerRef, HostListener, HostBinding, ViewEncapsulation, ENVIRONMENT_INITIALIZER, Inject, ViewChildren, TemplateRef, ContentChild, APP_INITIALIZER, Optional } from '@angular/core';
4
+ import { InjectionToken, inject, DestroyRef, ElementRef, ChangeDetectorRef, Injector, signal, output, computed, Input, Directive, viewChild, effect, EventEmitter, Output, Component, forwardRef, LOCALE_ID, Injectable, ChangeDetectionStrategy, ViewChild, ViewContainerRef, HostListener, HostBinding, ViewEncapsulation, ENVIRONMENT_INITIALIZER, Inject, ViewChildren, TemplateRef, ContentChild, APP_INITIALIZER, Optional } from '@angular/core';
5
5
  import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
6
6
  import { providePraxisI18n, PraxisI18nService, isCssTextTransform, getTextTransformer, GlobalActionService, GenericCrudService, GlobalConfigService, PraxisIconDirective, FieldControlType, resolveBuiltinPresets, INLINE_FILTER_CONTROL_TYPES, FieldSelectorRegistry, FIELD_SELECTOR_REGISTRY_BASE, FIELD_SELECTOR_REGISTRY_DISABLE_DEFAULTS, LoggerService, normalizeControlTypeToken, resolveInlineFilterControlType, resolveControlTypeAlias, DEFAULT_FIELD_SELECTOR_CONTROL_TYPE_MAP, resolveValuePresentation, FieldDataType, DynamicFormService, classifyEntityLookupResult, ComponentMetadataRegistry, createCpfCnpjValidator, NumericFormat, interpolatePraxisTranslation, FIELD_METADATA_CAPABILITIES } from '@praxisui/core';
7
- import { BehaviorSubject, combineLatest, Subscription, of, EMPTY, fromEvent, take as take$1 } from 'rxjs';
7
+ import { BehaviorSubject, combineLatest, of, Subscription, EMPTY, fromEvent, take as take$1 } from 'rxjs';
8
8
  import { Router } from '@angular/router';
9
9
  import * as i1$3 from '@angular/material/dialog';
10
10
  import { MatDialog, MAT_DIALOG_DATA, MatDialogRef, MatDialogModule } from '@angular/material/dialog';
11
- import { take, startWith, debounceTime, distinctUntilChanged, switchMap, tap, catchError, filter } from 'rxjs/operators';
11
+ import { take, startWith, debounceTime, map, catchError, distinctUntilChanged, switchMap, tap, filter } from 'rxjs/operators';
12
12
  import * as i4$1 from '@angular/material/select';
13
13
  import { MatSelect, MatSelectModule } from '@angular/material/select';
14
14
  import * as i1 from '@angular/common';
@@ -28,7 +28,7 @@ import * as i1$2 from '@angular/material/button';
28
28
  import { MatIconButton, MatButtonModule } from '@angular/material/button';
29
29
  import * as i6 from '@angular/material/datepicker';
30
30
  import { MatDatepickerModule } from '@angular/material/datepicker';
31
- import { DateAdapter, MatNativeDateModule, provideNativeDateAdapter } from '@angular/material/core';
31
+ import { NativeDateAdapter, DateAdapter, MatNativeDateModule, MAT_NATIVE_DATE_FORMATS, MAT_DATE_FORMATS } from '@angular/material/core';
32
32
  import * as i2$2 from '@angular/cdk/overlay';
33
33
  import { CdkOverlayOrigin, CdkConnectedOverlay, OverlayModule } from '@angular/cdk/overlay';
34
34
  import * as i8 from '@angular/material/progress-spinner';
@@ -2847,6 +2847,11 @@ class SimpleBaseSelectComponent extends SimpleBaseInputComponent {
2847
2847
  this.registerMatSelect(select);
2848
2848
  }
2849
2849
  }, ...(ngDevMode ? [{ debugName: "matSelectInitEffect" }] : []));
2850
+ multipleControlNormalizationEffect = effect(() => {
2851
+ this.formControl();
2852
+ this.multiple();
2853
+ queueMicrotask(() => this.normalizeMultipleControlValue());
2854
+ }, ...(ngDevMode ? [{ debugName: "multipleControlNormalizationEffect" }] : []));
2850
2855
  /** CRUD service for remote option loading (optional) */
2851
2856
  crudService = inject(GenericCrudService, {
2852
2857
  optional: true,
@@ -2898,6 +2903,7 @@ class SimpleBaseSelectComponent extends SimpleBaseInputComponent {
2898
2903
  }
2899
2904
  const isMultiple = !!metadata.multiple;
2900
2905
  this.multiple.set(isMultiple);
2906
+ this.normalizeMultipleControlValue();
2901
2907
  this.searchable.set(!!metadata.searchable);
2902
2908
  this.selectAll.set(!!metadata.selectAll);
2903
2909
  this.maxSelections.set(metadata.maxSelections ?? null);
@@ -2984,7 +2990,12 @@ class SimpleBaseSelectComponent extends SimpleBaseInputComponent {
2984
2990
  select.selectionChange
2985
2991
  .pipe(takeUntilDestroyed(this.destroyRef))
2986
2992
  .subscribe((event) => {
2987
- this.selectionChange.emit(event.value);
2993
+ const value = event.value;
2994
+ this.selectionChange.emit(value);
2995
+ this.onChange(value);
2996
+ this.valueChange.emit(value);
2997
+ this.fieldState.update((state) => ({ ...state, value }));
2998
+ this.markAsDirty();
2988
2999
  });
2989
3000
  }
2990
3001
  applySelectAttributes() {
@@ -3067,6 +3078,23 @@ class SimpleBaseSelectComponent extends SimpleBaseInputComponent {
3067
3078
  this.isReadonlyEffective() ||
3068
3079
  !!this.presentationMode);
3069
3080
  }
3081
+ normalizeMultipleControlValue() {
3082
+ if (!this.multiple())
3083
+ return;
3084
+ const control = this.control();
3085
+ const current = control.value;
3086
+ if (Array.isArray(current))
3087
+ return;
3088
+ const normalized = current === null || current === undefined || current === ''
3089
+ ? []
3090
+ : [current];
3091
+ control.setValue(normalized, { emitEvent: false });
3092
+ this.fieldState.update((state) => ({ ...state, value: normalized }));
3093
+ }
3094
+ setExternalControl(control) {
3095
+ super.setExternalControl(control);
3096
+ this.normalizeMultipleControlValue();
3097
+ }
3070
3098
  /** Whether to show the clear button (if enabled in metadata) */
3071
3099
  showClear() {
3072
3100
  const cfg = this.metadata()?.clearButton;
@@ -3274,10 +3302,10 @@ class SimpleBaseSelectComponent extends SimpleBaseInputComponent {
3274
3302
  const current = Array.isArray(this.control().value)
3275
3303
  ? [...this.control().value]
3276
3304
  : [];
3277
- const exists = current.includes(option.value);
3305
+ const exists = current.some((value) => this.areOptionValuesEqual(value, option.value));
3278
3306
  if (exists) {
3279
3307
  // remove if already selected
3280
- const updated = current.filter((v) => v !== option.value);
3308
+ const updated = current.filter((value) => !this.areOptionValuesEqual(value, option.value));
3281
3309
  this.setValue(updated);
3282
3310
  }
3283
3311
  else {
@@ -3300,8 +3328,23 @@ class SimpleBaseSelectComponent extends SimpleBaseInputComponent {
3300
3328
  isSelected(value) {
3301
3329
  const current = this.control().value;
3302
3330
  return this.multiple()
3303
- ? Array.isArray(current) && current.includes(value)
3304
- : current === value;
3331
+ ? Array.isArray(current) && current.some((item) => this.areOptionValuesEqual(item, value))
3332
+ : this.areOptionValuesEqual(current, value);
3333
+ }
3334
+ isOptionDisabled(option) {
3335
+ if (option.disabled)
3336
+ return true;
3337
+ if (!this.multiple())
3338
+ return false;
3339
+ const max = this.maxSelections();
3340
+ if (!max || this.isSelected(option.value))
3341
+ return false;
3342
+ const current = this.control().value;
3343
+ const currentCount = Array.isArray(current) ? current.length : 0;
3344
+ return currentCount >= max;
3345
+ }
3346
+ areOptionValuesEqual(left, right) {
3347
+ return left === right;
3305
3348
  }
3306
3349
  /**
3307
3350
  * Toggles selection of all options when `selectAll` is enabled in multiple
@@ -6077,6 +6120,70 @@ function createMaterialCheckboxGroupComponentMetadata(locale = 'en-US') {
6077
6120
  return createWave1ComponentDocMeta(PDX_MATERIAL_CHECKBOX_GROUP_EDITORIAL_DESCRIPTOR, locale);
6078
6121
  }
6079
6122
 
6123
+ class PraxisNativeDateAdapter extends NativeDateAdapter {
6124
+ praxisLocale;
6125
+ constructor() {
6126
+ super();
6127
+ this.praxisLocale = inject(LOCALE_ID, { optional: true }) || 'en-US';
6128
+ this.setLocale(this.praxisLocale);
6129
+ }
6130
+ parse(value) {
6131
+ if (value == null || value === '') {
6132
+ return null;
6133
+ }
6134
+ if (Object.prototype.toString.call(value) === '[object Date]') {
6135
+ return value;
6136
+ }
6137
+ if (typeof value === 'number') {
6138
+ return new Date(value);
6139
+ }
6140
+ if (typeof value !== 'string') {
6141
+ return super.parse(value);
6142
+ }
6143
+ const text = value.trim();
6144
+ if (!text) {
6145
+ return null;
6146
+ }
6147
+ const iso = /^(\d{4})-(\d{1,2})-(\d{1,2})$/.exec(text);
6148
+ if (iso) {
6149
+ return this.createValidatedDate(Number(iso[1]), Number(iso[2]) - 1, Number(iso[3]));
6150
+ }
6151
+ const localized = /^(\d{1,2})[\/.-](\d{1,2})[\/.-](\d{2}|\d{4})$/.exec(text);
6152
+ if (localized) {
6153
+ const first = Number(localized[1]);
6154
+ const second = Number(localized[2]);
6155
+ const year = this.normalizeYear(Number(localized[3]));
6156
+ const dayFirst = !this.praxisLocale.toLowerCase().startsWith('en');
6157
+ const day = dayFirst ? first : second;
6158
+ const month = dayFirst ? second : first;
6159
+ return this.createValidatedDate(year, month - 1, day);
6160
+ }
6161
+ return super.parse(text);
6162
+ }
6163
+ normalizeYear(year) {
6164
+ if (year >= 100) {
6165
+ return year;
6166
+ }
6167
+ return year >= 70 ? 1900 + year : 2000 + year;
6168
+ }
6169
+ createValidatedDate(year, month, day) {
6170
+ if (!Number.isInteger(year) || !Number.isInteger(month) || !Number.isInteger(day)) {
6171
+ return null;
6172
+ }
6173
+ const parsed = new Date(year, month, day);
6174
+ return parsed.getFullYear() === year
6175
+ && parsed.getMonth() === month
6176
+ && parsed.getDate() === day
6177
+ ? parsed
6178
+ : null;
6179
+ }
6180
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: PraxisNativeDateAdapter, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
6181
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: PraxisNativeDateAdapter });
6182
+ }
6183
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: PraxisNativeDateAdapter, decorators: [{
6184
+ type: Injectable
6185
+ }], ctorParameters: () => [] });
6186
+
6080
6187
  class PraxisDateRangeShortcutsOverlayComponent {
6081
6188
  items = [];
6082
6189
  activeId = null;
@@ -6191,22 +6298,48 @@ class MaterialDateRangeComponent extends SimpleBaseInputComponent {
6191
6298
  }, ...(ngDevMode ? [{ debugName: "startAt" }] : []));
6192
6299
  // Overlay state
6193
6300
  overlayOpen = false;
6301
+ shortcutOverlayViewportMargin = 12;
6194
6302
  pickerOpen = false;
6195
6303
  dateAdapter = inject(DateAdapter);
6196
6304
  picker;
6305
+ endDateInput;
6197
6306
  shouldShowShortcuts = () => !!(this.metadata()?.showShortcuts);
6198
6307
  overlayPositions = () => {
6199
- const pos = this.metadata()?.shortcutsPosition ?? 'left';
6200
- return pos === 'left'
6201
- ? [
6202
- { originX: 'start', originY: 'top', overlayX: 'end', overlayY: 'top', offsetX: -8 },
6203
- { originX: 'start', originY: 'bottom', overlayX: 'end', overlayY: 'bottom', offsetX: -8 },
6204
- ]
6205
- : [
6206
- { originX: 'end', originY: 'top', overlayX: 'start', overlayY: 'top', offsetX: 8 },
6207
- { originX: 'end', originY: 'bottom', overlayX: 'start', overlayY: 'bottom', offsetX: 8 },
6208
- ];
6308
+ const preferredPosition = this.metadata()?.shortcutsPosition ?? 'auto';
6309
+ const below = this.shortcutOverlayBelowPositions();
6310
+ const left = this.shortcutOverlayLeftPositions();
6311
+ const right = this.shortcutOverlayRightPositions();
6312
+ switch (preferredPosition) {
6313
+ case 'left':
6314
+ return [...left, ...right, ...below];
6315
+ case 'right':
6316
+ return [...right, ...left, ...below];
6317
+ case 'below':
6318
+ case 'auto':
6319
+ default:
6320
+ return [...below, ...right, ...left];
6321
+ }
6209
6322
  };
6323
+ shortcutOverlayBelowPositions() {
6324
+ return [
6325
+ { originX: 'start', originY: 'bottom', overlayX: 'start', overlayY: 'top', offsetY: 8 },
6326
+ { originX: 'end', originY: 'bottom', overlayX: 'end', overlayY: 'top', offsetY: 8 },
6327
+ { originX: 'start', originY: 'top', overlayX: 'start', overlayY: 'bottom', offsetY: -8 },
6328
+ { originX: 'end', originY: 'top', overlayX: 'end', overlayY: 'bottom', offsetY: -8 },
6329
+ ];
6330
+ }
6331
+ shortcutOverlayLeftPositions() {
6332
+ return [
6333
+ { originX: 'start', originY: 'top', overlayX: 'end', overlayY: 'top', offsetX: -8 },
6334
+ { originX: 'start', originY: 'bottom', overlayX: 'end', overlayY: 'bottom', offsetX: -8 },
6335
+ ];
6336
+ }
6337
+ shortcutOverlayRightPositions() {
6338
+ return [
6339
+ { originX: 'end', originY: 'top', overlayX: 'start', overlayY: 'top', offsetX: 8 },
6340
+ { originX: 'end', originY: 'bottom', overlayX: 'start', overlayY: 'bottom', offsetX: 8 },
6341
+ ];
6342
+ }
6210
6343
  resolvedPresets = computed(() => {
6211
6344
  const md = this.metadata();
6212
6345
  return resolveBuiltinPresets(this.resolveAdapterLocale(), this.dateAdapter, {
@@ -6344,6 +6477,14 @@ class MaterialDateRangeComponent extends SimpleBaseInputComponent {
6344
6477
  shouldPropagateRangeGroupChanges() {
6345
6478
  return !this.pickerOpen;
6346
6479
  }
6480
+ focusEndDateInput(event) {
6481
+ const keyboardEvent = event;
6482
+ if (keyboardEvent.shiftKey || this.isReadonlyEffective()) {
6483
+ return;
6484
+ }
6485
+ keyboardEvent.preventDefault();
6486
+ this.endDateInput?.nativeElement.focus();
6487
+ }
6347
6488
  propagateRangeValue() {
6348
6489
  const { start, end } = this.rangeGroup.getRawValue();
6349
6490
  if (!start && !end) {
@@ -6552,12 +6693,14 @@ class MaterialDateRangeComponent extends SimpleBaseInputComponent {
6552
6693
  }
6553
6694
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: MaterialDateRangeComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
6554
6695
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.17", type: MaterialDateRangeComponent, isStandalone: true, selector: "pdx-material-date-range", inputs: { readonlyMode: "readonlyMode", disabledMode: "disabledMode", visible: "visible", presentationMode: "presentationMode", metadataInput: ["metadata", "metadataInput"] }, outputs: { validationChange: "validationChange" }, host: { properties: { "class": "componentCssClasses()", "class.praxis-disabled": "disabledMode", "style.display": "visible ? \"block\" : \"none\"", "attr.aria-hidden": "visible ? null : \"true\"", "style.width": "\"100%\"", "attr.data-field-type": "\"dateRange\"", "attr.data-field-name": "metadata()?.name", "attr.data-component-id": "componentId()" } }, providers: [
6696
+ { provide: DateAdapter, useClass: PraxisNativeDateAdapter },
6697
+ { provide: MAT_DATE_FORMATS, useValue: MAT_NATIVE_DATE_FORMATS },
6555
6698
  {
6556
6699
  provide: NG_VALUE_ACCESSOR,
6557
6700
  useExisting: forwardRef(() => MaterialDateRangeComponent),
6558
6701
  multi: true,
6559
6702
  },
6560
- ], viewQueries: [{ propertyName: "picker", first: true, predicate: ["picker"], descendants: true, static: true }], usesInheritance: true, ngImport: i0, template: `
6703
+ ], viewQueries: [{ propertyName: "picker", first: true, predicate: ["picker"], descendants: true, static: true }, { propertyName: "endDateInput", first: true, predicate: ["endDateInput"], descendants: true }], usesInheritance: true, ngImport: i0, template: `
6561
6704
  <div class="pdx-date-range-wrap" cdkOverlayOrigin #origin="cdkOverlayOrigin">
6562
6705
  <mat-form-field
6563
6706
  [appearance]="materialAppearance()"
@@ -6601,8 +6744,10 @@ class MaterialDateRangeComponent extends SimpleBaseInputComponent {
6601
6744
  ? metadata()?.startPlaceholder
6602
6745
  : null)
6603
6746
  "
6747
+ (keydown.tab)="focusEndDateInput($event)"
6604
6748
  />
6605
6749
  <input
6750
+ #endDateInput
6606
6751
  matEndDate
6607
6752
  formControlName="end"
6608
6753
  [attr.placeholder]="
@@ -6641,6 +6786,7 @@ class MaterialDateRangeComponent extends SimpleBaseInputComponent {
6641
6786
  [startAt]="startAt()"
6642
6787
  [touchUi]="metadata()?.touchUi || false"
6643
6788
  [color]="materialColor()"
6789
+ panelClass="pdx-datepicker-panel"
6644
6790
  ></mat-date-range-picker>
6645
6791
 
6646
6792
 
@@ -6682,6 +6828,8 @@ class MaterialDateRangeComponent extends SimpleBaseInputComponent {
6682
6828
  [cdkConnectedOverlayHasBackdrop]="true"
6683
6829
  [cdkConnectedOverlayBackdropClass]="'cdk-overlay-transparent-backdrop'"
6684
6830
  [cdkConnectedOverlayPositions]="overlayPositions()"
6831
+ [cdkConnectedOverlayPush]="true"
6832
+ [cdkConnectedOverlayViewportMargin]="shortcutOverlayViewportMargin"
6685
6833
  (backdropClick)="closeShortcuts()"
6686
6834
  (detach)="onOverlayDetach()"
6687
6835
  >
@@ -6693,15 +6841,11 @@ class MaterialDateRangeComponent extends SimpleBaseInputComponent {
6693
6841
  </ng-template>
6694
6842
  }
6695
6843
  </div>
6696
- `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2.MatLabel, selector: "mat-label" }, { kind: "directive", type: i2.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "directive", type: i2.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "directive", type: i2.MatPrefix, selector: "[matPrefix], [matIconPrefix], [matTextPrefix]", inputs: ["matTextPrefix"] }, { kind: "directive", type: i2.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatDatepickerModule }, { kind: "component", type: i6.MatDatepickerToggle, selector: "mat-datepicker-toggle", inputs: ["for", "tabIndex", "aria-label", "disabled", "disableRipple"], exportAs: ["matDatepickerToggle"] }, { kind: "component", type: i6.MatDateRangeInput, selector: "mat-date-range-input", inputs: ["rangePicker", "required", "dateFilter", "min", "max", "disabled", "separator", "comparisonStart", "comparisonEnd"], exportAs: ["matDateRangeInput"] }, { kind: "directive", type: i6.MatStartDate, selector: "input[matStartDate]", outputs: ["dateChange", "dateInput"] }, { kind: "directive", type: i6.MatEndDate, selector: "input[matEndDate]", outputs: ["dateChange", "dateInput"] }, { kind: "component", type: i6.MatDateRangePicker, selector: "mat-date-range-picker", exportAs: ["matDateRangePicker"] }, { kind: "ngmodule", type: MatNativeDateModule }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i5.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "directive", type: CdkOverlayOrigin, selector: "[cdk-overlay-origin], [overlay-origin], [cdkOverlayOrigin]", exportAs: ["cdkOverlayOrigin"] }, { kind: "directive", type: CdkConnectedOverlay, selector: "[cdk-connected-overlay], [connected-overlay], [cdkConnectedOverlay]", inputs: ["cdkConnectedOverlayOrigin", "cdkConnectedOverlayPositions", "cdkConnectedOverlayPositionStrategy", "cdkConnectedOverlayOffsetX", "cdkConnectedOverlayOffsetY", "cdkConnectedOverlayWidth", "cdkConnectedOverlayHeight", "cdkConnectedOverlayMinWidth", "cdkConnectedOverlayMinHeight", "cdkConnectedOverlayBackdropClass", "cdkConnectedOverlayPanelClass", "cdkConnectedOverlayViewportMargin", "cdkConnectedOverlayScrollStrategy", "cdkConnectedOverlayOpen", "cdkConnectedOverlayDisableClose", "cdkConnectedOverlayTransformOriginOn", "cdkConnectedOverlayHasBackdrop", "cdkConnectedOverlayLockPosition", "cdkConnectedOverlayFlexibleDimensions", "cdkConnectedOverlayGrowAfterOpen", "cdkConnectedOverlayPush", "cdkConnectedOverlayDisposeOnNavigation"], outputs: ["backdropClick", "positionChange", "attach", "detach", "overlayKeydown", "overlayOutsideClick"], exportAs: ["cdkConnectedOverlay"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.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: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: PraxisDateRangeShortcutsOverlayComponent, selector: "pdx-date-range-shortcuts-overlay", inputs: ["items", "activeId"], outputs: ["selectPreset"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
6844
+ `, isInline: true, styles: ["::ng-deep .cdk-overlay-connected-position-bounding-box:has(.pdx-datepicker-panel){z-index:var(--praxis-layer-popup, 1400)!important}::ng-deep .cdk-overlay-pane:has(.pdx-datepicker-panel){z-index:var(--praxis-layer-popup, 1400)!important}@media(min-width:600px){::ng-deep .cdk-overlay-pane.mat-datepicker-dialog{position:fixed!important;top:50%!important;left:50%!important;transform:translate(-50%,-50%)!important;max-width:calc(100vw - 32px)!important;max-height:calc(100vh - 96px)!important}::ng-deep .cdk-overlay-pane.mat-datepicker-dialog .mat-datepicker-content-touch,::ng-deep .pdx-datepicker-panel.mat-datepicker-content-touch{width:min(360px,calc(100vw - 32px))!important;height:auto!important;max-height:calc(100vh - 96px)!important}::ng-deep .cdk-overlay-pane.mat-datepicker-dialog .mat-datepicker-content-container,::ng-deep .cdk-overlay-pane.mat-datepicker-dialog .mat-calendar,::ng-deep .pdx-datepicker-panel.mat-datepicker-content-touch .mat-datepicker-content-container,::ng-deep .pdx-datepicker-panel.mat-datepicker-content-touch .mat-calendar{width:100%!important;height:auto!important;max-height:calc(100vh - 120px)!important}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2.MatLabel, selector: "mat-label" }, { kind: "directive", type: i2.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "directive", type: i2.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "directive", type: i2.MatPrefix, selector: "[matPrefix], [matIconPrefix], [matTextPrefix]", inputs: ["matTextPrefix"] }, { kind: "directive", type: i2.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatDatepickerModule }, { kind: "component", type: i6.MatDatepickerToggle, selector: "mat-datepicker-toggle", inputs: ["for", "tabIndex", "aria-label", "disabled", "disableRipple"], exportAs: ["matDatepickerToggle"] }, { kind: "component", type: i6.MatDateRangeInput, selector: "mat-date-range-input", inputs: ["rangePicker", "required", "dateFilter", "min", "max", "disabled", "separator", "comparisonStart", "comparisonEnd"], exportAs: ["matDateRangeInput"] }, { kind: "directive", type: i6.MatStartDate, selector: "input[matStartDate]", outputs: ["dateChange", "dateInput"] }, { kind: "directive", type: i6.MatEndDate, selector: "input[matEndDate]", outputs: ["dateChange", "dateInput"] }, { kind: "component", type: i6.MatDateRangePicker, selector: "mat-date-range-picker", exportAs: ["matDateRangePicker"] }, { kind: "ngmodule", type: MatNativeDateModule }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i5.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "directive", type: CdkOverlayOrigin, selector: "[cdk-overlay-origin], [overlay-origin], [cdkOverlayOrigin]", exportAs: ["cdkOverlayOrigin"] }, { kind: "directive", type: CdkConnectedOverlay, selector: "[cdk-connected-overlay], [connected-overlay], [cdkConnectedOverlay]", inputs: ["cdkConnectedOverlayOrigin", "cdkConnectedOverlayPositions", "cdkConnectedOverlayPositionStrategy", "cdkConnectedOverlayOffsetX", "cdkConnectedOverlayOffsetY", "cdkConnectedOverlayWidth", "cdkConnectedOverlayHeight", "cdkConnectedOverlayMinWidth", "cdkConnectedOverlayMinHeight", "cdkConnectedOverlayBackdropClass", "cdkConnectedOverlayPanelClass", "cdkConnectedOverlayViewportMargin", "cdkConnectedOverlayScrollStrategy", "cdkConnectedOverlayOpen", "cdkConnectedOverlayDisableClose", "cdkConnectedOverlayTransformOriginOn", "cdkConnectedOverlayHasBackdrop", "cdkConnectedOverlayLockPosition", "cdkConnectedOverlayFlexibleDimensions", "cdkConnectedOverlayGrowAfterOpen", "cdkConnectedOverlayPush", "cdkConnectedOverlayDisposeOnNavigation"], outputs: ["backdropClick", "positionChange", "attach", "detach", "overlayKeydown", "overlayOutsideClick"], exportAs: ["cdkConnectedOverlay"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.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: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: PraxisDateRangeShortcutsOverlayComponent, selector: "pdx-date-range-shortcuts-overlay", inputs: ["items", "activeId"], outputs: ["selectPreset"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
6697
6845
  }
6698
6846
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: MaterialDateRangeComponent, decorators: [{
6699
6847
  type: Component,
6700
- args: [{
6701
- selector: 'pdx-material-date-range',
6702
- standalone: true,
6703
- changeDetection: ChangeDetectionStrategy.OnPush,
6704
- template: `
6848
+ args: [{ selector: 'pdx-material-date-range', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: `
6705
6849
  <div class="pdx-date-range-wrap" cdkOverlayOrigin #origin="cdkOverlayOrigin">
6706
6850
  <mat-form-field
6707
6851
  [appearance]="materialAppearance()"
@@ -6745,8 +6889,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
6745
6889
  ? metadata()?.startPlaceholder
6746
6890
  : null)
6747
6891
  "
6892
+ (keydown.tab)="focusEndDateInput($event)"
6748
6893
  />
6749
6894
  <input
6895
+ #endDateInput
6750
6896
  matEndDate
6751
6897
  formControlName="end"
6752
6898
  [attr.placeholder]="
@@ -6785,6 +6931,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
6785
6931
  [startAt]="startAt()"
6786
6932
  [touchUi]="metadata()?.touchUi || false"
6787
6933
  [color]="materialColor()"
6934
+ panelClass="pdx-datepicker-panel"
6788
6935
  ></mat-date-range-picker>
6789
6936
 
6790
6937
 
@@ -6826,6 +6973,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
6826
6973
  [cdkConnectedOverlayHasBackdrop]="true"
6827
6974
  [cdkConnectedOverlayBackdropClass]="'cdk-overlay-transparent-backdrop'"
6828
6975
  [cdkConnectedOverlayPositions]="overlayPositions()"
6976
+ [cdkConnectedOverlayPush]="true"
6977
+ [cdkConnectedOverlayViewportMargin]="shortcutOverlayViewportMargin"
6829
6978
  (backdropClick)="closeShortcuts()"
6830
6979
  (detach)="onOverlayDetach()"
6831
6980
  >
@@ -6837,8 +6986,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
6837
6986
  </ng-template>
6838
6987
  }
6839
6988
  </div>
6840
- `,
6841
- imports: [
6989
+ `, imports: [
6842
6990
  CommonModule,
6843
6991
  MatFormFieldModule,
6844
6992
  MatInputModule,
@@ -6852,15 +7000,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
6852
7000
  PraxisIconDirective,
6853
7001
  ReactiveFormsModule,
6854
7002
  PraxisDateRangeShortcutsOverlayComponent,
6855
- ],
6856
- providers: [
7003
+ ], providers: [
7004
+ { provide: DateAdapter, useClass: PraxisNativeDateAdapter },
7005
+ { provide: MAT_DATE_FORMATS, useValue: MAT_NATIVE_DATE_FORMATS },
6857
7006
  {
6858
7007
  provide: NG_VALUE_ACCESSOR,
6859
7008
  useExisting: forwardRef(() => MaterialDateRangeComponent),
6860
7009
  multi: true,
6861
7010
  },
6862
- ],
6863
- host: {
7011
+ ], host: {
6864
7012
  '[class]': 'componentCssClasses()',
6865
7013
  '[class.praxis-disabled]': 'disabledMode',
6866
7014
  '[style.display]': 'visible ? "block" : "none"',
@@ -6869,8 +7017,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
6869
7017
  '[attr.data-field-type]': '"dateRange"',
6870
7018
  '[attr.data-field-name]': 'metadata()?.name',
6871
7019
  '[attr.data-component-id]': 'componentId()',
6872
- },
6873
- }]
7020
+ }, styles: ["::ng-deep .cdk-overlay-connected-position-bounding-box:has(.pdx-datepicker-panel){z-index:var(--praxis-layer-popup, 1400)!important}::ng-deep .cdk-overlay-pane:has(.pdx-datepicker-panel){z-index:var(--praxis-layer-popup, 1400)!important}@media(min-width:600px){::ng-deep .cdk-overlay-pane.mat-datepicker-dialog{position:fixed!important;top:50%!important;left:50%!important;transform:translate(-50%,-50%)!important;max-width:calc(100vw - 32px)!important;max-height:calc(100vh - 96px)!important}::ng-deep .cdk-overlay-pane.mat-datepicker-dialog .mat-datepicker-content-touch,::ng-deep .pdx-datepicker-panel.mat-datepicker-content-touch{width:min(360px,calc(100vw - 32px))!important;height:auto!important;max-height:calc(100vh - 96px)!important}::ng-deep .cdk-overlay-pane.mat-datepicker-dialog .mat-datepicker-content-container,::ng-deep .cdk-overlay-pane.mat-datepicker-dialog .mat-calendar,::ng-deep .pdx-datepicker-panel.mat-datepicker-content-touch .mat-datepicker-content-container,::ng-deep .pdx-datepicker-panel.mat-datepicker-content-touch .mat-calendar{width:100%!important;height:auto!important;max-height:calc(100vh - 120px)!important}}\n"] }]
6874
7021
  }], propDecorators: { validationChange: [{ type: i0.Output, args: ["validationChange"] }], readonlyMode: [{
6875
7022
  type: Input
6876
7023
  }], disabledMode: [{
@@ -6885,6 +7032,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
6885
7032
  }], picker: [{
6886
7033
  type: ViewChild,
6887
7034
  args: ['picker', { static: true }]
7035
+ }], endDateInput: [{
7036
+ type: ViewChild,
7037
+ args: ['endDateInput']
6888
7038
  }] } });
6889
7039
 
6890
7040
  const PDX_MATERIAL_DATE_RANGE_EDITORIAL_DESCRIPTOR = {
@@ -7016,7 +7166,8 @@ class MaterialDatepickerComponent extends SimpleBaseInputComponent {
7016
7166
  }
7017
7167
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: MaterialDatepickerComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
7018
7168
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.17", type: MaterialDatepickerComponent, isStandalone: true, selector: "pdx-material-datepicker", inputs: { readonlyMode: "readonlyMode", disabledMode: "disabledMode", visible: "visible", presentationMode: "presentationMode" }, outputs: { validationChange: "validationChange" }, host: { properties: { "class": "componentCssClasses()", "class.praxis-disabled": "disabledMode", "style.display": "visible ? null : \"none\"", "attr.aria-hidden": "visible ? null : \"true\"", "attr.data-field-type": "\"date\"", "attr.data-field-name": "metadata()?.name", "attr.data-component-id": "componentId()" } }, providers: [
7019
- provideNativeDateAdapter(),
7169
+ { provide: DateAdapter, useClass: PraxisNativeDateAdapter },
7170
+ { provide: MAT_DATE_FORMATS, useValue: MAT_NATIVE_DATE_FORMATS },
7020
7171
  {
7021
7172
  provide: NG_VALUE_ACCESSOR,
7022
7173
  useExisting: forwardRef(() => MaterialDatepickerComponent),
@@ -7109,7 +7260,7 @@ class MaterialDatepickerComponent extends SimpleBaseInputComponent {
7109
7260
  </mat-hint>
7110
7261
  }
7111
7262
  </mat-form-field>
7112
- `, isInline: true, styles: ["::ng-deep .cdk-overlay-connected-position-bounding-box:has(.pdx-datepicker-panel){z-index:var(--praxis-layer-popup, 1400)!important}::ng-deep .cdk-overlay-pane:has(.pdx-datepicker-panel){z-index:var(--praxis-layer-popup, 1400)!important}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2.MatLabel, selector: "mat-label" }, { kind: "directive", type: i2.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "directive", type: i2.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "directive", type: i2.MatPrefix, selector: "[matPrefix], [matIconPrefix], [matTextPrefix]", inputs: ["matTextPrefix"] }, { kind: "directive", type: i2.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i3$1.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: MatIconModule }, { kind: "component", type: i4.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i1$2.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatDatepickerModule }, { kind: "component", type: i6.MatDatepicker, selector: "mat-datepicker", exportAs: ["matDatepicker"] }, { kind: "directive", type: i6.MatDatepickerInput, selector: "input[matDatepicker]", inputs: ["matDatepicker", "min", "max", "matDatepickerFilter"], exportAs: ["matDatepickerInput"] }, { kind: "component", type: i6.MatDatepickerToggle, selector: "mat-datepicker-toggle", inputs: ["for", "tabIndex", "aria-label", "disabled", "disableRipple"], exportAs: ["matDatepickerToggle"] }, { kind: "ngmodule", type: MatNativeDateModule }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i5.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.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: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }] });
7263
+ `, isInline: true, styles: ["::ng-deep .cdk-overlay-connected-position-bounding-box:has(.pdx-datepicker-panel){z-index:var(--praxis-layer-popup, 1400)!important}::ng-deep .cdk-overlay-pane:has(.pdx-datepicker-panel){z-index:var(--praxis-layer-popup, 1400)!important}@media(min-width:600px){::ng-deep .cdk-overlay-pane.mat-datepicker-dialog{position:fixed!important;top:50%!important;left:50%!important;transform:translate(-50%,-50%)!important;max-width:calc(100vw - 32px)!important;max-height:calc(100vh - 96px)!important}::ng-deep .cdk-overlay-pane.mat-datepicker-dialog .mat-datepicker-content-touch,::ng-deep .pdx-datepicker-panel.mat-datepicker-content-touch{width:min(360px,calc(100vw - 32px))!important;height:auto!important;max-height:calc(100vh - 96px)!important}::ng-deep .cdk-overlay-pane.mat-datepicker-dialog .mat-datepicker-content-container,::ng-deep .cdk-overlay-pane.mat-datepicker-dialog .mat-calendar,::ng-deep .pdx-datepicker-panel.mat-datepicker-content-touch .mat-datepicker-content-container,::ng-deep .pdx-datepicker-panel.mat-datepicker-content-touch .mat-calendar{width:100%!important;height:auto!important;max-height:calc(100vh - 120px)!important}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2.MatLabel, selector: "mat-label" }, { kind: "directive", type: i2.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "directive", type: i2.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "directive", type: i2.MatPrefix, selector: "[matPrefix], [matIconPrefix], [matTextPrefix]", inputs: ["matTextPrefix"] }, { kind: "directive", type: i2.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i3$1.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: MatIconModule }, { kind: "component", type: i4.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i1$2.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatDatepickerModule }, { kind: "component", type: i6.MatDatepicker, selector: "mat-datepicker", exportAs: ["matDatepicker"] }, { kind: "directive", type: i6.MatDatepickerInput, selector: "input[matDatepicker]", inputs: ["matDatepicker", "min", "max", "matDatepickerFilter"], exportAs: ["matDatepickerInput"] }, { kind: "component", type: i6.MatDatepickerToggle, selector: "mat-datepicker-toggle", inputs: ["for", "tabIndex", "aria-label", "disabled", "disableRipple"], exportAs: ["matDatepickerToggle"] }, { kind: "ngmodule", type: MatNativeDateModule }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i5.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.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: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }] });
7113
7264
  }
7114
7265
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: MaterialDatepickerComponent, decorators: [{
7115
7266
  type: Component,
@@ -7212,7 +7363,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
7212
7363
  PraxisIconDirective,
7213
7364
  ReactiveFormsModule,
7214
7365
  ], providers: [
7215
- provideNativeDateAdapter(),
7366
+ { provide: DateAdapter, useClass: PraxisNativeDateAdapter },
7367
+ { provide: MAT_DATE_FORMATS, useValue: MAT_NATIVE_DATE_FORMATS },
7216
7368
  {
7217
7369
  provide: NG_VALUE_ACCESSOR,
7218
7370
  useExisting: forwardRef(() => MaterialDatepickerComponent),
@@ -7226,7 +7378,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
7226
7378
  '[attr.data-field-type]': '"date"',
7227
7379
  '[attr.data-field-name]': 'metadata()?.name',
7228
7380
  '[attr.data-component-id]': 'componentId()',
7229
- }, styles: ["::ng-deep .cdk-overlay-connected-position-bounding-box:has(.pdx-datepicker-panel){z-index:var(--praxis-layer-popup, 1400)!important}::ng-deep .cdk-overlay-pane:has(.pdx-datepicker-panel){z-index:var(--praxis-layer-popup, 1400)!important}\n"] }]
7381
+ }, styles: ["::ng-deep .cdk-overlay-connected-position-bounding-box:has(.pdx-datepicker-panel){z-index:var(--praxis-layer-popup, 1400)!important}::ng-deep .cdk-overlay-pane:has(.pdx-datepicker-panel){z-index:var(--praxis-layer-popup, 1400)!important}@media(min-width:600px){::ng-deep .cdk-overlay-pane.mat-datepicker-dialog{position:fixed!important;top:50%!important;left:50%!important;transform:translate(-50%,-50%)!important;max-width:calc(100vw - 32px)!important;max-height:calc(100vh - 96px)!important}::ng-deep .cdk-overlay-pane.mat-datepicker-dialog .mat-datepicker-content-touch,::ng-deep .pdx-datepicker-panel.mat-datepicker-content-touch{width:min(360px,calc(100vw - 32px))!important;height:auto!important;max-height:calc(100vh - 96px)!important}::ng-deep .cdk-overlay-pane.mat-datepicker-dialog .mat-datepicker-content-container,::ng-deep .cdk-overlay-pane.mat-datepicker-dialog .mat-calendar,::ng-deep .pdx-datepicker-panel.mat-datepicker-content-touch .mat-datepicker-content-container,::ng-deep .pdx-datepicker-panel.mat-datepicker-content-touch .mat-calendar{width:100%!important;height:auto!important;max-height:calc(100vh - 120px)!important}}\n"] }]
7230
7382
  }], propDecorators: { validationChange: [{ type: i0.Output, args: ["validationChange"] }], readonlyMode: [{
7231
7383
  type: Input
7232
7384
  }], disabledMode: [{
@@ -8066,6 +8218,12 @@ function formatDisplayValue(field, value, options) {
8066
8218
  const trimmed = value.trim();
8067
8219
  if (!trimmed)
8068
8220
  return EMPTY_DISPLAY;
8221
+ if (presentation && presentation.type !== 'string') {
8222
+ return formatTypedValue(field, trimmed, presentation);
8223
+ }
8224
+ const documentIdentifier = formatDocumentIdentifierValue(field, trimmed);
8225
+ if (documentIdentifier)
8226
+ return documentIdentifier;
8069
8227
  if (presentation) {
8070
8228
  return formatTypedValue(field, trimmed, presentation);
8071
8229
  }
@@ -8171,6 +8329,77 @@ function formatCurrencyBoundary(field, value, options) {
8171
8329
  return `${currency} ${formatCompactNumber(value)}`;
8172
8330
  }
8173
8331
  }
8332
+ function formatDocumentIdentifierValue(field, value) {
8333
+ if (/[a-z]/i.test(value))
8334
+ return null;
8335
+ const digits = value.replace(/\D/g, '');
8336
+ const kind = inferDocumentIdentifierKind(field, digits.length);
8337
+ if (kind === 'cpf' && digits.length === 11) {
8338
+ return formatCpfIdentifier(digits);
8339
+ }
8340
+ if (kind === 'cnpj' && digits.length === 14) {
8341
+ return formatCnpjIdentifier(digits);
8342
+ }
8343
+ return null;
8344
+ }
8345
+ function formatCpfIdentifier(digits) {
8346
+ return `${digits.slice(0, 3)}.${digits.slice(3, 6)}.${digits.slice(6, 9)}-${digits.slice(9)}`;
8347
+ }
8348
+ function formatCnpjIdentifier(digits) {
8349
+ return `${digits.slice(0, 2)}.${digits.slice(2, 5)}.${digits.slice(5, 8)}/${digits.slice(8, 12)}-${digits.slice(12)}`;
8350
+ }
8351
+ function inferDocumentIdentifierKind(field, digitsLength) {
8352
+ const controlType = normalizeComparableString(field?.controlType);
8353
+ const valuePresentationType = normalizeComparableString(field?.valuePresentation?.type);
8354
+ const documentKind = normalizeComparableString(field?.documentKind) ||
8355
+ normalizeComparableString(field?.documentType) ||
8356
+ normalizeComparableString(field?.identifierKind) ||
8357
+ normalizeComparableString(field?.identifierType);
8358
+ const signals = [
8359
+ field?.name,
8360
+ field?.id,
8361
+ field?.key,
8362
+ field?.label,
8363
+ field?.placeholder,
8364
+ field?.format,
8365
+ field?.mask,
8366
+ field?.inputMask,
8367
+ field?.pattern,
8368
+ field?.valuePresentation?.format,
8369
+ field?.valuePresentation?.mask,
8370
+ ]
8371
+ .map(normalizeComparableString)
8372
+ .filter(Boolean)
8373
+ .join('|');
8374
+ if (documentKind === 'cpf')
8375
+ return 'cpf';
8376
+ if (documentKind === 'cnpj')
8377
+ return 'cnpj';
8378
+ if (hasDocumentSignal(controlType, 'cpf') ||
8379
+ hasDocumentSignal(valuePresentationType, 'cpf') ||
8380
+ hasDocumentSignal(signals, 'cpf')) {
8381
+ return 'cpf';
8382
+ }
8383
+ if (hasDocumentSignal(controlType, 'cnpj') ||
8384
+ hasDocumentSignal(valuePresentationType, 'cnpj') ||
8385
+ hasDocumentSignal(signals, 'cnpj')) {
8386
+ return 'cnpj';
8387
+ }
8388
+ if (controlType === 'document' ||
8389
+ controlType === 'documentidentifier' ||
8390
+ controlType === 'documentid' ||
8391
+ valuePresentationType === 'document' ||
8392
+ valuePresentationType === 'documentidentifier') {
8393
+ if (digitsLength === 11)
8394
+ return 'cpf';
8395
+ if (digitsLength === 14)
8396
+ return 'cnpj';
8397
+ }
8398
+ return null;
8399
+ }
8400
+ function hasDocumentSignal(value, token) {
8401
+ return Boolean(value?.includes(token));
8402
+ }
8174
8403
  /**
8175
8404
  * Formats a value for presentation and linkifies emails/URLs.
8176
8405
  * Rely on Angular's built-in sanitization when binding via [innerHTML].
@@ -8568,6 +8797,9 @@ function normalizeString(value) {
8568
8797
  const trimmed = value.trim();
8569
8798
  return trimmed ? trimmed : undefined;
8570
8799
  }
8800
+ function normalizeComparableString(value) {
8801
+ return normalizeString(value)?.trim().toLowerCase().replace(/[\s_-]+/g, '');
8802
+ }
8571
8803
  function coerceDateValue(value, type) {
8572
8804
  if (value instanceof Date) {
8573
8805
  return value;
@@ -8607,6 +8839,210 @@ function coerceDateOnlyCalendarValue(value) {
8607
8839
  return coerceDateValue(value, 'date');
8608
8840
  }
8609
8841
 
8842
+ class OptionDisplayResolverService {
8843
+ resolve(field, rawValue, crudService) {
8844
+ if (!field || rawValue === null || rawValue === undefined || rawValue === '') {
8845
+ return of(null);
8846
+ }
8847
+ const objectLabel = this.resolveObjectLabel(rawValue);
8848
+ if (objectLabel) {
8849
+ return of(objectLabel);
8850
+ }
8851
+ const local = this.resolveFromLocalOptions(field, rawValue);
8852
+ if (local !== null) {
8853
+ return of(local);
8854
+ }
8855
+ if (!crudService || !this.shouldResolveRemotely(field)) {
8856
+ return of(null);
8857
+ }
8858
+ const ids = this.extractIds(field, rawValue);
8859
+ if (!ids.length) {
8860
+ return of(null);
8861
+ }
8862
+ const resourcePath = this.resolveResourcePath(field);
8863
+ if (!resourcePath) {
8864
+ return of(null);
8865
+ }
8866
+ try {
8867
+ crudService.configure(resourcePath);
8868
+ }
8869
+ catch {
8870
+ return of(null);
8871
+ }
8872
+ const optionSource = field.optionSource;
8873
+ const request$ = optionSource?.key
8874
+ ? crudService.getOptionSourceOptionsByIds(optionSource.key, ids)
8875
+ : crudService.getOptionsByIds(ids);
8876
+ return request$.pipe(map((options) => this.joinRemoteLabels(ids, options)), catchError(() => this.resolveRemoteByFilter(field, rawValue, ids, crudService)));
8877
+ }
8878
+ resolveFromLocalOptions(field, rawValue) {
8879
+ const options = this.localOptions(field);
8880
+ if (!options.length) {
8881
+ return null;
8882
+ }
8883
+ const values = Array.isArray(rawValue) ? rawValue : [rawValue];
8884
+ const labels = values
8885
+ .map((value) => {
8886
+ const directLabel = this.resolveObjectLabel(value);
8887
+ if (directLabel) {
8888
+ return directLabel;
8889
+ }
8890
+ const option = options.find((candidate) => this.areValuesEqual(candidate.value, this.extractId(field, value)));
8891
+ return option?.label?.trim() || '';
8892
+ })
8893
+ .filter(Boolean);
8894
+ return labels.length ? labels.join(', ') : null;
8895
+ }
8896
+ resolveRemoteByFilter(field, rawValue, ids, crudService) {
8897
+ const filter = {};
8898
+ const labelKey = this.optionLabelKey(field);
8899
+ const valueKey = this.optionValueKey(field);
8900
+ const includeIds = ids.length ? { includeIds: ids } : undefined;
8901
+ return crudService
8902
+ .filter(filter, { pageNumber: 0, pageSize: Math.max(ids.length, 1) }, includeIds)
8903
+ .pipe(map((page) => {
8904
+ const content = Array.isArray(page?.content) ? page.content : [];
8905
+ const options = content.map((item) => ({
8906
+ id: item?.[valueKey],
8907
+ label: item?.[labelKey],
8908
+ }));
8909
+ return this.joinRemoteLabels(ids, options);
8910
+ }), catchError(() => of(this.resolveFromLocalOptions(field, rawValue))));
8911
+ }
8912
+ localOptions(field) {
8913
+ const source = field.selectOptions ?? field.options;
8914
+ if (!Array.isArray(source)) {
8915
+ return [];
8916
+ }
8917
+ return source
8918
+ .map((option) => {
8919
+ const value = option?.value ?? option?.key ?? option?.id;
8920
+ const label = option?.label ?? option?.text ?? option?.value;
8921
+ return {
8922
+ value,
8923
+ label: label === null || label === undefined ? '' : String(label),
8924
+ };
8925
+ })
8926
+ .filter((option) => option.label.trim().length > 0);
8927
+ }
8928
+ shouldResolveRemotely(field) {
8929
+ if (field.optionSource) {
8930
+ return true;
8931
+ }
8932
+ if (!this.isSelectionControl(field) && !this.hasOptionBinding(field)) {
8933
+ return false;
8934
+ }
8935
+ return !!this.resolveResourcePath(field);
8936
+ }
8937
+ hasOptionBinding(field) {
8938
+ return !!(field.endpoint ||
8939
+ field.resourcePath ||
8940
+ field.valueField ||
8941
+ field.displayField ||
8942
+ field.optionValueKey ||
8943
+ field.optionLabelKey);
8944
+ }
8945
+ isSelectionControl(field) {
8946
+ const controlType = String(field.controlType ?? '')
8947
+ .trim()
8948
+ .toLowerCase()
8949
+ .replace(/_/g, '-');
8950
+ return (controlType.includes('select') ||
8951
+ controlType.includes('autocomplete') ||
8952
+ controlType.includes('lookup') ||
8953
+ controlType.includes('selection-list') ||
8954
+ controlType.includes('transfer-list') ||
8955
+ controlType.includes('checkbox-group') ||
8956
+ controlType.includes('radio-group') ||
8957
+ controlType.includes('chips') ||
8958
+ controlType.includes('button-toggle'));
8959
+ }
8960
+ resolveResourcePath(field) {
8961
+ const optionSource = field.optionSource;
8962
+ const raw = optionSource?.resourcePath ??
8963
+ field.resourcePath ??
8964
+ field.endpoint ??
8965
+ null;
8966
+ if (!raw || typeof raw !== 'string') {
8967
+ return null;
8968
+ }
8969
+ return raw
8970
+ .trim()
8971
+ .replace(/\/options\/filter\/?$/i, '')
8972
+ .replace(/\/filter\/?$/i, '');
8973
+ }
8974
+ extractIds(field, rawValue) {
8975
+ const values = Array.isArray(rawValue) ? rawValue : [rawValue];
8976
+ return values
8977
+ .map((value) => this.extractId(field, value))
8978
+ .filter((value) => typeof value === 'string' || typeof value === 'number')
8979
+ .filter((value) => String(value).trim().length > 0);
8980
+ }
8981
+ extractId(field, value) {
8982
+ if (value && typeof value === 'object') {
8983
+ const obj = value;
8984
+ const valueKey = this.optionValueKey(field);
8985
+ return obj[valueKey] ?? obj['id'] ?? obj['value'];
8986
+ }
8987
+ return value;
8988
+ }
8989
+ resolveObjectLabel(value) {
8990
+ if (Array.isArray(value)) {
8991
+ const labels = value
8992
+ .map((entry) => this.resolveObjectLabel(entry))
8993
+ .filter((entry) => !!entry);
8994
+ return labels.length ? labels.join(', ') : null;
8995
+ }
8996
+ if (!value || typeof value !== 'object') {
8997
+ return null;
8998
+ }
8999
+ const obj = value;
9000
+ const label = obj['label'] ?? obj['text'] ?? obj['name'] ?? obj['title'];
9001
+ return label === null || label === undefined ? null : String(label);
9002
+ }
9003
+ joinRemoteLabels(ids, options) {
9004
+ const labels = ids
9005
+ .map((id) => {
9006
+ const option = options.find((candidate) => this.areValuesEqual(candidate?.id, id));
9007
+ const label = option?.label;
9008
+ return label === null || label === undefined ? '' : String(label);
9009
+ })
9010
+ .filter((label) => label.trim().length > 0);
9011
+ return labels.length ? labels.join(', ') : null;
9012
+ }
9013
+ optionLabelKey(field) {
9014
+ return (field.optionLabelKey ??
9015
+ field.displayField ??
9016
+ 'label');
9017
+ }
9018
+ optionValueKey(field) {
9019
+ return (field.optionValueKey ??
9020
+ field.valueField ??
9021
+ 'id');
9022
+ }
9023
+ areValuesEqual(left, right) {
9024
+ if (left === right) {
9025
+ return true;
9026
+ }
9027
+ if ((typeof left === 'string' || typeof left === 'number') &&
9028
+ (typeof right === 'string' || typeof right === 'number')) {
9029
+ return String(left) === String(right);
9030
+ }
9031
+ try {
9032
+ return JSON.stringify(left) === JSON.stringify(right);
9033
+ }
9034
+ catch {
9035
+ return false;
9036
+ }
9037
+ }
9038
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: OptionDisplayResolverService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
9039
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: OptionDisplayResolverService, providedIn: 'root' });
9040
+ }
9041
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: OptionDisplayResolverService, decorators: [{
9042
+ type: Injectable,
9043
+ args: [{ providedIn: 'root' }]
9044
+ }] });
9045
+
8610
9046
  /**
8611
9047
  * Internal wrapper used by {@link DynamicFieldLoaderDirective}.
8612
9048
  *
@@ -8616,27 +9052,60 @@ function coerceDateOnlyCalendarValue(value) {
8616
9052
  */
8617
9053
  class FieldShellComponent {
8618
9054
  hostLocale = inject(LOCALE_ID, { optional: true }) ?? 'en-US';
9055
+ cdr = inject(ChangeDetectorRef);
9056
+ optionDisplayResolver = inject(OptionDisplayResolverService);
9057
+ crudService = inject(GenericCrudService, {
9058
+ optional: true,
9059
+ });
9060
+ valueSub;
9061
+ resolveSub;
9062
+ presentationDisplayValue = null;
9063
+ _field;
9064
+ _control;
9065
+ _presentationMode = false;
8619
9066
  /** Metadata for the dynamic field being rendered. */
8620
- field;
9067
+ set field(value) {
9068
+ this._field = value;
9069
+ this.refreshPresentationDisplayValue();
9070
+ }
9071
+ get field() {
9072
+ return this._field;
9073
+ }
8621
9074
  /** Index position of the field within the directive's list. */
8622
9075
  index;
8623
9076
  /** Controle reativo associado (injetado pela diretiva) */
8624
- control;
9077
+ set control(value) {
9078
+ this._control = value;
9079
+ this.bindControlValueChanges();
9080
+ this.refreshPresentationDisplayValue();
9081
+ }
9082
+ get control() {
9083
+ return this._control;
9084
+ }
8625
9085
  /** Estados – podem ser definidos externamente; caso contrário, derivam do metadata */
8626
9086
  readonlyMode = false;
8627
9087
  disabledMode = false;
8628
9088
  visible = true;
8629
- presentationMode = false;
9089
+ set presentationMode(value) {
9090
+ this._presentationMode = value;
9091
+ this.refreshPresentationDisplayValue();
9092
+ }
9093
+ get presentationMode() {
9094
+ return this._presentationMode;
9095
+ }
8630
9096
  /** Special input to enable canvas mode interactions */
8631
9097
  canvasMode = false;
8632
9098
  canvasMouseEnter = new EventEmitter();
8633
9099
  canvasMouseLeave = new EventEmitter();
8634
9100
  canvasClick = new EventEmitter();
8635
9101
  get fieldNameAttr() {
8636
- return this.field.name;
9102
+ return this._field?.name;
8637
9103
  }
8638
9104
  get fieldIdAttr() {
8639
- return this.field.id ?? undefined;
9105
+ return this._field?.id ?? undefined;
9106
+ }
9107
+ fieldLabelText() {
9108
+ return this._field?.label || this._field?.name;
8640
9109
  }
8641
9110
  get fieldControlTypeAttr() {
8642
9111
  const controlType = this.field?.controlType;
@@ -8679,6 +9148,10 @@ class FieldShellComponent {
8679
9148
  itemTemplate;
8680
9149
  /** View container used as the insertion point for the field component. */
8681
9150
  vc;
9151
+ ngOnDestroy() {
9152
+ this.valueSub?.unsubscribe();
9153
+ this.resolveSub?.unsubscribe();
9154
+ }
8682
9155
  /**
8683
9156
  * Defaults derivados dos metadados quando inputs não são explicitamente alterados.
8684
9157
  * - hidden/formHidden => visible=false
@@ -8726,7 +9199,7 @@ class FieldShellComponent {
8726
9199
  }
8727
9200
  }
8728
9201
  getPresentationValue() {
8729
- const raw = this.control?.value;
9202
+ const raw = this.presentationDisplayValue ?? this.control?.value;
8730
9203
  try {
8731
9204
  const fn = this.field?.transformDisplayValue;
8732
9205
  const formatted = typeof fn === 'function'
@@ -8748,9 +9221,14 @@ class FieldShellComponent {
8748
9221
  }
8749
9222
  getPresentationHtml() {
8750
9223
  const raw = this.control?.value;
9224
+ const displayValue = this.presentationDisplayValue;
8751
9225
  try {
8752
9226
  const fn = this.field?.transformDisplayValue;
8753
- const formatted = typeof fn === 'function' ? fn(raw) : null;
9227
+ const formatted = displayValue !== null
9228
+ ? displayValue
9229
+ : typeof fn === 'function'
9230
+ ? fn(raw)
9231
+ : null;
8754
9232
  const val = formatted == null ? raw : formatted;
8755
9233
  return formatDisplayHtml(this.field, val, {
8756
9234
  appLocale: this.hostLocale,
@@ -8766,12 +9244,121 @@ class FieldShellComponent {
8766
9244
  });
8767
9245
  }
8768
9246
  }
9247
+ getPresentationPrefixIcon() {
9248
+ const field = this.field;
9249
+ const explicit = this.normalizeIconName(field?.prefixIcon);
9250
+ if (explicit) {
9251
+ return explicit;
9252
+ }
9253
+ if (this.isStartIconPosition(field?.iconPosition)) {
9254
+ return this.normalizeIconName(field?.icon);
9255
+ }
9256
+ return '';
9257
+ }
9258
+ getPresentationSuffixIcon() {
9259
+ const field = this.field;
9260
+ const explicit = this.normalizeIconName(field?.suffixIcon);
9261
+ if (explicit) {
9262
+ return explicit;
9263
+ }
9264
+ if (this.isEndIconPosition(field?.iconPosition)) {
9265
+ return this.normalizeIconName(field?.icon);
9266
+ }
9267
+ return '';
9268
+ }
9269
+ getPresentationIconPalette(position) {
9270
+ const color = this.getPresentationIconColor(position);
9271
+ return color === 'primary' || color === 'accent' || color === 'warn'
9272
+ ? color
9273
+ : undefined;
9274
+ }
9275
+ getPresentationIconCustomColor(position) {
9276
+ const color = this.getPresentationIconColor(position);
9277
+ return color && !this.getPresentationIconPalette(position) ? color : null;
9278
+ }
9279
+ getPresentationIconSize() {
9280
+ const size = this.field?.iconFontSize ?? this.field?.iconSize;
9281
+ if (typeof size === 'number') {
9282
+ return `${size}px`;
9283
+ }
9284
+ if (typeof size === 'string' && size.trim().length) {
9285
+ const trimmed = size.trim();
9286
+ if (/^\d+(\.\d+)?$/.test(trimmed)) {
9287
+ return `${trimmed}px`;
9288
+ }
9289
+ if (trimmed === 'small') {
9290
+ return '1rem';
9291
+ }
9292
+ if (trimmed === 'medium') {
9293
+ return '1.125rem';
9294
+ }
9295
+ if (trimmed === 'large') {
9296
+ return '1.5rem';
9297
+ }
9298
+ return trimmed;
9299
+ }
9300
+ return null;
9301
+ }
9302
+ bindControlValueChanges() {
9303
+ this.valueSub?.unsubscribe();
9304
+ this.valueSub = undefined;
9305
+ if (!this.control) {
9306
+ return;
9307
+ }
9308
+ this.valueSub = this.control.valueChanges.subscribe(() => {
9309
+ this.refreshPresentationDisplayValue();
9310
+ });
9311
+ }
9312
+ getPresentationIconColor(position) {
9313
+ const field = this.field;
9314
+ const value = position === 'prefix'
9315
+ ? field?.prefixIconColor ?? field?.iconColor
9316
+ : field?.suffixIconColor ?? field?.iconColor;
9317
+ return typeof value === 'string' && value.trim().length
9318
+ ? value.trim()
9319
+ : undefined;
9320
+ }
9321
+ normalizeIconName(icon) {
9322
+ const raw = String(icon ?? '').trim();
9323
+ if (!raw) {
9324
+ return '';
9325
+ }
9326
+ if (raw.startsWith('mi:')) {
9327
+ return raw.slice(3).trim();
9328
+ }
9329
+ return raw;
9330
+ }
9331
+ isStartIconPosition(position) {
9332
+ const value = String(position ?? 'start').trim().toLowerCase();
9333
+ return ['start', 'left', 'before', 'prefix', 'leading'].includes(value);
9334
+ }
9335
+ isEndIconPosition(position) {
9336
+ const value = String(position ?? '').trim().toLowerCase();
9337
+ return ['end', 'right', 'after', 'suffix', 'trailing'].includes(value);
9338
+ }
9339
+ refreshPresentationDisplayValue() {
9340
+ this.resolveSub?.unsubscribe();
9341
+ this.resolveSub = undefined;
9342
+ this.presentationDisplayValue = null;
9343
+ if (!this.field) {
9344
+ return;
9345
+ }
9346
+ if (!this.effectivePresentationMode || this.renderContentInPresentation()) {
9347
+ return;
9348
+ }
9349
+ this.resolveSub = this.optionDisplayResolver
9350
+ .resolve(this.field, this.control?.value, this.crudService)
9351
+ .subscribe((value) => {
9352
+ this.presentationDisplayValue = value;
9353
+ this.cdr.markForCheck();
9354
+ });
9355
+ }
8769
9356
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: FieldShellComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
8770
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.17", type: FieldShellComponent, isStandalone: true, selector: "praxis-field-shell", inputs: { field: "field", index: "index", control: "control", readonlyMode: "readonlyMode", disabledMode: "disabledMode", visible: "visible", presentationMode: "presentationMode", canvasMode: "canvasMode", itemTemplate: "itemTemplate" }, outputs: { canvasMouseEnter: "canvasMouseEnter", canvasMouseLeave: "canvasMouseLeave", canvasClick: "canvasClick" }, host: { listeners: { "mouseenter": "onMouseEnter($event)", "mouseleave": "onMouseLeave()", "click": "onClick($event)" }, properties: { "attr.data-field-name": "this.fieldNameAttr", "attr.data-field-id": "this.fieldIdAttr", "attr.data-control-type": "this.fieldControlTypeAttr", "attr.data-field-index": "this.fieldIndexAttr", "style.display": "this.hostDisplay", "class.canvas-element": "this.isCanvasElement", "attr.data-canvas-type": "this.canvasType" }, classAttribute: "pfx-field-shell" }, viewQueries: [{ propertyName: "vc", first: true, predicate: ["insertionPoint"], descendants: true, read: ViewContainerRef }], ngImport: i0, template: `
9357
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.17", type: FieldShellComponent, isStandalone: true, selector: "praxis-field-shell", inputs: { field: "field", index: "index", control: "control", readonlyMode: "readonlyMode", disabledMode: "disabledMode", visible: "visible", presentationMode: "presentationMode", canvasMode: "canvasMode", itemTemplate: "itemTemplate" }, outputs: { canvasMouseEnter: "canvasMouseEnter", canvasMouseLeave: "canvasMouseLeave", canvasClick: "canvasClick" }, host: { listeners: { "mouseenter": "onMouseEnter($event)", "mouseleave": "onMouseLeave()", "click": "onClick($event)" }, properties: { "attr.data-field-name": "this.fieldNameAttr", "attr.data-field-id": "this.fieldIdAttr", "attr.data-control-type": "this.fieldControlTypeAttr", "attr.data-field-index": "this.fieldIndexAttr", "style.display": "this.hostDisplay", "class.canvas-element": "this.isCanvasElement", "attr.data-canvas-type": "this.canvasType" }, classAttribute: "pfx-field-shell" }, providers: [GenericCrudService], viewQueries: [{ propertyName: "vc", first: true, predicate: ["insertionPoint"], descendants: true, read: ViewContainerRef }], ngImport: i0, template: `
8771
9358
  <div
8772
9359
  class="pfx-field-shell-wrapper"
8773
9360
  [attr.data-field-index]="index"
8774
- [attr.data-field-id]="field.id"
9361
+ [attr.data-field-id]="fieldIdAttr"
8775
9362
  >
8776
9363
  <div
8777
9364
  class="pfx-field-shell-host"
@@ -8784,14 +9371,40 @@ class FieldShellComponent {
8784
9371
  >
8785
9372
  <!-- Presentation block -->
8786
9373
  @if (effectivePresentationMode && !renderContentInPresentation()) {
8787
- <div class="praxis-presentation" [attr.data-field]="field.name">
9374
+ <div class="praxis-presentation" [attr.data-field]="fieldNameAttr">
8788
9375
  <span class="praxis-presentation__label">{{
8789
- field.label || field.name
9376
+ fieldLabelText()
8790
9377
  }}</span>
8791
- <span
8792
- class="praxis-presentation__value"
8793
- [innerHTML]="getPresentationHtml()"
8794
- ></span>
9378
+ <span class="praxis-presentation__content">
9379
+ @if (getPresentationPrefixIcon(); as prefixIcon) {
9380
+ <mat-icon
9381
+ class="praxis-presentation__icon praxis-presentation__icon--prefix"
9382
+ aria-hidden="true"
9383
+ [praxisIcon]="prefixIcon"
9384
+ [color]="getPresentationIconPalette('prefix')"
9385
+ [style.color]="getPresentationIconCustomColor('prefix')"
9386
+ [style.font-size]="getPresentationIconSize()"
9387
+ [style.width]="getPresentationIconSize()"
9388
+ [style.height]="getPresentationIconSize()"
9389
+ ></mat-icon>
9390
+ }
9391
+ <span
9392
+ class="praxis-presentation__value"
9393
+ [innerHTML]="getPresentationHtml()"
9394
+ ></span>
9395
+ @if (getPresentationSuffixIcon(); as suffixIcon) {
9396
+ <mat-icon
9397
+ class="praxis-presentation__icon praxis-presentation__icon--suffix"
9398
+ aria-hidden="true"
9399
+ [praxisIcon]="suffixIcon"
9400
+ [color]="getPresentationIconPalette('suffix')"
9401
+ [style.color]="getPresentationIconCustomColor('suffix')"
9402
+ [style.font-size]="getPresentationIconSize()"
9403
+ [style.width]="getPresentationIconSize()"
9404
+ [style.height]="getPresentationIconSize()"
9405
+ ></mat-icon>
9406
+ }
9407
+ </span>
8795
9408
  </div>
8796
9409
  }
8797
9410
 
@@ -8832,15 +9445,15 @@ class FieldShellComponent {
8832
9445
 
8833
9446
  </div>
8834
9447
  </div>
8835
- `, isInline: true, styles: [".pfx-field-shell .mat-mdc-form-field,.pfx-field-shell mat-form-field{width:var(--pfx-field-shell-field-width, 100%)}.pfx-field-shell .mat-mdc-form-field-subscript-wrapper{min-height:20px;margin-top:2px}.pfx-field-shell .mat-mdc-form-field{margin-bottom:8px}.pfx-field-shell .mat-mdc-form-field-infix{min-width:0}:host{display:block;cursor:pointer;width:var(--pfx-field-shell-width, 100%);min-width:0;max-width:100%}.pfx-field-shell-wrapper,.pfx-field-shell-host{position:relative}.praxis-interaction-overlay{position:absolute;inset:0;pointer-events:all}.praxis-readonly-overlay,.praxis-disabled-overlay{cursor:not-allowed}.praxis-presentation{white-space:pre-wrap;display:block;padding:6px 0}.praxis-presentation__label{display:block;font-size:var(--pfx-pres-label-size, .78rem);line-height:1.2;letter-spacing:.02em;font-weight:500;opacity:.8;margin-bottom:2px}.praxis-presentation__value{display:block;font-size:var(--pfx-pres-value-size, 1rem);line-height:1.35;font-weight:600;opacity:.95}.presentation-mode.pres-label-left .praxis-presentation{display:flex;align-items:center;gap:8px}.presentation-mode.pres-label-left .praxis-presentation__label{margin:0;min-width:var(--pfx-pres-label-width, 140px);opacity:.85;text-align:var(--pfx-pres-label-align, start)}.presentation-mode .praxis-presentation__value{text-align:var(--pfx-pres-value-align, start)}.presentation-mode.pres-density-cozy .praxis-presentation{padding:6px 0}.presentation-mode.pres-density-compact .praxis-presentation{padding:2px 0;gap:6px}.presentation-mode.pres-compact .praxis-presentation{padding:2px 0}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
9448
+ `, isInline: true, styles: [".pfx-field-shell .mat-mdc-form-field,.pfx-field-shell mat-form-field{width:var(--pfx-field-shell-field-width, 100%)}.pfx-field-shell .mat-mdc-form-field-subscript-wrapper{min-height:20px;margin-top:2px}.pfx-field-shell .mat-mdc-form-field{margin-bottom:8px}.pfx-field-shell .mat-mdc-form-field-infix{min-width:0}:host{display:block;cursor:pointer;width:var(--pfx-field-shell-width, 100%);min-width:0;max-width:100%}.pfx-field-shell-wrapper,.pfx-field-shell-host{position:relative}.praxis-interaction-overlay{position:absolute;inset:0;pointer-events:all}.praxis-readonly-overlay,.praxis-disabled-overlay{cursor:not-allowed}.praxis-presentation{white-space:pre-wrap;display:block;max-width:100%;min-width:0;padding:6px 0}.praxis-presentation__label{display:block;font-size:var(--pfx-pres-label-size, .78rem);line-height:1.2;letter-spacing:.02em;font-weight:500;opacity:.8;margin-bottom:2px}.praxis-presentation__value{display:block;flex:1 1 auto;max-width:100%;min-width:0;overflow-wrap:anywhere;word-break:break-word;font-size:var(--pfx-pres-value-size, 1rem);line-height:1.35;font-weight:600;opacity:.95}.praxis-presentation__value a{color:var( --pfx-pres-link-color, color-mix( in srgb, var(--mat-sys-primary, #90caf9) 78%, var(--mat-sys-on-surface, #ffffff) 22% ) );text-decoration-color:var( --pfx-pres-link-decoration-color, color-mix(in srgb, currentColor 62%, transparent) );text-decoration-thickness:.08em;text-underline-offset:.18em;max-width:100%;overflow-wrap:anywhere;word-break:break-word}.praxis-presentation__value a:visited{color:var(--pfx-pres-link-visited-color, var(--pfx-pres-link-color, inherit))}.praxis-presentation__value a:hover{color:var(--pfx-pres-link-hover-color, var(--pfx-pres-link-color, currentColor));text-decoration-color:currentColor}.praxis-presentation__value a:focus-visible{outline:2px solid var(--pfx-pres-link-focus-ring-color, currentColor);outline-offset:2px;border-radius:2px}.praxis-presentation__content{display:flex;align-items:center;gap:6px;max-width:100%;min-width:0}.praxis-presentation__icon{flex:0 0 auto;font-size:1.125rem;width:1.125rem;height:1.125rem;line-height:1;opacity:.85}.presentation-mode.pres-label-left .praxis-presentation{display:flex;align-items:center;gap:8px}.presentation-mode.pres-label-left .praxis-presentation__label{margin:0;min-width:var(--pfx-pres-label-width, 140px);opacity:.85;text-align:var(--pfx-pres-label-align, start)}.presentation-mode .praxis-presentation__value,.presentation-mode .praxis-presentation__content{flex:1 1 auto;min-width:0;text-align:var(--pfx-pres-value-align, start)}.presentation-mode.pres-density-cozy .praxis-presentation{padding:6px 0}.presentation-mode.pres-density-compact .praxis-presentation{padding:2px 0;gap:6px}.presentation-mode.pres-compact .praxis-presentation{padding:2px 0}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i4.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
8836
9449
  }
8837
9450
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: FieldShellComponent, decorators: [{
8838
9451
  type: Component,
8839
- args: [{ selector: 'praxis-field-shell', standalone: true, imports: [CommonModule], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: `
9452
+ args: [{ selector: 'praxis-field-shell', standalone: true, imports: [CommonModule, MatIconModule, PraxisIconDirective], providers: [GenericCrudService], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: `
8840
9453
  <div
8841
9454
  class="pfx-field-shell-wrapper"
8842
9455
  [attr.data-field-index]="index"
8843
- [attr.data-field-id]="field.id"
9456
+ [attr.data-field-id]="fieldIdAttr"
8844
9457
  >
8845
9458
  <div
8846
9459
  class="pfx-field-shell-host"
@@ -8853,14 +9466,40 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
8853
9466
  >
8854
9467
  <!-- Presentation block -->
8855
9468
  @if (effectivePresentationMode && !renderContentInPresentation()) {
8856
- <div class="praxis-presentation" [attr.data-field]="field.name">
9469
+ <div class="praxis-presentation" [attr.data-field]="fieldNameAttr">
8857
9470
  <span class="praxis-presentation__label">{{
8858
- field.label || field.name
9471
+ fieldLabelText()
8859
9472
  }}</span>
8860
- <span
8861
- class="praxis-presentation__value"
8862
- [innerHTML]="getPresentationHtml()"
8863
- ></span>
9473
+ <span class="praxis-presentation__content">
9474
+ @if (getPresentationPrefixIcon(); as prefixIcon) {
9475
+ <mat-icon
9476
+ class="praxis-presentation__icon praxis-presentation__icon--prefix"
9477
+ aria-hidden="true"
9478
+ [praxisIcon]="prefixIcon"
9479
+ [color]="getPresentationIconPalette('prefix')"
9480
+ [style.color]="getPresentationIconCustomColor('prefix')"
9481
+ [style.font-size]="getPresentationIconSize()"
9482
+ [style.width]="getPresentationIconSize()"
9483
+ [style.height]="getPresentationIconSize()"
9484
+ ></mat-icon>
9485
+ }
9486
+ <span
9487
+ class="praxis-presentation__value"
9488
+ [innerHTML]="getPresentationHtml()"
9489
+ ></span>
9490
+ @if (getPresentationSuffixIcon(); as suffixIcon) {
9491
+ <mat-icon
9492
+ class="praxis-presentation__icon praxis-presentation__icon--suffix"
9493
+ aria-hidden="true"
9494
+ [praxisIcon]="suffixIcon"
9495
+ [color]="getPresentationIconPalette('suffix')"
9496
+ [style.color]="getPresentationIconCustomColor('suffix')"
9497
+ [style.font-size]="getPresentationIconSize()"
9498
+ [style.width]="getPresentationIconSize()"
9499
+ [style.height]="getPresentationIconSize()"
9500
+ ></mat-icon>
9501
+ }
9502
+ </span>
8864
9503
  </div>
8865
9504
  }
8866
9505
 
@@ -8901,7 +9540,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
8901
9540
 
8902
9541
  </div>
8903
9542
  </div>
8904
- `, host: { class: 'pfx-field-shell' }, styles: [".pfx-field-shell .mat-mdc-form-field,.pfx-field-shell mat-form-field{width:var(--pfx-field-shell-field-width, 100%)}.pfx-field-shell .mat-mdc-form-field-subscript-wrapper{min-height:20px;margin-top:2px}.pfx-field-shell .mat-mdc-form-field{margin-bottom:8px}.pfx-field-shell .mat-mdc-form-field-infix{min-width:0}:host{display:block;cursor:pointer;width:var(--pfx-field-shell-width, 100%);min-width:0;max-width:100%}.pfx-field-shell-wrapper,.pfx-field-shell-host{position:relative}.praxis-interaction-overlay{position:absolute;inset:0;pointer-events:all}.praxis-readonly-overlay,.praxis-disabled-overlay{cursor:not-allowed}.praxis-presentation{white-space:pre-wrap;display:block;padding:6px 0}.praxis-presentation__label{display:block;font-size:var(--pfx-pres-label-size, .78rem);line-height:1.2;letter-spacing:.02em;font-weight:500;opacity:.8;margin-bottom:2px}.praxis-presentation__value{display:block;font-size:var(--pfx-pres-value-size, 1rem);line-height:1.35;font-weight:600;opacity:.95}.presentation-mode.pres-label-left .praxis-presentation{display:flex;align-items:center;gap:8px}.presentation-mode.pres-label-left .praxis-presentation__label{margin:0;min-width:var(--pfx-pres-label-width, 140px);opacity:.85;text-align:var(--pfx-pres-label-align, start)}.presentation-mode .praxis-presentation__value{text-align:var(--pfx-pres-value-align, start)}.presentation-mode.pres-density-cozy .praxis-presentation{padding:6px 0}.presentation-mode.pres-density-compact .praxis-presentation{padding:2px 0;gap:6px}.presentation-mode.pres-compact .praxis-presentation{padding:2px 0}\n"] }]
9543
+ `, host: { class: 'pfx-field-shell' }, styles: [".pfx-field-shell .mat-mdc-form-field,.pfx-field-shell mat-form-field{width:var(--pfx-field-shell-field-width, 100%)}.pfx-field-shell .mat-mdc-form-field-subscript-wrapper{min-height:20px;margin-top:2px}.pfx-field-shell .mat-mdc-form-field{margin-bottom:8px}.pfx-field-shell .mat-mdc-form-field-infix{min-width:0}:host{display:block;cursor:pointer;width:var(--pfx-field-shell-width, 100%);min-width:0;max-width:100%}.pfx-field-shell-wrapper,.pfx-field-shell-host{position:relative}.praxis-interaction-overlay{position:absolute;inset:0;pointer-events:all}.praxis-readonly-overlay,.praxis-disabled-overlay{cursor:not-allowed}.praxis-presentation{white-space:pre-wrap;display:block;max-width:100%;min-width:0;padding:6px 0}.praxis-presentation__label{display:block;font-size:var(--pfx-pres-label-size, .78rem);line-height:1.2;letter-spacing:.02em;font-weight:500;opacity:.8;margin-bottom:2px}.praxis-presentation__value{display:block;flex:1 1 auto;max-width:100%;min-width:0;overflow-wrap:anywhere;word-break:break-word;font-size:var(--pfx-pres-value-size, 1rem);line-height:1.35;font-weight:600;opacity:.95}.praxis-presentation__value a{color:var( --pfx-pres-link-color, color-mix( in srgb, var(--mat-sys-primary, #90caf9) 78%, var(--mat-sys-on-surface, #ffffff) 22% ) );text-decoration-color:var( --pfx-pres-link-decoration-color, color-mix(in srgb, currentColor 62%, transparent) );text-decoration-thickness:.08em;text-underline-offset:.18em;max-width:100%;overflow-wrap:anywhere;word-break:break-word}.praxis-presentation__value a:visited{color:var(--pfx-pres-link-visited-color, var(--pfx-pres-link-color, inherit))}.praxis-presentation__value a:hover{color:var(--pfx-pres-link-hover-color, var(--pfx-pres-link-color, currentColor));text-decoration-color:currentColor}.praxis-presentation__value a:focus-visible{outline:2px solid var(--pfx-pres-link-focus-ring-color, currentColor);outline-offset:2px;border-radius:2px}.praxis-presentation__content{display:flex;align-items:center;gap:6px;max-width:100%;min-width:0}.praxis-presentation__icon{flex:0 0 auto;font-size:1.125rem;width:1.125rem;height:1.125rem;line-height:1;opacity:.85}.presentation-mode.pres-label-left .praxis-presentation{display:flex;align-items:center;gap:8px}.presentation-mode.pres-label-left .praxis-presentation__label{margin:0;min-width:var(--pfx-pres-label-width, 140px);opacity:.85;text-align:var(--pfx-pres-label-align, start)}.presentation-mode .praxis-presentation__value,.presentation-mode .praxis-presentation__content{flex:1 1 auto;min-width:0;text-align:var(--pfx-pres-value-align, start)}.presentation-mode.pres-density-cozy .praxis-presentation{padding:6px 0}.presentation-mode.pres-density-compact .praxis-presentation{padding:2px 0;gap:6px}.presentation-mode.pres-compact .praxis-presentation{padding:2px 0}\n"] }]
8905
9544
  }], propDecorators: { field: [{
8906
9545
  type: Input
8907
9546
  }], index: [{
@@ -10656,6 +11295,7 @@ class MaterialAsyncSelectComponent extends SimpleBaseSelectComponent {
10656
11295
  if (mappedOptions)
10657
11296
  this.options.set(mappedOptions);
10658
11297
  this.multiple.set(!!metadata.multiple);
11298
+ this.normalizeMultipleControlValue();
10659
11299
  this.searchable.set(metadata.searchable ?? !isCategoricalBucket);
10660
11300
  this.selectAll.set(!!metadata.selectAll);
10661
11301
  this.maxSelections.set(metadata.maxSelections ?? null);
@@ -10982,7 +11622,7 @@ class MaterialAsyncSelectComponent extends SimpleBaseSelectComponent {
10982
11622
  enhanced.displayWith = (opt) => opt && typeof opt === 'object' && 'label' in opt
10983
11623
  ? String(opt.label ?? '')
10984
11624
  : '';
10985
- enhanced.compareWith = (a, b) => this.areRemoteOptionValuesEqual(a, b);
11625
+ enhanced.compareWith = (a, b) => this.areOptionValuesEqual(a, b);
10986
11626
  }
10987
11627
  // ---------------------------------------------------------------------------
10988
11628
  // Phase 1: explicit reload API and dependency handling
@@ -11048,7 +11688,7 @@ class MaterialAsyncSelectComponent extends SimpleBaseSelectComponent {
11048
11688
  if (!selected.length) {
11049
11689
  return;
11050
11690
  }
11051
- const hasAllSelectedOptions = selected.every((value) => this.options().some((candidate) => this.areRemoteOptionValuesEqual(candidate.value, value)));
11691
+ const hasAllSelectedOptions = selected.every((value) => this.options().some((candidate) => this.areOptionValuesEqual(candidate.value, value)));
11052
11692
  if (hasAllSelectedOptions) {
11053
11693
  return;
11054
11694
  }
@@ -11073,7 +11713,7 @@ class MaterialAsyncSelectComponent extends SimpleBaseSelectComponent {
11073
11713
  resolveRemoteOptionDisabled(option) {
11074
11714
  return option.extra?.['selectable'] === false;
11075
11715
  }
11076
- areRemoteOptionValuesEqual(left, right) {
11716
+ areOptionValuesEqual(left, right) {
11077
11717
  return this.normalizeRemoteOptionValue(left) === this.normalizeRemoteOptionValue(right);
11078
11718
  }
11079
11719
  normalizeRemoteOptionValue(value) {
@@ -11125,15 +11765,13 @@ class MaterialAsyncSelectComponent extends SimpleBaseSelectComponent {
11125
11765
  <mat-option
11126
11766
  *ngIf="!multiple() && emptyOptionText()"
11127
11767
  [value]="null"
11128
- (click)="selectOption({ label: emptyOptionText()!, value: null })"
11129
11768
  >
11130
11769
  {{ emptyOptionText() }}
11131
11770
  </mat-option>
11132
11771
  <mat-option
11133
11772
  *ngFor="let option of options(); trackBy: trackByOption"
11134
11773
  [value]="option.value"
11135
- [disabled]="option.disabled"
11136
- (click)="selectOption(option)"
11774
+ [disabled]="isOptionDisabled(option)"
11137
11775
  >
11138
11776
  {{ option.label }}
11139
11777
  </mat-option>
@@ -11236,15 +11874,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
11236
11874
  <mat-option
11237
11875
  *ngIf="!multiple() && emptyOptionText()"
11238
11876
  [value]="null"
11239
- (click)="selectOption({ label: emptyOptionText()!, value: null })"
11240
11877
  >
11241
11878
  {{ emptyOptionText() }}
11242
11879
  </mat-option>
11243
11880
  <mat-option
11244
11881
  *ngFor="let option of options(); trackBy: trackByOption"
11245
11882
  [value]="option.value"
11246
- [disabled]="option.disabled"
11247
- (click)="selectOption(option)"
11883
+ [disabled]="isOptionDisabled(option)"
11248
11884
  >
11249
11885
  {{ option.label }}
11250
11886
  </mat-option>
@@ -12942,7 +13578,6 @@ class InlineEntityLookupComponent extends MaterialAsyncSelectComponent {
12942
13578
  <mat-option
12943
13579
  *ngIf="!multiple() && emptyOptionText()"
12944
13580
  [value]="null"
12945
- (click)="selectOption({ label: emptyOptionText()!, value: null })"
12946
13581
  >
12947
13582
  {{ emptyOptionText() }}
12948
13583
  </mat-option>
@@ -12950,8 +13585,7 @@ class InlineEntityLookupComponent extends MaterialAsyncSelectComponent {
12950
13585
  <mat-option
12951
13586
  *ngFor="let option of options(); trackBy: trackByOption"
12952
13587
  [value]="option.value"
12953
- [disabled]="option.disabled"
12954
- (click)="selectOption(option)"
13588
+ [disabled]="isOptionDisabled(option)"
12955
13589
  >
12956
13590
  @if (richLayoutEnabled()) {
12957
13591
  @if (optionLookupView(option); as item) {
@@ -13359,7 +13993,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
13359
13993
  <mat-option
13360
13994
  *ngIf="!multiple() && emptyOptionText()"
13361
13995
  [value]="null"
13362
- (click)="selectOption({ label: emptyOptionText()!, value: null })"
13363
13996
  >
13364
13997
  {{ emptyOptionText() }}
13365
13998
  </mat-option>
@@ -13367,8 +14000,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
13367
14000
  <mat-option
13368
14001
  *ngFor="let option of options(); trackBy: trackByOption"
13369
14002
  [value]="option.value"
13370
- [disabled]="option.disabled"
13371
- (click)="selectOption(option)"
14003
+ [disabled]="isOptionDisabled(option)"
13372
14004
  >
13373
14005
  @if (richLayoutEnabled()) {
13374
14006
  @if (optionLookupView(option); as item) {
@@ -15450,15 +16082,13 @@ class MaterialSelectComponent extends SimpleBaseSelectComponent {
15450
16082
  <mat-option
15451
16083
  *ngIf="emptyOptionText()"
15452
16084
  [value]="null"
15453
- (click)="selectOption({ label: emptyOptionText()!, value: null })"
15454
16085
  >
15455
16086
  {{ emptyOptionText() }}
15456
16087
  </mat-option>
15457
16088
  <mat-option
15458
16089
  *ngFor="let option of options(); trackBy: trackByOption"
15459
16090
  [value]="option.value"
15460
- [disabled]="option.disabled"
15461
- (click)="selectOption(option)"
16091
+ [disabled]="isOptionDisabled(option)"
15462
16092
  >
15463
16093
  {{ option.label }}
15464
16094
  </mat-option>
@@ -15560,15 +16190,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
15560
16190
  <mat-option
15561
16191
  *ngIf="emptyOptionText()"
15562
16192
  [value]="null"
15563
- (click)="selectOption({ label: emptyOptionText()!, value: null })"
15564
16193
  >
15565
16194
  {{ emptyOptionText() }}
15566
16195
  </mat-option>
15567
16196
  <mat-option
15568
16197
  *ngFor="let option of options(); trackBy: trackByOption"
15569
16198
  [value]="option.value"
15570
- [disabled]="option.disabled"
15571
- (click)="selectOption(option)"
16199
+ [disabled]="isOptionDisabled(option)"
15572
16200
  >
15573
16201
  {{ option.label }}
15574
16202
  </mat-option>
@@ -21020,7 +21648,7 @@ class MaterialPriceRangeComponent extends SimpleBaseInputComponent {
21020
21648
  <div class="mat-hint">{{ metadata()!.hint }}</div>
21021
21649
  }
21022
21650
  </div>
21023
- `, isInline: true, styles: [".price-range-container{display:flex;flex-direction:column}.range-label{display:block;margin:0 0 8px;font-size:14px;line-height:1.25;color:var(--md-sys-color-on-surface-variant)}.price-range-actions{display:flex;justify-content:flex-end;margin-top:4px}.range-inputs{display:flex;align-items:stretch}.range-inputs.layout-row{flex-direction:row}.range-inputs.layout-column{flex-direction:column}.range-inputs>pdx-material-currency{flex:1 1 0;width:100%;min-width:0}\n"], dependencies: [{ kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i1$2.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i4.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: MaterialCurrencyComponent, selector: "pdx-material-currency", inputs: ["metadata", "readonlyMode", "disabledMode", "visible", "presentationMode"], outputs: ["validationChange"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i5.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }] });
21651
+ `, isInline: true, styles: [".price-range-container{display:flex;flex-direction:column}.range-label{display:block;margin:0 0 6px;font-size:12px;line-height:16px;font-weight:500;color:var(--md-sys-color-on-surface-variant)}.mat-hint{display:block;margin-top:4px;font-size:12px;line-height:16px;font-weight:400;color:var(--mat-form-field-subscript-text-color, var(--md-sys-color-on-surface-variant))}.price-range-actions{display:flex;justify-content:flex-end;margin-top:4px}.range-inputs{display:flex;align-items:stretch}.range-inputs.layout-row{flex-direction:row}.range-inputs.layout-column{flex-direction:column}.range-inputs>pdx-material-currency{flex:1 1 0;width:100%;min-width:0}\n"], dependencies: [{ kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i1$2.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i4.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: MaterialCurrencyComponent, selector: "pdx-material-currency", inputs: ["metadata", "readonlyMode", "disabledMode", "visible", "presentationMode"], outputs: ["validationChange"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i5.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }] });
21024
21652
  }
21025
21653
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: MaterialPriceRangeComponent, decorators: [{
21026
21654
  type: Component,
@@ -21104,7 +21732,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
21104
21732
  '[attr.data-field-type]': '"priceRange"',
21105
21733
  '[attr.data-field-name]': 'metadata()?.name',
21106
21734
  '[attr.data-component-id]': 'componentId()',
21107
- }, styles: [".price-range-container{display:flex;flex-direction:column}.range-label{display:block;margin:0 0 8px;font-size:14px;line-height:1.25;color:var(--md-sys-color-on-surface-variant)}.price-range-actions{display:flex;justify-content:flex-end;margin-top:4px}.range-inputs{display:flex;align-items:stretch}.range-inputs.layout-row{flex-direction:row}.range-inputs.layout-column{flex-direction:column}.range-inputs>pdx-material-currency{flex:1 1 0;width:100%;min-width:0}\n"] }]
21735
+ }, styles: [".price-range-container{display:flex;flex-direction:column}.range-label{display:block;margin:0 0 6px;font-size:12px;line-height:16px;font-weight:500;color:var(--md-sys-color-on-surface-variant)}.mat-hint{display:block;margin-top:4px;font-size:12px;line-height:16px;font-weight:400;color:var(--mat-form-field-subscript-text-color, var(--md-sys-color-on-surface-variant))}.price-range-actions{display:flex;justify-content:flex-end;margin-top:4px}.range-inputs{display:flex;align-items:stretch}.range-inputs.layout-row{flex-direction:row}.range-inputs.layout-column{flex-direction:column}.range-inputs>pdx-material-currency{flex:1 1 0;width:100%;min-width:0}\n"] }]
21108
21736
  }], propDecorators: { validationChange: [{ type: i0.Output, args: ["validationChange"] }], readonlyMode: [{
21109
21737
  type: Input
21110
21738
  }], disabledMode: [{
@@ -22270,7 +22898,6 @@ class InlineSelectComponent extends SimpleBaseSelectComponent {
22270
22898
  <mat-option
22271
22899
  *ngIf="emptyOptionText()"
22272
22900
  [value]="null"
22273
- (click)="selectOption({ label: emptyOptionText()!, value: null })"
22274
22901
  >
22275
22902
  {{ emptyOptionText() }}
22276
22903
  </mat-option>
@@ -22278,8 +22905,7 @@ class InlineSelectComponent extends SimpleBaseSelectComponent {
22278
22905
  <mat-option
22279
22906
  *ngFor="let option of filteredOptions(); trackBy: trackByOption"
22280
22907
  [value]="option.value"
22281
- [disabled]="option.disabled"
22282
- (click)="selectOption(option)"
22908
+ [disabled]="isOptionDisabled(option)"
22283
22909
  >
22284
22910
  {{ option.label }}
22285
22911
  </mat-option>
@@ -22402,7 +23028,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
22402
23028
  <mat-option
22403
23029
  *ngIf="emptyOptionText()"
22404
23030
  [value]="null"
22405
- (click)="selectOption({ label: emptyOptionText()!, value: null })"
22406
23031
  >
22407
23032
  {{ emptyOptionText() }}
22408
23033
  </mat-option>
@@ -22410,8 +23035,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
22410
23035
  <mat-option
22411
23036
  *ngFor="let option of filteredOptions(); trackBy: trackByOption"
22412
23037
  [value]="option.value"
22413
- [disabled]="option.disabled"
22414
- (click)="selectOption(option)"
23038
+ [disabled]="isOptionDisabled(option)"
22415
23039
  >
22416
23040
  {{ option.label }}
22417
23041
  </mat-option>
@@ -22524,7 +23148,7 @@ class MaterialSearchableSelectComponent extends SimpleBaseSelectComponent {
22524
23148
  return this.isReadonlyEffective() || this.presentationMode ? 'true' : null;
22525
23149
  }
22526
23150
  isOptionDisabled(option) {
22527
- return this.isInteractionDisabled() || option.disabled === true;
23151
+ return this.isInteractionDisabled() || super.isOptionDisabled(option);
22528
23152
  }
22529
23153
  selectOption(option) {
22530
23154
  if (this.isInteractionDisabled()) {
@@ -22769,7 +23393,6 @@ class MaterialSearchableSelectComponent extends SimpleBaseSelectComponent {
22769
23393
  *ngFor="let option of filteredOptions(); trackBy: trackByOption"
22770
23394
  [value]="option.value"
22771
23395
  [disabled]="isOptionDisabled(option)"
22772
- (click)="selectOption(option)"
22773
23396
  >
22774
23397
  {{ option.label }}
22775
23398
  </mat-option>
@@ -22815,7 +23438,6 @@ class MaterialSearchableSelectComponent extends SimpleBaseSelectComponent {
22815
23438
  *ngIf="emptyOptionText()"
22816
23439
  [value]="null"
22817
23440
  [disabled]="isInteractionDisabled()"
22818
- (click)="selectOption({ label: emptyOptionText()!, value: null })"
22819
23441
  >
22820
23442
  {{ emptyOptionText() }}
22821
23443
  </mat-option>
@@ -22823,7 +23445,6 @@ class MaterialSearchableSelectComponent extends SimpleBaseSelectComponent {
22823
23445
  *ngFor="let option of filteredOptions(); trackBy: trackByOption"
22824
23446
  [value]="option.value"
22825
23447
  [disabled]="isOptionDisabled(option)"
22826
- (click)="selectOption(option)"
22827
23448
  >
22828
23449
  {{ option.label }}
22829
23450
  </mat-option>
@@ -22932,7 +23553,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
22932
23553
  *ngFor="let option of filteredOptions(); trackBy: trackByOption"
22933
23554
  [value]="option.value"
22934
23555
  [disabled]="isOptionDisabled(option)"
22935
- (click)="selectOption(option)"
22936
23556
  >
22937
23557
  {{ option.label }}
22938
23558
  </mat-option>
@@ -22978,7 +23598,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
22978
23598
  *ngIf="emptyOptionText()"
22979
23599
  [value]="null"
22980
23600
  [disabled]="isInteractionDisabled()"
22981
- (click)="selectOption({ label: emptyOptionText()!, value: null })"
22982
23601
  >
22983
23602
  {{ emptyOptionText() }}
22984
23603
  </mat-option>
@@ -22986,7 +23605,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
22986
23605
  *ngFor="let option of filteredOptions(); trackBy: trackByOption"
22987
23606
  [value]="option.value"
22988
23607
  [disabled]="isOptionDisabled(option)"
22989
- (click)="selectOption(option)"
22990
23608
  >
22991
23609
  {{ option.label }}
22992
23610
  </mat-option>
@@ -23402,7 +24020,6 @@ class InlineSearchableSelectComponent extends MaterialSearchableSelectComponent
23402
24020
  <mat-option
23403
24021
  *ngIf="!multiple() && emptyOptionText()"
23404
24022
  [value]="null"
23405
- (click)="selectOption({ label: emptyOptionText()!, value: null })"
23406
24023
  >
23407
24024
  {{ emptyOptionText() }}
23408
24025
  </mat-option>
@@ -23410,8 +24027,7 @@ class InlineSearchableSelectComponent extends MaterialSearchableSelectComponent
23410
24027
  <mat-option
23411
24028
  *ngFor="let option of filteredOptions(); trackBy: trackByOption"
23412
24029
  [value]="option.value"
23413
- [disabled]="option.disabled"
23414
- (click)="selectOption(option)"
24030
+ [disabled]="isOptionDisabled(option)"
23415
24031
  >
23416
24032
  {{ option.label }}
23417
24033
  </mat-option>
@@ -23550,7 +24166,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
23550
24166
  <mat-option
23551
24167
  *ngIf="!multiple() && emptyOptionText()"
23552
24168
  [value]="null"
23553
- (click)="selectOption({ label: emptyOptionText()!, value: null })"
23554
24169
  >
23555
24170
  {{ emptyOptionText() }}
23556
24171
  </mat-option>
@@ -23558,8 +24173,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
23558
24173
  <mat-option
23559
24174
  *ngFor="let option of filteredOptions(); trackBy: trackByOption"
23560
24175
  [value]="option.value"
23561
- [disabled]="option.disabled"
23562
- (click)="selectOption(option)"
24176
+ [disabled]="isOptionDisabled(option)"
23563
24177
  >
23564
24178
  {{ option.label }}
23565
24179
  </mat-option>
@@ -23989,7 +24603,6 @@ class InlineAsyncSelectComponent extends MaterialAsyncSelectComponent {
23989
24603
  <mat-option
23990
24604
  *ngIf="!multiple() && emptyOptionText()"
23991
24605
  [value]="null"
23992
- (click)="selectOption({ label: emptyOptionText()!, value: null })"
23993
24606
  >
23994
24607
  {{ emptyOptionText() }}
23995
24608
  </mat-option>
@@ -23997,8 +24610,7 @@ class InlineAsyncSelectComponent extends MaterialAsyncSelectComponent {
23997
24610
  <mat-option
23998
24611
  *ngFor="let option of options(); trackBy: trackByOption"
23999
24612
  [value]="option.value"
24000
- [disabled]="option.disabled"
24001
- (click)="selectOption(option)"
24613
+ [disabled]="isOptionDisabled(option)"
24002
24614
  >
24003
24615
  {{ option.label }}
24004
24616
  </mat-option>
@@ -24138,7 +24750,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
24138
24750
  <mat-option
24139
24751
  *ngIf="!multiple() && emptyOptionText()"
24140
24752
  [value]="null"
24141
- (click)="selectOption({ label: emptyOptionText()!, value: null })"
24142
24753
  >
24143
24754
  {{ emptyOptionText() }}
24144
24755
  </mat-option>
@@ -24146,8 +24757,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
24146
24757
  <mat-option
24147
24758
  *ngFor="let option of options(); trackBy: trackByOption"
24148
24759
  [value]="option.value"
24149
- [disabled]="option.disabled"
24150
- (click)="selectOption(option)"
24760
+ [disabled]="isOptionDisabled(option)"
24151
24761
  >
24152
24762
  {{ option.label }}
24153
24763
  </mat-option>