@praxisui/dynamic-fields 9.0.0-beta.20 → 9.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.
@@ -3,7 +3,7 @@ import { NgControl, FormControl, Validators, ReactiveFormsModule, NG_VALUE_ACCES
3
3
  import * as i0 from '@angular/core';
4
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
- 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, ResourceDiscoveryService, ResourceSurfaceOpenAdapterService, classifyEntityLookupResult, ComponentMetadataRegistry, createCpfCnpjValidator, NumericFormat, interpolatePraxisTranslation, FIELD_METADATA_CAPABILITIES } from '@praxisui/core';
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, PraxisJsonLogicService, renderPraxisPresentationVisualizationHtml, resolveFieldPresentation as resolveFieldPresentation$1, DynamicFormService, ResourceDiscoveryService, ResourceSurfaceOpenAdapterService, classifyEntityLookupResult, ComponentMetadataRegistry, createCpfCnpjValidator, NumericFormat, interpolatePraxisTranslation, FIELD_METADATA_CAPABILITIES } from '@praxisui/core';
7
7
  import { Subscription, BehaviorSubject, combineLatest, of, EMPTY, firstValueFrom, fromEvent, take as take$1 } from 'rxjs';
8
8
  import { Router } from '@angular/router';
9
9
  import * as i1$3 from '@angular/material/dialog';
@@ -5963,6 +5963,7 @@ class MaterialCheckboxGroupComponent extends SimpleBaseSelectComponent {
5963
5963
  presentationMode = false;
5964
5964
  disabledModeAppliedToControl = false;
5965
5965
  ngDoCheck() {
5966
+ this.normalizeBooleanControlValue();
5966
5967
  this.syncDisabledModeControlState();
5967
5968
  }
5968
5969
  checkboxInteractionDisabled() {
@@ -6041,6 +6042,11 @@ class MaterialCheckboxGroupComponent extends SimpleBaseSelectComponent {
6041
6042
  optionLabelKey: matMetadata.optionLabelKey,
6042
6043
  optionValueKey: matMetadata.optionValueKey,
6043
6044
  });
6045
+ this.normalizeBooleanControlValue();
6046
+ }
6047
+ setExternalControl(control) {
6048
+ super.setExternalControl(control);
6049
+ this.normalizeBooleanControlValue();
6044
6050
  }
6045
6051
  /** Disables options when maxSelections reached */
