@praxisui/dynamic-fields 8.0.0-beta.20 → 8.0.0-beta.22

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';
@@ -330,6 +330,9 @@ const PRAXIS_DYNAMIC_FIELDS_EN_US = {
330
330
  'praxis.dynamicFields.entityLookup.dialog.filters.placeholder.between': 'Use start value, end value',
331
331
  'praxis.dynamicFields.entityLookup.dialog.filters.placeholder.date': 'YYYY-MM-DD',
332
332
  'praxis.dynamicFields.entityLookup.dialog.filters.placeholder.default': 'Enter a value',
333
+ 'praxis.dynamicFields.entityLookup.dialog.filters.selectEmpty': 'Select {label}',
334
+ 'praxis.dynamicFields.entityLookup.dialog.filters.startAriaLabel': '{label} start',
335
+ 'praxis.dynamicFields.entityLookup.dialog.filters.endAriaLabel': '{label} end',
333
336
  'praxis.dynamicFields.entityLookup.dialog.filters.operator.contains': 'Operator: contains',
334
337
  'praxis.dynamicFields.entityLookup.dialog.filters.operator.startsWith': 'Operator: starts with',
335
338
  'praxis.dynamicFields.entityLookup.dialog.filters.operator.equals': 'Operator: equals',
@@ -622,6 +625,9 @@ const PRAXIS_DYNAMIC_FIELDS_PT_BR = {
622
625
  'praxis.dynamicFields.entityLookup.dialog.filters.placeholder.between': 'Use valor inicial, valor final',
623
626
  'praxis.dynamicFields.entityLookup.dialog.filters.placeholder.date': 'AAAA-MM-DD',
624
627
  'praxis.dynamicFields.entityLookup.dialog.filters.placeholder.default': 'Digite um valor',
628
+ 'praxis.dynamicFields.entityLookup.dialog.filters.selectEmpty': 'Selecione {label}',
629
+ 'praxis.dynamicFields.entityLookup.dialog.filters.startAriaLabel': '{label} inicial',
630
+ 'praxis.dynamicFields.entityLookup.dialog.filters.endAriaLabel': '{label} final',
625
631
  'praxis.dynamicFields.entityLookup.dialog.filters.operator.contains': 'Operador: contem',
626
632
  'praxis.dynamicFields.entityLookup.dialog.filters.operator.startsWith': 'Operador: comeca com',
627
633
  'praxis.dynamicFields.entityLookup.dialog.filters.operator.equals': 'Operador: igual a',
@@ -2841,6 +2847,11 @@ class SimpleBaseSelectComponent extends SimpleBaseInputComponent {
2841
2847
  this.registerMatSelect(select);
2842
2848
  }
2843
2849
  }, ...(ngDevMode ? [{ debugName: "matSelectInitEffect" }] : []));
2850
+ multipleControlNormalizationEffect = effect(() => {
2851
+ this.formControl();
2852
+ this.multiple();
2853
+ queueMicrotask(() => this.normalizeMultipleControlValue());
2854
+ }, ...(ngDevMode ? [{ debugName: "multipleControlNormalizationEffect" }] : []));
2844
2855
  /** CRUD service for remote option loading (optional) */
