@praxisui/core 9.0.36 → 9.0.38

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.
@@ -8,13 +8,13 @@ import * as i1$3 from '@angular/common';
8
8
  import { Location, DOCUMENT, CommonModule } from '@angular/common';
9
9
  import { Router, ActivatedRoute } from '@angular/router';
10
10
  import * as i1$2 from '@angular/forms';
11
- import { Validators, FormGroup, FormControl, FormArray, FormsModule } from '@angular/forms';
11
+ import { Validators, FormGroup, FormControl, FormArray, FormsModule, ReactiveFormsModule } from '@angular/forms';
12
12
  import { MatSnackBar } from '@angular/material/snack-bar';
13
13
  import * as i1$1 from '@angular/material/icon';
14
14
  import { MatIconRegistry, MatIconModule } from '@angular/material/icon';
15
15
  import * as i2 from '@angular/material/button';
16
16
  import { MatButtonModule } from '@angular/material/button';
17
- import * as i3 from '@angular/material/form-field';
17
+ import * as i4 from '@angular/material/form-field';
18
18
  import { MatFormFieldModule } from '@angular/material/form-field';
19
19
  import * as i5 from '@angular/material/input';
20
20
  import { MatInputModule } from '@angular/material/input';
@@ -25,16 +25,19 @@ import { MatSlideToggleModule } from '@angular/material/slide-toggle';
25
25
  import * as i8 from '@angular/material/tooltip';
26
26
  import { MatTooltipModule } from '@angular/material/tooltip';
27
27
  import { DomSanitizer } from '@angular/platform-browser';
28
- import * as i4 from '@angular/material/menu';
28
+ import * as i4$1 from '@angular/material/menu';
29
29
  import { MatMenuModule } from '@angular/material/menu';
30
- import * as i3$1 from '@angular/material/progress-spinner';
30
+ import * as i3 from '@angular/material/progress-spinner';
31
31
  import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
32
- import * as i2$1 from '@angular/material/card';
33
- import { MatCardModule } from '@angular/material/card';
34
- import * as i8$1 from '@angular/material/chips';
35
- import { MatChipsModule } from '@angular/material/chips';
32
+ import * as i3$1 from '@angular/material/button-toggle';
33
+ import { MatButtonToggleModule } from '@angular/material/button-toggle';
34
+ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
36
35
  import * as i1$4 from '@angular/material/dialog';
37
36
  import { MAT_DIALOG_DATA, MatDialogModule, MatDialog } from '@angular/material/dialog';
37
+ import * as i8$1 from '@angular/material/chips';
38
+ import { MatChipsModule } from '@angular/material/chips';
39
+ import * as i2$1 from '@angular/material/card';
40
+ import { MatCardModule } from '@angular/material/card';
38
41
  import * as i1$5 from '@angular/material/tabs';
39
42
  import { MatTabsModule } from '@angular/material/tabs';
40
43
 
@@ -3641,7 +3644,8 @@ class ApiConfigStorage {
3641
3644
  return resolved.trim();
3642
3645
  return this.inferComponentType(key);
3643
3646
  };
3644
- // Simple in-memory cache of etag/payload per key to support 304 reuse
3647
+ // Keep read/write validators separate: weak ETags can revalidate GETs but
3648
+ // cannot satisfy If-Match for governed writes.
3645
3649
  cache = new Map();
3646
3650
  constructor() { }