6046
6052
  isOptionDisabled(option) {
@@ -6245,6 +6251,43 @@ class MaterialCheckboxGroupComponent extends SimpleBaseSelectComponent {
6245
6251
  this.markAsTouched();
6246
6252
  this.syncBooleanOperationalEvents(nextValue);
6247
6253
  }
6254
+ normalizeBooleanControlValue() {
6255
+ if (!this.isBooleanCheckbox()) {
6256
+ return;
6257
+ }
6258
+ const control = this.control();
6259
+ const coerced = this.coerceBooleanControlValue(control.value);
6260
+ if (coerced === null || control.value === coerced) {
6261
+ return;
6262
+ }
6263
+ control.setValue(coerced, { emitEvent: false });
6264
+ this.fieldState.update((state) => ({ ...state, value: coerced }));
6265
+ }
6266
+ coerceBooleanControlValue(value) {
6267
+ if (typeof value === 'boolean')
6268
+ return value;
6269
+ if (typeof value === 'number') {
6270
+ if (value === 1)
6271
+ return true;
6272
+ if (value === 0)
6273
+ return false;
6274
+ return null;
6275
+ }
6276
+ if (typeof value !== 'string')
6277
+ return null;
6278
+ const normalized = value
6279
+ .normalize('NFD')
6280
+ .replace(/[\u0300-\u036f]/g, '')
6281
+ .trim()
6282
+ .toLowerCase();
6283
+ if (['true', 't', 'sim', 's', 'yes', 'y', 'si', 'oui', 'ja', '1', 'on'].includes(normalized)) {
6284
+ return true;
6285
+ }
6286
+ if (['false', 'f', 'nao', 'n', 'no', 'non', 'nein', '0', 'off'].includes(normalized)) {
6287
+ return false;
6288
+ }
6289
+ return null;
6290
+ }
6248
6291
  syncBooleanOperationalEvents(nextValue) {
6249
6292
  const emittedOption = {
6250
6293
  label: this.label?.trim() || this.humanizeName(this.metadata()?.name),
@@ -8855,7 +8898,7 @@ function formatDisplayValue(field, value, options) {
8855
8898
  if (value instanceof Date) {
8856
8899
  const explicit = resolveFieldPresentation(field, value, options);
8857
8900
  return explicit
8858
- ? formatTypedValue(field, value, explicit)
8901
+ ? formatTypedValue(field, value, explicit, options)
8859
8902
  : formatHeuristicDateTime(value, options);
8860
8903
  }
8861
8904
  if (value && typeof value === 'object') {
@@ -8884,13 +8927,13 @@ function formatDisplayValue(field, value, options) {
8884
8927
  if (!trimmed)
8885
8928
  return EMPTY_DISPLAY;
8886
8929
  if (presentation && presentation.type !== 'string') {
8887
- return formatTypedValue(field, trimmed, presentation);
8930
+ return formatTypedValue(field, trimmed, presentation, options);
8888
8931
  }
8889
8932
  const documentIdentifier = formatDocumentIdentifierValue(field, trimmed);
8890
8933
  if (documentIdentifier)
8891
8934
  return documentIdentifier;
8892
8935
  if (presentation) {
8893
- return formatTypedValue(field, trimmed, presentation);
8936
+ return formatTypedValue(field, trimmed, presentation, options);
8894
8937
  }
8895
8938
  if (isISODate(trimmed))
8896
8939
  return formatHeuristicDate(trimmed, options);
@@ -8901,13 +8944,13 @@ function formatDisplayValue(field, value, options) {
8901
8944
  }
8902
8945
  if (typeof value === 'number') {
8903
8946
  if (presentation) {
8904
- return formatTypedValue(field, value, presentation);
8947
+ return formatTypedValue(field, value, presentation, options);
8905
8948
  }
8906
8949
  return String(value);
8907
8950
  }
8908
8951
  if (typeof value === 'boolean') {
8909
8952
  if (presentation) {
8910
- return formatTypedValue(field, value, presentation);
8953
+ return formatTypedValue(field, value, presentation, options);
8911
8954
  }
8912
8955
  return String(value);
8913
8956
  }
@@ -9337,10 +9380,10 @@ function mergeLocalization(base, override) {
9337
9380
  : {}),
9338
9381
  };
9339
9382
  }
9340
- function formatTypedValue(field, value, presentation) {
9383
+ function formatTypedValue(field, value, presentation, options) {
9341
9384
  switch (presentation.type) {
9342
9385
  case 'boolean':
9343
- return formatBooleanPresentation(value, presentation.locale);
9386
+ return formatBooleanPresentation(value, presentation.locale, field, options);
9344
9387
  case 'date':
9345
9388
  case 'datetime':
9346
9389
  case 'time':
@@ -9364,18 +9407,62 @@ function formatTypedValue(field, value, presentation) {
9364
9407
  return String(value);
9365
9408
  }
9366
9409
  }
9367
- function formatBooleanPresentation(value, locale) {
9368
- const [trueLabel, falseLabel] = resolveBooleanLabels(locale);
9369
- if (typeof value === 'string') {
9370
- const normalized = value.trim().toLowerCase();
9371
- if (normalized === 'true')
9372
- return trueLabel;
9373
- if (normalized === 'false')
9374
- return falseLabel;
9410
+ function formatBooleanPresentation(value, locale, field, options) {
9411
+ const labels = resolveBooleanLabels(locale, field, options);
9412
+ const coerced = coerceBooleanPresentationValue(value);
9413
+ if (coerced !== null)
9414
+ return coerced ? labels[0] : labels[1];
9415
+ return value ? labels[0] : labels[1];
9416
+ }
9417
+ function coerceBooleanPresentationValue(value) {
9418
+ if (typeof value === 'boolean')
9419
+ return value;
9420
+ if (typeof value === 'number') {
9421
+ if (value === 1)
9422
+ return true;
9423
+ if (value === 0)
9424
+ return false;
9425
+ return null;
9426
+ }
9427
+ if (typeof value !== 'string')
9428
+ return null;
9429
+ const normalized = normalizeComparableString(value);
9430
+ if (normalized === 'true' ||
9431
+ normalized === 't' ||
9432
+ normalized === 'sim' ||
9433
+ normalized === 's' ||
9434
+ normalized === 'yes' ||
9435
+ normalized === 'y' ||
9436
+ normalized === 'si' ||
9437
+ normalized === 'oui' ||
9438
+ normalized === 'ja' ||
9439
+ normalized === '1') {
9440
+ return true;
9441
+ }
9442
+ if (normalized === 'false' ||
9443
+ normalized === 'f' ||
9444
+ normalized === 'nao' ||
9445
+ normalized === 'n' ||
9446
+ normalized === 'no' ||
9447
+ normalized === 'non' ||
9448
+ normalized === 'nein' ||
9449
+ normalized === '0') {
9450
+ return false;
9375
9451
  }
9376
- return value ? trueLabel : falseLabel;
9452
+ return null;
9377
9453
  }
9378
- function resolveBooleanLabels(locale) {
9454
+ function resolveBooleanLabels(locale, field, options) {
9455
+ if (options?.booleanLabels?.trueLabel && options.booleanLabels.falseLabel) {
9456
+ return [options.booleanLabels.trueLabel, options.booleanLabels.falseLabel];
9457
+ }
9458
+ const explicit = field?.valuePresentation?.booleanLabels ?? field?.booleanLabels;
9459
+ if (explicit && typeof explicit === 'object') {
9460
+ const trueLabel = normalizeString(explicit.trueLabel ?? explicit.true ?? explicit.yes);
9461
+ const falseLabel = normalizeString(explicit.falseLabel ?? explicit.false ?? explicit.no);
9462
+ if (trueLabel && falseLabel) {
9463
+ return [trueLabel, falseLabel];
9464
+ }
9465
+ }
9379
9466
  const normalized = String(locale || '').trim().toLowerCase();
9380
9467
  if (normalized.startsWith('pt')) {
9381
9468
  return ['Sim', 'Não'];
@@ -9754,7 +9841,9 @@ class FieldShellComponent {
9754
9841
  angularLocale = inject(LOCALE_ID, { optional: true }) ?? 'en-US';
9755
9842
  i18n = inject(PraxisI18nService, { optional: true });
9756
9843
  cdr = inject(ChangeDetectorRef);
9844
+ jsonLogic = inject(PraxisJsonLogicService);
9757
9845
  optionDisplayResolver = inject(OptionDisplayResolverService);
9846
+ sanitizer = inject(DomSanitizer);
9758
9847
  crudService = inject(GenericCrudService, {
9759
9848
  optional: true,
9760
9849
  });
@@ -9915,52 +10004,158 @@ class FieldShellComponent {
9915
10004
  }
9916
10005
  }
9917
10006
  getPresentationValue() {
9918
- const raw = this.presentationDisplayValue ?? this.control?.value;
10007
+ const resolved = this.getResolvedPresentation();
10008
+ const raw = this.getPresentationLabelOverride(resolved) ??
10009
+ this.presentationDisplayValue ??
10010
+ this.control?.value;
10011
+ const field = this.getPresentationFormattingField(resolved);
9919
10012
  try {
9920
- const fn = this.field?.transformDisplayValue;
10013
+ const fn = field?.transformDisplayValue;
9921
10014
  const formatted = typeof fn === 'function'
9922
10015
  ? fn(raw)
9923
- : formatDisplayValue(this.field, raw, {
10016
+ : formatDisplayValue(field, raw, {
9924
10017
  appLocale: this.resolvePresentationAppLocale(),
9925
- surfaceLocale: this.field?.localization?.locale ?? this.field?.locale ?? undefined,
9926
- localization: this.field?.localization ?? undefined,
10018
+ surfaceLocale: field?.localization?.locale ?? field?.locale ?? undefined,
10019
+ localization: field?.localization ?? undefined,
10020
+ booleanLabels: this.resolveBooleanLabels(),
9927
10021
  });
9928
10022
  return formatted == null ? '' : String(formatted);
9929
10023
  }
9930
10024
  catch {
9931
- return formatDisplayValue(this.field, raw, {
10025
+ return formatDisplayValue(field, raw, {
9932
10026
  appLocale: this.resolvePresentationAppLocale(),
9933
- surfaceLocale: this.field?.localization?.locale ?? this.field?.locale ?? undefined,
9934
- localization: this.field?.localization ?? undefined,
10027
+ surfaceLocale: field?.localization?.locale ?? field?.locale ?? undefined,
10028
+ localization: field?.localization ?? undefined,
10029
+ booleanLabels: this.resolveBooleanLabels(),
9935
10030
  });
9936
10031
  }
9937
10032
  }
9938
10033
  getPresentationHtml() {
10034
+ const resolved = this.getResolvedPresentation();
10035
+ if (resolved.presenter === 'microVisualization' && resolved.visualization) {
10036
+ return this.sanitizer.bypassSecurityTrustHtml(renderPraxisPresentationVisualizationHtml(resolved.visualization, {
10037
+ locale: this.resolvePresentationAppLocale(),
10038
+ }));
10039
+ }
9939
10040
  const raw = this.control?.value;
9940
10041
  const displayValue = this.presentationDisplayValue;
10042
+ const field = this.getPresentationFormattingField(resolved);
10043
+ const semanticLabel = this.getPresentationLabelOverride(resolved);
9941
10044
  try {
9942
- const fn = this.field?.transformDisplayValue;
9943
- const formatted = displayValue !== null
9944
- ? displayValue
9945
- : typeof fn === 'function'
9946
- ? fn(raw)
9947
- : null;
10045
+ const fn = field?.transformDisplayValue;
10046
+ const formatted = semanticLabel !== null
10047
+ ? semanticLabel
10048
+ : displayValue !== null
10049
+ ? displayValue
10050
+ : typeof fn === 'function'
10051
+ ? fn(raw)
10052
+ : null;
9948
10053
  const val = formatted == null ? raw : formatted;
9949
- return formatDisplayHtml(this.field, val, {
10054
+ return formatDisplayHtml(field, val, {
9950
10055
  appLocale: this.resolvePresentationAppLocale(),
9951
- surfaceLocale: this.field?.localization?.locale ?? this.field?.locale ?? undefined,
9952
- localization: this.field?.localization ?? undefined,
10056
+ surfaceLocale: field?.localization?.locale ?? field?.locale ?? undefined,
10057
+ localization: field?.localization ?? undefined,
10058
+ booleanLabels: this.resolveBooleanLabels(),
9953
10059
  });
9954
10060
  }
9955
10061
  catch {
9956
- return formatDisplayHtml(this.field, raw, {
10062
+ return formatDisplayHtml(field, semanticLabel ?? raw, {
9957
10063
  appLocale: this.resolvePresentationAppLocale(),
9958
- surfaceLocale: this.field?.localization?.locale ?? this.field?.locale ?? undefined,
9959
- localization: this.field?.localization ?? undefined,
10064
+ surfaceLocale: field?.localization?.locale ?? field?.locale ?? undefined,
10065
+ localization: field?.localization ?? undefined,
10066
+ booleanLabels: this.resolveBooleanLabels(),
9960
10067
  });
9961
10068
  }
9962
10069
  }
10070
+ getResolvedPresentation() {
10071
+ const field = this.field;
10072
+ return resolveFieldPresentation$1(field?.presentation, field?.presentationRules, this.buildPresentationContext(), { jsonLogic: this.jsonLogic });
10073
+ }
10074
+ hasResolvedPresentationState() {
10075
+ const presentation = this.getResolvedPresentation();
10076
+ return Boolean(presentation.presenter ||
10077
+ presentation.tone ||
10078
+ presentation.icon ||
10079
+ presentation.label ||
10080
+ presentation.badge ||
10081
+ presentation.tooltip ||
10082
+ presentation.appearance ||
10083
+ presentation.valuePresentation ||
10084
+ presentation.visualization);
10085
+ }
10086
+ getPresentationTone() {
10087
+ return this.getResolvedPresentation().tone ?? null;
10088
+ }
10089
+ getPresentationAppearance() {
10090
+ return this.getResolvedPresentation().appearance ?? null;
10091
+ }
10092
+ getPresentationPresenter() {
10093
+ const presenter = this.getResolvedPresentation().presenter;
10094
+ if (presenter) {
10095
+ return presenter;
10096
+ }
10097
+ return this.isBooleanPresentationField() ? 'chip' : 'text';
10098
+ }
10099
+ getPresentationTooltip() {
10100
+ return this.getResolvedPresentation().tooltip ?? this.field?.tooltip ?? null;
10101
+ }
10102
+ getPresentationBadge() {
10103
+ const presentation = this.getResolvedPresentation();
10104
+ if (!presentation.badge || this.shouldPresentationLabelReplaceValue(presentation)) {
10105
+ return null;
10106
+ }
10107
+ return presentation.badge;
10108
+ }
10109
+ isBooleanPresentationField() {
10110
+ const field = this.field;
10111
+ const type = String(field?.valuePresentation?.type ?? field?.dataType ?? field?.controlType ?? '').toLowerCase();
10112
+ return (type === 'boolean' ||
10113
+ type.includes('checkbox') ||
10114
+ type.includes('toggle'));
10115
+ }
10116
+ getBooleanPresentationState() {
10117
+ if (!this.isBooleanPresentationField())
10118
+ return null;
10119
+ const raw = this.control?.value;
10120
+ if (typeof raw === 'boolean')
10121
+ return raw;
10122
+ if (typeof raw === 'number') {
10123
+ if (raw === 1)
10124
+ return true;
10125
+ if (raw === 0)
10126
+ return false;
10127
+ return null;
10128
+ }
10129
+ if (typeof raw !== 'string')
10130
+ return null;
10131
+ const normalized = raw.normalize('NFD').replace(/[\u0300-\u036f]/g, '').trim().toLowerCase();
10132
+ if (['true', 't', 'sim', 's', 'yes', 'y', 'si', 'oui', 'ja', '1'].includes(normalized))
10133
+ return true;
10134
+ if (['false', 'f', 'nao', 'n', 'no', 'non', 'nein', '0'].includes(normalized))
10135
+ return false;
10136
+ return null;
10137
+ }
10138
+ resolveBooleanLabels() {
10139
+ if (this.field?.localization?.locale || this.field?.locale) {
10140
+ return null;
10141
+ }
10142
+ const locale = this.i18n?.getLocale?.() ?? this.angularLocale;
10143
+ if (String(locale).toLowerCase().startsWith('pt')) {
10144
+ return {
10145
+ trueLabel: this.i18n?.t('praxis.dynamicFields.boolean.true', undefined, 'Sim') ?? 'Sim',
10146
+ falseLabel: this.i18n?.t('praxis.dynamicFields.boolean.false', undefined, 'Não') ?? 'Não',
10147
+ };
10148
+ }
10149
+ return {
10150
+ trueLabel: this.i18n?.t('praxis.dynamicFields.boolean.true', undefined, 'Yes') ?? 'Yes',
10151
+ falseLabel: this.i18n?.t('praxis.dynamicFields.boolean.false', undefined, 'No') ?? 'No',
10152
+ };
10153
+ }
9963
10154
  getPresentationPrefixIcon() {
10155
+ const semanticIcon = this.normalizeIconName(this.getResolvedPresentation().icon);
10156
+ if (semanticIcon) {
10157
+ return semanticIcon;
10158
+ }
9964
10159
  const field = this.field;
9965
10160
  const explicit = this.normalizeIconName(field?.prefixIcon);
9966
10161
  if (explicit) {
@@ -10026,6 +10221,9 @@ class FieldShellComponent {
10026
10221
  });
10027
10222
  }
10028
10223
  getPresentationIconColor(position) {
10224
+ if (position === 'prefix' && this.getResolvedPresentation().icon) {
10225
+ return undefined;
10226
+ }
10029
10227
  const field = this.field;
10030
10228
  const value = position === 'prefix'
10031
10229
  ? field?.prefixIconColor ?? field?.iconColor
@@ -10060,6 +10258,55 @@ class FieldShellComponent {
10060
10258
  const angularLocale = this.angularLocale?.trim();
10061
10259
  return angularLocale || 'en-US';
10062
10260
  }
10261
+ getPresentationFormattingField(presentation) {
10262
+ if (!presentation.valuePresentation) {
10263
+ return this.field;
10264
+ }
10265
+ return {
10266
+ ...this.field,
10267
+ valuePresentation: presentation.valuePresentation,
10268
+ };
10269
+ }
10270
+ getPresentationLabelOverride(presentation) {
10271
+ if (!presentation.label || !this.shouldPresentationLabelReplaceValue(presentation)) {
10272
+ return null;
10273
+ }
10274
+ return presentation.label;
10275
+ }
10276
+ shouldPresentationLabelReplaceValue(presentation) {
10277
+ return (Boolean(presentation.label) &&
10278
+ ['status', 'badge', 'chip'].includes(String(presentation.presenter ?? '')));
10279
+ }
10280
+ buildPresentationContext() {
10281
+ const field = this.field;
10282
+ const rawValue = this.control?.value;
10283
+ const fieldName = typeof field?.name === 'string' && field.name.trim().length
10284
+ ? field.name.trim()
10285
+ : undefined;
10286
+ const formData = this.asRecord(field?.presentationContext?.formData ?? field?.formData);
10287
+ const row = this.asRecord(field?.presentationContext?.row ?? field?.row);
10288
+ const context = {
10289
+ value: rawValue,
10290
+ rawValue,
10291
+ fieldName,
10292
+ field,
10293
+ metadata: field,
10294
+ formData,
10295
+ row,
10296
+ };
10297
+ if (formData) {
10298
+ Object.assign(context, formData);
10299
+ }
10300
+ if (fieldName) {
10301
+ context[fieldName] = rawValue;
10302
+ }
10303
+ return context;
10304
+ }
10305
+ asRecord(value) {
10306
+ return value && typeof value === 'object' && !Array.isArray(value)
10307
+ ? value
10308
+ : undefined;
10309
+ }
10063
10310
  refreshPresentationDisplayValue() {
10064
10311
  this.resolveSub?.unsubscribe();
10065
10312
  this.resolveSub = undefined;
@@ -10095,7 +10342,18 @@ class FieldShellComponent {
10095
10342
  >
10096
10343
  <!-- Presentation block -->
10097
10344
  @if (effectivePresentationMode && !renderContentInPresentation()) {
10098
- <div class="praxis-presentation" [attr.data-field]="fieldNameAttr">
10345
+ <div
10346
+ class="praxis-presentation"
10347
+ [class.praxis-presentation--boolean]="isBooleanPresentationField()"
10348
+ [class.praxis-presentation--boolean-true]="getBooleanPresentationState() === true"
10349
+ [class.praxis-presentation--boolean-false]="getBooleanPresentationState() === false"
10350
+ [class.praxis-presentation--semantic]="hasResolvedPresentationState()"
10351
+ [attr.data-field]="fieldNameAttr"
10352
+ [attr.data-presentation-tone]="getPresentationTone()"
10353
+ [attr.data-presentation-appearance]="getPresentationAppearance()"
10354
+ [attr.data-presentation-presenter]="getPresentationPresenter()"
10355
+ [attr.title]="getPresentationTooltip()"
10356
+ >
10099
10357
  <span class="praxis-presentation__label">{{
10100
10358
  fieldLabelText()
10101
10359
  }}</span>
@@ -10116,6 +10374,9 @@ class FieldShellComponent {
10116
10374
  class="praxis-presentation__value"
10117
10375
  [innerHTML]="getPresentationHtml()"
10118
10376
  ></span>
10377
+ @if (getPresentationBadge(); as badge) {
10378
+ <span class="praxis-presentation__badge">{{ badge }}</span>
10379
+ }
10119
10380
  @if (getPresentationSuffixIcon(); as suffixIcon) {
10120
10381
  <mat-icon
10121
10382
  class="praxis-presentation__icon praxis-presentation__icon--suffix"
@@ -10179,7 +10440,7 @@ class FieldShellComponent {
10179
10440
 
10180
10441
  </div>
10181
10442
  </div>
10182
- `, 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}.pfx-field-shell-authoring-hit-target{position:absolute;inset:0;z-index:2;display:block;width:100%;min-width:0;min-height:100%;padding:0;border:0;border-radius:inherit;background:transparent;cursor:pointer;appearance:none;-webkit-appearance:none}.pfx-field-shell-authoring-hit-target:focus-visible{outline:2px solid var(--mat-sys-primary, #90caf9);outline-offset:2px}.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 });
10443
+ `, 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}.pfx-field-shell-authoring-hit-target{position:absolute;inset:0;z-index:2;display:block;width:100%;min-width:0;min-height:100%;padding:0;border:0;border-radius:inherit;background:transparent;cursor:pointer;appearance:none;-webkit-appearance:none}.pfx-field-shell-authoring-hit-target:focus-visible{outline:2px solid var(--mat-sys-primary, #90caf9);outline-offset:2px}.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}.praxis-presentation--semantic{--pfx-pres-semantic-color: var(--mat-sys-on-surface-variant, currentColor);--pfx-pres-semantic-bg: color-mix(in srgb, currentColor 7%, transparent);--pfx-pres-semantic-border: color-mix(in srgb, currentColor 16%, transparent)}.praxis-presentation[data-presentation-tone=info]{--pfx-pres-semantic-color: var(--pfx-pres-info-color, var(--mat-sys-primary, #0b5cad))}.praxis-presentation[data-presentation-tone=success]{--pfx-pres-semantic-color: var(--pfx-pres-success-color, var(--praxis-success, #0f7b4a))}.praxis-presentation[data-presentation-tone=warning]{--pfx-pres-semantic-color: var(--pfx-pres-warning-color, var(--praxis-warning, #a16207))}.praxis-presentation[data-presentation-tone=danger]{--pfx-pres-semantic-color: var(--pfx-pres-danger-color, var(--mat-sys-error, #ba1a1a))}.praxis-presentation--semantic .praxis-presentation__icon{color:var(--pfx-pres-semantic-color);opacity:1}.praxis-presentation--semantic .praxis-presentation__content{justify-content:flex-start}.praxis-presentation--semantic .praxis-presentation__value{flex:0 1 auto}.praxis-presentation[data-presentation-presenter=status] .praxis-presentation__value,.praxis-presentation[data-presentation-presenter=badge] .praxis-presentation__value,.praxis-presentation[data-presentation-presenter=chip] .praxis-presentation__value{display:inline-flex;flex:0 1 auto;align-items:center;justify-content:center;box-sizing:border-box;min-height:var(--pfx-pres-status-min-height, 24px);padding:var(--pfx-pres-status-padding, 2px 9px);border-radius:var(--pfx-pres-status-radius, 999px);border:1px solid var(--pfx-pres-semantic-border);color:var(--pfx-pres-semantic-color);background:var(--pfx-pres-semantic-bg);font-size:var(--pfx-pres-status-font-size, .8rem);font-weight:var(--pfx-pres-status-font-weight, 700);line-height:var(--pfx-pres-status-line-height, 1.1)}.praxis-presentation[data-presentation-appearance=filled] .praxis-presentation__value{color:var(--pfx-pres-status-filled-color, var(--mat-sys-on-primary, #ffffff));background:var(--pfx-pres-semantic-color);border-color:var(--pfx-pres-semantic-color)}.praxis-presentation[data-presentation-appearance=outlined] .praxis-presentation__value{background:transparent;border-color:var(--pfx-pres-semantic-color)}.praxis-presentation[data-presentation-appearance=plain] .praxis-presentation__value{border-color:transparent;background:transparent;padding-inline:0}.praxis-presentation__badge{display:inline-flex;flex:0 0 auto;align-items:center;justify-content:center;box-sizing:border-box;min-height:20px;padding:1px 7px;border-radius:999px;border:1px solid var(--pfx-pres-semantic-border, color-mix(in srgb, currentColor 16%, transparent));color:var(--pfx-pres-semantic-color, currentColor);background:var(--pfx-pres-semantic-bg, color-mix(in srgb, currentColor 7%, transparent));font-size:.72rem;line-height:1;font-weight:700;white-space:nowrap}.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 .praxis-presentation--semantic .praxis-presentation__value{flex:0 1 auto}.presentation-mode .praxis-presentation--semantic .praxis-presentation__content{justify-content:flex-start}.presentation-mode .praxis-presentation--semantic[data-presentation-presenter=iconValue] .praxis-presentation__value{display:inline-flex;flex:0 0 auto;width:auto}.praxis-presentation[data-presentation-presenter=microVisualization] .praxis-presentation__value{display:block;width:100%;max-width:var(--pfx-pres-micro-max-width, 320px);font-size:var(--pfx-pres-micro-font-size, .78rem);line-height:1.2}.pfx-micro-viz{display:grid;gap:6px;width:100%;min-width:0}.pfx-micro-viz__fallback{color:var(--mat-sys-on-surface-variant, currentColor);font-weight:600}.pfx-micro-viz__row{display:grid;grid-template-columns:minmax(48px,.65fr) minmax(92px,1fr) auto;gap:6px;align-items:center;min-width:0}.pfx-micro-viz__label,.pfx-micro-viz__value{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.pfx-micro-viz__label{color:var(--mat-sys-on-surface-variant, currentColor);font-weight:600;opacity:.84}.pfx-micro-viz__value{justify-self:end;font-weight:700}.pfx-micro-viz__track{position:relative;height:8px;overflow:hidden;border-radius:999px;background:color-mix(in srgb,var(--mat-sys-on-surface, currentColor) 12%,transparent)}.pfx-micro-viz__bar,.pfx-micro-viz__target{position:absolute;inset-block:0;border-radius:inherit;background:var(--pfx-micro-tone-color, var(--mat-sys-primary, currentColor))}.pfx-micro-viz__segments{display:flex;height:10px;overflow:hidden;border-radius:999px;background:color-mix(in srgb,var(--mat-sys-on-surface, currentColor) 12%,transparent)}.pfx-micro-viz__segment{min-width:2px;background:var(--pfx-micro-tone-color, var(--mat-sys-primary, currentColor))}.pfx-micro-viz__bullet{display:grid;gap:5px}.pfx-micro-viz__bullet .pfx-micro-viz__track{height:12px}.pfx-micro-viz__target{width:2px;min-width:2px;transform:translate(-1px);background:var(--mat-sys-on-surface, currentColor);opacity:.74}.pfx-micro-viz__delta{display:inline-flex;align-items:center;gap:5px;min-width:0;color:var(--pfx-micro-tone-color, var(--mat-sys-primary, currentColor));font-weight:800}.pfx-micro-viz__delta-symbol{display:inline-grid;place-items:center;width:18px;height:18px;border-radius:999px;background:color-mix(in srgb,currentColor 14%,transparent);font-size:.72rem;line-height:1}.pfx-micro-viz__meta{display:flex;align-items:center;justify-content:space-between;gap:8px;min-width:0;color:var(--mat-sys-on-surface-variant, currentColor);font-weight:600;opacity:.82}.pfx-micro-viz [data-tone=success]{--pfx-micro-tone-color: var(--praxis-success, #0f7b4a)}.pfx-micro-viz [data-tone=warning],.pfx-micro-viz[data-tone=warning]{--pfx-micro-tone-color: var(--praxis-warning, #a16207)}.pfx-micro-viz [data-tone=danger],.pfx-micro-viz[data-tone=danger],.pfx-micro-viz [data-tone=critical],.pfx-micro-viz[data-tone=critical]{--pfx-micro-tone-color: var(--mat-sys-error, #ba1a1a)}.pfx-micro-viz [data-tone=info],.pfx-micro-viz[data-tone=info]{--pfx-micro-tone-color: var(--mat-sys-primary, #0b5cad)}@media(max-width:480px){.presentation-mode.pres-label-left .praxis-presentation{flex-direction:column;align-items:flex-start;gap:4px}.presentation-mode.pres-label-left .praxis-presentation__label{min-width:0;width:auto;text-align:start}.presentation-mode.pres-label-left .praxis-presentation__content{width:100%;flex-basis:auto}}.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}.presentation-mode.pres-compact .praxis-presentation__label,.presentation-mode.pres-density-compact .praxis-presentation__label{font-size:var(--pfx-pres-compact-label-size, var(--pfx-pres-label-size, .72rem));margin-bottom:var(--pfx-pres-compact-label-gap, 1px)}.presentation-mode.pres-compact .praxis-presentation__value,.presentation-mode.pres-density-compact .praxis-presentation__value{font-size:var(--pfx-pres-compact-value-size, var(--pfx-pres-value-size, .92rem));line-height:var(--pfx-pres-compact-value-line-height, 1.22)}.presentation-mode .praxis-presentation--boolean .praxis-presentation__value{display:inline-flex;flex:0 1 auto;align-items:center;justify-content:center;box-sizing:border-box;min-height:var(--pfx-pres-boolean-min-height, 22px);padding:var(--pfx-pres-boolean-padding, 0 8px);border-radius:var(--pfx-pres-boolean-radius, 999px);border:1px solid var(--pfx-pres-boolean-border-color, color-mix(in srgb, currentColor 18%, transparent));background:var(--pfx-pres-boolean-bg, color-mix(in srgb, currentColor 8%, transparent));font-size:var(--pfx-pres-boolean-font-size, .78rem);font-weight:var(--pfx-pres-boolean-font-weight, 700);line-height:var(--pfx-pres-boolean-line-height, 1);text-transform:var(--pfx-pres-boolean-text-transform, none)}.presentation-mode .praxis-presentation--boolean-true .praxis-presentation__value{color:var(--pfx-pres-boolean-true-color, var(--mat-sys-primary, currentColor));background:var(--pfx-pres-boolean-true-bg, color-mix(in srgb, var(--mat-sys-primary, currentColor) 10%, transparent));border-color:var(--pfx-pres-boolean-true-border-color, color-mix(in srgb, var(--mat-sys-primary, currentColor) 24%, transparent))}.presentation-mode .praxis-presentation--boolean-false .praxis-presentation__value{color:var(--pfx-pres-boolean-false-color, var(--mat-sys-on-surface-variant, currentColor));background:var(--pfx-pres-boolean-false-bg, color-mix(in srgb, var(--mat-sys-on-surface, currentColor) 6%, transparent));border-color:var(--pfx-pres-boolean-false-border-color, color-mix(in srgb, var(--mat-sys-on-surface, currentColor) 16%, transparent))}\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 });
10183
10444
  }
10184
10445
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: FieldShellComponent, decorators: [{
10185
10446
  type: Component,
@@ -10203,7 +10464,18 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
10203
10464
  >
10204
10465
  <!-- Presentation block -->
10205
10466
  @if (effectivePresentationMode && !renderContentInPresentation()) {
10206
- <div class="praxis-presentation" [attr.data-field]="fieldNameAttr">
10467
+ <div
10468
+ class="praxis-presentation"
10469
+ [class.praxis-presentation--boolean]="isBooleanPresentationField()"
10470
+ [class.praxis-presentation--boolean-true]="getBooleanPresentationState() === true"
10471
+ [class.praxis-presentation--boolean-false]="getBooleanPresentationState() === false"
10472
+ [class.praxis-presentation--semantic]="hasResolvedPresentationState()"
10473
+ [attr.data-field]="fieldNameAttr"
10474
+ [attr.data-presentation-tone]="getPresentationTone()"
10475
+ [attr.data-presentation-appearance]="getPresentationAppearance()"
10476
+ [attr.data-presentation-presenter]="getPresentationPresenter()"
10477
+ [attr.title]="getPresentationTooltip()"
10478
+ >
10207
10479
  <span class="praxis-presentation__label">{{
10208
10480
  fieldLabelText()
10209
10481
  }}</span>
@@ -10224,6 +10496,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
10224
10496
  class="praxis-presentation__value"
10225
10497
  [innerHTML]="getPresentationHtml()"
10226
10498
  ></span>
10499
+ @if (getPresentationBadge(); as badge) {
10500
+ <span class="praxis-presentation__badge">{{ badge }}</span>
10501
+ }
10227
10502
  @if (getPresentationSuffixIcon(); as suffixIcon) {
10228
10503
  <mat-icon
10229
10504
  class="praxis-presentation__icon praxis-presentation__icon--suffix"
@@ -10287,7 +10562,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
10287
10562
 
10288
10563
  </div>
10289
10564
  </div>
10290
- `, 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}.pfx-field-shell-authoring-hit-target{position:absolute;inset:0;z-index:2;display:block;width:100%;min-width:0;min-height:100%;padding:0;border:0;border-radius:inherit;background:transparent;cursor:pointer;appearance:none;-webkit-appearance:none}.pfx-field-shell-authoring-hit-target:focus-visible{outline:2px solid var(--mat-sys-primary, #90caf9);outline-offset:2px}.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"] }]
10565
+ `, 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}.pfx-field-shell-authoring-hit-target{position:absolute;inset:0;z-index:2;display:block;width:100%;min-width:0;min-height:100%;padding:0;border:0;border-radius:inherit;background:transparent;cursor:pointer;appearance:none;-webkit-appearance:none}.pfx-field-shell-authoring-hit-target:focus-visible{outline:2px solid var(--mat-sys-primary, #90caf9);outline-offset:2px}.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}.praxis-presentation--semantic{--pfx-pres-semantic-color: var(--mat-sys-on-surface-variant, currentColor);--pfx-pres-semantic-bg: color-mix(in srgb, currentColor 7%, transparent);--pfx-pres-semantic-border: color-mix(in srgb, currentColor 16%, transparent)}.praxis-presentation[data-presentation-tone=info]{--pfx-pres-semantic-color: var(--pfx-pres-info-color, var(--mat-sys-primary, #0b5cad))}.praxis-presentation[data-presentation-tone=success]{--pfx-pres-semantic-color: var(--pfx-pres-success-color, var(--praxis-success, #0f7b4a))}.praxis-presentation[data-presentation-tone=warning]{--pfx-pres-semantic-color: var(--pfx-pres-warning-color, var(--praxis-warning, #a16207))}.praxis-presentation[data-presentation-tone=danger]{--pfx-pres-semantic-color: var(--pfx-pres-danger-color, var(--mat-sys-error, #ba1a1a))}.praxis-presentation--semantic .praxis-presentation__icon{color:var(--pfx-pres-semantic-color);opacity:1}.praxis-presentation--semantic .praxis-presentation__content{justify-content:flex-start}.praxis-presentation--semantic .praxis-presentation__value{flex:0 1 auto}.praxis-presentation[data-presentation-presenter=status] .praxis-presentation__value,.praxis-presentation[data-presentation-presenter=badge] .praxis-presentation__value,.praxis-presentation[data-presentation-presenter=chip] .praxis-presentation__value{display:inline-flex;flex:0 1 auto;align-items:center;justify-content:center;box-sizing:border-box;min-height:var(--pfx-pres-status-min-height, 24px);padding:var(--pfx-pres-status-padding, 2px 9px);border-radius:var(--pfx-pres-status-radius, 999px);border:1px solid var(--pfx-pres-semantic-border);color:var(--pfx-pres-semantic-color);background:var(--pfx-pres-semantic-bg);font-size:var(--pfx-pres-status-font-size, .8rem);font-weight:var(--pfx-pres-status-font-weight, 700);line-height:var(--pfx-pres-status-line-height, 1.1)}.praxis-presentation[data-presentation-appearance=filled] .praxis-presentation__value{color:var(--pfx-pres-status-filled-color, var(--mat-sys-on-primary, #ffffff));background:var(--pfx-pres-semantic-color);border-color:var(--pfx-pres-semantic-color)}.praxis-presentation[data-presentation-appearance=outlined] .praxis-presentation__value{background:transparent;border-color:var(--pfx-pres-semantic-color)}.praxis-presentation[data-presentation-appearance=plain] .praxis-presentation__value{border-color:transparent;background:transparent;padding-inline:0}.praxis-presentation__badge{display:inline-flex;flex:0 0 auto;align-items:center;justify-content:center;box-sizing:border-box;min-height:20px;padding:1px 7px;border-radius:999px;border:1px solid var(--pfx-pres-semantic-border, color-mix(in srgb, currentColor 16%, transparent));color:var(--pfx-pres-semantic-color, currentColor);background:var(--pfx-pres-semantic-bg, color-mix(in srgb, currentColor 7%, transparent));font-size:.72rem;line-height:1;font-weight:700;white-space:nowrap}.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 .praxis-presentation--semantic .praxis-presentation__value{flex:0 1 auto}.presentation-mode .praxis-presentation--semantic .praxis-presentation__content{justify-content:flex-start}.presentation-mode .praxis-presentation--semantic[data-presentation-presenter=iconValue] .praxis-presentation__value{display:inline-flex;flex:0 0 auto;width:auto}.praxis-presentation[data-presentation-presenter=microVisualization] .praxis-presentation__value{display:block;width:100%;max-width:var(--pfx-pres-micro-max-width, 320px);font-size:var(--pfx-pres-micro-font-size, .78rem);line-height:1.2}.pfx-micro-viz{display:grid;gap:6px;width:100%;min-width:0}.pfx-micro-viz__fallback{color:var(--mat-sys-on-surface-variant, currentColor);font-weight:600}.pfx-micro-viz__row{display:grid;grid-template-columns:minmax(48px,.65fr) minmax(92px,1fr) auto;gap:6px;align-items:center;min-width:0}.pfx-micro-viz__label,.pfx-micro-viz__value{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.pfx-micro-viz__label{color:var(--mat-sys-on-surface-variant, currentColor);font-weight:600;opacity:.84}.pfx-micro-viz__value{justify-self:end;font-weight:700}.pfx-micro-viz__track{position:relative;height:8px;overflow:hidden;border-radius:999px;background:color-mix(in srgb,var(--mat-sys-on-surface, currentColor) 12%,transparent)}.pfx-micro-viz__bar,.pfx-micro-viz__target{position:absolute;inset-block:0;border-radius:inherit;background:var(--pfx-micro-tone-color, var(--mat-sys-primary, currentColor))}.pfx-micro-viz__segments{display:flex;height:10px;overflow:hidden;border-radius:999px;background:color-mix(in srgb,var(--mat-sys-on-surface, currentColor) 12%,transparent)}.pfx-micro-viz__segment{min-width:2px;background:var(--pfx-micro-tone-color, var(--mat-sys-primary, currentColor))}.pfx-micro-viz__bullet{display:grid;gap:5px}.pfx-micro-viz__bullet .pfx-micro-viz__track{height:12px}.pfx-micro-viz__target{width:2px;min-width:2px;transform:translate(-1px);background:var(--mat-sys-on-surface, currentColor);opacity:.74}.pfx-micro-viz__delta{display:inline-flex;align-items:center;gap:5px;min-width:0;color:var(--pfx-micro-tone-color, var(--mat-sys-primary, currentColor));font-weight:800}.pfx-micro-viz__delta-symbol{display:inline-grid;place-items:center;width:18px;height:18px;border-radius:999px;background:color-mix(in srgb,currentColor 14%,transparent);font-size:.72rem;line-height:1}.pfx-micro-viz__meta{display:flex;align-items:center;justify-content:space-between;gap:8px;min-width:0;color:var(--mat-sys-on-surface-variant, currentColor);font-weight:600;opacity:.82}.pfx-micro-viz [data-tone=success]{--pfx-micro-tone-color: var(--praxis-success, #0f7b4a)}.pfx-micro-viz [data-tone=warning],.pfx-micro-viz[data-tone=warning]{--pfx-micro-tone-color: var(--praxis-warning, #a16207)}.pfx-micro-viz [data-tone=danger],.pfx-micro-viz[data-tone=danger],.pfx-micro-viz [data-tone=critical],.pfx-micro-viz[data-tone=critical]{--pfx-micro-tone-color: var(--mat-sys-error, #ba1a1a)}.pfx-micro-viz [data-tone=info],.pfx-micro-viz[data-tone=info]{--pfx-micro-tone-color: var(--mat-sys-primary, #0b5cad)}@media(max-width:480px){.presentation-mode.pres-label-left .praxis-presentation{flex-direction:column;align-items:flex-start;gap:4px}.presentation-mode.pres-label-left .praxis-presentation__label{min-width:0;width:auto;text-align:start}.presentation-mode.pres-label-left .praxis-presentation__content{width:100%;flex-basis:auto}}.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}.presentation-mode.pres-compact .praxis-presentation__label,.presentation-mode.pres-density-compact .praxis-presentation__label{font-size:var(--pfx-pres-compact-label-size, var(--pfx-pres-label-size, .72rem));margin-bottom:var(--pfx-pres-compact-label-gap, 1px)}.presentation-mode.pres-compact .praxis-presentation__value,.presentation-mode.pres-density-compact .praxis-presentation__value{font-size:var(--pfx-pres-compact-value-size, var(--pfx-pres-value-size, .92rem));line-height:var(--pfx-pres-compact-value-line-height, 1.22)}.presentation-mode .praxis-presentation--boolean .praxis-presentation__value{display:inline-flex;flex:0 1 auto;align-items:center;justify-content:center;box-sizing:border-box;min-height:var(--pfx-pres-boolean-min-height, 22px);padding:var(--pfx-pres-boolean-padding, 0 8px);border-radius:var(--pfx-pres-boolean-radius, 999px);border:1px solid var(--pfx-pres-boolean-border-color, color-mix(in srgb, currentColor 18%, transparent));background:var(--pfx-pres-boolean-bg, color-mix(in srgb, currentColor 8%, transparent));font-size:var(--pfx-pres-boolean-font-size, .78rem);font-weight:var(--pfx-pres-boolean-font-weight, 700);line-height:var(--pfx-pres-boolean-line-height, 1);text-transform:var(--pfx-pres-boolean-text-transform, none)}.presentation-mode .praxis-presentation--boolean-true .praxis-presentation__value{color:var(--pfx-pres-boolean-true-color, var(--mat-sys-primary, currentColor));background:var(--pfx-pres-boolean-true-bg, color-mix(in srgb, var(--mat-sys-primary, currentColor) 10%, transparent));border-color:var(--pfx-pres-boolean-true-border-color, color-mix(in srgb, var(--mat-sys-primary, currentColor) 24%, transparent))}.presentation-mode .praxis-presentation--boolean-false .praxis-presentation__value{color:var(--pfx-pres-boolean-false-color, var(--mat-sys-on-surface-variant, currentColor));background:var(--pfx-pres-boolean-false-bg, color-mix(in srgb, var(--mat-sys-on-surface, currentColor) 6%, transparent));border-color:var(--pfx-pres-boolean-false-border-color, color-mix(in srgb, var(--mat-sys-on-surface, currentColor) 16%, transparent))}\n"] }]
10291
10566
  }], propDecorators: { field: [{
10292
10567
  type: Input
10293
10568
  }], index: [{
@@ -13697,7 +13972,7 @@ class InlineEntityLookupComponent extends MaterialAsyncSelectComponent {
13697
13972
  .trim();
13698
13973
  }
13699
13974
  interpolateLookupText(template, values) {
13700
- return Object.entries(values).reduce((resolved, [key, value]) => resolved.replaceAll(`{${key}}`, value), template);
13975
+ return Object.entries(values).reduce((resolved, [key, value]) => resolved.split(`{${key}}`).join(value), template);
13701
13976
  }
13702
13977
  lookupDependencyLabels() {
13703
13978
  const dependsOn = this.optionSource()?.dependsOn ?? [];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@praxisui/dynamic-fields",
3
- "version": "9.0.0-beta.20",
3
+ "version": "9.0.0-beta.22",
4
4
  "description": "Angular Material-based dynamic form fields for Praxis UI with lazy loading and metadata-driven rendering.",
5
5
  "peerDependencies": {
6
6
  "@angular/common": "^21.0.0",
@@ -11,8 +11,8 @@
11
11
  "@angular/platform-browser": "^21.0.0",
12
12
  "@angular/router": "^21.0.0",
13
13
  "rxjs": "^7.8.0",
14
- "@praxisui/core": "^9.0.0-beta.20",
15
- "@praxisui/cron-builder": "^9.0.0-beta.20"
14
+ "@praxisui/core": "^9.0.0-beta.22",
15
+ "@praxisui/cron-builder": "^9.0.0-beta.22"
16
16
  },
17
17
  "dependencies": {
18
18
  "libphonenumber-js": "^1.12.41",