2845
2856
  crudService = inject(GenericCrudService, {
2846
2857
  optional: true,
@@ -2892,6 +2903,7 @@ class SimpleBaseSelectComponent extends SimpleBaseInputComponent {
2892
2903
  }
2893
2904
  const isMultiple = !!metadata.multiple;
2894
2905
  this.multiple.set(isMultiple);
2906
+ this.normalizeMultipleControlValue();
2895
2907
  this.searchable.set(!!metadata.searchable);
2896
2908
  this.selectAll.set(!!metadata.selectAll);
2897
2909
  this.maxSelections.set(metadata.maxSelections ?? null);
@@ -2978,7 +2990,12 @@ class SimpleBaseSelectComponent extends SimpleBaseInputComponent {
2978
2990
  select.selectionChange
2979
2991
  .pipe(takeUntilDestroyed(this.destroyRef))
2980
2992
  .subscribe((event) => {
2981
- 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();
2982
2999
  });
2983
3000
  }
2984
3001
  applySelectAttributes() {
@@ -3061,6 +3078,23 @@ class SimpleBaseSelectComponent extends SimpleBaseInputComponent {
3061
3078
  this.isReadonlyEffective() ||
3062
3079
  !!this.presentationMode);
3063
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
+ }
3064
3098
  /** Whether to show the clear button (if enabled in metadata) */
3065
3099
  showClear() {
3066
3100
  const cfg = this.metadata()?.clearButton;
@@ -3268,10 +3302,10 @@ class SimpleBaseSelectComponent extends SimpleBaseInputComponent {
3268
3302
  const current = Array.isArray(this.control().value)
3269
3303
  ? [...this.control().value]
3270
3304
  : [];
3271
- const exists = current.includes(option.value);
3305
+ const exists = current.some((value) => this.areOptionValuesEqual(value, option.value));
3272
3306
  if (exists) {
3273
3307
  // remove if already selected
3274
- const updated = current.filter((v) => v !== option.value);
3308
+ const updated = current.filter((value) => !this.areOptionValuesEqual(value, option.value));
3275
3309
  this.setValue(updated);
3276
3310
  }
3277
3311
  else {
@@ -3294,8 +3328,23 @@ class SimpleBaseSelectComponent extends SimpleBaseInputComponent {
3294
3328
  isSelected(value) {
3295
3329
  const current = this.control().value;
3296
3330
  return this.multiple()
3297
- ? Array.isArray(current) && current.includes(value)
3298
- : 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;
3299
3348
  }
3300
3349
  /**
3301
3350
  * Toggles selection of all options when `selectAll` is enabled in multiple
@@ -6071,6 +6120,70 @@ function createMaterialCheckboxGroupComponentMetadata(locale = 'en-US') {
6071
6120
  return createWave1ComponentDocMeta(PDX_MATERIAL_CHECKBOX_GROUP_EDITORIAL_DESCRIPTOR, locale);
6072
6121
  }
6073
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
+
6074
6187
  class PraxisDateRangeShortcutsOverlayComponent {
6075
6188
  items = [];
6076
6189
  activeId = null;
@@ -6185,21 +6298,48 @@ class MaterialDateRangeComponent extends SimpleBaseInputComponent {
6185
6298
  }, ...(ngDevMode ? [{ debugName: "startAt" }] : []));
6186
6299
  // Overlay state
6187
6300
  overlayOpen = false;
6301
+ shortcutOverlayViewportMargin = 12;
6302
+ pickerOpen = false;
6188
6303
  dateAdapter = inject(DateAdapter);
6189
6304
  picker;
6305
+ endDateInput;
6190
6306
  shouldShowShortcuts = () => !!(this.metadata()?.showShortcuts);
6191
6307
  overlayPositions = () => {
6192
- const pos = this.metadata()?.shortcutsPosition ?? 'left';
6193
- return pos === 'left'
6194
- ? [
6195
- { originX: 'start', originY: 'top', overlayX: 'end', overlayY: 'top', offsetX: -8 },
6196
- { originX: 'start', originY: 'bottom', overlayX: 'end', overlayY: 'bottom', offsetX: -8 },
6197
- ]
6198
- : [
6199
- { originX: 'end', originY: 'top', overlayX: 'start', overlayY: 'top', offsetX: 8 },
6200
- { originX: 'end', originY: 'bottom', overlayX: 'start', overlayY: 'bottom', offsetX: 8 },
6201
- ];
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
+ }
6202
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
+ }
6203
6343
  resolvedPresets = computed(() => {
6204
6344
  const md = this.metadata();
6205
6345
  return resolveBuiltinPresets(this.resolveAdapterLocale(), this.dateAdapter, {
@@ -6286,6 +6426,9 @@ class MaterialDateRangeComponent extends SimpleBaseInputComponent {
6286
6426
  if (!this.shouldPropagateRangeGroupChanges()) {
6287
6427
  return;
6288
6428
  }
6429
+ if (!start && !end && this.isEmptyRangeValue(this.control().value)) {
6430
+ return;
6431
+ }
6289
6432
  const value = {
6290
6433
  startDate: start ?? null,
6291
6434
  endDate: end ?? null,
@@ -6301,25 +6444,93 @@ class MaterialDateRangeComponent extends SimpleBaseInputComponent {
6301
6444
  this.control()
6302
6445
  .valueChanges.pipe(takeUntilDestroyed(this.destroyRef))
6303
6446
  .subscribe((val) => {
6447
+ if (this.pickerOpen) {
6448
+ return;
6449
+ }
6304
6450
  const normalized = this.normalizeDateRangeValue(val);
6451
+ const current = this.rangeGroup.getRawValue();
6452
+ const nextStart = normalized?.startDate ?? null;
6453
+ const nextEnd = normalized?.endDate ?? null;
6454
+ if (this.areDatesEqual(current.start ?? null, nextStart) &&
6455
+ this.areDatesEqual(current.end ?? null, nextEnd)) {
6456
+ return;
6457
+ }
6305
6458
  this.rangeGroup.patchValue({
6306
- start: normalized?.startDate ?? null,
6307
- end: normalized?.endDate ?? null,
6459
+ start: nextStart,
6460
+ end: nextEnd,
6308
6461
  }, { emitEvent: false });
6309
6462
  });
6310
6463
  // Sync overlay with picker lifecycle
6311
6464
  const p = this.picker;
6312
6465
  p.openedStream.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(() => {
6466
+ this.pickerOpen = true;
6313
6467
  if (this.shouldShowShortcuts())
6314
6468
  this.openShortcuts();
6315
6469
  });
6316
6470
  p.closedStream.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(() => {
6471
+ this.pickerOpen = false;
6317
6472
  this.closeShortcuts();
6473
+ this.propagateRangeValue();
6318
6474
  });
6319
6475
  super.ngOnInit();
6320
6476
  }
6321
6477
  shouldPropagateRangeGroupChanges() {
6322
- return true;
6478
+ return !this.pickerOpen;
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
+ }
6488
+ propagateRangeValue() {
6489
+ const { start, end } = this.rangeGroup.getRawValue();
6490
+ if (!start && !end) {
6491
+ this.setValue(null);
6492
+ return;
6493
+ }
6494
+ const current = this.control().value;
6495
+ this.setValue({
6496
+ startDate: start ?? null,
6497
+ endDate: end ?? null,
6498
+ ...(current?.preset ? { preset: current.preset } : {}),
6499
+ ...(current?.timezone ? { timezone: current.timezone } : {}),
6500
+ ...(current?.label ? { label: current.label } : {}),
6501
+ ...(current?.isComparison !== undefined ? { isComparison: current.isComparison } : {}),
6502
+ });
6503
+ }
6504
+ isEmptyRangeValue(value) {
6505
+ if (value === null || value === undefined) {
6506
+ return true;
6507
+ }
6508
+ if (!value || typeof value !== 'object') {
6509
+ return false;
6510
+ }
6511
+ const record = value;
6512
+ const start = record['startDate'] ??
6513
+ record['start'] ??
6514
+ record['fromDate'] ??
6515
+ record['from'] ??
6516
+ record['beginDate'] ??
6517
+ record['begin'];
6518
+ const end = record['endDate'] ??
6519
+ record['end'] ??
6520
+ record['toDate'] ??
6521
+ record['to'] ??
6522
+ record['finishDate'] ??
6523
+ record['finish'];
6524
+ return start == null && end == null;
6525
+ }
6526
+ areDatesEqual(left, right) {
6527
+ if (left === right) {
6528
+ return true;
6529
+ }
6530
+ if (!left || !right) {
6531
+ return false;
6532
+ }
6533
+ return left.getTime() === right.getTime();
6323
6534
  }
6324
6535
  async validateField() {
6325
6536
  const errors = await super.validateField();
@@ -6482,12 +6693,14 @@ class MaterialDateRangeComponent extends SimpleBaseInputComponent {
6482
6693
  }
6483
6694
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: MaterialDateRangeComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
6484
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 },
6485
6698
  {
6486
6699
  provide: NG_VALUE_ACCESSOR,
6487
6700
  useExisting: forwardRef(() => MaterialDateRangeComponent),
6488
6701
  multi: true,
6489
6702
  },
6490
- ], 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: `
6491
6704
  <div class="pdx-date-range-wrap" cdkOverlayOrigin #origin="cdkOverlayOrigin">
6492
6705
  <mat-form-field
6493
6706
  [appearance]="materialAppearance()"
@@ -6531,8 +6744,10 @@ class MaterialDateRangeComponent extends SimpleBaseInputComponent {
6531
6744
  ? metadata()?.startPlaceholder
6532
6745
  : null)
6533
6746
  "
6747
+ (keydown.tab)="focusEndDateInput($event)"
6534
6748
  />
6535
6749
  <input
6750
+ #endDateInput
6536
6751
  matEndDate
6537
6752
  formControlName="end"
6538
6753
  [attr.placeholder]="
@@ -6571,6 +6786,7 @@ class MaterialDateRangeComponent extends SimpleBaseInputComponent {
6571
6786
  [startAt]="startAt()"
6572
6787
  [touchUi]="metadata()?.touchUi || false"
6573
6788
  [color]="materialColor()"
6789
+ panelClass="pdx-datepicker-panel"
6574
6790
  ></mat-date-range-picker>
6575
6791
 
6576
6792
 
@@ -6612,6 +6828,8 @@ class MaterialDateRangeComponent extends SimpleBaseInputComponent {
6612
6828
  [cdkConnectedOverlayHasBackdrop]="true"
6613
6829
  [cdkConnectedOverlayBackdropClass]="'cdk-overlay-transparent-backdrop'"
6614
6830
  [cdkConnectedOverlayPositions]="overlayPositions()"
6831
+ [cdkConnectedOverlayPush]="true"
6832
+ [cdkConnectedOverlayViewportMargin]="shortcutOverlayViewportMargin"
6615
6833
  (backdropClick)="closeShortcuts()"
6616
6834
  (detach)="onOverlayDetach()"
6617
6835
  >
@@ -6623,15 +6841,11 @@ class MaterialDateRangeComponent extends SimpleBaseInputComponent {
6623
6841
  </ng-template>
6624
6842
  }
6625
6843
  </div>
6626
- `, 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 });
6627
6845
  }
6628
6846
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: MaterialDateRangeComponent, decorators: [{
6629
6847
  type: Component,
6630
- args: [{
6631
- selector: 'pdx-material-date-range',
6632
- standalone: true,
6633
- changeDetection: ChangeDetectionStrategy.OnPush,
6634
- template: `
6848
+ args: [{ selector: 'pdx-material-date-range', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: `
6635
6849
  <div class="pdx-date-range-wrap" cdkOverlayOrigin #origin="cdkOverlayOrigin">
6636
6850
  <mat-form-field
6637
6851
  [appearance]="materialAppearance()"
@@ -6675,8 +6889,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
6675
6889
  ? metadata()?.startPlaceholder
6676
6890
  : null)
6677
6891
  "
6892
+ (keydown.tab)="focusEndDateInput($event)"
6678
6893
  />
6679
6894
  <input
6895
+ #endDateInput
6680
6896
  matEndDate
6681
6897
  formControlName="end"
6682
6898
  [attr.placeholder]="
@@ -6715,6 +6931,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
6715
6931
  [startAt]="startAt()"
6716
6932
  [touchUi]="metadata()?.touchUi || false"
6717
6933
  [color]="materialColor()"
6934
+ panelClass="pdx-datepicker-panel"
6718
6935
  ></mat-date-range-picker>
6719
6936
 
6720
6937
 
@@ -6756,6 +6973,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
6756
6973
  [cdkConnectedOverlayHasBackdrop]="true"
6757
6974
  [cdkConnectedOverlayBackdropClass]="'cdk-overlay-transparent-backdrop'"
6758
6975
  [cdkConnectedOverlayPositions]="overlayPositions()"
6976
+ [cdkConnectedOverlayPush]="true"
6977
+ [cdkConnectedOverlayViewportMargin]="shortcutOverlayViewportMargin"
6759
6978
  (backdropClick)="closeShortcuts()"
6760
6979
  (detach)="onOverlayDetach()"
6761
6980
  >
@@ -6767,8 +6986,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
6767
6986
  </ng-template>
6768
6987
  }
6769
6988
  </div>
6770
- `,
6771
- imports: [
6989
+ `, imports: [
6772
6990
  CommonModule,
6773
6991
  MatFormFieldModule,
6774
6992
  MatInputModule,
@@ -6782,15 +7000,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
6782
7000
  PraxisIconDirective,
6783
7001
  ReactiveFormsModule,
6784
7002
  PraxisDateRangeShortcutsOverlayComponent,
6785
- ],
6786
- providers: [
7003
+ ], providers: [
7004
+ { provide: DateAdapter, useClass: PraxisNativeDateAdapter },
7005
+ { provide: MAT_DATE_FORMATS, useValue: MAT_NATIVE_DATE_FORMATS },
6787
7006
  {
6788
7007
  provide: NG_VALUE_ACCESSOR,
6789
7008
  useExisting: forwardRef(() => MaterialDateRangeComponent),
6790
7009
  multi: true,
6791
7010
  },
6792
- ],
6793
- host: {
7011
+ ], host: {
6794
7012
  '[class]': 'componentCssClasses()',
6795
7013
  '[class.praxis-disabled]': 'disabledMode',
6796
7014
  '[style.display]': 'visible ? "block" : "none"',
@@ -6799,8 +7017,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
6799
7017
  '[attr.data-field-type]': '"dateRange"',
6800
7018
  '[attr.data-field-name]': 'metadata()?.name',
6801
7019
  '[attr.data-component-id]': 'componentId()',
6802
- },
6803
- }]
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"] }]
6804
7021
  }], propDecorators: { validationChange: [{ type: i0.Output, args: ["validationChange"] }], readonlyMode: [{
6805
7022
  type: Input
6806
7023
  }], disabledMode: [{
@@ -6815,6 +7032,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
6815
7032
  }], picker: [{
6816
7033
  type: ViewChild,
6817
7034
  args: ['picker', { static: true }]
7035
+ }], endDateInput: [{
7036
+ type: ViewChild,
7037
+ args: ['endDateInput']
6818
7038
  }] } });
6819
7039
 
6820
7040
  const PDX_MATERIAL_DATE_RANGE_EDITORIAL_DESCRIPTOR = {
@@ -6886,6 +7106,9 @@ class MaterialDatepickerComponent extends SimpleBaseInputComponent {
6886
7106
  });
6887
7107
  return st.readonly;
6888
7108
  }
7109
+ isInputReadonly() {
7110
+ return this.isReadonlyEffective() || this.metadata()?.manualInput === false;
7111
+ }
6889
7112
  errorStateMatcher() {
6890
7113
  return getErrorStateMatcherForField(this.metadata());
6891
7114
  }
@@ -6943,7 +7166,8 @@ class MaterialDatepickerComponent extends SimpleBaseInputComponent {
6943
7166
  }
6944
7167
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: MaterialDatepickerComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
6945
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: [
6946
- provideNativeDateAdapter(),
7169
+ { provide: DateAdapter, useClass: PraxisNativeDateAdapter },
7170
+ { provide: MAT_DATE_FORMATS, useValue: MAT_NATIVE_DATE_FORMATS },
6947
7171
  {
6948
7172
  provide: NG_VALUE_ACCESSOR,
6949
7173
  useExisting: forwardRef(() => MaterialDatepickerComponent),
@@ -6974,7 +7198,7 @@ class MaterialDatepickerComponent extends SimpleBaseInputComponent {
6974
7198
  shouldShowPlaceholder && placeholder ? placeholder : null
6975
7199
  "
6976
7200
  [required]="metadata()?.required || false"
6977
- [readonly]="isReadonlyEffective()"
7201
+ [readonly]="isInputReadonly()"
6978
7202
  [min]="minDate()"
6979
7203
  [max]="maxDate()"
6980
7204
  [attr.aria-disabled]="disabledMode ? 'true' : null"
@@ -7036,7 +7260,7 @@ class MaterialDatepickerComponent extends SimpleBaseInputComponent {
7036
7260
  </mat-hint>
7037
7261
  }
7038
7262
  </mat-form-field>
7039
- `, 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"] }] });
7040
7264
  }
7041
7265
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: MaterialDatepickerComponent, decorators: [{
7042
7266
  type: Component,
@@ -7065,7 +7289,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
7065
7289
  shouldShowPlaceholder && placeholder ? placeholder : null
7066
7290
  "
7067
7291
  [required]="metadata()?.required || false"
7068
- [readonly]="isReadonlyEffective()"
7292
+ [readonly]="isInputReadonly()"
7069
7293
  [min]="minDate()"
7070
7294
  [max]="maxDate()"
7071
7295
  [attr.aria-disabled]="disabledMode ? 'true' : null"
@@ -7139,7 +7363,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
7139
7363
  PraxisIconDirective,
7140
7364
  ReactiveFormsModule,
7141
7365
  ], providers: [
7142
- provideNativeDateAdapter(),
7366
+ { provide: DateAdapter, useClass: PraxisNativeDateAdapter },
7367
+ { provide: MAT_DATE_FORMATS, useValue: MAT_NATIVE_DATE_FORMATS },
7143
7368
  {
7144
7369
  provide: NG_VALUE_ACCESSOR,
7145
7370
  useExisting: forwardRef(() => MaterialDatepickerComponent),
@@ -7153,7 +7378,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
7153
7378
  '[attr.data-field-type]': '"date"',
7154
7379
  '[attr.data-field-name]': 'metadata()?.name',
7155
7380
  '[attr.data-component-id]': 'componentId()',
7156
- }, 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"] }]
7157
7382
  }], propDecorators: { validationChange: [{ type: i0.Output, args: ["validationChange"] }], readonlyMode: [{
7158
7383
  type: Input
7159
7384
  }], disabledMode: [{
@@ -7993,6 +8218,12 @@ function formatDisplayValue(field, value, options) {
7993
8218
  const trimmed = value.trim();
7994
8219
  if (!trimmed)
7995
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;
7996
8227
  if (presentation) {
7997
8228
  return formatTypedValue(field, trimmed, presentation);
7998
8229
  }
@@ -8098,6 +8329,77 @@ function formatCurrencyBoundary(field, value, options) {
8098
8329
  return `${currency} ${formatCompactNumber(value)}`;
8099
8330
  }
8100
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
+ }
8101
8403
  /**
8102
8404
  * Formats a value for presentation and linkifies emails/URLs.
8103
8405
  * Rely on Angular's built-in sanitization when binding via [innerHTML].
@@ -8495,6 +8797,9 @@ function normalizeString(value) {
8495
8797
  const trimmed = value.trim();
8496
8798
  return trimmed ? trimmed : undefined;
8497
8799
  }
8800
+ function normalizeComparableString(value) {
8801
+ return normalizeString(value)?.trim().toLowerCase().replace(/[\s_-]+/g, '');
8802
+ }
8498
8803
  function coerceDateValue(value, type) {
8499
8804
  if (value instanceof Date) {
8500
8805
  return value;
@@ -8534,6 +8839,210 @@ function coerceDateOnlyCalendarValue(value) {
8534
8839
  return coerceDateValue(value, 'date');
8535
8840
  }
8536
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
+
8537
9046
  /**
8538
9047
  * Internal wrapper used by {@link DynamicFieldLoaderDirective}.
8539
9048
  *
@@ -8543,27 +9052,60 @@ function coerceDateOnlyCalendarValue(value) {
8543
9052
  */
8544
9053
  class FieldShellComponent {
8545
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;
8546
9066
  /** Metadata for the dynamic field being rendered. */
8547
- field;
9067
+ set field(value) {
9068
+ this._field = value;
9069
+ this.refreshPresentationDisplayValue();
9070
+ }
9071
+ get field() {
9072
+ return this._field;
9073
+ }
8548
9074
  /** Index position of the field within the directive's list. */
8549
9075
  index;
8550
9076
  /** Controle reativo associado (injetado pela diretiva) */
8551
- control;
9077
+ set control(value) {
9078
+ this._control = value;
9079
+ this.bindControlValueChanges();
9080
+ this.refreshPresentationDisplayValue();
9081
+ }
9082
+ get control() {
9083
+ return this._control;
9084
+ }
8552
9085
  /** Estados – podem ser definidos externamente; caso contrário, derivam do metadata */
8553
9086
  readonlyMode = false;
8554
9087
  disabledMode = false;
8555
9088
  visible = true;
8556
- presentationMode = false;
9089
+ set presentationMode(value) {
9090
+ this._presentationMode = value;
9091
+ this.refreshPresentationDisplayValue();
9092
+ }
9093
+ get presentationMode() {
9094
+ return this._presentationMode;
9095
+ }
8557
9096
  /** Special input to enable canvas mode interactions */
8558
9097
  canvasMode = false;
8559
9098
  canvasMouseEnter = new EventEmitter();
8560
9099
  canvasMouseLeave = new EventEmitter();
8561
9100
  canvasClick = new EventEmitter();
8562
9101
  get fieldNameAttr() {
8563
- return this.field.name;
9102
+ return this._field?.name;
8564
9103
  }
8565
9104
  get fieldIdAttr() {
8566
- return this.field.id ?? undefined;
9105
+ return this._field?.id ?? undefined;
9106
+ }
9107
+ fieldLabelText() {
9108
+ return this._field?.label || this._field?.name;
8567
9109
  }
8568
9110
  get fieldControlTypeAttr() {
8569
9111
  const controlType = this.field?.controlType;
@@ -8606,6 +9148,10 @@ class FieldShellComponent {
8606
9148
  itemTemplate;
8607
9149
  /** View container used as the insertion point for the field component. */
8608
9150
  vc;
9151
+ ngOnDestroy() {
9152
+ this.valueSub?.unsubscribe();
9153
+ this.resolveSub?.unsubscribe();
9154
+ }
8609
9155
  /**
8610
9156
  * Defaults derivados dos metadados quando inputs não são explicitamente alterados.
8611
9157
  * - hidden/formHidden => visible=false
@@ -8653,7 +9199,7 @@ class FieldShellComponent {
8653
9199
  }
8654
9200
  }
8655
9201
  getPresentationValue() {
8656
- const raw = this.control?.value;
9202
+ const raw = this.presentationDisplayValue ?? this.control?.value;
8657
9203
  try {
8658
9204
  const fn = this.field?.transformDisplayValue;
8659
9205
  const formatted = typeof fn === 'function'
@@ -8675,9 +9221,14 @@ class FieldShellComponent {
8675
9221
  }
8676
9222
  getPresentationHtml() {
8677
9223
  const raw = this.control?.value;
9224
+ const displayValue = this.presentationDisplayValue;
8678
9225
  try {
8679
9226
  const fn = this.field?.transformDisplayValue;
8680
- const formatted = typeof fn === 'function' ? fn(raw) : null;
9227
+ const formatted = displayValue !== null
9228
+ ? displayValue
9229
+ : typeof fn === 'function'
9230
+ ? fn(raw)
9231
+ : null;
8681
9232
  const val = formatted == null ? raw : formatted;
8682
9233
  return formatDisplayHtml(this.field, val, {
8683
9234
  appLocale: this.hostLocale,
@@ -8693,12 +9244,121 @@ class FieldShellComponent {
8693
9244
  });
8694
9245
  }
8695
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
+ }
8696
9356
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: FieldShellComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
8697
- 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: `
8698
9358
  <div
8699
9359
  class="pfx-field-shell-wrapper"
8700
9360
  [attr.data-field-index]="index"
8701
- [attr.data-field-id]="field.id"
9361
+ [attr.data-field-id]="fieldIdAttr"
8702
9362
  >
8703
9363
  <div
8704
9364
  class="pfx-field-shell-host"
@@ -8711,14 +9371,40 @@ class FieldShellComponent {
8711
9371
  >
8712
9372
  <!-- Presentation block -->
8713
9373
  @if (effectivePresentationMode && !renderContentInPresentation()) {
8714
- <div class="praxis-presentation" [attr.data-field]="field.name">
9374
+ <div class="praxis-presentation" [attr.data-field]="fieldNameAttr">
8715
9375
  <span class="praxis-presentation__label">{{
8716
- field.label || field.name
9376
+ fieldLabelText()
8717
9377
  }}</span>
8718
- <span
8719
- class="praxis-presentation__value"
8720
- [innerHTML]="getPresentationHtml()"
8721
- ></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>
8722
9408
  </div>
8723
9409
  }
8724
9410
 
@@ -8759,15 +9445,15 @@ class FieldShellComponent {
8759
9445
 
8760
9446
  </div>
8761
9447
  </div>
8762
- `, 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 });
8763
9449
  }
8764
9450
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: FieldShellComponent, decorators: [{
8765
9451
  type: Component,
8766
- 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: `
8767
9453
  <div
8768
9454
  class="pfx-field-shell-wrapper"
8769
9455
  [attr.data-field-index]="index"
8770
- [attr.data-field-id]="field.id"
9456
+ [attr.data-field-id]="fieldIdAttr"
8771
9457
  >
8772
9458
  <div
8773
9459
  class="pfx-field-shell-host"
@@ -8780,14 +9466,40 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
8780
9466
  >
8781
9467
  <!-- Presentation block -->
8782
9468
  @if (effectivePresentationMode && !renderContentInPresentation()) {
8783
- <div class="praxis-presentation" [attr.data-field]="field.name">
9469
+ <div class="praxis-presentation" [attr.data-field]="fieldNameAttr">
8784
9470
  <span class="praxis-presentation__label">{{
8785
- field.label || field.name
9471
+ fieldLabelText()
8786
9472
  }}</span>
8787
- <span
8788
- class="praxis-presentation__value"
8789
- [innerHTML]="getPresentationHtml()"
8790
- ></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>
8791
9503
  </div>
8792
9504
  }
8793
9505
 
@@ -8828,7 +9540,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
8828
9540
 
8829
9541
  </div>
8830
9542
  </div>
8831
- `, 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"] }]
8832
9544
  }], propDecorators: { field: [{
8833
9545
  type: Input
8834
9546
  }], index: [{
@@ -9320,6 +10032,22 @@ class DynamicFieldLoaderDirective {
9320
10032
  this.rebindControlsOnly();
9321
10033
  return;
9322
10034
  }
10035
+ const sameRenderShape = this.hasSameRenderShape(this.lastFieldsSnapshot, newSnapshot);
10036
+ if (sameRenderShape && this.updateExistingFieldMetadata(this.fields || [])) {
10037
+ this.dbg('[DFL] ngOnChanges: updated existing field metadata in place');
10038
+ this.traceLog('ngOnChanges:update-metadata-in-place', {
10039
+ reason: 'same field names/controlTypes with metadata changes',
10040
+ changedKeys: Object.keys(changes || {}),
10041
+ formGroupRefChanged,
10042
+ });
10043
+ this._dbgPrevFieldsRef = this.fields;
10044
+ this._dbgPrevFormGroupRef = this.formGroup;
10045
+ if (formGroupRefChanged) {
10046
+ this.rebindControlsOnly();
10047
+ }
10048
+ this.lastFieldsSnapshot = newSnapshot;
10049
+ return;
10050
+ }
9323
10051
  this._dbgPrevFieldsRef = this.fields;
9324
10052
  this._dbgPrevFormGroupRef = this.formGroup;
9325
10053
  this.traceLog('ngOnChanges:renderFields', {
@@ -9652,6 +10380,69 @@ class DynamicFieldLoaderDirective {
9652
10380
  /**
9653
10381
  * Reatribui apenas os FormControls existentes aos componentes/shells sem refazer a renderização.
9654
10382
  */
10383
+ hasSameRenderShape(previous, next) {
10384
+ if (!previous.length || previous.length !== next.length) {
10385
+ return false;
10386
+ }
10387
+ return next.every((field, index) => {
10388
+ const current = previous[index];
10389
+ return current?.name === field.name && current?.controlType === field.controlType;
10390
+ });
10391
+ }
10392
+ updateExistingFieldMetadata(fields) {
10393
+ if (!fields.length || fields.length !== this.currentOrder.length) {
10394
+ return false;
10395
+ }
10396
+ for (const field of fields) {
10397
+ if (!this.componentRefs.has(field.name) || !this.shellRefs.has(field.name)) {
10398
+ return false;
10399
+ }
10400
+ }
10401
+ for (const [index, field] of fields.entries()) {
10402
+ const fieldWithId = field.id ? field : { ...field, id: field.name };
10403
+ const shellRef = this.shellRefs.get(field.name);
10404
+ if (shellRef) {
10405
+ shellRef.instance.field = fieldWithId;
10406
+ shellRef.instance.index = index;
10407
+ shellRef.instance.control = this.formGroup?.get(field.name);
10408
+ try {
10409
+ shellRef.changeDetectorRef.detectChanges();
10410
+ }
10411
+ catch { }
10412
+ }
10413
+ const compRef = this.componentRefs.get(field.name);
10414
+ if (!compRef) {
10415
+ return false;
10416
+ }
10417
+ const instance = compRef.instance;
10418
+ if (typeof instance.setInputMetadata === 'function') {
10419
+ try {
10420
+ instance.setInputMetadata(fieldWithId);
10421
+ }
10422
+ catch {
10423
+ return false;
10424
+ }
10425
+ }
10426
+ else if (instance?.metadata && typeof instance.metadata === 'function' && 'set' in instance.metadata) {
10427
+ try {
10428
+ instance.metadata.set(fieldWithId);
10429
+ }
10430
+ catch {
10431
+ return false;
10432
+ }
10433
+ }
10434
+ else {
10435
+ return false;
10436
+ }
10437
+ try {
10438
+ compRef.changeDetectorRef.detectChanges();
10439
+ }
10440
+ catch { }
10441
+ }
10442
+ this.currentOrder = fields.map((field) => field.name);
10443
+ this.componentsCreated.emit(new Map(this.componentRefs));
10444
+ return true;
10445
+ }
9655
10446
  rebindControlsOnly() {
9656
10447
  this.dbg('[DFL] rebindControlsOnly: start');
9657
10448
  const fieldNames = this.currentOrder.length
@@ -10504,6 +11295,7 @@ class MaterialAsyncSelectComponent extends SimpleBaseSelectComponent {
10504
11295
  if (mappedOptions)
10505
11296
  this.options.set(mappedOptions);
10506
11297
  this.multiple.set(!!metadata.multiple);
11298
+ this.normalizeMultipleControlValue();
10507
11299
  this.searchable.set(metadata.searchable ?? !isCategoricalBucket);
10508
11300
  this.selectAll.set(!!metadata.selectAll);
10509
11301
  this.maxSelections.set(metadata.maxSelections ?? null);
@@ -10830,7 +11622,7 @@ class MaterialAsyncSelectComponent extends SimpleBaseSelectComponent {
10830
11622
  enhanced.displayWith = (opt) => opt && typeof opt === 'object' && 'label' in opt
10831
11623
  ? String(opt.label ?? '')
10832
11624
  : '';
10833
- enhanced.compareWith = (a, b) => this.areRemoteOptionValuesEqual(a, b);
11625
+ enhanced.compareWith = (a, b) => this.areOptionValuesEqual(a, b);
10834
11626
  }
10835
11627
  // ---------------------------------------------------------------------------
10836
11628
  // Phase 1: explicit reload API and dependency handling
@@ -10896,7 +11688,7 @@ class MaterialAsyncSelectComponent extends SimpleBaseSelectComponent {
10896
11688
  if (!selected.length) {
10897
11689
  return;
10898
11690
  }
10899
- 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)));
10900
11692
  if (hasAllSelectedOptions) {
10901
11693
  return;
10902
11694
  }
@@ -10921,7 +11713,7 @@ class MaterialAsyncSelectComponent extends SimpleBaseSelectComponent {
10921
11713
  resolveRemoteOptionDisabled(option) {
10922
11714
  return option.extra?.['selectable'] === false;
10923
11715
  }
10924
- areRemoteOptionValuesEqual(left, right) {
11716
+ areOptionValuesEqual(left, right) {
10925
11717
  return this.normalizeRemoteOptionValue(left) === this.normalizeRemoteOptionValue(right);
10926
11718
  }
10927
11719
  normalizeRemoteOptionValue(value) {
@@ -10973,15 +11765,13 @@ class MaterialAsyncSelectComponent extends SimpleBaseSelectComponent {
10973
11765
  <mat-option
10974
11766
  *ngIf="!multiple() && emptyOptionText()"
10975
11767
  [value]="null"
10976
- (click)="selectOption({ label: emptyOptionText()!, value: null })"
10977
11768
  >
10978
11769
  {{ emptyOptionText() }}
10979
11770
  </mat-option>
10980
11771
  <mat-option
10981
11772
  *ngFor="let option of options(); trackBy: trackByOption"
10982
11773
  [value]="option.value"
10983
- [disabled]="option.disabled"
10984
- (click)="selectOption(option)"
11774
+ [disabled]="isOptionDisabled(option)"
10985
11775
  >
10986
11776
  {{ option.label }}
10987
11777
  </mat-option>
@@ -11084,15 +11874,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
11084
11874
  <mat-option
11085
11875
  *ngIf="!multiple() && emptyOptionText()"
11086
11876
  [value]="null"
11087
- (click)="selectOption({ label: emptyOptionText()!, value: null })"
11088
11877
  >
11089
11878
  {{ emptyOptionText() }}
11090
11879
  </mat-option>
11091
11880
  <mat-option
11092
11881
  *ngFor="let option of options(); trackBy: trackByOption"
11093
11882
  [value]="option.value"
11094
- [disabled]="option.disabled"
11095
- (click)="selectOption(option)"
11883
+ [disabled]="isOptionDisabled(option)"
11096
11884
  >
11097
11885
  {{ option.label }}
11098
11886
  </mat-option>
@@ -11777,6 +12565,15 @@ class InlineEntityLookupComponent extends MaterialAsyncSelectComponent {
11777
12565
  dialogClearFiltersActionText() {
11778
12566
  return this.tDynamicFields('entityLookup.dialog.filters.clear', 'Limpar filtros');
11779
12567
  }
12568
+ dialogFilterSelectEmptyText(label) {
12569
+ return this.tDynamicFields('entityLookup.dialog.filters.selectEmpty', 'Selecione {label}', { label: label.toLowerCase() });
12570
+ }
12571
+ dialogFilterStartAriaLabelText(label) {
12572
+ return this.tDynamicFields('entityLookup.dialog.filters.startAriaLabel', '{label} inicial', { label });
12573
+ }
12574
+ dialogFilterEndAriaLabelText(label) {
12575
+ return this.tDynamicFields('entityLookup.dialog.filters.endAriaLabel', '{label} final', { label });
12576
+ }
11780
12577
  dialogPreviewSelectionStateLabelText() {
11781
12578
  return this.tDynamicFields('entityLookup.dialog.preview.selectionState', 'Estado');
11782
12579
  }
@@ -12781,7 +13578,6 @@ class InlineEntityLookupComponent extends MaterialAsyncSelectComponent {
12781
13578
  <mat-option
12782
13579
  *ngIf="!multiple() && emptyOptionText()"
12783
13580
  [value]="null"
12784
- (click)="selectOption({ label: emptyOptionText()!, value: null })"
12785
13581
  >
12786
13582
  {{ emptyOptionText() }}
12787
13583
  </mat-option>
@@ -12789,8 +13585,7 @@ class InlineEntityLookupComponent extends MaterialAsyncSelectComponent {
12789
13585
  <mat-option
12790
13586
  *ngFor="let option of options(); trackBy: trackByOption"
12791
13587
  [value]="option.value"
12792
- [disabled]="option.disabled"
12793
- (click)="selectOption(option)"
13588
+ [disabled]="isOptionDisabled(option)"
12794
13589
  >
12795
13590
  @if (richLayoutEnabled()) {
12796
13591
  @if (optionLookupView(option); as item) {
@@ -13198,7 +13993,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
13198
13993
  <mat-option
13199
13994
  *ngIf="!multiple() && emptyOptionText()"
13200
13995
  [value]="null"
13201
- (click)="selectOption({ label: emptyOptionText()!, value: null })"
13202
13996
  >
13203
13997
  {{ emptyOptionText() }}
13204
13998
  </mat-option>
@@ -13206,8 +14000,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
13206
14000
  <mat-option
13207
14001
  *ngFor="let option of options(); trackBy: trackByOption"
13208
14002
  [value]="option.value"
13209
- [disabled]="option.disabled"
13210
- (click)="selectOption(option)"
14003
+ [disabled]="isOptionDisabled(option)"
13211
14004
  >
13212
14005
  @if (richLayoutEnabled()) {
13213
14006
  @if (optionLookupView(option); as item) {
@@ -13322,6 +14115,7 @@ class EntityLookupDialogComponent {
13322
14115
  dialogSearchControl = new FormControl('');
13323
14116
  filterPanelOpen = new FormControl(false, { nonNullable: true });
13324
14117
  dialogFilterControls = new Map();
14118
+ dialogFilterSecondaryControls = new Map();
13325
14119
  previewIdentity = null;
13326
14120
  activeResultIndex = 0;
13327
14121
  ngAfterViewInit() {
@@ -13411,6 +14205,15 @@ class EntityLookupDialogComponent {
13411
14205
  this.dialogFilterControls.set(field, created);
13412
14206
  return created;
13413
14207
  }
14208
+ filterSecondaryControl(field) {
14209
+ const existing = this.dialogFilterSecondaryControls.get(field);
14210
+ if (existing) {
14211
+ return existing;
14212
+ }
14213
+ const created = new FormControl('', { nonNullable: true });
14214
+ this.dialogFilterSecondaryControls.set(field, created);
14215
+ return created;
14216
+ }
13414
14217
  dialogFilterLabel(definition) {
13415
14218
  return definition.label || this.humanizeColumnField(definition.field);
13416
14219
  }
@@ -13418,6 +14221,62 @@ class EntityLookupDialogComponent {
13418
14221
  const operator = definition.defaultOperator ?? definition.operators[0];
13419
14222
  return this.lookup().dialogFilterPlaceholderText(operator, definition.type);
13420
14223
  }
14224
+ dialogFilterRangeEndPlaceholder(definition) {
14225
+ return definition.type === 'date'
14226
+ ? this.lookup().dialogFilterPlaceholderText('between', 'date')
14227
+ : this.lookup().dialogFilterPlaceholderText('between', definition.type);
14228
+ }
14229
+ dialogFilterStartAriaLabel(definition) {
14230
+ return this.lookup().dialogFilterStartAriaLabelText(this.dialogFilterLabel(definition));
14231
+ }
14232
+ dialogFilterEndAriaLabel(definition) {
14233
+ return this.lookup().dialogFilterEndAriaLabelText(this.dialogFilterLabel(definition));
14234
+ }
14235
+ dialogFilterInputType(definition) {
14236
+ if (definition.type === 'date') {
14237
+ return 'date';
14238
+ }
14239
+ if (definition.type === 'number') {
14240
+ return 'number';
14241
+ }
14242
+ return 'text';
14243
+ }
14244
+ useDialogEnumSelect(definition) {
14245
+ return definition.type === 'enum' && !this.useDialogMultiSelect(definition);
14246
+ }
14247
+ useDialogMultiSelect(definition) {
14248
+ const operator = definition.defaultOperator ?? definition.operators[0];
14249
+ return definition.type === 'enum' && operator === 'in';
14250
+ }
14251
+ useDialogRangeInputs(definition) {
14252
+ const operator = definition.defaultOperator ?? definition.operators[0];
14253
+ return operator === 'between' && (definition.type === 'date' || definition.type === 'number');
14254
+ }
14255
+ dialogFilterSelectEmptyText(definition) {
14256
+ return this.lookup().dialogFilterSelectEmptyText(this.dialogFilterLabel(definition));
14257
+ }
14258
+ dialogEnumOptions(definition) {
14259
+ const values = new Map();
14260
+ const defaultValues = this.data.metadata.optionSource?.filtering?.defaultFilters?.[definition.field];
14261
+ if (Array.isArray(defaultValues)) {
14262
+ for (const value of defaultValues) {
14263
+ this.pushDialogEnumOption(values, value);
14264
+ }
14265
+ }
14266
+ const activeFilter = this.lookup().lookupFilterForField(definition.field)?.value;
14267
+ if (Array.isArray(activeFilter)) {
14268
+ for (const value of activeFilter) {
14269
+ this.pushDialogEnumOption(values, value);
14270
+ }
14271
+ }
14272
+ else if (activeFilter !== null && activeFilter !== undefined && activeFilter !== '') {
14273
+ this.pushDialogEnumOption(values, activeFilter);
14274
+ }
14275
+ for (const option of this.resultOptions()) {
14276
+ this.pushDialogEnumOption(values, this.resolveDialogFilterFieldValue(option, definition.field));
14277
+ }
14278
+ return Array.from(values.entries()).map(([value, label]) => ({ value, label }));
14279
+ }
13421
14280
  dialogOperatorHint(definition) {
13422
14281
  const operator = definition.defaultOperator ?? definition.operators[0];
13423
14282
  return this.lookup().dialogFilterOperatorHintText(operator);
@@ -13436,7 +14295,8 @@ class EntityLookupDialogComponent {
13436
14295
  }
13437
14296
  resetDialogFilters() {
13438
14297
  for (const definition of this.dialogFilterDefinitions()) {
13439
- this.filterControl(definition.field).setValue('');
14298
+ this.filterControl(definition.field).setValue(this.dialogFilterEmptyValue(definition));
14299
+ this.filterSecondaryControl(definition.field).setValue('');
13440
14300
  }
13441
14301
  this.lookup().clearLookupFilters();
13442
14302
  }
@@ -13703,46 +14563,114 @@ class EntityLookupDialogComponent {
13703
14563
  initializeDialogFilters() {
13704
14564
  for (const definition of this.dialogFilterDefinitions()) {
13705
14565
  const current = this.lookup().lookupFilterForField(definition.field);
13706
- this.filterControl(definition.field).setValue(this.serializeDialogFilterValue(current?.value));
14566
+ const operator = definition.defaultOperator ?? definition.operators[0];
14567
+ if (this.useDialogMultiSelect(definition)) {
14568
+ const values = Array.isArray(current?.value)
14569
+ ? current?.value.map((item) => this.serializeDialogFilterScalarValue(item))
14570
+ : current?.value === null || current?.value === undefined || current?.value === ''
14571
+ ? []
14572
+ : [this.serializeDialogFilterScalarValue(current.value)];
14573
+ this.filterControl(definition.field).setValue(values);
14574
+ this.filterSecondaryControl(definition.field).setValue('');
14575
+ continue;
14576
+ }
14577
+ if (this.useDialogRangeInputs(definition)) {
14578
+ const values = Array.isArray(current?.value) ? current.value : [];
14579
+ this.filterControl(definition.field).setValue(this.serializeDialogFilterScalarValue(values[0]));
14580
+ this.filterSecondaryControl(definition.field).setValue(this.serializeDialogFilterScalarValue(values[1]));
14581
+ continue;
14582
+ }
14583
+ this.filterControl(definition.field).setValue(this.serializeDialogFilterSingleValue(current?.value, operator));
14584
+ this.filterSecondaryControl(definition.field).setValue('');
13707
14585
  }
13708
14586
  }
13709
- serializeDialogFilterValue(value) {
14587
+ dialogFilterEmptyValue(definition) {
14588
+ return this.useDialogMultiSelect(definition) ? [] : '';
14589
+ }
14590
+ serializeDialogFilterSingleValue(value, operator) {
13710
14591
  if (Array.isArray(value)) {
13711
- return value.map((item) => this.serializeDialogFilterValue(item)).join(', ');
14592
+ if (operator === 'in') {
14593
+ return value.map((item) => this.serializeDialogFilterScalarValue(item)).join(', ');
14594
+ }
14595
+ return this.serializeDialogFilterScalarValue(value[0]);
13712
14596
  }
14597
+ return this.serializeDialogFilterScalarValue(value);
14598
+ }
14599
+ serializeDialogFilterScalarValue(value) {
13713
14600
  if (value === null || value === undefined) {
13714
14601
  return '';
13715
14602
  }
13716
14603
  return String(value);
13717
14604
  }
13718
14605
  buildDialogFilterRequest(definition) {
13719
- const rawInput = this.filterControl(definition.field).value.trim();
13720
- if (!rawInput) {
14606
+ const operator = definition.defaultOperator ?? definition.operators[0];
14607
+ const value = this.normalizeDialogFilterControlValue(definition, operator, this.filterControl(definition.field).value, this.filterSecondaryControl(definition.field).value);
14608
+ if (value === undefined) {
13721
14609
  return undefined;
13722
14610
  }
13723
- const operator = definition.defaultOperator ?? definition.operators[0];
13724
14611
  return {
13725
14612
  field: definition.field,
13726
14613
  operator,
13727
- value: this.parseDialogFilterValue(definition.type, operator, rawInput),
14614
+ value,
13728
14615
  };
13729
14616
  }
13730
- parseDialogFilterValue(type, operator, rawInput) {
13731
- const parts = rawInput
13732
- .split(',')
13733
- .map((item) => item.trim())
13734
- .filter((item) => !!item);
13735
- const values = operator === 'between' ? parts.slice(0, 2) : operator === 'in' ? parts : [rawInput];
13736
- return operator === 'between' || operator === 'in'
13737
- ? values.map((item) => this.parseDialogFilterPrimitive(type, item))
13738
- : this.parseDialogFilterPrimitive(type, values[0] ?? rawInput);
14617
+ normalizeDialogFilterControlValue(definition, operator, primaryValue, secondaryValue) {
14618
+ if (this.useDialogMultiSelect(definition)) {
14619
+ const values = Array.isArray(primaryValue)
14620
+ ? primaryValue
14621
+ .map((item) => this.normalizeDialogFilterScalarValue(definition.type, item))
14622
+ .filter((item) => item !== undefined)
14623
+ : [];
14624
+ return values.length ? values : undefined;
14625
+ }
14626
+ if (this.useDialogRangeInputs(definition)) {
14627
+ const start = this.normalizeDialogFilterScalarValue(definition.type, primaryValue);
14628
+ const end = this.normalizeDialogFilterScalarValue(definition.type, secondaryValue);
14629
+ if (start === undefined && end === undefined) {
14630
+ return undefined;
14631
+ }
14632
+ if (start === undefined || end === undefined) {
14633
+ return undefined;
14634
+ }
14635
+ return [start, end];
14636
+ }
14637
+ if (operator === 'in') {
14638
+ const rawInput = String(primaryValue ?? '').trim();
14639
+ if (!rawInput) {
14640
+ return undefined;
14641
+ }
14642
+ const values = rawInput
14643
+ .split(',')
14644
+ .map((item) => this.normalizeDialogFilterScalarValue(definition.type, item))
14645
+ .filter((item) => item !== undefined);
14646
+ return values.length ? values : undefined;
14647
+ }
14648
+ return this.normalizeDialogFilterScalarValue(definition.type, primaryValue);
13739
14649
  }
13740
- parseDialogFilterPrimitive(type, value) {
13741
- if (type !== 'number') {
13742
- return value;
14650
+ normalizeDialogFilterScalarValue(type, value) {
14651
+ const text = String(value ?? '').trim();
14652
+ if (!text) {
14653
+ return undefined;
13743
14654
  }
13744
- const numeric = Number(value);
13745
- return Number.isFinite(numeric) ? numeric : value;
14655
+ if (type === 'date' || type === 'text' || type === 'reference' || type === 'enum') {
14656
+ return text;
14657
+ }
14658
+ const numeric = Number(text);
14659
+ return Number.isFinite(numeric) ? numeric : undefined;
14660
+ }
14661
+ resolveDialogFilterFieldValue(option, field) {
14662
+ const value = option.value;
14663
+ if (value && typeof value === 'object' && field in value) {
14664
+ return value[field];
14665
+ }
14666
+ return undefined;
14667
+ }
14668
+ pushDialogEnumOption(target, value) {
14669
+ const normalized = this.serializeDialogFilterScalarValue(value);
14670
+ if (!normalized || target.has(normalized)) {
14671
+ return;
14672
+ }
14673
+ target.set(normalized, normalized);
13746
14674
  }
13747
14675
  syncPreviewIdentity() {
13748
14676
  const selected = this.lookup().selectedLookupView();
@@ -13897,11 +14825,57 @@ class EntityLookupDialogComponent {
13897
14825
  *ngFor="let definition of dialogFilterDefinitions()"
13898
14826
  >
13899
14827
  <span>{{ dialogFilterLabel(definition) }}</span>
13900
- <input
13901
- type="text"
13902
- [formControl]="filterControl(definition.field)"
13903
- [placeholder]="dialogFilterPlaceholder(definition)"
13904
- />
14828
+ @if (useDialogMultiSelect(definition)) {
14829
+ <select
14830
+ multiple
14831
+ class="pdx-lookup-dialog-filter-select is-multiple"
14832
+ [formControl]="filterControl(definition.field)"
14833
+ [attr.aria-label]="dialogFilterLabel(definition)"
14834
+ >
14835
+ <option
14836
+ *ngFor="let option of dialogEnumOptions(definition)"
14837
+ [value]="option.value"
14838
+ >
14839
+ {{ option.label }}
14840
+ </option>
14841
+ </select>
14842
+ } @else if (useDialogRangeInputs(definition)) {
14843
+ <span class="pdx-lookup-dialog-filter-range">
14844
+ <input
14845
+ [type]="dialogFilterInputType(definition)"
14846
+ [formControl]="filterControl(definition.field)"
14847
+ [placeholder]="dialogFilterPlaceholder(definition)"
14848
+ [attr.aria-label]="dialogFilterStartAriaLabel(definition)"
14849
+ />
14850
+ <input
14851
+ [type]="dialogFilterInputType(definition)"
14852
+ [formControl]="filterSecondaryControl(definition.field)"
14853
+ [placeholder]="dialogFilterRangeEndPlaceholder(definition)"
14854
+ [attr.aria-label]="dialogFilterEndAriaLabel(definition)"
14855
+ />
14856
+ </span>
14857
+ } @else if (useDialogEnumSelect(definition)) {
14858
+ <select
14859
+ class="pdx-lookup-dialog-filter-select"
14860
+ [formControl]="filterControl(definition.field)"
14861
+ [attr.aria-label]="dialogFilterLabel(definition)"
14862
+ >
14863
+ <option value="">{{ dialogFilterSelectEmptyText(definition) }}</option>
14864
+ <option
14865
+ *ngFor="let option of dialogEnumOptions(definition)"
14866
+ [value]="option.value"
14867
+ >
14868
+ {{ option.label }}
14869
+ </option>
14870
+ </select>
14871
+ } @else {
14872
+ <input
14873
+ [type]="dialogFilterInputType(definition)"
14874
+ [formControl]="filterControl(definition.field)"
14875
+ [placeholder]="dialogFilterPlaceholder(definition)"
14876
+ [attr.aria-label]="dialogFilterLabel(definition)"
14877
+ />
14878
+ }
13905
14879
  <small>{{ dialogOperatorHint(definition) }}</small>
13906
14880
  </label>
13907
14881
  </div>
@@ -14156,7 +15130,7 @@ class EntityLookupDialogComponent {
14156
15130
  {{ applyText() }}
14157
15131
  </button>
14158
15132
  </mat-dialog-actions>
14159
- `, isInline: true, styles: [".pdx-lookup-dialog-toolbar{display:flex;flex-wrap:wrap;gap:12px;align-items:start}.pdx-lookup-dialog-intro{display:grid;gap:4px;margin:0 0 12px}.pdx-lookup-dialog-intro strong{color:var(--md-sys-color-on-surface);font-size:.96rem;line-height:1.3}.pdx-lookup-dialog-intro span{color:var(--md-sys-color-on-surface-variant);font-size:.82rem;line-height:1.35}.pdx-lookup-dialog-search{flex:1 1 320px}.pdx-lookup-dialog-sort{display:inline-flex;align-items:center;gap:8px;min-height:56px;color:var(--md-sys-color-on-surface-variant);font-size:.85rem}.pdx-lookup-dialog-sort select{min-width:180px;min-height:40px;border:1px solid var(--md-sys-color-outline-variant);border-radius:6px;background:var(--md-sys-color-surface);color:var(--md-sys-color-on-surface);padding:0 10px}.pdx-lookup-dialog-filter-panel{display:flex;flex-direction:column;gap:12px;padding:12px;margin:8px 0 12px;border:1px solid var(--md-sys-color-outline-variant);border-radius:8px;background:var(--md-sys-color-surface-container-lowest)}.pdx-lookup-dialog-filter-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:12px}.pdx-lookup-dialog-filter-field{display:flex;flex-direction:column;gap:6px;color:var(--md-sys-color-on-surface);font-size:.9rem}.pdx-lookup-dialog-filter-field input{min-height:40px;border:1px solid var(--md-sys-color-outline-variant);border-radius:6px;background:var(--md-sys-color-surface);color:var(--md-sys-color-on-surface);padding:0 10px}.pdx-lookup-dialog-filter-field small{color:var(--md-sys-color-on-surface-variant)}.pdx-lookup-dialog-filter-actions{display:flex;justify-content:flex-end;gap:8px}.pdx-lookup-dialog-summary{margin:8px 0 12px;display:flex;flex-wrap:wrap;gap:8px;color:var(--md-sys-color-on-surface-variant);font-size:.85rem}.pdx-lookup-dialog-summary-warning{color:var(--md-sys-color-error)}.pdx-lookup-dialog-content-grid{display:block}.pdx-lookup-dialog-content-grid.has-preview{display:grid;grid-template-columns:minmax(0,1fr) 280px;gap:16px;align-items:start}.pdx-lookup-dialog-results{display:flex;flex-direction:column;gap:10px;max-height:52vh;overflow:auto;padding-right:4px}.pdx-lookup-dialog-results.is-card-layout{gap:12px}.pdx-lookup-dialog-results.is-compact-layout{gap:6px}.pdx-lookup-dialog-table{display:flex;flex-direction:column;border:1px solid var(--md-sys-color-outline-variant);border-radius:8px;overflow:hidden}.pdx-lookup-dialog-table-head,.pdx-lookup-dialog-table-row{display:flex;align-items:stretch}.pdx-lookup-dialog-table-head{background:var(--md-sys-color-surface-container-low);border-bottom:1px solid var(--md-sys-color-outline-variant)}.pdx-lookup-dialog-table-row{width:100%;text-align:left;border:0;border-bottom:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface);color:var(--md-sys-color-on-surface);cursor:pointer}.pdx-lookup-dialog-table-row:last-child{border-bottom:0}.pdx-lookup-dialog-table-row.is-selected{background:color-mix(in srgb,var(--md-sys-color-primary) 8%,var(--md-sys-color-surface))}.pdx-lookup-dialog-table-row.is-disabled{opacity:.65;cursor:not-allowed}.pdx-lookup-dialog-table-row.is-blocked,.pdx-lookup-dialog-row.is-blocked{background:color-mix(in srgb,var(--md-sys-color-error) 4%,var(--md-sys-color-surface))}.pdx-lookup-dialog-table-row.is-legacy,.pdx-lookup-dialog-row.is-legacy{background:color-mix(in srgb,var(--md-sys-color-tertiary) 8%,var(--md-sys-color-surface))}.pdx-lookup-dialog-table-cell{min-width:0;padding:10px 12px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.pdx-lookup-dialog-table-cell.is-head{font-size:.78rem;font-weight:600;color:var(--md-sys-color-on-surface-variant)}.pdx-lookup-dialog-row{display:block;width:100%;text-align:left;border:1px solid var(--md-sys-color-outline-variant);border-radius:8px;background:var(--md-sys-color-surface);color:var(--md-sys-color-on-surface);padding:12px 14px;cursor:pointer}.pdx-lookup-dialog-row.is-selected{border-color:var(--md-sys-color-primary);box-shadow:inset 0 0 0 1px var(--md-sys-color-primary);background:color-mix(in srgb,var(--md-sys-color-primary) 8%,var(--md-sys-color-surface))}.pdx-lookup-dialog-row.is-disabled{opacity:.65;cursor:not-allowed}.pdx-lookup-dialog-row-main,.pdx-lookup-dialog-row-heading,.pdx-lookup-dialog-row-meta{display:flex;flex-wrap:wrap;gap:8px}.pdx-lookup-dialog-row-main{flex-direction:column;gap:8px}.pdx-lookup-dialog-row-heading strong{font-size:.98rem;line-height:1.3}.pdx-lookup-dialog-row-heading small{border-radius:6px;padding:2px 6px;background:var(--md-sys-color-surface-container-high);color:var(--md-sys-color-on-surface-variant);font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;font-size:.74rem;line-height:1.2}.pdx-lookup-dialog-results.is-card-layout .pdx-lookup-dialog-row-main{display:grid;grid-template-columns:auto minmax(0,1fr);align-items:start;gap:12px}.pdx-lookup-dialog-results.is-compact-layout .pdx-lookup-dialog-row{padding:8px 10px}.pdx-lookup-dialog-results.is-compact-layout .pdx-lookup-dialog-row-heading,.pdx-lookup-dialog-results.is-compact-layout .pdx-lookup-dialog-row-meta{gap:6px}.pdx-lookup-dialog-results.is-compact-layout .pdx-lookup-dialog-row-description{font-size:.85rem}.pdx-lookup-dialog-row-description{color:var(--md-sys-color-on-surface-variant);line-height:1.35}.pdx-lookup-dialog-row-meta{align-items:center}.pdx-lookup-dialog-row-note,.pdx-lookup-option-note{display:inline-flex;align-items:center;min-height:24px;padding:4px 8px;border-radius:8px;font-size:.76rem;line-height:1.3}.pdx-lookup-dialog-row-note.is-warning,.pdx-lookup-option-note.is-warning{background:#fffbeb;color:#92400e}.pdx-lookup-dialog-row-note.is-danger,.pdx-lookup-option-note.is-danger{background:#fef2f2;color:#991b1b}.pdx-lookup-dialog-state,.pdx-lookup-dialog-footer-row{display:flex;align-items:center;gap:10px;justify-content:center;padding:16px 0 4px}.pdx-lookup-dialog-runtime-host{display:none}.pdx-lookup-dialog-preview{border:1px solid var(--md-sys-color-outline-variant);border-radius:8px;background:var(--md-sys-color-surface-container-lowest);padding:14px;display:flex;flex-direction:column;gap:10px;position:sticky;top:0}.pdx-lookup-dialog-preview-meta{display:flex;flex-wrap:wrap;align-items:center;gap:8px}.pdx-lookup-dialog-preview-heading{display:flex;flex-direction:column;gap:4px}.pdx-lookup-dialog-preview-heading small,.pdx-lookup-dialog-preview-description,.pdx-lookup-dialog-preview-grid dt{color:var(--md-sys-color-on-surface-variant)}.pdx-lookup-dialog-preview-badges{display:flex;flex-wrap:wrap;gap:8px}.pdx-lookup-dialog-preview-note{display:grid;gap:2px;padding:8px 10px;border-radius:8px;border:1px solid transparent;font-size:.78rem;line-height:1.35}.pdx-lookup-dialog-preview-note strong{font-size:.72rem;line-height:1.2;text-transform:uppercase;letter-spacing:.02em}.pdx-lookup-dialog-preview-note.is-warning{background:#fffbeb;border-color:#fde68a;color:#92400e}.pdx-lookup-dialog-preview-note.is-danger{background:#fef2f2;border-color:#fecaca;color:#991b1b}.pdx-lookup-dialog-preview-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px;margin:0}.pdx-lookup-dialog-preview-grid div{min-width:0}.pdx-lookup-dialog-preview-grid dt{font-size:.78rem;margin-bottom:2px}.pdx-lookup-dialog-preview-grid dd{margin:0;overflow-wrap:anywhere}.pdx-lookup-dialog-preview-actions{display:flex;flex-wrap:wrap;gap:8px}@media(max-width:960px){.pdx-lookup-dialog-toolbar{flex-direction:column;align-items:stretch}.pdx-lookup-dialog-search,.pdx-lookup-dialog-sort{width:100%;flex:1 1 auto}.pdx-lookup-dialog-sort{min-height:0;flex-direction:column;align-items:stretch}.pdx-lookup-dialog-sort select{width:100%;min-width:0}.pdx-lookup-dialog-content-grid.has-preview{grid-template-columns:minmax(0,1fr)}.pdx-lookup-dialog-preview{position:static}}@media(max-width:640px){.pdx-lookup-dialog-intro{margin-bottom:10px}.pdx-lookup-dialog-results{max-height:none;padding-right:0}.pdx-lookup-dialog-row{padding:10px 12px}.pdx-lookup-dialog-results.is-card-layout .pdx-lookup-dialog-row-main{grid-template-columns:minmax(0,1fr)}.pdx-lookup-dialog-preview{padding:12px}.pdx-lookup-dialog-preview-grid{grid-template-columns:minmax(0,1fr)}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$1.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { 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.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatDialogModule }, { kind: "directive", type: i1$3.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: i1$3.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "directive", type: i1$3.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i1$2.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { 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.MatPrefix, selector: "[matPrefix], [matIconPrefix], [matTextPrefix]", inputs: ["matTextPrefix"] }, { 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: MatProgressSpinnerModule }, { kind: "component", type: i8.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }, { kind: "component", type: InlineEntityLookupComponent, selector: "pdx-inline-entity-lookup", inputs: ["initialMetadata"] }] });
15133
+ `, isInline: true, styles: [".pdx-lookup-dialog-toolbar{display:flex;flex-wrap:wrap;gap:12px;align-items:start}.pdx-lookup-dialog-intro{display:grid;gap:4px;margin:0 0 12px}.pdx-lookup-dialog-intro strong{color:var(--md-sys-color-on-surface);font-size:.96rem;line-height:1.3}.pdx-lookup-dialog-intro span{color:var(--md-sys-color-on-surface-variant);font-size:.82rem;line-height:1.35}.pdx-lookup-dialog-search{flex:1 1 320px}.pdx-lookup-dialog-sort{display:inline-flex;align-items:center;gap:8px;min-height:56px;color:var(--md-sys-color-on-surface-variant);font-size:.85rem}.pdx-lookup-dialog-sort select{min-width:180px;min-height:40px;border:1px solid var(--md-sys-color-outline-variant);border-radius:6px;background:var(--md-sys-color-surface);color:var(--md-sys-color-on-surface);padding:0 10px}.pdx-lookup-dialog-filter-panel{display:flex;flex-direction:column;gap:12px;padding:12px;margin:8px 0 12px;border:1px solid var(--md-sys-color-outline-variant);border-radius:8px;background:var(--md-sys-color-surface-container-lowest)}.pdx-lookup-dialog-filter-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:12px}.pdx-lookup-dialog-filter-field{display:flex;flex-direction:column;gap:6px;color:var(--md-sys-color-on-surface);font-size:.9rem}.pdx-lookup-dialog-filter-field input,.pdx-lookup-dialog-filter-field select{min-height:40px;border:1px solid var(--md-sys-color-outline-variant);border-radius:6px;background:var(--md-sys-color-surface);color:var(--md-sys-color-on-surface);padding:0 10px}.pdx-lookup-dialog-filter-field select.is-multiple{min-height:96px;padding:8px 10px}.pdx-lookup-dialog-filter-range{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:8px}.pdx-lookup-dialog-filter-field small{color:var(--md-sys-color-on-surface-variant)}.pdx-lookup-dialog-filter-actions{display:flex;justify-content:flex-end;gap:8px}.pdx-lookup-dialog-summary{margin:8px 0 12px;display:flex;flex-wrap:wrap;gap:8px;color:var(--md-sys-color-on-surface-variant);font-size:.85rem}.pdx-lookup-dialog-summary-warning{color:var(--md-sys-color-error)}.pdx-lookup-dialog-content-grid{display:block}.pdx-lookup-dialog-content-grid.has-preview{display:grid;grid-template-columns:minmax(0,1fr) 280px;gap:16px;align-items:start}.pdx-lookup-dialog-results{display:flex;flex-direction:column;gap:10px;max-height:52vh;overflow:auto;padding-right:4px}.pdx-lookup-dialog-results.is-card-layout{gap:12px}.pdx-lookup-dialog-results.is-compact-layout{gap:6px}.pdx-lookup-dialog-table{display:flex;flex-direction:column;border:1px solid var(--md-sys-color-outline-variant);border-radius:8px;overflow:hidden}.pdx-lookup-dialog-table-head,.pdx-lookup-dialog-table-row{display:flex;align-items:stretch}.pdx-lookup-dialog-table-head{background:var(--md-sys-color-surface-container-low);border-bottom:1px solid var(--md-sys-color-outline-variant)}.pdx-lookup-dialog-table-row{width:100%;text-align:left;border:0;border-bottom:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface);color:var(--md-sys-color-on-surface);cursor:pointer}.pdx-lookup-dialog-table-row:last-child{border-bottom:0}.pdx-lookup-dialog-table-row.is-selected{background:color-mix(in srgb,var(--md-sys-color-primary) 8%,var(--md-sys-color-surface))}.pdx-lookup-dialog-table-row.is-disabled{opacity:.65;cursor:not-allowed}.pdx-lookup-dialog-table-row.is-blocked,.pdx-lookup-dialog-row.is-blocked{background:color-mix(in srgb,var(--md-sys-color-error) 4%,var(--md-sys-color-surface))}.pdx-lookup-dialog-table-row.is-legacy,.pdx-lookup-dialog-row.is-legacy{background:color-mix(in srgb,var(--md-sys-color-tertiary) 8%,var(--md-sys-color-surface))}.pdx-lookup-dialog-table-cell{min-width:0;padding:10px 12px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.pdx-lookup-dialog-table-cell.is-head{font-size:.78rem;font-weight:600;color:var(--md-sys-color-on-surface-variant)}.pdx-lookup-dialog-row{display:block;width:100%;text-align:left;border:1px solid var(--md-sys-color-outline-variant);border-radius:8px;background:var(--md-sys-color-surface);color:var(--md-sys-color-on-surface);padding:12px 14px;cursor:pointer}.pdx-lookup-dialog-row.is-selected{border-color:var(--md-sys-color-primary);box-shadow:inset 0 0 0 1px var(--md-sys-color-primary);background:color-mix(in srgb,var(--md-sys-color-primary) 8%,var(--md-sys-color-surface))}.pdx-lookup-dialog-row.is-disabled{opacity:.65;cursor:not-allowed}.pdx-lookup-dialog-row-main,.pdx-lookup-dialog-row-heading,.pdx-lookup-dialog-row-meta{display:flex;flex-wrap:wrap;gap:8px}.pdx-lookup-dialog-row-main{flex-direction:column;gap:8px}.pdx-lookup-dialog-row-heading strong{font-size:.98rem;line-height:1.3}.pdx-lookup-dialog-row-heading small{border-radius:6px;padding:2px 6px;background:var(--md-sys-color-surface-container-high);color:var(--md-sys-color-on-surface-variant);font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;font-size:.74rem;line-height:1.2}.pdx-lookup-dialog-results.is-card-layout .pdx-lookup-dialog-row-main{display:grid;grid-template-columns:auto minmax(0,1fr);align-items:start;gap:12px}.pdx-lookup-dialog-results.is-compact-layout .pdx-lookup-dialog-row{padding:8px 10px}.pdx-lookup-dialog-results.is-compact-layout .pdx-lookup-dialog-row-heading,.pdx-lookup-dialog-results.is-compact-layout .pdx-lookup-dialog-row-meta{gap:6px}.pdx-lookup-dialog-results.is-compact-layout .pdx-lookup-dialog-row-description{font-size:.85rem}.pdx-lookup-dialog-row-description{color:var(--md-sys-color-on-surface-variant);line-height:1.35}.pdx-lookup-dialog-row-meta{align-items:center}.pdx-lookup-dialog-row-note,.pdx-lookup-option-note{display:inline-flex;align-items:center;min-height:24px;padding:4px 8px;border-radius:8px;font-size:.76rem;line-height:1.3}.pdx-lookup-dialog-row-note.is-warning,.pdx-lookup-option-note.is-warning{background:#fffbeb;color:#92400e}.pdx-lookup-dialog-row-note.is-danger,.pdx-lookup-option-note.is-danger{background:#fef2f2;color:#991b1b}.pdx-lookup-dialog-state,.pdx-lookup-dialog-footer-row{display:flex;align-items:center;gap:10px;justify-content:center;padding:16px 0 4px}.pdx-lookup-dialog-runtime-host{display:none}.pdx-lookup-dialog-preview{border:1px solid var(--md-sys-color-outline-variant);border-radius:8px;background:var(--md-sys-color-surface-container-lowest);padding:14px;display:flex;flex-direction:column;gap:10px;position:sticky;top:0}.pdx-lookup-dialog-preview-meta{display:flex;flex-wrap:wrap;align-items:center;gap:8px}.pdx-lookup-dialog-preview-heading{display:flex;flex-direction:column;gap:4px}.pdx-lookup-dialog-preview-heading small,.pdx-lookup-dialog-preview-description,.pdx-lookup-dialog-preview-grid dt{color:var(--md-sys-color-on-surface-variant)}.pdx-lookup-dialog-preview-badges{display:flex;flex-wrap:wrap;gap:8px}.pdx-lookup-dialog-preview-note{display:grid;gap:2px;padding:8px 10px;border-radius:8px;border:1px solid transparent;font-size:.78rem;line-height:1.35}.pdx-lookup-dialog-preview-note strong{font-size:.72rem;line-height:1.2;text-transform:uppercase;letter-spacing:.02em}.pdx-lookup-dialog-preview-note.is-warning{background:#fffbeb;border-color:#fde68a;color:#92400e}.pdx-lookup-dialog-preview-note.is-danger{background:#fef2f2;border-color:#fecaca;color:#991b1b}.pdx-lookup-dialog-preview-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px;margin:0}.pdx-lookup-dialog-preview-grid div{min-width:0}.pdx-lookup-dialog-preview-grid dt{font-size:.78rem;margin-bottom:2px}.pdx-lookup-dialog-preview-grid dd{margin:0;overflow-wrap:anywhere}.pdx-lookup-dialog-preview-actions{display:flex;flex-wrap:wrap;gap:8px}@media(max-width:960px){.pdx-lookup-dialog-toolbar{flex-direction:column;align-items:stretch}.pdx-lookup-dialog-search,.pdx-lookup-dialog-sort{width:100%;flex:1 1 auto}.pdx-lookup-dialog-sort{min-height:0;flex-direction:column;align-items:stretch}.pdx-lookup-dialog-sort select{width:100%;min-width:0}.pdx-lookup-dialog-content-grid.has-preview{grid-template-columns:minmax(0,1fr)}.pdx-lookup-dialog-preview{position:static}}@media(max-width:640px){.pdx-lookup-dialog-intro{margin-bottom:10px}.pdx-lookup-dialog-results{max-height:none;padding-right:0}.pdx-lookup-dialog-row{padding:10px 12px}.pdx-lookup-dialog-results.is-card-layout .pdx-lookup-dialog-row-main{grid-template-columns:minmax(0,1fr)}.pdx-lookup-dialog-preview{padding:12px}.pdx-lookup-dialog-preview-grid{grid-template-columns:minmax(0,1fr)}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$1.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { 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.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i1$1.SelectMultipleControlValueAccessor, selector: "select[multiple][formControlName],select[multiple][formControl],select[multiple][ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatDialogModule }, { kind: "directive", type: i1$3.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: i1$3.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "directive", type: i1$3.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i1$2.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { 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.MatPrefix, selector: "[matPrefix], [matIconPrefix], [matTextPrefix]", inputs: ["matTextPrefix"] }, { 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: MatProgressSpinnerModule }, { kind: "component", type: i8.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }, { kind: "component", type: InlineEntityLookupComponent, selector: "pdx-inline-entity-lookup", inputs: ["initialMetadata"] }] });
14160
15134
  }
14161
15135
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: EntityLookupDialogComponent, decorators: [{
14162
15136
  type: Component,
@@ -14229,11 +15203,57 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
14229
15203
  *ngFor="let definition of dialogFilterDefinitions()"
14230
15204
  >
14231
15205
  <span>{{ dialogFilterLabel(definition) }}</span>
14232
- <input
14233
- type="text"
14234
- [formControl]="filterControl(definition.field)"
14235
- [placeholder]="dialogFilterPlaceholder(definition)"
14236
- />
15206
+ @if (useDialogMultiSelect(definition)) {
15207
+ <select
15208
+ multiple
15209
+ class="pdx-lookup-dialog-filter-select is-multiple"
15210
+ [formControl]="filterControl(definition.field)"
15211
+ [attr.aria-label]="dialogFilterLabel(definition)"
15212
+ >
15213
+ <option
15214
+ *ngFor="let option of dialogEnumOptions(definition)"
15215
+ [value]="option.value"
15216
+ >
15217
+ {{ option.label }}
15218
+ </option>
15219
+ </select>
15220
+ } @else if (useDialogRangeInputs(definition)) {
15221
+ <span class="pdx-lookup-dialog-filter-range">
15222
+ <input
15223
+ [type]="dialogFilterInputType(definition)"
15224
+ [formControl]="filterControl(definition.field)"
15225
+ [placeholder]="dialogFilterPlaceholder(definition)"
15226
+ [attr.aria-label]="dialogFilterStartAriaLabel(definition)"
15227
+ />
15228
+ <input
15229
+ [type]="dialogFilterInputType(definition)"
15230
+ [formControl]="filterSecondaryControl(definition.field)"
15231
+ [placeholder]="dialogFilterRangeEndPlaceholder(definition)"
15232
+ [attr.aria-label]="dialogFilterEndAriaLabel(definition)"
15233
+ />
15234
+ </span>
15235
+ } @else if (useDialogEnumSelect(definition)) {
15236
+ <select
15237
+ class="pdx-lookup-dialog-filter-select"
15238
+ [formControl]="filterControl(definition.field)"
15239
+ [attr.aria-label]="dialogFilterLabel(definition)"
15240
+ >
15241
+ <option value="">{{ dialogFilterSelectEmptyText(definition) }}</option>
15242
+ <option
15243
+ *ngFor="let option of dialogEnumOptions(definition)"
15244
+ [value]="option.value"
15245
+ >
15246
+ {{ option.label }}
15247
+ </option>
15248
+ </select>
15249
+ } @else {
15250
+ <input
15251
+ [type]="dialogFilterInputType(definition)"
15252
+ [formControl]="filterControl(definition.field)"
15253
+ [placeholder]="dialogFilterPlaceholder(definition)"
15254
+ [attr.aria-label]="dialogFilterLabel(definition)"
15255
+ />
15256
+ }
14237
15257
  <small>{{ dialogOperatorHint(definition) }}</small>
14238
15258
  </label>
14239
15259
  </div>
@@ -14488,7 +15508,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
14488
15508
  {{ applyText() }}
14489
15509
  </button>
14490
15510
  </mat-dialog-actions>
14491
- `, styles: [".pdx-lookup-dialog-toolbar{display:flex;flex-wrap:wrap;gap:12px;align-items:start}.pdx-lookup-dialog-intro{display:grid;gap:4px;margin:0 0 12px}.pdx-lookup-dialog-intro strong{color:var(--md-sys-color-on-surface);font-size:.96rem;line-height:1.3}.pdx-lookup-dialog-intro span{color:var(--md-sys-color-on-surface-variant);font-size:.82rem;line-height:1.35}.pdx-lookup-dialog-search{flex:1 1 320px}.pdx-lookup-dialog-sort{display:inline-flex;align-items:center;gap:8px;min-height:56px;color:var(--md-sys-color-on-surface-variant);font-size:.85rem}.pdx-lookup-dialog-sort select{min-width:180px;min-height:40px;border:1px solid var(--md-sys-color-outline-variant);border-radius:6px;background:var(--md-sys-color-surface);color:var(--md-sys-color-on-surface);padding:0 10px}.pdx-lookup-dialog-filter-panel{display:flex;flex-direction:column;gap:12px;padding:12px;margin:8px 0 12px;border:1px solid var(--md-sys-color-outline-variant);border-radius:8px;background:var(--md-sys-color-surface-container-lowest)}.pdx-lookup-dialog-filter-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:12px}.pdx-lookup-dialog-filter-field{display:flex;flex-direction:column;gap:6px;color:var(--md-sys-color-on-surface);font-size:.9rem}.pdx-lookup-dialog-filter-field input{min-height:40px;border:1px solid var(--md-sys-color-outline-variant);border-radius:6px;background:var(--md-sys-color-surface);color:var(--md-sys-color-on-surface);padding:0 10px}.pdx-lookup-dialog-filter-field small{color:var(--md-sys-color-on-surface-variant)}.pdx-lookup-dialog-filter-actions{display:flex;justify-content:flex-end;gap:8px}.pdx-lookup-dialog-summary{margin:8px 0 12px;display:flex;flex-wrap:wrap;gap:8px;color:var(--md-sys-color-on-surface-variant);font-size:.85rem}.pdx-lookup-dialog-summary-warning{color:var(--md-sys-color-error)}.pdx-lookup-dialog-content-grid{display:block}.pdx-lookup-dialog-content-grid.has-preview{display:grid;grid-template-columns:minmax(0,1fr) 280px;gap:16px;align-items:start}.pdx-lookup-dialog-results{display:flex;flex-direction:column;gap:10px;max-height:52vh;overflow:auto;padding-right:4px}.pdx-lookup-dialog-results.is-card-layout{gap:12px}.pdx-lookup-dialog-results.is-compact-layout{gap:6px}.pdx-lookup-dialog-table{display:flex;flex-direction:column;border:1px solid var(--md-sys-color-outline-variant);border-radius:8px;overflow:hidden}.pdx-lookup-dialog-table-head,.pdx-lookup-dialog-table-row{display:flex;align-items:stretch}.pdx-lookup-dialog-table-head{background:var(--md-sys-color-surface-container-low);border-bottom:1px solid var(--md-sys-color-outline-variant)}.pdx-lookup-dialog-table-row{width:100%;text-align:left;border:0;border-bottom:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface);color:var(--md-sys-color-on-surface);cursor:pointer}.pdx-lookup-dialog-table-row:last-child{border-bottom:0}.pdx-lookup-dialog-table-row.is-selected{background:color-mix(in srgb,var(--md-sys-color-primary) 8%,var(--md-sys-color-surface))}.pdx-lookup-dialog-table-row.is-disabled{opacity:.65;cursor:not-allowed}.pdx-lookup-dialog-table-row.is-blocked,.pdx-lookup-dialog-row.is-blocked{background:color-mix(in srgb,var(--md-sys-color-error) 4%,var(--md-sys-color-surface))}.pdx-lookup-dialog-table-row.is-legacy,.pdx-lookup-dialog-row.is-legacy{background:color-mix(in srgb,var(--md-sys-color-tertiary) 8%,var(--md-sys-color-surface))}.pdx-lookup-dialog-table-cell{min-width:0;padding:10px 12px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.pdx-lookup-dialog-table-cell.is-head{font-size:.78rem;font-weight:600;color:var(--md-sys-color-on-surface-variant)}.pdx-lookup-dialog-row{display:block;width:100%;text-align:left;border:1px solid var(--md-sys-color-outline-variant);border-radius:8px;background:var(--md-sys-color-surface);color:var(--md-sys-color-on-surface);padding:12px 14px;cursor:pointer}.pdx-lookup-dialog-row.is-selected{border-color:var(--md-sys-color-primary);box-shadow:inset 0 0 0 1px var(--md-sys-color-primary);background:color-mix(in srgb,var(--md-sys-color-primary) 8%,var(--md-sys-color-surface))}.pdx-lookup-dialog-row.is-disabled{opacity:.65;cursor:not-allowed}.pdx-lookup-dialog-row-main,.pdx-lookup-dialog-row-heading,.pdx-lookup-dialog-row-meta{display:flex;flex-wrap:wrap;gap:8px}.pdx-lookup-dialog-row-main{flex-direction:column;gap:8px}.pdx-lookup-dialog-row-heading strong{font-size:.98rem;line-height:1.3}.pdx-lookup-dialog-row-heading small{border-radius:6px;padding:2px 6px;background:var(--md-sys-color-surface-container-high);color:var(--md-sys-color-on-surface-variant);font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;font-size:.74rem;line-height:1.2}.pdx-lookup-dialog-results.is-card-layout .pdx-lookup-dialog-row-main{display:grid;grid-template-columns:auto minmax(0,1fr);align-items:start;gap:12px}.pdx-lookup-dialog-results.is-compact-layout .pdx-lookup-dialog-row{padding:8px 10px}.pdx-lookup-dialog-results.is-compact-layout .pdx-lookup-dialog-row-heading,.pdx-lookup-dialog-results.is-compact-layout .pdx-lookup-dialog-row-meta{gap:6px}.pdx-lookup-dialog-results.is-compact-layout .pdx-lookup-dialog-row-description{font-size:.85rem}.pdx-lookup-dialog-row-description{color:var(--md-sys-color-on-surface-variant);line-height:1.35}.pdx-lookup-dialog-row-meta{align-items:center}.pdx-lookup-dialog-row-note,.pdx-lookup-option-note{display:inline-flex;align-items:center;min-height:24px;padding:4px 8px;border-radius:8px;font-size:.76rem;line-height:1.3}.pdx-lookup-dialog-row-note.is-warning,.pdx-lookup-option-note.is-warning{background:#fffbeb;color:#92400e}.pdx-lookup-dialog-row-note.is-danger,.pdx-lookup-option-note.is-danger{background:#fef2f2;color:#991b1b}.pdx-lookup-dialog-state,.pdx-lookup-dialog-footer-row{display:flex;align-items:center;gap:10px;justify-content:center;padding:16px 0 4px}.pdx-lookup-dialog-runtime-host{display:none}.pdx-lookup-dialog-preview{border:1px solid var(--md-sys-color-outline-variant);border-radius:8px;background:var(--md-sys-color-surface-container-lowest);padding:14px;display:flex;flex-direction:column;gap:10px;position:sticky;top:0}.pdx-lookup-dialog-preview-meta{display:flex;flex-wrap:wrap;align-items:center;gap:8px}.pdx-lookup-dialog-preview-heading{display:flex;flex-direction:column;gap:4px}.pdx-lookup-dialog-preview-heading small,.pdx-lookup-dialog-preview-description,.pdx-lookup-dialog-preview-grid dt{color:var(--md-sys-color-on-surface-variant)}.pdx-lookup-dialog-preview-badges{display:flex;flex-wrap:wrap;gap:8px}.pdx-lookup-dialog-preview-note{display:grid;gap:2px;padding:8px 10px;border-radius:8px;border:1px solid transparent;font-size:.78rem;line-height:1.35}.pdx-lookup-dialog-preview-note strong{font-size:.72rem;line-height:1.2;text-transform:uppercase;letter-spacing:.02em}.pdx-lookup-dialog-preview-note.is-warning{background:#fffbeb;border-color:#fde68a;color:#92400e}.pdx-lookup-dialog-preview-note.is-danger{background:#fef2f2;border-color:#fecaca;color:#991b1b}.pdx-lookup-dialog-preview-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px;margin:0}.pdx-lookup-dialog-preview-grid div{min-width:0}.pdx-lookup-dialog-preview-grid dt{font-size:.78rem;margin-bottom:2px}.pdx-lookup-dialog-preview-grid dd{margin:0;overflow-wrap:anywhere}.pdx-lookup-dialog-preview-actions{display:flex;flex-wrap:wrap;gap:8px}@media(max-width:960px){.pdx-lookup-dialog-toolbar{flex-direction:column;align-items:stretch}.pdx-lookup-dialog-search,.pdx-lookup-dialog-sort{width:100%;flex:1 1 auto}.pdx-lookup-dialog-sort{min-height:0;flex-direction:column;align-items:stretch}.pdx-lookup-dialog-sort select{width:100%;min-width:0}.pdx-lookup-dialog-content-grid.has-preview{grid-template-columns:minmax(0,1fr)}.pdx-lookup-dialog-preview{position:static}}@media(max-width:640px){.pdx-lookup-dialog-intro{margin-bottom:10px}.pdx-lookup-dialog-results{max-height:none;padding-right:0}.pdx-lookup-dialog-row{padding:10px 12px}.pdx-lookup-dialog-results.is-card-layout .pdx-lookup-dialog-row-main{grid-template-columns:minmax(0,1fr)}.pdx-lookup-dialog-preview{padding:12px}.pdx-lookup-dialog-preview-grid{grid-template-columns:minmax(0,1fr)}}\n"] }]
15511
+ `, styles: [".pdx-lookup-dialog-toolbar{display:flex;flex-wrap:wrap;gap:12px;align-items:start}.pdx-lookup-dialog-intro{display:grid;gap:4px;margin:0 0 12px}.pdx-lookup-dialog-intro strong{color:var(--md-sys-color-on-surface);font-size:.96rem;line-height:1.3}.pdx-lookup-dialog-intro span{color:var(--md-sys-color-on-surface-variant);font-size:.82rem;line-height:1.35}.pdx-lookup-dialog-search{flex:1 1 320px}.pdx-lookup-dialog-sort{display:inline-flex;align-items:center;gap:8px;min-height:56px;color:var(--md-sys-color-on-surface-variant);font-size:.85rem}.pdx-lookup-dialog-sort select{min-width:180px;min-height:40px;border:1px solid var(--md-sys-color-outline-variant);border-radius:6px;background:var(--md-sys-color-surface);color:var(--md-sys-color-on-surface);padding:0 10px}.pdx-lookup-dialog-filter-panel{display:flex;flex-direction:column;gap:12px;padding:12px;margin:8px 0 12px;border:1px solid var(--md-sys-color-outline-variant);border-radius:8px;background:var(--md-sys-color-surface-container-lowest)}.pdx-lookup-dialog-filter-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:12px}.pdx-lookup-dialog-filter-field{display:flex;flex-direction:column;gap:6px;color:var(--md-sys-color-on-surface);font-size:.9rem}.pdx-lookup-dialog-filter-field input,.pdx-lookup-dialog-filter-field select{min-height:40px;border:1px solid var(--md-sys-color-outline-variant);border-radius:6px;background:var(--md-sys-color-surface);color:var(--md-sys-color-on-surface);padding:0 10px}.pdx-lookup-dialog-filter-field select.is-multiple{min-height:96px;padding:8px 10px}.pdx-lookup-dialog-filter-range{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:8px}.pdx-lookup-dialog-filter-field small{color:var(--md-sys-color-on-surface-variant)}.pdx-lookup-dialog-filter-actions{display:flex;justify-content:flex-end;gap:8px}.pdx-lookup-dialog-summary{margin:8px 0 12px;display:flex;flex-wrap:wrap;gap:8px;color:var(--md-sys-color-on-surface-variant);font-size:.85rem}.pdx-lookup-dialog-summary-warning{color:var(--md-sys-color-error)}.pdx-lookup-dialog-content-grid{display:block}.pdx-lookup-dialog-content-grid.has-preview{display:grid;grid-template-columns:minmax(0,1fr) 280px;gap:16px;align-items:start}.pdx-lookup-dialog-results{display:flex;flex-direction:column;gap:10px;max-height:52vh;overflow:auto;padding-right:4px}.pdx-lookup-dialog-results.is-card-layout{gap:12px}.pdx-lookup-dialog-results.is-compact-layout{gap:6px}.pdx-lookup-dialog-table{display:flex;flex-direction:column;border:1px solid var(--md-sys-color-outline-variant);border-radius:8px;overflow:hidden}.pdx-lookup-dialog-table-head,.pdx-lookup-dialog-table-row{display:flex;align-items:stretch}.pdx-lookup-dialog-table-head{background:var(--md-sys-color-surface-container-low);border-bottom:1px solid var(--md-sys-color-outline-variant)}.pdx-lookup-dialog-table-row{width:100%;text-align:left;border:0;border-bottom:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface);color:var(--md-sys-color-on-surface);cursor:pointer}.pdx-lookup-dialog-table-row:last-child{border-bottom:0}.pdx-lookup-dialog-table-row.is-selected{background:color-mix(in srgb,var(--md-sys-color-primary) 8%,var(--md-sys-color-surface))}.pdx-lookup-dialog-table-row.is-disabled{opacity:.65;cursor:not-allowed}.pdx-lookup-dialog-table-row.is-blocked,.pdx-lookup-dialog-row.is-blocked{background:color-mix(in srgb,var(--md-sys-color-error) 4%,var(--md-sys-color-surface))}.pdx-lookup-dialog-table-row.is-legacy,.pdx-lookup-dialog-row.is-legacy{background:color-mix(in srgb,var(--md-sys-color-tertiary) 8%,var(--md-sys-color-surface))}.pdx-lookup-dialog-table-cell{min-width:0;padding:10px 12px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.pdx-lookup-dialog-table-cell.is-head{font-size:.78rem;font-weight:600;color:var(--md-sys-color-on-surface-variant)}.pdx-lookup-dialog-row{display:block;width:100%;text-align:left;border:1px solid var(--md-sys-color-outline-variant);border-radius:8px;background:var(--md-sys-color-surface);color:var(--md-sys-color-on-surface);padding:12px 14px;cursor:pointer}.pdx-lookup-dialog-row.is-selected{border-color:var(--md-sys-color-primary);box-shadow:inset 0 0 0 1px var(--md-sys-color-primary);background:color-mix(in srgb,var(--md-sys-color-primary) 8%,var(--md-sys-color-surface))}.pdx-lookup-dialog-row.is-disabled{opacity:.65;cursor:not-allowed}.pdx-lookup-dialog-row-main,.pdx-lookup-dialog-row-heading,.pdx-lookup-dialog-row-meta{display:flex;flex-wrap:wrap;gap:8px}.pdx-lookup-dialog-row-main{flex-direction:column;gap:8px}.pdx-lookup-dialog-row-heading strong{font-size:.98rem;line-height:1.3}.pdx-lookup-dialog-row-heading small{border-radius:6px;padding:2px 6px;background:var(--md-sys-color-surface-container-high);color:var(--md-sys-color-on-surface-variant);font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;font-size:.74rem;line-height:1.2}.pdx-lookup-dialog-results.is-card-layout .pdx-lookup-dialog-row-main{display:grid;grid-template-columns:auto minmax(0,1fr);align-items:start;gap:12px}.pdx-lookup-dialog-results.is-compact-layout .pdx-lookup-dialog-row{padding:8px 10px}.pdx-lookup-dialog-results.is-compact-layout .pdx-lookup-dialog-row-heading,.pdx-lookup-dialog-results.is-compact-layout .pdx-lookup-dialog-row-meta{gap:6px}.pdx-lookup-dialog-results.is-compact-layout .pdx-lookup-dialog-row-description{font-size:.85rem}.pdx-lookup-dialog-row-description{color:var(--md-sys-color-on-surface-variant);line-height:1.35}.pdx-lookup-dialog-row-meta{align-items:center}.pdx-lookup-dialog-row-note,.pdx-lookup-option-note{display:inline-flex;align-items:center;min-height:24px;padding:4px 8px;border-radius:8px;font-size:.76rem;line-height:1.3}.pdx-lookup-dialog-row-note.is-warning,.pdx-lookup-option-note.is-warning{background:#fffbeb;color:#92400e}.pdx-lookup-dialog-row-note.is-danger,.pdx-lookup-option-note.is-danger{background:#fef2f2;color:#991b1b}.pdx-lookup-dialog-state,.pdx-lookup-dialog-footer-row{display:flex;align-items:center;gap:10px;justify-content:center;padding:16px 0 4px}.pdx-lookup-dialog-runtime-host{display:none}.pdx-lookup-dialog-preview{border:1px solid var(--md-sys-color-outline-variant);border-radius:8px;background:var(--md-sys-color-surface-container-lowest);padding:14px;display:flex;flex-direction:column;gap:10px;position:sticky;top:0}.pdx-lookup-dialog-preview-meta{display:flex;flex-wrap:wrap;align-items:center;gap:8px}.pdx-lookup-dialog-preview-heading{display:flex;flex-direction:column;gap:4px}.pdx-lookup-dialog-preview-heading small,.pdx-lookup-dialog-preview-description,.pdx-lookup-dialog-preview-grid dt{color:var(--md-sys-color-on-surface-variant)}.pdx-lookup-dialog-preview-badges{display:flex;flex-wrap:wrap;gap:8px}.pdx-lookup-dialog-preview-note{display:grid;gap:2px;padding:8px 10px;border-radius:8px;border:1px solid transparent;font-size:.78rem;line-height:1.35}.pdx-lookup-dialog-preview-note strong{font-size:.72rem;line-height:1.2;text-transform:uppercase;letter-spacing:.02em}.pdx-lookup-dialog-preview-note.is-warning{background:#fffbeb;border-color:#fde68a;color:#92400e}.pdx-lookup-dialog-preview-note.is-danger{background:#fef2f2;border-color:#fecaca;color:#991b1b}.pdx-lookup-dialog-preview-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px;margin:0}.pdx-lookup-dialog-preview-grid div{min-width:0}.pdx-lookup-dialog-preview-grid dt{font-size:.78rem;margin-bottom:2px}.pdx-lookup-dialog-preview-grid dd{margin:0;overflow-wrap:anywhere}.pdx-lookup-dialog-preview-actions{display:flex;flex-wrap:wrap;gap:8px}@media(max-width:960px){.pdx-lookup-dialog-toolbar{flex-direction:column;align-items:stretch}.pdx-lookup-dialog-search,.pdx-lookup-dialog-sort{width:100%;flex:1 1 auto}.pdx-lookup-dialog-sort{min-height:0;flex-direction:column;align-items:stretch}.pdx-lookup-dialog-sort select{width:100%;min-width:0}.pdx-lookup-dialog-content-grid.has-preview{grid-template-columns:minmax(0,1fr)}.pdx-lookup-dialog-preview{position:static}}@media(max-width:640px){.pdx-lookup-dialog-intro{margin-bottom:10px}.pdx-lookup-dialog-results{max-height:none;padding-right:0}.pdx-lookup-dialog-row{padding:10px 12px}.pdx-lookup-dialog-results.is-card-layout .pdx-lookup-dialog-row-main{grid-template-columns:minmax(0,1fr)}.pdx-lookup-dialog-preview{padding:12px}.pdx-lookup-dialog-preview-grid{grid-template-columns:minmax(0,1fr)}}\n"] }]
14492
15512
  }], propDecorators: { lookup: [{ type: i0.ViewChild, args: [i0.forwardRef(() => InlineEntityLookupComponent), { isSignal: true }] }] } });
14493
15513
 
14494
15514
  const PDX_ENTITY_LOOKUP_EDITORIAL_DESCRIPTOR = {
@@ -15062,15 +16082,13 @@ class MaterialSelectComponent extends SimpleBaseSelectComponent {
15062
16082
  <mat-option
15063
16083
  *ngIf="emptyOptionText()"
15064
16084
  [value]="null"
15065
- (click)="selectOption({ label: emptyOptionText()!, value: null })"
15066
16085
  >
15067
16086
  {{ emptyOptionText() }}
15068
16087
  </mat-option>
15069
16088
  <mat-option
15070
16089
  *ngFor="let option of options(); trackBy: trackByOption"
15071
16090
  [value]="option.value"
15072
- [disabled]="option.disabled"
15073
- (click)="selectOption(option)"
16091
+ [disabled]="isOptionDisabled(option)"
15074
16092
  >
15075
16093
  {{ option.label }}
15076
16094
  </mat-option>
@@ -15172,15 +16190,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
15172
16190
  <mat-option
15173
16191
  *ngIf="emptyOptionText()"
15174
16192
  [value]="null"
15175
- (click)="selectOption({ label: emptyOptionText()!, value: null })"
15176
16193
  >
15177
16194
  {{ emptyOptionText() }}
15178
16195
  </mat-option>
15179
16196
  <mat-option
15180
16197
  *ngFor="let option of options(); trackBy: trackByOption"
15181
16198
  [value]="option.value"
15182
- [disabled]="option.disabled"
15183
- (click)="selectOption(option)"
16199
+ [disabled]="isOptionDisabled(option)"
15184
16200
  >
15185
16201
  {{ option.label }}
15186
16202
  </mat-option>
@@ -17614,6 +18630,12 @@ class ColorInputComponent extends SimpleBaseInputComponent {
17614
18630
  getSpecificCssClasses() {
17615
18631
  return ['pdx-color-input'];
17616
18632
  }
18633
+ // Angular Material recommends always-floating labels for text-like prefixes
18634
+ // in fill/outline fields. Keep this until Material supports prefix alignment
18635
+ // without forcing the label to float.
18636
+ effectiveFloatLabelBehavior() {
18637
+ return 'always';
18638
+ }
17617
18639
  /** Applies component metadata with strong typing. */
17618
18640
  setInputMetadata(metadata) {
17619
18641
  const { placeholder, ...rest } = metadata;
@@ -17950,7 +18972,7 @@ class ColorInputComponent extends SimpleBaseInputComponent {
17950
18972
  [appearance]="materialAppearance()"
17951
18973
  [color]="materialColor()"
17952
18974
  [class]="componentCssClasses()"
17953
- [floatLabel]="floatLabelBehavior()"
18975
+ [floatLabel]="effectiveFloatLabelBehavior()"
17954
18976
  [subscriptSizing]="metadata()?.materialDesign?.subscriptSizing || 'fixed'"
17955
18977
  [hideRequiredMarker]="metadata()?.materialDesign?.hideRequiredMarker || false"
17956
18978
  >
@@ -18077,7 +19099,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
18077
19099
  [appearance]="materialAppearance()"
18078
19100
  [color]="materialColor()"
18079
19101
  [class]="componentCssClasses()"
18080
- [floatLabel]="floatLabelBehavior()"
19102
+ [floatLabel]="effectiveFloatLabelBehavior()"
18081
19103
  [subscriptSizing]="metadata()?.materialDesign?.subscriptSizing || 'fixed'"
18082
19104
  [hideRequiredMarker]="metadata()?.materialDesign?.hideRequiredMarker || false"
18083
19105
  >
@@ -20626,7 +21648,7 @@ class MaterialPriceRangeComponent extends SimpleBaseInputComponent {
20626
21648
  <div class="mat-hint">{{ metadata()!.hint }}</div>
20627
21649
  }
20628
21650
  </div>
20629
- `, 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"] }] });
20630
21652
  }
20631
21653
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: MaterialPriceRangeComponent, decorators: [{
20632
21654
  type: Component,
@@ -20710,7 +21732,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
20710
21732
  '[attr.data-field-type]': '"priceRange"',
20711
21733
  '[attr.data-field-name]': 'metadata()?.name',
20712
21734
  '[attr.data-component-id]': 'componentId()',
20713
- }, 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"] }]
20714
21736
  }], propDecorators: { validationChange: [{ type: i0.Output, args: ["validationChange"] }], readonlyMode: [{
20715
21737
  type: Input
20716
21738
  }], disabledMode: [{
@@ -21876,7 +22898,6 @@ class InlineSelectComponent extends SimpleBaseSelectComponent {
21876
22898
  <mat-option
21877
22899
  *ngIf="emptyOptionText()"
21878
22900
  [value]="null"
21879
- (click)="selectOption({ label: emptyOptionText()!, value: null })"
21880
22901
  >
21881
22902
  {{ emptyOptionText() }}
21882
22903
  </mat-option>
@@ -21884,8 +22905,7 @@ class InlineSelectComponent extends SimpleBaseSelectComponent {
21884
22905
  <mat-option
21885
22906
  *ngFor="let option of filteredOptions(); trackBy: trackByOption"
21886
22907
  [value]="option.value"
21887
- [disabled]="option.disabled"
21888
- (click)="selectOption(option)"
22908
+ [disabled]="isOptionDisabled(option)"
21889
22909
  >
21890
22910
  {{ option.label }}
21891
22911
  </mat-option>
@@ -22008,7 +23028,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
22008
23028
  <mat-option
22009
23029
  *ngIf="emptyOptionText()"
22010
23030
  [value]="null"
22011
- (click)="selectOption({ label: emptyOptionText()!, value: null })"
22012
23031
  >
22013
23032
  {{ emptyOptionText() }}
22014
23033
  </mat-option>
@@ -22016,8 +23035,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
22016
23035
  <mat-option
22017
23036
  *ngFor="let option of filteredOptions(); trackBy: trackByOption"
22018
23037
  [value]="option.value"
22019
- [disabled]="option.disabled"
22020
- (click)="selectOption(option)"
23038
+ [disabled]="isOptionDisabled(option)"
22021
23039
  >
22022
23040
  {{ option.label }}
22023
23041
  </mat-option>
@@ -22130,7 +23148,7 @@ class MaterialSearchableSelectComponent extends SimpleBaseSelectComponent {
22130
23148
  return this.isReadonlyEffective() || this.presentationMode ? 'true' : null;
22131
23149
  }
22132
23150
  isOptionDisabled(option) {
22133
- return this.isInteractionDisabled() || option.disabled === true;
23151
+ return this.isInteractionDisabled() || super.isOptionDisabled(option);
22134
23152
  }
22135
23153
  selectOption(option) {
22136
23154
  if (this.isInteractionDisabled()) {
@@ -22375,7 +23393,6 @@ class MaterialSearchableSelectComponent extends SimpleBaseSelectComponent {
22375
23393
  *ngFor="let option of filteredOptions(); trackBy: trackByOption"
22376
23394
  [value]="option.value"
22377
23395
  [disabled]="isOptionDisabled(option)"
22378
- (click)="selectOption(option)"
22379
23396
  >
22380
23397
  {{ option.label }}
22381
23398
  </mat-option>
@@ -22421,7 +23438,6 @@ class MaterialSearchableSelectComponent extends SimpleBaseSelectComponent {
22421
23438
  *ngIf="emptyOptionText()"
22422
23439
  [value]="null"
22423
23440
  [disabled]="isInteractionDisabled()"
22424
- (click)="selectOption({ label: emptyOptionText()!, value: null })"
22425
23441
  >
22426
23442
  {{ emptyOptionText() }}
22427
23443
  </mat-option>
@@ -22429,7 +23445,6 @@ class MaterialSearchableSelectComponent extends SimpleBaseSelectComponent {
22429
23445
  *ngFor="let option of filteredOptions(); trackBy: trackByOption"
22430
23446
  [value]="option.value"
22431
23447
  [disabled]="isOptionDisabled(option)"
22432
- (click)="selectOption(option)"
22433
23448
  >
22434
23449
  {{ option.label }}
22435
23450
  </mat-option>
@@ -22538,7 +23553,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
22538
23553
  *ngFor="let option of filteredOptions(); trackBy: trackByOption"
22539
23554
  [value]="option.value"
22540
23555
  [disabled]="isOptionDisabled(option)"
22541
- (click)="selectOption(option)"
22542
23556
  >
22543
23557
  {{ option.label }}
22544
23558
  </mat-option>
@@ -22584,7 +23598,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
22584
23598
  *ngIf="emptyOptionText()"
22585
23599
  [value]="null"
22586
23600
  [disabled]="isInteractionDisabled()"
22587
- (click)="selectOption({ label: emptyOptionText()!, value: null })"
22588
23601
  >
22589
23602
  {{ emptyOptionText() }}
22590
23603
  </mat-option>
@@ -22592,7 +23605,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
22592
23605
  *ngFor="let option of filteredOptions(); trackBy: trackByOption"
22593
23606
  [value]="option.value"
22594
23607
  [disabled]="isOptionDisabled(option)"
22595
- (click)="selectOption(option)"
22596
23608
  >
22597
23609
  {{ option.label }}
22598
23610
  </mat-option>
@@ -23008,7 +24020,6 @@ class InlineSearchableSelectComponent extends MaterialSearchableSelectComponent
23008
24020
  <mat-option
23009
24021
  *ngIf="!multiple() && emptyOptionText()"
23010
24022
  [value]="null"
23011
- (click)="selectOption({ label: emptyOptionText()!, value: null })"
23012
24023
  >
23013
24024
  {{ emptyOptionText() }}
23014
24025
  </mat-option>
@@ -23016,8 +24027,7 @@ class InlineSearchableSelectComponent extends MaterialSearchableSelectComponent
23016
24027
  <mat-option
23017
24028
  *ngFor="let option of filteredOptions(); trackBy: trackByOption"
23018
24029
  [value]="option.value"
23019
- [disabled]="option.disabled"
23020
- (click)="selectOption(option)"
24030
+ [disabled]="isOptionDisabled(option)"
23021
24031
  >
23022
24032
  {{ option.label }}
23023
24033
  </mat-option>
@@ -23156,7 +24166,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
23156
24166
  <mat-option
23157
24167
  *ngIf="!multiple() && emptyOptionText()"
23158
24168
  [value]="null"
23159
- (click)="selectOption({ label: emptyOptionText()!, value: null })"
23160
24169
  >
23161
24170
  {{ emptyOptionText() }}
23162
24171
  </mat-option>
@@ -23164,8 +24173,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
23164
24173
  <mat-option
23165
24174
  *ngFor="let option of filteredOptions(); trackBy: trackByOption"
23166
24175
  [value]="option.value"
23167
- [disabled]="option.disabled"
23168
- (click)="selectOption(option)"
24176
+ [disabled]="isOptionDisabled(option)"
23169
24177
  >
23170
24178
  {{ option.label }}
23171
24179
  </mat-option>
@@ -23595,7 +24603,6 @@ class InlineAsyncSelectComponent extends MaterialAsyncSelectComponent {
23595
24603
  <mat-option
23596
24604
  *ngIf="!multiple() && emptyOptionText()"
23597
24605
  [value]="null"
23598
- (click)="selectOption({ label: emptyOptionText()!, value: null })"
23599
24606
  >
23600
24607
  {{ emptyOptionText() }}
23601
24608
  </mat-option>
@@ -23603,8 +24610,7 @@ class InlineAsyncSelectComponent extends MaterialAsyncSelectComponent {
23603
24610
  <mat-option
23604
24611
  *ngFor="let option of options(); trackBy: trackByOption"
23605
24612
  [value]="option.value"
23606
- [disabled]="option.disabled"
23607
- (click)="selectOption(option)"
24613
+ [disabled]="isOptionDisabled(option)"
23608
24614
  >
23609
24615
  {{ option.label }}
23610
24616
  </mat-option>
@@ -23744,7 +24750,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
23744
24750
  <mat-option
23745
24751
  *ngIf="!multiple() && emptyOptionText()"
23746
24752
  [value]="null"
23747
- (click)="selectOption({ label: emptyOptionText()!, value: null })"
23748
24753
  >
23749
24754
  {{ emptyOptionText() }}
23750
24755
  </mat-option>
@@ -23752,8 +24757,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
23752
24757
  <mat-option
23753
24758
  *ngFor="let option of options(); trackBy: trackByOption"
23754
24759
  [value]="option.value"
23755
- [disabled]="option.disabled"
23756
- (click)="selectOption(option)"
24760
+ [disabled]="isOptionDisabled(option)"
23757
24761
  >
23758
24762
  {{ option.label }}
23759
24763
  </mat-option>
@@ -49100,6 +50104,12 @@ class MaterialColorPickerComponent extends SimpleBaseInputComponent {
49100
50104
  getSpecificCssClasses() {
49101
50105
  return ['pdx-material-colorpicker'];
49102
50106
  }
50107
+ // Angular Material recommends always-floating labels for text-like prefixes
50108
+ // in fill/outline fields. Keep this until Material supports prefix alignment
50109
+ // without forcing the label to float.
50110
+ effectiveFloatLabelBehavior() {
50111
+ return 'always';
50112
+ }
49103
50113
  errorStateMatcher() {
49104
50114
  return getErrorStateMatcherForField(this.metadata());
49105
50115
  }
@@ -49198,7 +50208,7 @@ class MaterialColorPickerComponent extends SimpleBaseInputComponent {
49198
50208
  [appearance]="materialAppearance()"
49199
50209
  [color]="materialColor()"
49200
50210
  [class]="componentCssClasses()"
49201
- [floatLabel]="floatLabelBehavior()"
50211
+ [floatLabel]="effectiveFloatLabelBehavior()"
49202
50212
  [subscriptSizing]="metadata()?.materialDesign?.subscriptSizing || 'fixed'"
49203
50213
  [hideRequiredMarker]="metadata()?.materialDesign?.hideRequiredMarker || false"
49204
50214
  >
@@ -49282,7 +50292,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
49282
50292
  [appearance]="materialAppearance()"
49283
50293
  [color]="materialColor()"
49284
50294
  [class]="componentCssClasses()"
49285
- [floatLabel]="floatLabelBehavior()"
50295
+ [floatLabel]="effectiveFloatLabelBehavior()"
49286
50296
  [subscriptSizing]="metadata()?.materialDesign?.subscriptSizing || 'fixed'"
49287
50297
  [hideRequiredMarker]="metadata()?.materialDesign?.hideRequiredMarker || false"
49288
50298
  >
@@ -50358,6 +51368,12 @@ class PdxColorPickerComponent extends SimpleBaseInputComponent {
50358
51368
  }
50359
51369
  errorStateMatcher() { return getErrorStateMatcherForField(this.metadata()); }
50360
51370
  getSpecificCssClasses() { return ['pdx-color-picker']; }
51371
+ // Angular Material recommends always-floating labels for text-like prefixes
51372
+ // in fill/outline fields. Keep this until Material supports prefix alignment
51373
+ // without forcing the label to float.
51374
+ effectiveFloatLabelBehavior() {
51375
+ return 'always';
51376
+ }
50361
51377
  // Accept hot metadata updates from DynamicFieldLoader / DynamicForm
50362
51378
  setInputMetadata(meta) {
50363
51379
  try {
@@ -50628,7 +51644,7 @@ class PdxColorPickerComponent extends SimpleBaseInputComponent {
50628
51644
  [appearance]="materialAppearance()"
50629
51645
  [color]="materialColor()"
50630
51646
  [class]="componentCssClasses()"
50631
- [floatLabel]="floatLabelBehavior()"
51647
+ [floatLabel]="effectiveFloatLabelBehavior()"
50632
51648
  [subscriptSizing]="metadata()?.materialDesign?.subscriptSizing || 'fixed'"
50633
51649
  [hideRequiredMarker]="metadata()?.materialDesign?.hideRequiredMarker || false"
50634
51650
  >
@@ -50799,7 +51815,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
50799
51815
  [appearance]="materialAppearance()"
50800
51816
  [color]="materialColor()"
50801
51817
  [class]="componentCssClasses()"
50802
- [floatLabel]="floatLabelBehavior()"
51818
+ [floatLabel]="effectiveFloatLabelBehavior()"
50803
51819
  [subscriptSizing]="metadata()?.materialDesign?.subscriptSizing || 'fixed'"
50804
51820
  [hideRequiredMarker]="metadata()?.materialDesign?.hideRequiredMarker || false"
50805
51821
  >