@praxisui/dynamic-fields 9.0.0-beta.20 → 9.0.0-beta.21

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.
@@ -179,7 +179,7 @@ Use `stateInitialValues` apenas quando o valor do preset precisa continuar coere
179
179
 
180
180
  | Field | controlType | Quando usar | Quando evitar | Valor esperado | Snippet | Detail doc |
181
181
  | ------------- | --------------------------------------------- | ----------------------------------------------------------------------------------------------------- | ------------------------------------------------ | ----------------------------- | ------------------------------------------------------------------------------- | ----------------------------------------- |
182
- | Checkbox | <span id="checkbox"></span>`checkbox` | booleano simples com `selectionMode: 'boolean'` ou multiplas escolhas com `selectionMode: 'multiple'` | contrato novo sem `selectionMode`; escolha unica | `boolean \| unknown[]` | `{ name: 'privacyConsent', controlType: 'checkbox', selectionMode: 'boolean' }` | `pdx-material-checkbox-group.json-api.md` |
182
+ | Checkbox | <span id="checkbox"></span>`checkbox` | booleano simples com `selectionMode: 'boolean'` ou múltiplas escolhas com `selectionMode: 'multiple'`; em migrações, flags `S`/`N` e `1`/`0` são normalizadas no modo booleano | contrato novo sem `selectionMode`; escolha única | `boolean \| unknown[]` | `{ name: 'privacyConsent', controlType: 'checkbox', selectionMode: 'boolean' }` | `pdx-material-checkbox-group.json-api.md` |
183
183
  | Radio group | <span id="radio"></span>`radio` | escolha unica explicita com `selectionMode: 'single'` | muitas opcoes/espaco restrito | `string \| number \| boolean` | `{ name: 'priority', controlType: 'radio', selectionMode: 'single' }` | `pdx-material-radio-group.json-api.md` |
184
184
  | Toggle | <span id="toggle"></span>`toggle` | booleano binario | multiplos estados | `boolean` | `{ name: 'active', controlType: 'toggle' }` | `pdx-material-slide-toggle.json-api.md` |
185
185
  | Button toggle | <span id="buttontoggle"></span>`buttonToggle` | escolha segmentada curta | listas longas | `string \| number` | `{ name: 'mode', controlType: 'buttonToggle' }` | `pdx-material-button-toggle.json-api.md` |
@@ -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, 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;
9375
9441
  }