3647
3651
  shouldLogLoadError(key, err) {
@@ -3668,7 +3672,7 @@ class ApiConfigStorage {
3668
3672
  }
3669
3673
  executeLoadConfigRequest(key, establishAvailability) {
3670
3674
  const cached = this.cache.get(key);
3671
- const etag = cached?.etag;
3675
+ const etag = cached?.readEtag ?? cached?.writeEtag;
3672
3676
  const { type, id } = this.resolveKey(key);
3673
3677
  const url = `${this.baseUrl}`;
3674
3678
  const params = this.buildParams(type, id, cached?.scope);
@@ -3691,11 +3695,14 @@ class ApiConfigStorage {
3691
3695
  return this.http
3692
3696
  .get(url, { observe: 'response', headers, params })
3693
3697
  .pipe(map((resp) => {
3694
- const nextEtag = this.stripQuotes(resp.headers.get('ETag'));
3695
3698
  const body = resp.body;
3696
- if (nextEtag) {
3699
+ const responseEtag = resp.headers.get('ETag');
3700
+ const readEtag = this.resolveReadEtag(responseEtag, body?.etag);
3701
+ const writeEtag = this.resolveWriteEtag(responseEtag, body?.etag);
3702
+ if (readEtag || writeEtag) {
3697
3703
  this.cache.set(key, {
3698
- etag: nextEtag,
3704
+ readEtag,
3705
+ writeEtag,
3699
3706
  payload: body?.payload,
3700
3707
  scope: this.resolveResponseScope(body?.scope),
3701
3708
  });
@@ -3723,11 +3730,14 @@ class ApiConfigStorage {
3723
3730
  return this.http
3724
3731
  .get(url, { observe: 'response', headers, params })
3725
3732
  .pipe(map((resp) => {
3726
- const nextEtag = this.stripQuotes(resp.headers.get('ETag'));
3727
3733
  const body = resp.body;
3728
- if (nextEtag) {
3734
+ const responseEtag = resp.headers.get('ETag');
3735
+ const readEtag = this.resolveReadEtag(responseEtag, body?.etag);
3736
+ const writeEtag = this.resolveWriteEtag(responseEtag, body?.etag);
3737
+ if (readEtag || writeEtag) {
3729
3738
  this.cache.set(key, {
3730
- etag: nextEtag,
3739
+ readEtag,
3740
+ writeEtag,
3731
3741
  payload: body?.payload,
3732
3742
  scope: this.resolveResponseScope(body?.scope),
3733
3743
  });
@@ -3754,16 +3764,20 @@ class ApiConfigStorage {
3754
3764
  const url = `${this.baseUrl}`;
3755
3765
  const cached = this.cache.get(key);
3756
3766
  const params = this.buildParams(type, id, cached?.scope);
3757
- const headers = this.buildHeaders(cached?.etag ? { 'If-Match': this.formatEtag(cached.etag) } : undefined);
3767
+ const headers = this.buildHeaders(cached?.writeEtag
3768
+ ? { 'If-Match': this.formatEtag(cached.writeEtag) }
3769
+ : undefined);
3758
3770
  return this.http
3759
3771
  .put(url, { payload: config }, { observe: 'response', headers, params })
3760
3772
  .pipe(map((resp) => {
3761
- const nextEtag = this.stripQuotes(resp.headers.get('ETag'));
3762
- const payload = resp.body?.payload ?? config;
3773
+ const body = resp.body;
3774
+ const responseEtag = resp.headers.get('ETag');
3775
+ const payload = body?.payload ?? config;
3763
3776
  this.cache.set(key, {
3764
- etag: nextEtag,
3777
+ readEtag: this.resolveReadEtag(responseEtag, body?.etag),
3778
+ writeEtag: this.resolveWriteEtag(responseEtag, body?.etag),
3765
3779
  payload,
3766
- scope: this.resolveResponseScope(resp.body?.scope) ?? cached?.scope,
3780
+ scope: this.resolveResponseScope(body?.scope) ?? cached?.scope,
3767
3781
  });
3768
3782
  }), catchError((err) => {
3769
3783
  if (this.shouldLogSaveError(key, err)) {
@@ -3796,18 +3810,22 @@ class ApiConfigStorage {
3796
3810
  shouldPropagateLoadError(key, _err) {
3797
3811
  if (this.opts?.errorPolicy !== 'fail')
3798
3812
  return false;
3799
- return key.startsWith('praxis:global-config');
3813
+ return (key.startsWith('praxis:global-config')
3814
+ || key.startsWith('dynamic-page:'));
3800
3815
  }
3801
3816
  isCriticalPersistenceKey(key) {
3802
3817
  return (key.startsWith('praxis:global-config')
3803
- || key.startsWith('table-config:'));
3818
+ || key.startsWith('table-config:')
3819
+ || key.startsWith('dynamic-page:'));
3804
3820
  }
3805
3821
  clearConfig(key) {
3806
3822
  const { type, id } = this.resolveKey(key);
3807
3823
  const url = `${this.baseUrl}`;
3808
3824
  const cached = this.cache.get(key);
3809
3825
  const params = this.buildParams(type, id, cached?.scope);
3810
- const headers = this.buildHeaders(cached?.etag ? { 'If-Match': this.formatEtag(cached.etag) } : undefined);
3826
+ const headers = this.buildHeaders(cached?.writeEtag
3827
+ ? { 'If-Match': this.formatEtag(cached.writeEtag) }
3828
+ : undefined);
3811
3829
  return this.http
3812
3830
  .delete(url, { observe: 'response', headers, params })
3813
3831
  .pipe(map(() => {
@@ -3919,19 +3937,35 @@ class ApiConfigStorage {
3919
3937
  const parts = value.split(':');
3920
3938
  return (parts.length === 4 || parts.length === 5) && !parts[0].includes('/');
3921
3939
  }
3922
- stripQuotes(value) {
3923
- if (!value)
3940
+ resolveReadEtag(responseHeader, responseBodyEtag) {
3941
+ const header = responseHeader?.trim();
3942
+ if (header)
3943
+ return header;
3944
+ return this.resolveWriteEtag(null, responseBodyEtag);
3945
+ }
3946
+ resolveWriteEtag(responseHeader, responseBodyEtag) {
3947
+ const bodyEtag = this.normalizeStrongEtag(responseBodyEtag);
3948
+ if (bodyEtag)
3949
+ return bodyEtag;
3950
+ return this.normalizeStrongEtag(responseHeader);
3951
+ }
3952
+ normalizeStrongEtag(value) {
3953
+ if (typeof value !== 'string')
3954
+ return null;
3955
+ const normalized = value.trim();
3956
+ if (!normalized || normalized.startsWith('W/'))
3924
3957
  return null;
3925
- const v = value.trim();
3926
- if (v.startsWith('"') && v.endsWith('"') && v.length >= 2) {
3927
- return v.substring(1, v.length - 1);
3958
+ if (normalized.startsWith('"')
3959
+ && normalized.endsWith('"')
3960
+ && normalized.length >= 2) {
3961
+ return normalized.substring(1, normalized.length - 1);
3928
3962
  }
3929
- return v;
3963
+ return normalized;
3930
3964
  }
3931
3965
  formatEtag(etag) {
3932
3966
  if (!etag)
3933
3967
  return undefined;
3934
- return etag.startsWith('"') ? etag : `"${etag}"`;
3968
+ return etag.startsWith('"') || etag.startsWith('W/') ? etag : `"${etag}"`;
3935
3969
  }
3936
3970
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: ApiConfigStorage, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
3937
3971
  static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: ApiConfigStorage, providedIn: 'root' });
@@ -14488,6 +14522,51 @@ const RELATED_RESOURCE_OUTLET_I18N_CONFIG = {
14488
14522
  'action.delete.label': 'Remover {{noun}}',
14489
14523
  'action.delete.tooltip': 'Remova {{noun}} do contexto selecionado.',
14490
14524
  'status.ready': 'Recurso relacionado pronto',
14525
+ 'editor.title': 'Apresentação do recurso relacionado',
14526
+ 'editor.description': 'Configure somente a moldura visual. A relação e seus dados continuam governados pelos metadados.',
14527
+ 'editor.shell.title': 'Apresentação',
14528
+ 'editor.shell.help': 'Textos e escolhas de exibição desta instância do outlet.',
14529
+ 'editor.field.title': 'Título',
14530
+ 'editor.field.subtitle': 'Subtítulo',
14531
+ 'editor.field.icon': 'Ícone',
14532
+ 'editor.field.icon.choose': 'Escolher ícone do outlet',
14533
+ 'editor.field.mode': 'Modo de exibição',
14534
+ 'editor.field.mode.inline': 'Em linha',
14535
+ 'editor.field.mode.openAction': 'Ação de abertura',
14536
+ 'editor.field.presentation': 'Apresentação ao abrir',
14537
+ 'editor.field.presentation.drawer': 'Painel lateral',
14538
+ 'editor.field.presentation.modal': 'Modal',
14539
+ 'editor.field.compact': 'Usar estados vazios e de carregamento compactos',
14540
+ 'editor.emptyState.title': 'Estado vazio',
14541
+ 'editor.emptyState.help': 'Sobrescreva somente a apresentação. Ações, templates e comportamento contextual permanecem intactos.',
14542
+ 'editor.emptyState.field.title': 'Título',
14543
+ 'editor.emptyState.field.message': 'Mensagem',
14544
+ 'editor.emptyState.field.description': 'Descrição',
14545
+ 'editor.emptyState.field.icon': 'Ícone',
14546
+ 'editor.emptyState.field.icon.choose': 'Escolher ícone do estado vazio',
14547
+ 'editor.emptyState.field.tone': 'Tom',
14548
+ 'editor.emptyState.field.variant': 'Variante',
14549
+ 'editor.emptyState.field.alignment': 'Alinhamento',
14550
+ 'editor.emptyState.field.density': 'Densidade',
14551
+ 'editor.emptyState.field.iconContainer': 'Contêiner do ícone',
14552
+ 'editor.value.derived': 'Usar padrão do runtime',
14553
+ 'editor.value.derived.short': 'Automático',
14554
+ 'editor.value.tone.neutral': 'Neutro',
14555
+ 'editor.value.tone.primary': 'Primário',
14556
+ 'editor.value.tone.secondary': 'Secundário',
14557
+ 'editor.value.variant.inline': 'Em linha',
14558
+ 'editor.value.variant.card': 'Cartão',
14559
+ 'editor.value.variant.panel': 'Painel',
14560
+ 'editor.value.variant.transparent': 'Transparente',
14561
+ 'editor.value.alignment.start': 'Início',
14562
+ 'editor.value.alignment.center': 'Centro',
14563
+ 'editor.value.density.compact': 'Compacta',
14564
+ 'editor.value.density.comfortable': 'Confortável',
14565
+ 'editor.value.iconContainer.none': 'Nenhum',
14566
+ 'editor.value.iconContainer.circle': 'Círculo',
14567
+ 'editor.value.iconContainer.soft': 'Suave',
14568
+ 'editor.boundary.title': 'A relação é somente leitura aqui',
14569
+ 'editor.boundary.description': 'Paths de recursos, vínculos com o pai, operações, filtros e a configuração da tabela filha permanecem com seus donos canônicos.',
14491
14570
  },
14492
14571
  'en-US': {
14493
14572
  'state.idle.title': 'Related resource not selected',
@@ -14514,6 +14593,51 @@ const RELATED_RESOURCE_OUTLET_I18N_CONFIG = {
14514
14593
  'action.delete.label': 'Remove {{noun}}',
14515
14594
  'action.delete.tooltip': 'Remove {{noun}} from the selected context.',
14516
14595
  'status.ready': 'Related resource ready',
14596
+ 'editor.title': 'Related resource presentation',
14597
+ 'editor.description': 'Configure only the visual shell. The relationship and its data remain governed by metadata.',
14598
+ 'editor.shell.title': 'Presentation',
14599
+ 'editor.shell.help': 'Copy and display choices for this outlet instance.',
14600
+ 'editor.field.title': 'Title',
14601
+ 'editor.field.subtitle': 'Subtitle',
14602
+ 'editor.field.icon': 'Icon',
14603
+ 'editor.field.icon.choose': 'Choose outlet icon',
14604
+ 'editor.field.mode': 'Display mode',
14605
+ 'editor.field.mode.inline': 'Inline',
14606
+ 'editor.field.mode.openAction': 'Open action',
14607
+ 'editor.field.presentation': 'Open presentation',
14608
+ 'editor.field.presentation.drawer': 'Drawer',
14609
+ 'editor.field.presentation.modal': 'Modal',
14610
+ 'editor.field.compact': 'Use compact empty and loading states',
14611
+ 'editor.emptyState.title': 'Empty state',
14612
+ 'editor.emptyState.help': 'Override presentation only. Actions, templates and contextual behavior remain untouched.',
14613
+ 'editor.emptyState.field.title': 'Title',
14614
+ 'editor.emptyState.field.message': 'Message',
14615
+ 'editor.emptyState.field.description': 'Description',
14616
+ 'editor.emptyState.field.icon': 'Icon',
14617
+ 'editor.emptyState.field.icon.choose': 'Choose empty-state icon',
14618
+ 'editor.emptyState.field.tone': 'Tone',
14619
+ 'editor.emptyState.field.variant': 'Variant',
14620
+ 'editor.emptyState.field.alignment': 'Alignment',
14621
+ 'editor.emptyState.field.density': 'Density',
14622
+ 'editor.emptyState.field.iconContainer': 'Icon container',
14623
+ 'editor.value.derived': 'Use runtime default',
14624
+ 'editor.value.derived.short': 'Auto',
14625
+ 'editor.value.tone.neutral': 'Neutral',
14626
+ 'editor.value.tone.primary': 'Primary',
14627
+ 'editor.value.tone.secondary': 'Secondary',
14628
+ 'editor.value.variant.inline': 'Inline',
14629
+ 'editor.value.variant.card': 'Card',
14630
+ 'editor.value.variant.panel': 'Panel',
14631
+ 'editor.value.variant.transparent': 'Transparent',
14632
+ 'editor.value.alignment.start': 'Start',
14633
+ 'editor.value.alignment.center': 'Center',
14634
+ 'editor.value.density.compact': 'Compact',
14635
+ 'editor.value.density.comfortable': 'Comfortable',
14636
+ 'editor.value.iconContainer.none': 'None',
14637
+ 'editor.value.iconContainer.circle': 'Circle',
14638
+ 'editor.value.iconContainer.soft': 'Soft',
14639
+ 'editor.boundary.title': 'Relationship is read-only here',
14640
+ 'editor.boundary.description': 'Resource paths, parent bindings, operations, filters and child table configuration stay with their canonical owners.',
14517
14641
  },
14518
14642
  },
14519
14643
  },
@@ -27019,7 +27143,7 @@ class SurfaceOpenActionEditorComponent {
27019
27143
  </mat-form-field>
27020
27144
  </div>
27021
27145
  </div>
27022
- `, isInline: true, styles: [".surface-editor{display:grid;gap:14px;min-width:0}.surface-section{display:grid;gap:10px;min-width:0;padding:14px;border:1px solid var(--md-sys-color-outline-variant);border-radius:8px;background:var(--md-sys-color-surface-container-low)}.surface-section-header{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-bottom:0}.surface-section-title{font-size:12px;font-weight:700;letter-spacing:0;text-transform:uppercase;color:var(--md-sys-color-on-surface-variant);margin-bottom:0}.surface-section-header .surface-section-title{margin-bottom:0}.surface-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(220px,100%),1fr));gap:12px 16px;min-width:0}.surface-preset-row{display:flex;flex-wrap:wrap;gap:8px;margin-bottom:8px}.surface-span-2{grid-column:span 2}.surface-span-all{width:100%;min-width:0}.surface-component-meta{display:grid;gap:4px;padding:10px 12px;border-radius:8px;background:var(--md-sys-color-surface-container)}.surface-component-title{font-weight:600;color:var(--md-sys-color-on-surface)}.surface-component-description,.surface-empty{color:var(--md-sys-color-on-surface-variant);font-size:12px;line-height:1.45}.surface-bindings{display:grid;gap:10px;min-width:0}.surface-binding-row{display:grid;grid-template-columns:minmax(min(220px,100%),1.15fr) minmax(min(240px,100%),1.25fr) minmax(128px,.55fr) auto;gap:10px;align-items:start;min-width:0;padding:10px;border-radius:8px;background:var(--md-sys-color-surface-container)}.surface-binding-row mat-form-field:nth-child(4){grid-column:1 / -2}.surface-binding-remove{color:var(--md-sys-color-error)}.surface-guidance{display:grid;gap:4px;padding:10px 12px;border-radius:8px;background:color-mix(in srgb,var(--md-sys-color-primary-container) 18%,transparent);color:var(--md-sys-color-on-surface-variant);font-size:12px;line-height:1.45}.surface-guidance__item{overflow-wrap:anywhere}.surface-guidance__item--primary{color:var(--md-sys-color-on-surface)}mat-form-field{width:100%;min-width:0}@media(max-width:960px){.surface-section{padding:12px}.surface-span-2{grid-column:1 / -1}.surface-binding-row{grid-template-columns:minmax(0,1fr)}.surface-binding-row mat-form-field:nth-child(4){grid-column:auto}}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$2.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$2.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i3.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i3.MatLabel, selector: "mat-label" }, { kind: "directive", type: i3.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "directive", type: i3.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i5.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i6.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i6.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatSlideToggleModule }, { kind: "component", type: i7.MatSlideToggle, selector: "mat-slide-toggle", inputs: ["name", "id", "labelPosition", "aria-label", "aria-labelledby", "aria-describedby", "required", "color", "disabled", "disableRipple", "tabIndex", "checked", "hideIcon", "disabledInteractive"], outputs: ["change", "toggleChange"], exportAs: ["matSlideToggle"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i8.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: PraxisIconButtonComponent, selector: "button[praxisIconButton]", inputs: ["praxisIconButton", "size", "appearance", "presentation", "pressed", "busy"] }] });
27146
+ `, isInline: true, styles: [".surface-editor{display:grid;gap:14px;min-width:0}.surface-section{display:grid;gap:10px;min-width:0;padding:14px;border:1px solid var(--md-sys-color-outline-variant);border-radius:8px;background:var(--md-sys-color-surface-container-low)}.surface-section-header{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-bottom:0}.surface-section-title{font-size:12px;font-weight:700;letter-spacing:0;text-transform:uppercase;color:var(--md-sys-color-on-surface-variant);margin-bottom:0}.surface-section-header .surface-section-title{margin-bottom:0}.surface-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(220px,100%),1fr));gap:12px 16px;min-width:0}.surface-preset-row{display:flex;flex-wrap:wrap;gap:8px;margin-bottom:8px}.surface-span-2{grid-column:span 2}.surface-span-all{width:100%;min-width:0}.surface-component-meta{display:grid;gap:4px;padding:10px 12px;border-radius:8px;background:var(--md-sys-color-surface-container)}.surface-component-title{font-weight:600;color:var(--md-sys-color-on-surface)}.surface-component-description,.surface-empty{color:var(--md-sys-color-on-surface-variant);font-size:12px;line-height:1.45}.surface-bindings{display:grid;gap:10px;min-width:0}.surface-binding-row{display:grid;grid-template-columns:minmax(min(220px,100%),1.15fr) minmax(min(240px,100%),1.25fr) minmax(128px,.55fr) auto;gap:10px;align-items:start;min-width:0;padding:10px;border-radius:8px;background:var(--md-sys-color-surface-container)}.surface-binding-row mat-form-field:nth-child(4){grid-column:1 / -2}.surface-binding-remove{color:var(--md-sys-color-error)}.surface-guidance{display:grid;gap:4px;padding:10px 12px;border-radius:8px;background:color-mix(in srgb,var(--md-sys-color-primary-container) 18%,transparent);color:var(--md-sys-color-on-surface-variant);font-size:12px;line-height:1.45}.surface-guidance__item{overflow-wrap:anywhere}.surface-guidance__item--primary{color:var(--md-sys-color-on-surface)}mat-form-field{width:100%;min-width:0}@media(max-width:960px){.surface-section{padding:12px}.surface-span-2{grid-column:1 / -1}.surface-binding-row{grid-template-columns:minmax(0,1fr)}.surface-binding-row mat-form-field:nth-child(4){grid-column:auto}}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$2.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$2.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i4.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i4.MatLabel, selector: "mat-label" }, { kind: "directive", type: i4.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "directive", type: i4.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i5.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i6.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i6.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatSlideToggleModule }, { kind: "component", type: i7.MatSlideToggle, selector: "mat-slide-toggle", inputs: ["name", "id", "labelPosition", "aria-label", "aria-labelledby", "aria-describedby", "required", "color", "disabled", "disableRipple", "tabIndex", "checked", "hideIcon", "disabledInteractive"], outputs: ["change", "toggleChange"], exportAs: ["matSlideToggle"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i8.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: PraxisIconButtonComponent, selector: "button[praxisIconButton]", inputs: ["praxisIconButton", "size", "appearance", "presentation", "pressed", "busy"] }] });
27023
27147
  }
27024
27148
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: SurfaceOpenActionEditorComponent, decorators: [{
27025
27149
  type: Component,
@@ -27384,6 +27508,151 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
27384
27508
  type: Output
27385
27509
  }] } });
27386
27510
 
27511
+ class ComponentAuthoringManifestProjectionError extends Error {
27512
+ name = 'ComponentAuthoringManifestProjectionError';
27513
+ code;
27514
+ path;
27515
+ constructor(code, path, message) {
27516
+ super(message);
27517
+ this.code = code;
27518
+ this.path = path;
27519
+ }
27520
+ }
27521
+ /**
27522
+ * Materializa um manifesto filho sem copiar ou redefinir operações do owner.
27523
+ *
27524
+ * A função é deliberadamente fail-closed: toda referência deve existir na fonte,
27525
+ * e a closure de targets, validators e examples precisa permanecer executável.
27526
+ */
27527
+ function projectComponentAuthoringManifest(source, projection) {
27528
+ assertProjectionIdentity(source, projection);
27529
+ assertSourceIdentitiesUnique(source);
27530
+ assertReferenceListNotEmpty(projection.runtimeInputNames, 'runtimeInputNames');
27531
+ assertReferenceListNotEmpty(projection.operationIds, 'operationIds');
27532
+ assertUniqueReferences(projection.runtimeInputNames, 'runtimeInputNames');
27533
+ assertUniqueReferences(projection.operationIds, 'operationIds');
27534
+ assertUniqueReferences(projection.roundTripRequirements ?? [], 'roundTripRequirements');
27535
+ const runtimeInputs = selectByStableId(source.runtimeInputs, projection.runtimeInputNames, (input) => input.name, 'runtimeInputNames', 'AUTHORING_MANIFEST_PROJECTION_RUNTIME_INPUT_MISSING');
27536
+ const operations = selectByStableId(source.operations, projection.operationIds, (operation) => operation.operationId, 'operationIds', 'AUTHORING_MANIFEST_PROJECTION_OPERATION_MISSING');
27537
+ const editableTargets = closeEditableTargets(source.editableTargets, operations);
27538
+ const validators = closeValidators(source.validators, operations);
27539
+ const examples = closeExamples(source.examples, operations);
27540
+ const roundTripRequirements = selectRoundTripRequirements(source.roundTripRequirements ?? [], projection.roundTripRequirements ?? []);
27541
+ return cloneManifestValue({
27542
+ schemaVersion: source.schemaVersion,
27543
+ componentId: projection.componentId.trim(),
27544
+ ownerPackage: source.ownerPackage,
27545
+ configSchemaId: source.configSchemaId,
27546
+ manifestVersion: projection.manifestVersion.trim(),
27547
+ runtimeInputs,
27548
+ editableTargets,
27549
+ operations,
27550
+ validators,
27551
+ ...(roundTripRequirements.length ? { roundTripRequirements } : {}),
27552
+ examples,
27553
+ });
27554
+ }
27555
+ function assertSourceIdentitiesUnique(source) {
27556
+ assertSourceCollectionIdentitiesUnique(source.runtimeInputs, (input) => input.name, 'source.runtimeInputs', 'name');
27557
+ assertSourceCollectionIdentitiesUnique(source.operations, (operation) => operation.operationId, 'source.operations', 'operationId');
27558
+ assertSourceCollectionIdentitiesUnique(source.editableTargets, (target) => target.kind, 'source.editableTargets', 'kind');
27559
+ assertSourceCollectionIdentitiesUnique(source.validators, (validator) => validator.validatorId, 'source.validators', 'validatorId');
27560
+ assertSourceCollectionIdentitiesUnique(source.examples, (example) => example.id, 'source.examples', 'id');
27561
+ }
27562
+ function assertSourceCollectionIdentitiesUnique(items, identity, path, identityProperty) {
27563
+ const seen = new Set();
27564
+ items.forEach((item, index) => {
27565
+ const stableId = identity(item)?.trim();
27566
+ if (!stableId) {
27567
+ fail('AUTHORING_MANIFEST_PROJECTION_ID_INVALID', `${path}[${index}].${identityProperty}`, 'Source manifest stable identities must be non-empty.');
27568
+ }
27569
+ if (seen.has(stableId)) {
27570
+ fail('AUTHORING_MANIFEST_PROJECTION_SOURCE_ID_DUPLICATE', `${path}[${index}].${identityProperty}`, `Duplicate source manifest identity ${stableId}.`);
27571
+ }
27572
+ seen.add(stableId);
27573
+ });
27574
+ }
27575
+ function assertReferenceListNotEmpty(references, path) {
27576
+ if (!references.length) {
27577
+ fail('AUTHORING_MANIFEST_PROJECTION_EMPTY_REFERENCE_LIST', path, 'Required projection reference lists must not be empty.');
27578
+ }
27579
+ }
27580
+ function assertProjectionIdentity(source, projection) {
27581
+ if (projection.sourceComponentId !== source.componentId) {
27582
+ fail('AUTHORING_MANIFEST_PROJECTION_SOURCE_MISMATCH', 'sourceComponentId', `Expected sourceComponentId ${source.componentId}, received ${projection.sourceComponentId}.`);
27583
+ }
27584
+ if (!projection.componentId?.trim()) {
27585
+ fail('AUTHORING_MANIFEST_PROJECTION_ID_INVALID', 'componentId', 'Projected componentId must be a non-empty canonical id.');
27586
+ }
27587
+ if (!projection.manifestVersion?.trim()) {
27588
+ fail('AUTHORING_MANIFEST_PROJECTION_ID_INVALID', 'manifestVersion', 'Projected manifestVersion must be non-empty.');
27589
+ }
27590
+ }
27591
+ function assertUniqueReferences(references, path) {
27592
+ const seen = new Set();
27593
+ references.forEach((reference, index) => {
27594
+ const normalized = reference?.trim();
27595
+ if (!normalized || seen.has(normalized)) {
27596
+ fail('AUTHORING_MANIFEST_PROJECTION_DUPLICATE_REFERENCE', `${path}[${index}]`, normalized
27597
+ ? `Duplicate stable reference ${normalized}.`
27598
+ : 'Stable references must be non-empty.');
27599
+ }
27600
+ seen.add(normalized);
27601
+ });
27602
+ }
27603
+ function selectByStableId(source, references, identity, path, missingCode) {
27604
+ const sourceById = new Map(source.map((item) => [identity(item), item]));
27605
+ return references.map((reference, index) => {
27606
+ const resolved = sourceById.get(reference);
27607
+ if (!resolved) {
27608
+ fail(missingCode, `${path}[${index}]`, `Stable reference ${reference} does not exist in the source manifest.`);
27609
+ }
27610
+ return resolved;
27611
+ });
27612
+ }
27613
+ function closeEditableTargets(sourceTargets, operations) {
27614
+ const targetKinds = unique(operations
27615
+ .map((operation) => operation.target?.kind ?? operation.targetKind)
27616
+ .filter((kind) => !!kind));
27617
+ return selectByStableId(sourceTargets, targetKinds, (target) => target.kind, 'source.editableTargets', 'AUTHORING_MANIFEST_PROJECTION_TARGET_MISSING');
27618
+ }
27619
+ function closeValidators(sourceValidators, operations) {
27620
+ const validatorIds = unique(operations.flatMap((operation) => operation.validators ?? []));
27621
+ return selectByStableId(sourceValidators, validatorIds, (validator) => validator.validatorId, 'source.validators', 'AUTHORING_MANIFEST_PROJECTION_VALIDATOR_MISSING');
27622
+ }
27623
+ function closeExamples(sourceExamples, operations) {
27624
+ const operationIds = new Set(operations.map((operation) => operation.operationId));
27625
+ const examples = sourceExamples.filter((example) => operationIds.has(example.operationId));
27626
+ if (!examples.length) {
27627
+ fail('AUTHORING_MANIFEST_PROJECTION_EXAMPLE_MISSING', 'source.examples', 'The projected operations have no source examples.');
27628
+ }
27629
+ if (!examples.some((example) => example.isPositive !== false)) {
27630
+ fail('AUTHORING_MANIFEST_PROJECTION_POSITIVE_EXAMPLE_MISSING', 'source.examples', 'The projected operations require at least one positive source example.');
27631
+ }
27632
+ if (!examples.some((example) => example.isPositive === false)) {
27633
+ fail('AUTHORING_MANIFEST_PROJECTION_NEGATIVE_EXAMPLE_MISSING', 'source.examples', 'The projected operations require at least one negative source example.');
27634
+ }
27635
+ return examples;
27636
+ }
27637
+ function selectRoundTripRequirements(sourceRequirements, projectedRequirements) {
27638
+ return selectByStableId(sourceRequirements, projectedRequirements, (requirement) => requirement, 'roundTripRequirements', 'AUTHORING_MANIFEST_PROJECTION_ROUND_TRIP_REQUIREMENT_MISSING');
27639
+ }
27640
+ function unique(values) {
27641
+ return [...new Set(values)];
27642
+ }
27643
+ function fail(code, path, message) {
27644
+ throw new ComponentAuthoringManifestProjectionError(code, path, message);
27645
+ }
27646
+ function cloneManifestValue(value) {
27647
+ if (Array.isArray(value)) {
27648
+ return value.map((item) => cloneManifestValue(item));
27649
+ }
27650
+ if (value && typeof value === 'object') {
27651
+ return Object.fromEntries(Object.entries(value).map(([key, item]) => [key, cloneManifestValue(item)]));
27652
+ }
27653
+ return value;
27654
+ }
27655
+
27387
27656
  /**
27388
27657
  * Catálogo de capacidades genéricas de FieldMetadata para uso da IA.
27389
27658
  * Baseado em projects/praxis-core/src/lib/models/component-metadata.interface.ts
@@ -31112,7 +31381,9 @@ class PraxisRichTextBlockComponent {
31112
31381
  contentFormat = 'plain';
31113
31382
  content = '';
31114
31383
  get renderedContent() {
31115
- const format = isAllowedEditorialContentFormat(this.contentFormat) ? this.contentFormat : 'plain';
31384
+ const format = isAllowedEditorialContentFormat(this.contentFormat)
31385
+ ? this.contentFormat
31386
+ : 'plain';
31116
31387
  const html = format === 'markdown'
31117
31388
  ? renderEditorialMarkdown(this.content)
31118
31389
  : renderEditorialPlain(this.content);
@@ -31125,11 +31396,15 @@ class PraxisRichTextBlockComponent {
31125
31396
  [class.prt-block-emphasis]="variant === 'emphasis'"
31126
31397
  [class.prt-block-subtle]="variant === 'subtle'"
31127
31398
  [class.prt-block-plain]="appearance === 'plain'"
31128
- >
31399
+ >
31129
31400
  @if (icon || title || subtitle) {
31130
31401
  <header class="prt-head">
31131
31402
  @if (icon) {
31132
- <mat-icon class="prt-icon" aria-hidden="true" [praxisIcon]="icon"></mat-icon>
31403
+ <mat-icon
31404
+ class="prt-icon"
31405
+ aria-hidden="true"
31406
+ [praxisIcon]="icon"
31407
+ ></mat-icon>
31133
31408
  }
31134
31409
  <div class="prt-title-wrap">
31135
31410
  @if (title) {
@@ -31141,15 +31416,15 @@ class PraxisRichTextBlockComponent {
31141
31416
  </div>
31142
31417
  </header>
31143
31418
  }
31144
-
31419
+
31145
31420
  <div class="prt-content" [innerHTML]="renderedContent"></div>
31146
31421
  </section>
31147
- `, isInline: true, styles: [":host{display:block;--prt-border: color-mix(in srgb, var(--md-sys-color-outline-variant) 72%, transparent);--prt-bg: linear-gradient( 180deg, color-mix(in srgb, var(--md-sys-color-surface) 96%, var(--md-sys-color-surface-container-lowest) 4%), color-mix(in srgb, var(--md-sys-color-surface-container-low) 92%, var(--md-sys-color-surface) 8%) );--prt-emphasis-border: color-mix(in srgb, var(--md-sys-color-primary) 32%, var(--md-sys-color-outline-variant));--prt-emphasis-bg: linear-gradient( 180deg, color-mix(in srgb, var(--md-sys-color-primary-container) 36%, var(--md-sys-color-surface) 64%), color-mix(in srgb, var(--md-sys-color-surface) 96%, var(--md-sys-color-primary-container) 4%) );--prt-subtle-bg: color-mix(in srgb, var(--md-sys-color-surface-container-low) 82%, transparent);--prt-icon-bg: color-mix(in srgb, var(--md-sys-color-primary-container) 64%, transparent);--prt-code-bg: color-mix(in srgb, var(--md-sys-color-surface-container-highest) 82%, transparent)}:host-context(.mdc-theme-dark),:host-context(.theme-dark){--prt-border: color-mix(in srgb, var(--md-sys-color-outline-variant) 84%, transparent);--prt-bg: linear-gradient( 180deg, color-mix(in srgb, var(--md-sys-color-surface-container-low) 92%, var(--md-sys-color-surface) 8%), color-mix(in srgb, var(--md-sys-color-surface-container) 90%, var(--md-sys-color-surface-container-high) 10%) );--prt-emphasis-border: color-mix(in srgb, var(--md-sys-color-primary) 42%, var(--md-sys-color-outline-variant));--prt-emphasis-bg: linear-gradient( 180deg, color-mix(in srgb, var(--md-sys-color-primary-container) 28%, var(--md-sys-color-surface-container-low) 72%), color-mix(in srgb, var(--md-sys-color-surface-container) 92%, var(--md-sys-color-primary-container) 8%) );--prt-subtle-bg: color-mix(in srgb, var(--md-sys-color-surface-container-low) 88%, transparent);--prt-icon-bg: color-mix(in srgb, var(--md-sys-color-primary-container) 42%, transparent);--prt-code-bg: color-mix(in srgb, var(--md-sys-color-surface-container-high) 88%, transparent)}.prt-block{display:grid;gap:12px;padding:16px 18px;border-radius:16px;border:1px solid var(--prt-border);background:var(--prt-bg);color:var(--md-sys-color-on-surface)}.prt-block-emphasis{border-color:var(--prt-emphasis-border);background:var(--prt-emphasis-bg)}.prt-block-subtle{background:var(--prt-subtle-bg);border-style:dashed}.prt-block-plain{padding:0;border:0;border-radius:0;background:transparent}.prt-head{display:grid;grid-template-columns:auto 1fr;gap:12px;align-items:start}.prt-icon{display:inline-flex;align-items:center;justify-content:center;width:36px;height:36px;border-radius:12px;background:var(--prt-icon-bg);color:var(--md-sys-color-primary);font-size:20px;line-height:1}.prt-title-wrap{display:grid;gap:4px}.prt-title{margin:0;font-size:1rem;font-weight:700;line-height:1.3}.prt-subtitle{margin:0;color:var(--md-sys-color-on-surface-variant);font-size:.86rem;line-height:1.4}.prt-content{color:var(--md-sys-color-on-surface);font-size:.94rem;line-height:1.6}.prt-content :where(p,ul){margin:0}.prt-content :where(p+p,p+ul,ul+p,ul+ul){margin-top:10px}.prt-content ul{padding-left:18px}.prt-content a{color:var(--md-sys-color-primary);text-decoration:underline;text-underline-offset:2px}.prt-content strong{font-weight:700}.prt-content em{font-style:italic}.prt-content code{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:.88em;padding:.1em .35em;border-radius:6px;background:var(--prt-code-bg)}.prt-block-plain .prt-icon{width:32px;height:32px;border-radius:10px;background:color-mix(in srgb,var(--md-sys-color-surface-container-high) 80%,transparent)}.prt-block-plain .prt-content{font-size:.92rem}\n"], dependencies: [{ kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$1.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 });
31422
+ `, isInline: true, styles: [":host{display:block;min-width:0;max-width:100%;--prt-border: color-mix( in srgb, var(--md-sys-color-outline-variant) 72%, transparent );--prt-bg: linear-gradient( 180deg, color-mix( in srgb, var(--md-sys-color-surface) 96%, var(--md-sys-color-surface-container-lowest) 4% ), color-mix( in srgb, var(--md-sys-color-surface-container-low) 92%, var(--md-sys-color-surface) 8% ) );--prt-emphasis-border: color-mix( in srgb, var(--md-sys-color-primary) 32%, var(--md-sys-color-outline-variant) );--prt-emphasis-bg: linear-gradient( 180deg, color-mix( in srgb, var(--md-sys-color-primary-container) 36%, var(--md-sys-color-surface) 64% ), color-mix( in srgb, var(--md-sys-color-surface) 96%, var(--md-sys-color-primary-container) 4% ) );--prt-subtle-bg: color-mix( in srgb, var(--md-sys-color-surface-container-low) 82%, transparent );--prt-icon-bg: color-mix( in srgb, var(--md-sys-color-primary-container) 64%, transparent );--prt-code-bg: color-mix( in srgb, var(--md-sys-color-surface-container-highest) 82%, transparent )}:host-context(.mdc-theme-dark),:host-context(.theme-dark){--prt-border: color-mix( in srgb, var(--md-sys-color-outline-variant) 84%, transparent );--prt-bg: linear-gradient( 180deg, color-mix( in srgb, var(--md-sys-color-surface-container-low) 92%, var(--md-sys-color-surface) 8% ), color-mix( in srgb, var(--md-sys-color-surface-container) 90%, var(--md-sys-color-surface-container-high) 10% ) );--prt-emphasis-border: color-mix( in srgb, var(--md-sys-color-primary) 42%, var(--md-sys-color-outline-variant) );--prt-emphasis-bg: linear-gradient( 180deg, color-mix( in srgb, var(--md-sys-color-primary-container) 28%, var(--md-sys-color-surface-container-low) 72% ), color-mix( in srgb, var(--md-sys-color-surface-container) 92%, var(--md-sys-color-primary-container) 8% ) );--prt-subtle-bg: color-mix( in srgb, var(--md-sys-color-surface-container-low) 88%, transparent );--prt-icon-bg: color-mix( in srgb, var(--md-sys-color-primary-container) 42%, transparent );--prt-code-bg: color-mix( in srgb, var(--md-sys-color-surface-container-high) 88%, transparent )}.prt-block{display:grid;min-width:0;max-width:100%;box-sizing:border-box;gap:12px;padding:16px 18px;border-radius:16px;border:1px solid var(--prt-border);background:var(--prt-bg);color:var(--md-sys-color-on-surface)}.prt-block-emphasis{border-color:var(--prt-emphasis-border);background:var(--prt-emphasis-bg)}.prt-block-subtle{background:var(--prt-subtle-bg);border-style:dashed}.prt-block-plain{padding:0;border:0;border-radius:0;background:transparent}.prt-head{display:grid;grid-template-columns:auto 1fr;gap:12px;align-items:start}.prt-icon{display:inline-flex;align-items:center;justify-content:center;width:36px;height:36px;border-radius:12px;background:var(--prt-icon-bg);color:var(--md-sys-color-primary);font-size:20px;line-height:1}.prt-title-wrap{display:grid;min-width:0;gap:4px}.prt-title,.prt-subtitle,.prt-content{overflow-wrap:anywhere}.prt-title{margin:0;font-size:1rem;font-weight:700;line-height:1.3}.prt-subtitle{margin:0;color:var(--md-sys-color-on-surface-variant);font-size:.86rem;line-height:1.4}.prt-content{color:var(--md-sys-color-on-surface);font-size:.94rem;line-height:1.6}.prt-content :where(p,ul){margin:0}.prt-content :where(p+p,p+ul,ul+p,ul+ul){margin-top:10px}.prt-content ul{padding-left:18px}.prt-content a{color:var(--md-sys-color-primary);text-decoration:underline;text-underline-offset:2px}.prt-content strong{font-weight:700}.prt-content em{font-style:italic}.prt-content code{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:.88em;padding:.1em .35em;border-radius:6px;background:var(--prt-code-bg)}.prt-block-plain .prt-icon{width:32px;height:32px;border-radius:10px;background:color-mix(in srgb,var(--md-sys-color-surface-container-high) 80%,transparent)}.prt-block-plain .prt-content{font-size:.92rem}\n"], dependencies: [{ kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$1.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 });
31148
31423
  }
31149
31424
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: PraxisRichTextBlockComponent, decorators: [{
31150
31425
  type: Component,
31151
31426
  args: [{ selector: 'praxis-rich-text-block', standalone: true, imports: [MatIconModule, PraxisIconDirective], host: {
31152
- 'class': 'praxis-rich-text-block',
31427
+ class: 'praxis-rich-text-block',
31153
31428
  '[attr.data-instance-id]': 'instanceId || null',
31154
31429
  '[attr.data-analytics-id]': 'analyticsId || null',
31155
31430
  '[attr.data-variant]': 'variant',
@@ -31161,11 +31436,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
31161
31436
  [class.prt-block-emphasis]="variant === 'emphasis'"
31162
31437
  [class.prt-block-subtle]="variant === 'subtle'"
31163
31438
  [class.prt-block-plain]="appearance === 'plain'"
31164
- >
31439
+ >
31165
31440
  @if (icon || title || subtitle) {
31166
31441
  <header class="prt-head">
31167
31442
  @if (icon) {
31168
- <mat-icon class="prt-icon" aria-hidden="true" [praxisIcon]="icon"></mat-icon>
31443
+ <mat-icon
31444
+ class="prt-icon"
31445
+ aria-hidden="true"
31446
+ [praxisIcon]="icon"
31447
+ ></mat-icon>
31169
31448
  }
31170
31449
  <div class="prt-title-wrap">
31171
31450
  @if (title) {
@@ -31177,10 +31456,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
31177
31456
  </div>
31178
31457
  </header>
31179
31458
  }
31180
-
31459
+
31181
31460
  <div class="prt-content" [innerHTML]="renderedContent"></div>
31182
31461
  </section>
31183
- `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{display:block;--prt-border: color-mix(in srgb, var(--md-sys-color-outline-variant) 72%, transparent);--prt-bg: linear-gradient( 180deg, color-mix(in srgb, var(--md-sys-color-surface) 96%, var(--md-sys-color-surface-container-lowest) 4%), color-mix(in srgb, var(--md-sys-color-surface-container-low) 92%, var(--md-sys-color-surface) 8%) );--prt-emphasis-border: color-mix(in srgb, var(--md-sys-color-primary) 32%, var(--md-sys-color-outline-variant));--prt-emphasis-bg: linear-gradient( 180deg, color-mix(in srgb, var(--md-sys-color-primary-container) 36%, var(--md-sys-color-surface) 64%), color-mix(in srgb, var(--md-sys-color-surface) 96%, var(--md-sys-color-primary-container) 4%) );--prt-subtle-bg: color-mix(in srgb, var(--md-sys-color-surface-container-low) 82%, transparent);--prt-icon-bg: color-mix(in srgb, var(--md-sys-color-primary-container) 64%, transparent);--prt-code-bg: color-mix(in srgb, var(--md-sys-color-surface-container-highest) 82%, transparent)}:host-context(.mdc-theme-dark),:host-context(.theme-dark){--prt-border: color-mix(in srgb, var(--md-sys-color-outline-variant) 84%, transparent);--prt-bg: linear-gradient( 180deg, color-mix(in srgb, var(--md-sys-color-surface-container-low) 92%, var(--md-sys-color-surface) 8%), color-mix(in srgb, var(--md-sys-color-surface-container) 90%, var(--md-sys-color-surface-container-high) 10%) );--prt-emphasis-border: color-mix(in srgb, var(--md-sys-color-primary) 42%, var(--md-sys-color-outline-variant));--prt-emphasis-bg: linear-gradient( 180deg, color-mix(in srgb, var(--md-sys-color-primary-container) 28%, var(--md-sys-color-surface-container-low) 72%), color-mix(in srgb, var(--md-sys-color-surface-container) 92%, var(--md-sys-color-primary-container) 8%) );--prt-subtle-bg: color-mix(in srgb, var(--md-sys-color-surface-container-low) 88%, transparent);--prt-icon-bg: color-mix(in srgb, var(--md-sys-color-primary-container) 42%, transparent);--prt-code-bg: color-mix(in srgb, var(--md-sys-color-surface-container-high) 88%, transparent)}.prt-block{display:grid;gap:12px;padding:16px 18px;border-radius:16px;border:1px solid var(--prt-border);background:var(--prt-bg);color:var(--md-sys-color-on-surface)}.prt-block-emphasis{border-color:var(--prt-emphasis-border);background:var(--prt-emphasis-bg)}.prt-block-subtle{background:var(--prt-subtle-bg);border-style:dashed}.prt-block-plain{padding:0;border:0;border-radius:0;background:transparent}.prt-head{display:grid;grid-template-columns:auto 1fr;gap:12px;align-items:start}.prt-icon{display:inline-flex;align-items:center;justify-content:center;width:36px;height:36px;border-radius:12px;background:var(--prt-icon-bg);color:var(--md-sys-color-primary);font-size:20px;line-height:1}.prt-title-wrap{display:grid;gap:4px}.prt-title{margin:0;font-size:1rem;font-weight:700;line-height:1.3}.prt-subtitle{margin:0;color:var(--md-sys-color-on-surface-variant);font-size:.86rem;line-height:1.4}.prt-content{color:var(--md-sys-color-on-surface);font-size:.94rem;line-height:1.6}.prt-content :where(p,ul){margin:0}.prt-content :where(p+p,p+ul,ul+p,ul+ul){margin-top:10px}.prt-content ul{padding-left:18px}.prt-content a{color:var(--md-sys-color-primary);text-decoration:underline;text-underline-offset:2px}.prt-content strong{font-weight:700}.prt-content em{font-style:italic}.prt-content code{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:.88em;padding:.1em .35em;border-radius:6px;background:var(--prt-code-bg)}.prt-block-plain .prt-icon{width:32px;height:32px;border-radius:10px;background:color-mix(in srgb,var(--md-sys-color-surface-container-high) 80%,transparent)}.prt-block-plain .prt-content{font-size:.92rem}\n"] }]
31462
+ `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{display:block;min-width:0;max-width:100%;--prt-border: color-mix( in srgb, var(--md-sys-color-outline-variant) 72%, transparent );--prt-bg: linear-gradient( 180deg, color-mix( in srgb, var(--md-sys-color-surface) 96%, var(--md-sys-color-surface-container-lowest) 4% ), color-mix( in srgb, var(--md-sys-color-surface-container-low) 92%, var(--md-sys-color-surface) 8% ) );--prt-emphasis-border: color-mix( in srgb, var(--md-sys-color-primary) 32%, var(--md-sys-color-outline-variant) );--prt-emphasis-bg: linear-gradient( 180deg, color-mix( in srgb, var(--md-sys-color-primary-container) 36%, var(--md-sys-color-surface) 64% ), color-mix( in srgb, var(--md-sys-color-surface) 96%, var(--md-sys-color-primary-container) 4% ) );--prt-subtle-bg: color-mix( in srgb, var(--md-sys-color-surface-container-low) 82%, transparent );--prt-icon-bg: color-mix( in srgb, var(--md-sys-color-primary-container) 64%, transparent );--prt-code-bg: color-mix( in srgb, var(--md-sys-color-surface-container-highest) 82%, transparent )}:host-context(.mdc-theme-dark),:host-context(.theme-dark){--prt-border: color-mix( in srgb, var(--md-sys-color-outline-variant) 84%, transparent );--prt-bg: linear-gradient( 180deg, color-mix( in srgb, var(--md-sys-color-surface-container-low) 92%, var(--md-sys-color-surface) 8% ), color-mix( in srgb, var(--md-sys-color-surface-container) 90%, var(--md-sys-color-surface-container-high) 10% ) );--prt-emphasis-border: color-mix( in srgb, var(--md-sys-color-primary) 42%, var(--md-sys-color-outline-variant) );--prt-emphasis-bg: linear-gradient( 180deg, color-mix( in srgb, var(--md-sys-color-primary-container) 28%, var(--md-sys-color-surface-container-low) 72% ), color-mix( in srgb, var(--md-sys-color-surface-container) 92%, var(--md-sys-color-primary-container) 8% ) );--prt-subtle-bg: color-mix( in srgb, var(--md-sys-color-surface-container-low) 88%, transparent );--prt-icon-bg: color-mix( in srgb, var(--md-sys-color-primary-container) 42%, transparent );--prt-code-bg: color-mix( in srgb, var(--md-sys-color-surface-container-high) 88%, transparent )}.prt-block{display:grid;min-width:0;max-width:100%;box-sizing:border-box;gap:12px;padding:16px 18px;border-radius:16px;border:1px solid var(--prt-border);background:var(--prt-bg);color:var(--md-sys-color-on-surface)}.prt-block-emphasis{border-color:var(--prt-emphasis-border);background:var(--prt-emphasis-bg)}.prt-block-subtle{background:var(--prt-subtle-bg);border-style:dashed}.prt-block-plain{padding:0;border:0;border-radius:0;background:transparent}.prt-head{display:grid;grid-template-columns:auto 1fr;gap:12px;align-items:start}.prt-icon{display:inline-flex;align-items:center;justify-content:center;width:36px;height:36px;border-radius:12px;background:var(--prt-icon-bg);color:var(--md-sys-color-primary);font-size:20px;line-height:1}.prt-title-wrap{display:grid;min-width:0;gap:4px}.prt-title,.prt-subtitle,.prt-content{overflow-wrap:anywhere}.prt-title{margin:0;font-size:1rem;font-weight:700;line-height:1.3}.prt-subtitle{margin:0;color:var(--md-sys-color-on-surface-variant);font-size:.86rem;line-height:1.4}.prt-content{color:var(--md-sys-color-on-surface);font-size:.94rem;line-height:1.6}.prt-content :where(p,ul){margin:0}.prt-content :where(p+p,p+ul,ul+p,ul+ul){margin-top:10px}.prt-content ul{padding-left:18px}.prt-content a{color:var(--md-sys-color-primary);text-decoration:underline;text-underline-offset:2px}.prt-content strong{font-weight:700}.prt-content em{font-style:italic}.prt-content code{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:.88em;padding:.1em .35em;border-radius:6px;background:var(--prt-code-bg)}.prt-block-plain .prt-icon{width:32px;height:32px;border-radius:10px;background:color-mix(in srgb,var(--md-sys-color-surface-container-high) 80%,transparent)}.prt-block-plain .prt-content{font-size:.92rem}\n"] }]
31184
31463
  }], propDecorators: { instanceId: [{
31185
31464
  type: Input
31186
31465
  }], analyticsId: [{
@@ -31254,7 +31533,9 @@ function renderInlineMarkdown(text) {
31254
31533
  if (!normalized) {
31255
31534
  return escapeHtml(decodeHtml(label));
31256
31535
  }
31257
- const target = normalized.target ? ` target="${escapeHtml(normalized.target)}"` : '';
31536
+ const target = normalized.target
31537
+ ? ` target="${escapeHtml(normalized.target)}"`
31538
+ : '';
31258
31539
  const rel = normalized.rel || EDITORIAL_EXTERNAL_LINK_REL;
31259
31540
  return reserve(`<a href="${escapeHtml(normalized.href)}"${target} rel="${escapeHtml(rel)}">${escapeHtml(normalized.label)}</a>`);
31260
31541
  });
@@ -31285,7 +31566,7 @@ function decodeHtml(value) {
31285
31566
  .replace(/&lt;/g, '<')
31286
31567
  .replace(/&gt;/g, '>')
31287
31568
  .replace(/&quot;/g, '"')
31288
- .replace(/&#39;/g, '\'')
31569
+ .replace(/&#39;/g, "'")
31289
31570
  .replace(/&amp;/g, '&');
31290
31571
  }
31291
31572
 
@@ -32664,7 +32945,11 @@ class WidgetShellComponent {
32664
32945
  return false;
32665
32946
  if (this.shell?.showHeader != null)
32666
32947
  return !!this.shell.showHeader;
32667
- return !!(this.shell?.title || this.shell?.subtitle || this.shell?.icon || this.headerActions.length || this.windowActions.length);
32948
+ return !!(this.shell?.title ||
32949
+ this.shell?.subtitle ||
32950
+ this.shell?.icon ||
32951
+ this.headerActions.length ||
32952
+ this.windowActions.length);
32668
32953
  }
32669
32954
  get headerActions() {
32670
32955
  return (this.shell?.actions || []).filter((a) => this.isVisible(a) && (a.placement || 'header') === 'header');
@@ -32712,13 +32997,15 @@ class WidgetShellComponent {
32712
32997
  this.action.emit(event);
32713
32998
  }
32714
32999
  onHeaderPointerDown(event) {
32715
- if (!this.dragSurfaceInteractive || this.isInteractiveHeaderTarget(event.target)) {
33000
+ if (!this.dragSurfaceInteractive ||
33001
+ this.isInteractiveHeaderTarget(event.target)) {
32716
33002
  return;
32717
33003
  }
32718
33004
  this.dragSurfacePointerDown.emit(event);
32719
33005
  }
32720
33006
  onHeaderKeydown(event) {
32721
- if (!this.dragSurfaceInteractive || this.isInteractiveHeaderTarget(event.target)) {
33007
+ if (!this.dragSurfaceInteractive ||
33008
+ this.isInteractiveHeaderTarget(event.target)) {
32722
33009
  return;
32723
33010
  }
32724
33011
  this.dragSurfaceKeydown.emit(event);
@@ -32800,7 +33087,7 @@ class WidgetShellComponent {
32800
33087
  if (!presetId)
32801
33088
  return undefined;
32802
33089
  const ctxPresets = this.context?.ui?.shell?.presets || {};
32803
- return (ctxPresets && ctxPresets[presetId]) || BUILTIN_SHELL_PRESETS[presetId];
33090
+ return ((ctxPresets && ctxPresets[presetId]) || BUILTIN_SHELL_PRESETS[presetId]);
32804
33091
  }
32805
33092
  mergeAppearance(base, override) {
32806
33093
  if (!base && !override)
@@ -32842,294 +33129,378 @@ class WidgetShellComponent {
32842
33129
  }
32843
33130
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: WidgetShellComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
32844
33131
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: WidgetShellComponent, isStandalone: true, selector: "praxis-widget-shell", inputs: { shell: "shell", context: "context", dragSurfaceEnabled: "dragSurfaceEnabled", dragSurfaceLabel: "dragSurfaceLabel" }, outputs: { action: "action", dragSurfacePointerDown: "dragSurfacePointerDown", dragSurfaceKeydown: "dragSurfaceKeydown" }, host: { properties: { "class.pdx-widget-shell-collapsed": "this.hostCollapsed" } }, providers: [providePraxisI18nConfig(WIDGET_SHELL_I18N_CONFIG)], queries: [{ propertyName: "loader", first: true, predicate: DynamicWidgetLoaderDirective, descendants: true }], usesOnChanges: true, ngImport: i0, template: `
32845
- <section
32846
- class="pdx-shell"
32847
- [class.no-shell]="!shellEnabled"
32848
- [class.dashboard]="shellEnabled"
32849
- [class.collapsed]="collapsed"
32850
- [class.expanded]="expanded"
32851
- [class.fullscreen]="fullscreen"
32852
- [class.body-fill]="shell?.bodyLayout === 'fill'"
32853
- [class.body-scroll]="shell?.bodyLayout === 'scroll'"
32854
- [style.--pdx-shell-card-bg]="appearance?.card?.background || null"
32855
- [style.--pdx-shell-card-border]="appearance?.card?.borderColor || null"
32856
- [style.--pdx-shell-card-radius]="appearance?.card?.borderRadius || null"
32857
- [style.--pdx-shell-card-shadow]="appearance?.card?.shadow || null"
32858
- [style.--pdx-shell-header-bg]="appearance?.header?.background || null"
32859
- [style.--pdx-shell-header-border]="appearance?.header?.borderColor || null"
32860
- [style.--pdx-shell-title-color]="appearance?.header?.titleColor || null"
32861
- [style.--pdx-shell-subtitle-color]="appearance?.header?.subtitleColor || null"
32862
- [style.--pdx-shell-icon-color]="appearance?.header?.iconColor || null"
32863
- [style.--pdx-shell-body-bg]="appearance?.body?.background || null"
32864
- [style.--pdx-shell-body-color]="appearance?.body?.textColor || null"
32865
- [style.--pdx-shell-body-padding]="appearance?.body?.padding || null"
32866
- [style.--pdx-shell-title-size]="appearance?.typography?.titleSize || null"
32867
- [style.--pdx-shell-title-weight]="appearance?.typography?.titleWeight || null"
32868
- [style.--pdx-shell-subtitle-size]="appearance?.typography?.subtitleSize || null"
32869
- (click)="stopIfExpanded($event)"
33132
+ <section
33133
+ class="pdx-shell"
33134
+ [class.no-shell]="!shellEnabled"
33135
+ [class.dashboard]="shellEnabled"
33136
+ [class.collapsed]="collapsed"
33137
+ [class.expanded]="expanded"
33138
+ [class.fullscreen]="fullscreen"
33139
+ [class.body-fill]="shell?.bodyLayout === 'fill'"
33140
+ [class.body-scroll]="shell?.bodyLayout === 'scroll'"
33141
+ [style.--pdx-shell-card-bg]="appearance?.card?.background || null"
33142
+ [style.--pdx-shell-card-border]="appearance?.card?.borderColor || null"
33143
+ [style.--pdx-shell-card-radius]="appearance?.card?.borderRadius || null"
33144
+ [style.--pdx-shell-card-shadow]="appearance?.card?.shadow || null"
33145
+ [style.--pdx-shell-header-bg]="appearance?.header?.background || null"
33146
+ [style.--pdx-shell-header-border]="
33147
+ appearance?.header?.borderColor || null
33148
+ "
33149
+ [style.--pdx-shell-title-color]="appearance?.header?.titleColor || null"
33150
+ [style.--pdx-shell-subtitle-color]="
33151
+ appearance?.header?.subtitleColor || null
33152
+ "
33153
+ [style.--pdx-shell-icon-color]="appearance?.header?.iconColor || null"
33154
+ [style.--pdx-shell-body-bg]="appearance?.body?.background || null"
33155
+ [style.--pdx-shell-body-color]="appearance?.body?.textColor || null"
33156
+ [style.--pdx-shell-body-padding]="appearance?.body?.padding || null"
33157
+ [style.--pdx-shell-title-size]="appearance?.typography?.titleSize || null"
33158
+ [style.--pdx-shell-title-weight]="
33159
+ appearance?.typography?.titleWeight || null
33160
+ "
33161
+ [style.--pdx-shell-subtitle-size]="
33162
+ appearance?.typography?.subtitleSize || null
33163
+ "
33164
+ (click)="stopIfExpanded($event)"
33165
+ >
33166
+ @if (showHeader) {
33167
+ <header
33168
+ class="pdx-shell-header"
33169
+ [class.pdx-shell-header--drag-enabled]="dragSurfaceInteractive"
33170
+ [attr.aria-label]="dragSurfaceInteractive ? dragSurfaceLabel : null"
33171
+ [attr.tabindex]="dragSurfaceInteractive ? 0 : null"
33172
+ (pointerdown)="onHeaderPointerDown($event)"
33173
+ (keydown)="onHeaderKeydown($event)"
32870
33174
  >
32871
- @if (showHeader) {
32872
- <header
32873
- class="pdx-shell-header"
32874
- [class.pdx-shell-header--drag-enabled]="dragSurfaceInteractive"
32875
- [attr.aria-label]="dragSurfaceInteractive ? dragSurfaceLabel : null"
32876
- [attr.tabindex]="dragSurfaceInteractive ? 0 : null"
32877
- (pointerdown)="onHeaderPointerDown($event)"
32878
- (keydown)="onHeaderKeydown($event)"
32879
- >
32880
- <div class="pdx-shell-title">
32881
- @if (shell?.icon) {
32882
- <mat-icon [praxisIcon]="shell?.icon"></mat-icon>
32883
- }
32884
- <div class="pdx-shell-text">
32885
- <div class="pdx-shell-title-text">{{ shellText(shell?.title) }}</div>
32886
- @if (shell?.subtitle) {
32887
- <div class="pdx-shell-subtitle">{{ shellText(shell?.subtitle) }}</div>
32888
- }
33175
+ <div class="pdx-shell-title">
33176
+ @if (shell?.icon) {
33177
+ <mat-icon [praxisIcon]="shell?.icon"></mat-icon>
33178
+ }
33179
+ <div class="pdx-shell-text">
33180
+ <div class="pdx-shell-title-text">
33181
+ {{ shellText(shell?.title) }}
32889
33182
  </div>
33183
+ @if (shell?.subtitle) {
33184
+ <div class="pdx-shell-subtitle">
33185
+ {{ shellText(shell?.subtitle) }}
33186
+ </div>
33187
+ }
32890
33188
  </div>
32891
- <div class="pdx-shell-actions">
32892
- @if (!expanded && !fullscreen) {
32893
- @for (action of visibleHeaderActions; track action.id) {
32894
- <ng-container>
32895
- @if (action.variant !== 'icon') {
32896
- <button
32897
- [disabled]="action.disabled"
32898
- [matTooltip]="actionText(action.tooltip)"
32899
- matTooltipPosition="above"
32900
- [ngClass]="action.variant === 'outlined' ? 'pdx-action-outlined' : 'pdx-action-text'"
32901
- [class.pdx-shell-action--pressed]="action.pressed === true"
32902
- mat-button
32903
- type="button"
32904
- [attr.aria-pressed]="action.pressed == null ? null : action.pressed"
32905
- (click)="onAction(action, $event)"
32906
- >
32907
- @if (displayActionIcon(action); as actionIcon) {
32908
- <mat-icon [praxisIcon]="actionIcon"></mat-icon>
32909
- }
32910
- <span class="pdx-action-label">{{ actionText(action.label) }}</span>
32911
- </button>
32912
- }
32913
- @if (action.variant === 'icon') {
33189
+ </div>
33190
+ <div class="pdx-shell-actions">
33191
+ @if (!expanded && !fullscreen) {
33192
+ @for (action of visibleHeaderActions; track action.id) {
33193
+ <ng-container>
33194
+ @if (action.variant !== 'icon') {
33195
+ <button
33196
+ [disabled]="action.disabled"
33197
+ [matTooltip]="actionText(action.tooltip)"
33198
+ matTooltipPosition="above"
33199
+ [ngClass]="
33200
+ action.variant === 'outlined'
33201
+ ? 'pdx-action-outlined'
33202
+ : 'pdx-action-text'
33203
+ "
33204
+ [class.pdx-shell-action--pressed]="
33205
+ action.pressed === true
33206
+ "
33207
+ mat-button
33208
+ type="button"
33209
+ [attr.aria-pressed]="
33210
+ action.pressed == null ? null : action.pressed
33211
+ "
33212
+ (click)="onAction(action, $event)"
33213
+ >
32914
33214
  @if (displayActionIcon(action); as actionIcon) {
32915
- <button
32916
- [praxisIconButton]="actionIcon"
32917
- size="compact"
32918
- [pressed]="actionPressedState(action)"
32919
- [disabled]="action.disabled"
32920
- [matTooltip]="actionText(action.tooltip, actionText(action.label))"
32921
- matTooltipPosition="above"
32922
- [attr.aria-label]="actionText(action.label, actionText(action.tooltip, action.id))"
32923
- type="button"
32924
- (click)="onAction(action, $event)"
32925
- ></button>
33215
+ <mat-icon [praxisIcon]="actionIcon"></mat-icon>
32926
33216
  }
32927
- }
32928
- </ng-container>
32929
- }
32930
- @if (overflowHeaderActions.length) {
32931
- <button
32932
- praxisIconButton="ms:more_horiz"
32933
- size="compact"
32934
- type="button"
32935
- [matTooltip]="moreActionsLabel()"
32936
- matTooltipPosition="above"
32937
- [attr.aria-label]="moreActionsLabel()"
32938
- [matMenuTriggerFor]="overflowMenu"
32939
- (click)="$event.stopPropagation()"
32940
- ></button>
32941
- }
32942
- }
32943
- @if (windowActions.length) {
32944
- <div class="pdx-shell-window-actions">
32945
- @for (action of windowActions; track action.id) {
33217
+ <span class="pdx-action-label">{{
33218
+ actionText(action.label)
33219
+ }}</span>
33220
+ </button>
33221
+ }
33222
+ @if (action.variant === 'icon') {
32946
33223
  @if (displayActionIcon(action); as actionIcon) {
32947
33224
  <button
32948
33225
  [praxisIconButton]="actionIcon"
32949
33226
  size="compact"
32950
33227
  [pressed]="actionPressedState(action)"
32951
33228
  [disabled]="action.disabled"
32952
- [matTooltip]="actionText(action.tooltip, actionText(action.label))"
33229
+ [matTooltip]="
33230
+ actionText(action.tooltip, actionText(action.label))
33231
+ "
32953
33232
  matTooltipPosition="above"
32954
- [attr.aria-label]="actionText(action.label, actionText(action.tooltip, action.id))"
33233
+ [attr.aria-label]="
33234
+ actionText(
33235
+ action.label,
33236
+ actionText(action.tooltip, action.id)
33237
+ )
33238
+ "
32955
33239
  type="button"
32956
33240
  (click)="onAction(action, $event)"
32957
33241
  ></button>
32958
33242
  }
32959
33243
  }
32960
- </div>
33244
+ </ng-container>
32961
33245
  }
32962
- </div>
32963
- <mat-menu #overflowMenu="matMenu">
32964
- @for (action of overflowHeaderActions; track action.id) {
33246
+ @if (overflowHeaderActions.length) {
32965
33247
  <button
32966
- mat-menu-item
32967
- [attr.aria-pressed]="action.pressed == null ? null : action.pressed"
32968
- (click)="onAction(action, $event)"
32969
- >
33248
+ praxisIconButton="ms:more_horiz"
33249
+ size="compact"
33250
+ type="button"
33251
+ [matTooltip]="moreActionsLabel()"
33252
+ matTooltipPosition="above"
33253
+ [attr.aria-label]="moreActionsLabel()"
33254
+ [matMenuTriggerFor]="overflowMenu"
33255
+ (click)="$event.stopPropagation()"
33256
+ ></button>
33257
+ }
33258
+ }
33259
+ @if (windowActions.length) {
33260
+ <div class="pdx-shell-window-actions">
33261
+ @for (action of windowActions; track action.id) {
32970
33262
  @if (displayActionIcon(action); as actionIcon) {
32971
- <mat-icon [praxisIcon]="actionIcon"></mat-icon>
33263
+ <button
33264
+ [praxisIconButton]="actionIcon"
33265
+ size="compact"
33266
+ [pressed]="actionPressedState(action)"
33267
+ [disabled]="action.disabled"
33268
+ [matTooltip]="
33269
+ actionText(action.tooltip, actionText(action.label))
33270
+ "
33271
+ matTooltipPosition="above"
33272
+ [attr.aria-label]="
33273
+ actionText(
33274
+ action.label,
33275
+ actionText(action.tooltip, action.id)
33276
+ )
33277
+ "
33278
+ type="button"
33279
+ (click)="onAction(action, $event)"
33280
+ ></button>
32972
33281
  }
32973
- <span>{{ actionText(action.label, action.id) }}</span>
32974
- </button>
32975
- }
32976
- </mat-menu>
32977
- </header>
32978
- }
32979
- <div class="pdx-shell-body" [class.hidden]="collapsed">
32980
- <ng-content></ng-content>
32981
- </div>
32982
- </section>
32983
- @if (expanded || fullscreen) {
32984
- <div class="pdx-shell-backdrop" (click)="closeOverlay()"></div>
33282
+ }
33283
+ </div>
33284
+ }
33285
+ </div>
33286
+ <mat-menu #overflowMenu="matMenu">
33287
+ @for (action of overflowHeaderActions; track action.id) {
33288
+ <button
33289
+ mat-menu-item
33290
+ [attr.aria-pressed]="
33291
+ action.pressed == null ? null : action.pressed
33292
+ "
33293
+ (click)="onAction(action, $event)"
33294
+ >
33295
+ @if (displayActionIcon(action); as actionIcon) {
33296
+ <mat-icon [praxisIcon]="actionIcon"></mat-icon>
33297
+ }
33298
+ <span>{{ actionText(action.label, action.id) }}</span>
33299
+ </button>
33300
+ }
33301
+ </mat-menu>
33302
+ </header>
32985
33303
  }
32986
- `, isInline: true, styles: [":host{display:block;height:100%}:host(.pdx-widget-shell-collapsed){height:auto}.pdx-shell{position:relative;height:100%;display:flex;flex-direction:column}.pdx-shell.no-shell{background:transparent;border:none;border-radius:0;box-shadow:none}.pdx-shell.dashboard{background:var(--pdx-shell-card-bg, var(--pdx-dashboard-card-bg, var(--md-sys-color-surface-container-low)));border:1px solid var(--pdx-shell-card-border, var(--pdx-dashboard-card-border, var(--md-sys-color-outline-variant)));border-radius:var(--pdx-shell-card-radius, 12px);box-shadow:var(--pdx-shell-card-shadow, 0 4px 12px rgba(15, 23, 42, .06));overflow:hidden}.pdx-shell-header{display:flex;align-items:center;gap:10px;padding:8px 10px 7px;border-bottom:1px solid var(--pdx-shell-header-border, var(--md-sys-color-outline-variant));background:var(--pdx-shell-header-bg, var(--md-sys-color-surface-container))}.pdx-shell-header--drag-enabled{cursor:grab;-webkit-user-select:none;user-select:none;touch-action:none}.pdx-shell-header--drag-enabled:active{cursor:grabbing}.pdx-shell-header--drag-enabled:focus-visible{outline:2px solid color-mix(in srgb,var(--md-sys-color-primary) 72%,white 28%);outline-offset:-2px}.pdx-shell-title{display:flex;align-items:center;gap:8px;min-width:0;flex:1;color:var(--pdx-shell-title-color, inherit)}.pdx-shell-title mat-icon{color:var(--pdx-shell-icon-color, currentColor)}.pdx-shell-text{min-width:0}.pdx-shell-title-text{font-weight:var(--pdx-shell-title-weight, 600);font-size:var(--pdx-shell-title-size, 13px);line-height:1.15;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.pdx-shell-subtitle{font-size:var(--pdx-shell-subtitle-size, 11px);opacity:.75;color:var(--pdx-shell-subtitle-color, currentColor);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.pdx-shell-actions,.pdx-shell-window-actions{display:flex;align-items:center;gap:4px}.pdx-shell-window-actions{margin-left:auto}@media(max-width:640px){.pdx-shell-header,.pdx-shell-title{align-items:flex-start}.pdx-shell-text{display:grid;gap:2px}.pdx-shell-title-text,.pdx-shell-subtitle{display:-webkit-box;white-space:normal;overflow-wrap:anywhere;-webkit-box-orient:vertical}.pdx-shell-title-text,.pdx-shell-subtitle{-webkit-line-clamp:2}.pdx-shell-actions{flex:0 0 auto}}.pdx-action-outlined{border:1px solid var(--md-sys-color-outline-variant);border-radius:999px;padding:0 10px}.pdx-action-text{padding:0 8px}.pdx-shell-action--pressed:not(.praxis-icon-button){color:var(--md-sys-color-primary);background:color-mix(in srgb,var(--md-sys-color-primary) 12%,transparent)}.pdx-action-label{font-size:12px;font-weight:500}.pdx-shell-body{flex:1;min-height:0;padding:var(--pdx-shell-body-padding, 8px 10px 10px 10px);background:var(--pdx-shell-body-bg, transparent);color:var(--pdx-shell-body-color, inherit)}.pdx-shell.no-shell .pdx-shell-body{padding:0}.pdx-shell-body.hidden{display:none}.pdx-shell.collapsed{height:auto}.pdx-shell.collapsed .pdx-shell-header{border-bottom-color:transparent}.pdx-shell.body-fill .pdx-shell-body,.pdx-shell.body-scroll .pdx-shell-body,.pdx-shell.expanded .pdx-shell-body,.pdx-shell.fullscreen .pdx-shell-body{overflow:auto;display:flex;flex-direction:column;min-height:0}.pdx-shell.collapsed .pdx-shell-body{display:none}.pdx-shell.body-fill .pdx-shell-body{overflow:hidden}.pdx-shell.body-scroll .pdx-shell-body{overflow:auto}.pdx-shell.body-fill .pdx-shell-body>*,.pdx-shell.body-scroll .pdx-shell-body>*,.pdx-shell.expanded .pdx-shell-body>*,.pdx-shell.fullscreen .pdx-shell-body>*{flex:1 1 auto;min-height:0;width:100%}.pdx-shell.expanded{position:fixed;top:10vh;left:50%;width:min(920px,92vw);height:min(640px,82vh);transform:translate(-50%);z-index:var(--praxis-layer-widget-shell-expanded, 1290);box-shadow:var(--mat-elevation-level8)}.pdx-shell.fullscreen{position:fixed;inset:0;width:auto;height:auto;transform:none;border-radius:0;z-index:var(--praxis-layer-widget-shell-fullscreen, 1291);box-shadow:var(--mat-elevation-level8)}.pdx-shell-backdrop{position:fixed;inset:0;z-index:var(--praxis-layer-widget-shell-backdrop, 1280);background:#0000008c;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$3.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i4.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i4.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i4.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i8.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: PraxisIconButtonComponent, selector: "button[praxisIconButton]", inputs: ["praxisIconButton", "size", "appearance", "presentation", "pressed", "busy"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
33304
+ <div class="pdx-shell-body" [class.hidden]="collapsed">
33305
+ <ng-content></ng-content>
33306
+ </div>
33307
+ </section>
33308
+ @if (expanded || fullscreen) {
33309
+ <div class="pdx-shell-backdrop" (click)="closeOverlay()"></div>
33310
+ }
33311
+ `, isInline: true, styles: [":host{display:block;height:100%}:host(.pdx-widget-shell-collapsed){height:auto}.pdx-shell{position:relative;height:100%;display:flex;flex-direction:column}.pdx-shell.no-shell{background:transparent;border:none;border-radius:0;box-shadow:none}.pdx-shell.dashboard{background:var( --pdx-shell-card-bg, var( --pdx-dashboard-card-bg, var(--md-sys-color-surface-container-low) ) );border:1px solid var( --pdx-shell-card-border, var( --pdx-dashboard-card-border, var(--md-sys-color-outline-variant) ) );border-radius:var(--pdx-shell-card-radius, 12px);box-shadow:var( --pdx-shell-card-shadow, 0 4px 12px rgba(15, 23, 42, .06) );overflow:hidden}.pdx-shell-header{display:flex;align-items:center;gap:10px;padding:8px 10px 7px;border-bottom:1px solid var(--pdx-shell-header-border, var(--md-sys-color-outline-variant));background:var( --pdx-shell-header-bg, var(--md-sys-color-surface-container) )}.pdx-shell-header--drag-enabled{cursor:grab;-webkit-user-select:none;user-select:none;touch-action:none}.pdx-shell-header--drag-enabled:active{cursor:grabbing}.pdx-shell-header--drag-enabled:focus-visible{outline:2px solid color-mix(in srgb,var(--md-sys-color-primary) 72%,white 28%);outline-offset:-2px}.pdx-shell-title{display:flex;align-items:center;gap:8px;min-width:0;flex:1;color:var(--pdx-shell-title-color, inherit)}.pdx-shell-title mat-icon{color:var(--pdx-shell-icon-color, currentColor)}.pdx-shell-text{min-width:0}.pdx-shell-title-text{font-weight:var(--pdx-shell-title-weight, 600);font-size:var(--pdx-shell-title-size, 13px);line-height:1.15;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.pdx-shell-subtitle{font-size:var(--pdx-shell-subtitle-size, 11px);color:var( --pdx-shell-subtitle-color, var(--md-sys-color-on-surface-variant, currentColor) );white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.pdx-shell-actions,.pdx-shell-window-actions{display:flex;align-items:center;gap:4px}.pdx-shell-window-actions{margin-left:auto}@media(max-width:640px){.pdx-shell-header,.pdx-shell-title{align-items:flex-start}.pdx-shell-text{display:grid;gap:2px}.pdx-shell-title-text,.pdx-shell-subtitle{display:-webkit-box;white-space:normal;overflow-wrap:anywhere;-webkit-box-orient:vertical}.pdx-shell-title-text,.pdx-shell-subtitle{-webkit-line-clamp:2}.pdx-shell-actions{flex:0 0 auto}}.pdx-action-outlined{border:1px solid var(--md-sys-color-outline-variant);border-radius:999px;padding:0 10px}.pdx-action-text{padding:0 8px}.pdx-shell-action--pressed:not(.praxis-icon-button){color:var(--md-sys-color-primary);background:color-mix(in srgb,var(--md-sys-color-primary) 12%,transparent)}.pdx-action-label{font-size:12px;font-weight:500}.pdx-shell-body{flex:1;min-height:0;padding:var(--pdx-shell-body-padding, 8px 10px 10px 10px);background:var(--pdx-shell-body-bg, transparent);color:var(--pdx-shell-body-color, inherit)}.pdx-shell.no-shell .pdx-shell-body{padding:0}.pdx-shell-body.hidden{display:none}.pdx-shell.collapsed{height:auto}.pdx-shell.collapsed .pdx-shell-header{border-bottom-color:transparent}.pdx-shell.body-fill .pdx-shell-body,.pdx-shell.body-scroll .pdx-shell-body,.pdx-shell.expanded .pdx-shell-body,.pdx-shell.fullscreen .pdx-shell-body{overflow:auto;display:flex;flex-direction:column;min-height:0}.pdx-shell.collapsed .pdx-shell-body{display:none}.pdx-shell.body-fill .pdx-shell-body{overflow:hidden}.pdx-shell.body-scroll .pdx-shell-body{overflow:auto}.pdx-shell.body-fill .pdx-shell-body>*,.pdx-shell.body-scroll .pdx-shell-body>*,.pdx-shell.expanded .pdx-shell-body>*,.pdx-shell.fullscreen .pdx-shell-body>*{flex:1 1 auto;min-height:0;width:100%}.pdx-shell.expanded{position:fixed;top:10vh;left:50%;width:min(920px,92vw);height:min(640px,82vh);transform:translate(-50%);z-index:var(--praxis-layer-widget-shell-expanded, 1290);box-shadow:var(--mat-elevation-level8)}.pdx-shell.fullscreen{position:fixed;inset:0;width:auto;height:auto;transform:none;border-radius:0;z-index:var(--praxis-layer-widget-shell-fullscreen, 1291);box-shadow:var(--mat-elevation-level8)}.pdx-shell-backdrop{position:fixed;inset:0;z-index:var(--praxis-layer-widget-shell-backdrop, 1280);background:#0000008c;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$3.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i4$1.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i4$1.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i4$1.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i8.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: PraxisIconButtonComponent, selector: "button[praxisIconButton]", inputs: ["praxisIconButton", "size", "appearance", "presentation", "pressed", "busy"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
32987
33312
  }
32988
33313
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: WidgetShellComponent, decorators: [{
32989
33314
  type: Component,
32990
- args: [{ selector: 'praxis-widget-shell', standalone: true, imports: [CommonModule, MatButtonModule, MatIconModule, MatMenuModule, MatTooltipModule, PraxisIconButtonComponent, PraxisIconDirective], providers: [providePraxisI18nConfig(WIDGET_SHELL_I18N_CONFIG)], template: `
32991
- <section
32992
- class="pdx-shell"
32993
- [class.no-shell]="!shellEnabled"
32994
- [class.dashboard]="shellEnabled"
32995
- [class.collapsed]="collapsed"
32996
- [class.expanded]="expanded"
32997
- [class.fullscreen]="fullscreen"
32998
- [class.body-fill]="shell?.bodyLayout === 'fill'"
32999
- [class.body-scroll]="shell?.bodyLayout === 'scroll'"
33000
- [style.--pdx-shell-card-bg]="appearance?.card?.background || null"
33001
- [style.--pdx-shell-card-border]="appearance?.card?.borderColor || null"
33002
- [style.--pdx-shell-card-radius]="appearance?.card?.borderRadius || null"
33003
- [style.--pdx-shell-card-shadow]="appearance?.card?.shadow || null"
33004
- [style.--pdx-shell-header-bg]="appearance?.header?.background || null"
33005
- [style.--pdx-shell-header-border]="appearance?.header?.borderColor || null"
33006
- [style.--pdx-shell-title-color]="appearance?.header?.titleColor || null"
33007
- [style.--pdx-shell-subtitle-color]="appearance?.header?.subtitleColor || null"
33008
- [style.--pdx-shell-icon-color]="appearance?.header?.iconColor || null"
33009
- [style.--pdx-shell-body-bg]="appearance?.body?.background || null"
33010
- [style.--pdx-shell-body-color]="appearance?.body?.textColor || null"
33011
- [style.--pdx-shell-body-padding]="appearance?.body?.padding || null"
33012
- [style.--pdx-shell-title-size]="appearance?.typography?.titleSize || null"
33013
- [style.--pdx-shell-title-weight]="appearance?.typography?.titleWeight || null"
33014
- [style.--pdx-shell-subtitle-size]="appearance?.typography?.subtitleSize || null"
33015
- (click)="stopIfExpanded($event)"
33315
+ args: [{ selector: 'praxis-widget-shell', standalone: true, imports: [
33316
+ CommonModule,
33317
+ MatButtonModule,
33318
+ MatIconModule,
33319
+ MatMenuModule,
33320
+ MatTooltipModule,
33321
+ PraxisIconButtonComponent,
33322
+ PraxisIconDirective,
33323
+ ], providers: [providePraxisI18nConfig(WIDGET_SHELL_I18N_CONFIG)], template: `
33324
+ <section
33325
+ class="pdx-shell"
33326
+ [class.no-shell]="!shellEnabled"
33327
+ [class.dashboard]="shellEnabled"
33328
+ [class.collapsed]="collapsed"
33329
+ [class.expanded]="expanded"
33330
+ [class.fullscreen]="fullscreen"
33331
+ [class.body-fill]="shell?.bodyLayout === 'fill'"
33332
+ [class.body-scroll]="shell?.bodyLayout === 'scroll'"
33333
+ [style.--pdx-shell-card-bg]="appearance?.card?.background || null"
33334
+ [style.--pdx-shell-card-border]="appearance?.card?.borderColor || null"
33335
+ [style.--pdx-shell-card-radius]="appearance?.card?.borderRadius || null"
33336
+ [style.--pdx-shell-card-shadow]="appearance?.card?.shadow || null"
33337
+ [style.--pdx-shell-header-bg]="appearance?.header?.background || null"
33338
+ [style.--pdx-shell-header-border]="
33339
+ appearance?.header?.borderColor || null
33340
+ "
33341
+ [style.--pdx-shell-title-color]="appearance?.header?.titleColor || null"
33342
+ [style.--pdx-shell-subtitle-color]="
33343
+ appearance?.header?.subtitleColor || null
33344
+ "
33345
+ [style.--pdx-shell-icon-color]="appearance?.header?.iconColor || null"
33346
+ [style.--pdx-shell-body-bg]="appearance?.body?.background || null"
33347
+ [style.--pdx-shell-body-color]="appearance?.body?.textColor || null"
33348
+ [style.--pdx-shell-body-padding]="appearance?.body?.padding || null"
33349
+ [style.--pdx-shell-title-size]="appearance?.typography?.titleSize || null"
33350
+ [style.--pdx-shell-title-weight]="
33351
+ appearance?.typography?.titleWeight || null
33352
+ "
33353
+ [style.--pdx-shell-subtitle-size]="
33354
+ appearance?.typography?.subtitleSize || null
33355
+ "
33356
+ (click)="stopIfExpanded($event)"
33357
+ >
33358
+ @if (showHeader) {
33359
+ <header
33360
+ class="pdx-shell-header"
33361
+ [class.pdx-shell-header--drag-enabled]="dragSurfaceInteractive"
33362
+ [attr.aria-label]="dragSurfaceInteractive ? dragSurfaceLabel : null"
33363
+ [attr.tabindex]="dragSurfaceInteractive ? 0 : null"
33364
+ (pointerdown)="onHeaderPointerDown($event)"
33365
+ (keydown)="onHeaderKeydown($event)"
33016
33366
  >
33017
- @if (showHeader) {
33018
- <header
33019
- class="pdx-shell-header"
33020
- [class.pdx-shell-header--drag-enabled]="dragSurfaceInteractive"
33021
- [attr.aria-label]="dragSurfaceInteractive ? dragSurfaceLabel : null"
33022
- [attr.tabindex]="dragSurfaceInteractive ? 0 : null"
33023
- (pointerdown)="onHeaderPointerDown($event)"
33024
- (keydown)="onHeaderKeydown($event)"
33025
- >
33026
- <div class="pdx-shell-title">
33027
- @if (shell?.icon) {
33028
- <mat-icon [praxisIcon]="shell?.icon"></mat-icon>
33029
- }
33030
- <div class="pdx-shell-text">
33031
- <div class="pdx-shell-title-text">{{ shellText(shell?.title) }}</div>
33032
- @if (shell?.subtitle) {
33033
- <div class="pdx-shell-subtitle">{{ shellText(shell?.subtitle) }}</div>
33034
- }
33367
+ <div class="pdx-shell-title">
33368
+ @if (shell?.icon) {
33369
+ <mat-icon [praxisIcon]="shell?.icon"></mat-icon>
33370
+ }
33371
+ <div class="pdx-shell-text">
33372
+ <div class="pdx-shell-title-text">
33373
+ {{ shellText(shell?.title) }}
33035
33374
  </div>
33375
+ @if (shell?.subtitle) {
33376
+ <div class="pdx-shell-subtitle">
33377
+ {{ shellText(shell?.subtitle) }}
33378
+ </div>
33379
+ }
33036
33380
  </div>
33037
- <div class="pdx-shell-actions">
33038
- @if (!expanded && !fullscreen) {
33039
- @for (action of visibleHeaderActions; track action.id) {
33040
- <ng-container>
33041
- @if (action.variant !== 'icon') {
33042
- <button
33043
- [disabled]="action.disabled"
33044
- [matTooltip]="actionText(action.tooltip)"
33045
- matTooltipPosition="above"
33046
- [ngClass]="action.variant === 'outlined' ? 'pdx-action-outlined' : 'pdx-action-text'"
33047
- [class.pdx-shell-action--pressed]="action.pressed === true"
33048
- mat-button
33049
- type="button"
33050
- [attr.aria-pressed]="action.pressed == null ? null : action.pressed"
33051
- (click)="onAction(action, $event)"
33052
- >
33053
- @if (displayActionIcon(action); as actionIcon) {
33054
- <mat-icon [praxisIcon]="actionIcon"></mat-icon>
33055
- }
33056
- <span class="pdx-action-label">{{ actionText(action.label) }}</span>
33057
- </button>
33058
- }
33059
- @if (action.variant === 'icon') {
33381
+ </div>
33382
+ <div class="pdx-shell-actions">
33383
+ @if (!expanded && !fullscreen) {
33384
+ @for (action of visibleHeaderActions; track action.id) {
33385
+ <ng-container>
33386
+ @if (action.variant !== 'icon') {
33387
+ <button
33388
+ [disabled]="action.disabled"
33389
+ [matTooltip]="actionText(action.tooltip)"
33390
+ matTooltipPosition="above"
33391
+ [ngClass]="
33392
+ action.variant === 'outlined'
33393
+ ? 'pdx-action-outlined'
33394
+ : 'pdx-action-text'
33395
+ "
33396
+ [class.pdx-shell-action--pressed]="
33397
+ action.pressed === true
33398
+ "
33399
+ mat-button
33400
+ type="button"
33401
+ [attr.aria-pressed]="
33402
+ action.pressed == null ? null : action.pressed
33403
+ "
33404
+ (click)="onAction(action, $event)"
33405
+ >
33060
33406
  @if (displayActionIcon(action); as actionIcon) {
33061
- <button
33062
- [praxisIconButton]="actionIcon"
33063
- size="compact"
33064
- [pressed]="actionPressedState(action)"
33065
- [disabled]="action.disabled"
33066
- [matTooltip]="actionText(action.tooltip, actionText(action.label))"
33067
- matTooltipPosition="above"
33068
- [attr.aria-label]="actionText(action.label, actionText(action.tooltip, action.id))"
33069
- type="button"
33070
- (click)="onAction(action, $event)"
33071
- ></button>
33407
+ <mat-icon [praxisIcon]="actionIcon"></mat-icon>
33072
33408
  }
33073
- }
33074
- </ng-container>
33075
- }
33076
- @if (overflowHeaderActions.length) {
33077
- <button
33078
- praxisIconButton="ms:more_horiz"
33079
- size="compact"
33080
- type="button"
33081
- [matTooltip]="moreActionsLabel()"
33082
- matTooltipPosition="above"
33083
- [attr.aria-label]="moreActionsLabel()"
33084
- [matMenuTriggerFor]="overflowMenu"
33085
- (click)="$event.stopPropagation()"
33086
- ></button>
33087
- }
33088
- }
33089
- @if (windowActions.length) {
33090
- <div class="pdx-shell-window-actions">
33091
- @for (action of windowActions; track action.id) {
33409
+ <span class="pdx-action-label">{{
33410
+ actionText(action.label)
33411
+ }}</span>
33412
+ </button>
33413
+ }
33414
+ @if (action.variant === 'icon') {
33092
33415
  @if (displayActionIcon(action); as actionIcon) {
33093
33416
  <button
33094
33417
  [praxisIconButton]="actionIcon"
33095
33418
  size="compact"
33096
33419
  [pressed]="actionPressedState(action)"
33097
33420
  [disabled]="action.disabled"
33098
- [matTooltip]="actionText(action.tooltip, actionText(action.label))"
33421
+ [matTooltip]="
33422
+ actionText(action.tooltip, actionText(action.label))
33423
+ "
33099
33424
  matTooltipPosition="above"
33100
- [attr.aria-label]="actionText(action.label, actionText(action.tooltip, action.id))"
33425
+ [attr.aria-label]="
33426
+ actionText(
33427
+ action.label,
33428
+ actionText(action.tooltip, action.id)
33429
+ )
33430
+ "
33101
33431
  type="button"
33102
33432
  (click)="onAction(action, $event)"
33103
33433
  ></button>
33104
33434
  }
33105
33435
  }
33106
- </div>
33436
+ </ng-container>
33107
33437
  }
33108
- </div>
33109
- <mat-menu #overflowMenu="matMenu">
33110
- @for (action of overflowHeaderActions; track action.id) {
33438
+ @if (overflowHeaderActions.length) {
33111
33439
  <button
33112
- mat-menu-item
33113
- [attr.aria-pressed]="action.pressed == null ? null : action.pressed"
33114
- (click)="onAction(action, $event)"
33115
- >
33440
+ praxisIconButton="ms:more_horiz"
33441
+ size="compact"
33442
+ type="button"
33443
+ [matTooltip]="moreActionsLabel()"
33444
+ matTooltipPosition="above"
33445
+ [attr.aria-label]="moreActionsLabel()"
33446
+ [matMenuTriggerFor]="overflowMenu"
33447
+ (click)="$event.stopPropagation()"
33448
+ ></button>
33449
+ }
33450
+ }
33451
+ @if (windowActions.length) {
33452
+ <div class="pdx-shell-window-actions">
33453
+ @for (action of windowActions; track action.id) {
33116
33454
  @if (displayActionIcon(action); as actionIcon) {
33117
- <mat-icon [praxisIcon]="actionIcon"></mat-icon>
33455
+ <button
33456
+ [praxisIconButton]="actionIcon"
33457
+ size="compact"
33458
+ [pressed]="actionPressedState(action)"
33459
+ [disabled]="action.disabled"
33460
+ [matTooltip]="
33461
+ actionText(action.tooltip, actionText(action.label))
33462
+ "
33463
+ matTooltipPosition="above"
33464
+ [attr.aria-label]="
33465
+ actionText(
33466
+ action.label,
33467
+ actionText(action.tooltip, action.id)
33468
+ )
33469
+ "
33470
+ type="button"
33471
+ (click)="onAction(action, $event)"
33472
+ ></button>
33118
33473
  }
33119
- <span>{{ actionText(action.label, action.id) }}</span>
33120
- </button>
33121
- }
33122
- </mat-menu>
33123
- </header>
33124
- }
33125
- <div class="pdx-shell-body" [class.hidden]="collapsed">
33126
- <ng-content></ng-content>
33127
- </div>
33128
- </section>
33129
- @if (expanded || fullscreen) {
33130
- <div class="pdx-shell-backdrop" (click)="closeOverlay()"></div>
33474
+ }
33475
+ </div>
33476
+ }
33477
+ </div>
33478
+ <mat-menu #overflowMenu="matMenu">
33479
+ @for (action of overflowHeaderActions; track action.id) {
33480
+ <button
33481
+ mat-menu-item
33482
+ [attr.aria-pressed]="
33483
+ action.pressed == null ? null : action.pressed
33484
+ "
33485
+ (click)="onAction(action, $event)"
33486
+ >
33487
+ @if (displayActionIcon(action); as actionIcon) {
33488
+ <mat-icon [praxisIcon]="actionIcon"></mat-icon>
33489
+ }
33490
+ <span>{{ actionText(action.label, action.id) }}</span>
33491
+ </button>
33492
+ }
33493
+ </mat-menu>
33494
+ </header>
33131
33495
  }
33132
- `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{display:block;height:100%}:host(.pdx-widget-shell-collapsed){height:auto}.pdx-shell{position:relative;height:100%;display:flex;flex-direction:column}.pdx-shell.no-shell{background:transparent;border:none;border-radius:0;box-shadow:none}.pdx-shell.dashboard{background:var(--pdx-shell-card-bg, var(--pdx-dashboard-card-bg, var(--md-sys-color-surface-container-low)));border:1px solid var(--pdx-shell-card-border, var(--pdx-dashboard-card-border, var(--md-sys-color-outline-variant)));border-radius:var(--pdx-shell-card-radius, 12px);box-shadow:var(--pdx-shell-card-shadow, 0 4px 12px rgba(15, 23, 42, .06));overflow:hidden}.pdx-shell-header{display:flex;align-items:center;gap:10px;padding:8px 10px 7px;border-bottom:1px solid var(--pdx-shell-header-border, var(--md-sys-color-outline-variant));background:var(--pdx-shell-header-bg, var(--md-sys-color-surface-container))}.pdx-shell-header--drag-enabled{cursor:grab;-webkit-user-select:none;user-select:none;touch-action:none}.pdx-shell-header--drag-enabled:active{cursor:grabbing}.pdx-shell-header--drag-enabled:focus-visible{outline:2px solid color-mix(in srgb,var(--md-sys-color-primary) 72%,white 28%);outline-offset:-2px}.pdx-shell-title{display:flex;align-items:center;gap:8px;min-width:0;flex:1;color:var(--pdx-shell-title-color, inherit)}.pdx-shell-title mat-icon{color:var(--pdx-shell-icon-color, currentColor)}.pdx-shell-text{min-width:0}.pdx-shell-title-text{font-weight:var(--pdx-shell-title-weight, 600);font-size:var(--pdx-shell-title-size, 13px);line-height:1.15;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.pdx-shell-subtitle{font-size:var(--pdx-shell-subtitle-size, 11px);opacity:.75;color:var(--pdx-shell-subtitle-color, currentColor);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.pdx-shell-actions,.pdx-shell-window-actions{display:flex;align-items:center;gap:4px}.pdx-shell-window-actions{margin-left:auto}@media(max-width:640px){.pdx-shell-header,.pdx-shell-title{align-items:flex-start}.pdx-shell-text{display:grid;gap:2px}.pdx-shell-title-text,.pdx-shell-subtitle{display:-webkit-box;white-space:normal;overflow-wrap:anywhere;-webkit-box-orient:vertical}.pdx-shell-title-text,.pdx-shell-subtitle{-webkit-line-clamp:2}.pdx-shell-actions{flex:0 0 auto}}.pdx-action-outlined{border:1px solid var(--md-sys-color-outline-variant);border-radius:999px;padding:0 10px}.pdx-action-text{padding:0 8px}.pdx-shell-action--pressed:not(.praxis-icon-button){color:var(--md-sys-color-primary);background:color-mix(in srgb,var(--md-sys-color-primary) 12%,transparent)}.pdx-action-label{font-size:12px;font-weight:500}.pdx-shell-body{flex:1;min-height:0;padding:var(--pdx-shell-body-padding, 8px 10px 10px 10px);background:var(--pdx-shell-body-bg, transparent);color:var(--pdx-shell-body-color, inherit)}.pdx-shell.no-shell .pdx-shell-body{padding:0}.pdx-shell-body.hidden{display:none}.pdx-shell.collapsed{height:auto}.pdx-shell.collapsed .pdx-shell-header{border-bottom-color:transparent}.pdx-shell.body-fill .pdx-shell-body,.pdx-shell.body-scroll .pdx-shell-body,.pdx-shell.expanded .pdx-shell-body,.pdx-shell.fullscreen .pdx-shell-body{overflow:auto;display:flex;flex-direction:column;min-height:0}.pdx-shell.collapsed .pdx-shell-body{display:none}.pdx-shell.body-fill .pdx-shell-body{overflow:hidden}.pdx-shell.body-scroll .pdx-shell-body{overflow:auto}.pdx-shell.body-fill .pdx-shell-body>*,.pdx-shell.body-scroll .pdx-shell-body>*,.pdx-shell.expanded .pdx-shell-body>*,.pdx-shell.fullscreen .pdx-shell-body>*{flex:1 1 auto;min-height:0;width:100%}.pdx-shell.expanded{position:fixed;top:10vh;left:50%;width:min(920px,92vw);height:min(640px,82vh);transform:translate(-50%);z-index:var(--praxis-layer-widget-shell-expanded, 1290);box-shadow:var(--mat-elevation-level8)}.pdx-shell.fullscreen{position:fixed;inset:0;width:auto;height:auto;transform:none;border-radius:0;z-index:var(--praxis-layer-widget-shell-fullscreen, 1291);box-shadow:var(--mat-elevation-level8)}.pdx-shell-backdrop{position:fixed;inset:0;z-index:var(--praxis-layer-widget-shell-backdrop, 1280);background:#0000008c;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px)}\n"] }]
33496
+ <div class="pdx-shell-body" [class.hidden]="collapsed">
33497
+ <ng-content></ng-content>
33498
+ </div>
33499
+ </section>
33500
+ @if (expanded || fullscreen) {
33501
+ <div class="pdx-shell-backdrop" (click)="closeOverlay()"></div>
33502
+ }
33503
+ `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{display:block;height:100%}:host(.pdx-widget-shell-collapsed){height:auto}.pdx-shell{position:relative;height:100%;display:flex;flex-direction:column}.pdx-shell.no-shell{background:transparent;border:none;border-radius:0;box-shadow:none}.pdx-shell.dashboard{background:var( --pdx-shell-card-bg, var( --pdx-dashboard-card-bg, var(--md-sys-color-surface-container-low) ) );border:1px solid var( --pdx-shell-card-border, var( --pdx-dashboard-card-border, var(--md-sys-color-outline-variant) ) );border-radius:var(--pdx-shell-card-radius, 12px);box-shadow:var( --pdx-shell-card-shadow, 0 4px 12px rgba(15, 23, 42, .06) );overflow:hidden}.pdx-shell-header{display:flex;align-items:center;gap:10px;padding:8px 10px 7px;border-bottom:1px solid var(--pdx-shell-header-border, var(--md-sys-color-outline-variant));background:var( --pdx-shell-header-bg, var(--md-sys-color-surface-container) )}.pdx-shell-header--drag-enabled{cursor:grab;-webkit-user-select:none;user-select:none;touch-action:none}.pdx-shell-header--drag-enabled:active{cursor:grabbing}.pdx-shell-header--drag-enabled:focus-visible{outline:2px solid color-mix(in srgb,var(--md-sys-color-primary) 72%,white 28%);outline-offset:-2px}.pdx-shell-title{display:flex;align-items:center;gap:8px;min-width:0;flex:1;color:var(--pdx-shell-title-color, inherit)}.pdx-shell-title mat-icon{color:var(--pdx-shell-icon-color, currentColor)}.pdx-shell-text{min-width:0}.pdx-shell-title-text{font-weight:var(--pdx-shell-title-weight, 600);font-size:var(--pdx-shell-title-size, 13px);line-height:1.15;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.pdx-shell-subtitle{font-size:var(--pdx-shell-subtitle-size, 11px);color:var( --pdx-shell-subtitle-color, var(--md-sys-color-on-surface-variant, currentColor) );white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.pdx-shell-actions,.pdx-shell-window-actions{display:flex;align-items:center;gap:4px}.pdx-shell-window-actions{margin-left:auto}@media(max-width:640px){.pdx-shell-header,.pdx-shell-title{align-items:flex-start}.pdx-shell-text{display:grid;gap:2px}.pdx-shell-title-text,.pdx-shell-subtitle{display:-webkit-box;white-space:normal;overflow-wrap:anywhere;-webkit-box-orient:vertical}.pdx-shell-title-text,.pdx-shell-subtitle{-webkit-line-clamp:2}.pdx-shell-actions{flex:0 0 auto}}.pdx-action-outlined{border:1px solid var(--md-sys-color-outline-variant);border-radius:999px;padding:0 10px}.pdx-action-text{padding:0 8px}.pdx-shell-action--pressed:not(.praxis-icon-button){color:var(--md-sys-color-primary);background:color-mix(in srgb,var(--md-sys-color-primary) 12%,transparent)}.pdx-action-label{font-size:12px;font-weight:500}.pdx-shell-body{flex:1;min-height:0;padding:var(--pdx-shell-body-padding, 8px 10px 10px 10px);background:var(--pdx-shell-body-bg, transparent);color:var(--pdx-shell-body-color, inherit)}.pdx-shell.no-shell .pdx-shell-body{padding:0}.pdx-shell-body.hidden{display:none}.pdx-shell.collapsed{height:auto}.pdx-shell.collapsed .pdx-shell-header{border-bottom-color:transparent}.pdx-shell.body-fill .pdx-shell-body,.pdx-shell.body-scroll .pdx-shell-body,.pdx-shell.expanded .pdx-shell-body,.pdx-shell.fullscreen .pdx-shell-body{overflow:auto;display:flex;flex-direction:column;min-height:0}.pdx-shell.collapsed .pdx-shell-body{display:none}.pdx-shell.body-fill .pdx-shell-body{overflow:hidden}.pdx-shell.body-scroll .pdx-shell-body{overflow:auto}.pdx-shell.body-fill .pdx-shell-body>*,.pdx-shell.body-scroll .pdx-shell-body>*,.pdx-shell.expanded .pdx-shell-body>*,.pdx-shell.fullscreen .pdx-shell-body>*{flex:1 1 auto;min-height:0;width:100%}.pdx-shell.expanded{position:fixed;top:10vh;left:50%;width:min(920px,92vw);height:min(640px,82vh);transform:translate(-50%);z-index:var(--praxis-layer-widget-shell-expanded, 1290);box-shadow:var(--mat-elevation-level8)}.pdx-shell.fullscreen{position:fixed;inset:0;width:auto;height:auto;transform:none;border-radius:0;z-index:var(--praxis-layer-widget-shell-fullscreen, 1291);box-shadow:var(--mat-elevation-level8)}.pdx-shell-backdrop{position:fixed;inset:0;z-index:var(--praxis-layer-widget-shell-backdrop, 1280);background:#0000008c;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px)}\n"] }]
33133
33504
  }], propDecorators: { hostCollapsed: [{
33134
33505
  type: HostBinding,
33135
33506
  args: ['class.pdx-widget-shell-collapsed']
@@ -37486,7 +37857,7 @@ class DynamicWidgetContextToolbarComponent {
37486
37857
  </mat-menu>
37487
37858
  }
37488
37859
  </div>
37489
- `, isInline: true, styles: [".pdx-widget-context-toolbar{position:absolute;top:-19px;right:12px;z-index:4;display:inline-flex;align-items:center;gap:4px;min-height:34px;padding:2px 4px;border:1px solid color-mix(in srgb,var(--md-sys-color-primary) 28%,var(--md-sys-color-outline-variant));border-radius:999px;background:color-mix(in srgb,var(--md-sys-color-surface-container-high) 88%,transparent);box-shadow:0 10px 28px #0f172a38,0 0 0 1px color-mix(in srgb,var(--md-sys-color-primary) 10%,transparent);-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px)}.pdx-widget-context-toolbar--with-context{border-radius:18px}.pdx-widget-context-toolbar__context{display:inline-flex;align-items:center;align-self:stretch;max-width:180px;padding:0 8px 0 10px;border-right:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 64%,transparent);color:var(--md-sys-color-on-surface-variant);font-size:11px;font-weight:700;letter-spacing:.01em;line-height:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n"], dependencies: [{ kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i4.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i4.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i4.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i8.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }, { kind: "component", type: PraxisIconButtonComponent, selector: "button[praxisIconButton]", inputs: ["praxisIconButton", "size", "appearance", "presentation", "pressed", "busy"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
37860
+ `, isInline: true, styles: [".pdx-widget-context-toolbar{position:absolute;top:-19px;right:12px;z-index:4;display:inline-flex;align-items:center;gap:4px;min-height:34px;padding:2px 4px;border:1px solid color-mix(in srgb,var(--md-sys-color-primary) 28%,var(--md-sys-color-outline-variant));border-radius:999px;background:color-mix(in srgb,var(--md-sys-color-surface-container-high) 88%,transparent);box-shadow:0 10px 28px #0f172a38,0 0 0 1px color-mix(in srgb,var(--md-sys-color-primary) 10%,transparent);-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px)}.pdx-widget-context-toolbar--with-context{border-radius:18px}.pdx-widget-context-toolbar__context{display:inline-flex;align-items:center;align-self:stretch;max-width:180px;padding:0 8px 0 10px;border-right:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 64%,transparent);color:var(--md-sys-color-on-surface-variant);font-size:11px;font-weight:700;letter-spacing:.01em;line-height:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n"], dependencies: [{ kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i4$1.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i4$1.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i4$1.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i8.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }, { kind: "component", type: PraxisIconButtonComponent, selector: "button[praxisIconButton]", inputs: ["praxisIconButton", "size", "appearance", "presentation", "pressed", "busy"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
37490
37861
  }
37491
37862
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: DynamicWidgetContextToolbarComponent, decorators: [{
37492
37863
  type: Component,
@@ -39237,9 +39608,7 @@ class DynamicWidgetPageComponent {
39237
39608
  return this.isAuthoringCapabilityEnabled('canvas');
39238
39609
  }
39239
39610
  canOpenPageSettings() {
39240
- return this.isAuthoringCapabilityEnabled('pageSettings')
39241
- && this.showPageSettingsButton
39242
- && !!(this.pageEditorComponent || this.defaultPageEditor);
39611
+ return this.showPageSettingsButton && this.canInvokePageSettings();
39243
39612
  }
39244
39613
  canOpenWidgetShellSettings() {
39245
39614
  return this.isWidgetShellCapabilityEnabled()
@@ -39700,7 +40069,7 @@ class DynamicWidgetPageComponent {
39700
40069
  this.dispatchWidgetComponentSettingsToRuntime(key);
39701
40070
  return;
39702
40071
  }
39703
- const page = this.materializeRuntimeInputsForWidget(this.ensurePageDefinition(), key);
40072
+ const page = this.ensurePageDefinition();
39704
40073
  const widget = page.widgets.find((w) => w.key === key);
39705
40074
  if (!widget)
39706
40075
  return;
@@ -39711,9 +40080,12 @@ class DynamicWidgetPageComponent {
39711
40080
  return;
39712
40081
  }
39713
40082
  const persistedInputs = this.cloneStateValues(widget.definition.inputs || {});
40083
+ const materializedInputs = metadata.configEditor?.contextResolver
40084
+ ? this.readMaterializedInputsForWidget(metadata, key)
40085
+ : undefined;
39714
40086
  const requestId = ++this.nextConfigEditorContextRequestId;
39715
40087
  this.configEditorContextRequests.set(key, requestId);
39716
- const contextResult = await this.resolveWidgetConfigEditorContext(metadata, page, widget, key, persistedInputs);
40088
+ const contextResult = await this.resolveWidgetConfigEditorContext(metadata, page, widget, key, persistedInputs, materializedInputs);
39717
40089
  if (this.configEditorContextRequests.get(key) !== requestId) {
39718
40090
  return;
39719
40091
  }
@@ -39736,7 +40108,7 @@ class DynamicWidgetPageComponent {
39736
40108
  ref.applied$.subscribe((result) => this.applyWidgetComponentInputs(key, result, false));
39737
40109
  ref.saved$.subscribe((result) => this.applyWidgetComponentInputs(key, result, true));
39738
40110
  }
39739
- async resolveWidgetConfigEditorContext(metadata, page, widget, key, persistedInputs) {
40111
+ async resolveWidgetConfigEditorContext(metadata, page, widget, key, persistedInputs, materializedInputs) {
39740
40112
  const resolver = metadata.configEditor?.contextResolver;
39741
40113
  if (!resolver) {
39742
40114
  return {};
@@ -39747,6 +40119,11 @@ class DynamicWidgetPageComponent {
39747
40119
  widgetKey: key,
39748
40120
  widgetType: widget.definition?.id,
39749
40121
  persistedInputs: this.cloneStateValues(persistedInputs),
40122
+ ...(materializedInputs
40123
+ ? {
40124
+ materializedInputs: this.cloneStateValues(materializedInputs),
40125
+ }
40126
+ : {}),
39750
40127
  page: this.cloneStateValues(page),
39751
40128
  widget: this.cloneStateValues(widget),
39752
40129
  metadata,
@@ -39783,39 +40160,22 @@ class DynamicWidgetPageComponent {
39783
40160
  !Array.isArray(value) &&
39784
40161
  ('context' in value || 'diagnostics' in value));
39785
40162
  }
39786
- materializeRuntimeInputsForWidget(page, key) {
40163
+ readMaterializedInputsForWidget(metadata, key) {
39787
40164
  const normalizedKey = String(key || '').trim();
39788
40165
  if (!normalizedKey) {
39789
- return page;
39790
- }
39791
- const widget = page.widgets?.find((candidate) => candidate.key === normalizedKey);
39792
- if (!widget) {
39793
- return page;
40166
+ return undefined;
39794
40167
  }
39795
- const inputNames = this.componentMetadata
39796
- ?.get(widget.definition?.id || '')
39797
- ?.inputs?.map((input) => input.name)
40168
+ const inputNames = metadata.inputs
40169
+ ?.map((input) => input.name)
39798
40170
  ?.filter((name) => typeof name === 'string' && !!name.trim()) || [];
39799
40171
  if (!inputNames.length) {
39800
- return page;
40172
+ return undefined;
39801
40173
  }
39802
40174
  const loader = this.findWidgetLoader(normalizedKey);
39803
- const materializedInputs = loader?.materializedInputSnapshot(inputNames) || {};
39804
- if (!Object.keys(materializedInputs).length) {
39805
- return page;
39806
- }
39807
- const result = this.applyWidgetInputPatchToPage(page, normalizedKey, {
39808
- sourceComponentId: widget.definition?.id,
39809
- output: 'runtimeInputSnapshot',
39810
- payload: {
39811
- inputPatch: materializedInputs,
39812
- },
39813
- });
39814
- if (!result.changed) {
39815
- return page;
40175
+ if (!loader) {
40176
+ return undefined;
39816
40177
  }
39817
- this.applyPageUpdate(result.page, true, undefined, true, true);
39818
- return result.page;
40178
+ return this.cloneStateValues(loader.materializedInputSnapshot(inputNames));
39819
40179
  }
39820
40180
  findWidgetLoader(key) {
39821
40181
  return this.widgetLoaders?.find((loader) => loader.ownerWidgetKey === key);
@@ -39982,7 +40342,7 @@ class DynamicWidgetPageComponent {
39982
40342
  return (endpoint.kind === 'component-port' && endpoint.ref.widget === widgetKey);
39983
40343
  }
39984
40344
  openPageSettings() {
39985
- if (!this.canOpenPageSettings())
40345
+ if (!this.canInvokePageSettings())
39986
40346
  return;
39987
40347
  if (!this.settingsPanel)
39988
40348
  return;
@@ -40008,6 +40368,10 @@ class DynamicWidgetPageComponent {
40008
40368
  ref.applied$.subscribe((result) => this.applyPageLayout(result, false));
40009
40369
  ref.saved$.subscribe((result) => this.applyPageLayout(result, true));
40010
40370
  }
40371
+ canInvokePageSettings() {
40372
+ return this.isAuthoringCapabilityEnabled('pageSettings')
40373
+ && !!(this.pageEditorComponent || this.defaultPageEditor);
40374
+ }
40011
40375
  applyWidgetShell(key, result, persist) {
40012
40376
  if (!result)
40013
40377
  return;
@@ -43370,7 +43734,7 @@ class PraxisRelatedResourceOutletComponent {
43370
43734
  </div>
43371
43735
  }
43372
43736
  </section>
43373
- `, isInline: true, styles: [":host{display:block;min-width:0}.pdx-related-outlet{display:block;min-width:0;color:var(--md-sys-color-on-surface, currentColor)}.pdx-related-outlet__state{display:grid;grid-template-columns:auto minmax(0,1fr) auto;align-items:center;gap:var(--pdx-related-outlet-gap, 12px);min-height:var(--pdx-related-outlet-min-height, 64px);padding:var(--pdx-related-outlet-padding, 12px);border:1px solid var(--md-sys-color-outline-variant, rgba(0, 0, 0, .16));border-radius:var(--pdx-related-outlet-radius, 8px);background:var(--md-sys-color-surface-container-low, var(--md-sys-color-surface, transparent))}.pdx-related-outlet--compact .pdx-related-outlet__state{min-height:var(--pdx-related-outlet-compact-min-height, 48px);padding:var(--pdx-related-outlet-compact-padding, 8px 10px)}.pdx-related-outlet__state--ready{border-color:var(--md-sys-color-primary, currentColor)}.pdx-related-outlet__icon{display:inline-grid;place-items:center;width:32px;height:32px;color:var(--md-sys-color-primary, currentColor)}.pdx-related-outlet__state--busy .pdx-related-outlet__icon{color:var(--md-sys-color-secondary, currentColor)}.pdx-related-outlet__copy{display:grid;gap:2px;min-width:0}.pdx-related-outlet__copy h3,.pdx-related-outlet__copy p{margin:0}.pdx-related-outlet__copy h3{font:var(--md-sys-typescale-title-small, 600 .95rem/1.25rem system-ui);color:var(--md-sys-color-on-surface, currentColor)}.pdx-related-outlet__copy p{font:var(--md-sys-typescale-body-small, 400 .82rem/1.15rem system-ui);color:var(--md-sys-color-on-surface-variant, currentColor)}@media(max-width:600px){.pdx-related-outlet__state{grid-template-columns:auto minmax(0,1fr)}.pdx-related-outlet__state button{grid-column:1 / -1;justify-self:start}}\n"], dependencies: [{ kind: "directive", type: DynamicWidgetLoaderDirective, selector: "[dynamicWidgetLoader]", inputs: ["dynamicWidgetLoader", "ownerWidgetKey", "context", "strictValidation", "autoWireOutputs"], outputs: ["widgetEvent", "widgetDiagnostic"], exportAs: ["dynamicWidgetLoader"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatProgressSpinnerModule }, { kind: "component", type: i3$1.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }] });
43737
+ `, isInline: true, styles: [":host{display:block;min-width:0}.pdx-related-outlet{display:block;min-width:0;color:var(--md-sys-color-on-surface, currentColor)}.pdx-related-outlet__state{display:grid;grid-template-columns:auto minmax(0,1fr) auto;align-items:center;gap:var(--pdx-related-outlet-gap, 12px);min-height:var(--pdx-related-outlet-min-height, 64px);padding:var(--pdx-related-outlet-padding, 12px);border:1px solid var(--md-sys-color-outline-variant, rgba(0, 0, 0, .16));border-radius:var(--pdx-related-outlet-radius, 8px);background:var(--md-sys-color-surface-container-low, var(--md-sys-color-surface, transparent))}.pdx-related-outlet--compact .pdx-related-outlet__state{min-height:var(--pdx-related-outlet-compact-min-height, 48px);padding:var(--pdx-related-outlet-compact-padding, 8px 10px)}.pdx-related-outlet__state--ready{border-color:var(--md-sys-color-primary, currentColor)}.pdx-related-outlet__icon{display:inline-grid;place-items:center;width:32px;height:32px;color:var(--md-sys-color-primary, currentColor)}.pdx-related-outlet__state--busy .pdx-related-outlet__icon{color:var(--md-sys-color-secondary, currentColor)}.pdx-related-outlet__copy{display:grid;gap:2px;min-width:0}.pdx-related-outlet__copy h3,.pdx-related-outlet__copy p{margin:0}.pdx-related-outlet__copy h3{font:var(--md-sys-typescale-title-small, 600 .95rem/1.25rem system-ui);color:var(--md-sys-color-on-surface, currentColor)}.pdx-related-outlet__copy p{font:var(--md-sys-typescale-body-small, 400 .82rem/1.15rem system-ui);color:var(--md-sys-color-on-surface-variant, currentColor)}@media(max-width:600px){.pdx-related-outlet__state{grid-template-columns:auto minmax(0,1fr)}.pdx-related-outlet__state button{grid-column:1 / -1;justify-self:start}}\n"], dependencies: [{ kind: "directive", type: DynamicWidgetLoaderDirective, selector: "[dynamicWidgetLoader]", inputs: ["dynamicWidgetLoader", "ownerWidgetKey", "context", "strictValidation", "autoWireOutputs"], outputs: ["widgetEvent", "widgetDiagnostic"], exportAs: ["dynamicWidgetLoader"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatProgressSpinnerModule }, { kind: "component", type: i3.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }] });
43374
43738
  }
43375
43739
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: PraxisRelatedResourceOutletComponent, decorators: [{
43376
43740
  type: Component,
@@ -43424,424 +43788,46 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
43424
43788
  `, styles: [":host{display:block;min-width:0}.pdx-related-outlet{display:block;min-width:0;color:var(--md-sys-color-on-surface, currentColor)}.pdx-related-outlet__state{display:grid;grid-template-columns:auto minmax(0,1fr) auto;align-items:center;gap:var(--pdx-related-outlet-gap, 12px);min-height:var(--pdx-related-outlet-min-height, 64px);padding:var(--pdx-related-outlet-padding, 12px);border:1px solid var(--md-sys-color-outline-variant, rgba(0, 0, 0, .16));border-radius:var(--pdx-related-outlet-radius, 8px);background:var(--md-sys-color-surface-container-low, var(--md-sys-color-surface, transparent))}.pdx-related-outlet--compact .pdx-related-outlet__state{min-height:var(--pdx-related-outlet-compact-min-height, 48px);padding:var(--pdx-related-outlet-compact-padding, 8px 10px)}.pdx-related-outlet__state--ready{border-color:var(--md-sys-color-primary, currentColor)}.pdx-related-outlet__icon{display:inline-grid;place-items:center;width:32px;height:32px;color:var(--md-sys-color-primary, currentColor)}.pdx-related-outlet__state--busy .pdx-related-outlet__icon{color:var(--md-sys-color-secondary, currentColor)}.pdx-related-outlet__copy{display:grid;gap:2px;min-width:0}.pdx-related-outlet__copy h3,.pdx-related-outlet__copy p{margin:0}.pdx-related-outlet__copy h3{font:var(--md-sys-typescale-title-small, 600 .95rem/1.25rem system-ui);color:var(--md-sys-color-on-surface, currentColor)}.pdx-related-outlet__copy p{font:var(--md-sys-typescale-body-small, 400 .82rem/1.15rem system-ui);color:var(--md-sys-color-on-surface-variant, currentColor)}@media(max-width:600px){.pdx-related-outlet__state{grid-template-columns:auto minmax(0,1fr)}.pdx-related-outlet__state button{grid-column:1 / -1;justify-self:start}}\n"] }]
43425
43789
  }], ctorParameters: () => [], propDecorators: { surface: [{ type: i0.Input, args: [{ isSignal: true, alias: "surface", required: false }] }], surfaceId: [{ type: i0.Input, args: [{ isSignal: true, alias: "surfaceId", required: false }] }], surfaceCatalog: [{ type: i0.Input, args: [{ isSignal: true, alias: "surfaceCatalog", required: false }] }], discoverySource: [{ type: i0.Input, args: [{ isSignal: true, alias: "discoverySource", required: false }] }], parentLinks: [{ type: i0.Input, args: [{ isSignal: true, alias: "parentLinks", required: false }] }], apiEndpointKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "apiEndpointKey", required: false }] }], apiUrlEntry: [{ type: i0.Input, args: [{ isSignal: true, alias: "apiUrlEntry", required: false }] }], parentRecord: [{ type: i0.Input, args: [{ isSignal: true, alias: "parentRecord", required: false }] }], parentResourceId: [{ type: i0.Input, args: [{ isSignal: true, alias: "parentResourceId", required: false }] }], parentIdentity: [{ type: i0.Input, args: [{ isSignal: true, alias: "parentIdentity", required: false }] }], parentResourcePath: [{ type: i0.Input, args: [{ isSignal: true, alias: "parentResourcePath", required: false }] }], presentation: [{ type: i0.Input, args: [{ isSignal: true, alias: "presentation", required: false }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], subtitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "subtitle", required: false }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], tableId: [{ type: i0.Input, args: [{ isSignal: true, alias: "tableId", required: false }] }], tableConfig: [{ type: i0.Input, args: [{ isSignal: true, alias: "tableConfig", required: false }] }], enableCustomization: [{ type: i0.Input, args: [{ isSignal: true, alias: "enableCustomization", required: false }] }], authoringCapability: [{ type: i0.Input, args: [{ isSignal: true, alias: "authoringCapability", required: false }] }], emptyState: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyState", required: false }] }], queryContext: [{ type: i0.Input, args: [{ isSignal: true, alias: "queryContext", required: false }] }], mode: [{ type: i0.Input, args: [{ isSignal: true, alias: "mode", required: false }] }], state: [{ type: i0.Input, args: [{ isSignal: true, alias: "state", required: false }] }], stateReason: [{ type: i0.Input, args: [{ isSignal: true, alias: "stateReason", required: false }] }], compact: [{ type: i0.Input, args: [{ isSignal: true, alias: "compact", required: false }] }], strictValidation: [{ type: i0.Input, args: [{ isSignal: true, alias: "strictValidation", required: false }] }], ownerWidgetKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "ownerWidgetKey", required: false }] }], surfaceOpen: [{ type: i0.Output, args: ["surfaceOpen"] }], widgetEvent: [{ type: i0.Output, args: ["widgetEvent"] }], resourceEvent: [{ type: i0.Output, args: ["resourceEvent"] }] } });
43426
43790
 
43427
- const PRAXIS_RELATED_RESOURCE_OUTLET_PORTS = [
43428
- {
43429
- id: 'parentResourceId',
43430
- label: 'Identificador do recurso pai',
43431
- direction: 'input',
43432
- semanticKind: 'value',
43433
- schema: {
43434
- id: 'string | number | null',
43435
- kind: 'ts-type',
43436
- ref: 'string | number | null',
43437
- },
43438
- description: 'Seleção canônica que governa a resolução da coleção filha.',
43439
- exposure: { public: true, group: 'context' },
43440
- },
43441
- {
43442
- id: 'parentIdentity',
43443
- label: 'Identidade visual do recurso pai',
43444
- direction: 'input',
43445
- semanticKind: 'view-context',
43446
- schema: {
43447
- id: 'MaterializedResourceIdentity | null',
43448
- kind: 'ts-type',
43449
- ref: 'MaterializedResourceIdentity | null',
43450
- },
43451
- description: 'Identidade somente leitura do taskScope, sem transportar o registro pai.',
43452
- exposure: { public: true, group: 'context' },
43453
- },
43454
- {
43455
- id: 'queryContext',
43456
- label: 'Contexto de consulta',
43457
- direction: 'input',
43458
- semanticKind: 'query-context',
43459
- schema: {
43460
- id: 'RelatedResourceQueryContext',
43461
- kind: 'ts-type',
43462
- ref: 'RelatedResourceQueryContext',
43463
- },
43464
- description: 'Contexto adicional mesclado ao filtro pai-filho publicado pela surface.',
43465
- exposure: { public: true, advanced: true, group: 'context' },
43466
- },
43467
- {
43468
- id: 'surfaceOpen',
43469
- label: 'Abertura da superfície relacionada',
43470
- direction: 'output',
43471
- semanticKind: 'event',
43472
- schema: {
43473
- id: 'SurfaceOpenPayload',
43474
- kind: 'ts-type',
43475
- ref: 'SurfaceOpenPayload',
43476
- },
43477
- cardinality: 'stream',
43478
- description: 'Solicita ao host a abertura mediada da superfície no modo open-action.',
43479
- exposure: { public: true, group: 'events' },
43480
- },
43481
- {
43482
- id: 'widgetEvent',
43483
- label: 'Evento do widget relacionado',
43484
- direction: 'output',
43485
- semanticKind: 'event',
43486
- schema: {
43487
- id: 'WidgetEventEnvelope',
43488
- kind: 'ts-type',
43489
- ref: 'WidgetEventEnvelope',
43490
- },
43491
- cardinality: 'stream',
43492
- description: 'Reemite eventos do widget filho com identidade de ownership.',
43493
- exposure: { public: true, advanced: true, group: 'events' },
43494
- },
43495
- {
43496
- id: 'resourceEvent',
43497
- label: 'Evento canônico do recurso relacionado',
43498
- direction: 'output',
43499
- semanticKind: 'event',
43500
- schema: {
43501
- id: 'PraxisResourceEvent',
43502
- kind: 'ts-type',
43503
- ref: 'PraxisResourceEvent',
43504
- },
43505
- cardinality: 'stream',
43506
- description: 'Promove seleção, mutação e lifecycle do recurso filho para a composição.',
43507
- exposure: { public: true, group: 'events' },
43508
- },
43791
+ const DEFAULT_ICONS = [
43792
+ 'search', 'close', 'check', 'add', 'remove', 'delete', 'edit', 'save', 'cancel', 'warning', 'error', 'info', 'help',
43793
+ 'face', 'person', 'account_circle', 'people', 'group', 'settings', 'home', 'menu', 'more_horiz', 'more_vert', 'refresh', 'arrow_back', 'arrow_forward', 'expand_more', 'expand_less', 'open_in_full', 'fullscreen', 'open_in_new',
43794
+ 'star', 'star_half', 'star_border', 'favorite', 'favorite_border', 'thumb_up', 'thumb_down', 'share', 'send', 'ios_share', 'download', 'upload', 'file_upload', 'file_download',
43795
+ 'shopping_cart', 'shopping_bag', 'store', 'storefront', 'local_mall', 'local_offer', 'attach_money', 'money', 'payments', 'price_change', 'receipt', 'receipt_long', 'request_quote', 'point_of_sale', 'credit_card', 'payment',
43796
+ 'event', 'date_range', 'schedule', 'alarm', 'watch_later', 'pending_actions',
43797
+ 'location_on', 'location_city', 'map', 'public', 'language', 'place', 'pin_drop', 'route', 'near_me', 'navigation', 'layers', 'terrain',
43798
+ 'email', 'call', 'phone', 'chat', 'forum', 'mark_email_unread', 'mark_chat_unread',
43799
+ 'wifi', 'bluetooth', 'cloud', 'cloud_upload', 'cloud_download', 'cloud_done', 'cloud_queue', 'cloud_sync', 'backup', 'bolt', 'lock', 'lock_open', 'visibility', 'visibility_off', 'vpn_key', 'key', 'fingerprint', 'shield', 'security', 'admin_panel_settings', 'privacy_tip', 'policy', 'verified',
43800
+ 'label', 'bookmark', 'book', 'description', 'article', 'note', 'assignment', 'assignment_turned_in', 'assignment_ind', 'grading', 'subject',
43801
+ 'home_max', 'home_work', 'dashboard', 'analytics', 'assessment', 'insert_chart', 'bar_chart', 'show_chart', 'timeline', 'insights', 'pie_chart', 'donut_large', 'donut_small',
43802
+ 'inventory', 'inventory_2', 'list', 'reorder', 'filter_list', 'sort', 'tune', 'settings_applications', 'build', 'build_circle', 'construction', 'bug_report', 'code', 'terminal', 'data_object', 'dataset', 'storage',
43803
+ 'rule', 'rule_folder', 'folder', 'folder_open', 'create_new_folder', 'drive_file_move', 'drive_file_rename_outline',
43804
+ 'text_fields', 'title', 'format_bold', 'format_italic', 'format_underlined', 'format_list_bulleted', 'format_list_numbered', 'insert_link', 'link', 'attach_file', 'attachment',
43805
+ 'image', 'photo', 'photo_camera', 'collections', 'slideshow', 'movie', 'videocam', 'play_arrow', 'pause', 'stop', 'fast_forward', 'fast_rewind', 'skip_next', 'skip_previous', 'volume_up', 'volume_off', 'equalizer', 'music_note', 'library_music',
43806
+ 'notifications', 'notifications_active', 'notifications_off', 'do_not_disturb',
43807
+ 'airplanemode_active', 'train', 'directions_car', 'directions_bus', 'directions_bike', 'directions_walk', 'directions_boat', 'local_taxi',
43509
43808
  ];
43510
- const PRAXIS_RELATED_RESOURCE_OUTLET_COMPONENT_METADATA = {
43511
- id: 'praxis-related-resource-outlet',
43512
- selector: 'praxis-related-resource-outlet',
43513
- component: PraxisRelatedResourceOutletComponent,
43514
- friendlyName: 'Related Resource Outlet',
43515
- description: 'Runtime genérico para materializar surface.relatedResource como tabela filha governada por metadata.',
43516
- icon: 'hub',
43517
- inputs: [
43518
- { name: 'surfaceId', type: 'string | null', description: 'Identidade declarativa da surface quando o outlet deve descobri-la no catálogo do recurso.' },
43519
- { name: 'surfaceCatalog', type: 'ResourceSurfaceCatalogResponse | null', description: 'Catálogo de surfaces já carregado pelo host; evita nova consulta quando disponível.' },
43520
- { name: 'discoverySource', type: 'ResourceLinkSource | null', description: 'Resposta HATEOAS ou mapa de links usado para seguir rel surfaces quando surface não foi fornecida.' },
43521
- { name: 'parentLinks', type: 'RestApiLinks | RestApiResponse<unknown> | null', description: 'Atalho para links do registro pai; tem o mesmo papel de discoverySource para rel surfaces.' },
43522
- { name: 'apiEndpointKey', type: 'ApiEndpoint | null', description: 'Endpoint Praxis usado pelo ResourceDiscoveryService ao resolver links ou fallback do catálogo.' },
43523
- { name: 'apiUrlEntry', type: 'ApiUrlEntry | null', description: 'Entrada de API já resolvida para hosts destacados ou integrações remotas.' },
43524
- { name: 'surface', type: 'ResourceSurfaceCatalogItem | null', description: 'Surface de catálogo que pode publicar relatedResource.' },
43525
- { name: 'parentRecord', type: 'Record<string, unknown> | null', description: 'Registro pai usado para resolver parentIdPathVariable.' },
43526
- { name: 'parentResourceId', type: 'string | number | null', description: 'Identificador explícito do registro pai quando não vem do record.' },
43527
- { name: 'parentIdentity', type: 'MaterializedResourceIdentity | null', description: 'Identidade visual somente leitura do recurso pai para continuidade de contexto.' },
43528
- { name: 'parentResourcePath', type: 'string | null', description: 'ResourcePath do recurso pai para contexto da surface.' },
43529
- { name: 'presentation', type: 'SurfacePresentation', description: 'Apresentação usada no payload de abertura host-mediated.', default: 'drawer' },
43530
- { name: 'title', type: 'string | null', description: 'Título opcional que substitui o título publicado pela surface.' },
43531
- { name: 'subtitle', type: 'string | null', description: 'Subtítulo opcional que substitui a descrição publicada pela surface.' },
43532
- { name: 'icon', type: 'string | null', description: 'Ícone opcional da superfície relacionada.' },
43533
- { name: 'queryContext', type: 'RelatedResourceQueryContext | null', description: 'QueryContext base mesclado com o filtro canônico da relação filha.' },
43534
- { name: 'tableId', type: 'string | null', description: 'Identidade estável da tabela filha para persistência, observabilidade e testes.' },
43535
- { name: 'tableConfig', type: 'Record<string, unknown> | null', description: 'Configuração parcial mesclada ao preset canônico. Ações CRUD com ids create, edit e delete aceitam somente overrides visuais (label, tooltip, icon, color, appearance, type, position e order); semântica, alvo, formulários, confirmação e disponibilidade permanecem governados pelo materializador.' },
43536
- { name: 'emptyState', type: 'Record<string, unknown> | null', description: 'Override opcional para behavior.emptyState da tabela filha. Quando omitido, o outlet deriva texto, icone, layout e ação create a partir de surface.relatedResource e dos metadados da surface.' },
43537
- { name: 'enableCustomization', type: 'boolean', description: 'Opt-in explicito para authoring governado da tabela filha.', default: false },
43538
- { name: 'authoringCapability', type: 'string | null', description: 'Capability publica do EnterpriseRuntimeContext exigida quando o authoring da tabela filha estiver habilitado.' },
43539
- { name: 'mode', type: "'inline' | 'open-action'", description: 'Renderiza a tabela filha inline ou emite payload para abertura host-mediated.', default: 'inline' },
43540
- { name: 'state', type: 'RelatedResourceResolutionState | null', description: 'Override de estado para hosts/outlets que estejam carregando discovery remoto.' },
43541
- { name: 'stateReason', type: 'string | null', description: 'Motivo governado associado ao override de estado.' },
43542
- { name: 'compact', type: 'boolean', description: 'Reduz densidade visual dos estados não materializados.', default: false },
43543
- { name: 'strictValidation', type: 'boolean', description: 'Validação estrita do widget materializado pelo DynamicWidgetLoader.', default: false },
43544
- { name: 'ownerWidgetKey', type: 'string', description: 'Identidade do owner usada para correlacionar eventos do widget filho.', default: 'related-resource.outlet' },
43545
- ],
43546
- outputs: [
43547
- { name: 'surfaceOpen', type: 'SurfaceOpenPayload', description: 'Emitido em modo open-action com o payload pronto de surface.open.' },
43548
- { name: 'widgetEvent', type: 'WidgetEventEnvelope', description: 'Reemite eventos do widget filho materializado.' },
43549
- { name: 'resourceEvent', type: 'PraxisResourceEvent', description: 'Promove eventos canonicos emitidos pelo widget filho materializado.' },
43550
- ],
43551
- ports: PRAXIS_RELATED_RESOURCE_OUTLET_PORTS,
43552
- tags: ['resource', 'surface', 'related-resource', 'runtime', 'metadata-driven'],
43553
- lib: '@praxisui/core',
43554
- };
43555
- function providePraxisRelatedResourceOutletMetadata() {
43556
- return {
43557
- provide: ENVIRONMENT_INITIALIZER,
43558
- multi: true,
43559
- useFactory: (registry) => () => {
43560
- registry.register(PRAXIS_RELATED_RESOURCE_OUTLET_COMPONENT_METADATA);
43561
- },
43562
- deps: [ComponentMetadataRegistry],
43563
- };
43564
- }
43565
-
43566
- class EmptyStateCardComponent {
43567
- icon = 'tab';
43568
- title = 'Sem configuração disponível';
43569
- description;
43570
- primaryAction;
43571
- secondaryActions = [];
43572
- inline = false;
43573
- tone = 'neutral';
43574
- variant = 'card';
43575
- alignment = 'start';
43576
- density = 'comfortable';
43577
- iconContainer = 'none';
43578
- effectiveVariant() {
43579
- return this.inline && this.variant === 'card' ? 'inline' : this.variant;
43580
- }
43581
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: EmptyStateCardComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
43582
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: EmptyStateCardComponent, isStandalone: true, selector: "praxis-empty-state-card", inputs: { icon: "icon", title: "title", description: "description", primaryAction: "primaryAction", secondaryActions: "secondaryActions", inline: "inline", tone: "tone", variant: "variant", alignment: "alignment", density: "density", iconContainer: "iconContainer" }, ngImport: i0, template: `
43583
- <mat-card
43584
- class="empty-card"
43585
- [class.empty-inline]="inline"
43586
- [class.tone-primary]="tone === 'primary'"
43587
- [class.tone-secondary]="tone === 'secondary'"
43588
- [class.variant-inline]="effectiveVariant() === 'inline'"
43589
- [class.variant-panel]="effectiveVariant() === 'panel'"
43590
- [class.variant-transparent]="effectiveVariant() === 'transparent'"
43591
- [class.align-center]="alignment === 'center'"
43592
- [class.density-compact]="density === 'compact'"
43593
- [class.icon-circle]="iconContainer === 'circle'"
43594
- [class.icon-soft]="iconContainer === 'soft'"
43595
- appearance="outlined"
43596
- >
43597
- <mat-card-content>
43598
- <div class="content">
43599
- @if (icon) {
43600
- <mat-icon class="icon" [fontIcon]="icon"></mat-icon>
43601
- }
43602
- <div class="texts">
43603
- <h3 class="title">{{ title }}</h3>
43604
- @if (description) {
43605
- <p class="desc">{{ description }}</p>
43606
- }
43607
- </div>
43608
- </div>
43609
- <div class="actions">
43610
- @if (primaryAction) {
43611
- <button type="button" mat-flat-button color="primary" (click)="primaryAction.action()">
43612
- @if (primaryAction.icon) {
43613
- <mat-icon [fontIcon]="primaryAction.icon"></mat-icon>
43614
- }
43615
- {{ primaryAction.label }}
43616
- </button>
43617
- }
43618
- @for (a of secondaryActions; track a) {
43619
- <button type="button" mat-stroked-button [color]="a.color" (click)="a.action()">
43620
- @if (a.icon) {
43621
- <mat-icon [fontIcon]="a.icon"></mat-icon>
43622
- }
43623
- {{ a.label }}
43624
- </button>
43625
- }
43626
- </div>
43627
- </mat-card-content>
43628
- </mat-card>
43629
- `, isInline: true, styles: [".empty-card{display:block;margin:var(--pdx-empty-state-margin, 12px);border-color:var(--pdx-empty-state-border-color, var(--md-sys-color-outline-variant));border-radius:var(--pdx-empty-state-radius, 8px);background:var(--pdx-empty-state-bg, var(--md-sys-color-surface));color:var(--pdx-empty-state-fg, var(--md-sys-color-on-surface));--empty-icon-color: var(--pdx-empty-state-icon-color, var(--md-sys-color-on-surface-variant))}.empty-card.empty-inline,.empty-card.variant-inline{margin:var(--pdx-empty-state-inline-margin, 8px 0)}.empty-card.variant-panel{margin:var(--pdx-empty-state-panel-margin, 0)}.empty-card.variant-transparent{margin:var(--pdx-empty-state-transparent-margin, 0);border-color:transparent;background:transparent;box-shadow:none}.content{display:flex;align-items:center;gap:var(--pdx-empty-state-gap, 12px)}.align-center .content{flex-direction:column;justify-content:center;text-align:center}.icon{display:inline-grid;place-items:center;flex:0 0 auto;font-size:var(--pdx-empty-state-icon-size, 32px);width:var(--pdx-empty-state-icon-box-size, 32px);height:var(--pdx-empty-state-icon-box-size, 32px);color:var(--empty-icon-color)}.icon-circle .icon,.icon-soft .icon{width:var(--pdx-empty-state-icon-container-size, 44px);height:var(--pdx-empty-state-icon-container-size, 44px);border-radius:var(--pdx-empty-state-icon-container-radius, 999px);font-size:var(--pdx-empty-state-icon-container-icon-size, 22px)}.icon-circle .icon{border:1px solid var(--pdx-empty-state-icon-container-border-color, color-mix(in srgb, var(--empty-icon-color) 24%, transparent));background:var(--pdx-empty-state-icon-container-bg, color-mix(in srgb, var(--empty-icon-color) 10%, transparent))}.icon-soft .icon{background:var(--pdx-empty-state-icon-container-bg, color-mix(in srgb, var(--empty-icon-color) 10%, transparent))}.texts{display:grid;gap:var(--pdx-empty-state-text-gap, 4px)}.align-center .texts{justify-items:center}.title{margin:0;font-family:var(--pdx-empty-state-title-font-family, var(--md-sys-typescale-title-small-font-family, inherit));font-size:var(--pdx-empty-state-title-font-size, 16px);font-weight:var(--pdx-empty-state-title-font-weight, 600);line-height:var(--pdx-empty-state-title-line-height, 1.3);color:var(--pdx-empty-state-title-color, var(--md-sys-color-on-surface))}.desc{margin:0;max-width:var(--pdx-empty-state-description-max-width, none);font-family:var(--pdx-empty-state-description-font-family, var(--md-sys-typescale-body-medium-font-family, inherit));font-size:var(--pdx-empty-state-description-font-size, inherit);line-height:var(--pdx-empty-state-description-line-height, 1.4);color:var(--pdx-empty-state-description-color, var(--md-sys-color-on-surface-variant))}.actions{display:flex;justify-content:var(--pdx-empty-state-actions-justify, flex-start);gap:var(--pdx-empty-state-actions-gap, 8px);margin-top:var(--pdx-empty-state-actions-margin-top, 12px);flex-wrap:wrap}.actions .mat-mdc-button-base{width:fit-content;max-width:100%;height:var(--pdx-empty-state-action-height, var(--praxis-action-control-height, 40px));min-height:var(--pdx-empty-state-action-height, var(--praxis-action-control-height, 40px));padding-inline:var(--pdx-empty-state-action-padding-inline, var(--praxis-action-control-padding-inline, 12px));border-radius:var(--pdx-empty-state-action-radius, var(--praxis-action-control-radius, 8px));gap:var(--pdx-empty-state-action-gap, var(--praxis-action-control-gap, 8px));font-size:var(--pdx-empty-state-action-font-size, var(--praxis-action-control-font-size, .875rem));font-weight:var(--pdx-empty-state-action-font-weight, var(--praxis-action-control-font-weight, 500));line-height:var(--pdx-empty-state-action-line-height, var(--praxis-action-control-line-height, 1.25rem));white-space:nowrap}.actions .mat-mdc-button-base mat-icon{width:var(--pdx-empty-state-action-icon-size, var(--praxis-action-control-icon-size, 18px));height:var(--pdx-empty-state-action-icon-size, var(--praxis-action-control-icon-size, 18px));margin:0;font-size:var(--pdx-empty-state-action-icon-size, var(--praxis-action-control-icon-size, 18px));line-height:var(--pdx-empty-state-action-icon-size, var(--praxis-action-control-icon-size, 18px))}.actions .mat-mdc-button-base:focus-visible{outline:2px solid var(--pdx-empty-state-action-focus-ring, var(--praxis-action-control-focus-ring, var(--md-sys-color-primary)));outline-offset:2px}.actions .mat-mdc-button-base:disabled{opacity:var(--pdx-empty-state-action-disabled-opacity, var(--praxis-action-control-disabled-opacity, .62))}.align-center .actions{justify-content:var(--pdx-empty-state-actions-justify, center)}.density-compact .content{gap:var(--pdx-empty-state-compact-gap, 8px)}.density-compact .actions .mat-mdc-button-base{height:var(--pdx-empty-state-action-height, var(--praxis-action-control-compact-height, 36px));min-height:var(--pdx-empty-state-action-height, var(--praxis-action-control-compact-height, 36px))}.density-compact .icon{font-size:var(--pdx-empty-state-compact-icon-size, 24px);width:var(--pdx-empty-state-compact-icon-box-size, 24px);height:var(--pdx-empty-state-compact-icon-box-size, 24px)}.density-compact.icon-circle .icon,.density-compact.icon-soft .icon{width:var(--pdx-empty-state-compact-icon-container-size, 36px);height:var(--pdx-empty-state-compact-icon-container-size, 36px);font-size:var(--pdx-empty-state-compact-icon-container-icon-size, 20px)}.empty-card.tone-primary{--empty-icon-color: var(--md-sys-color-primary)}.empty-card.tone-secondary{--empty-icon-color: var(--md-sys-color-secondary)}\n"], dependencies: [{ kind: "ngmodule", type: MatCardModule }, { kind: "component", type: i2$1.MatCard, selector: "mat-card", inputs: ["appearance"], exportAs: ["matCard"] }, { kind: "directive", type: i2$1.MatCardContent, selector: "mat-card-content" }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }] });
43630
- }
43631
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: EmptyStateCardComponent, decorators: [{
43632
- type: Component,
43633
- args: [{ selector: 'praxis-empty-state-card', standalone: true, imports: [MatCardModule, MatButtonModule, MatIconModule], template: `
43634
- <mat-card
43635
- class="empty-card"
43636
- [class.empty-inline]="inline"
43637
- [class.tone-primary]="tone === 'primary'"
43638
- [class.tone-secondary]="tone === 'secondary'"
43639
- [class.variant-inline]="effectiveVariant() === 'inline'"
43640
- [class.variant-panel]="effectiveVariant() === 'panel'"
43641
- [class.variant-transparent]="effectiveVariant() === 'transparent'"
43642
- [class.align-center]="alignment === 'center'"
43643
- [class.density-compact]="density === 'compact'"
43644
- [class.icon-circle]="iconContainer === 'circle'"
43645
- [class.icon-soft]="iconContainer === 'soft'"
43646
- appearance="outlined"
43647
- >
43648
- <mat-card-content>
43649
- <div class="content">
43650
- @if (icon) {
43651
- <mat-icon class="icon" [fontIcon]="icon"></mat-icon>
43652
- }
43653
- <div class="texts">
43654
- <h3 class="title">{{ title }}</h3>
43655
- @if (description) {
43656
- <p class="desc">{{ description }}</p>
43657
- }
43658
- </div>
43659
- </div>
43660
- <div class="actions">
43661
- @if (primaryAction) {
43662
- <button type="button" mat-flat-button color="primary" (click)="primaryAction.action()">
43663
- @if (primaryAction.icon) {
43664
- <mat-icon [fontIcon]="primaryAction.icon"></mat-icon>
43665
- }
43666
- {{ primaryAction.label }}
43667
- </button>
43668
- }
43669
- @for (a of secondaryActions; track a) {
43670
- <button type="button" mat-stroked-button [color]="a.color" (click)="a.action()">
43671
- @if (a.icon) {
43672
- <mat-icon [fontIcon]="a.icon"></mat-icon>
43673
- }
43674
- {{ a.label }}
43675
- </button>
43676
- }
43677
- </div>
43678
- </mat-card-content>
43679
- </mat-card>
43680
- `, styles: [".empty-card{display:block;margin:var(--pdx-empty-state-margin, 12px);border-color:var(--pdx-empty-state-border-color, var(--md-sys-color-outline-variant));border-radius:var(--pdx-empty-state-radius, 8px);background:var(--pdx-empty-state-bg, var(--md-sys-color-surface));color:var(--pdx-empty-state-fg, var(--md-sys-color-on-surface));--empty-icon-color: var(--pdx-empty-state-icon-color, var(--md-sys-color-on-surface-variant))}.empty-card.empty-inline,.empty-card.variant-inline{margin:var(--pdx-empty-state-inline-margin, 8px 0)}.empty-card.variant-panel{margin:var(--pdx-empty-state-panel-margin, 0)}.empty-card.variant-transparent{margin:var(--pdx-empty-state-transparent-margin, 0);border-color:transparent;background:transparent;box-shadow:none}.content{display:flex;align-items:center;gap:var(--pdx-empty-state-gap, 12px)}.align-center .content{flex-direction:column;justify-content:center;text-align:center}.icon{display:inline-grid;place-items:center;flex:0 0 auto;font-size:var(--pdx-empty-state-icon-size, 32px);width:var(--pdx-empty-state-icon-box-size, 32px);height:var(--pdx-empty-state-icon-box-size, 32px);color:var(--empty-icon-color)}.icon-circle .icon,.icon-soft .icon{width:var(--pdx-empty-state-icon-container-size, 44px);height:var(--pdx-empty-state-icon-container-size, 44px);border-radius:var(--pdx-empty-state-icon-container-radius, 999px);font-size:var(--pdx-empty-state-icon-container-icon-size, 22px)}.icon-circle .icon{border:1px solid var(--pdx-empty-state-icon-container-border-color, color-mix(in srgb, var(--empty-icon-color) 24%, transparent));background:var(--pdx-empty-state-icon-container-bg, color-mix(in srgb, var(--empty-icon-color) 10%, transparent))}.icon-soft .icon{background:var(--pdx-empty-state-icon-container-bg, color-mix(in srgb, var(--empty-icon-color) 10%, transparent))}.texts{display:grid;gap:var(--pdx-empty-state-text-gap, 4px)}.align-center .texts{justify-items:center}.title{margin:0;font-family:var(--pdx-empty-state-title-font-family, var(--md-sys-typescale-title-small-font-family, inherit));font-size:var(--pdx-empty-state-title-font-size, 16px);font-weight:var(--pdx-empty-state-title-font-weight, 600);line-height:var(--pdx-empty-state-title-line-height, 1.3);color:var(--pdx-empty-state-title-color, var(--md-sys-color-on-surface))}.desc{margin:0;max-width:var(--pdx-empty-state-description-max-width, none);font-family:var(--pdx-empty-state-description-font-family, var(--md-sys-typescale-body-medium-font-family, inherit));font-size:var(--pdx-empty-state-description-font-size, inherit);line-height:var(--pdx-empty-state-description-line-height, 1.4);color:var(--pdx-empty-state-description-color, var(--md-sys-color-on-surface-variant))}.actions{display:flex;justify-content:var(--pdx-empty-state-actions-justify, flex-start);gap:var(--pdx-empty-state-actions-gap, 8px);margin-top:var(--pdx-empty-state-actions-margin-top, 12px);flex-wrap:wrap}.actions .mat-mdc-button-base{width:fit-content;max-width:100%;height:var(--pdx-empty-state-action-height, var(--praxis-action-control-height, 40px));min-height:var(--pdx-empty-state-action-height, var(--praxis-action-control-height, 40px));padding-inline:var(--pdx-empty-state-action-padding-inline, var(--praxis-action-control-padding-inline, 12px));border-radius:var(--pdx-empty-state-action-radius, var(--praxis-action-control-radius, 8px));gap:var(--pdx-empty-state-action-gap, var(--praxis-action-control-gap, 8px));font-size:var(--pdx-empty-state-action-font-size, var(--praxis-action-control-font-size, .875rem));font-weight:var(--pdx-empty-state-action-font-weight, var(--praxis-action-control-font-weight, 500));line-height:var(--pdx-empty-state-action-line-height, var(--praxis-action-control-line-height, 1.25rem));white-space:nowrap}.actions .mat-mdc-button-base mat-icon{width:var(--pdx-empty-state-action-icon-size, var(--praxis-action-control-icon-size, 18px));height:var(--pdx-empty-state-action-icon-size, var(--praxis-action-control-icon-size, 18px));margin:0;font-size:var(--pdx-empty-state-action-icon-size, var(--praxis-action-control-icon-size, 18px));line-height:var(--pdx-empty-state-action-icon-size, var(--praxis-action-control-icon-size, 18px))}.actions .mat-mdc-button-base:focus-visible{outline:2px solid var(--pdx-empty-state-action-focus-ring, var(--praxis-action-control-focus-ring, var(--md-sys-color-primary)));outline-offset:2px}.actions .mat-mdc-button-base:disabled{opacity:var(--pdx-empty-state-action-disabled-opacity, var(--praxis-action-control-disabled-opacity, .62))}.align-center .actions{justify-content:var(--pdx-empty-state-actions-justify, center)}.density-compact .content{gap:var(--pdx-empty-state-compact-gap, 8px)}.density-compact .actions .mat-mdc-button-base{height:var(--pdx-empty-state-action-height, var(--praxis-action-control-compact-height, 36px));min-height:var(--pdx-empty-state-action-height, var(--praxis-action-control-compact-height, 36px))}.density-compact .icon{font-size:var(--pdx-empty-state-compact-icon-size, 24px);width:var(--pdx-empty-state-compact-icon-box-size, 24px);height:var(--pdx-empty-state-compact-icon-box-size, 24px)}.density-compact.icon-circle .icon,.density-compact.icon-soft .icon{width:var(--pdx-empty-state-compact-icon-container-size, 36px);height:var(--pdx-empty-state-compact-icon-container-size, 36px);font-size:var(--pdx-empty-state-compact-icon-container-icon-size, 20px)}.empty-card.tone-primary{--empty-icon-color: var(--md-sys-color-primary)}.empty-card.tone-secondary{--empty-icon-color: var(--md-sys-color-secondary)}\n"] }]
43681
- }], propDecorators: { icon: [{
43682
- type: Input
43683
- }], title: [{
43684
- type: Input
43685
- }], description: [{
43686
- type: Input
43687
- }], primaryAction: [{
43688
- type: Input
43689
- }], secondaryActions: [{
43690
- type: Input
43691
- }], inline: [{
43692
- type: Input
43693
- }], tone: [{
43694
- type: Input
43695
- }], variant: [{
43696
- type: Input
43697
- }], alignment: [{
43698
- type: Input
43699
- }], density: [{
43700
- type: Input
43701
- }], iconContainer: [{
43702
- type: Input
43703
- }] } });
43704
-
43705
- class ResourceQuickConnectComponent {
43706
- resourcePath = '';
43707
- isDirty$ = new BehaviorSubject(false);
43708
- isValid$ = new BehaviorSubject(false);
43709
- isBusy$ = new BehaviorSubject(false);
43710
- // Values are provided via Inputs by the opener; no DI data coupling required.
43711
- // When used standalone, consumers can bind [(resourcePath)].
43712
- ngOnInit() {
43713
- this.updateValidity();
43714
- }
43715
- ngOnChanges() {
43716
- this.updateValidity();
43717
- }
43718
- updateState() {
43719
- this.isDirty$.next(true);
43720
- this.updateValidity();
43721
- }
43722
- updateValidity() {
43723
- const trimmed = this.resourcePath?.trim() || '';
43724
- this.isValid$.next(!!trimmed && this.isValidPath(trimmed));
43725
- }
43726
- getSettingsValue() {
43727
- return { resourcePath: this.normalizedPath() };
43728
- }
43729
- onSave() {
43730
- return this.getSettingsValue();
43731
- }
43732
- showInvalid() {
43733
- const trimmed = this.resourcePath?.trim() || '';
43734
- return !!trimmed && !this.isValidPath(trimmed);
43735
- }
43736
- normalizedPath() {
43737
- const trimmed = this.resourcePath?.trim() || '';
43738
- if (!trimmed)
43739
- return '';
43740
- if (trimmed.startsWith('/'))
43741
- return trimmed;
43742
- if (trimmed.startsWith('http://') || trimmed.startsWith('https://'))
43743
- return trimmed;
43744
- return `/${trimmed}`;
43745
- }
43746
- isValidPath(value) {
43747
- if (value.startsWith('http://') || value.startsWith('https://'))
43748
- return true;
43749
- return /^\/?[a-zA-Z0-9][a-zA-Z0-9/_-]*$/.test(value);
43750
- }
43751
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: ResourceQuickConnectComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
43752
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: ResourceQuickConnectComponent, isStandalone: true, selector: "praxis-resource-quick-connect", inputs: { resourcePath: "resourcePath" }, usesOnChanges: true, ngImport: i0, template: `
43753
- <div class="pdx-quick-connect">
43754
- <mat-form-field appearance="outline">
43755
- <mat-label>Rota do recurso (API)</mat-label>
43756
- <input
43757
- matInput
43758
- [(ngModel)]="resourcePath"
43759
- (ngModelChange)="updateState()"
43760
- placeholder="ex.: human-resources/departamentos"
43761
- />
43762
- <mat-icon matSuffix [praxisIcon]="'link'"></mat-icon>
43763
- @if (showInvalid()) {
43764
- <mat-error>Use apenas letras, números, /, - ou _.</mat-error>
43765
- }
43766
- </mat-form-field>
43767
- <small class="pdx-quick-connect__hint">Conecte o componente à fonte de dados (ex.: /api/&lt;rota-do-recurso&gt;)</small>
43768
- @if (normalizedPath() && normalizedPath() !== resourcePath) {
43769
- <small class="pdx-quick-connect__hint">
43770
- Rota normalizada: {{ normalizedPath() }}
43771
- </small>
43772
- }
43773
- </div>
43774
- `, isInline: true, styles: [".pdx-quick-connect{display:grid;gap:12px;padding:12px;border-radius:12px;border:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface);color:var(--md-sys-color-on-surface)}.pdx-quick-connect__hint{color:var(--md-sys-color-on-surface-variant);font-size:.9rem}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i3.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i3.MatLabel, selector: "mat-label" }, { kind: "directive", type: i3.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "directive", type: i3.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i5.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }] });
43775
- }
43776
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: ResourceQuickConnectComponent, decorators: [{
43777
- type: Component,
43778
- args: [{ selector: 'praxis-resource-quick-connect', standalone: true, imports: [FormsModule, MatFormFieldModule, MatInputModule, MatIconModule, PraxisIconDirective], template: `
43779
- <div class="pdx-quick-connect">
43780
- <mat-form-field appearance="outline">
43781
- <mat-label>Rota do recurso (API)</mat-label>
43782
- <input
43783
- matInput
43784
- [(ngModel)]="resourcePath"
43785
- (ngModelChange)="updateState()"
43786
- placeholder="ex.: human-resources/departamentos"
43787
- />
43788
- <mat-icon matSuffix [praxisIcon]="'link'"></mat-icon>
43789
- @if (showInvalid()) {
43790
- <mat-error>Use apenas letras, números, /, - ou _.</mat-error>
43791
- }
43792
- </mat-form-field>
43793
- <small class="pdx-quick-connect__hint">Conecte o componente à fonte de dados (ex.: /api/&lt;rota-do-recurso&gt;)</small>
43794
- @if (normalizedPath() && normalizedPath() !== resourcePath) {
43795
- <small class="pdx-quick-connect__hint">
43796
- Rota normalizada: {{ normalizedPath() }}
43797
- </small>
43798
- }
43799
- </div>
43800
- `, styles: [".pdx-quick-connect{display:grid;gap:12px;padding:12px;border-radius:12px;border:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface);color:var(--md-sys-color-on-surface)}.pdx-quick-connect__hint{color:var(--md-sys-color-on-surface-variant);font-size:.9rem}\n"] }]
43801
- }], propDecorators: { resourcePath: [{
43802
- type: Input
43803
- }] } });
43804
-
43805
- const DEFAULT_ICONS = [
43806
- 'search', 'close', 'check', 'add', 'remove', 'delete', 'edit', 'save', 'cancel', 'warning', 'error', 'info', 'help',
43807
- 'face', 'person', 'account_circle', 'people', 'group', 'settings', 'home', 'menu', 'more_horiz', 'more_vert', 'refresh', 'arrow_back', 'arrow_forward', 'expand_more', 'expand_less', 'open_in_full', 'fullscreen', 'open_in_new',
43808
- 'star', 'star_half', 'star_border', 'favorite', 'favorite_border', 'thumb_up', 'thumb_down', 'share', 'send', 'ios_share', 'download', 'upload', 'file_upload', 'file_download',
43809
- 'shopping_cart', 'shopping_bag', 'store', 'storefront', 'local_mall', 'local_offer', 'attach_money', 'money', 'payments', 'price_change', 'receipt', 'receipt_long', 'request_quote', 'point_of_sale', 'credit_card', 'payment',
43810
- 'event', 'date_range', 'schedule', 'alarm', 'watch_later', 'pending_actions',
43811
- 'location_on', 'location_city', 'map', 'public', 'language', 'place', 'pin_drop', 'route', 'near_me', 'navigation', 'layers', 'terrain',
43812
- 'email', 'call', 'phone', 'chat', 'forum', 'mark_email_unread', 'mark_chat_unread',
43813
- 'wifi', 'bluetooth', 'cloud', 'cloud_upload', 'cloud_download', 'cloud_done', 'cloud_queue', 'cloud_sync', 'backup', 'bolt', 'lock', 'lock_open', 'visibility', 'visibility_off', 'vpn_key', 'key', 'fingerprint', 'shield', 'security', 'admin_panel_settings', 'privacy_tip', 'policy', 'verified',
43814
- 'label', 'bookmark', 'book', 'description', 'article', 'note', 'assignment', 'assignment_turned_in', 'assignment_ind', 'grading', 'subject',
43815
- 'home_max', 'home_work', 'dashboard', 'analytics', 'assessment', 'insert_chart', 'bar_chart', 'show_chart', 'timeline', 'insights', 'pie_chart', 'donut_large', 'donut_small',
43816
- 'inventory', 'inventory_2', 'list', 'reorder', 'filter_list', 'sort', 'tune', 'settings_applications', 'build', 'build_circle', 'construction', 'bug_report', 'code', 'terminal', 'data_object', 'dataset', 'storage',
43817
- 'rule', 'rule_folder', 'folder', 'folder_open', 'create_new_folder', 'drive_file_move', 'drive_file_rename_outline',
43818
- 'text_fields', 'title', 'format_bold', 'format_italic', 'format_underlined', 'format_list_bulleted', 'format_list_numbered', 'insert_link', 'link', 'attach_file', 'attachment',
43819
- 'image', 'photo', 'photo_camera', 'collections', 'slideshow', 'movie', 'videocam', 'play_arrow', 'pause', 'stop', 'fast_forward', 'fast_rewind', 'skip_next', 'skip_previous', 'volume_up', 'volume_off', 'equalizer', 'music_note', 'library_music',
43820
- 'notifications', 'notifications_active', 'notifications_off', 'do_not_disturb',
43821
- 'airplanemode_active', 'train', 'directions_car', 'directions_bus', 'directions_bike', 'directions_walk', 'directions_boat', 'local_taxi',
43822
- ];
43823
- class PraxisIconPickerComponent {
43824
- data;
43825
- dialogRef;
43826
- value;
43827
- icons = DEFAULT_ICONS;
43828
- selected = new EventEmitter();
43829
- cancel = new EventEmitter();
43830
- searchInput;
43831
- query = '';
43832
- filtered = [];
43833
- selectedFamily = 'mi';
43834
- constructor(data, dialogRef) {
43835
- this.data = data;
43836
- this.dialogRef = dialogRef;
43837
- if (data) {
43838
- this.value = data.value;
43839
- if (Array.isArray(data.icons) && data.icons.length)
43840
- this.icons = data.icons;
43841
- const fam = this.familyFromValue(this.value);
43842
- if (fam) {
43843
- this.selectedFamily = fam.family;
43844
- this.value = fam.name;
43809
+ class PraxisIconPickerComponent {
43810
+ data;
43811
+ dialogRef;
43812
+ value;
43813
+ icons = DEFAULT_ICONS;
43814
+ selected = new EventEmitter();
43815
+ cancel = new EventEmitter();
43816
+ searchInput;
43817
+ query = '';
43818
+ filtered = [];
43819
+ selectedFamily = 'mi';
43820
+ constructor(data, dialogRef) {
43821
+ this.data = data;
43822
+ this.dialogRef = dialogRef;
43823
+ if (data) {
43824
+ this.value = data.value;
43825
+ if (Array.isArray(data.icons) && data.icons.length)
43826
+ this.icons = data.icons;
43827
+ const fam = this.familyFromValue(this.value);
43828
+ if (fam) {
43829
+ this.selectedFamily = fam.family;
43830
+ this.value = fam.name;
43845
43831
  }
43846
43832
  }
43847
43833
  this.query = (this.value || '').trim();
@@ -44011,7 +43997,7 @@ class PraxisIconPickerComponent {
44011
43997
  }
44012
43998
  </div>
44013
43999
  </div>
44014
- `, isInline: true, styles: [".pip-root{display:flex;flex-direction:column;min-width:340px;max-width:760px;max-height:80vh;overflow:hidden;padding:16px;color:var(--md-sys-color-on-surface)}.pip-head{display:flex;gap:12px;align-items:center;margin-bottom:12px;flex-wrap:wrap}.pip-search{flex:1;min-width:180px}.pip-spacer{flex:1}.pip-body{flex:1;overflow:auto;display:grid;grid-template-columns:repeat(auto-fill,minmax(120px,1fr));gap:10px;padding:4px}.pip-item{display:flex;gap:10px;align-items:center;justify-content:flex-start;padding:10px;border:1px solid var(--md-sys-color-outline-variant);border-radius:10px;background:var(--md-sys-color-surface);color:inherit;cursor:pointer;transition:background-color .18s ease,border-color .18s ease,box-shadow .18s ease}.pip-item:hover{background:var(--md-sys-color-surface-container)}.pip-item:focus-visible{outline:2px solid var(--md-sys-color-primary);outline-offset:2px}.pip-item.selected{border-color:var(--md-sys-color-primary);box-shadow:0 0 0 2px var(--md-sys-color-primary)}.pip-name{font-size:12px;color:var(--md-sys-color-on-surface-variant);white-space:nowrap;text-overflow:ellipsis;overflow:hidden}.pip-hint{font-size:12px;color:var(--md-sys-color-on-surface-variant);margin:-6px 0 8px}.pip-stats{display:flex;justify-content:space-between;gap:8px;font-size:12px;color:var(--md-sys-color-on-surface-variant);margin-bottom:8px}.pip-shortcut{opacity:.9}.pip-empty{padding:12px;border:1px dashed var(--md-sys-color-outline-variant);border-radius:10px;color:var(--md-sys-color-on-surface-variant);background:var(--md-sys-color-surface-container);margin-top:8px}.pip-footer{display:flex;gap:12px;align-items:center;margin-top:10px}.pip-typed{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:12px;color:var(--md-sys-color-on-surface)}.pip-family{display:flex;align-items:center}.pip-family .mat-mdc-chip-listbox{min-width:260px}.pip-root .mat-icon{font-family:Material Icons,Material Symbols Outlined,Material Symbols Rounded,Material Symbols Sharp!important;font-variation-settings:\"FILL\" 0,\"wght\" 400,\"GRAD\" 0,\"opsz\" 24;color:currentColor}.material-symbols-outlined{font-family:Material Symbols Outlined;font-weight:400;font-style:normal;font-size:24px;line-height:1;letter-spacing:normal;text-transform:none;display:inline-block;white-space:nowrap;word-wrap:normal;direction:ltr;-webkit-font-feature-settings:\"liga\";-webkit-font-smoothing:antialiased;font-variation-settings:\"FILL\" 0,\"wght\" 400,\"GRAD\" 0,\"opsz\" 24}.material-symbols-rounded{font-family:Material Symbols Rounded;font-weight:400;font-style:normal;font-size:24px;line-height:1;letter-spacing:normal;text-transform:none;display:inline-block;white-space:nowrap;word-wrap:normal;direction:ltr;-webkit-font-feature-settings:\"liga\";-webkit-font-smoothing:antialiased;font-variation-settings:\"FILL\" 0,\"wght\" 400,\"GRAD\" 0,\"opsz\" 24}.material-symbols-sharp{font-family:Material Symbols Sharp;font-weight:400;font-style:normal;font-size:24px;line-height:1;letter-spacing:normal;text-transform:none;display:inline-block;white-space:nowrap;word-wrap:normal;direction:ltr;-webkit-font-feature-settings:\"liga\";-webkit-font-smoothing:antialiased;font-variation-settings:\"FILL\" 0,\"wght\" 400,\"GRAD\" 0,\"opsz\" 24}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$3.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i3.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i3.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i5.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatChipsModule }, { kind: "component", type: i8$1.MatChipListbox, selector: "mat-chip-listbox", inputs: ["multiple", "aria-orientation", "selectable", "compareWith", "required", "hideSingleSelectionIndicator", "value"], outputs: ["change"] }, { kind: "component", type: i8$1.MatChipOption, selector: "mat-basic-chip-option, [mat-basic-chip-option], mat-chip-option, [mat-chip-option]", inputs: ["selectable", "selected"], outputs: ["selectionChange"] }, { kind: "ngmodule", type: MatDialogModule }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i8.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }] });
44000
+ `, isInline: true, styles: [".pip-root{display:flex;flex-direction:column;min-width:340px;max-width:760px;max-height:80vh;overflow:hidden;padding:16px;color:var(--md-sys-color-on-surface)}.pip-head{display:flex;gap:12px;align-items:center;margin-bottom:12px;flex-wrap:wrap}.pip-search{flex:1;min-width:180px}.pip-spacer{flex:1}.pip-body{flex:1;overflow:auto;display:grid;grid-template-columns:repeat(auto-fill,minmax(120px,1fr));gap:10px;padding:4px}.pip-item{display:flex;gap:10px;align-items:center;justify-content:flex-start;padding:10px;border:1px solid var(--md-sys-color-outline-variant);border-radius:10px;background:var(--md-sys-color-surface);color:inherit;cursor:pointer;transition:background-color .18s ease,border-color .18s ease,box-shadow .18s ease}.pip-item:hover{background:var(--md-sys-color-surface-container)}.pip-item:focus-visible{outline:2px solid var(--md-sys-color-primary);outline-offset:2px}.pip-item.selected{border-color:var(--md-sys-color-primary);box-shadow:0 0 0 2px var(--md-sys-color-primary)}.pip-name{font-size:12px;color:var(--md-sys-color-on-surface-variant);white-space:nowrap;text-overflow:ellipsis;overflow:hidden}.pip-hint{font-size:12px;color:var(--md-sys-color-on-surface-variant);margin:-6px 0 8px}.pip-stats{display:flex;justify-content:space-between;gap:8px;font-size:12px;color:var(--md-sys-color-on-surface-variant);margin-bottom:8px}.pip-shortcut{opacity:.9}.pip-empty{padding:12px;border:1px dashed var(--md-sys-color-outline-variant);border-radius:10px;color:var(--md-sys-color-on-surface-variant);background:var(--md-sys-color-surface-container);margin-top:8px}.pip-footer{display:flex;gap:12px;align-items:center;margin-top:10px}.pip-typed{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:12px;color:var(--md-sys-color-on-surface)}.pip-family{display:flex;align-items:center}.pip-family .mat-mdc-chip-listbox{min-width:260px}.pip-root .mat-icon{font-family:Material Icons,Material Symbols Outlined,Material Symbols Rounded,Material Symbols Sharp!important;font-variation-settings:\"FILL\" 0,\"wght\" 400,\"GRAD\" 0,\"opsz\" 24;color:currentColor}.material-symbols-outlined{font-family:Material Symbols Outlined;font-weight:400;font-style:normal;font-size:24px;line-height:1;letter-spacing:normal;text-transform:none;display:inline-block;white-space:nowrap;word-wrap:normal;direction:ltr;-webkit-font-feature-settings:\"liga\";-webkit-font-smoothing:antialiased;font-variation-settings:\"FILL\" 0,\"wght\" 400,\"GRAD\" 0,\"opsz\" 24}.material-symbols-rounded{font-family:Material Symbols Rounded;font-weight:400;font-style:normal;font-size:24px;line-height:1;letter-spacing:normal;text-transform:none;display:inline-block;white-space:nowrap;word-wrap:normal;direction:ltr;-webkit-font-feature-settings:\"liga\";-webkit-font-smoothing:antialiased;font-variation-settings:\"FILL\" 0,\"wght\" 400,\"GRAD\" 0,\"opsz\" 24}.material-symbols-sharp{font-family:Material Symbols Sharp;font-weight:400;font-style:normal;font-size:24px;line-height:1;letter-spacing:normal;text-transform:none;display:inline-block;white-space:nowrap;word-wrap:normal;direction:ltr;-webkit-font-feature-settings:\"liga\";-webkit-font-smoothing:antialiased;font-variation-settings:\"FILL\" 0,\"wght\" 400,\"GRAD\" 0,\"opsz\" 24}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$3.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i4.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i4.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i5.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatChipsModule }, { kind: "component", type: i8$1.MatChipListbox, selector: "mat-chip-listbox", inputs: ["multiple", "aria-orientation", "selectable", "compareWith", "required", "hideSingleSelectionIndicator", "value"], outputs: ["change"] }, { kind: "component", type: i8$1.MatChipOption, selector: "mat-basic-chip-option, [mat-basic-chip-option], mat-chip-option, [mat-chip-option]", inputs: ["selectable", "selected"], outputs: ["selectionChange"] }, { kind: "ngmodule", type: MatDialogModule }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i8.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }] });
44015
44001
  }
44016
44002
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: PraxisIconPickerComponent, decorators: [{
44017
44003
  type: Component,
@@ -44145,6 +44131,1480 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
44145
44131
  args: [{ providedIn: 'root' }]
44146
44132
  }] });
44147
44133
 
44134
+ const EMPTY_FORM_VALUE = {
44135
+ title: '',
44136
+ subtitle: '',
44137
+ icon: '',
44138
+ mode: 'inline',
44139
+ presentation: 'drawer',
44140
+ compact: false,
44141
+ emptyState: {
44142
+ title: '',
44143
+ message: '',
44144
+ description: '',
44145
+ icon: '',
44146
+ tone: '',
44147
+ variant: '',
44148
+ alignment: '',
44149
+ density: '',
44150
+ iconContainer: '',
44151
+ },
44152
+ };
44153
+ const EMPTY_STATE_TEXT_FIELDS = ['title', 'message', 'description', 'icon'];
44154
+ const EMPTY_STATE_ENUM_FIELDS = [
44155
+ 'tone',
44156
+ 'variant',
44157
+ 'alignment',
44158
+ 'density',
44159
+ 'iconContainer',
44160
+ ];
44161
+ class PraxisRelatedResourceOutletConfigEditorComponent {
44162
+ inputs = input(null, ...(ngDevMode ? [{ debugName: "inputs" }] : /* istanbul ignore next */ []));
44163
+ widgetKey = input(undefined, ...(ngDevMode ? [{ debugName: "widgetKey" }] : /* istanbul ignore next */ []));
44164
+ widgetType = input(undefined, ...(ngDevMode ? [{ debugName: "widgetType" }] : /* istanbul ignore next */ []));
44165
+ form = new FormGroup({
44166
+ title: new FormControl('', { nonNullable: true }),
44167
+ subtitle: new FormControl('', { nonNullable: true }),
44168
+ icon: new FormControl('', { nonNullable: true }),
44169
+ mode: new FormControl('inline', { nonNullable: true }),
44170
+ presentation: new FormControl('drawer', { nonNullable: true }),
44171
+ compact: new FormControl(false, { nonNullable: true }),
44172
+ emptyState: new FormGroup({
44173
+ title: new FormControl('', { nonNullable: true }),
44174
+ message: new FormControl('', { nonNullable: true }),
44175
+ description: new FormControl('', { nonNullable: true }),
44176
+ icon: new FormControl('', { nonNullable: true }),
44177
+ tone: new FormControl('', { nonNullable: true }),
44178
+ variant: new FormControl('', { nonNullable: true }),
44179
+ alignment: new FormControl('', { nonNullable: true }),
44180
+ density: new FormControl('', { nonNullable: true }),
44181
+ iconContainer: new FormControl('', { nonNullable: true }),
44182
+ }),
44183
+ });
44184
+ isDirty$ = new BehaviorSubject(false);
44185
+ isValid$ = new BehaviorSubject(true);
44186
+ isBusy$ = new BehaviorSubject(false);
44187
+ i18n = inject(PraxisI18nService);
44188
+ iconPicker = inject(IconPickerService);
44189
+ persistedInputs = {};
44190
+ baselineFormValue = structuredClone(EMPTY_FORM_VALUE);
44191
+ constructor() {
44192
+ this.form.valueChanges
44193
+ .pipe(takeUntilDestroyed())
44194
+ .subscribe(() => this.publishState());
44195
+ effect(() => {
44196
+ this.initialize(this.inputs());
44197
+ });
44198
+ }
44199
+ getSettingsValue() {
44200
+ return { inputs: this.buildInputs() };
44201
+ }
44202
+ onSave() {
44203
+ return this.getSettingsValue();
44204
+ }
44205
+ reset() {
44206
+ this.form.reset(structuredClone(this.baselineFormValue), { emitEvent: false });
44207
+ this.publishState();
44208
+ }
44209
+ async selectIcon(target) {
44210
+ const control = target === 'outlet'
44211
+ ? this.form.controls.icon
44212
+ : this.form.controls.emptyState.controls.icon;
44213
+ const selected = await this.iconPicker.openDialog({ value: control.value });
44214
+ if (selected !== undefined) {
44215
+ control.setValue(selected);
44216
+ }
44217
+ }
44218
+ t(key, fallback) {
44219
+ return this.i18n.t(key, undefined, fallback, RELATED_RESOURCE_OUTLET_I18N_NAMESPACE);
44220
+ }
44221
+ initialize(inputs) {
44222
+ this.persistedInputs = structuredClone(inputs ?? {});
44223
+ this.baselineFormValue = this.readFormValue(this.persistedInputs);
44224
+ this.form.reset(structuredClone(this.baselineFormValue), { emitEvent: false });
44225
+ this.publishState();
44226
+ }
44227
+ readFormValue(inputs) {
44228
+ const emptyState = this.objectValue(inputs['emptyState']);
44229
+ return {
44230
+ title: this.stringValue(inputs['title']),
44231
+ subtitle: this.stringValue(inputs['subtitle']),
44232
+ icon: this.stringValue(inputs['icon']),
44233
+ mode: inputs['mode'] === 'open-action' ? 'open-action' : 'inline',
44234
+ presentation: inputs['presentation'] === 'modal' ? 'modal' : 'drawer',
44235
+ compact: inputs['compact'] === true,
44236
+ emptyState: {
44237
+ title: this.stringValue(emptyState['title']),
44238
+ message: this.stringValue(emptyState['message']),
44239
+ description: this.stringValue(emptyState['description']),
44240
+ icon: this.stringValue(emptyState['icon']),
44241
+ tone: this.enumValue(emptyState['tone'], ['neutral', 'primary', 'secondary']),
44242
+ variant: this.enumValue(emptyState['variant'], ['card', 'inline', 'panel', 'transparent']),
44243
+ alignment: this.enumValue(emptyState['alignment'], ['start', 'center']),
44244
+ density: this.enumValue(emptyState['density'], ['compact', 'comfortable']),
44245
+ iconContainer: this.enumValue(emptyState['iconContainer'], ['none', 'circle', 'soft']),
44246
+ },
44247
+ };
44248
+ }
44249
+ buildInputs() {
44250
+ const next = structuredClone(this.persistedInputs);
44251
+ const current = this.form.getRawValue();
44252
+ this.applyTextChange(next, 'title', current.title, this.baselineFormValue.title);
44253
+ this.applyTextChange(next, 'subtitle', current.subtitle, this.baselineFormValue.subtitle);
44254
+ this.applyTextChange(next, 'icon', current.icon, this.baselineFormValue.icon);
44255
+ this.applyDefaultedChange(next, 'mode', current.mode, this.baselineFormValue.mode, 'inline');
44256
+ this.applyDefaultedChange(next, 'presentation', current.presentation, this.baselineFormValue.presentation, 'drawer');
44257
+ this.applyDefaultedChange(next, 'compact', current.compact, this.baselineFormValue.compact, false);
44258
+ this.applyEmptyStateChanges(next, current.emptyState);
44259
+ return next;
44260
+ }
44261
+ applyEmptyStateChanges(inputs, current) {
44262
+ const baseline = this.baselineFormValue.emptyState;
44263
+ const changed = EMPTY_STATE_TEXT_FIELDS.some((field) => current[field] !== baseline[field])
44264
+ || EMPTY_STATE_ENUM_FIELDS.some((field) => current[field] !== baseline[field]);
44265
+ if (!changed) {
44266
+ return;
44267
+ }
44268
+ const existing = this.objectValue(inputs['emptyState']);
44269
+ const next = structuredClone(existing);
44270
+ for (const field of EMPTY_STATE_TEXT_FIELDS) {
44271
+ this.applyTextChange(next, field, current[field], baseline[field]);
44272
+ }
44273
+ for (const field of EMPTY_STATE_ENUM_FIELDS) {
44274
+ if (current[field] === baseline[field]) {
44275
+ continue;
44276
+ }
44277
+ if (current[field]) {
44278
+ next[field] = current[field];
44279
+ }
44280
+ else {
44281
+ delete next[field];
44282
+ }
44283
+ }
44284
+ if (Object.keys(next).length > 0) {
44285
+ inputs['emptyState'] = next;
44286
+ }
44287
+ else {
44288
+ delete inputs['emptyState'];
44289
+ }
44290
+ }
44291
+ applyTextChange(target, field, current, baseline) {
44292
+ if (current === baseline) {
44293
+ return;
44294
+ }
44295
+ const value = current.trim();
44296
+ if (value) {
44297
+ target[field] = value;
44298
+ }
44299
+ else {
44300
+ delete target[field];
44301
+ }
44302
+ }
44303
+ applyDefaultedChange(target, field, current, baseline, defaultValue) {
44304
+ if (current === baseline) {
44305
+ return;
44306
+ }
44307
+ if (current === defaultValue && !Object.prototype.hasOwnProperty.call(this.persistedInputs, field)) {
44308
+ delete target[field];
44309
+ return;
44310
+ }
44311
+ target[field] = current;
44312
+ }
44313
+ publishState() {
44314
+ this.isDirty$.next(JSON.stringify(this.form.getRawValue()) !== JSON.stringify(this.baselineFormValue));
44315
+ this.isValid$.next(this.form.valid);
44316
+ }
44317
+ objectValue(value) {
44318
+ return value && typeof value === 'object' && !Array.isArray(value)
44319
+ ? value
44320
+ : {};
44321
+ }
44322
+ stringValue(value) {
44323
+ return typeof value === 'string' ? value : '';
44324
+ }
44325
+ enumValue(value, allowed) {
44326
+ return typeof value === 'string' && allowed.includes(value) ? value : '';
44327
+ }
44328
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: PraxisRelatedResourceOutletConfigEditorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
44329
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.14", type: PraxisRelatedResourceOutletConfigEditorComponent, isStandalone: true, selector: "praxis-related-resource-outlet-config-editor", inputs: { inputs: { classPropertyName: "inputs", publicName: "inputs", isSignal: true, isRequired: false, transformFunction: null }, widgetKey: { classPropertyName: "widgetKey", publicName: "widgetKey", isSignal: true, isRequired: false, transformFunction: null }, widgetType: { classPropertyName: "widgetType", publicName: "widgetType", isSignal: true, isRequired: false, transformFunction: null } }, providers: [providePraxisI18nConfig(RELATED_RESOURCE_OUTLET_I18N_CONFIG)], ngImport: i0, template: `
44330
+ <form
44331
+ class="pdx-related-outlet-editor"
44332
+ [formGroup]="form"
44333
+ data-testid="related-resource-outlet-config-editor"
44334
+ >
44335
+ <header class="pdx-related-outlet-editor__header">
44336
+ <span class="pdx-related-outlet-editor__header-icon" aria-hidden="true">
44337
+ <mat-icon fontIcon="account_tree" />
44338
+ </span>
44339
+ <span>
44340
+ <strong>{{ t('editor.title', 'Related resource presentation') }}</strong>
44341
+ <small>
44342
+ {{
44343
+ t(
44344
+ 'editor.description',
44345
+ 'Configure only the visual shell. The relationship and its data remain governed by metadata.'
44346
+ )
44347
+ }}
44348
+ </small>
44349
+ </span>
44350
+ </header>
44351
+
44352
+ <section class="pdx-related-outlet-editor__section" aria-labelledby="related-outlet-shell-title">
44353
+ <div class="pdx-related-outlet-editor__section-heading">
44354
+ <h3 id="related-outlet-shell-title">{{ t('editor.shell.title', 'Presentation') }}</h3>
44355
+ <p>{{ t('editor.shell.help', 'Copy and display choices for this outlet instance.') }}</p>
44356
+ </div>
44357
+
44358
+ <div class="pdx-related-outlet-editor__fields">
44359
+ <mat-form-field appearance="outline">
44360
+ <mat-label>{{ t('editor.field.title', 'Title') }}</mat-label>
44361
+ <input matInput formControlName="title" />
44362
+ </mat-form-field>
44363
+
44364
+ <mat-form-field appearance="outline">
44365
+ <mat-label>{{ t('editor.field.icon', 'Icon') }}</mat-label>
44366
+ <input matInput formControlName="icon" />
44367
+ <button
44368
+ mat-icon-button
44369
+ matSuffix
44370
+ type="button"
44371
+ (click)="selectIcon('outlet')"
44372
+ [attr.aria-label]="t('editor.field.icon.choose', 'Choose outlet icon')"
44373
+ >
44374
+ <mat-icon fontIcon="apps" />
44375
+ </button>
44376
+ </mat-form-field>
44377
+
44378
+ <mat-form-field appearance="outline" class="pdx-related-outlet-editor__wide">
44379
+ <mat-label>{{ t('editor.field.subtitle', 'Subtitle') }}</mat-label>
44380
+ <textarea matInput formControlName="subtitle" rows="2"></textarea>
44381
+ </mat-form-field>
44382
+ </div>
44383
+
44384
+ <div class="pdx-related-outlet-editor__choice-grid">
44385
+ <fieldset>
44386
+ <legend>{{ t('editor.field.mode', 'Display mode') }}</legend>
44387
+ <mat-button-toggle-group
44388
+ formControlName="mode"
44389
+ hideSingleSelectionIndicator
44390
+ [attr.aria-label]="t('editor.field.mode', 'Display mode')"
44391
+ >
44392
+ <mat-button-toggle value="inline">
44393
+ <mat-icon fontIcon="table_rows" aria-hidden="true" />
44394
+ {{ t('editor.field.mode.inline', 'Inline') }}
44395
+ </mat-button-toggle>
44396
+ <mat-button-toggle value="open-action">
44397
+ <mat-icon fontIcon="open_in_new" aria-hidden="true" />
44398
+ {{ t('editor.field.mode.openAction', 'Open action') }}
44399
+ </mat-button-toggle>
44400
+ </mat-button-toggle-group>
44401
+ </fieldset>
44402
+
44403
+ <fieldset>
44404
+ <legend>{{ t('editor.field.presentation', 'Open presentation') }}</legend>
44405
+ <mat-button-toggle-group
44406
+ formControlName="presentation"
44407
+ hideSingleSelectionIndicator
44408
+ [attr.aria-label]="t('editor.field.presentation', 'Open presentation')"
44409
+ >
44410
+ <mat-button-toggle value="drawer">
44411
+ <mat-icon fontIcon="view_sidebar" aria-hidden="true" />
44412
+ {{ t('editor.field.presentation.drawer', 'Drawer') }}
44413
+ </mat-button-toggle>
44414
+ <mat-button-toggle value="modal">
44415
+ <mat-icon fontIcon="web_asset" aria-hidden="true" />
44416
+ {{ t('editor.field.presentation.modal', 'Modal') }}
44417
+ </mat-button-toggle>
44418
+ </mat-button-toggle-group>
44419
+ </fieldset>
44420
+ </div>
44421
+
44422
+ </section>
44423
+
44424
+ <section
44425
+ class="pdx-related-outlet-editor__section"
44426
+ formGroupName="emptyState"
44427
+ aria-labelledby="related-outlet-empty-state-title"
44428
+ >
44429
+ <div class="pdx-related-outlet-editor__section-heading">
44430
+ <h3 id="related-outlet-empty-state-title">{{ t('editor.emptyState.title', 'Empty state') }}</h3>
44431
+ <p>
44432
+ {{
44433
+ t(
44434
+ 'editor.emptyState.help',
44435
+ 'Override presentation only. Actions, templates and contextual behavior remain untouched.'
44436
+ )
44437
+ }}
44438
+ </p>
44439
+ </div>
44440
+
44441
+ <div class="pdx-related-outlet-editor__fields">
44442
+ <mat-form-field appearance="outline">
44443
+ <mat-label>{{ t('editor.emptyState.field.title', 'Title') }}</mat-label>
44444
+ <input matInput formControlName="title" />
44445
+ </mat-form-field>
44446
+
44447
+ <mat-form-field appearance="outline">
44448
+ <mat-label>{{ t('editor.emptyState.field.icon', 'Icon') }}</mat-label>
44449
+ <input matInput formControlName="icon" />
44450
+ <button
44451
+ mat-icon-button
44452
+ matSuffix
44453
+ type="button"
44454
+ (click)="selectIcon('emptyState')"
44455
+ [attr.aria-label]="t('editor.emptyState.field.icon.choose', 'Choose empty-state icon')"
44456
+ >
44457
+ <mat-icon fontIcon="apps" />
44458
+ </button>
44459
+ </mat-form-field>
44460
+
44461
+ <mat-form-field appearance="outline" class="pdx-related-outlet-editor__wide">
44462
+ <mat-label>{{ t('editor.emptyState.field.message', 'Message') }}</mat-label>
44463
+ <input matInput formControlName="message" />
44464
+ </mat-form-field>
44465
+
44466
+ <mat-form-field appearance="outline" class="pdx-related-outlet-editor__wide">
44467
+ <mat-label>{{ t('editor.emptyState.field.description', 'Description') }}</mat-label>
44468
+ <textarea matInput formControlName="description" rows="2"></textarea>
44469
+ </mat-form-field>
44470
+
44471
+ </div>
44472
+
44473
+ <div class="pdx-related-outlet-editor__appearance-grid">
44474
+ <fieldset class="pdx-related-outlet-editor__appearance-cluster">
44475
+ <legend>{{ t('editor.emptyState.field.tone', 'Tone') }}</legend>
44476
+ <mat-button-toggle-group
44477
+ formControlName="tone"
44478
+ hideSingleSelectionIndicator
44479
+ [attr.aria-label]="t('editor.emptyState.field.tone', 'Tone')"
44480
+ >
44481
+ <mat-button-toggle value="">
44482
+ <mat-icon fontIcon="auto_awesome" aria-hidden="true" />
44483
+ {{ t('editor.value.derived.short', 'Auto') }}
44484
+ </mat-button-toggle>
44485
+ <mat-button-toggle value="neutral">
44486
+ <mat-icon fontIcon="contrast" aria-hidden="true" />
44487
+ {{ t('editor.value.tone.neutral', 'Neutral') }}
44488
+ </mat-button-toggle>
44489
+ <mat-button-toggle value="primary">
44490
+ <mat-icon fontIcon="stars" aria-hidden="true" />
44491
+ {{ t('editor.value.tone.primary', 'Primary') }}
44492
+ </mat-button-toggle>
44493
+ <mat-button-toggle value="secondary">
44494
+ <mat-icon fontIcon="palette" aria-hidden="true" />
44495
+ {{ t('editor.value.tone.secondary', 'Secondary') }}
44496
+ </mat-button-toggle>
44497
+ </mat-button-toggle-group>
44498
+ </fieldset>
44499
+
44500
+ <fieldset class="pdx-related-outlet-editor__appearance-cluster pdx-related-outlet-editor__appearance-cluster--wide">
44501
+ <legend>{{ t('editor.emptyState.field.variant', 'Variant') }}</legend>
44502
+ <mat-button-toggle-group
44503
+ formControlName="variant"
44504
+ hideSingleSelectionIndicator
44505
+ [attr.aria-label]="t('editor.emptyState.field.variant', 'Variant')"
44506
+ >
44507
+ <mat-button-toggle value="">
44508
+ <mat-icon fontIcon="auto_awesome" aria-hidden="true" />
44509
+ {{ t('editor.value.derived.short', 'Auto') }}
44510
+ </mat-button-toggle>
44511
+ <mat-button-toggle value="inline">
44512
+ <mat-icon fontIcon="view_stream" aria-hidden="true" />
44513
+ {{ t('editor.value.variant.inline', 'Inline') }}
44514
+ </mat-button-toggle>
44515
+ <mat-button-toggle value="card">
44516
+ <mat-icon fontIcon="crop_square" aria-hidden="true" />
44517
+ {{ t('editor.value.variant.card', 'Card') }}
44518
+ </mat-button-toggle>
44519
+ <mat-button-toggle value="panel">
44520
+ <mat-icon fontIcon="view_agenda" aria-hidden="true" />
44521
+ {{ t('editor.value.variant.panel', 'Panel') }}
44522
+ </mat-button-toggle>
44523
+ <mat-button-toggle value="transparent">
44524
+ <mat-icon fontIcon="layers_clear" aria-hidden="true" />
44525
+ {{ t('editor.value.variant.transparent', 'Transparent') }}
44526
+ </mat-button-toggle>
44527
+ </mat-button-toggle-group>
44528
+ </fieldset>
44529
+
44530
+ <fieldset class="pdx-related-outlet-editor__appearance-cluster">
44531
+ <legend>{{ t('editor.emptyState.field.alignment', 'Alignment') }}</legend>
44532
+ <mat-button-toggle-group
44533
+ formControlName="alignment"
44534
+ hideSingleSelectionIndicator
44535
+ [attr.aria-label]="t('editor.emptyState.field.alignment', 'Alignment')"
44536
+ >
44537
+ <mat-button-toggle value="">
44538
+ <mat-icon fontIcon="auto_awesome" aria-hidden="true" />
44539
+ {{ t('editor.value.derived.short', 'Auto') }}
44540
+ </mat-button-toggle>
44541
+ <mat-button-toggle value="start">
44542
+ <mat-icon fontIcon="format_align_left" aria-hidden="true" />
44543
+ {{ t('editor.value.alignment.start', 'Start') }}
44544
+ </mat-button-toggle>
44545
+ <mat-button-toggle value="center">
44546
+ <mat-icon fontIcon="format_align_center" aria-hidden="true" />
44547
+ {{ t('editor.value.alignment.center', 'Center') }}
44548
+ </mat-button-toggle>
44549
+ </mat-button-toggle-group>
44550
+ </fieldset>
44551
+
44552
+ <div class="pdx-related-outlet-editor__appearance-cluster pdx-related-outlet-editor__density-cluster">
44553
+ <fieldset>
44554
+ <legend>{{ t('editor.emptyState.field.density', 'Density') }}</legend>
44555
+ <mat-button-toggle-group
44556
+ formControlName="density"
44557
+ hideSingleSelectionIndicator
44558
+ [attr.aria-label]="t('editor.emptyState.field.density', 'Density')"
44559
+ >
44560
+ <mat-button-toggle value="">
44561
+ <mat-icon fontIcon="auto_awesome" aria-hidden="true" />
44562
+ {{ t('editor.value.derived.short', 'Auto') }}
44563
+ </mat-button-toggle>
44564
+ <mat-button-toggle value="compact">
44565
+ <mat-icon fontIcon="density_small" aria-hidden="true" />
44566
+ {{ t('editor.value.density.compact', 'Compact') }}
44567
+ </mat-button-toggle>
44568
+ <mat-button-toggle value="comfortable">
44569
+ <mat-icon fontIcon="density_medium" aria-hidden="true" />
44570
+ {{ t('editor.value.density.comfortable', 'Comfortable') }}
44571
+ </mat-button-toggle>
44572
+ </mat-button-toggle-group>
44573
+ </fieldset>
44574
+ <mat-slide-toggle [formControl]="form.controls.compact">
44575
+ {{ t('editor.field.compact', 'Use compact empty and loading states') }}
44576
+ </mat-slide-toggle>
44577
+ </div>
44578
+
44579
+ <fieldset class="pdx-related-outlet-editor__appearance-cluster">
44580
+ <legend>{{ t('editor.emptyState.field.iconContainer', 'Icon container') }}</legend>
44581
+ <mat-button-toggle-group
44582
+ formControlName="iconContainer"
44583
+ hideSingleSelectionIndicator
44584
+ [attr.aria-label]="t('editor.emptyState.field.iconContainer', 'Icon container')"
44585
+ >
44586
+ <mat-button-toggle value="">
44587
+ <mat-icon fontIcon="auto_awesome" aria-hidden="true" />
44588
+ {{ t('editor.value.derived.short', 'Auto') }}
44589
+ </mat-button-toggle>
44590
+ <mat-button-toggle value="none">
44591
+ <mat-icon fontIcon="block" aria-hidden="true" />
44592
+ {{ t('editor.value.iconContainer.none', 'None') }}
44593
+ </mat-button-toggle>
44594
+ <mat-button-toggle value="circle">
44595
+ <mat-icon fontIcon="circle" aria-hidden="true" />
44596
+ {{ t('editor.value.iconContainer.circle', 'Circle') }}
44597
+ </mat-button-toggle>
44598
+ <mat-button-toggle value="soft">
44599
+ <mat-icon fontIcon="blur_on" aria-hidden="true" />
44600
+ {{ t('editor.value.iconContainer.soft', 'Soft') }}
44601
+ </mat-button-toggle>
44602
+ </mat-button-toggle-group>
44603
+ </fieldset>
44604
+ </div>
44605
+ </section>
44606
+
44607
+ <aside class="pdx-related-outlet-editor__boundary" role="note">
44608
+ <mat-icon fontIcon="lock" aria-hidden="true" />
44609
+ <span>
44610
+ <strong>{{ t('editor.boundary.title', 'Relationship is read-only here') }}</strong>
44611
+ <small>
44612
+ {{
44613
+ t(
44614
+ 'editor.boundary.description',
44615
+ 'Resource paths, parent bindings, operations, filters and child table configuration stay with their canonical owners.'
44616
+ )
44617
+ }}
44618
+ </small>
44619
+ </span>
44620
+ </aside>
44621
+ </form>
44622
+ `, isInline: true, styles: [":host{display:block;color:var(--md-sys-color-on-surface, currentColor)}.pdx-related-outlet-editor{display:grid;gap:var(--pdx-spacing-lg, 24px);padding:var(--pdx-spacing-md, 16px)}.pdx-related-outlet-editor__header,.pdx-related-outlet-editor__boundary{display:grid;grid-template-columns:auto minmax(0,1fr);align-items:start;gap:var(--pdx-spacing-sm, 12px)}.pdx-related-outlet-editor__header-icon{display:inline-grid;place-items:center;width:40px;height:40px;border-radius:var(--md-sys-shape-corner-medium, 12px);color:var(--md-sys-color-primary, currentColor);background:var(--md-sys-color-primary-container, transparent)}.pdx-related-outlet-editor__header strong,.pdx-related-outlet-editor__boundary strong,.pdx-related-outlet-editor__header small,.pdx-related-outlet-editor__boundary small{display:block}.pdx-related-outlet-editor__header strong{font:var(--md-sys-typescale-title-medium, 600 1rem/1.4 system-ui)}.pdx-related-outlet-editor__header small,.pdx-related-outlet-editor__boundary small,.pdx-related-outlet-editor__section-heading p{color:var(--md-sys-color-on-surface-variant, currentColor)}.pdx-related-outlet-editor__section{display:grid;gap:var(--pdx-spacing-md, 16px)}.pdx-related-outlet-editor__section-heading h3,.pdx-related-outlet-editor__section-heading p{margin:0}.pdx-related-outlet-editor__section-heading h3{font:var(--md-sys-typescale-title-small, 600 .95rem/1.3 system-ui)}.pdx-related-outlet-editor__section-heading p{margin-top:4px;font:var(--md-sys-typescale-body-small, 400 .82rem/1.35 system-ui)}.pdx-related-outlet-editor__fields{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--pdx-spacing-sm, 12px)}.pdx-related-outlet-editor__wide{grid-column:1 / -1}.pdx-related-outlet-editor__choice-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--pdx-spacing-md, 16px)}.pdx-related-outlet-editor__appearance-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,280px),1fr));gap:var(--pdx-spacing-sm, 12px)}.pdx-related-outlet-editor__appearance-cluster{display:grid;align-content:start;gap:var(--pdx-spacing-sm, 12px);min-width:0}.pdx-related-outlet-editor__appearance-cluster--wide{grid-column:1 / -1}.pdx-related-outlet-editor__appearance-cluster mat-button-toggle-group{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,132px),1fr))}.pdx-related-outlet-editor__appearance-cluster mat-button-toggle{min-height:44px}.pdx-related-outlet-editor__density-cluster{gap:var(--pdx-spacing-md, 16px)}fieldset{min-width:0;margin:0;padding:0;border:0}legend{margin-bottom:8px;font:var(--md-sys-typescale-label-large, 500 .88rem/1.2 system-ui)}mat-button-toggle-group{width:100%}mat-button-toggle{flex:1 1 0}mat-button-toggle mat-icon{margin-right:6px}.pdx-related-outlet-editor__boundary{padding:var(--pdx-spacing-sm, 12px);border:1px solid var(--md-sys-color-outline-variant, currentColor);border-radius:var(--md-sys-shape-corner-medium, 12px);background:var(--md-sys-color-surface-container-low, transparent)}.pdx-related-outlet-editor__boundary mat-icon{color:var(--md-sys-color-on-surface-variant, currentColor)}@media(max-width:640px){.pdx-related-outlet-editor__fields,.pdx-related-outlet-editor__choice-grid{grid-template-columns:minmax(0,1fr)}.pdx-related-outlet-editor__wide{grid-column:auto}mat-button-toggle-group{display:grid}}@media(max-width:420px){.pdx-related-outlet-editor__appearance-cluster mat-button-toggle-group{grid-template-columns:minmax(0,1fr)}}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i1$2.FormGroupName, selector: "[formGroupName]", inputs: ["formGroupName"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatButtonToggleModule }, { kind: "directive", type: i3$1.MatButtonToggleGroup, selector: "mat-button-toggle-group", inputs: ["appearance", "name", "vertical", "value", "multiple", "disabled", "disabledInteractive", "hideSingleSelectionIndicator", "hideMultipleSelectionIndicator"], outputs: ["valueChange", "change"], exportAs: ["matButtonToggleGroup"] }, { kind: "component", type: i3$1.MatButtonToggle, selector: "mat-button-toggle", inputs: ["aria-label", "aria-labelledby", "id", "name", "value", "tabIndex", "disableRipple", "appearance", "checked", "disabled", "disabledInteractive"], outputs: ["change"], exportAs: ["matButtonToggle"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i4.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i4.MatLabel, selector: "mat-label" }, { kind: "directive", type: i4.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i5.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatSlideToggleModule }, { kind: "component", type: i7.MatSlideToggle, selector: "mat-slide-toggle", inputs: ["name", "id", "labelPosition", "aria-label", "aria-labelledby", "aria-describedby", "required", "color", "disabled", "disableRipple", "tabIndex", "checked", "hideIcon", "disabledInteractive"], outputs: ["change", "toggleChange"], exportAs: ["matSlideToggle"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
44623
+ }
44624
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: PraxisRelatedResourceOutletConfigEditorComponent, decorators: [{
44625
+ type: Component,
44626
+ args: [{ selector: 'praxis-related-resource-outlet-config-editor', imports: [
44627
+ ReactiveFormsModule,
44628
+ MatButtonModule,
44629
+ MatButtonToggleModule,
44630
+ MatFormFieldModule,
44631
+ MatIconModule,
44632
+ MatInputModule,
44633
+ MatSlideToggleModule,
44634
+ ], providers: [providePraxisI18nConfig(RELATED_RESOURCE_OUTLET_I18N_CONFIG)], changeDetection: ChangeDetectionStrategy.OnPush, template: `
44635
+ <form
44636
+ class="pdx-related-outlet-editor"
44637
+ [formGroup]="form"
44638
+ data-testid="related-resource-outlet-config-editor"
44639
+ >
44640
+ <header class="pdx-related-outlet-editor__header">
44641
+ <span class="pdx-related-outlet-editor__header-icon" aria-hidden="true">
44642
+ <mat-icon fontIcon="account_tree" />
44643
+ </span>
44644
+ <span>
44645
+ <strong>{{ t('editor.title', 'Related resource presentation') }}</strong>
44646
+ <small>
44647
+ {{
44648
+ t(
44649
+ 'editor.description',
44650
+ 'Configure only the visual shell. The relationship and its data remain governed by metadata.'
44651
+ )
44652
+ }}
44653
+ </small>
44654
+ </span>
44655
+ </header>
44656
+
44657
+ <section class="pdx-related-outlet-editor__section" aria-labelledby="related-outlet-shell-title">
44658
+ <div class="pdx-related-outlet-editor__section-heading">
44659
+ <h3 id="related-outlet-shell-title">{{ t('editor.shell.title', 'Presentation') }}</h3>
44660
+ <p>{{ t('editor.shell.help', 'Copy and display choices for this outlet instance.') }}</p>
44661
+ </div>
44662
+
44663
+ <div class="pdx-related-outlet-editor__fields">
44664
+ <mat-form-field appearance="outline">
44665
+ <mat-label>{{ t('editor.field.title', 'Title') }}</mat-label>
44666
+ <input matInput formControlName="title" />
44667
+ </mat-form-field>
44668
+
44669
+ <mat-form-field appearance="outline">
44670
+ <mat-label>{{ t('editor.field.icon', 'Icon') }}</mat-label>
44671
+ <input matInput formControlName="icon" />
44672
+ <button
44673
+ mat-icon-button
44674
+ matSuffix
44675
+ type="button"
44676
+ (click)="selectIcon('outlet')"
44677
+ [attr.aria-label]="t('editor.field.icon.choose', 'Choose outlet icon')"
44678
+ >
44679
+ <mat-icon fontIcon="apps" />
44680
+ </button>
44681
+ </mat-form-field>
44682
+
44683
+ <mat-form-field appearance="outline" class="pdx-related-outlet-editor__wide">
44684
+ <mat-label>{{ t('editor.field.subtitle', 'Subtitle') }}</mat-label>
44685
+ <textarea matInput formControlName="subtitle" rows="2"></textarea>
44686
+ </mat-form-field>
44687
+ </div>
44688
+
44689
+ <div class="pdx-related-outlet-editor__choice-grid">
44690
+ <fieldset>
44691
+ <legend>{{ t('editor.field.mode', 'Display mode') }}</legend>
44692
+ <mat-button-toggle-group
44693
+ formControlName="mode"
44694
+ hideSingleSelectionIndicator
44695
+ [attr.aria-label]="t('editor.field.mode', 'Display mode')"
44696
+ >
44697
+ <mat-button-toggle value="inline">
44698
+ <mat-icon fontIcon="table_rows" aria-hidden="true" />
44699
+ {{ t('editor.field.mode.inline', 'Inline') }}
44700
+ </mat-button-toggle>
44701
+ <mat-button-toggle value="open-action">
44702
+ <mat-icon fontIcon="open_in_new" aria-hidden="true" />
44703
+ {{ t('editor.field.mode.openAction', 'Open action') }}
44704
+ </mat-button-toggle>
44705
+ </mat-button-toggle-group>
44706
+ </fieldset>
44707
+
44708
+ <fieldset>
44709
+ <legend>{{ t('editor.field.presentation', 'Open presentation') }}</legend>
44710
+ <mat-button-toggle-group
44711
+ formControlName="presentation"
44712
+ hideSingleSelectionIndicator
44713
+ [attr.aria-label]="t('editor.field.presentation', 'Open presentation')"
44714
+ >
44715
+ <mat-button-toggle value="drawer">
44716
+ <mat-icon fontIcon="view_sidebar" aria-hidden="true" />
44717
+ {{ t('editor.field.presentation.drawer', 'Drawer') }}
44718
+ </mat-button-toggle>
44719
+ <mat-button-toggle value="modal">
44720
+ <mat-icon fontIcon="web_asset" aria-hidden="true" />
44721
+ {{ t('editor.field.presentation.modal', 'Modal') }}
44722
+ </mat-button-toggle>
44723
+ </mat-button-toggle-group>
44724
+ </fieldset>
44725
+ </div>
44726
+
44727
+ </section>
44728
+
44729
+ <section
44730
+ class="pdx-related-outlet-editor__section"
44731
+ formGroupName="emptyState"
44732
+ aria-labelledby="related-outlet-empty-state-title"
44733
+ >
44734
+ <div class="pdx-related-outlet-editor__section-heading">
44735
+ <h3 id="related-outlet-empty-state-title">{{ t('editor.emptyState.title', 'Empty state') }}</h3>
44736
+ <p>
44737
+ {{
44738
+ t(
44739
+ 'editor.emptyState.help',
44740
+ 'Override presentation only. Actions, templates and contextual behavior remain untouched.'
44741
+ )
44742
+ }}
44743
+ </p>
44744
+ </div>
44745
+
44746
+ <div class="pdx-related-outlet-editor__fields">
44747
+ <mat-form-field appearance="outline">
44748
+ <mat-label>{{ t('editor.emptyState.field.title', 'Title') }}</mat-label>
44749
+ <input matInput formControlName="title" />
44750
+ </mat-form-field>
44751
+
44752
+ <mat-form-field appearance="outline">
44753
+ <mat-label>{{ t('editor.emptyState.field.icon', 'Icon') }}</mat-label>
44754
+ <input matInput formControlName="icon" />
44755
+ <button
44756
+ mat-icon-button
44757
+ matSuffix
44758
+ type="button"
44759
+ (click)="selectIcon('emptyState')"
44760
+ [attr.aria-label]="t('editor.emptyState.field.icon.choose', 'Choose empty-state icon')"
44761
+ >
44762
+ <mat-icon fontIcon="apps" />
44763
+ </button>
44764
+ </mat-form-field>
44765
+
44766
+ <mat-form-field appearance="outline" class="pdx-related-outlet-editor__wide">
44767
+ <mat-label>{{ t('editor.emptyState.field.message', 'Message') }}</mat-label>
44768
+ <input matInput formControlName="message" />
44769
+ </mat-form-field>
44770
+
44771
+ <mat-form-field appearance="outline" class="pdx-related-outlet-editor__wide">
44772
+ <mat-label>{{ t('editor.emptyState.field.description', 'Description') }}</mat-label>
44773
+ <textarea matInput formControlName="description" rows="2"></textarea>
44774
+ </mat-form-field>
44775
+
44776
+ </div>
44777
+
44778
+ <div class="pdx-related-outlet-editor__appearance-grid">
44779
+ <fieldset class="pdx-related-outlet-editor__appearance-cluster">
44780
+ <legend>{{ t('editor.emptyState.field.tone', 'Tone') }}</legend>
44781
+ <mat-button-toggle-group
44782
+ formControlName="tone"
44783
+ hideSingleSelectionIndicator
44784
+ [attr.aria-label]="t('editor.emptyState.field.tone', 'Tone')"
44785
+ >
44786
+ <mat-button-toggle value="">
44787
+ <mat-icon fontIcon="auto_awesome" aria-hidden="true" />
44788
+ {{ t('editor.value.derived.short', 'Auto') }}
44789
+ </mat-button-toggle>
44790
+ <mat-button-toggle value="neutral">
44791
+ <mat-icon fontIcon="contrast" aria-hidden="true" />
44792
+ {{ t('editor.value.tone.neutral', 'Neutral') }}
44793
+ </mat-button-toggle>
44794
+ <mat-button-toggle value="primary">
44795
+ <mat-icon fontIcon="stars" aria-hidden="true" />
44796
+ {{ t('editor.value.tone.primary', 'Primary') }}
44797
+ </mat-button-toggle>
44798
+ <mat-button-toggle value="secondary">
44799
+ <mat-icon fontIcon="palette" aria-hidden="true" />
44800
+ {{ t('editor.value.tone.secondary', 'Secondary') }}
44801
+ </mat-button-toggle>
44802
+ </mat-button-toggle-group>
44803
+ </fieldset>
44804
+
44805
+ <fieldset class="pdx-related-outlet-editor__appearance-cluster pdx-related-outlet-editor__appearance-cluster--wide">
44806
+ <legend>{{ t('editor.emptyState.field.variant', 'Variant') }}</legend>
44807
+ <mat-button-toggle-group
44808
+ formControlName="variant"
44809
+ hideSingleSelectionIndicator
44810
+ [attr.aria-label]="t('editor.emptyState.field.variant', 'Variant')"
44811
+ >
44812
+ <mat-button-toggle value="">
44813
+ <mat-icon fontIcon="auto_awesome" aria-hidden="true" />
44814
+ {{ t('editor.value.derived.short', 'Auto') }}
44815
+ </mat-button-toggle>
44816
+ <mat-button-toggle value="inline">
44817
+ <mat-icon fontIcon="view_stream" aria-hidden="true" />
44818
+ {{ t('editor.value.variant.inline', 'Inline') }}
44819
+ </mat-button-toggle>
44820
+ <mat-button-toggle value="card">
44821
+ <mat-icon fontIcon="crop_square" aria-hidden="true" />
44822
+ {{ t('editor.value.variant.card', 'Card') }}
44823
+ </mat-button-toggle>
44824
+ <mat-button-toggle value="panel">
44825
+ <mat-icon fontIcon="view_agenda" aria-hidden="true" />
44826
+ {{ t('editor.value.variant.panel', 'Panel') }}
44827
+ </mat-button-toggle>
44828
+ <mat-button-toggle value="transparent">
44829
+ <mat-icon fontIcon="layers_clear" aria-hidden="true" />
44830
+ {{ t('editor.value.variant.transparent', 'Transparent') }}
44831
+ </mat-button-toggle>
44832
+ </mat-button-toggle-group>
44833
+ </fieldset>
44834
+
44835
+ <fieldset class="pdx-related-outlet-editor__appearance-cluster">
44836
+ <legend>{{ t('editor.emptyState.field.alignment', 'Alignment') }}</legend>
44837
+ <mat-button-toggle-group
44838
+ formControlName="alignment"
44839
+ hideSingleSelectionIndicator
44840
+ [attr.aria-label]="t('editor.emptyState.field.alignment', 'Alignment')"
44841
+ >
44842
+ <mat-button-toggle value="">
44843
+ <mat-icon fontIcon="auto_awesome" aria-hidden="true" />
44844
+ {{ t('editor.value.derived.short', 'Auto') }}
44845
+ </mat-button-toggle>
44846
+ <mat-button-toggle value="start">
44847
+ <mat-icon fontIcon="format_align_left" aria-hidden="true" />
44848
+ {{ t('editor.value.alignment.start', 'Start') }}
44849
+ </mat-button-toggle>
44850
+ <mat-button-toggle value="center">
44851
+ <mat-icon fontIcon="format_align_center" aria-hidden="true" />
44852
+ {{ t('editor.value.alignment.center', 'Center') }}
44853
+ </mat-button-toggle>
44854
+ </mat-button-toggle-group>
44855
+ </fieldset>
44856
+
44857
+ <div class="pdx-related-outlet-editor__appearance-cluster pdx-related-outlet-editor__density-cluster">
44858
+ <fieldset>
44859
+ <legend>{{ t('editor.emptyState.field.density', 'Density') }}</legend>
44860
+ <mat-button-toggle-group
44861
+ formControlName="density"
44862
+ hideSingleSelectionIndicator
44863
+ [attr.aria-label]="t('editor.emptyState.field.density', 'Density')"
44864
+ >
44865
+ <mat-button-toggle value="">
44866
+ <mat-icon fontIcon="auto_awesome" aria-hidden="true" />
44867
+ {{ t('editor.value.derived.short', 'Auto') }}
44868
+ </mat-button-toggle>
44869
+ <mat-button-toggle value="compact">
44870
+ <mat-icon fontIcon="density_small" aria-hidden="true" />
44871
+ {{ t('editor.value.density.compact', 'Compact') }}
44872
+ </mat-button-toggle>
44873
+ <mat-button-toggle value="comfortable">
44874
+ <mat-icon fontIcon="density_medium" aria-hidden="true" />
44875
+ {{ t('editor.value.density.comfortable', 'Comfortable') }}
44876
+ </mat-button-toggle>
44877
+ </mat-button-toggle-group>
44878
+ </fieldset>
44879
+ <mat-slide-toggle [formControl]="form.controls.compact">
44880
+ {{ t('editor.field.compact', 'Use compact empty and loading states') }}
44881
+ </mat-slide-toggle>
44882
+ </div>
44883
+
44884
+ <fieldset class="pdx-related-outlet-editor__appearance-cluster">
44885
+ <legend>{{ t('editor.emptyState.field.iconContainer', 'Icon container') }}</legend>
44886
+ <mat-button-toggle-group
44887
+ formControlName="iconContainer"
44888
+ hideSingleSelectionIndicator
44889
+ [attr.aria-label]="t('editor.emptyState.field.iconContainer', 'Icon container')"
44890
+ >
44891
+ <mat-button-toggle value="">
44892
+ <mat-icon fontIcon="auto_awesome" aria-hidden="true" />
44893
+ {{ t('editor.value.derived.short', 'Auto') }}
44894
+ </mat-button-toggle>
44895
+ <mat-button-toggle value="none">
44896
+ <mat-icon fontIcon="block" aria-hidden="true" />
44897
+ {{ t('editor.value.iconContainer.none', 'None') }}
44898
+ </mat-button-toggle>
44899
+ <mat-button-toggle value="circle">
44900
+ <mat-icon fontIcon="circle" aria-hidden="true" />
44901
+ {{ t('editor.value.iconContainer.circle', 'Circle') }}
44902
+ </mat-button-toggle>
44903
+ <mat-button-toggle value="soft">
44904
+ <mat-icon fontIcon="blur_on" aria-hidden="true" />
44905
+ {{ t('editor.value.iconContainer.soft', 'Soft') }}
44906
+ </mat-button-toggle>
44907
+ </mat-button-toggle-group>
44908
+ </fieldset>
44909
+ </div>
44910
+ </section>
44911
+
44912
+ <aside class="pdx-related-outlet-editor__boundary" role="note">
44913
+ <mat-icon fontIcon="lock" aria-hidden="true" />
44914
+ <span>
44915
+ <strong>{{ t('editor.boundary.title', 'Relationship is read-only here') }}</strong>
44916
+ <small>
44917
+ {{
44918
+ t(
44919
+ 'editor.boundary.description',
44920
+ 'Resource paths, parent bindings, operations, filters and child table configuration stay with their canonical owners.'
44921
+ )
44922
+ }}
44923
+ </small>
44924
+ </span>
44925
+ </aside>
44926
+ </form>
44927
+ `, styles: [":host{display:block;color:var(--md-sys-color-on-surface, currentColor)}.pdx-related-outlet-editor{display:grid;gap:var(--pdx-spacing-lg, 24px);padding:var(--pdx-spacing-md, 16px)}.pdx-related-outlet-editor__header,.pdx-related-outlet-editor__boundary{display:grid;grid-template-columns:auto minmax(0,1fr);align-items:start;gap:var(--pdx-spacing-sm, 12px)}.pdx-related-outlet-editor__header-icon{display:inline-grid;place-items:center;width:40px;height:40px;border-radius:var(--md-sys-shape-corner-medium, 12px);color:var(--md-sys-color-primary, currentColor);background:var(--md-sys-color-primary-container, transparent)}.pdx-related-outlet-editor__header strong,.pdx-related-outlet-editor__boundary strong,.pdx-related-outlet-editor__header small,.pdx-related-outlet-editor__boundary small{display:block}.pdx-related-outlet-editor__header strong{font:var(--md-sys-typescale-title-medium, 600 1rem/1.4 system-ui)}.pdx-related-outlet-editor__header small,.pdx-related-outlet-editor__boundary small,.pdx-related-outlet-editor__section-heading p{color:var(--md-sys-color-on-surface-variant, currentColor)}.pdx-related-outlet-editor__section{display:grid;gap:var(--pdx-spacing-md, 16px)}.pdx-related-outlet-editor__section-heading h3,.pdx-related-outlet-editor__section-heading p{margin:0}.pdx-related-outlet-editor__section-heading h3{font:var(--md-sys-typescale-title-small, 600 .95rem/1.3 system-ui)}.pdx-related-outlet-editor__section-heading p{margin-top:4px;font:var(--md-sys-typescale-body-small, 400 .82rem/1.35 system-ui)}.pdx-related-outlet-editor__fields{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--pdx-spacing-sm, 12px)}.pdx-related-outlet-editor__wide{grid-column:1 / -1}.pdx-related-outlet-editor__choice-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--pdx-spacing-md, 16px)}.pdx-related-outlet-editor__appearance-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,280px),1fr));gap:var(--pdx-spacing-sm, 12px)}.pdx-related-outlet-editor__appearance-cluster{display:grid;align-content:start;gap:var(--pdx-spacing-sm, 12px);min-width:0}.pdx-related-outlet-editor__appearance-cluster--wide{grid-column:1 / -1}.pdx-related-outlet-editor__appearance-cluster mat-button-toggle-group{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,132px),1fr))}.pdx-related-outlet-editor__appearance-cluster mat-button-toggle{min-height:44px}.pdx-related-outlet-editor__density-cluster{gap:var(--pdx-spacing-md, 16px)}fieldset{min-width:0;margin:0;padding:0;border:0}legend{margin-bottom:8px;font:var(--md-sys-typescale-label-large, 500 .88rem/1.2 system-ui)}mat-button-toggle-group{width:100%}mat-button-toggle{flex:1 1 0}mat-button-toggle mat-icon{margin-right:6px}.pdx-related-outlet-editor__boundary{padding:var(--pdx-spacing-sm, 12px);border:1px solid var(--md-sys-color-outline-variant, currentColor);border-radius:var(--md-sys-shape-corner-medium, 12px);background:var(--md-sys-color-surface-container-low, transparent)}.pdx-related-outlet-editor__boundary mat-icon{color:var(--md-sys-color-on-surface-variant, currentColor)}@media(max-width:640px){.pdx-related-outlet-editor__fields,.pdx-related-outlet-editor__choice-grid{grid-template-columns:minmax(0,1fr)}.pdx-related-outlet-editor__wide{grid-column:auto}mat-button-toggle-group{display:grid}}@media(max-width:420px){.pdx-related-outlet-editor__appearance-cluster mat-button-toggle-group{grid-template-columns:minmax(0,1fr)}}\n"] }]
44928
+ }], ctorParameters: () => [], propDecorators: { inputs: [{ type: i0.Input, args: [{ isSignal: true, alias: "inputs", required: false }] }], widgetKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "widgetKey", required: false }] }], widgetType: [{ type: i0.Input, args: [{ isSignal: true, alias: "widgetType", required: false }] }] } });
44929
+
44930
+ const PRAXIS_RELATED_RESOURCE_OUTLET_PORTS = [
44931
+ {
44932
+ id: 'parentResourceId',
44933
+ label: 'Identificador do recurso pai',
44934
+ direction: 'input',
44935
+ semanticKind: 'value',
44936
+ schema: {
44937
+ id: 'string | number | null',
44938
+ kind: 'ts-type',
44939
+ ref: 'string | number | null',
44940
+ },
44941
+ description: 'Seleção canônica que governa a resolução da coleção filha.',
44942
+ exposure: { public: true, group: 'context' },
44943
+ },
44944
+ {
44945
+ id: 'parentIdentity',
44946
+ label: 'Identidade visual do recurso pai',
44947
+ direction: 'input',
44948
+ semanticKind: 'view-context',
44949
+ schema: {
44950
+ id: 'MaterializedResourceIdentity | null',
44951
+ kind: 'ts-type',
44952
+ ref: 'MaterializedResourceIdentity | null',
44953
+ },
44954
+ description: 'Identidade somente leitura do taskScope, sem transportar o registro pai.',
44955
+ exposure: { public: true, group: 'context' },
44956
+ },
44957
+ {
44958
+ id: 'queryContext',
44959
+ label: 'Contexto de consulta',
44960
+ direction: 'input',
44961
+ semanticKind: 'query-context',
44962
+ schema: {
44963
+ id: 'RelatedResourceQueryContext',
44964
+ kind: 'ts-type',
44965
+ ref: 'RelatedResourceQueryContext',
44966
+ },
44967
+ description: 'Contexto adicional mesclado ao filtro pai-filho publicado pela surface.',
44968
+ exposure: { public: true, advanced: true, group: 'context' },
44969
+ },
44970
+ {
44971
+ id: 'surfaceOpen',
44972
+ label: 'Abertura da superfície relacionada',
44973
+ direction: 'output',
44974
+ semanticKind: 'event',
44975
+ schema: {
44976
+ id: 'SurfaceOpenPayload',
44977
+ kind: 'ts-type',
44978
+ ref: 'SurfaceOpenPayload',
44979
+ },
44980
+ cardinality: 'stream',
44981
+ description: 'Solicita ao host a abertura mediada da superfície no modo open-action.',
44982
+ exposure: { public: true, group: 'events' },
44983
+ },
44984
+ {
44985
+ id: 'widgetEvent',
44986
+ label: 'Evento do widget relacionado',
44987
+ direction: 'output',
44988
+ semanticKind: 'event',
44989
+ schema: {
44990
+ id: 'WidgetEventEnvelope',
44991
+ kind: 'ts-type',
44992
+ ref: 'WidgetEventEnvelope',
44993
+ },
44994
+ cardinality: 'stream',
44995
+ description: 'Reemite eventos do widget filho com identidade de ownership.',
44996
+ exposure: { public: true, advanced: true, group: 'events' },
44997
+ },
44998
+ {
44999
+ id: 'resourceEvent',
45000
+ label: 'Evento canônico do recurso relacionado',
45001
+ direction: 'output',
45002
+ semanticKind: 'event',
45003
+ schema: {
45004
+ id: 'PraxisResourceEvent',
45005
+ kind: 'ts-type',
45006
+ ref: 'PraxisResourceEvent',
45007
+ },
45008
+ cardinality: 'stream',
45009
+ description: 'Promove seleção, mutação e lifecycle do recurso filho para a composição.',
45010
+ exposure: { public: true, group: 'events' },
45011
+ },
45012
+ ];
45013
+ const PRAXIS_RELATED_RESOURCE_OUTLET_COMPONENT_METADATA = {
45014
+ id: 'praxis-related-resource-outlet',
45015
+ selector: 'praxis-related-resource-outlet',
45016
+ component: PraxisRelatedResourceOutletComponent,
45017
+ friendlyName: 'Related Resource Outlet',
45018
+ description: 'Runtime genérico para materializar surface.relatedResource como tabela filha governada por metadata.',
45019
+ icon: 'hub',
45020
+ inputs: [
45021
+ { name: 'surfaceId', type: 'string | null', description: 'Identidade declarativa da surface quando o outlet deve descobri-la no catálogo do recurso.' },
45022
+ { name: 'surfaceCatalog', type: 'ResourceSurfaceCatalogResponse | null', description: 'Catálogo de surfaces já carregado pelo host; evita nova consulta quando disponível.' },
45023
+ { name: 'discoverySource', type: 'ResourceLinkSource | null', description: 'Resposta HATEOAS ou mapa de links usado para seguir rel surfaces quando surface não foi fornecida.' },
45024
+ { name: 'parentLinks', type: 'RestApiLinks | RestApiResponse<unknown> | null', description: 'Atalho para links do registro pai; tem o mesmo papel de discoverySource para rel surfaces.' },
45025
+ { name: 'apiEndpointKey', type: 'ApiEndpoint | null', description: 'Endpoint Praxis usado pelo ResourceDiscoveryService ao resolver links ou fallback do catálogo.' },
45026
+ { name: 'apiUrlEntry', type: 'ApiUrlEntry | null', description: 'Entrada de API já resolvida para hosts destacados ou integrações remotas.' },
45027
+ { name: 'surface', type: 'ResourceSurfaceCatalogItem | null', description: 'Surface de catálogo que pode publicar relatedResource.' },
45028
+ { name: 'parentRecord', type: 'Record<string, unknown> | null', description: 'Registro pai usado para resolver parentIdPathVariable.' },
45029
+ { name: 'parentResourceId', type: 'string | number | null', description: 'Identificador explícito do registro pai quando não vem do record.' },
45030
+ { name: 'parentIdentity', type: 'MaterializedResourceIdentity | null', description: 'Identidade visual somente leitura do recurso pai para continuidade de contexto.' },
45031
+ { name: 'parentResourcePath', type: 'string | null', description: 'ResourcePath do recurso pai para contexto da surface.' },
45032
+ { name: 'presentation', type: 'SurfacePresentation', description: 'Apresentação usada no payload de abertura host-mediated.', default: 'drawer' },
45033
+ { name: 'title', type: 'string | null', description: 'Título opcional que substitui o título publicado pela surface.' },
45034
+ { name: 'subtitle', type: 'string | null', description: 'Subtítulo opcional que substitui a descrição publicada pela surface.' },
45035
+ { name: 'icon', type: 'string | null', description: 'Ícone opcional da superfície relacionada.' },
45036
+ { name: 'queryContext', type: 'RelatedResourceQueryContext | null', description: 'QueryContext base mesclado com o filtro canônico da relação filha.' },
45037
+ { name: 'tableId', type: 'string | null', description: 'Identidade estável da tabela filha para persistência, observabilidade e testes.' },
45038
+ { name: 'tableConfig', type: 'Record<string, unknown> | null', description: 'Configuração parcial mesclada ao preset canônico. Ações CRUD com ids create, edit e delete aceitam somente overrides visuais (label, tooltip, icon, color, appearance, type, position e order); semântica, alvo, formulários, confirmação e disponibilidade permanecem governados pelo materializador.' },
45039
+ { name: 'emptyState', type: 'Record<string, unknown> | null', description: 'Override opcional para behavior.emptyState da tabela filha. Quando omitido, o outlet deriva texto, icone, layout e ação create a partir de surface.relatedResource e dos metadados da surface.' },
45040
+ { name: 'enableCustomization', type: 'boolean', description: 'Opt-in explicito para authoring governado da tabela filha.', default: false },
45041
+ { name: 'authoringCapability', type: 'string | null', description: 'Capability publica do EnterpriseRuntimeContext exigida quando o authoring da tabela filha estiver habilitado.' },
45042
+ { name: 'mode', type: "'inline' | 'open-action'", description: 'Renderiza a tabela filha inline ou emite payload para abertura host-mediated.', default: 'inline' },
45043
+ { name: 'state', type: 'RelatedResourceResolutionState | null', description: 'Override de estado para hosts/outlets que estejam carregando discovery remoto.' },
45044
+ { name: 'stateReason', type: 'string | null', description: 'Motivo governado associado ao override de estado.' },
45045
+ { name: 'compact', type: 'boolean', description: 'Reduz densidade visual dos estados não materializados.', default: false },
45046
+ { name: 'strictValidation', type: 'boolean', description: 'Validação estrita do widget materializado pelo DynamicWidgetLoader.', default: false },
45047
+ { name: 'ownerWidgetKey', type: 'string', description: 'Identidade do owner usada para correlacionar eventos do widget filho.', default: 'related-resource.outlet' },
45048
+ ],
45049
+ outputs: [
45050
+ { name: 'surfaceOpen', type: 'SurfaceOpenPayload', description: 'Emitido em modo open-action com o payload pronto de surface.open.' },
45051
+ { name: 'widgetEvent', type: 'WidgetEventEnvelope', description: 'Reemite eventos do widget filho materializado.' },
45052
+ { name: 'resourceEvent', type: 'PraxisResourceEvent', description: 'Promove eventos canonicos emitidos pelo widget filho materializado.' },
45053
+ ],
45054
+ ports: PRAXIS_RELATED_RESOURCE_OUTLET_PORTS,
45055
+ configEditor: {
45056
+ component: PraxisRelatedResourceOutletConfigEditorComponent,
45057
+ title: 'Related resource presentation',
45058
+ },
45059
+ authoringManifestRef: {
45060
+ componentId: 'praxis-related-resource-outlet',
45061
+ version: '1.0.0',
45062
+ source: 'PRAXIS_RELATED_RESOURCE_OUTLET_AUTHORING_MANIFEST',
45063
+ },
45064
+ tags: ['resource', 'surface', 'related-resource', 'runtime', 'metadata-driven'],
45065
+ lib: '@praxisui/core',
45066
+ };
45067
+ function providePraxisRelatedResourceOutletMetadata() {
45068
+ return {
45069
+ provide: ENVIRONMENT_INITIALIZER,
45070
+ multi: true,
45071
+ useFactory: (registry) => () => {
45072
+ registry.register(PRAXIS_RELATED_RESOURCE_OUTLET_COMPONENT_METADATA);
45073
+ },
45074
+ deps: [ComponentMetadataRegistry],
45075
+ };
45076
+ }
45077
+
45078
+ const nullableTextSchema = {
45079
+ oneOf: [{ type: 'string' }, { type: 'null' }],
45080
+ };
45081
+ const presentationValidators = [
45082
+ 'component-config-editor-respected',
45083
+ 'editor-round-trip-preserve',
45084
+ ];
45085
+ const PRAXIS_RELATED_RESOURCE_OUTLET_AUTHORING_MANIFEST = {
45086
+ schemaVersion: '1.0.0',
45087
+ componentId: 'praxis-related-resource-outlet',
45088
+ ownerPackage: '@praxisui/core',
45089
+ configSchemaId: 'PraxisRelatedResourceOutletPresentationInputs',
45090
+ manifestVersion: '1.0.0',
45091
+ runtimeInputs: [
45092
+ { name: 'title', type: 'string | null', description: 'Optional visual title override.' },
45093
+ { name: 'subtitle', type: 'string | null', description: 'Optional visual subtitle override.' },
45094
+ { name: 'icon', type: 'string | null', description: 'Optional visual icon override.' },
45095
+ { name: 'mode', type: "'inline' | 'open-action'", allowedValues: ['inline', 'open-action'], description: 'Outlet display mode.' },
45096
+ { name: 'presentation', type: "'drawer' | 'modal'", allowedValues: ['drawer', 'modal'], description: 'Host-mediated presentation used by open-action mode.' },
45097
+ { name: 'compact', type: 'boolean', allowedValues: [true, false], description: 'Compact visual density for non-materialized states.' },
45098
+ {
45099
+ name: 'emptyState',
45100
+ type: 'PraxisRelatedResourceOutletEmptyStatePresentation',
45101
+ description: 'Closed presentation-only empty-state subset. Actions, templates and contexts are not authorable here.',
45102
+ },
45103
+ ],
45104
+ editableTargets: [
45105
+ {
45106
+ kind: 'relatedResourceOutletPresentation',
45107
+ resolver: 'component-config',
45108
+ description: 'Persisted visual shell inputs owned by the Related Resource Outlet config editor.',
45109
+ },
45110
+ {
45111
+ kind: 'relatedResourceOutletEmptyStatePresentation',
45112
+ resolver: 'component-config',
45113
+ description: 'Persisted presentation-only emptyState subset; opaque empty-state fields are preserved unchanged.',
45114
+ },
45115
+ ],
45116
+ operations: [
45117
+ {
45118
+ operationId: 'related-resource-outlet.presentation.set-title',
45119
+ title: 'Set related-resource title',
45120
+ description: 'Sets only the persisted visual title; relationship metadata and runtime context remain unchanged.',
45121
+ scope: 'global',
45122
+ targetKind: 'relatedResourceOutletPresentation',
45123
+ target: {
45124
+ kind: 'relatedResourceOutletPresentation',
45125
+ resolver: 'component-config',
45126
+ ambiguityPolicy: 'fail',
45127
+ required: false,
45128
+ },
45129
+ inputSchema: {
45130
+ type: 'object',
45131
+ additionalProperties: false,
45132
+ required: ['value'],
45133
+ properties: { value: nullableTextSchema },
45134
+ },
45135
+ effects: [{ kind: 'set-value', path: 'title', inputPath: 'value' }],
45136
+ destructive: false,
45137
+ requiresConfirmation: false,
45138
+ validators: presentationValidators,
45139
+ affectedPaths: ['title'],
45140
+ submissionImpact: 'visual-only',
45141
+ preconditions: ['component-config-loaded'],
45142
+ },
45143
+ {
45144
+ operationId: 'related-resource-outlet.presentation.set-subtitle',
45145
+ title: 'Set related-resource subtitle',
45146
+ description: 'Sets only the persisted visual subtitle; relationship metadata and runtime context remain unchanged.',
45147
+ scope: 'global',
45148
+ targetKind: 'relatedResourceOutletPresentation',
45149
+ target: {
45150
+ kind: 'relatedResourceOutletPresentation',
45151
+ resolver: 'component-config',
45152
+ ambiguityPolicy: 'fail',
45153
+ required: false,
45154
+ },
45155
+ inputSchema: {
45156
+ type: 'object',
45157
+ additionalProperties: false,
45158
+ required: ['value'],
45159
+ properties: { value: nullableTextSchema },
45160
+ },
45161
+ effects: [{ kind: 'set-value', path: 'subtitle', inputPath: 'value' }],
45162
+ destructive: false,
45163
+ requiresConfirmation: false,
45164
+ validators: presentationValidators,
45165
+ affectedPaths: ['subtitle'],
45166
+ submissionImpact: 'visual-only',
45167
+ preconditions: ['component-config-loaded'],
45168
+ },
45169
+ {
45170
+ operationId: 'related-resource-outlet.presentation.set-icon',
45171
+ title: 'Set related-resource icon',
45172
+ description: 'Sets only the persisted visual icon; relationship metadata and runtime context remain unchanged.',
45173
+ scope: 'global',
45174
+ targetKind: 'relatedResourceOutletPresentation',
45175
+ target: {
45176
+ kind: 'relatedResourceOutletPresentation',
45177
+ resolver: 'component-config',
45178
+ ambiguityPolicy: 'fail',
45179
+ required: false,
45180
+ },
45181
+ inputSchema: {
45182
+ type: 'object',
45183
+ additionalProperties: false,
45184
+ required: ['value'],
45185
+ properties: { value: nullableTextSchema },
45186
+ },
45187
+ effects: [{ kind: 'set-value', path: 'icon', inputPath: 'value' }],
45188
+ destructive: false,
45189
+ requiresConfirmation: false,
45190
+ validators: presentationValidators,
45191
+ affectedPaths: ['icon'],
45192
+ submissionImpact: 'visual-only',
45193
+ preconditions: ['component-config-loaded'],
45194
+ },
45195
+ {
45196
+ operationId: 'related-resource-outlet.presentation.set-mode',
45197
+ title: 'Set related-resource display mode',
45198
+ description: 'Selects inline rendering or a host-mediated open action without changing the relationship or its operation.',
45199
+ scope: 'global',
45200
+ targetKind: 'relatedResourceOutletPresentation',
45201
+ target: {
45202
+ kind: 'relatedResourceOutletPresentation',
45203
+ resolver: 'component-config',
45204
+ ambiguityPolicy: 'fail',
45205
+ required: false,
45206
+ },
45207
+ inputSchema: {
45208
+ type: 'object',
45209
+ additionalProperties: false,
45210
+ required: ['value'],
45211
+ properties: { value: { enum: ['inline', 'open-action'] } },
45212
+ },
45213
+ effects: [{ kind: 'set-value', path: 'mode', inputPath: 'value' }],
45214
+ destructive: false,
45215
+ requiresConfirmation: false,
45216
+ validators: presentationValidators,
45217
+ affectedPaths: ['mode'],
45218
+ submissionImpact: 'visual-only',
45219
+ preconditions: ['component-config-loaded'],
45220
+ },
45221
+ {
45222
+ operationId: 'related-resource-outlet.presentation.set-open-presentation',
45223
+ title: 'Set related-resource open presentation',
45224
+ description: 'Selects drawer or modal for the host-mediated open payload without changing target resource semantics.',
45225
+ scope: 'global',
45226
+ targetKind: 'relatedResourceOutletPresentation',
45227
+ target: {
45228
+ kind: 'relatedResourceOutletPresentation',
45229
+ resolver: 'component-config',
45230
+ ambiguityPolicy: 'fail',
45231
+ required: false,
45232
+ },
45233
+ inputSchema: {
45234
+ type: 'object',
45235
+ additionalProperties: false,
45236
+ required: ['value'],
45237
+ properties: { value: { enum: ['drawer', 'modal'] } },
45238
+ },
45239
+ effects: [{ kind: 'set-value', path: 'presentation', inputPath: 'value' }],
45240
+ destructive: false,
45241
+ requiresConfirmation: false,
45242
+ validators: presentationValidators,
45243
+ affectedPaths: ['presentation'],
45244
+ submissionImpact: 'visual-only',
45245
+ preconditions: ['component-config-loaded'],
45246
+ },
45247
+ {
45248
+ operationId: 'related-resource-outlet.presentation.set-compact',
45249
+ title: 'Set compact related-resource states',
45250
+ description: 'Changes only the visual density of non-materialized outlet states.',
45251
+ scope: 'global',
45252
+ targetKind: 'relatedResourceOutletPresentation',
45253
+ target: {
45254
+ kind: 'relatedResourceOutletPresentation',
45255
+ resolver: 'component-config',
45256
+ ambiguityPolicy: 'fail',
45257
+ required: false,
45258
+ },
45259
+ inputSchema: {
45260
+ type: 'object',
45261
+ additionalProperties: false,
45262
+ required: ['value'],
45263
+ properties: { value: { type: 'boolean' } },
45264
+ },
45265
+ effects: [{ kind: 'set-value', path: 'compact', inputPath: 'value' }],
45266
+ destructive: false,
45267
+ requiresConfirmation: false,
45268
+ validators: presentationValidators,
45269
+ affectedPaths: ['compact'],
45270
+ submissionImpact: 'visual-only',
45271
+ preconditions: ['component-config-loaded'],
45272
+ },
45273
+ {
45274
+ operationId: 'related-resource-outlet.presentation.configure-empty-state',
45275
+ title: 'Configure related-resource empty-state presentation',
45276
+ description: 'Merges only the closed presentation subset; actions, contexts, images, templates and unknown fields remain opaque.',
45277
+ scope: 'global',
45278
+ targetKind: 'relatedResourceOutletEmptyStatePresentation',
45279
+ target: {
45280
+ kind: 'relatedResourceOutletEmptyStatePresentation',
45281
+ resolver: 'component-config',
45282
+ ambiguityPolicy: 'fail',
45283
+ required: false,
45284
+ },
45285
+ inputSchema: {
45286
+ type: 'object',
45287
+ additionalProperties: false,
45288
+ minProperties: 1,
45289
+ properties: {
45290
+ title: nullableTextSchema,
45291
+ message: nullableTextSchema,
45292
+ description: nullableTextSchema,
45293
+ icon: nullableTextSchema,
45294
+ tone: { oneOf: [{ enum: ['neutral', 'primary', 'secondary'] }, { type: 'null' }] },
45295
+ variant: { oneOf: [{ enum: ['card', 'inline', 'panel', 'transparent'] }, { type: 'null' }] },
45296
+ alignment: { oneOf: [{ enum: ['start', 'center'] }, { type: 'null' }] },
45297
+ density: { oneOf: [{ enum: ['compact', 'comfortable'] }, { type: 'null' }] },
45298
+ iconContainer: { oneOf: [{ enum: ['none', 'circle', 'soft'] }, { type: 'null' }] },
45299
+ },
45300
+ },
45301
+ effects: [{ kind: 'merge-object', path: 'emptyState' }],
45302
+ destructive: false,
45303
+ requiresConfirmation: false,
45304
+ validators: presentationValidators,
45305
+ affectedPaths: [
45306
+ 'emptyState.title',
45307
+ 'emptyState.message',
45308
+ 'emptyState.description',
45309
+ 'emptyState.icon',
45310
+ 'emptyState.tone',
45311
+ 'emptyState.variant',
45312
+ 'emptyState.alignment',
45313
+ 'emptyState.density',
45314
+ 'emptyState.iconContainer',
45315
+ ],
45316
+ submissionImpact: 'visual-only',
45317
+ preconditions: ['component-config-loaded'],
45318
+ },
45319
+ ],
45320
+ validators: [
45321
+ {
45322
+ validatorId: 'component-config-editor-respected',
45323
+ level: 'error',
45324
+ code: 'RELATED_RESOURCE_OUTLET_CONFIG_EDITOR_RESPECTED',
45325
+ description: 'Only paths owned by the published config editor may be authored.',
45326
+ },
45327
+ {
45328
+ validatorId: 'editor-round-trip-preserve',
45329
+ level: 'error',
45330
+ code: 'RELATED_RESOURCE_OUTLET_EDITOR_ROUND_TRIP_PRESERVE',
45331
+ description: 'Save and reopen must preserve runtime, relationship, Table-owned and unknown persisted inputs without drift.',
45332
+ },
45333
+ ],
45334
+ roundTripRequirements: [
45335
+ 'Opening the editor must never materialize runtime inputs or mutate the persisted widget definition.',
45336
+ 'Apply, Save, Reset and Reopen must preserve every input outside the presentation-only editor boundary byte-for-byte.',
45337
+ 'parentResourceId, surfaceId, surface, parentRecord, queryContext, state, relationship semantics and tableConfig are never authorable by this manifest.',
45338
+ 'Unknown root inputs and unknown or behavior-bearing emptyState fields remain opaque and are preserved unchanged.',
45339
+ ],
45340
+ examples: [
45341
+ {
45342
+ id: 'set-related-resource-shell',
45343
+ request: 'Show the related participants inline with the title Participants and compact states.',
45344
+ operationId: 'related-resource-outlet.presentation.set-title',
45345
+ params: { value: 'Participants' },
45346
+ isPositive: true,
45347
+ },
45348
+ {
45349
+ id: 'set-related-resource-empty-state-copy',
45350
+ request: 'Use No participants yet as the empty-state title.',
45351
+ operationId: 'related-resource-outlet.presentation.configure-empty-state',
45352
+ params: { title: 'No participants yet' },
45353
+ isPositive: true,
45354
+ },
45355
+ {
45356
+ id: 'reject-related-resource-relationship-authoring',
45357
+ request: 'Change the child resource path, parent field, filter operation and tableConfig from this outlet editor.',
45358
+ operationId: 'related-resource-outlet.presentation.configure-empty-state',
45359
+ params: {
45360
+ childResourcePath: 'operations/participants',
45361
+ childParentField: 'missionId',
45362
+ tableConfig: { columns: [] },
45363
+ },
45364
+ isPositive: false,
45365
+ },
45366
+ ],
45367
+ };
45368
+
45369
+ class EmptyStateCardComponent {
45370
+ icon = 'tab';
45371
+ title = 'Sem configuração disponível';
45372
+ description;
45373
+ primaryAction;
45374
+ secondaryActions = [];
45375
+ inline = false;
45376
+ tone = 'neutral';
45377
+ variant = 'card';
45378
+ alignment = 'start';
45379
+ density = 'comfortable';
45380
+ iconContainer = 'none';
45381
+ effectiveVariant() {
45382
+ return this.inline && this.variant === 'card' ? 'inline' : this.variant;
45383
+ }
45384
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: EmptyStateCardComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
45385
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: EmptyStateCardComponent, isStandalone: true, selector: "praxis-empty-state-card", inputs: { icon: "icon", title: "title", description: "description", primaryAction: "primaryAction", secondaryActions: "secondaryActions", inline: "inline", tone: "tone", variant: "variant", alignment: "alignment", density: "density", iconContainer: "iconContainer" }, ngImport: i0, template: `
45386
+ <mat-card
45387
+ class="empty-card"
45388
+ [class.empty-inline]="inline"
45389
+ [class.tone-primary]="tone === 'primary'"
45390
+ [class.tone-secondary]="tone === 'secondary'"
45391
+ [class.variant-inline]="effectiveVariant() === 'inline'"
45392
+ [class.variant-panel]="effectiveVariant() === 'panel'"
45393
+ [class.variant-transparent]="effectiveVariant() === 'transparent'"
45394
+ [class.align-center]="alignment === 'center'"
45395
+ [class.density-compact]="density === 'compact'"
45396
+ [class.icon-circle]="iconContainer === 'circle'"
45397
+ [class.icon-soft]="iconContainer === 'soft'"
45398
+ appearance="outlined"
45399
+ >
45400
+ <mat-card-content>
45401
+ <div class="content">
45402
+ @if (icon) {
45403
+ <mat-icon class="icon" [fontIcon]="icon"></mat-icon>
45404
+ }
45405
+ <div class="texts">
45406
+ <h3 class="title">{{ title }}</h3>
45407
+ @if (description) {
45408
+ <p class="desc">{{ description }}</p>
45409
+ }
45410
+ </div>
45411
+ </div>
45412
+ <div class="actions">
45413
+ @if (primaryAction) {
45414
+ <button type="button" mat-flat-button color="primary" (click)="primaryAction.action()">
45415
+ @if (primaryAction.icon) {
45416
+ <mat-icon [fontIcon]="primaryAction.icon"></mat-icon>
45417
+ }
45418
+ {{ primaryAction.label }}
45419
+ </button>
45420
+ }
45421
+ @for (a of secondaryActions; track a) {
45422
+ <button type="button" mat-stroked-button [color]="a.color" (click)="a.action()">
45423
+ @if (a.icon) {
45424
+ <mat-icon [fontIcon]="a.icon"></mat-icon>
45425
+ }
45426
+ {{ a.label }}
45427
+ </button>
45428
+ }
45429
+ </div>
45430
+ </mat-card-content>
45431
+ </mat-card>
45432
+ `, isInline: true, styles: [".empty-card{display:block;margin:var(--pdx-empty-state-margin, 12px);border-color:var(--pdx-empty-state-border-color, var(--md-sys-color-outline-variant));border-radius:var(--pdx-empty-state-radius, 8px);background:var(--pdx-empty-state-bg, var(--md-sys-color-surface));color:var(--pdx-empty-state-fg, var(--md-sys-color-on-surface));--empty-icon-color: var(--pdx-empty-state-icon-color, var(--md-sys-color-on-surface-variant))}.empty-card.empty-inline,.empty-card.variant-inline{margin:var(--pdx-empty-state-inline-margin, 8px 0)}.empty-card.variant-panel{margin:var(--pdx-empty-state-panel-margin, 0)}.empty-card.variant-transparent{margin:var(--pdx-empty-state-transparent-margin, 0);border-color:transparent;background:transparent;box-shadow:none}.content{display:flex;align-items:center;gap:var(--pdx-empty-state-gap, 12px)}.align-center .content{flex-direction:column;justify-content:center;text-align:center}.icon{display:inline-grid;place-items:center;flex:0 0 auto;font-size:var(--pdx-empty-state-icon-size, 32px);width:var(--pdx-empty-state-icon-box-size, 32px);height:var(--pdx-empty-state-icon-box-size, 32px);color:var(--empty-icon-color)}.icon-circle .icon,.icon-soft .icon{width:var(--pdx-empty-state-icon-container-size, 44px);height:var(--pdx-empty-state-icon-container-size, 44px);border-radius:var(--pdx-empty-state-icon-container-radius, 999px);font-size:var(--pdx-empty-state-icon-container-icon-size, 22px)}.icon-circle .icon{border:1px solid var(--pdx-empty-state-icon-container-border-color, color-mix(in srgb, var(--empty-icon-color) 24%, transparent));background:var(--pdx-empty-state-icon-container-bg, color-mix(in srgb, var(--empty-icon-color) 10%, transparent))}.icon-soft .icon{background:var(--pdx-empty-state-icon-container-bg, color-mix(in srgb, var(--empty-icon-color) 10%, transparent))}.texts{display:grid;gap:var(--pdx-empty-state-text-gap, 4px)}.align-center .texts{justify-items:center}.title{margin:0;font-family:var(--pdx-empty-state-title-font-family, var(--md-sys-typescale-title-small-font-family, inherit));font-size:var(--pdx-empty-state-title-font-size, 16px);font-weight:var(--pdx-empty-state-title-font-weight, 600);line-height:var(--pdx-empty-state-title-line-height, 1.3);color:var(--pdx-empty-state-title-color, var(--md-sys-color-on-surface))}.desc{margin:0;max-width:var(--pdx-empty-state-description-max-width, none);font-family:var(--pdx-empty-state-description-font-family, var(--md-sys-typescale-body-medium-font-family, inherit));font-size:var(--pdx-empty-state-description-font-size, inherit);line-height:var(--pdx-empty-state-description-line-height, 1.4);color:var(--pdx-empty-state-description-color, var(--md-sys-color-on-surface-variant))}.actions{display:flex;justify-content:var(--pdx-empty-state-actions-justify, flex-start);gap:var(--pdx-empty-state-actions-gap, 8px);margin-top:var(--pdx-empty-state-actions-margin-top, 12px);flex-wrap:wrap}.actions .mat-mdc-button-base{width:fit-content;max-width:100%;height:var(--pdx-empty-state-action-height, var(--praxis-action-control-height, 40px));min-height:var(--pdx-empty-state-action-height, var(--praxis-action-control-height, 40px));padding-inline:var(--pdx-empty-state-action-padding-inline, var(--praxis-action-control-padding-inline, 12px));border-radius:var(--pdx-empty-state-action-radius, var(--praxis-action-control-radius, 8px));gap:var(--pdx-empty-state-action-gap, var(--praxis-action-control-gap, 8px));font-size:var(--pdx-empty-state-action-font-size, var(--praxis-action-control-font-size, .875rem));font-weight:var(--pdx-empty-state-action-font-weight, var(--praxis-action-control-font-weight, 500));line-height:var(--pdx-empty-state-action-line-height, var(--praxis-action-control-line-height, 1.25rem));white-space:nowrap}.actions .mat-mdc-button-base mat-icon{width:var(--pdx-empty-state-action-icon-size, var(--praxis-action-control-icon-size, 18px));height:var(--pdx-empty-state-action-icon-size, var(--praxis-action-control-icon-size, 18px));margin:0;font-size:var(--pdx-empty-state-action-icon-size, var(--praxis-action-control-icon-size, 18px));line-height:var(--pdx-empty-state-action-icon-size, var(--praxis-action-control-icon-size, 18px))}.actions .mat-mdc-button-base:focus-visible{outline:2px solid var(--pdx-empty-state-action-focus-ring, var(--praxis-action-control-focus-ring, var(--md-sys-color-primary)));outline-offset:2px}.actions .mat-mdc-button-base:disabled{opacity:var(--pdx-empty-state-action-disabled-opacity, var(--praxis-action-control-disabled-opacity, .62))}.align-center .actions{justify-content:var(--pdx-empty-state-actions-justify, center)}.density-compact .content{gap:var(--pdx-empty-state-compact-gap, 8px)}.density-compact .actions .mat-mdc-button-base{height:var(--pdx-empty-state-action-height, var(--praxis-action-control-compact-height, 36px));min-height:var(--pdx-empty-state-action-height, var(--praxis-action-control-compact-height, 36px))}.density-compact .icon{font-size:var(--pdx-empty-state-compact-icon-size, 24px);width:var(--pdx-empty-state-compact-icon-box-size, 24px);height:var(--pdx-empty-state-compact-icon-box-size, 24px)}.density-compact.icon-circle .icon,.density-compact.icon-soft .icon{width:var(--pdx-empty-state-compact-icon-container-size, 36px);height:var(--pdx-empty-state-compact-icon-container-size, 36px);font-size:var(--pdx-empty-state-compact-icon-container-icon-size, 20px)}.empty-card.tone-primary{--empty-icon-color: var(--md-sys-color-primary)}.empty-card.tone-secondary{--empty-icon-color: var(--md-sys-color-secondary)}\n"], dependencies: [{ kind: "ngmodule", type: MatCardModule }, { kind: "component", type: i2$1.MatCard, selector: "mat-card", inputs: ["appearance"], exportAs: ["matCard"] }, { kind: "directive", type: i2$1.MatCardContent, selector: "mat-card-content" }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }] });
45433
+ }
45434
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: EmptyStateCardComponent, decorators: [{
45435
+ type: Component,
45436
+ args: [{ selector: 'praxis-empty-state-card', standalone: true, imports: [MatCardModule, MatButtonModule, MatIconModule], template: `
45437
+ <mat-card
45438
+ class="empty-card"
45439
+ [class.empty-inline]="inline"
45440
+ [class.tone-primary]="tone === 'primary'"
45441
+ [class.tone-secondary]="tone === 'secondary'"
45442
+ [class.variant-inline]="effectiveVariant() === 'inline'"
45443
+ [class.variant-panel]="effectiveVariant() === 'panel'"
45444
+ [class.variant-transparent]="effectiveVariant() === 'transparent'"
45445
+ [class.align-center]="alignment === 'center'"
45446
+ [class.density-compact]="density === 'compact'"
45447
+ [class.icon-circle]="iconContainer === 'circle'"
45448
+ [class.icon-soft]="iconContainer === 'soft'"
45449
+ appearance="outlined"
45450
+ >
45451
+ <mat-card-content>
45452
+ <div class="content">
45453
+ @if (icon) {
45454
+ <mat-icon class="icon" [fontIcon]="icon"></mat-icon>
45455
+ }
45456
+ <div class="texts">
45457
+ <h3 class="title">{{ title }}</h3>
45458
+ @if (description) {
45459
+ <p class="desc">{{ description }}</p>
45460
+ }
45461
+ </div>
45462
+ </div>
45463
+ <div class="actions">
45464
+ @if (primaryAction) {
45465
+ <button type="button" mat-flat-button color="primary" (click)="primaryAction.action()">
45466
+ @if (primaryAction.icon) {
45467
+ <mat-icon [fontIcon]="primaryAction.icon"></mat-icon>
45468
+ }
45469
+ {{ primaryAction.label }}
45470
+ </button>
45471
+ }
45472
+ @for (a of secondaryActions; track a) {
45473
+ <button type="button" mat-stroked-button [color]="a.color" (click)="a.action()">
45474
+ @if (a.icon) {
45475
+ <mat-icon [fontIcon]="a.icon"></mat-icon>
45476
+ }
45477
+ {{ a.label }}
45478
+ </button>
45479
+ }
45480
+ </div>
45481
+ </mat-card-content>
45482
+ </mat-card>
45483
+ `, styles: [".empty-card{display:block;margin:var(--pdx-empty-state-margin, 12px);border-color:var(--pdx-empty-state-border-color, var(--md-sys-color-outline-variant));border-radius:var(--pdx-empty-state-radius, 8px);background:var(--pdx-empty-state-bg, var(--md-sys-color-surface));color:var(--pdx-empty-state-fg, var(--md-sys-color-on-surface));--empty-icon-color: var(--pdx-empty-state-icon-color, var(--md-sys-color-on-surface-variant))}.empty-card.empty-inline,.empty-card.variant-inline{margin:var(--pdx-empty-state-inline-margin, 8px 0)}.empty-card.variant-panel{margin:var(--pdx-empty-state-panel-margin, 0)}.empty-card.variant-transparent{margin:var(--pdx-empty-state-transparent-margin, 0);border-color:transparent;background:transparent;box-shadow:none}.content{display:flex;align-items:center;gap:var(--pdx-empty-state-gap, 12px)}.align-center .content{flex-direction:column;justify-content:center;text-align:center}.icon{display:inline-grid;place-items:center;flex:0 0 auto;font-size:var(--pdx-empty-state-icon-size, 32px);width:var(--pdx-empty-state-icon-box-size, 32px);height:var(--pdx-empty-state-icon-box-size, 32px);color:var(--empty-icon-color)}.icon-circle .icon,.icon-soft .icon{width:var(--pdx-empty-state-icon-container-size, 44px);height:var(--pdx-empty-state-icon-container-size, 44px);border-radius:var(--pdx-empty-state-icon-container-radius, 999px);font-size:var(--pdx-empty-state-icon-container-icon-size, 22px)}.icon-circle .icon{border:1px solid var(--pdx-empty-state-icon-container-border-color, color-mix(in srgb, var(--empty-icon-color) 24%, transparent));background:var(--pdx-empty-state-icon-container-bg, color-mix(in srgb, var(--empty-icon-color) 10%, transparent))}.icon-soft .icon{background:var(--pdx-empty-state-icon-container-bg, color-mix(in srgb, var(--empty-icon-color) 10%, transparent))}.texts{display:grid;gap:var(--pdx-empty-state-text-gap, 4px)}.align-center .texts{justify-items:center}.title{margin:0;font-family:var(--pdx-empty-state-title-font-family, var(--md-sys-typescale-title-small-font-family, inherit));font-size:var(--pdx-empty-state-title-font-size, 16px);font-weight:var(--pdx-empty-state-title-font-weight, 600);line-height:var(--pdx-empty-state-title-line-height, 1.3);color:var(--pdx-empty-state-title-color, var(--md-sys-color-on-surface))}.desc{margin:0;max-width:var(--pdx-empty-state-description-max-width, none);font-family:var(--pdx-empty-state-description-font-family, var(--md-sys-typescale-body-medium-font-family, inherit));font-size:var(--pdx-empty-state-description-font-size, inherit);line-height:var(--pdx-empty-state-description-line-height, 1.4);color:var(--pdx-empty-state-description-color, var(--md-sys-color-on-surface-variant))}.actions{display:flex;justify-content:var(--pdx-empty-state-actions-justify, flex-start);gap:var(--pdx-empty-state-actions-gap, 8px);margin-top:var(--pdx-empty-state-actions-margin-top, 12px);flex-wrap:wrap}.actions .mat-mdc-button-base{width:fit-content;max-width:100%;height:var(--pdx-empty-state-action-height, var(--praxis-action-control-height, 40px));min-height:var(--pdx-empty-state-action-height, var(--praxis-action-control-height, 40px));padding-inline:var(--pdx-empty-state-action-padding-inline, var(--praxis-action-control-padding-inline, 12px));border-radius:var(--pdx-empty-state-action-radius, var(--praxis-action-control-radius, 8px));gap:var(--pdx-empty-state-action-gap, var(--praxis-action-control-gap, 8px));font-size:var(--pdx-empty-state-action-font-size, var(--praxis-action-control-font-size, .875rem));font-weight:var(--pdx-empty-state-action-font-weight, var(--praxis-action-control-font-weight, 500));line-height:var(--pdx-empty-state-action-line-height, var(--praxis-action-control-line-height, 1.25rem));white-space:nowrap}.actions .mat-mdc-button-base mat-icon{width:var(--pdx-empty-state-action-icon-size, var(--praxis-action-control-icon-size, 18px));height:var(--pdx-empty-state-action-icon-size, var(--praxis-action-control-icon-size, 18px));margin:0;font-size:var(--pdx-empty-state-action-icon-size, var(--praxis-action-control-icon-size, 18px));line-height:var(--pdx-empty-state-action-icon-size, var(--praxis-action-control-icon-size, 18px))}.actions .mat-mdc-button-base:focus-visible{outline:2px solid var(--pdx-empty-state-action-focus-ring, var(--praxis-action-control-focus-ring, var(--md-sys-color-primary)));outline-offset:2px}.actions .mat-mdc-button-base:disabled{opacity:var(--pdx-empty-state-action-disabled-opacity, var(--praxis-action-control-disabled-opacity, .62))}.align-center .actions{justify-content:var(--pdx-empty-state-actions-justify, center)}.density-compact .content{gap:var(--pdx-empty-state-compact-gap, 8px)}.density-compact .actions .mat-mdc-button-base{height:var(--pdx-empty-state-action-height, var(--praxis-action-control-compact-height, 36px));min-height:var(--pdx-empty-state-action-height, var(--praxis-action-control-compact-height, 36px))}.density-compact .icon{font-size:var(--pdx-empty-state-compact-icon-size, 24px);width:var(--pdx-empty-state-compact-icon-box-size, 24px);height:var(--pdx-empty-state-compact-icon-box-size, 24px)}.density-compact.icon-circle .icon,.density-compact.icon-soft .icon{width:var(--pdx-empty-state-compact-icon-container-size, 36px);height:var(--pdx-empty-state-compact-icon-container-size, 36px);font-size:var(--pdx-empty-state-compact-icon-container-icon-size, 20px)}.empty-card.tone-primary{--empty-icon-color: var(--md-sys-color-primary)}.empty-card.tone-secondary{--empty-icon-color: var(--md-sys-color-secondary)}\n"] }]
45484
+ }], propDecorators: { icon: [{
45485
+ type: Input
45486
+ }], title: [{
45487
+ type: Input
45488
+ }], description: [{
45489
+ type: Input
45490
+ }], primaryAction: [{
45491
+ type: Input
45492
+ }], secondaryActions: [{
45493
+ type: Input
45494
+ }], inline: [{
45495
+ type: Input
45496
+ }], tone: [{
45497
+ type: Input
45498
+ }], variant: [{
45499
+ type: Input
45500
+ }], alignment: [{
45501
+ type: Input
45502
+ }], density: [{
45503
+ type: Input
45504
+ }], iconContainer: [{
45505
+ type: Input
45506
+ }] } });
45507
+
45508
+ class ResourceQuickConnectComponent {
45509
+ resourcePath = '';
45510
+ isDirty$ = new BehaviorSubject(false);
45511
+ isValid$ = new BehaviorSubject(false);
45512
+ isBusy$ = new BehaviorSubject(false);
45513
+ // Values are provided via Inputs by the opener; no DI data coupling required.
45514
+ // When used standalone, consumers can bind [(resourcePath)].
45515
+ ngOnInit() {
45516
+ this.updateValidity();
45517
+ }
45518
+ ngOnChanges() {
45519
+ this.updateValidity();
45520
+ }
45521
+ updateState() {
45522
+ this.isDirty$.next(true);
45523
+ this.updateValidity();
45524
+ }
45525
+ updateValidity() {
45526
+ const trimmed = this.resourcePath?.trim() || '';
45527
+ this.isValid$.next(!!trimmed && this.isValidPath(trimmed));
45528
+ }
45529
+ getSettingsValue() {
45530
+ return { resourcePath: this.normalizedPath() };
45531
+ }
45532
+ onSave() {
45533
+ return this.getSettingsValue();
45534
+ }
45535
+ showInvalid() {
45536
+ const trimmed = this.resourcePath?.trim() || '';
45537
+ return !!trimmed && !this.isValidPath(trimmed);
45538
+ }
45539
+ normalizedPath() {
45540
+ const trimmed = this.resourcePath?.trim() || '';
45541
+ if (!trimmed)
45542
+ return '';
45543
+ if (trimmed.startsWith('/'))
45544
+ return trimmed;
45545
+ if (trimmed.startsWith('http://') || trimmed.startsWith('https://'))
45546
+ return trimmed;
45547
+ return `/${trimmed}`;
45548
+ }
45549
+ isValidPath(value) {
45550
+ if (value.startsWith('http://') || value.startsWith('https://'))
45551
+ return true;
45552
+ return /^\/?[a-zA-Z0-9][a-zA-Z0-9/_-]*$/.test(value);
45553
+ }
45554
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: ResourceQuickConnectComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
45555
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: ResourceQuickConnectComponent, isStandalone: true, selector: "praxis-resource-quick-connect", inputs: { resourcePath: "resourcePath" }, usesOnChanges: true, ngImport: i0, template: `
45556
+ <div class="pdx-quick-connect">
45557
+ <mat-form-field appearance="outline">
45558
+ <mat-label>Rota do recurso (API)</mat-label>
45559
+ <input
45560
+ matInput
45561
+ [(ngModel)]="resourcePath"
45562
+ (ngModelChange)="updateState()"
45563
+ placeholder="ex.: human-resources/departamentos"
45564
+ />
45565
+ <mat-icon matSuffix [praxisIcon]="'link'"></mat-icon>
45566
+ @if (showInvalid()) {
45567
+ <mat-error>Use apenas letras, números, /, - ou _.</mat-error>
45568
+ }
45569
+ </mat-form-field>
45570
+ <small class="pdx-quick-connect__hint">Conecte o componente à fonte de dados (ex.: /api/&lt;rota-do-recurso&gt;)</small>
45571
+ @if (normalizedPath() && normalizedPath() !== resourcePath) {
45572
+ <small class="pdx-quick-connect__hint">
45573
+ Rota normalizada: {{ normalizedPath() }}
45574
+ </small>
45575
+ }
45576
+ </div>
45577
+ `, isInline: true, styles: [".pdx-quick-connect{display:grid;gap:12px;padding:12px;border-radius:12px;border:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface);color:var(--md-sys-color-on-surface)}.pdx-quick-connect__hint{color:var(--md-sys-color-on-surface-variant);font-size:.9rem}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i4.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i4.MatLabel, selector: "mat-label" }, { kind: "directive", type: i4.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "directive", type: i4.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i5.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }] });
45578
+ }
45579
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: ResourceQuickConnectComponent, decorators: [{
45580
+ type: Component,
45581
+ args: [{ selector: 'praxis-resource-quick-connect', standalone: true, imports: [FormsModule, MatFormFieldModule, MatInputModule, MatIconModule, PraxisIconDirective], template: `
45582
+ <div class="pdx-quick-connect">
45583
+ <mat-form-field appearance="outline">
45584
+ <mat-label>Rota do recurso (API)</mat-label>
45585
+ <input
45586
+ matInput
45587
+ [(ngModel)]="resourcePath"
45588
+ (ngModelChange)="updateState()"
45589
+ placeholder="ex.: human-resources/departamentos"
45590
+ />
45591
+ <mat-icon matSuffix [praxisIcon]="'link'"></mat-icon>
45592
+ @if (showInvalid()) {
45593
+ <mat-error>Use apenas letras, números, /, - ou _.</mat-error>
45594
+ }
45595
+ </mat-form-field>
45596
+ <small class="pdx-quick-connect__hint">Conecte o componente à fonte de dados (ex.: /api/&lt;rota-do-recurso&gt;)</small>
45597
+ @if (normalizedPath() && normalizedPath() !== resourcePath) {
45598
+ <small class="pdx-quick-connect__hint">
45599
+ Rota normalizada: {{ normalizedPath() }}
45600
+ </small>
45601
+ }
45602
+ </div>
45603
+ `, styles: [".pdx-quick-connect{display:grid;gap:12px;padding:12px;border-radius:12px;border:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface);color:var(--md-sys-color-on-surface)}.pdx-quick-connect__hint{color:var(--md-sys-color-on-surface-variant);font-size:.9rem}\n"] }]
45604
+ }], propDecorators: { resourcePath: [{
45605
+ type: Input
45606
+ }] } });
45607
+
44148
45608
  /** Optional DI token used by SchemaViewer when input is not provided. */
44149
45609
  const SCHEMA_VIEWER_CONTEXT = new InjectionToken('SCHEMA_VIEWER_CONTEXT');
44150
45610
 
@@ -45059,4 +46519,4 @@ function provideHookWhitelist(allowed) {
45059
46519
  * Generated bundle index. Do not edit.
45060
46520
  */
45061
46521
 
45062
- export { API_CONFIG_STORAGE_OPTIONS, API_URL, ASYNC_CONFIG_STORAGE, AllowedFileTypes, AnalyticsPresentationResolver, AnalyticsSchemaContractService, AnalyticsStatsRequestBuilderService, ApiConfigStorage, ApiEndpoint, BUILTIN_PAGE_LAYOUT_PRESETS, BUILTIN_PAGE_THEME_PRESETS, BUILTIN_SHELL_PRESETS, COMPONENT_METADATA_REGISTRY_I18N_CONFIG, COMPONENT_METADATA_REGISTRY_I18N_NAMESPACE, CONFIG_STORAGE, CONNECTION_STORAGE, ComponentKeyService, ComponentMetadataRegistry, ComponentRuntimeProfileService, CompositionRuntimeFacade, CompositionValidatorService, ConsoleLoggerSink, CrudOperationResolutionService, DEFAULT_FIELD_SELECTOR_CONTROL_TYPE_MAP, DEFAULT_JSON_LOGIC_OPERATORS, DEFAULT_TABLE_CONFIG, DOMAIN_CATALOG_COMPONENT_CONTEXT_PACK, DOMAIN_CATALOG_CONTEXT_HINT_SCHEMA_VERSION, DYNAMIC_PAGE_AI_CAPABILITIES, DYNAMIC_PAGE_COMPONENT_CONTEXT_PACK, DYNAMIC_PAGE_CONFIG_EDITOR, DYNAMIC_PAGE_SHELL_EDITOR, DefaultLoadingRenderer, DeferredAsyncConfigStorage, DomainCatalogService, DomainKnowledgeService, DomainRuleService, DynamicFormService, DynamicWidgetLoaderDirective, DynamicWidgetPageComponent, EDITORIAL_ALLOWED_CONTENT_FORMATS, EDITORIAL_COMPLIANCE_PRESETS, EDITORIAL_EXTERNAL_LINK_REL, EDITORIAL_FORM_TEMPLATE_CATALOG, EDITORIAL_HTML_ENABLED, EDITORIAL_MARKDOWN_IMAGES_ENABLED, EDITORIAL_SOLUTION_CATALOG, EDITORIAL_SOLUTION_PRESETS, EDITORIAL_THEME_PRESETS, EDITORIAL_WIDGET_CONVENTION_INPUTS, EDITORIAL_WIDGET_TAG, EMPLOYEE_ONBOARDING_EDITORIAL_SOLUTION, EMPLOYEE_ONBOARDING_EDITORIAL_TEMPLATE, EMPLOYEE_ONBOARDING_GUIDED_EDITORIAL_SOLUTION, EMPLOYEE_ONBOARDING_GUIDED_EDITORIAL_TEMPLATE, EVENT_REGISTRATION_EDITORIAL_SOLUTION, EVENT_REGISTRATION_EDITORIAL_TEMPLATE, EmptyStateCardComponent, EnterpriseRuntimeContextService, ErrorMessageService, FIELD_METADATA_CAPABILITIES, FIELD_SELECTOR_REGISTRY_BASE, FIELD_SELECTOR_REGISTRY_DISABLE_DEFAULTS, FIELD_SELECTOR_REGISTRY_OVERRIDES, FORM_HOOKS, FORM_HOOKS_PRESETS, FORM_HOOKS_WHITELIST, FORM_HOOK_RESOLVERS, FieldControlType, FieldDataType, FieldSelectorRegistry, FormHooksRegistry, GLOBAL_ACTION_CATALOG, GLOBAL_ACTION_HANDLERS, GLOBAL_ACTION_UI_SCHEMAS, GLOBAL_ANALYTICS_SERVICE, GLOBAL_API_CLIENT, GLOBAL_CONFIG, GLOBAL_DIALOG_SERVICE, GLOBAL_ROUTE_GUARD_RESOLVER, GLOBAL_SURFACE_SERVICE, GLOBAL_TOAST_SERVICE, GenericCrudService, GlobalActionService, GlobalConfigService, INLINE_FILTER_ALIAS_TOKENS, INLINE_FILTER_CONTROL_TYPES, INLINE_FILTER_CONTROL_TYPE_SET, INLINE_FILTER_CONTROL_TYPE_VALUES, INLINE_FILTER_TOKEN_TO_BASE_CONTROL_TYPE, INLINE_FILTER_TOKEN_TO_CONTROL_TYPE, IconPickerService, IconPosition, IconSize, LOGGER_LEVEL_BY_ENV, LOGGER_LEVEL_PRIORITY, LoadingOrchestrator, LocalConnectionStorage, LocalStorageAsyncAdapter, LocalStorageCacheAdapter, LocalStorageConfigService, LoggerService, LoggerThrottleTracker, LoggerWarnOnceTracker, MemoryCacheAdapter, NestedPortCatalogService, NestedWidgetConfigAccessor, NumericFormat, OVERLAY_DECIDER_DEBUG, OVERLAY_DECISION_MATRIX, ObservabilityDashboardService, OverlayDeciderService, PRAXIS_ACTION_CONTROL_DEFAULTS, PRAXIS_ACTION_CONTROL_VARS, PRAXIS_COLLECTION_EXPORT_HTTP_OPTIONS, PRAXIS_COLLECTION_EXPORT_PROVIDER, PRAXIS_COLLECTION_SEARCH_DEFAULTS, PRAXIS_COLLECTION_SEARCH_VARS, PRAXIS_CORPORATE_SENSITIVE_KEYS, PRAXIS_DEFAULT_EXPORT_SECURITY_POLICY, PRAXIS_DEFAULT_OBSERVABILITY_ALERT_RULES, PRAXIS_DYNAMIC_PAGE_COMPONENT_METADATA, PRAXIS_ENTERPRISE_RUNTIME_CONTEXT_OPTIONS, PRAXIS_ENTERPRISE_RUNTIME_CONTEXT_READY, PRAXIS_EXPORT_FORMULA_PREFIXES, PRAXIS_EXPORT_SECURITY_POLICY, PRAXIS_FOOTER_LINKS_METADATA, PRAXIS_GLOBAL_ACTION_CATALOG, PRAXIS_GLOBAL_CONFIG_BOOTSTRAP_OPTIONS, PRAXIS_GLOBAL_CONFIG_BOOTSTRAP_READY, PRAXIS_GLOBAL_CONFIG_TENANT_RESOLVER, PRAXIS_HERO_BANNER_METADATA, PRAXIS_I18N_CONFIG, PRAXIS_I18N_TRANSLATOR, PRAXIS_JSON_LOGIC_OPERATORS, PRAXIS_LAYER_SCALE_DEFAULTS, PRAXIS_LAYER_SCALE_VARS, PRAXIS_LEGAL_NOTICE_METADATA, PRAXIS_LOADING_CTX, PRAXIS_LOADING_RENDERER, PRAXIS_LOGGER_CONFIG, PRAXIS_LOGGER_SINKS, PRAXIS_OBSERVABILITY_DASHBOARD_OPTIONS, PRAXIS_QUERY_FILTER_EXPRESSION_SCHEMA_VERSION, PRAXIS_RELATED_RESOURCE_OUTLET_COMPONENT_METADATA, PRAXIS_RELATED_RESOURCE_OUTLET_PORTS, PRAXIS_RICH_TEXT_BLOCK_METADATA, PRAXIS_TABLE_DETAIL_INLINE_NODE_RESOLVERS, PRAXIS_TABLE_DETAIL_INLINE_RENDERERS, PRAXIS_TABLE_DETAIL_RESOURCE_RESOLVER, PRAXIS_TELEMETRY_TRANSPORT, PRAXIS_THEME_SURFACE_DEFAULTS, PRAXIS_THEME_SURFACE_VARS, PRAXIS_USER_CONTEXT_SUMMARY_METADATA, PRIVACY_CONSENT_EDITORIAL_SOLUTION, PRIVACY_CONSENT_EDITORIAL_TEMPLATE, PraxisCollectionExportService, PraxisCore, PraxisFooterLinksComponent, PraxisGlobalErrorHandler, PraxisHeroBannerComponent, PraxisHttpCollectionExportProvider, PraxisI18nService, PraxisIconButtonComponent, PraxisIconDirective, PraxisIconPickerComponent, PraxisJsonLogicError, PraxisJsonLogicService, PraxisLayerScaleStyleService, PraxisLegalNoticeComponent, PraxisLoadingInterceptor, PraxisRelatedResourceOutletComponent, PraxisResourceIdentityComponent, PraxisRichTextBlockComponent, PraxisRuntimeComponentObservationRegistryService, PraxisSurfaceHostComponent, PraxisUserContextSummaryComponent, RESOURCE_DISCOVERY_I18N_CONFIG, RESOURCE_DISCOVERY_I18N_NAMESPACE, RULE_PROPERTY_SCHEMA, RelatedResourceSurfaceResolverService, RemoteConfigStorage, ResourceActionOpenAdapterService, ResourceDiscoveryService, ResourceQuickConnectComponent, ResourceRecordOpenError, ResourceRecordOpenService, ResourceSurfaceOpenAdapterService, SCHEMA_VIEWER_CONTEXT, SETTINGS_PANEL_BRIDGE, SETTINGS_PANEL_DATA, STEPPER_CONFIG_EDITOR, SURFACE_DRAWER_BRIDGE, SURFACE_DRAWER_CONTENT_DATA, SURFACE_DRAWER_REF, SURFACE_NAVIGATION_I18N_CONFIG, SURFACE_NAVIGATION_I18N_NAMESPACE, SURFACE_OPEN_I18N_CONFIG, SURFACE_OPEN_I18N_NAMESPACE, SURFACE_OPEN_PRESETS, SchemaMetadataClient, SchemaNormalizerService, SchemaViewerComponent, SurfaceBindingRuntimeService, SurfaceNavigationError, SurfaceOpenActionEditorComponent, SurfaceOpenMaterializerService, SurfaceOutletRegistryService, TABLE_CONFIG_EDITOR, TableConfigService, TelemetryLoggerSink, TelemetryService, ValidationPattern, WidgetPageStateRuntimeService, WidgetShellComponent, applyLocalCustomizations$2 as applyLocalCustomizations, applyLocalCustomizations$1 as applyLocalFormCustomizations, assertPraxisCollectionExportArtifact, assertPraxisRuntimeComponentObservationSerializable, buildAngularValidators, buildApiUrl, buildBaseColumnFromDef, buildBaseFormField, buildFormConfigFromEditorialTemplate, buildHeaders, buildPageKey, buildPraxisActionControlCss, buildPraxisCollectionSearchCss, buildPraxisEffectDistinctKey, buildPraxisLayerScaleCss, buildPraxisThemeSurfaceCss, buildSchemaId, buildSchemaIdStorageKeySegment, buildValidatorsFromValidatorOptions, cancelIfCpfInvalidHook, clampRange, classifyEntityLookupResult, clonePraxisRuntimeComponentObservation, cloneTableConfig, cnpjAlphaValidator, collapseWhitespace, composeHeadersWithVersion, conditionalAsyncValidator, convertFormLayoutToConfig, createCorporateLoggerConfig, createCorporateObservabilityOptions, createCpfCnpjValidator, createDefaultFormConfig, createDefaultTableConfig, createEmptyFormConfig, createEmptyRichContentDocument, createFieldLayoutItem, createPersistedPage, customAsyncValidatorFn, customValidatorFn, debounceAsyncValidator, deepMerge, domainKnowledgeTimelineToRichContentDocument, domainRuleTimelineToRichContentDocument, ensureIds, ensureNoConflictsHookFactory, ensurePageIds, escapePraxisExportCell, evaluateFieldAccess, extractNormalizedError, fetchWithETag, fileTypeValidator, fillUndefined, generateId, getDefaultFormHints, getEditorialCompliancePresetById, getEditorialFormTemplateById, getEditorialFormTemplateCatalog, getEditorialSolutionById, getEditorialSolutionCatalog, getEditorialSolutionPresetById, getEditorialThemePresetById, getEssentialConfig, getFieldMetadataCapabilities, getFormColumnFieldNames, getFormLayoutFieldNames, getGlobalActionCatalog, getGlobalActionPayloadActualType, getGlobalActionPayloadTypeIssue, getGlobalActionUiSchema, getMissingGlobalActionPayloadKeys, getPraxisTableCellVisualizationConstraint, getPraxisTableCellVisualizationGuidance, getReferencedFieldMetadata, getRequiredGlobalActionPayloadKeys, getTextTransformer, hasMeaningfulGlobalActionPayloadValue, hasPraxisCollectionExportArtifact, interpolatePraxisTranslation, isAllowedEditorialContentFormat, isAllowedEditorialHref, isCssTextTransform, isDomainRuleSnapshotProblemResponse, isEditorialComponentMeta, isEntityLookupMultiplePayloadMode, isEntityLookupPayloadMode, isEntityLookupPayloadModeCompatible, isEntityLookupResultSelectable, isEntityLookupSinglePayloadMode, isFormLayoutItem, isGlobalActionRef, isInlineFilterControlType, isLookupDialogSize, isLookupFilterFieldType, isLookupFilterOperator, isPraxisI18nMessageDescriptor, isPraxisPresentationVisualizationTableSafe, isPraxisRuntimeGlobalActionEffect, isProgrammaticDateRangePreset, isRangeValidForFilter, isRequiredGlobalActionParamPayloadMissing, isRequiredGlobalActionPayloadMissing, isStaticDateRangePreset, isSurfaceNavigationError, isTableConfigV2, isValidFormConfig, isValidTableConfig, legacyCnpjValidator, legacyCpfValidator, logOnErrorHook, mapFieldDefinitionToMetadata, mapFieldDefinitionsToMetadata, matchFieldValidator, materializeFormLayoutFromMetadata, materializeResourceIdentity, maxFileSizeValidator, mergeFieldMetadata, mergePraxisI18nConfigs, mergeTableConfigs, migrateFormLayoutRule, migrateLegacyCompositionLink, migrateLegacyCompositionLinks, minWordsValidator, normalizeControlTypeKey, normalizeControlTypeToken, normalizeEditorialLink, normalizeEnd, normalizeFieldAccessMetadata, normalizeFieldConstraints, normalizeFieldPresentation, normalizeFormConfig, normalizeFormLayoutItems, normalizeFormMetadata, normalizeGlobalActionRef$1 as normalizeGlobalActionRef, normalizeLayoutPolicy, normalizeLookupFilterRequest, normalizePath, normalizePraxisDataQueryContext, normalizePraxisEffectPolicy, normalizePraxisPresentationVisualization, normalizePraxisQueryFilterExpression, normalizePraxisQueryFilterNode, normalizeReactiveDeterminations, normalizeResourceAvailabilityReasonCode, normalizeResourceIdentityContract, normalizeStart, normalizeSurfaceOperationContext, normalizeUnknownError, normalizeWidgetEventPath, notifySuccessHook, parseJsonResponseOrEmpty, praxisLoadingInterceptorFn, prefillFromContextHook, projectGroupedCommandPartialRows, provideDefaultFormHooks, provideFieldSelectorRegistryBase, provideFieldSelectorRegistryOverride, provideFieldSelectorRegistryRuntime, provideFormHookPresets, provideFormHooks, provideGlobalActionCatalog, provideGlobalActionHandler, provideGlobalConfig, provideGlobalConfigReady, provideGlobalConfigSeed, provideGlobalConfigTenant, provideHookResolvers, provideHookWhitelist, provideOverlayDecisionMatrix, providePraxisAnalyticsGlobalActions, providePraxisCollectionExportProvider, providePraxisDynamicPageMetadata, providePraxisEnterpriseRuntimeContext, providePraxisFooterLinksMetadata, providePraxisGlobalActionCatalog, providePraxisGlobalActions, providePraxisGlobalConfigBootstrap, providePraxisHeroBannerMetadata, providePraxisHttpCollectionExportProvider, providePraxisHttpLoading, providePraxisI18n, providePraxisI18nConfig, providePraxisI18nTranslator, providePraxisIconDefaults, providePraxisJsonLogicOperator, providePraxisJsonLogicOperatorOverride, providePraxisLegalNoticeMetadata, providePraxisLoadingDefaults, providePraxisLogging, providePraxisRelatedResourceOutletMetadata, providePraxisRichTextBlockMetadata, providePraxisToastGlobalActions, providePraxisUserContextSummaryMetadata, provideRemoteGlobalConfig, readPraxisExportValue, reconcileFilterConfig, reconcileFormConfig, reconcileTableConfig, registerPraxisRuntimeComponentObservation, removeDiacritics, renderPraxisPresentationVisualizationHtml, reportTelemetryHookFactory, requiredCheckedValidator, requiredPresenceValidator, resolveBuiltinPresets, resolveColumnTypeFromFieldDefinition, resolveControlTypeAlias, resolveDateRangeShortcutPreset, resolveDateRangeShortcutPresets, resolveDefaultValuePresentationFormat, resolveEntityLookupPayloadMode, resolveFieldPresentation, resolveGroupedCommandPartialRowSpans, resolveHidden, resolveInlineFilterControlType, resolveInlineFilterControlTypeToBaseControlType, resolveLoggerConfig, resolveObservabilityOptions, resolveOffset, resolveOrder, resolvePraxisCollectionExportItems, resolvePraxisExportFields, resolvePraxisExportScope, resolvePraxisFilterCriteria, resolvePraxisI18nDocument, resolveResourceAvailabilityReasonKey, resolveResourceIdentityContract, resolveSpan, resolveTextMaskFormat, resolveTextMaskFormatFromFieldDefinition, resolveValuePresentation, resolveValuePresentationLocale, serializeEntityLookupValueForPayload, serializeOptionSourceFilterRequest, serializePraxisCollectionToCsv, serializePraxisCollectionToExcel, serializePraxisCollectionToJson, slugify, staticDateRangePresetToPreset, stripMasksHook, supportsImplicitValuePresentation, syncWithServerMetadata, toCamel, toCapitalize, toKebab, toPascal, toSentenceCase, toSnake, toTitleCase, translateResourceAvailabilityReason, translateResourceDiscoveryText, translateSurfaceNavigationRejected, translateUnavailableWorkflowMessage, trim, uniqueAsyncValidator, urlValidator, validateGlobalActionRef, validateGlobalActionRefs, withFormConfigSections, withMessage, withPraxisHttpLoading };
46522
+ export { API_CONFIG_STORAGE_OPTIONS, API_URL, ASYNC_CONFIG_STORAGE, AllowedFileTypes, AnalyticsPresentationResolver, AnalyticsSchemaContractService, AnalyticsStatsRequestBuilderService, ApiConfigStorage, ApiEndpoint, BUILTIN_PAGE_LAYOUT_PRESETS, BUILTIN_PAGE_THEME_PRESETS, BUILTIN_SHELL_PRESETS, COMPONENT_METADATA_REGISTRY_I18N_CONFIG, COMPONENT_METADATA_REGISTRY_I18N_NAMESPACE, CONFIG_STORAGE, CONNECTION_STORAGE, ComponentAuthoringManifestProjectionError, ComponentKeyService, ComponentMetadataRegistry, ComponentRuntimeProfileService, CompositionRuntimeFacade, CompositionValidatorService, ConsoleLoggerSink, CrudOperationResolutionService, DEFAULT_FIELD_SELECTOR_CONTROL_TYPE_MAP, DEFAULT_JSON_LOGIC_OPERATORS, DEFAULT_TABLE_CONFIG, DOMAIN_CATALOG_COMPONENT_CONTEXT_PACK, DOMAIN_CATALOG_CONTEXT_HINT_SCHEMA_VERSION, DYNAMIC_PAGE_AI_CAPABILITIES, DYNAMIC_PAGE_COMPONENT_CONTEXT_PACK, DYNAMIC_PAGE_CONFIG_EDITOR, DYNAMIC_PAGE_SHELL_EDITOR, DefaultLoadingRenderer, DeferredAsyncConfigStorage, DomainCatalogService, DomainKnowledgeService, DomainRuleService, DynamicFormService, DynamicWidgetLoaderDirective, DynamicWidgetPageComponent, EDITORIAL_ALLOWED_CONTENT_FORMATS, EDITORIAL_COMPLIANCE_PRESETS, EDITORIAL_EXTERNAL_LINK_REL, EDITORIAL_FORM_TEMPLATE_CATALOG, EDITORIAL_HTML_ENABLED, EDITORIAL_MARKDOWN_IMAGES_ENABLED, EDITORIAL_SOLUTION_CATALOG, EDITORIAL_SOLUTION_PRESETS, EDITORIAL_THEME_PRESETS, EDITORIAL_WIDGET_CONVENTION_INPUTS, EDITORIAL_WIDGET_TAG, EMPLOYEE_ONBOARDING_EDITORIAL_SOLUTION, EMPLOYEE_ONBOARDING_EDITORIAL_TEMPLATE, EMPLOYEE_ONBOARDING_GUIDED_EDITORIAL_SOLUTION, EMPLOYEE_ONBOARDING_GUIDED_EDITORIAL_TEMPLATE, EVENT_REGISTRATION_EDITORIAL_SOLUTION, EVENT_REGISTRATION_EDITORIAL_TEMPLATE, EmptyStateCardComponent, EnterpriseRuntimeContextService, ErrorMessageService, FIELD_METADATA_CAPABILITIES, FIELD_SELECTOR_REGISTRY_BASE, FIELD_SELECTOR_REGISTRY_DISABLE_DEFAULTS, FIELD_SELECTOR_REGISTRY_OVERRIDES, FORM_HOOKS, FORM_HOOKS_PRESETS, FORM_HOOKS_WHITELIST, FORM_HOOK_RESOLVERS, FieldControlType, FieldDataType, FieldSelectorRegistry, FormHooksRegistry, GLOBAL_ACTION_CATALOG, GLOBAL_ACTION_HANDLERS, GLOBAL_ACTION_UI_SCHEMAS, GLOBAL_ANALYTICS_SERVICE, GLOBAL_API_CLIENT, GLOBAL_CONFIG, GLOBAL_DIALOG_SERVICE, GLOBAL_ROUTE_GUARD_RESOLVER, GLOBAL_SURFACE_SERVICE, GLOBAL_TOAST_SERVICE, GenericCrudService, GlobalActionService, GlobalConfigService, INLINE_FILTER_ALIAS_TOKENS, INLINE_FILTER_CONTROL_TYPES, INLINE_FILTER_CONTROL_TYPE_SET, INLINE_FILTER_CONTROL_TYPE_VALUES, INLINE_FILTER_TOKEN_TO_BASE_CONTROL_TYPE, INLINE_FILTER_TOKEN_TO_CONTROL_TYPE, IconPickerService, IconPosition, IconSize, LOGGER_LEVEL_BY_ENV, LOGGER_LEVEL_PRIORITY, LoadingOrchestrator, LocalConnectionStorage, LocalStorageAsyncAdapter, LocalStorageCacheAdapter, LocalStorageConfigService, LoggerService, LoggerThrottleTracker, LoggerWarnOnceTracker, MemoryCacheAdapter, NestedPortCatalogService, NestedWidgetConfigAccessor, NumericFormat, OVERLAY_DECIDER_DEBUG, OVERLAY_DECISION_MATRIX, ObservabilityDashboardService, OverlayDeciderService, PRAXIS_ACTION_CONTROL_DEFAULTS, PRAXIS_ACTION_CONTROL_VARS, PRAXIS_COLLECTION_EXPORT_HTTP_OPTIONS, PRAXIS_COLLECTION_EXPORT_PROVIDER, PRAXIS_COLLECTION_SEARCH_DEFAULTS, PRAXIS_COLLECTION_SEARCH_VARS, PRAXIS_CORPORATE_SENSITIVE_KEYS, PRAXIS_DEFAULT_EXPORT_SECURITY_POLICY, PRAXIS_DEFAULT_OBSERVABILITY_ALERT_RULES, PRAXIS_DYNAMIC_PAGE_COMPONENT_METADATA, PRAXIS_ENTERPRISE_RUNTIME_CONTEXT_OPTIONS, PRAXIS_ENTERPRISE_RUNTIME_CONTEXT_READY, PRAXIS_EXPORT_FORMULA_PREFIXES, PRAXIS_EXPORT_SECURITY_POLICY, PRAXIS_FOOTER_LINKS_METADATA, PRAXIS_GLOBAL_ACTION_CATALOG, PRAXIS_GLOBAL_CONFIG_BOOTSTRAP_OPTIONS, PRAXIS_GLOBAL_CONFIG_BOOTSTRAP_READY, PRAXIS_GLOBAL_CONFIG_TENANT_RESOLVER, PRAXIS_HERO_BANNER_METADATA, PRAXIS_I18N_CONFIG, PRAXIS_I18N_TRANSLATOR, PRAXIS_JSON_LOGIC_OPERATORS, PRAXIS_LAYER_SCALE_DEFAULTS, PRAXIS_LAYER_SCALE_VARS, PRAXIS_LEGAL_NOTICE_METADATA, PRAXIS_LOADING_CTX, PRAXIS_LOADING_RENDERER, PRAXIS_LOGGER_CONFIG, PRAXIS_LOGGER_SINKS, PRAXIS_OBSERVABILITY_DASHBOARD_OPTIONS, PRAXIS_QUERY_FILTER_EXPRESSION_SCHEMA_VERSION, PRAXIS_RELATED_RESOURCE_OUTLET_AUTHORING_MANIFEST, PRAXIS_RELATED_RESOURCE_OUTLET_COMPONENT_METADATA, PRAXIS_RELATED_RESOURCE_OUTLET_PORTS, PRAXIS_RICH_TEXT_BLOCK_METADATA, PRAXIS_TABLE_DETAIL_INLINE_NODE_RESOLVERS, PRAXIS_TABLE_DETAIL_INLINE_RENDERERS, PRAXIS_TABLE_DETAIL_RESOURCE_RESOLVER, PRAXIS_TELEMETRY_TRANSPORT, PRAXIS_THEME_SURFACE_DEFAULTS, PRAXIS_THEME_SURFACE_VARS, PRAXIS_USER_CONTEXT_SUMMARY_METADATA, PRIVACY_CONSENT_EDITORIAL_SOLUTION, PRIVACY_CONSENT_EDITORIAL_TEMPLATE, PraxisCollectionExportService, PraxisCore, PraxisFooterLinksComponent, PraxisGlobalErrorHandler, PraxisHeroBannerComponent, PraxisHttpCollectionExportProvider, PraxisI18nService, PraxisIconButtonComponent, PraxisIconDirective, PraxisIconPickerComponent, PraxisJsonLogicError, PraxisJsonLogicService, PraxisLayerScaleStyleService, PraxisLegalNoticeComponent, PraxisLoadingInterceptor, PraxisRelatedResourceOutletComponent, PraxisRelatedResourceOutletConfigEditorComponent, PraxisResourceIdentityComponent, PraxisRichTextBlockComponent, PraxisRuntimeComponentObservationRegistryService, PraxisSurfaceHostComponent, PraxisUserContextSummaryComponent, RESOURCE_DISCOVERY_I18N_CONFIG, RESOURCE_DISCOVERY_I18N_NAMESPACE, RULE_PROPERTY_SCHEMA, RelatedResourceSurfaceResolverService, RemoteConfigStorage, ResourceActionOpenAdapterService, ResourceDiscoveryService, ResourceQuickConnectComponent, ResourceRecordOpenError, ResourceRecordOpenService, ResourceSurfaceOpenAdapterService, SCHEMA_VIEWER_CONTEXT, SETTINGS_PANEL_BRIDGE, SETTINGS_PANEL_DATA, STEPPER_CONFIG_EDITOR, SURFACE_DRAWER_BRIDGE, SURFACE_DRAWER_CONTENT_DATA, SURFACE_DRAWER_REF, SURFACE_NAVIGATION_I18N_CONFIG, SURFACE_NAVIGATION_I18N_NAMESPACE, SURFACE_OPEN_I18N_CONFIG, SURFACE_OPEN_I18N_NAMESPACE, SURFACE_OPEN_PRESETS, SchemaMetadataClient, SchemaNormalizerService, SchemaViewerComponent, SurfaceBindingRuntimeService, SurfaceNavigationError, SurfaceOpenActionEditorComponent, SurfaceOpenMaterializerService, SurfaceOutletRegistryService, TABLE_CONFIG_EDITOR, TableConfigService, TelemetryLoggerSink, TelemetryService, ValidationPattern, WidgetPageStateRuntimeService, WidgetShellComponent, applyLocalCustomizations$2 as applyLocalCustomizations, applyLocalCustomizations$1 as applyLocalFormCustomizations, assertPraxisCollectionExportArtifact, assertPraxisRuntimeComponentObservationSerializable, buildAngularValidators, buildApiUrl, buildBaseColumnFromDef, buildBaseFormField, buildFormConfigFromEditorialTemplate, buildHeaders, buildPageKey, buildPraxisActionControlCss, buildPraxisCollectionSearchCss, buildPraxisEffectDistinctKey, buildPraxisLayerScaleCss, buildPraxisThemeSurfaceCss, buildSchemaId, buildSchemaIdStorageKeySegment, buildValidatorsFromValidatorOptions, cancelIfCpfInvalidHook, clampRange, classifyEntityLookupResult, clonePraxisRuntimeComponentObservation, cloneTableConfig, cnpjAlphaValidator, collapseWhitespace, composeHeadersWithVersion, conditionalAsyncValidator, convertFormLayoutToConfig, createCorporateLoggerConfig, createCorporateObservabilityOptions, createCpfCnpjValidator, createDefaultFormConfig, createDefaultTableConfig, createEmptyFormConfig, createEmptyRichContentDocument, createFieldLayoutItem, createPersistedPage, customAsyncValidatorFn, customValidatorFn, debounceAsyncValidator, deepMerge, domainKnowledgeTimelineToRichContentDocument, domainRuleTimelineToRichContentDocument, ensureIds, ensureNoConflictsHookFactory, ensurePageIds, escapePraxisExportCell, evaluateFieldAccess, extractNormalizedError, fetchWithETag, fileTypeValidator, fillUndefined, generateId, getDefaultFormHints, getEditorialCompliancePresetById, getEditorialFormTemplateById, getEditorialFormTemplateCatalog, getEditorialSolutionById, getEditorialSolutionCatalog, getEditorialSolutionPresetById, getEditorialThemePresetById, getEssentialConfig, getFieldMetadataCapabilities, getFormColumnFieldNames, getFormLayoutFieldNames, getGlobalActionCatalog, getGlobalActionPayloadActualType, getGlobalActionPayloadTypeIssue, getGlobalActionUiSchema, getMissingGlobalActionPayloadKeys, getPraxisTableCellVisualizationConstraint, getPraxisTableCellVisualizationGuidance, getReferencedFieldMetadata, getRequiredGlobalActionPayloadKeys, getTextTransformer, hasMeaningfulGlobalActionPayloadValue, hasPraxisCollectionExportArtifact, interpolatePraxisTranslation, isAllowedEditorialContentFormat, isAllowedEditorialHref, isCssTextTransform, isDomainRuleSnapshotProblemResponse, isEditorialComponentMeta, isEntityLookupMultiplePayloadMode, isEntityLookupPayloadMode, isEntityLookupPayloadModeCompatible, isEntityLookupResultSelectable, isEntityLookupSinglePayloadMode, isFormLayoutItem, isGlobalActionRef, isInlineFilterControlType, isLookupDialogSize, isLookupFilterFieldType, isLookupFilterOperator, isPraxisI18nMessageDescriptor, isPraxisPresentationVisualizationTableSafe, isPraxisRuntimeGlobalActionEffect, isProgrammaticDateRangePreset, isRangeValidForFilter, isRequiredGlobalActionParamPayloadMissing, isRequiredGlobalActionPayloadMissing, isStaticDateRangePreset, isSurfaceNavigationError, isTableConfigV2, isValidFormConfig, isValidTableConfig, legacyCnpjValidator, legacyCpfValidator, logOnErrorHook, mapFieldDefinitionToMetadata, mapFieldDefinitionsToMetadata, matchFieldValidator, materializeFormLayoutFromMetadata, materializeResourceIdentity, maxFileSizeValidator, mergeFieldMetadata, mergePraxisI18nConfigs, mergeTableConfigs, migrateFormLayoutRule, migrateLegacyCompositionLink, migrateLegacyCompositionLinks, minWordsValidator, normalizeControlTypeKey, normalizeControlTypeToken, normalizeEditorialLink, normalizeEnd, normalizeFieldAccessMetadata, normalizeFieldConstraints, normalizeFieldPresentation, normalizeFormConfig, normalizeFormLayoutItems, normalizeFormMetadata, normalizeGlobalActionRef$1 as normalizeGlobalActionRef, normalizeLayoutPolicy, normalizeLookupFilterRequest, normalizePath, normalizePraxisDataQueryContext, normalizePraxisEffectPolicy, normalizePraxisPresentationVisualization, normalizePraxisQueryFilterExpression, normalizePraxisQueryFilterNode, normalizeReactiveDeterminations, normalizeResourceAvailabilityReasonCode, normalizeResourceIdentityContract, normalizeStart, normalizeSurfaceOperationContext, normalizeUnknownError, normalizeWidgetEventPath, notifySuccessHook, parseJsonResponseOrEmpty, praxisLoadingInterceptorFn, prefillFromContextHook, projectComponentAuthoringManifest, projectGroupedCommandPartialRows, provideDefaultFormHooks, provideFieldSelectorRegistryBase, provideFieldSelectorRegistryOverride, provideFieldSelectorRegistryRuntime, provideFormHookPresets, provideFormHooks, provideGlobalActionCatalog, provideGlobalActionHandler, provideGlobalConfig, provideGlobalConfigReady, provideGlobalConfigSeed, provideGlobalConfigTenant, provideHookResolvers, provideHookWhitelist, provideOverlayDecisionMatrix, providePraxisAnalyticsGlobalActions, providePraxisCollectionExportProvider, providePraxisDynamicPageMetadata, providePraxisEnterpriseRuntimeContext, providePraxisFooterLinksMetadata, providePraxisGlobalActionCatalog, providePraxisGlobalActions, providePraxisGlobalConfigBootstrap, providePraxisHeroBannerMetadata, providePraxisHttpCollectionExportProvider, providePraxisHttpLoading, providePraxisI18n, providePraxisI18nConfig, providePraxisI18nTranslator, providePraxisIconDefaults, providePraxisJsonLogicOperator, providePraxisJsonLogicOperatorOverride, providePraxisLegalNoticeMetadata, providePraxisLoadingDefaults, providePraxisLogging, providePraxisRelatedResourceOutletMetadata, providePraxisRichTextBlockMetadata, providePraxisToastGlobalActions, providePraxisUserContextSummaryMetadata, provideRemoteGlobalConfig, readPraxisExportValue, reconcileFilterConfig, reconcileFormConfig, reconcileTableConfig, registerPraxisRuntimeComponentObservation, removeDiacritics, renderPraxisPresentationVisualizationHtml, reportTelemetryHookFactory, requiredCheckedValidator, requiredPresenceValidator, resolveBuiltinPresets, resolveColumnTypeFromFieldDefinition, resolveControlTypeAlias, resolveDateRangeShortcutPreset, resolveDateRangeShortcutPresets, resolveDefaultValuePresentationFormat, resolveEntityLookupPayloadMode, resolveFieldPresentation, resolveGroupedCommandPartialRowSpans, resolveHidden, resolveInlineFilterControlType, resolveInlineFilterControlTypeToBaseControlType, resolveLoggerConfig, resolveObservabilityOptions, resolveOffset, resolveOrder, resolvePraxisCollectionExportItems, resolvePraxisExportFields, resolvePraxisExportScope, resolvePraxisFilterCriteria, resolvePraxisI18nDocument, resolveResourceAvailabilityReasonKey, resolveResourceIdentityContract, resolveSpan, resolveTextMaskFormat, resolveTextMaskFormatFromFieldDefinition, resolveValuePresentation, resolveValuePresentationLocale, serializeEntityLookupValueForPayload, serializeOptionSourceFilterRequest, serializePraxisCollectionToCsv, serializePraxisCollectionToExcel, serializePraxisCollectionToJson, slugify, staticDateRangePresetToPreset, stripMasksHook, supportsImplicitValuePresentation, syncWithServerMetadata, toCamel, toCapitalize, toKebab, toPascal, toSentenceCase, toSnake, toTitleCase, translateResourceAvailabilityReason, translateResourceDiscoveryText, translateSurfaceNavigationRejected, translateUnavailableWorkflowMessage, trim, uniqueAsyncValidator, urlValidator, validateGlobalActionRef, validateGlobalActionRefs, withFormConfigSections, withMessage, withPraxisHttpLoading };