9376
- return value ? trueLabel : falseLabel;
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;
9451
+ }
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,6 +9841,7 @@ 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);
9758
9846
  crudService = inject(GenericCrudService, {
9759
9847
  optional: true,
@@ -9915,52 +10003,152 @@ class FieldShellComponent {
9915
10003
  }
9916
10004
  }
9917
10005
  getPresentationValue() {
9918
- const raw = this.presentationDisplayValue ?? this.control?.value;
10006
+ const resolved = this.getResolvedPresentation();
10007
+ const raw = this.getPresentationLabelOverride(resolved) ??
10008
+ this.presentationDisplayValue ??
10009
+ this.control?.value;
10010
+ const field = this.getPresentationFormattingField(resolved);
9919
10011
  try {
9920
- const fn = this.field?.transformDisplayValue;
10012
+ const fn = field?.transformDisplayValue;
9921
10013
  const formatted = typeof fn === 'function'
9922
10014
  ? fn(raw)
9923
- : formatDisplayValue(this.field, raw, {
10015
+ : formatDisplayValue(field, raw, {
9924
10016
  appLocale: this.resolvePresentationAppLocale(),
9925
- surfaceLocale: this.field?.localization?.locale ?? this.field?.locale ?? undefined,
9926
- localization: this.field?.localization ?? undefined,
10017
+ surfaceLocale: field?.localization?.locale ?? field?.locale ?? undefined,
10018
+ localization: field?.localization ?? undefined,
10019
+ booleanLabels: this.resolveBooleanLabels(),
9927
10020
  });
9928
10021
  return formatted == null ? '' : String(formatted);
9929
10022
  }
9930
10023
  catch {
9931
- return formatDisplayValue(this.field, raw, {
10024
+ return formatDisplayValue(field, raw, {
9932
10025
  appLocale: this.resolvePresentationAppLocale(),
9933
- surfaceLocale: this.field?.localization?.locale ?? this.field?.locale ?? undefined,
9934
- localization: this.field?.localization ?? undefined,
10026
+ surfaceLocale: field?.localization?.locale ?? field?.locale ?? undefined,
10027
+ localization: field?.localization ?? undefined,
10028
+ booleanLabels: this.resolveBooleanLabels(),
9935
10029
  });
9936
10030
  }
9937
10031
  }
9938
10032
  getPresentationHtml() {
10033
+ const resolved = this.getResolvedPresentation();
9939
10034
  const raw = this.control?.value;
9940
10035
  const displayValue = this.presentationDisplayValue;
10036
+ const field = this.getPresentationFormattingField(resolved);
10037
+ const semanticLabel = this.getPresentationLabelOverride(resolved);
9941
10038
  try {
9942
- const fn = this.field?.transformDisplayValue;
9943
- const formatted = displayValue !== null
9944
- ? displayValue
9945
- : typeof fn === 'function'
9946
- ? fn(raw)
9947
- : null;
10039
+ const fn = field?.transformDisplayValue;
10040
+ const formatted = semanticLabel !== null
10041
+ ? semanticLabel
10042
+ : displayValue !== null
10043
+ ? displayValue
10044
+ : typeof fn === 'function'
10045
+ ? fn(raw)
10046
+ : null;
9948
10047
  const val = formatted == null ? raw : formatted;
9949
- return formatDisplayHtml(this.field, val, {
10048
+ return formatDisplayHtml(field, val, {
9950
10049
  appLocale: this.resolvePresentationAppLocale(),
9951
- surfaceLocale: this.field?.localization?.locale ?? this.field?.locale ?? undefined,
9952
- localization: this.field?.localization ?? undefined,
10050
+ surfaceLocale: field?.localization?.locale ?? field?.locale ?? undefined,
10051
+ localization: field?.localization ?? undefined,
10052
+ booleanLabels: this.resolveBooleanLabels(),
9953
10053
  });
9954
10054
  }
9955
10055
  catch {
9956
- return formatDisplayHtml(this.field, raw, {
10056
+ return formatDisplayHtml(field, semanticLabel ?? raw, {
9957
10057
  appLocale: this.resolvePresentationAppLocale(),
9958
- surfaceLocale: this.field?.localization?.locale ?? this.field?.locale ?? undefined,
9959
- localization: this.field?.localization ?? undefined,
10058
+ surfaceLocale: field?.localization?.locale ?? field?.locale ?? undefined,
10059
+ localization: field?.localization ?? undefined,
10060
+ booleanLabels: this.resolveBooleanLabels(),
9960
10061
  });
9961
10062
  }
9962
10063
  }
10064
+ getResolvedPresentation() {
10065
+ const field = this.field;
10066
+ return resolveFieldPresentation$1(field?.presentation, field?.presentationRules, this.buildPresentationContext(), { jsonLogic: this.jsonLogic });
10067
+ }
10068
+ hasResolvedPresentationState() {
10069
+ const presentation = this.getResolvedPresentation();
10070
+ return Boolean(presentation.presenter ||
10071
+ presentation.tone ||
10072
+ presentation.icon ||
10073
+ presentation.label ||
10074
+ presentation.badge ||
10075
+ presentation.tooltip ||
10076
+ presentation.appearance ||
10077
+ presentation.valuePresentation);
10078
+ }
10079
+ getPresentationTone() {
10080
+ return this.getResolvedPresentation().tone ?? null;
10081
+ }
10082
+ getPresentationAppearance() {
10083
+ return this.getResolvedPresentation().appearance ?? null;
10084
+ }
10085
+ getPresentationPresenter() {
10086
+ const presenter = this.getResolvedPresentation().presenter;
10087
+ if (presenter) {
10088
+ return presenter;
10089
+ }
10090
+ return this.isBooleanPresentationField() ? 'chip' : 'text';
10091
+ }
10092
+ getPresentationTooltip() {
10093
+ return this.getResolvedPresentation().tooltip ?? this.field?.tooltip ?? null;
10094
+ }
10095
+ getPresentationBadge() {
10096
+ const presentation = this.getResolvedPresentation();
10097
+ if (!presentation.badge || this.shouldPresentationLabelReplaceValue(presentation)) {
10098
+ return null;
10099
+ }
10100
+ return presentation.badge;
10101
+ }
10102
+ isBooleanPresentationField() {
10103
+ const field = this.field;
10104
+ const type = String(field?.valuePresentation?.type ?? field?.dataType ?? field?.controlType ?? '').toLowerCase();
10105
+ return (type === 'boolean' ||
10106
+ type.includes('checkbox') ||
10107
+ type.includes('toggle'));
10108
+ }
10109
+ getBooleanPresentationState() {
10110
+ if (!this.isBooleanPresentationField())
10111
+ return null;
10112
+ const raw = this.control?.value;
10113
+ if (typeof raw === 'boolean')
10114
+ return raw;
10115
+ if (typeof raw === 'number') {
10116
+ if (raw === 1)
10117
+ return true;
10118
+ if (raw === 0)
10119
+ return false;
10120
+ return null;
10121
+ }
10122
+ if (typeof raw !== 'string')
10123
+ return null;
10124
+ const normalized = raw.normalize('NFD').replace(/[\u0300-\u036f]/g, '').trim().toLowerCase();
10125
+ if (['true', 't', 'sim', 's', 'yes', 'y', 'si', 'oui', 'ja', '1'].includes(normalized))
10126
+ return true;
10127
+ if (['false', 'f', 'nao', 'n', 'no', 'non', 'nein', '0'].includes(normalized))
10128
+ return false;
10129
+ return null;
10130
+ }
10131
+ resolveBooleanLabels() {
10132
+ if (this.field?.localization?.locale || this.field?.locale) {
10133
+ return null;
10134
+ }
10135
+ const locale = this.i18n?.getLocale?.() ?? this.angularLocale;
10136
+ if (String(locale).toLowerCase().startsWith('pt')) {
10137
+ return {
10138
+ trueLabel: this.i18n?.t('praxis.dynamicFields.boolean.true', undefined, 'Sim') ?? 'Sim',
10139
+ falseLabel: this.i18n?.t('praxis.dynamicFields.boolean.false', undefined, 'Não') ?? 'Não',
10140
+ };
10141
+ }
10142
+ return {
10143
+ trueLabel: this.i18n?.t('praxis.dynamicFields.boolean.true', undefined, 'Yes') ?? 'Yes',
10144
+ falseLabel: this.i18n?.t('praxis.dynamicFields.boolean.false', undefined, 'No') ?? 'No',
10145
+ };
10146
+ }
9963
10147
  getPresentationPrefixIcon() {
10148
+ const semanticIcon = this.normalizeIconName(this.getResolvedPresentation().icon);
10149
+ if (semanticIcon) {
10150
+ return semanticIcon;
10151
+ }
9964
10152
  const field = this.field;
9965
10153
  const explicit = this.normalizeIconName(field?.prefixIcon);
9966
10154
  if (explicit) {
@@ -10026,6 +10214,9 @@ class FieldShellComponent {
10026
10214
  });
10027
10215
  }
10028
10216
  getPresentationIconColor(position) {
10217
+ if (position === 'prefix' && this.getResolvedPresentation().icon) {
10218
+ return undefined;
10219
+ }
10029
10220
  const field = this.field;
10030
10221
  const value = position === 'prefix'
10031
10222
  ? field?.prefixIconColor ?? field?.iconColor
@@ -10060,6 +10251,55 @@ class FieldShellComponent {
10060
10251
  const angularLocale = this.angularLocale?.trim();
10061
10252
  return angularLocale || 'en-US';
10062
10253
  }
10254
+ getPresentationFormattingField(presentation) {
10255
+ if (!presentation.valuePresentation) {
10256
+ return this.field;
10257
+ }
10258
+ return {
10259
+ ...this.field,
10260
+ valuePresentation: presentation.valuePresentation,
10261
+ };
10262
+ }
10263
+ getPresentationLabelOverride(presentation) {
10264
+ if (!presentation.label || !this.shouldPresentationLabelReplaceValue(presentation)) {
10265
+ return null;
10266
+ }
10267
+ return presentation.label;
10268
+ }
10269
+ shouldPresentationLabelReplaceValue(presentation) {
10270
+ return (Boolean(presentation.label) &&
10271
+ ['status', 'badge', 'chip'].includes(String(presentation.presenter ?? '')));
10272
+ }
10273
+ buildPresentationContext() {
10274
+ const field = this.field;
10275
+ const rawValue = this.control?.value;
10276
+ const fieldName = typeof field?.name === 'string' && field.name.trim().length
10277
+ ? field.name.trim()
10278
+ : undefined;
10279
+ const formData = this.asRecord(field?.presentationContext?.formData ?? field?.formData);
10280
+ const row = this.asRecord(field?.presentationContext?.row ?? field?.row);
10281
+ const context = {
10282
+ value: rawValue,
10283
+ rawValue,
10284
+ fieldName,
10285
+ field,
10286
+ metadata: field,
10287
+ formData,
10288
+ row,
10289
+ };
10290
+ if (formData) {
10291
+ Object.assign(context, formData);
10292
+ }
10293
+ if (fieldName) {
10294
+ context[fieldName] = rawValue;
10295
+ }
10296
+ return context;
10297
+ }
10298
+ asRecord(value) {
10299
+ return value && typeof value === 'object' && !Array.isArray(value)
10300
+ ? value
10301
+ : undefined;
10302
+ }
10063
10303
  refreshPresentationDisplayValue() {
10064
10304
  this.resolveSub?.unsubscribe();
10065
10305
  this.resolveSub = undefined;
@@ -10095,7 +10335,18 @@ class FieldShellComponent {
10095
10335
  >
10096
10336
  <!-- Presentation block -->
10097
10337
  @if (effectivePresentationMode && !renderContentInPresentation()) {
10098
- <div class="praxis-presentation" [attr.data-field]="fieldNameAttr">
10338
+ <div
10339
+ class="praxis-presentation"
10340
+ [class.praxis-presentation--boolean]="isBooleanPresentationField()"
10341
+ [class.praxis-presentation--boolean-true]="getBooleanPresentationState() === true"
10342
+ [class.praxis-presentation--boolean-false]="getBooleanPresentationState() === false"
10343
+ [class.praxis-presentation--semantic]="hasResolvedPresentationState()"
10344
+ [attr.data-field]="fieldNameAttr"
10345
+ [attr.data-presentation-tone]="getPresentationTone()"
10346
+ [attr.data-presentation-appearance]="getPresentationAppearance()"
10347
+ [attr.data-presentation-presenter]="getPresentationPresenter()"
10348
+ [attr.title]="getPresentationTooltip()"
10349
+ >
10099
10350
  <span class="praxis-presentation__label">{{
10100
10351
  fieldLabelText()
10101
10352
  }}</span>
@@ -10116,6 +10367,9 @@ class FieldShellComponent {
10116
10367
  class="praxis-presentation__value"
10117
10368
  [innerHTML]="getPresentationHtml()"
10118
10369
  ></span>
10370
+ @if (getPresentationBadge(); as badge) {
10371
+ <span class="praxis-presentation__badge">{{ badge }}</span>
10372
+ }
10119
10373
  @if (getPresentationSuffixIcon(); as suffixIcon) {
10120
10374
  <mat-icon
10121
10375
  class="praxis-presentation__icon praxis-presentation__icon--suffix"
@@ -10179,7 +10433,7 @@ class FieldShellComponent {
10179
10433
 
10180
10434
  </div>
10181
10435
  </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 });
10436
+ `, 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}@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
10437
  }
10184
10438
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: FieldShellComponent, decorators: [{
10185
10439
  type: Component,
@@ -10203,7 +10457,18 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
10203
10457
  >
10204
10458
  <!-- Presentation block -->
10205
10459
  @if (effectivePresentationMode && !renderContentInPresentation()) {
10206
- <div class="praxis-presentation" [attr.data-field]="fieldNameAttr">
10460
+ <div
10461
+ class="praxis-presentation"
10462
+ [class.praxis-presentation--boolean]="isBooleanPresentationField()"
10463
+ [class.praxis-presentation--boolean-true]="getBooleanPresentationState() === true"
10464
+ [class.praxis-presentation--boolean-false]="getBooleanPresentationState() === false"
10465
+ [class.praxis-presentation--semantic]="hasResolvedPresentationState()"
10466
+ [attr.data-field]="fieldNameAttr"
10467
+ [attr.data-presentation-tone]="getPresentationTone()"
10468
+ [attr.data-presentation-appearance]="getPresentationAppearance()"
10469
+ [attr.data-presentation-presenter]="getPresentationPresenter()"
10470
+ [attr.title]="getPresentationTooltip()"
10471
+ >
10207
10472
  <span class="praxis-presentation__label">{{
10208
10473
  fieldLabelText()
10209
10474
  }}</span>
@@ -10224,6 +10489,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
10224
10489
  class="praxis-presentation__value"
10225
10490
  [innerHTML]="getPresentationHtml()"
10226
10491
  ></span>
10492
+ @if (getPresentationBadge(); as badge) {
10493
+ <span class="praxis-presentation__badge">{{ badge }}</span>
10494
+ }
10227
10495
  @if (getPresentationSuffixIcon(); as suffixIcon) {
10228
10496
  <mat-icon
10229
10497
  class="praxis-presentation__icon praxis-presentation__icon--suffix"
@@ -10287,7 +10555,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
10287
10555
 
10288
10556
  </div>
10289
10557
  </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"] }]
10558
+ `, 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}@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
10559
  }], propDecorators: { field: [{
10292
10560
  type: Input
10293
10561
  }], index: [{
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.21",
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.21",
15
+ "@praxisui/cron-builder": "^9.0.0-beta.21"
16
16
  },
17
17
  "dependencies": {
18
18
  "libphonenumber-js": "^1.12.41",