@praxisui/table 1.0.0-beta.54 → 1.0.0-beta.56

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.
@@ -5,15 +5,15 @@ import { CommonModule } from '@angular/common';
5
5
  import * as i8$1 from '@angular/material/table';
6
6
  import { MatTableDataSource, MatTableModule, MatTable } from '@angular/material/table';
7
7
  import { HttpContext } from '@angular/common/http';
8
- import * as i19 from '@angular/material/paginator';
8
+ import * as i18 from '@angular/material/paginator';
9
9
  import { MatPaginatorModule, MatPaginator } from '@angular/material/paginator';
10
- import * as i21 from '@angular/material/sort';
10
+ import * as i20 from '@angular/material/sort';
11
11
  import { MatSortModule, MatSort } from '@angular/material/sort';
12
12
  import * as i3 from '@angular/material/button';
13
13
  import { MatButtonModule } from '@angular/material/button';
14
14
  import * as i5 from '@angular/material/icon';
15
15
  import { MatIconModule } from '@angular/material/icon';
16
- import * as i5$1 from '@angular/material/menu';
16
+ import * as i17 from '@angular/material/menu';
17
17
  import { MatMenuModule } from '@angular/material/menu';
18
18
  import * as i6$1 from '@angular/material/slide-toggle';
19
19
  import { MatSlideToggleModule } from '@angular/material/slide-toggle';
@@ -23,12 +23,12 @@ import * as i2$1 from '@angular/material/snack-bar';
23
23
  import { MatSnackBarModule, MatSnackBar } from '@angular/material/snack-bar';
24
24
  import * as i9 from '@angular/material/checkbox';
25
25
  import { MatCheckboxModule } from '@angular/material/checkbox';
26
- import * as i14 from '@angular/material/badge';
26
+ import * as i15$2 from '@angular/material/badge';
27
27
  import { MatBadgeModule } from '@angular/material/badge';
28
28
  import * as i1$1 from '@angular/forms';
29
29
  import { FormsModule, ReactiveFormsModule, Validators, FormGroup, FormControl } from '@angular/forms';
30
30
  import { SelectionModel } from '@angular/cdk/collections';
31
- import * as i13 from '@angular/cdk/drag-drop';
31
+ import * as i12 from '@angular/cdk/drag-drop';
32
32
  import { moveItemInArray, DragDropModule } from '@angular/cdk/drag-drop';
33
33
  import { Subject, debounceTime, takeUntil, of, firstValueFrom, BehaviorSubject, take as take$1 } from 'rxjs';
34
34
  import * as i1 from '@praxisui/core';
@@ -42,7 +42,7 @@ import * as i6 from '@angular/material/form-field';
42
42
  import { MatFormFieldModule } from '@angular/material/form-field';
43
43
  import * as i7 from '@angular/material/input';
44
44
  import { MatInputModule } from '@angular/material/input';
45
- import * as i5$2 from '@angular/material/select';
45
+ import * as i5$1 from '@angular/material/select';
46
46
  import { MatSelectModule } from '@angular/material/select';
47
47
  import * as i3$1 from '@praxisui/settings-panel';
48
48
  import { SettingsPanelService, SETTINGS_PANEL_DATA, SETTINGS_PANEL_REF } from '@praxisui/settings-panel';
@@ -62,20 +62,20 @@ import { MatChipsModule } from '@angular/material/chips';
62
62
  import * as i1$3 from '@angular/material/dialog';
63
63
  import { MatDialogModule } from '@angular/material/dialog';
64
64
  import { distinctUntilChanged, debounceTime as debounceTime$1, take, map, startWith, takeUntil as takeUntil$1 } from 'rxjs/operators';
65
- import * as i15$2 from '@angular/material/datepicker';
65
+ import * as i15$3 from '@angular/material/datepicker';
66
66
  import { MatDatepickerModule } from '@angular/material/datepicker';
67
67
  import { MatNativeDateModule, MatOptionModule } from '@angular/material/core';
68
- import * as i17 from '@angular/material/autocomplete';
68
+ import * as i17$1 from '@angular/material/autocomplete';
69
69
  import { MatAutocompleteModule } from '@angular/material/autocomplete';
70
70
  import { toCellClassAndStyle, RuleEffectsPanelComponent } from '@praxisui/table-rule-builder';
71
- import { DynamicFieldLoaderDirective, supportsClearButtonControlType, MaterialRatingComponent } from '@praxisui/dynamic-fields';
72
- import * as i15$3 from '@angular/material/progress-bar';
71
+ import { DynamicFieldLoaderDirective, supportsClearButtonControlType } from '@praxisui/dynamic-fields';
72
+ import * as i15$4 from '@angular/material/progress-bar';
73
73
  import { MatProgressBarModule } from '@angular/material/progress-bar';
74
- import * as i12 from '@angular/cdk/overlay';
74
+ import * as i11$1 from '@angular/cdk/overlay';
75
75
  import { OverlayModule, CdkOverlayOrigin } from '@angular/cdk/overlay';
76
76
  import { A11yModule } from '@angular/cdk/a11y';
77
77
  import * as i6$2 from '@angular/router';
78
- import * as i11$1 from '@angular/cdk/scrolling';
78
+ import * as i10$3 from '@angular/cdk/scrolling';
79
79
  import { ScrollingModule } from '@angular/cdk/scrolling';
80
80
  import * as i6$3 from '@praxisui/dialog';
81
81
 
@@ -2192,7 +2192,7 @@ class PraxisTableToolbar {
2192
2192
  }
2193
2193
  </div>
2194
2194
  </mat-toolbar>
2195
- `, isInline: true, styles: [":host{display:block}.praxis-toolbar{background:transparent;box-shadow:none;padding:var(--pfx-toolbar-pad-y, 6px) var(--pfx-toolbar-pad-x, 12px);min-height:var(--pfx-filter-h, 44px);display:flex;flex-direction:row;align-items:flex-start;gap:8px;flex-wrap:wrap}.praxis-toolbar.mat-toolbar-single-row,.praxis-toolbar .mat-toolbar-row{height:auto}.praxis-toolbar.mat-toolbar-multiple-rows{min-height:var(--pfx-filter-h, 44px)}.toolbar-main{display:flex;align-items:stretch;min-width:0;gap:8px;min-height:var(--pfx-filter-h, 44px);flex:1 1 auto}.toolbar-actions{display:flex;align-items:center;justify-content:flex-end;gap:8px;min-height:var(--pfx-filter-h, 44px);flex:0 0 auto;margin-left:auto}.actions-group{display:flex;align-items:center;gap:8px}.action-btn{height:40px}.action-btn--fab{width:48px;height:48px}.pfx-tonal{background:var(--md-sys-color-secondary-container);color:var(--md-sys-color-on-secondary-container)}.pfx-tonal:hover{background:var(--md-sys-color-secondary-container)}.mobile-actions{display:none;align-items:center;gap:8px}.overflow-trigger{height:40px}.end-actions{display:flex;align-items:center;gap:8px}@media(min-width:1024px){.toolbar-actions{justify-content:flex-end}}@media(max-width:1023px){.actions-group{display:none}.mobile-actions{display:flex}.toolbar-actions{justify-content:flex-end}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: MatToolbarModule }, { kind: "component", type: i2.MatToolbar, selector: "mat-toolbar", inputs: ["color"], exportAs: ["matToolbar"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3.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: "component", type: i3.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i3.MatFabButton, selector: "button[mat-fab], a[mat-fab], button[matFab], a[matFab]", inputs: ["extended"], exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i5.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }, { kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i5$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: i5$1.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i5$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: i10.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }] });
2195
+ `, isInline: true, styles: [":host{display:block}.praxis-toolbar{background:transparent;box-shadow:none;padding:var(--pfx-toolbar-pad-y, 6px) var(--pfx-toolbar-pad-x, 12px);min-height:var(--pfx-filter-h, 44px);display:flex;flex-direction:row;align-items:flex-start;gap:8px;flex-wrap:wrap}.praxis-toolbar.mat-toolbar-single-row,.praxis-toolbar .mat-toolbar-row{height:auto}.praxis-toolbar.mat-toolbar-multiple-rows{min-height:var(--pfx-filter-h, 44px)}.toolbar-main{display:flex;align-items:stretch;min-width:0;gap:8px;min-height:var(--pfx-filter-h, 44px);flex:1 1 auto}.toolbar-actions{display:flex;align-items:center;justify-content:flex-end;gap:8px;min-height:var(--pfx-filter-h, 44px);flex:0 0 auto;margin-left:auto}.actions-group{display:flex;align-items:center;gap:8px}.action-btn{height:40px}.action-btn--fab{width:48px;height:48px}.pfx-tonal{background:var(--md-sys-color-secondary-container);color:var(--md-sys-color-on-secondary-container)}.pfx-tonal:hover{background:var(--md-sys-color-secondary-container)}.mobile-actions{display:none;align-items:center;gap:8px}.overflow-trigger{height:40px}.end-actions{display:flex;align-items:center;gap:8px}@media(min-width:1024px){.toolbar-actions{justify-content:flex-end}}@media(max-width:1023px){.actions-group{display:none}.mobile-actions{display:flex}.toolbar-actions{justify-content:flex-end}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: MatToolbarModule }, { kind: "component", type: i2.MatToolbar, selector: "mat-toolbar", inputs: ["color"], exportAs: ["matToolbar"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3.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: "component", type: i3.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i3.MatFabButton, selector: "button[mat-fab], a[mat-fab], button[matFab], a[matFab]", inputs: ["extended"], exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i5.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }, { kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i17.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: i17.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i17.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: i10.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }] });
2196
2196
  }
2197
2197
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: PraxisTableToolbar, decorators: [{
2198
2198
  type: Component,
@@ -4121,7 +4121,7 @@ class VisualFormulaBuilderComponent {
4121
4121
  </div>
4122
4122
  </mat-expansion-panel>
4123
4123
  </div>
4124
- `, isInline: true, styles: [":host{--vfb-primary: var(--md-sys-color-primary);--vfb-primary-container: var(--md-sys-color-primary-container);--vfb-on-primary-container: var(--md-sys-color-on-primary-container);--vfb-surface-container-low: var(--md-sys-color-surface-container-low);--vfb-surface-container: var(--md-sys-color-surface-container);--vfb-outline: var(--md-sys-color-outline);--vfb-on-surface-variant: var(--md-sys-color-on-surface-variant);--vfb-error: var(--md-sys-color-error);--vfb-error-container: var(--md-sys-color-error-container);--vfb-on-error-container: var(--md-sys-color-on-error-container)}.visual-formula-builder{display:flex;flex-direction:column;gap:16px}.formula-type-card,.parameters-card,.expression-preview-card{background-color:var(--vfb-surface-container-low)}.compact-header{padding-bottom:8px;align-items:center}.compact-header .mat-mdc-card-title{font-size:1.1rem;margin:0;line-height:1.2}.compact-header .mat-mdc-card-subtitle{font-size:.875rem;margin:0}.compact-header .mat-mdc-card-avatar{align-self:center}.formula-icon,.params-icon,.preview-icon{background-color:var(--vfb-primary-container);color:var(--vfb-on-primary-container);border-radius:50%;width:36px;height:36px;font-size:20px;display:inline-flex;align-items:center;justify-content:center}.formula-type-select{width:100%}.help-icon-button{--mdc-icon-button-state-layer-size: 28px;--mdc-icon-button-icon-size: 18px;width:28px;height:28px;padding:0;display:inline-flex;align-items:center;justify-content:center;vertical-align:middle}.help-icon-button mat-icon{font-size:18px;line-height:18px;width:18px;height:18px}.formula-option{display:flex;align-items:center;gap:12px;padding:8px 0}.option-icon{color:var(--vfb-primary);font-size:20px;opacity:.95}.option-content{display:flex;flex-direction:column}.option-label{font-weight:500;font-size:.9rem}.option-description{font-size:.8rem;color:var(--vfb-on-surface-variant)}.parameters-form{display:flex;flex-direction:column;gap:16px}.parameter-field{display:flex;flex-direction:column}.full-width{width:100%}.field-option{display:flex;align-items:center;gap:8px}.field-type-icon{font-size:16px;color:var(--vfb-outline)}.field-info{display:flex;flex-direction:column}.field-label{font-weight:500;font-size:.9rem}.field-name{font-size:.8rem;color:var(--vfb-on-surface-variant);font-family:monospace}.checkbox-field{padding:8px 0}.checkbox-hint{font-size:.75rem;color:var(--vfb-on-surface-variant);margin-top:4px;margin-left:32px}.expression-textarea{font-family:Monaco,Menlo,Ubuntu Mono,Consolas,monospace!important;font-size:13px!important;line-height:1.4!important}.test-panel{margin-top:8px}.test-content{padding:16px 0}.test-actions{display:flex;gap:12px;margin-bottom:16px}.sample-data-section{margin:16px 0}.sample-data{background-color:var(--vfb-surface-container);padding:12px;border-radius:4px;font-size:12px;overflow-x:auto}.test-result{margin:16px 0}.success-result,.error-result{display:flex;align-items:center;gap:8px;padding:12px;border-radius:4px}.success-result{background-color:var(--vfb-primary-container);color:var(--vfb-on-primary-container)}.error-result{background-color:var(--vfb-error-container);color:var(--vfb-on-error-container)}.result-icon.success{color:var(--vfb-primary)}.result-icon.error{color:var(--vfb-error)}.result-value{font-weight:500;font-family:monospace}.validation-errors{margin:16px 0}.error-chip{background-color:var(--vfb-error-container);color:var(--vfb-on-error-container)}.value-input-container{display:flex;flex-direction:column;gap:12px}.value-input-selector{display:flex;align-items:center;margin-bottom:8px}.input-mode-toggle{font-size:.875rem}.input-mode-toggle .mat-button-toggle{height:36px;display:flex;align-items:center;gap:6px}.literal-input-container{width:100%}@media(max-width:768px){.test-actions{flex-direction:column}.sample-data{font-size:10px}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i1$1.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3.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: "component", type: i3.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i5.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i6.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i6.MatLabel, selector: "mat-label" }, { kind: "directive", type: i6.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i7.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: i5$2.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: i5$2.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatCheckboxModule }, { kind: "component", type: i9.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "ngmodule", type: MatCardModule }, { kind: "component", type: i10$1.MatCard, selector: "mat-card", inputs: ["appearance"], exportAs: ["matCard"] }, { kind: "directive", type: i10$1.MatCardAvatar, selector: "[mat-card-avatar], [matCardAvatar]" }, { kind: "directive", type: i10$1.MatCardContent, selector: "mat-card-content" }, { kind: "component", type: i10$1.MatCardHeader, selector: "mat-card-header" }, { kind: "directive", type: i10$1.MatCardSubtitle, selector: "mat-card-subtitle, [mat-card-subtitle], [matCardSubtitle]" }, { kind: "directive", type: i10$1.MatCardTitle, selector: "mat-card-title, [mat-card-title], [matCardTitle]" }, { kind: "ngmodule", type: MatChipsModule }, { kind: "component", type: i15.MatChip, selector: "mat-basic-chip, [mat-basic-chip], mat-chip, [mat-chip]", inputs: ["role", "id", "aria-label", "aria-description", "value", "color", "removable", "highlighted", "disableRipple", "disabled"], outputs: ["removed", "destroyed"], exportAs: ["matChip"] }, { kind: "directive", type: i15.MatChipAvatar, selector: "mat-chip-avatar, [matChipAvatar]" }, { kind: "component", type: i15.MatChipSet, selector: "mat-chip-set", inputs: ["disabled", "role", "tabIndex"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i10.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: MatExpansionModule }, { kind: "component", type: i8.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "component", type: i8.MatExpansionPanelHeader, selector: "mat-expansion-panel-header", inputs: ["expandedHeight", "collapsedHeight", "tabIndex"] }, { kind: "directive", type: i8.MatExpansionPanelTitle, selector: "mat-panel-title" }, { kind: "directive", type: i8.MatExpansionPanelDescription, selector: "mat-panel-description" }, { kind: "ngmodule", type: MatDividerModule }, { kind: "component", type: i10$2.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "ngmodule", type: MatButtonToggleModule }, { kind: "directive", type: i15$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: i15$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: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4124
+ `, isInline: true, styles: [":host{--vfb-primary: var(--md-sys-color-primary);--vfb-primary-container: var(--md-sys-color-primary-container);--vfb-on-primary-container: var(--md-sys-color-on-primary-container);--vfb-surface-container-low: var(--md-sys-color-surface-container-low);--vfb-surface-container: var(--md-sys-color-surface-container);--vfb-outline: var(--md-sys-color-outline);--vfb-on-surface-variant: var(--md-sys-color-on-surface-variant);--vfb-error: var(--md-sys-color-error);--vfb-error-container: var(--md-sys-color-error-container);--vfb-on-error-container: var(--md-sys-color-on-error-container)}.visual-formula-builder{display:flex;flex-direction:column;gap:16px}.formula-type-card,.parameters-card,.expression-preview-card{background-color:var(--vfb-surface-container-low)}.compact-header{padding-bottom:8px;align-items:center}.compact-header .mat-mdc-card-title{font-size:1.1rem;margin:0;line-height:1.2}.compact-header .mat-mdc-card-subtitle{font-size:.875rem;margin:0}.compact-header .mat-mdc-card-avatar{align-self:center}.formula-icon,.params-icon,.preview-icon{background-color:var(--vfb-primary-container);color:var(--vfb-on-primary-container);border-radius:50%;width:36px;height:36px;font-size:20px;display:inline-flex;align-items:center;justify-content:center}.formula-type-select{width:100%}.help-icon-button{--mdc-icon-button-state-layer-size: 28px;--mdc-icon-button-icon-size: 18px;width:28px;height:28px;padding:0;display:inline-flex;align-items:center;justify-content:center;vertical-align:middle}.help-icon-button mat-icon{font-size:18px;line-height:18px;width:18px;height:18px}.formula-option{display:flex;align-items:center;gap:12px;padding:8px 0}.option-icon{color:var(--vfb-primary);font-size:20px;opacity:.95}.option-content{display:flex;flex-direction:column}.option-label{font-weight:500;font-size:.9rem}.option-description{font-size:.8rem;color:var(--vfb-on-surface-variant)}.parameters-form{display:flex;flex-direction:column;gap:16px}.parameter-field{display:flex;flex-direction:column}.full-width{width:100%}.field-option{display:flex;align-items:center;gap:8px}.field-type-icon{font-size:16px;color:var(--vfb-outline)}.field-info{display:flex;flex-direction:column}.field-label{font-weight:500;font-size:.9rem}.field-name{font-size:.8rem;color:var(--vfb-on-surface-variant);font-family:monospace}.checkbox-field{padding:8px 0}.checkbox-hint{font-size:.75rem;color:var(--vfb-on-surface-variant);margin-top:4px;margin-left:32px}.expression-textarea{font-family:Monaco,Menlo,Ubuntu Mono,Consolas,monospace!important;font-size:13px!important;line-height:1.4!important}.test-panel{margin-top:8px}.test-content{padding:16px 0}.test-actions{display:flex;gap:12px;margin-bottom:16px}.sample-data-section{margin:16px 0}.sample-data{background-color:var(--vfb-surface-container);padding:12px;border-radius:4px;font-size:12px;overflow-x:auto}.test-result{margin:16px 0}.success-result,.error-result{display:flex;align-items:center;gap:8px;padding:12px;border-radius:4px}.success-result{background-color:var(--vfb-primary-container);color:var(--vfb-on-primary-container)}.error-result{background-color:var(--vfb-error-container);color:var(--vfb-on-error-container)}.result-icon.success{color:var(--vfb-primary)}.result-icon.error{color:var(--vfb-error)}.result-value{font-weight:500;font-family:monospace}.validation-errors{margin:16px 0}.error-chip{background-color:var(--vfb-error-container);color:var(--vfb-on-error-container)}.value-input-container{display:flex;flex-direction:column;gap:12px}.value-input-selector{display:flex;align-items:center;margin-bottom:8px}.input-mode-toggle{font-size:.875rem}.input-mode-toggle .mat-button-toggle{height:36px;display:flex;align-items:center;gap:6px}.literal-input-container{width:100%}@media(max-width:768px){.test-actions{flex-direction:column}.sample-data{font-size:10px}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i1$1.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3.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: "component", type: i3.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i5.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i6.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i6.MatLabel, selector: "mat-label" }, { kind: "directive", type: i6.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i7.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: i5$1.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: i5$1.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatCheckboxModule }, { kind: "component", type: i9.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "ngmodule", type: MatCardModule }, { kind: "component", type: i10$1.MatCard, selector: "mat-card", inputs: ["appearance"], exportAs: ["matCard"] }, { kind: "directive", type: i10$1.MatCardAvatar, selector: "[mat-card-avatar], [matCardAvatar]" }, { kind: "directive", type: i10$1.MatCardContent, selector: "mat-card-content" }, { kind: "component", type: i10$1.MatCardHeader, selector: "mat-card-header" }, { kind: "directive", type: i10$1.MatCardSubtitle, selector: "mat-card-subtitle, [mat-card-subtitle], [matCardSubtitle]" }, { kind: "directive", type: i10$1.MatCardTitle, selector: "mat-card-title, [mat-card-title], [matCardTitle]" }, { kind: "ngmodule", type: MatChipsModule }, { kind: "component", type: i15.MatChip, selector: "mat-basic-chip, [mat-basic-chip], mat-chip, [mat-chip]", inputs: ["role", "id", "aria-label", "aria-description", "value", "color", "removable", "highlighted", "disableRipple", "disabled"], outputs: ["removed", "destroyed"], exportAs: ["matChip"] }, { kind: "directive", type: i15.MatChipAvatar, selector: "mat-chip-avatar, [matChipAvatar]" }, { kind: "component", type: i15.MatChipSet, selector: "mat-chip-set", inputs: ["disabled", "role", "tabIndex"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i10.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: MatExpansionModule }, { kind: "component", type: i8.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "component", type: i8.MatExpansionPanelHeader, selector: "mat-expansion-panel-header", inputs: ["expandedHeight", "collapsedHeight", "tabIndex"] }, { kind: "directive", type: i8.MatExpansionPanelTitle, selector: "mat-panel-title" }, { kind: "directive", type: i8.MatExpansionPanelDescription, selector: "mat-panel-description" }, { kind: "ngmodule", type: MatDividerModule }, { kind: "component", type: i10$2.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "ngmodule", type: MatButtonToggleModule }, { kind: "directive", type: i15$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: i15$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: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4125
4125
  }
4126
4126
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: VisualFormulaBuilderComponent, decorators: [{
4127
4127
  type: Component,
@@ -7113,7 +7113,7 @@ class DataFormatterComponent {
7113
7113
  </div>
7114
7114
  </div> }
7115
7115
  </div>
7116
- `, isInline: true, styles: [".data-formatter{display:flex;flex-direction:column;gap:16px}.formatter-header{display:flex;align-items:center;gap:12px;padding:16px 0;border-bottom:1px solid var(--md-sys-color-outline-variant)}.header-icon{font-size:24px;width:24px;height:24px;color:var(--md-sys-color-primary)}.header-content h4{margin:0 0 4px;font-size:1.1rem;font-weight:500;color:var(--md-sys-color-on-surface)}.header-description{margin:0;font-size:.875rem;color:var(--md-sys-color-on-surface-variant)}.format-section{display:flex;flex-direction:column;gap:16px}.format-row{display:flex;gap:16px;align-items:center;flex-wrap:wrap}.full-width{width:100%}.help-icon-button{--mdc-icon-button-state-layer-size: 28px;--mdc-icon-button-icon-size: 18px;width:28px;height:28px;padding:0;display:inline-flex;align-items:center;justify-content:center;vertical-align:middle}.help-icon-button mat-icon{font-size:18px;line-height:18px;width:18px;height:18px}.decimal-select,.currency-select{min-width:200px;flex:1}.truncate-length{flex:1;min-width:120px}.truncate-suffix{flex:1;min-width:100px}.boolean-value{flex:1;min-width:150px}.format-checkbox{margin-right:16px}.preset-option{display:flex;justify-content:space-between;align-items:center;width:100%;padding:4px 0}.preset-content{display:flex;flex-direction:column;flex:1}.preset-label{font-weight:500;font-size:.9rem}.preset-description{font-size:.8rem;color:var(--md-sys-color-on-surface-variant)}.preset-example{font-family:monospace;font-size:.8rem;color:var(--md-sys-color-primary);background-color:var(--md-sys-color-primary-container);padding:2px 6px;border-radius:4px;margin-left:8px}.truncate-options{margin-left:24px;padding-left:16px;border-left:2px solid var(--md-sys-color-outline-variant)}.custom-boolean{margin-top:8px}.preview-section{margin-top:16px}.preview-content{display:flex;align-items:center;gap:12px;padding:16px;background-color:var(--md-sys-color-surface-container);border-radius:8px;margin-top:16px}.preview-icon{color:var(--md-sys-color-secondary)}.preview-text{display:flex;flex-direction:column;gap:4px}.preview-label{font-size:.875rem;color:var(--md-sys-color-on-surface-variant)}.preview-value{font-family:monospace;font-size:1rem;font-weight:500;color:var(--md-sys-color-on-surface);background-color:var(--md-sys-color-surface-container-high);padding:8px 12px;border-radius:4px;border:1px solid var(--md-sys-color-outline-variant)}@media(max-width:768px){.format-row{flex-direction:column;align-items:stretch}.decimal-select,.currency-select,.truncate-length,.truncate-suffix,.boolean-value{min-width:unset;width:100%}.format-checkbox{margin-right:0;margin-bottom:8px}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { kind: "directive", type: i1$1.MaxValidator, selector: "input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]", inputs: ["max"] }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i5.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i6.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i6.MatLabel, selector: "mat-label" }, { kind: "directive", type: i6.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i7.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: i5$2.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: i5$2.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatCheckboxModule }, { kind: "component", type: i9.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "ngmodule", type: MatCardModule }, { kind: "ngmodule", type: MatDividerModule }, { kind: "component", type: i10$2.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i10.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: MatChipsModule }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
7116
+ `, isInline: true, styles: [".data-formatter{display:flex;flex-direction:column;gap:16px}.formatter-header{display:flex;align-items:center;gap:12px;padding:16px 0;border-bottom:1px solid var(--md-sys-color-outline-variant)}.header-icon{font-size:24px;width:24px;height:24px;color:var(--md-sys-color-primary)}.header-content h4{margin:0 0 4px;font-size:1.1rem;font-weight:500;color:var(--md-sys-color-on-surface)}.header-description{margin:0;font-size:.875rem;color:var(--md-sys-color-on-surface-variant)}.format-section{display:flex;flex-direction:column;gap:16px}.format-row{display:flex;gap:16px;align-items:center;flex-wrap:wrap}.full-width{width:100%}.help-icon-button{--mdc-icon-button-state-layer-size: 28px;--mdc-icon-button-icon-size: 18px;width:28px;height:28px;padding:0;display:inline-flex;align-items:center;justify-content:center;vertical-align:middle}.help-icon-button mat-icon{font-size:18px;line-height:18px;width:18px;height:18px}.decimal-select,.currency-select{min-width:200px;flex:1}.truncate-length{flex:1;min-width:120px}.truncate-suffix{flex:1;min-width:100px}.boolean-value{flex:1;min-width:150px}.format-checkbox{margin-right:16px}.preset-option{display:flex;justify-content:space-between;align-items:center;width:100%;padding:4px 0}.preset-content{display:flex;flex-direction:column;flex:1}.preset-label{font-weight:500;font-size:.9rem}.preset-description{font-size:.8rem;color:var(--md-sys-color-on-surface-variant)}.preset-example{font-family:monospace;font-size:.8rem;color:var(--md-sys-color-primary);background-color:var(--md-sys-color-primary-container);padding:2px 6px;border-radius:4px;margin-left:8px}.truncate-options{margin-left:24px;padding-left:16px;border-left:2px solid var(--md-sys-color-outline-variant)}.custom-boolean{margin-top:8px}.preview-section{margin-top:16px}.preview-content{display:flex;align-items:center;gap:12px;padding:16px;background-color:var(--md-sys-color-surface-container);border-radius:8px;margin-top:16px}.preview-icon{color:var(--md-sys-color-secondary)}.preview-text{display:flex;flex-direction:column;gap:4px}.preview-label{font-size:.875rem;color:var(--md-sys-color-on-surface-variant)}.preview-value{font-family:monospace;font-size:1rem;font-weight:500;color:var(--md-sys-color-on-surface);background-color:var(--md-sys-color-surface-container-high);padding:8px 12px;border-radius:4px;border:1px solid var(--md-sys-color-outline-variant)}@media(max-width:768px){.format-row{flex-direction:column;align-items:stretch}.decimal-select,.currency-select,.truncate-length,.truncate-suffix,.boolean-value{min-width:unset;width:100%}.format-checkbox{margin-right:0;margin-bottom:8px}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { kind: "directive", type: i1$1.MaxValidator, selector: "input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]", inputs: ["max"] }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i5.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i6.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i6.MatLabel, selector: "mat-label" }, { kind: "directive", type: i6.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i7.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: i5$1.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: i5$1.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatCheckboxModule }, { kind: "component", type: i9.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "ngmodule", type: MatCardModule }, { kind: "ngmodule", type: MatDividerModule }, { kind: "component", type: i10$2.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i10.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: MatChipsModule }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
7117
7117
  }
7118
7118
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: DataFormatterComponent, decorators: [{
7119
7119
  type: Component,
@@ -7462,8 +7462,139 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
7462
7462
  type: Output
7463
7463
  }] } });
7464
7464
 
7465
+ class TableRatingCellComponent {
7466
+ itemsCount = 5;
7467
+ value = 0;
7468
+ size = 'medium';
7469
+ ratingColor;
7470
+ outlineColor;
7471
+ ariaLabel;
7472
+ starPath = 'M12 2.25 14.98 8.29 21.64 9.26 16.82 13.96 17.96 20.6 12 17.47 6.04 20.6 7.18 13.96 2.36 9.26 9.02 8.29 12 2.25Z';
7473
+ accessibleLabel() {
7474
+ const count = this.normalizedItemsCount();
7475
+ const value = this.normalizedValue();
7476
+ const base = typeof this.ariaLabel === 'string' && this.ariaLabel.trim() ? this.ariaLabel.trim() : 'Avaliacao';
7477
+ if (base.includes('{value}') || base.includes('{max}')) {
7478
+ return base
7479
+ .replaceAll('{value}', this.formatValue(value))
7480
+ .replaceAll('{max}', String(count));
7481
+ }
7482
+ return `${base}: ${this.formatValue(value)} de ${count}`;
7483
+ }
7484
+ items() {
7485
+ const count = this.normalizedItemsCount();
7486
+ const visualValue = this.normalizedValue();
7487
+ return Array.from({ length: count }, (_, index) => ({
7488
+ fillPercent: this.fillRatioFor(index, visualValue) * 100,
7489
+ }));
7490
+ }
7491
+ normalizedItemsCount() {
7492
+ return Number.isFinite(this.itemsCount) && this.itemsCount > 0 ? Math.floor(this.itemsCount) : 5;
7493
+ }
7494
+ normalizedValue() {
7495
+ const count = this.normalizedItemsCount();
7496
+ const numeric = Number.isFinite(this.value) ? this.value : 0;
7497
+ const clamped = Math.max(0, Math.min(count, numeric));
7498
+ return Math.round(clamped * 2) / 2;
7499
+ }
7500
+ iconSizePx() {
7501
+ switch (this.size) {
7502
+ case 'small':
7503
+ return 16;
7504
+ case 'large':
7505
+ return 28;
7506
+ default:
7507
+ return 20;
7508
+ }
7509
+ }
7510
+ formatValue(value) {
7511
+ return Number.isInteger(value) ? String(value) : value.toFixed(1).replace(/\.0$/, '');
7512
+ }
7513
+ fillRatioFor(index, visualValue) {
7514
+ const raw = visualValue - index;
7515
+ if (raw <= 0)
7516
+ return 0;
7517
+ if (raw >= 1)
7518
+ return 1;
7519
+ return raw;
7520
+ }
7521
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: TableRatingCellComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
7522
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.17", type: TableRatingCellComponent, isStandalone: true, selector: "praxis-table-rating", inputs: { itemsCount: "itemsCount", value: "value", size: "size", ratingColor: "ratingColor", outlineColor: "outlineColor", ariaLabel: "ariaLabel" }, host: { properties: { "attr.role": "\"img\"", "attr.aria-label": "accessibleLabel()", "style.--pfx-table-rating-fill": "ratingColor || null", "style.--pfx-table-rating-outline": "outlineColor || null", "class.pfx-table-rating--size-sm": "size === \"small\"", "class.pfx-table-rating--size-lg": "size === \"large\"" }, classAttribute: "pfx-table-rating" }, ngImport: i0, template: `
7523
+ <span class="pfx-table-rating__item" *ngFor="let item of items(); let i = index">
7524
+ <svg class="pfx-table-rating__svg pfx-table-rating__svg--outline" viewBox="0 0 24 24" aria-hidden="true" focusable="false">
7525
+ <path
7526
+ class="pfx-table-rating__outline"
7527
+ [attr.d]="starPath"
7528
+ fill="none"
7529
+ stroke-linejoin="round"
7530
+ stroke-linecap="round">
7531
+ </path>
7532
+ </svg>
7533
+ <span class="pfx-table-rating__fill-clip" [style.width.%]="item.fillPercent" aria-hidden="true">
7534
+ <svg
7535
+ class="pfx-table-rating__svg pfx-table-rating__svg--fill"
7536
+ viewBox="0 0 24 24"
7537
+ focusable="false"
7538
+ [style.width.px]="iconSizePx()"
7539
+ [style.height.px]="iconSizePx()">
7540
+ <path class="pfx-table-rating__fill" [attr.d]="starPath"></path>
7541
+ </svg>
7542
+ </span>
7543
+ </span>
7544
+ `, isInline: true, styles: [":host{--pfx-table-rating-size: 20px;--pfx-table-rating-fill: var(--md-sys-color-tertiary, var(--md-sys-color-primary, currentColor));--pfx-table-rating-outline: var(--md-sys-color-outline-variant, var(--md-sys-color-on-surface-variant, currentColor));display:inline-flex;align-items:center;gap:2px;line-height:0;vertical-align:middle}:host(.pfx-table-rating--size-sm){--pfx-table-rating-size: 16px}:host(.pfx-table-rating--size-lg){--pfx-table-rating-size: 28px}.pfx-table-rating__item{display:inline-flex;width:var(--pfx-table-rating-size);height:var(--pfx-table-rating-size);position:relative}.pfx-table-rating__svg{width:100%;height:100%;display:block}.pfx-table-rating__svg--outline{overflow:visible}.pfx-table-rating__fill-clip{position:absolute;inset:0 auto 0 0;height:100%;overflow:hidden}.pfx-table-rating__outline{stroke:var(--pfx-table-rating-outline);stroke-width:1.8}.pfx-table-rating__fill{fill:var(--pfx-table-rating-fill)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }] });
7545
+ }
7546
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: TableRatingCellComponent, decorators: [{
7547
+ type: Component,
7548
+ args: [{ selector: 'praxis-table-rating', standalone: true, imports: [CommonModule], host: {
7549
+ class: 'pfx-table-rating',
7550
+ '[attr.role]': '"img"',
7551
+ '[attr.aria-label]': 'accessibleLabel()',
7552
+ '[style.--pfx-table-rating-fill]': 'ratingColor || null',
7553
+ '[style.--pfx-table-rating-outline]': 'outlineColor || null',
7554
+ '[class.pfx-table-rating--size-sm]': 'size === "small"',
7555
+ '[class.pfx-table-rating--size-lg]': 'size === "large"',
7556
+ }, template: `
7557
+ <span class="pfx-table-rating__item" *ngFor="let item of items(); let i = index">
7558
+ <svg class="pfx-table-rating__svg pfx-table-rating__svg--outline" viewBox="0 0 24 24" aria-hidden="true" focusable="false">
7559
+ <path
7560
+ class="pfx-table-rating__outline"
7561
+ [attr.d]="starPath"
7562
+ fill="none"
7563
+ stroke-linejoin="round"
7564
+ stroke-linecap="round">
7565
+ </path>
7566
+ </svg>
7567
+ <span class="pfx-table-rating__fill-clip" [style.width.%]="item.fillPercent" aria-hidden="true">
7568
+ <svg
7569
+ class="pfx-table-rating__svg pfx-table-rating__svg--fill"
7570
+ viewBox="0 0 24 24"
7571
+ focusable="false"
7572
+ [style.width.px]="iconSizePx()"
7573
+ [style.height.px]="iconSizePx()">
7574
+ <path class="pfx-table-rating__fill" [attr.d]="starPath"></path>
7575
+ </svg>
7576
+ </span>
7577
+ </span>
7578
+ `, styles: [":host{--pfx-table-rating-size: 20px;--pfx-table-rating-fill: var(--md-sys-color-tertiary, var(--md-sys-color-primary, currentColor));--pfx-table-rating-outline: var(--md-sys-color-outline-variant, var(--md-sys-color-on-surface-variant, currentColor));display:inline-flex;align-items:center;gap:2px;line-height:0;vertical-align:middle}:host(.pfx-table-rating--size-sm){--pfx-table-rating-size: 16px}:host(.pfx-table-rating--size-lg){--pfx-table-rating-size: 28px}.pfx-table-rating__item{display:inline-flex;width:var(--pfx-table-rating-size);height:var(--pfx-table-rating-size);position:relative}.pfx-table-rating__svg{width:100%;height:100%;display:block}.pfx-table-rating__svg--outline{overflow:visible}.pfx-table-rating__fill-clip{position:absolute;inset:0 auto 0 0;height:100%;overflow:hidden}.pfx-table-rating__outline{stroke:var(--pfx-table-rating-outline);stroke-width:1.8}.pfx-table-rating__fill{fill:var(--pfx-table-rating-fill)}\n"] }]
7579
+ }], propDecorators: { itemsCount: [{
7580
+ type: Input
7581
+ }], value: [{
7582
+ type: Input
7583
+ }], size: [{
7584
+ type: Input
7585
+ }], ratingColor: [{
7586
+ type: Input
7587
+ }], outlineColor: [{
7588
+ type: Input
7589
+ }], ariaLabel: [{
7590
+ type: Input
7591
+ }] } });
7592
+
7465
7593
  class ColumnsConfigEditorComponent {
7466
7594
  cdr;
7595
+ ratingAriaLabelPlaceholder = 'Avaliação {value} de {max}';
7596
+ ratingRendererHint = 'Renderer padronizado e somente leitura para uso em tabela. Ícones customizados não são suportados neste contexto. Valores fracionados são normalizados em passos de 0.5 no grid. Use {value} e {max} no aria-label para sobrescrever o texto acessível completo; sem placeholders, o valor informado funciona como prefixo.';
7597
+ composeRatingRendererHint = 'Compose/Rating usa o mesmo renderer canônico de tabela e normaliza frações em passos de 0.5. Use {value} e {max} para sobrescrever o texto acessível completo.';
7467
7598
  config = { columns: [] };
7468
7599
  configChange = new EventEmitter();
7469
7600
  columnChange = new EventEmitter();
@@ -7622,6 +7753,7 @@ class ColumnsConfigEditorComponent {
7622
7753
  }
7623
7754
  // Renderer apply/preview state
7624
7755
  rendererValidationErrors = [];
7756
+ rendererImportWarnings = [];
7625
7757
  rendererIsValid = true;
7626
7758
  rendererPreviewEnabled = true;
7627
7759
  rendererAppliedSnapshot = null;
@@ -8502,6 +8634,7 @@ class ColumnsConfigEditorComponent {
8502
8634
  this.validateRenderer();
8503
8635
  if (!this.rendererIsValid)
8504
8636
  return;
8637
+ this.rendererImportWarnings = [];
8505
8638
  // snapshot current as applied
8506
8639
  this.rendererAppliedSnapshot = this.selectedColumn ? this._deepClone(this.selectedColumn.renderer) : null;
8507
8640
  // emit change explicitly
@@ -8521,6 +8654,7 @@ class ColumnsConfigEditorComponent {
8521
8654
  this.uiRendererType = null;
8522
8655
  this.uiRendererConditional = false;
8523
8656
  }
8657
+ this.rendererImportWarnings = [];
8524
8658
  this.onColumnPropertyChange();
8525
8659
  this.validateRenderer();
8526
8660
  }
@@ -8546,6 +8680,7 @@ class ColumnsConfigEditorComponent {
8546
8680
  return;
8547
8681
  try {
8548
8682
  const parsed = JSON.parse(input);
8683
+ this.rendererImportWarnings = this.collectRendererImportWarnings(parsed);
8549
8684
  const sanitized = this.sanitizeRenderer(parsed);
8550
8685
  this.selectedColumn.renderer = sanitized;
8551
8686
  this.uiRendererType = sanitized?.type || null;
@@ -8557,6 +8692,31 @@ class ColumnsConfigEditorComponent {
8557
8692
  // ignore invalid JSON
8558
8693
  }
8559
8694
  }
8695
+ collectRendererImportWarnings(input) {
8696
+ const warnings = [];
8697
+ const inspectRating = (rating, context) => {
8698
+ if (!rating || typeof rating !== 'object')
8699
+ return;
8700
+ if (Object.prototype.hasOwnProperty.call(rating, 'readonly')) {
8701
+ warnings.push(`${context}: readonly é legado no renderer de tabela, sera descartado na importacao e nao altera o comportamento visual.`);
8702
+ }
8703
+ const unsupportedKeys = ['icon', 'emptyIcon', 'outlineIcon', 'svgIcon', 'svgIconOutline', 'selection', 'allowHalf', 'precision']
8704
+ .filter((key) => Object.prototype.hasOwnProperty.call(rating, key));
8705
+ if (unsupportedKeys.length) {
8706
+ warnings.push(`${context}: campos ignorados pelo renderer de tabela: ${unsupportedKeys.join(', ')}.`);
8707
+ }
8708
+ };
8709
+ if (input?.type === 'rating') {
8710
+ inspectRating(input.rating, 'Rating');
8711
+ }
8712
+ if (input?.type === 'compose' && Array.isArray(input.compose?.items)) {
8713
+ input.compose.items.forEach((item, index) => {
8714
+ if (item?.type === 'rating')
8715
+ inspectRating(item.rating, `Compose/Rating item ${index + 1}`);
8716
+ });
8717
+ }
8718
+ return warnings;
8719
+ }
8560
8720
  sanitizeRenderer(input) {
8561
8721
  if (!input || typeof input !== 'object')
8562
8722
  return undefined;
@@ -8673,8 +8833,6 @@ class ColumnsConfigEditorComponent {
8673
8833
  out.rating.size = input.rating.size;
8674
8834
  if (typeof input.rating.ariaLabel === 'string')
8675
8835
  out.rating.ariaLabel = input.rating.ariaLabel;
8676
- if (typeof input.rating.readonly === 'boolean')
8677
- out.rating.readonly = input.rating.readonly;
8678
8836
  }
8679
8837
  if (t === 'menu' && input.menu) {
8680
8838
  out.menu = {};
@@ -8905,7 +9063,7 @@ class ColumnsConfigEditorComponent {
8905
9063
  const rend = col?.renderer || null;
8906
9064
  if (rend && rend.typeExpr) {
8907
9065
  const t = this.evalValueExpr(rend.typeExpr, row, 'string');
8908
- if (t === 'icon' || t === 'image' || t === 'badge' || t === 'link' || t === 'button' || t === 'chip' || t === 'progress' || t === 'avatar' || t === 'toggle' || t === 'menu' || t === 'html' || t === 'compose')
9066
+ if (t === 'icon' || t === 'image' || t === 'badge' || t === 'link' || t === 'button' || t === 'chip' || t === 'progress' || t === 'rating' || t === 'avatar' || t === 'toggle' || t === 'menu' || t === 'html' || t === 'compose')
8909
9067
  return t;
8910
9068
  if (t === 'text' || t === 'none')
8911
9069
  return null;
@@ -9008,6 +9166,76 @@ class ColumnsConfigEditorComponent {
9008
9166
  getPreviewProgressValue(row) { const pg = this.selectedColumn?.renderer?.progress; if (!pg?.valueExpr)
9009
9167
  return 0; const v = this.evalValueExpr(pg.valueExpr, row, 'number'); const n = typeof v === 'number' ? v : Number(v); if (!isFinite(n))
9010
9168
  return 0; return Math.max(0, Math.min(100, n)); }
9169
+ getPreviewRatingValue(row) {
9170
+ const rt = this.selectedColumn?.renderer?.rating;
9171
+ if (!rt?.valueExpr)
9172
+ return 0;
9173
+ const v = this.evalValueExpr(rt.valueExpr, row, 'number');
9174
+ const n = typeof v === 'number' ? v : Number(v);
9175
+ const max = this.getPreviewRatingMax();
9176
+ if (!isFinite(n))
9177
+ return 0;
9178
+ return this.normalizePreviewRatingValue(n, max);
9179
+ }
9180
+ getPreviewRatingMax() {
9181
+ const raw = Number(this.selectedColumn?.renderer?.rating?.max);
9182
+ return Number.isFinite(raw) && raw > 0 ? raw : 5;
9183
+ }
9184
+ getPreviewRatingColor() {
9185
+ const value = this.selectedColumn?.renderer?.rating?.color;
9186
+ return value === null || value === undefined || value === '' ? undefined : value;
9187
+ }
9188
+ getPreviewRatingOutlineColor() {
9189
+ const value = this.selectedColumn?.renderer?.rating?.outlineColor;
9190
+ return value === null || value === undefined || value === '' ? undefined : value;
9191
+ }
9192
+ getPreviewRatingSize() {
9193
+ const value = this.selectedColumn?.renderer?.rating?.size;
9194
+ return value === 'small' || value === 'medium' || value === 'large' ? value : 'medium';
9195
+ }
9196
+ getPreviewRatingAriaLabel() {
9197
+ const value = this.selectedColumn?.renderer?.rating?.ariaLabel;
9198
+ return value === null || value === undefined || value === '' ? undefined : value;
9199
+ }
9200
+ getComposePreviewItems(_row) {
9201
+ const compose = this.selectedColumn?.renderer?.compose;
9202
+ return Array.isArray(compose?.items) ? compose.items : [];
9203
+ }
9204
+ getComposePreviewRatingValue(item, row) {
9205
+ const rating = item?.rating;
9206
+ if (!rating?.valueExpr)
9207
+ return 0;
9208
+ const v = this.evalValueExpr(rating.valueExpr, row, 'number');
9209
+ const n = typeof v === 'number' ? v : Number(v);
9210
+ const max = this.getComposePreviewRatingMax(item);
9211
+ if (!isFinite(n))
9212
+ return 0;
9213
+ return this.normalizePreviewRatingValue(n, max);
9214
+ }
9215
+ getComposePreviewRatingMax(item) {
9216
+ const raw = Number(item?.rating?.max);
9217
+ return Number.isFinite(raw) && raw > 0 ? raw : 5;
9218
+ }
9219
+ getComposePreviewRatingColor(item) {
9220
+ const value = item?.rating?.color;
9221
+ return value === null || value === undefined || value === '' ? undefined : value;
9222
+ }
9223
+ getComposePreviewRatingOutlineColor(item) {
9224
+ const value = item?.rating?.outlineColor;
9225
+ return value === null || value === undefined || value === '' ? undefined : value;
9226
+ }
9227
+ getComposePreviewRatingSize(item) {
9228
+ const value = item?.rating?.size;
9229
+ return value === 'small' || value === 'medium' || value === 'large' ? value : 'medium';
9230
+ }
9231
+ getComposePreviewRatingAriaLabel(item) {
9232
+ const value = item?.rating?.ariaLabel;
9233
+ return value === null || value === undefined || value === '' ? undefined : value;
9234
+ }
9235
+ normalizePreviewRatingValue(value, max) {
9236
+ const clamped = Math.max(0, Math.min(max, value));
9237
+ return Math.round(clamped * 2) / 2;
9238
+ }
9011
9239
  getPreviewAvatarSrc(row) { const av = this.selectedColumn?.renderer?.avatar; if (!av)
9012
9240
  return null; const src = av.srcField ? this.getNested(row, av.srcField) : av.src; if (typeof src !== 'string')
9013
9241
  return null; if (/^\s*javascript:/i.test(src))
@@ -9135,6 +9363,10 @@ class ColumnsConfigEditorComponent {
9135
9363
  errs.push('Rating: max deve ser maior que 0.');
9136
9364
  if (rt.size && !['small', 'medium', 'large'].includes(rt.size))
9137
9365
  errs.push('Rating: size inválido.');
9366
+ if (rt.color != null && String(rt.color).trim() === '')
9367
+ errs.push('Rating: color não pode ser vazio.');
9368
+ if (rt.outlineColor != null && String(rt.outlineColor).trim() === '')
9369
+ errs.push('Rating: outlineColor não pode ser vazio.');
9138
9370
  }
9139
9371
  if (r.type === 'menu') {
9140
9372
  const mn = r.menu || {};
@@ -9301,6 +9533,8 @@ class ColumnsConfigEditorComponent {
9301
9533
  it.chip = {};
9302
9534
  if (kind === 'progress')
9303
9535
  it.progress = { valueExpr: "= 50" };
9536
+ if (kind === 'rating')
9537
+ it.rating = { valueExpr: '= 0', max: 5, size: 'medium' };
9304
9538
  if (kind === 'avatar')
9305
9539
  it.avatar = {};
9306
9540
  if (kind === 'toggle')
@@ -9360,6 +9594,32 @@ class ColumnsConfigEditorComponent {
9360
9594
  return; comp.layout = comp.layout || {}; comp.layout[key] = value; this.onColumnPropertyChange(); }
9361
9595
  getSelectedComposeItem() { const comp = this.ensureCompose(); if (!comp)
9362
9596
  return null; return comp.items?.[this.composeSelectedIndex] || null; }
9597
+ getSelectedComposeItemProp(path) {
9598
+ const item = this.getSelectedComposeItem();
9599
+ if (!item)
9600
+ return undefined;
9601
+ try {
9602
+ return path.split('.').reduce((acc, key) => (acc ? acc[key] : undefined), item);
9603
+ }
9604
+ catch {
9605
+ return undefined;
9606
+ }
9607
+ }
9608
+ setSelectedComposeItemProp(path, value) {
9609
+ const item = this.getSelectedComposeItem();
9610
+ if (!item)
9611
+ return;
9612
+ const parts = path.split('.');
9613
+ let ref = item;
9614
+ for (let i = 0; i < parts.length - 1; i += 1) {
9615
+ const key = parts[i];
9616
+ ref[key] = ref[key] || {};
9617
+ ref = ref[key];
9618
+ }
9619
+ ref[parts[parts.length - 1]] = value;
9620
+ this.onColumnPropertyChange();
9621
+ this.validateRenderer();
9622
+ }
9363
9623
  getColumnKeyInputType(column) {
9364
9624
  if (!column)
9365
9625
  return 'text';
@@ -10366,7 +10626,7 @@ class ColumnsConfigEditorComponent {
10366
10626
  Renderização da Célula
10367
10627
  </mat-panel-title>
10368
10628
  <mat-panel-description>
10369
- Ícone, imagem ou badge no lugar do texto
10629
+ Ícone, imagem, rating e outros renderers no lugar do texto
10370
10630
  </mat-panel-description>
10371
10631
  </mat-expansion-panel-header>
10372
10632
 
@@ -10719,6 +10979,43 @@ class ColumnsConfigEditorComponent {
10719
10979
  </div>
10720
10980
  }
10721
10981
 
10982
+ <!-- Rating configuration -->
10983
+ @if (uiRendererType === 'rating') {
10984
+ <div class="renderer-config">
10985
+ <mat-form-field appearance="outline">
10986
+ <mat-label>Expressão de valor</mat-label>
10987
+ <input matInput [value]="getRendererProp('rating','valueExpr') || ''" (input)="setRendererProp('rating','valueExpr',$any($event.target).value)" placeholder="= Number(row.score || 0) / 20" />
10988
+ </mat-form-field>
10989
+ <mat-form-field appearance="outline">
10990
+ <mat-label>Máximo de itens</mat-label>
10991
+ <input matInput type="number" min="1" [value]="getRendererProp('rating','max') || 5" (input)="setRendererProp('rating','max',$any($event.target).valueAsNumber)" />
10992
+ </mat-form-field>
10993
+ <mat-form-field appearance="outline">
10994
+ <mat-label>Cor do preenchimento</mat-label>
10995
+ <input matInput [value]="getRendererProp('rating','color') || ''" (input)="setRendererProp('rating','color',$any($event.target).value)" placeholder="#f59e0b" />
10996
+ </mat-form-field>
10997
+ <mat-form-field appearance="outline">
10998
+ <mat-label>Cor do contorno</mat-label>
10999
+ <input matInput [value]="getRendererProp('rating','outlineColor') || ''" (input)="setRendererProp('rating','outlineColor',$any($event.target).value)" placeholder="#cbd5e1" />
11000
+ </mat-form-field>
11001
+ <mat-form-field appearance="outline">
11002
+ <mat-label>Tamanho</mat-label>
11003
+ <mat-select [ngModel]="getRendererProp('rating','size') || 'medium'" [ngModelOptions]="{standalone: true}" (ngModelChange)="setRendererProp('rating','size',$event)">
11004
+ <mat-option value="small">Pequeno</mat-option>
11005
+ <mat-option value="medium">Médio</mat-option>
11006
+ <mat-option value="large">Grande</mat-option>
11007
+ </mat-select>
11008
+ </mat-form-field>
11009
+ <mat-form-field appearance="outline">
11010
+ <mat-label>aria-label</mat-label>
11011
+ <input matInput [value]="getRendererProp('rating','ariaLabel') || ''" (input)="setRendererProp('rating','ariaLabel',$any($event.target).value)" [placeholder]="ratingAriaLabelPlaceholder" />
11012
+ </mat-form-field>
11013
+ <div class="renderer-hint" style="grid-column: 1/-1; opacity:.78;">
11014
+ {{ ratingRendererHint }}
11015
+ </div>
11016
+ </div>
11017
+ }
11018
+
10722
11019
  <!-- Avatar configuration -->
10723
11020
  @if (uiRendererType === 'avatar') {
10724
11021
  <div class="renderer-config">
@@ -10846,6 +11143,7 @@ class ColumnsConfigEditorComponent {
10846
11143
  <button mat-stroked-button (click)="addComposeItem('badge')">Adicionar Badge</button>
10847
11144
  <button mat-stroked-button (click)="addComposeItem('chip')">Adicionar Chip</button>
10848
11145
  <button mat-stroked-button (click)="addComposeItem('progress')">Adicionar Progresso</button>
11146
+ <button mat-stroked-button (click)="addComposeItem('rating')">Adicionar Rating</button>
10849
11147
  <button mat-stroked-button (click)="addComposeItem('avatar')">Adicionar Avatar</button>
10850
11148
  <button mat-stroked-button (click)="addComposeItem('button')">Adicionar Botão</button>
10851
11149
  <button mat-stroked-button (click)="addComposeItem('toggle')">Adicionar Toggle</button>
@@ -10862,6 +11160,44 @@ class ColumnsConfigEditorComponent {
10862
11160
  <button mat-icon-button color="warn" (click)="removeComposeItem(i); $event.stopPropagation();"><mat-icon>delete</mat-icon></button>
10863
11161
  </div>
10864
11162
  </div>
11163
+ @if (getSelectedComposeItem(); as selectedCompose) {
11164
+ @if (selectedCompose.type === 'rating') {
11165
+ <div style="display:grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap:12px; margin-top:12px; padding:12px; border:1px solid var(--md-sys-color-outline-variant); border-radius:8px;">
11166
+ <div style="grid-column: 1/-1; font-weight:600;">Compose item: Rating</div>
11167
+ <mat-form-field appearance="outline">
11168
+ <mat-label>Expressão de valor</mat-label>
11169
+ <input matInput [value]="getSelectedComposeItemProp('rating.valueExpr') || ''" (input)="setSelectedComposeItemProp('rating.valueExpr', $any($event.target).value)" placeholder="= Number(row.score || 0) / 20" />
11170
+ </mat-form-field>
11171
+ <mat-form-field appearance="outline">
11172
+ <mat-label>Máximo de itens</mat-label>
11173
+ <input matInput type="number" min="1" [value]="getSelectedComposeItemProp('rating.max') || 5" (input)="setSelectedComposeItemProp('rating.max', $any($event.target).valueAsNumber)" />
11174
+ </mat-form-field>
11175
+ <mat-form-field appearance="outline">
11176
+ <mat-label>Cor do preenchimento</mat-label>
11177
+ <input matInput [value]="getSelectedComposeItemProp('rating.color') || ''" (input)="setSelectedComposeItemProp('rating.color', $any($event.target).value)" placeholder="#f59e0b" />
11178
+ </mat-form-field>
11179
+ <mat-form-field appearance="outline">
11180
+ <mat-label>Cor do contorno</mat-label>
11181
+ <input matInput [value]="getSelectedComposeItemProp('rating.outlineColor') || ''" (input)="setSelectedComposeItemProp('rating.outlineColor', $any($event.target).value)" placeholder="#cbd5e1" />
11182
+ </mat-form-field>
11183
+ <mat-form-field appearance="outline">
11184
+ <mat-label>Tamanho</mat-label>
11185
+ <mat-select [ngModel]="getSelectedComposeItemProp('rating.size') || 'medium'" [ngModelOptions]="{standalone: true}" (ngModelChange)="setSelectedComposeItemProp('rating.size', $event)">
11186
+ <mat-option value="small">Pequeno</mat-option>
11187
+ <mat-option value="medium">Médio</mat-option>
11188
+ <mat-option value="large">Grande</mat-option>
11189
+ </mat-select>
11190
+ </mat-form-field>
11191
+ <mat-form-field appearance="outline">
11192
+ <mat-label>aria-label</mat-label>
11193
+ <input matInput [value]="getSelectedComposeItemProp('rating.ariaLabel') || ''" (input)="setSelectedComposeItemProp('rating.ariaLabel', $any($event.target).value)" [placeholder]="ratingAriaLabelPlaceholder" />
11194
+ </mat-form-field>
11195
+ <div style="grid-column: 1/-1; opacity:.78;">
11196
+ {{ composeRatingRendererHint }}
11197
+ </div>
11198
+ </div>
11199
+ }
11200
+ }
10865
11201
  <div style="display:grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap:12px; margin-top:12px;">
10866
11202
  <mat-form-field appearance="outline">
10867
11203
  <mat-label>Direção</mat-label>
@@ -10913,6 +11249,12 @@ class ColumnsConfigEditorComponent {
10913
11249
  <li *ngFor="let err of rendererValidationErrors">{{ err }}</li>
10914
11250
  </ul>
10915
11251
  </div> }
11252
+ @if (rendererImportWarnings.length) { <div class="renderer-errors" style="grid-column: 1/-1; border-color: var(--md-sys-color-secondary); background: color-mix(in srgb, var(--md-sys-color-secondary-container) 55%, transparent);">
11253
+ <div><strong>Compatibilidade / importação:</strong></div>
11254
+ <ul style="margin:6px 0 0 18px; padding:0;">
11255
+ <li *ngFor="let warn of rendererImportWarnings">{{ warn }}</li>
11256
+ </ul>
11257
+ </div> }
10916
11258
 
10917
11259
  @if (rendererPreviewEnabled) { <div class="renderer-preview" style="grid-column: 1/-1;">
10918
11260
  <div style="display:flex; align-items:center; gap:8px; margin-bottom:6px;">
@@ -10951,6 +11293,17 @@ class ColumnsConfigEditorComponent {
10951
11293
  <ng-container *ngSwitchCase="'progress'">
10952
11294
  <div class="pfx-progress"><div class="pfx-progress-bar" [style.width.%]="getPreviewProgressValue(row)"></div></div>
10953
11295
  </ng-container>
11296
+ <ng-container *ngSwitchCase="'rating'">
11297
+ <praxis-table-rating
11298
+ class="pfx-rating-cell"
11299
+ [itemsCount]="getPreviewRatingMax()"
11300
+ [value]="getPreviewRatingValue(row)"
11301
+ [size]="getPreviewRatingSize()"
11302
+ [ratingColor]="getPreviewRatingColor()"
11303
+ [outlineColor]="getPreviewRatingOutlineColor()"
11304
+ [ariaLabel]="getPreviewRatingAriaLabel() || 'Avaliação'">
11305
+ </praxis-table-rating>
11306
+ </ng-container>
10954
11307
  <ng-container *ngSwitchCase="'avatar'">
10955
11308
  @if (getPreviewAvatarSrc(row); as asrc) { <ng-container>
10956
11309
  <img class="pfx-avatar" [src]="asrc" [ngStyle]="getPreviewAvatarStyle()" [class.shape-rounded]="getPreviewAvatarShape() === 'rounded'" [class.shape-circle]="getPreviewAvatarShape() === 'circle'" />
@@ -10967,7 +11320,24 @@ class ColumnsConfigEditorComponent {
10967
11320
  </ng-container>
10968
11321
  <ng-container *ngSwitchCase="'compose'">
10969
11322
  <span class="pfx-compose">
10970
- <span class="pfx-chip pfx-chip--outlined" *ngFor="let it of getComposeItemsUI()">{{ it.type }}</span>
11323
+ <ng-container *ngFor="let it of getComposePreviewItems(row)">
11324
+ <ng-container [ngSwitch]="it.type">
11325
+ <praxis-table-rating
11326
+ *ngSwitchCase="'rating'"
11327
+ class="pfx-rating-cell"
11328
+ [itemsCount]="getComposePreviewRatingMax(it)"
11329
+ [value]="getComposePreviewRatingValue(it, row)"
11330
+ [size]="getComposePreviewRatingSize(it)"
11331
+ [ratingColor]="getComposePreviewRatingColor(it)"
11332
+ [outlineColor]="getComposePreviewRatingOutlineColor(it)"
11333
+ [ariaLabel]="getComposePreviewRatingAriaLabel(it) || 'Avaliação'">
11334
+ </praxis-table-rating>
11335
+ <span *ngSwitchDefault class="pfx-chip pfx-chip--outlined">{{ it.type }}</span>
11336
+ </ng-container>
11337
+ </ng-container>
11338
+ </span>
11339
+ <span style="display:block; opacity:.7; margin-top:4px; font-size:12px;">
11340
+ Preview do compose renderiza o rating real e resume os demais itens pelo tipo.
10971
11341
  </span>
10972
11342
  </ng-container>
10973
11343
  <ng-container *ngSwitchDefault>
@@ -11086,7 +11456,7 @@ class ColumnsConfigEditorComponent {
11086
11456
  </div>
11087
11457
  </div>
11088
11458
  </div>
11089
- `, isInline: true, styles: [".columns-config-editor{display:flex;flex-direction:column;flex:1 1 auto;min-height:0;gap:16px}.educational-card{background:var(--md-sys-color-surface-container-low);border-left:4px solid var(--md-sys-color-primary);margin-bottom:12px}.inline-icon{font-size:18px;width:18px;height:18px;color:var(--md-sys-color-primary)}.help-icon-button{--mdc-icon-button-state-layer-size: 28px;--mdc-icon-button-icon-size: 18px;width:28px;height:28px;padding:0;display:inline-flex;align-items:center;justify-content:center;vertical-align:middle}.help-icon-button mat-icon{font-size:18px;line-height:18px;width:18px;height:18px}.global-config-accordion{margin-bottom:16px}.global-config-panel{background:var(--md-sys-color-surface-container);border-left:4px solid var(--md-sys-color-secondary)}.config-panel-content{padding:16px 20px 20px}.config-layout{display:flex;flex-wrap:wrap;gap:24px;align-items:flex-start}.config-group{display:flex;flex-direction:column;min-width:0}.config-group:not(.features-group){flex:0 0 auto}.features-group{flex:1 1 300px;min-width:300px}.control-section{display:flex;flex-direction:column;gap:8px}.control-label{font-size:.875rem;font-weight:500;color:var(--md-sys-color-on-surface);margin:0}.control-status{font-weight:400;color:var(--md-sys-color-on-surface-variant);font-size:.75rem;margin-left:4px}.visibility-toggle-group,.alignment-toggle-group{display:flex}.visibility-toggle-group .mat-button-toggle{min-width:90px;height:40px}.alignment-toggle-group .mat-button-toggle{min-width:56px;width:auto;height:40px;padding:0 8px}.features-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));gap:12px;margin-top:4px}.feature-checkbox{justify-self:start}.master-detail-layout{display:flex;flex:1;gap:16px;min-height:0}.master-panel{flex:0 0 350px;display:flex;flex-direction:column;background:var(--md-sys-color-surface-container-low);border-radius:8px;overflow:hidden}.list-header{display:flex;justify-content:space-between;align-items:center;padding:16px;background:var(--md-sys-color-surface-container);border-bottom:1px solid var(--md-sys-color-outline-variant)}.list-header h3{margin:0;font-size:1.1rem;font-weight:500}.add-column-fab{transform:scale(.7)}.columns-list-container{flex:1;overflow-y:auto}.columns-list{padding:0}.column-item{border-bottom:1px solid var(--md-sys-color-outline-variant);cursor:pointer;transition:background-color .2s}.column-item:hover{background:var(--md-sys-color-surface-container)}.column-item.selected{background:var(--md-sys-color-primary-container);color:var(--md-sys-color-on-primary-container)}.column-item-content{display:flex;justify-content:space-between;align-items:center;width:100%;padding:12px 16px}.column-main-info{flex:1;display:flex;flex-direction:column;gap:4px}.column-header{display:flex;align-items:center;gap:8px;width:100%}.drag-handle{cursor:grab;color:var(--md-sys-color-on-surface-variant);font-size:18px;flex-shrink:0}.column-text-info{flex:1;display:flex;flex-direction:column;gap:2px;min-width:0}.column-title{font-weight:600;font-size:.9rem;color:var(--md-sys-color-on-surface);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.column-field{font-size:.75rem;color:var(--md-sys-color-on-surface-variant);font-family:monospace;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.column-indicators{display:flex;align-items:center;gap:6px;flex-shrink:0}.column-type-icon,.mapping-indicator-icon,.renderer-indicator-icon{font-size:16px;color:var(--md-sys-color-on-surface-variant)}.visibility-checkbox{transform:scale(.9)}.remove-button{opacity:.7;transition:opacity .2s}.remove-button:hover{opacity:1}.detail-panel{flex:1;display:flex;flex-direction:column;background:var(--md-sys-color-surface-container-low);border-radius:8px;overflow:hidden}.no-selection-message{display:flex;flex-direction:column;align-items:center;justify-content:center;flex:1;text-align:center;padding:48px;color:var(--md-sys-color-on-surface-variant)}.no-selection-message mat-icon{font-size:48px;width:48px;height:48px;margin-bottom:16px}.editor-header{padding:16px 24px;background:var(--md-sys-color-surface-container);border-bottom:1px solid var(--md-sys-color-outline-variant)}.editor-title{margin:0;font-size:1.1rem;font-weight:500;color:var(--md-sys-color-on-surface)}.column-form{flex:1;padding:24px;overflow:visible}.form-row{display:flex;gap:16px;margin-bottom:24px;align-items:flex-start}.field-input,.header-input,.width-input,.data-type-input{flex:1}.header-input{flex:2}.alignment-group,.sticky-group{display:flex;flex-direction:column;gap:8px}.control-label{font-size:.875rem;font-weight:500;color:var(--md-sys-color-on-surface)}.renderer-grid,.renderer-config{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:12px}.renderer-actions{display:flex;gap:8px;align-items:center;flex-wrap:wrap;margin-top:8px}.renderer-errors{background:var(--md-sys-color-error-container);color:var(--md-sys-color-on-error-container);border:1px solid var(--md-sys-color-error);padding:8px 12px;border-radius:6px;font-size:.85rem}.renderer-preview{margin-top:8px;padding:8px 12px;background:var(--md-sys-color-surface-container-low);border:1px solid var(--md-sys-color-outline-variant);border-radius:6px}.renderer-preview-list{display:flex;gap:12px;align-items:center;flex-wrap:wrap}.renderer-preview-list .pfx-compose{display:inline-flex;gap:6px;align-items:center}.pfx-badge{display:inline-flex;align-items:center;gap:4px;padding:2px 6px;border-radius:10px;font-size:12px;line-height:1}.pfx-badge-icon{font-size:14px;width:14px;height:14px}.pfx-badge--outlined{border:1px solid var(--md-sys-color-outline-variant);color:var(--md-sys-color-on-surface);background:transparent}.pfx-badge--filled-primary{background:var(--md-sys-color-primary);color:var(--md-sys-color-on-primary)}.pfx-badge--filled-accent{background:var(--md-sys-color-secondary);color:var(--md-sys-color-on-secondary)}.pfx-badge--filled-warn{background:var(--md-sys-color-error);color:var(--md-sys-color-on-error)}.pfx-badge--soft-primary{background:var(--md-sys-color-primary-container);color:var(--md-sys-color-on-primary-container)}.pfx-badge--soft-accent{background:var(--md-sys-color-secondary-container);color:var(--md-sys-color-on-secondary-container)}.pfx-badge--soft-warn{background:var(--md-sys-color-error-container);color:var(--md-sys-color-on-error-container)}.pfx-cell-image{display:inline-block;border-radius:4px;object-fit:cover}.pfx-link{color:var(--md-sys-color-primary);text-decoration:underline;cursor:pointer}.pfx-chip{display:inline-flex;align-items:center;gap:4px;padding:2px 8px;border-radius:10px;font-size:12px;border:1px solid transparent}.pfx-chip--outlined{border-color:var(--md-sys-color-outline-variant);color:var(--md-sys-color-on-surface)}.pfx-chip--filled-primary{background:var(--md-sys-color-primary);color:var(--md-sys-color-on-primary)}.pfx-chip--filled-accent{background:var(--md-sys-color-secondary);color:var(--md-sys-color-on-secondary)}.pfx-chip--filled-warn{background:var(--md-sys-color-error);color:var(--md-sys-color-on-error)}.pfx-chip--soft-primary{background:var(--md-sys-color-primary-container);color:var(--md-sys-color-on-primary-container)}.pfx-chip--soft-accent{background:var(--md-sys-color-secondary-container);color:var(--md-sys-color-on-secondary-container)}.pfx-chip--soft-warn{background:var(--md-sys-color-error-container);color:var(--md-sys-color-on-error-container)}.pfx-progress{position:relative;width:120px;height:8px;background:var(--md-sys-color-surface-container-highest);border-radius:4px;overflow:hidden}.pfx-progress-bar{height:100%;background:var(--md-sys-color-primary)}.pfx-avatar{display:inline-flex;align-items:center;justify-content:center;background:var(--md-sys-color-surface-container);color:var(--md-sys-color-on-surface);border-radius:4px;overflow:hidden;font-weight:600;width:32px;height:32px}.pfx-avatar.shape-rounded{border-radius:8px}.pfx-avatar.shape-circle{border-radius:999px}.pfx-avatar--initials{text-transform:uppercase;font-size:12px}@media(max-width:768px){.master-detail-layout{flex-direction:column}.master-panel{flex:0 0 auto;max-height:300px}.form-row{flex-direction:column;gap:12px}.config-layout{flex-direction:column;gap:20px}.features-group{min-width:auto}.features-grid{grid-template-columns:1fr;gap:8px}.visibility-toggle-group .mat-button-toggle{min-width:80px;font-size:.875rem}}@media(max-width:480px){.visibility-toggle-group .mat-button-toggle{min-width:70px;font-size:.8rem}.alignment-toggle-group .mat-button-toggle{min-width:48px;padding:0 6px}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$2.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: i1$2.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i1$2.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "directive", type: i1$2.NgSwitchDefault, selector: "[ngSwitchDefault]" }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i1$1.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3.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: "component", type: i3.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i3.MatFabButton, selector: "button[mat-fab], a[mat-fab], button[matFab], a[matFab]", inputs: ["extended"], exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i5.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i6.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i6.MatLabel, selector: "mat-label" }, { kind: "directive", type: i6.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i7.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: MatCardModule }, { kind: "component", type: i10$1.MatCard, selector: "mat-card", inputs: ["appearance"], exportAs: ["matCard"] }, { kind: "directive", type: i10$1.MatCardContent, selector: "mat-card-content" }, { kind: "ngmodule", type: MatCheckboxModule }, { kind: "component", type: i9.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "ngmodule", type: MatButtonToggleModule }, { kind: "directive", type: i15$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: i15$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: MatSelectModule }, { kind: "component", type: i5$2.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: i5$2.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatListModule }, { kind: "component", type: i11.MatList, selector: "mat-list", exportAs: ["matList"] }, { kind: "component", type: i11.MatListItem, selector: "mat-list-item, a[mat-list-item], button[mat-list-item]", inputs: ["activated"], exportAs: ["matListItem"] }, { kind: "component", type: i10$2.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "ngmodule", type: MatDividerModule }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i10.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: MatExpansionModule }, { kind: "directive", type: i8.MatAccordion, selector: "mat-accordion", inputs: ["hideToggle", "displayMode", "togglePosition"], exportAs: ["matAccordion"] }, { kind: "component", type: i8.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "component", type: i8.MatExpansionPanelHeader, selector: "mat-expansion-panel-header", inputs: ["expandedHeight", "collapsedHeight", "tabIndex"] }, { kind: "directive", type: i8.MatExpansionPanelTitle, selector: "mat-panel-title" }, { kind: "directive", type: i8.MatExpansionPanelDescription, selector: "mat-panel-description" }, { kind: "ngmodule", type: MatBadgeModule }, { kind: "directive", type: i14.MatBadge, selector: "[matBadge]", inputs: ["matBadgeColor", "matBadgeOverlap", "matBadgeDisabled", "matBadgePosition", "matBadge", "matBadgeDescription", "matBadgeSize", "matBadgeHidden"] }, { kind: "ngmodule", type: MatSlideToggleModule }, { kind: "component", type: i6$1.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: DragDropModule }, { kind: "directive", type: i13.CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer", "cdkDropListHasAnchor"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: i13.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "directive", type: i13.CdkDragHandle, selector: "[cdkDragHandle]", inputs: ["cdkDragHandleDisabled"] }, { kind: "component", type: VisualFormulaBuilderComponent, selector: "visual-formula-builder", inputs: ["availableDataSchema", "currentFormula"], outputs: ["formulaChange", "generatedExpressionChange"] }, { kind: "component", type: ValueMappingEditorComponent, selector: "value-mapping-editor", inputs: ["currentMapping", "keyInputType", "labelKey", "labelValue"], outputs: ["mappingChange"] }, { kind: "component", type: DataFormatterComponent, selector: "data-formatter", inputs: ["columnType", "currentFormat"], outputs: ["formatChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
11459
+ `, isInline: true, styles: [".columns-config-editor{display:flex;flex-direction:column;flex:1 1 auto;min-height:0;gap:16px}.educational-card{background:var(--md-sys-color-surface-container-low);border-left:4px solid var(--md-sys-color-primary);margin-bottom:12px}.inline-icon{font-size:18px;width:18px;height:18px;color:var(--md-sys-color-primary)}.help-icon-button{--mdc-icon-button-state-layer-size: 28px;--mdc-icon-button-icon-size: 18px;width:28px;height:28px;padding:0;display:inline-flex;align-items:center;justify-content:center;vertical-align:middle}.help-icon-button mat-icon{font-size:18px;line-height:18px;width:18px;height:18px}.global-config-accordion{margin-bottom:16px}.global-config-panel{background:var(--md-sys-color-surface-container);border-left:4px solid var(--md-sys-color-secondary)}.config-panel-content{padding:16px 20px 20px}.config-layout{display:flex;flex-wrap:wrap;gap:24px;align-items:flex-start}.config-group{display:flex;flex-direction:column;min-width:0}.config-group:not(.features-group){flex:0 0 auto}.features-group{flex:1 1 300px;min-width:300px}.control-section{display:flex;flex-direction:column;gap:8px}.control-label{font-size:.875rem;font-weight:500;color:var(--md-sys-color-on-surface);margin:0}.control-status{font-weight:400;color:var(--md-sys-color-on-surface-variant);font-size:.75rem;margin-left:4px}.visibility-toggle-group,.alignment-toggle-group{display:flex}.visibility-toggle-group .mat-button-toggle{min-width:90px;height:40px}.alignment-toggle-group .mat-button-toggle{min-width:56px;width:auto;height:40px;padding:0 8px}.features-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));gap:12px;margin-top:4px}.feature-checkbox{justify-self:start}.master-detail-layout{display:flex;flex:1;gap:16px;min-height:0}.master-panel{flex:0 0 350px;display:flex;flex-direction:column;background:var(--md-sys-color-surface-container-low);border-radius:8px;overflow:hidden}.list-header{display:flex;justify-content:space-between;align-items:center;padding:16px;background:var(--md-sys-color-surface-container);border-bottom:1px solid var(--md-sys-color-outline-variant)}.list-header h3{margin:0;font-size:1.1rem;font-weight:500}.add-column-fab{transform:scale(.7)}.columns-list-container{flex:1;overflow-y:auto}.columns-list{padding:0}.column-item{border-bottom:1px solid var(--md-sys-color-outline-variant);cursor:pointer;transition:background-color .2s}.column-item:hover{background:var(--md-sys-color-surface-container)}.column-item.selected{background:var(--md-sys-color-primary-container);color:var(--md-sys-color-on-primary-container)}.column-item-content{display:flex;justify-content:space-between;align-items:center;width:100%;padding:12px 16px}.column-main-info{flex:1;display:flex;flex-direction:column;gap:4px}.column-header{display:flex;align-items:center;gap:8px;width:100%}.drag-handle{cursor:grab;color:var(--md-sys-color-on-surface-variant);font-size:18px;flex-shrink:0}.column-text-info{flex:1;display:flex;flex-direction:column;gap:2px;min-width:0}.column-title{font-weight:600;font-size:.9rem;color:var(--md-sys-color-on-surface);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.column-field{font-size:.75rem;color:var(--md-sys-color-on-surface-variant);font-family:monospace;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.column-indicators{display:flex;align-items:center;gap:6px;flex-shrink:0}.column-type-icon,.mapping-indicator-icon,.renderer-indicator-icon{font-size:16px;color:var(--md-sys-color-on-surface-variant)}.visibility-checkbox{transform:scale(.9)}.remove-button{opacity:.7;transition:opacity .2s}.remove-button:hover{opacity:1}.detail-panel{flex:1;display:flex;flex-direction:column;background:var(--md-sys-color-surface-container-low);border-radius:8px;overflow:hidden}.no-selection-message{display:flex;flex-direction:column;align-items:center;justify-content:center;flex:1;text-align:center;padding:48px;color:var(--md-sys-color-on-surface-variant)}.no-selection-message mat-icon{font-size:48px;width:48px;height:48px;margin-bottom:16px}.editor-header{padding:16px 24px;background:var(--md-sys-color-surface-container);border-bottom:1px solid var(--md-sys-color-outline-variant)}.editor-title{margin:0;font-size:1.1rem;font-weight:500;color:var(--md-sys-color-on-surface)}.column-form{flex:1;padding:24px;overflow:visible}.form-row{display:flex;gap:16px;margin-bottom:24px;align-items:flex-start}.field-input,.header-input,.width-input,.data-type-input{flex:1}.header-input{flex:2}.alignment-group,.sticky-group{display:flex;flex-direction:column;gap:8px}.control-label{font-size:.875rem;font-weight:500;color:var(--md-sys-color-on-surface)}.renderer-grid,.renderer-config{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:12px}.renderer-actions{display:flex;gap:8px;align-items:center;flex-wrap:wrap;margin-top:8px}.renderer-errors{background:var(--md-sys-color-error-container);color:var(--md-sys-color-on-error-container);border:1px solid var(--md-sys-color-error);padding:8px 12px;border-radius:6px;font-size:.85rem}.renderer-preview{margin-top:8px;padding:8px 12px;background:var(--md-sys-color-surface-container-low);border:1px solid var(--md-sys-color-outline-variant);border-radius:6px}.renderer-preview-list{display:flex;gap:12px;align-items:center;flex-wrap:wrap}.renderer-preview-list .pfx-compose{display:inline-flex;gap:6px;align-items:center}.pfx-badge{display:inline-flex;align-items:center;gap:4px;padding:2px 6px;border-radius:10px;font-size:12px;line-height:1}.pfx-badge-icon{font-size:14px;width:14px;height:14px}.pfx-badge--outlined{border:1px solid var(--md-sys-color-outline-variant);color:var(--md-sys-color-on-surface);background:transparent}.pfx-badge--filled-primary{background:var(--md-sys-color-primary);color:var(--md-sys-color-on-primary)}.pfx-badge--filled-accent{background:var(--md-sys-color-secondary);color:var(--md-sys-color-on-secondary)}.pfx-badge--filled-warn{background:var(--md-sys-color-error);color:var(--md-sys-color-on-error)}.pfx-badge--soft-primary{background:var(--md-sys-color-primary-container);color:var(--md-sys-color-on-primary-container)}.pfx-badge--soft-accent{background:var(--md-sys-color-secondary-container);color:var(--md-sys-color-on-secondary-container)}.pfx-badge--soft-warn{background:var(--md-sys-color-error-container);color:var(--md-sys-color-on-error-container)}.pfx-cell-image{display:inline-block;border-radius:4px;object-fit:cover}.pfx-link{color:var(--md-sys-color-primary);text-decoration:underline;cursor:pointer}.pfx-chip{display:inline-flex;align-items:center;gap:4px;padding:2px 8px;border-radius:10px;font-size:12px;border:1px solid transparent}.pfx-chip--outlined{border-color:var(--md-sys-color-outline-variant);color:var(--md-sys-color-on-surface)}.pfx-chip--filled-primary{background:var(--md-sys-color-primary);color:var(--md-sys-color-on-primary)}.pfx-chip--filled-accent{background:var(--md-sys-color-secondary);color:var(--md-sys-color-on-secondary)}.pfx-chip--filled-warn{background:var(--md-sys-color-error);color:var(--md-sys-color-on-error)}.pfx-chip--soft-primary{background:var(--md-sys-color-primary-container);color:var(--md-sys-color-on-primary-container)}.pfx-chip--soft-accent{background:var(--md-sys-color-secondary-container);color:var(--md-sys-color-on-secondary-container)}.pfx-chip--soft-warn{background:var(--md-sys-color-error-container);color:var(--md-sys-color-on-error-container)}.pfx-progress{position:relative;width:120px;height:8px;background:var(--md-sys-color-surface-container-highest);border-radius:4px;overflow:hidden}.pfx-progress-bar{height:100%;background:var(--md-sys-color-primary)}.pfx-avatar{display:inline-flex;align-items:center;justify-content:center;background:var(--md-sys-color-surface-container);color:var(--md-sys-color-on-surface);border-radius:4px;overflow:hidden;font-weight:600;width:32px;height:32px}.pfx-avatar.shape-rounded{border-radius:8px}.pfx-avatar.shape-circle{border-radius:999px}.pfx-avatar--initials{text-transform:uppercase;font-size:12px}@media(max-width:768px){.master-detail-layout{flex-direction:column}.master-panel{flex:0 0 auto;max-height:300px}.form-row{flex-direction:column;gap:12px}.config-layout{flex-direction:column;gap:20px}.features-group{min-width:auto}.features-grid{grid-template-columns:1fr;gap:8px}.visibility-toggle-group .mat-button-toggle{min-width:80px;font-size:.875rem}}@media(max-width:480px){.visibility-toggle-group .mat-button-toggle{min-width:70px;font-size:.8rem}.alignment-toggle-group .mat-button-toggle{min-width:48px;padding:0 6px}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$2.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: i1$2.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i1$2.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "directive", type: i1$2.NgSwitchDefault, selector: "[ngSwitchDefault]" }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i1$1.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3.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: "component", type: i3.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i3.MatFabButton, selector: "button[mat-fab], a[mat-fab], button[matFab], a[matFab]", inputs: ["extended"], exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i5.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i6.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i6.MatLabel, selector: "mat-label" }, { kind: "directive", type: i6.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i7.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: MatCardModule }, { kind: "component", type: i10$1.MatCard, selector: "mat-card", inputs: ["appearance"], exportAs: ["matCard"] }, { kind: "directive", type: i10$1.MatCardContent, selector: "mat-card-content" }, { kind: "ngmodule", type: MatCheckboxModule }, { kind: "component", type: i9.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "ngmodule", type: MatButtonToggleModule }, { kind: "directive", type: i15$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: i15$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: MatSelectModule }, { kind: "component", type: i5$1.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: i5$1.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatListModule }, { kind: "component", type: i11.MatList, selector: "mat-list", exportAs: ["matList"] }, { kind: "component", type: i11.MatListItem, selector: "mat-list-item, a[mat-list-item], button[mat-list-item]", inputs: ["activated"], exportAs: ["matListItem"] }, { kind: "component", type: i10$2.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "ngmodule", type: MatDividerModule }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i10.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: MatExpansionModule }, { kind: "directive", type: i8.MatAccordion, selector: "mat-accordion", inputs: ["hideToggle", "displayMode", "togglePosition"], exportAs: ["matAccordion"] }, { kind: "component", type: i8.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "component", type: i8.MatExpansionPanelHeader, selector: "mat-expansion-panel-header", inputs: ["expandedHeight", "collapsedHeight", "tabIndex"] }, { kind: "directive", type: i8.MatExpansionPanelTitle, selector: "mat-panel-title" }, { kind: "directive", type: i8.MatExpansionPanelDescription, selector: "mat-panel-description" }, { kind: "ngmodule", type: MatBadgeModule }, { kind: "directive", type: i15$2.MatBadge, selector: "[matBadge]", inputs: ["matBadgeColor", "matBadgeOverlap", "matBadgeDisabled", "matBadgePosition", "matBadge", "matBadgeDescription", "matBadgeSize", "matBadgeHidden"] }, { kind: "ngmodule", type: MatSlideToggleModule }, { kind: "component", type: i6$1.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: DragDropModule }, { kind: "directive", type: i12.CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer", "cdkDropListHasAnchor"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: i12.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "directive", type: i12.CdkDragHandle, selector: "[cdkDragHandle]", inputs: ["cdkDragHandleDisabled"] }, { kind: "component", type: VisualFormulaBuilderComponent, selector: "visual-formula-builder", inputs: ["availableDataSchema", "currentFormula"], outputs: ["formulaChange", "generatedExpressionChange"] }, { kind: "component", type: ValueMappingEditorComponent, selector: "value-mapping-editor", inputs: ["currentMapping", "keyInputType", "labelKey", "labelValue"], outputs: ["mappingChange"] }, { kind: "component", type: DataFormatterComponent, selector: "data-formatter", inputs: ["columnType", "currentFormat"], outputs: ["formatChange"] }, { kind: "component", type: TableRatingCellComponent, selector: "praxis-table-rating", inputs: ["itemsCount", "value", "size", "ratingColor", "outlineColor", "ariaLabel"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
11090
11460
  }
11091
11461
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: ColumnsConfigEditorComponent, decorators: [{
11092
11462
  type: Component,
@@ -11111,6 +11481,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
11111
11481
  VisualFormulaBuilderComponent,
11112
11482
  ValueMappingEditorComponent,
11113
11483
  DataFormatterComponent,
11484
+ TableRatingCellComponent,
11114
11485
  ], template: `
11115
11486
  <div class="columns-config-editor">
11116
11487
  <!-- Educational Card - Compact -->
@@ -11715,7 +12086,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
11715
12086
  Renderização da Célula
11716
12087
  </mat-panel-title>
11717
12088
  <mat-panel-description>
11718
- Ícone, imagem ou badge no lugar do texto
12089
+ Ícone, imagem, rating e outros renderers no lugar do texto
11719
12090
  </mat-panel-description>
11720
12091
  </mat-expansion-panel-header>
11721
12092
 
@@ -12068,6 +12439,43 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
12068
12439
  </div>
12069
12440
  }
12070
12441
 
12442
+ <!-- Rating configuration -->
12443
+ @if (uiRendererType === 'rating') {
12444
+ <div class="renderer-config">
12445
+ <mat-form-field appearance="outline">
12446
+ <mat-label>Expressão de valor</mat-label>
12447
+ <input matInput [value]="getRendererProp('rating','valueExpr') || ''" (input)="setRendererProp('rating','valueExpr',$any($event.target).value)" placeholder="= Number(row.score || 0) / 20" />
12448
+ </mat-form-field>
12449
+ <mat-form-field appearance="outline">
12450
+ <mat-label>Máximo de itens</mat-label>
12451
+ <input matInput type="number" min="1" [value]="getRendererProp('rating','max') || 5" (input)="setRendererProp('rating','max',$any($event.target).valueAsNumber)" />
12452
+ </mat-form-field>
12453
+ <mat-form-field appearance="outline">
12454
+ <mat-label>Cor do preenchimento</mat-label>
12455
+ <input matInput [value]="getRendererProp('rating','color') || ''" (input)="setRendererProp('rating','color',$any($event.target).value)" placeholder="#f59e0b" />
12456
+ </mat-form-field>
12457
+ <mat-form-field appearance="outline">
12458
+ <mat-label>Cor do contorno</mat-label>
12459
+ <input matInput [value]="getRendererProp('rating','outlineColor') || ''" (input)="setRendererProp('rating','outlineColor',$any($event.target).value)" placeholder="#cbd5e1" />
12460
+ </mat-form-field>
12461
+ <mat-form-field appearance="outline">
12462
+ <mat-label>Tamanho</mat-label>
12463
+ <mat-select [ngModel]="getRendererProp('rating','size') || 'medium'" [ngModelOptions]="{standalone: true}" (ngModelChange)="setRendererProp('rating','size',$event)">
12464
+ <mat-option value="small">Pequeno</mat-option>
12465
+ <mat-option value="medium">Médio</mat-option>
12466
+ <mat-option value="large">Grande</mat-option>
12467
+ </mat-select>
12468
+ </mat-form-field>
12469
+ <mat-form-field appearance="outline">
12470
+ <mat-label>aria-label</mat-label>
12471
+ <input matInput [value]="getRendererProp('rating','ariaLabel') || ''" (input)="setRendererProp('rating','ariaLabel',$any($event.target).value)" [placeholder]="ratingAriaLabelPlaceholder" />
12472
+ </mat-form-field>
12473
+ <div class="renderer-hint" style="grid-column: 1/-1; opacity:.78;">
12474
+ {{ ratingRendererHint }}
12475
+ </div>
12476
+ </div>
12477
+ }
12478
+
12071
12479
  <!-- Avatar configuration -->
12072
12480
  @if (uiRendererType === 'avatar') {
12073
12481
  <div class="renderer-config">
@@ -12195,6 +12603,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
12195
12603
  <button mat-stroked-button (click)="addComposeItem('badge')">Adicionar Badge</button>
12196
12604
  <button mat-stroked-button (click)="addComposeItem('chip')">Adicionar Chip</button>
12197
12605
  <button mat-stroked-button (click)="addComposeItem('progress')">Adicionar Progresso</button>
12606
+ <button mat-stroked-button (click)="addComposeItem('rating')">Adicionar Rating</button>
12198
12607
  <button mat-stroked-button (click)="addComposeItem('avatar')">Adicionar Avatar</button>
12199
12608
  <button mat-stroked-button (click)="addComposeItem('button')">Adicionar Botão</button>
12200
12609
  <button mat-stroked-button (click)="addComposeItem('toggle')">Adicionar Toggle</button>
@@ -12211,6 +12620,44 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
12211
12620
  <button mat-icon-button color="warn" (click)="removeComposeItem(i); $event.stopPropagation();"><mat-icon>delete</mat-icon></button>
12212
12621
  </div>
12213
12622
  </div>
12623
+ @if (getSelectedComposeItem(); as selectedCompose) {
12624
+ @if (selectedCompose.type === 'rating') {
12625
+ <div style="display:grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap:12px; margin-top:12px; padding:12px; border:1px solid var(--md-sys-color-outline-variant); border-radius:8px;">
12626
+ <div style="grid-column: 1/-1; font-weight:600;">Compose item: Rating</div>
12627
+ <mat-form-field appearance="outline">
12628
+ <mat-label>Expressão de valor</mat-label>
12629
+ <input matInput [value]="getSelectedComposeItemProp('rating.valueExpr') || ''" (input)="setSelectedComposeItemProp('rating.valueExpr', $any($event.target).value)" placeholder="= Number(row.score || 0) / 20" />
12630
+ </mat-form-field>
12631
+ <mat-form-field appearance="outline">
12632
+ <mat-label>Máximo de itens</mat-label>
12633
+ <input matInput type="number" min="1" [value]="getSelectedComposeItemProp('rating.max') || 5" (input)="setSelectedComposeItemProp('rating.max', $any($event.target).valueAsNumber)" />
12634
+ </mat-form-field>
12635
+ <mat-form-field appearance="outline">
12636
+ <mat-label>Cor do preenchimento</mat-label>
12637
+ <input matInput [value]="getSelectedComposeItemProp('rating.color') || ''" (input)="setSelectedComposeItemProp('rating.color', $any($event.target).value)" placeholder="#f59e0b" />
12638
+ </mat-form-field>
12639
+ <mat-form-field appearance="outline">
12640
+ <mat-label>Cor do contorno</mat-label>
12641
+ <input matInput [value]="getSelectedComposeItemProp('rating.outlineColor') || ''" (input)="setSelectedComposeItemProp('rating.outlineColor', $any($event.target).value)" placeholder="#cbd5e1" />
12642
+ </mat-form-field>
12643
+ <mat-form-field appearance="outline">
12644
+ <mat-label>Tamanho</mat-label>
12645
+ <mat-select [ngModel]="getSelectedComposeItemProp('rating.size') || 'medium'" [ngModelOptions]="{standalone: true}" (ngModelChange)="setSelectedComposeItemProp('rating.size', $event)">
12646
+ <mat-option value="small">Pequeno</mat-option>
12647
+ <mat-option value="medium">Médio</mat-option>
12648
+ <mat-option value="large">Grande</mat-option>
12649
+ </mat-select>
12650
+ </mat-form-field>
12651
+ <mat-form-field appearance="outline">
12652
+ <mat-label>aria-label</mat-label>
12653
+ <input matInput [value]="getSelectedComposeItemProp('rating.ariaLabel') || ''" (input)="setSelectedComposeItemProp('rating.ariaLabel', $any($event.target).value)" [placeholder]="ratingAriaLabelPlaceholder" />
12654
+ </mat-form-field>
12655
+ <div style="grid-column: 1/-1; opacity:.78;">
12656
+ {{ composeRatingRendererHint }}
12657
+ </div>
12658
+ </div>
12659
+ }
12660
+ }
12214
12661
  <div style="display:grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap:12px; margin-top:12px;">
12215
12662
  <mat-form-field appearance="outline">
12216
12663
  <mat-label>Direção</mat-label>
@@ -12262,6 +12709,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
12262
12709
  <li *ngFor="let err of rendererValidationErrors">{{ err }}</li>
12263
12710
  </ul>
12264
12711
  </div> }
12712
+ @if (rendererImportWarnings.length) { <div class="renderer-errors" style="grid-column: 1/-1; border-color: var(--md-sys-color-secondary); background: color-mix(in srgb, var(--md-sys-color-secondary-container) 55%, transparent);">
12713
+ <div><strong>Compatibilidade / importação:</strong></div>
12714
+ <ul style="margin:6px 0 0 18px; padding:0;">
12715
+ <li *ngFor="let warn of rendererImportWarnings">{{ warn }}</li>
12716
+ </ul>
12717
+ </div> }
12265
12718
 
12266
12719
  @if (rendererPreviewEnabled) { <div class="renderer-preview" style="grid-column: 1/-1;">
12267
12720
  <div style="display:flex; align-items:center; gap:8px; margin-bottom:6px;">
@@ -12300,6 +12753,17 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
12300
12753
  <ng-container *ngSwitchCase="'progress'">
12301
12754
  <div class="pfx-progress"><div class="pfx-progress-bar" [style.width.%]="getPreviewProgressValue(row)"></div></div>
12302
12755
  </ng-container>
12756
+ <ng-container *ngSwitchCase="'rating'">
12757
+ <praxis-table-rating
12758
+ class="pfx-rating-cell"
12759
+ [itemsCount]="getPreviewRatingMax()"
12760
+ [value]="getPreviewRatingValue(row)"
12761
+ [size]="getPreviewRatingSize()"
12762
+ [ratingColor]="getPreviewRatingColor()"
12763
+ [outlineColor]="getPreviewRatingOutlineColor()"
12764
+ [ariaLabel]="getPreviewRatingAriaLabel() || 'Avaliação'">
12765
+ </praxis-table-rating>
12766
+ </ng-container>
12303
12767
  <ng-container *ngSwitchCase="'avatar'">
12304
12768
  @if (getPreviewAvatarSrc(row); as asrc) { <ng-container>
12305
12769
  <img class="pfx-avatar" [src]="asrc" [ngStyle]="getPreviewAvatarStyle()" [class.shape-rounded]="getPreviewAvatarShape() === 'rounded'" [class.shape-circle]="getPreviewAvatarShape() === 'circle'" />
@@ -12316,7 +12780,24 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
12316
12780
  </ng-container>
12317
12781
  <ng-container *ngSwitchCase="'compose'">
12318
12782
  <span class="pfx-compose">
12319
- <span class="pfx-chip pfx-chip--outlined" *ngFor="let it of getComposeItemsUI()">{{ it.type }}</span>
12783
+ <ng-container *ngFor="let it of getComposePreviewItems(row)">
12784
+ <ng-container [ngSwitch]="it.type">
12785
+ <praxis-table-rating
12786
+ *ngSwitchCase="'rating'"
12787
+ class="pfx-rating-cell"
12788
+ [itemsCount]="getComposePreviewRatingMax(it)"
12789
+ [value]="getComposePreviewRatingValue(it, row)"
12790
+ [size]="getComposePreviewRatingSize(it)"
12791
+ [ratingColor]="getComposePreviewRatingColor(it)"
12792
+ [outlineColor]="getComposePreviewRatingOutlineColor(it)"
12793
+ [ariaLabel]="getComposePreviewRatingAriaLabel(it) || 'Avaliação'">
12794
+ </praxis-table-rating>
12795
+ <span *ngSwitchDefault class="pfx-chip pfx-chip--outlined">{{ it.type }}</span>
12796
+ </ng-container>
12797
+ </ng-container>
12798
+ </span>
12799
+ <span style="display:block; opacity:.7; margin-top:4px; font-size:12px;">
12800
+ Preview do compose renderiza o rating real e resume os demais itens pelo tipo.
12320
12801
  </span>
12321
12802
  </ng-container>
12322
12803
  <ng-container *ngSwitchDefault>
@@ -14285,7 +14766,7 @@ class BehaviorConfigEditorComponent {
14285
14766
  </mat-expansion-panel> }
14286
14767
  </form>
14287
14768
  </div>
14288
- `, isInline: true, styles: [".behavior-config-container{width:100%;padding:8px}.config-section{padding:16px}.mode-constraint-note{margin:0 0 12px;padding:10px 12px;border-radius:8px;border:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container-low);color:var(--md-sys-color-on-surface-variant);font-size:12px;line-height:1.35}.schema-only-note-inline{margin-top:-8px;font-size:12px;color:var(--md-sys-color-on-surface-variant)}.schema-only-note-inline a{color:var(--md-sys-color-primary);text-decoration:underline;margin-left:6px}.config-fields{display:flex;flex-direction:column;gap:16px;margin-top:16px}.toggle-field{display:flex;align-items:center;gap:8px}.section-icon{margin-right:8px;color:var(--md-sys-color-primary)}.info-icon{font-size:18px;width:18px;height:18px;color:var(--md-sys-color-on-surface-variant);cursor:help}.help-icon-button{--mdc-icon-button-state-layer-size: 28px;--mdc-icon-button-icon-size: 18px;width:28px;height:28px;padding:0;display:inline-flex;align-items:center;justify-content:center;vertical-align:middle}.help-icon-button mat-icon{font-size:18px;line-height:18px;width:18px;height:18px}mat-form-field{width:100%}mat-expansion-panel{margin-bottom:8px;border-radius:8px;overflow:hidden}mat-expansion-panel-header{min-height:56px}mat-panel-description{color:var(--md-sys-color-on-surface-variant)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { kind: "directive", type: i1$1.MaxValidator, selector: "input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]", inputs: ["max"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i6.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i6.MatLabel, selector: "mat-label" }, { kind: "directive", type: i6.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "directive", type: i6.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i7.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: i5$2.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: i5$2.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatSlideToggleModule }, { kind: "component", type: i6$1.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: MatExpansionModule }, { kind: "component", type: i8.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "component", type: i8.MatExpansionPanelHeader, selector: "mat-expansion-panel-header", inputs: ["expandedHeight", "collapsedHeight", "tabIndex"] }, { kind: "directive", type: i8.MatExpansionPanelTitle, selector: "mat-panel-title" }, { kind: "directive", type: i8.MatExpansionPanelDescription, selector: "mat-panel-description" }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i5.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i10.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: MatDividerModule }, { kind: "component", type: i10$2.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }] });
14769
+ `, isInline: true, styles: [".behavior-config-container{width:100%;padding:8px}.config-section{padding:16px}.mode-constraint-note{margin:0 0 12px;padding:10px 12px;border-radius:8px;border:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container-low);color:var(--md-sys-color-on-surface-variant);font-size:12px;line-height:1.35}.schema-only-note-inline{margin-top:-8px;font-size:12px;color:var(--md-sys-color-on-surface-variant)}.schema-only-note-inline a{color:var(--md-sys-color-primary);text-decoration:underline;margin-left:6px}.config-fields{display:flex;flex-direction:column;gap:16px;margin-top:16px}.toggle-field{display:flex;align-items:center;gap:8px}.section-icon{margin-right:8px;color:var(--md-sys-color-primary)}.info-icon{font-size:18px;width:18px;height:18px;color:var(--md-sys-color-on-surface-variant);cursor:help}.help-icon-button{--mdc-icon-button-state-layer-size: 28px;--mdc-icon-button-icon-size: 18px;width:28px;height:28px;padding:0;display:inline-flex;align-items:center;justify-content:center;vertical-align:middle}.help-icon-button mat-icon{font-size:18px;line-height:18px;width:18px;height:18px}mat-form-field{width:100%}mat-expansion-panel{margin-bottom:8px;border-radius:8px;overflow:hidden}mat-expansion-panel-header{min-height:56px}mat-panel-description{color:var(--md-sys-color-on-surface-variant)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { kind: "directive", type: i1$1.MaxValidator, selector: "input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]", inputs: ["max"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i6.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i6.MatLabel, selector: "mat-label" }, { kind: "directive", type: i6.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "directive", type: i6.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i7.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: i5$1.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: i5$1.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatSlideToggleModule }, { kind: "component", type: i6$1.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: MatExpansionModule }, { kind: "component", type: i8.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "component", type: i8.MatExpansionPanelHeader, selector: "mat-expansion-panel-header", inputs: ["expandedHeight", "collapsedHeight", "tabIndex"] }, { kind: "directive", type: i8.MatExpansionPanelTitle, selector: "mat-panel-title" }, { kind: "directive", type: i8.MatExpansionPanelDescription, selector: "mat-panel-description" }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i5.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i10.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: MatDividerModule }, { kind: "component", type: i10$2.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }] });
14289
14770
  }
14290
14771
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: BehaviorConfigEditorComponent, decorators: [{
14291
14772
  type: Component,
@@ -18016,7 +18497,7 @@ class ToolbarActionsEditorComponent {
18016
18497
  </mat-expansion-panel> }
18017
18498
  </form>
18018
18499
  </div>
18019
- `, isInline: true, styles: [":host{--tae-primary: var(--md-sys-color-primary);--tae-surface: var(--md-sys-color-surface);--tae-surface-low: var(--md-sys-color-surface-container-low);--tae-surface-variant: var(--md-sys-color-surface-variant);--tae-outline-variant: var(--md-sys-color-outline-variant);--tae-on-surface: var(--md-sys-color-on-surface);--tae-on-surface-variant: var(--md-sys-color-on-surface-variant)}.toolbar-actions-container{width:100%;padding:8px}.config-section{padding:16px}.section-hint{color:var(--tae-on-surface-variant);font-size:12px;margin-bottom:12px}.config-fields{display:flex;flex-direction:column;gap:16px;margin-top:16px}.nested-fields{display:flex;flex-direction:column;gap:12px;margin-left:24px;margin-top:12px;padding:16px;background-color:var(--tae-surface-variant);border-radius:8px}.action-section-title{width:100%;margin:12px 0 4px;font-size:12px;font-weight:600;letter-spacing:.04em;text-transform:uppercase;color:var(--tae-on-surface-variant)}.help-icon-button{--mdc-icon-button-state-layer-size: 28px;--mdc-icon-button-icon-size: 18px;width:28px;height:28px;padding:0;display:inline-flex;align-items:center;justify-content:center;vertical-align:middle}.help-icon-button mat-icon{font-size:18px;line-height:18px;width:18px;height:18px}.action-global-fields .mat-mdc-form-field-icon-suffix{align-self:center}.toggle-field{display:flex;align-items:center;gap:8px}.section-icon{margin-right:8px;color:var(--tae-primary)}.subsection{margin-top:24px;padding:16px;border:1px solid var(--tae-outline-variant);border-radius:8px}.subsection h4{margin:0 0 16px;color:var(--tae-on-surface);font-weight:500}.actions-header{margin:16px 0;display:flex;justify-content:flex-start}.actions-list{display:flex;flex-direction:column;gap:8px;min-height:60px}.action-item{border:1px solid var(--tae-outline-variant);border-radius:8px;background-color:var(--tae-surface);overflow:hidden}.action-header{display:flex;align-items:center;padding:12px 16px;background-color:var(--tae-surface-low);cursor:move}.drag-handle{margin-right:8px;color:var(--tae-on-surface-variant);cursor:grab}.drag-handle:active{cursor:grabbing}.action-label{flex:1;margin-left:8px;font-weight:500}.action-controls{display:flex;gap:4px}.action-details{padding:16px;border-top:1px solid var(--tae-outline-variant);background-color:var(--tae-surface)}.action-form{display:grid;grid-template-columns:repeat(auto-fit,minmax(250px,1fr));gap:16px}.action-global-fields{grid-column:1 / -1;padding:12px 14px;border:1px dashed var(--tae-outline-variant);border-radius:10px;background:var(--md-sys-color-surface-container)}.action-global-title{font-size:12px;font-weight:600;letter-spacing:.02em;text-transform:uppercase;color:var(--tae-on-surface-variant);margin-bottom:10px}.action-global-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:12px 16px}mat-form-field{width:100%}mat-expansion-panel{margin-bottom:8px;border-radius:8px;overflow:hidden}mat-expansion-panel-header{min-height:56px}mat-panel-description{color:var(--tae-on-surface-variant)}.cdk-drag-preview{box-sizing:border-box;border-radius:4px;box-shadow:var(--md-sys-elevation-level3)}.cdk-drag-placeholder{opacity:0}.cdk-drag-animating{transition:transform .25s cubic-bezier(0,0,.2,1)}.actions-list.cdk-drop-list-dragging .action-item:not(.cdk-drag-placeholder){transition:transform .25s cubic-bezier(0,0,.2,1)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1$2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { kind: "directive", type: i1$1.MaxValidator, selector: "input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]", inputs: ["max"] }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i6.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i6.MatLabel, selector: "mat-label" }, { kind: "directive", type: i6.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "directive", type: i6.MatPrefix, selector: "[matPrefix], [matIconPrefix], [matTextPrefix]", inputs: ["matTextPrefix"] }, { kind: "directive", type: i6.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i7.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: i5$2.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: i5$2.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "component", type: i5$2.MatOptgroup, selector: "mat-optgroup", inputs: ["label", "disabled"], exportAs: ["matOptgroup"] }, { kind: "ngmodule", type: MatSlideToggleModule }, { kind: "component", type: i6$1.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: MatExpansionModule }, { kind: "component", type: i8.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "component", type: i8.MatExpansionPanelHeader, selector: "mat-expansion-panel-header", inputs: ["expandedHeight", "collapsedHeight", "tabIndex"] }, { kind: "directive", type: i8.MatExpansionPanelTitle, selector: "mat-panel-title" }, { kind: "directive", type: i8.MatExpansionPanelDescription, selector: "mat-panel-description" }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i5.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i10.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: MatDividerModule }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3.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: "component", type: i3.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatListModule }, { kind: "ngmodule", type: MatChipsModule }, { kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i5$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: i5$1.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i5$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: DragDropModule }, { kind: "directive", type: i13.CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer", "cdkDropListHasAnchor"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: i13.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "directive", type: i13.CdkDragHandle, selector: "[cdkDragHandle]", inputs: ["cdkDragHandleDisabled"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }] });
18500
+ `, isInline: true, styles: [":host{--tae-primary: var(--md-sys-color-primary);--tae-surface: var(--md-sys-color-surface);--tae-surface-low: var(--md-sys-color-surface-container-low);--tae-surface-variant: var(--md-sys-color-surface-variant);--tae-outline-variant: var(--md-sys-color-outline-variant);--tae-on-surface: var(--md-sys-color-on-surface);--tae-on-surface-variant: var(--md-sys-color-on-surface-variant)}.toolbar-actions-container{width:100%;padding:8px}.config-section{padding:16px}.section-hint{color:var(--tae-on-surface-variant);font-size:12px;margin-bottom:12px}.config-fields{display:flex;flex-direction:column;gap:16px;margin-top:16px}.nested-fields{display:flex;flex-direction:column;gap:12px;margin-left:24px;margin-top:12px;padding:16px;background-color:var(--tae-surface-variant);border-radius:8px}.action-section-title{width:100%;margin:12px 0 4px;font-size:12px;font-weight:600;letter-spacing:.04em;text-transform:uppercase;color:var(--tae-on-surface-variant)}.help-icon-button{--mdc-icon-button-state-layer-size: 28px;--mdc-icon-button-icon-size: 18px;width:28px;height:28px;padding:0;display:inline-flex;align-items:center;justify-content:center;vertical-align:middle}.help-icon-button mat-icon{font-size:18px;line-height:18px;width:18px;height:18px}.action-global-fields .mat-mdc-form-field-icon-suffix{align-self:center}.toggle-field{display:flex;align-items:center;gap:8px}.section-icon{margin-right:8px;color:var(--tae-primary)}.subsection{margin-top:24px;padding:16px;border:1px solid var(--tae-outline-variant);border-radius:8px}.subsection h4{margin:0 0 16px;color:var(--tae-on-surface);font-weight:500}.actions-header{margin:16px 0;display:flex;justify-content:flex-start}.actions-list{display:flex;flex-direction:column;gap:8px;min-height:60px}.action-item{border:1px solid var(--tae-outline-variant);border-radius:8px;background-color:var(--tae-surface);overflow:hidden}.action-header{display:flex;align-items:center;padding:12px 16px;background-color:var(--tae-surface-low);cursor:move}.drag-handle{margin-right:8px;color:var(--tae-on-surface-variant);cursor:grab}.drag-handle:active{cursor:grabbing}.action-label{flex:1;margin-left:8px;font-weight:500}.action-controls{display:flex;gap:4px}.action-details{padding:16px;border-top:1px solid var(--tae-outline-variant);background-color:var(--tae-surface)}.action-form{display:grid;grid-template-columns:repeat(auto-fit,minmax(250px,1fr));gap:16px}.action-global-fields{grid-column:1 / -1;padding:12px 14px;border:1px dashed var(--tae-outline-variant);border-radius:10px;background:var(--md-sys-color-surface-container)}.action-global-title{font-size:12px;font-weight:600;letter-spacing:.02em;text-transform:uppercase;color:var(--tae-on-surface-variant);margin-bottom:10px}.action-global-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:12px 16px}mat-form-field{width:100%}mat-expansion-panel{margin-bottom:8px;border-radius:8px;overflow:hidden}mat-expansion-panel-header{min-height:56px}mat-panel-description{color:var(--tae-on-surface-variant)}.cdk-drag-preview{box-sizing:border-box;border-radius:4px;box-shadow:var(--md-sys-elevation-level3)}.cdk-drag-placeholder{opacity:0}.cdk-drag-animating{transition:transform .25s cubic-bezier(0,0,.2,1)}.actions-list.cdk-drop-list-dragging .action-item:not(.cdk-drag-placeholder){transition:transform .25s cubic-bezier(0,0,.2,1)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1$2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { kind: "directive", type: i1$1.MaxValidator, selector: "input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]", inputs: ["max"] }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i6.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i6.MatLabel, selector: "mat-label" }, { kind: "directive", type: i6.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "directive", type: i6.MatPrefix, selector: "[matPrefix], [matIconPrefix], [matTextPrefix]", inputs: ["matTextPrefix"] }, { kind: "directive", type: i6.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i7.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: i5$1.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: i5$1.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "component", type: i5$1.MatOptgroup, selector: "mat-optgroup", inputs: ["label", "disabled"], exportAs: ["matOptgroup"] }, { kind: "ngmodule", type: MatSlideToggleModule }, { kind: "component", type: i6$1.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: MatExpansionModule }, { kind: "component", type: i8.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "component", type: i8.MatExpansionPanelHeader, selector: "mat-expansion-panel-header", inputs: ["expandedHeight", "collapsedHeight", "tabIndex"] }, { kind: "directive", type: i8.MatExpansionPanelTitle, selector: "mat-panel-title" }, { kind: "directive", type: i8.MatExpansionPanelDescription, selector: "mat-panel-description" }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i5.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i10.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: MatDividerModule }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3.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: "component", type: i3.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatListModule }, { kind: "ngmodule", type: MatChipsModule }, { kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i17.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: i17.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i17.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: DragDropModule }, { kind: "directive", type: i12.CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer", "cdkDropListHasAnchor"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: i12.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "directive", type: i12.CdkDragHandle, selector: "[cdkDragHandle]", inputs: ["cdkDragHandleDisabled"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }] });
18020
18501
  }
18021
18502
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: ToolbarActionsEditorComponent, decorators: [{
18022
18503
  type: Component,
@@ -20484,7 +20965,7 @@ class MessagesLocalizationEditorComponent {
20484
20965
 
20485
20966
  </form>
20486
20967
  </div>
20487
- `, isInline: true, styles: [".messages-localization-container{width:100%;padding:8px}.config-section{padding:16px}.config-fields{display:flex;flex-direction:column;gap:16px;margin-top:16px}.toggle-field{display:flex;align-items:center;gap:8px}.section-icon{margin-right:8px;color:var(--md-sys-color-primary)}.info-icon{font-size:18px;width:18px;height:18px;color:var(--md-sys-color-on-surface-variant);cursor:help}.help-icon-button{--mdc-icon-button-state-layer-size: 28px;--mdc-icon-button-icon-size: 18px;width:28px;height:28px;padding:0;display:inline-flex;align-items:center;justify-content:center;vertical-align:middle}.help-icon-button mat-icon{font-size:18px;line-height:18px;width:18px;height:18px}.subsection{margin-top:24px;padding:16px;border:1px solid var(--md-sys-color-outline-variant);border-radius:8px}.subsection h4{margin:0 0 16px;color:var(--md-sys-color-on-surface);font-weight:500}.tab-content{padding:16px 0}.schema-note{margin-top:8px;color:var(--md-sys-color-on-surface-variant);font-size:12px}.schema-note code{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}mat-form-field{width:100%}mat-expansion-panel{margin-bottom:8px;border-radius:8px;overflow:hidden}mat-expansion-panel-header{min-height:56px}mat-panel-description{color:var(--md-sys-color-on-surface-variant)}mat-tab-group{margin-top:16px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { kind: "directive", type: i1$1.MaxValidator, selector: "input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]", inputs: ["max"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i6.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i6.MatLabel, selector: "mat-label" }, { kind: "directive", type: i6.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i7.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: i5$2.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: i5$2.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatSlideToggleModule }, { kind: "component", type: i6$1.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: MatExpansionModule }, { kind: "component", type: i8.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "component", type: i8.MatExpansionPanelHeader, selector: "mat-expansion-panel-header", inputs: ["expandedHeight", "collapsedHeight", "tabIndex"] }, { kind: "directive", type: i8.MatExpansionPanelTitle, selector: "mat-panel-title" }, { kind: "directive", type: i8.MatExpansionPanelDescription, selector: "mat-panel-description" }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i5.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i10.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: MatDividerModule }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatTabsModule }, { kind: "component", type: i4.MatTab, selector: "mat-tab", inputs: ["disabled", "label", "aria-label", "aria-labelledby", "labelClass", "bodyClass", "id"], exportAs: ["matTab"] }, { kind: "component", type: i4.MatTabGroup, selector: "mat-tab-group", inputs: ["color", "fitInkBarToContent", "mat-stretch-tabs", "mat-align-tabs", "dynamicHeight", "selectedIndex", "headerPosition", "animationDuration", "contentTabIndex", "disablePagination", "disableRipple", "preserveContent", "backgroundColor", "aria-label", "aria-labelledby"], outputs: ["selectedIndexChange", "focusChange", "animationDone", "selectedTabChange"], exportAs: ["matTabGroup"] }, { kind: "ngmodule", type: MatCardModule }] });
20968
+ `, isInline: true, styles: [".messages-localization-container{width:100%;padding:8px}.config-section{padding:16px}.config-fields{display:flex;flex-direction:column;gap:16px;margin-top:16px}.toggle-field{display:flex;align-items:center;gap:8px}.section-icon{margin-right:8px;color:var(--md-sys-color-primary)}.info-icon{font-size:18px;width:18px;height:18px;color:var(--md-sys-color-on-surface-variant);cursor:help}.help-icon-button{--mdc-icon-button-state-layer-size: 28px;--mdc-icon-button-icon-size: 18px;width:28px;height:28px;padding:0;display:inline-flex;align-items:center;justify-content:center;vertical-align:middle}.help-icon-button mat-icon{font-size:18px;line-height:18px;width:18px;height:18px}.subsection{margin-top:24px;padding:16px;border:1px solid var(--md-sys-color-outline-variant);border-radius:8px}.subsection h4{margin:0 0 16px;color:var(--md-sys-color-on-surface);font-weight:500}.tab-content{padding:16px 0}.schema-note{margin-top:8px;color:var(--md-sys-color-on-surface-variant);font-size:12px}.schema-note code{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}mat-form-field{width:100%}mat-expansion-panel{margin-bottom:8px;border-radius:8px;overflow:hidden}mat-expansion-panel-header{min-height:56px}mat-panel-description{color:var(--md-sys-color-on-surface-variant)}mat-tab-group{margin-top:16px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { kind: "directive", type: i1$1.MaxValidator, selector: "input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]", inputs: ["max"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i6.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i6.MatLabel, selector: "mat-label" }, { kind: "directive", type: i6.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i7.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: i5$1.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: i5$1.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatSlideToggleModule }, { kind: "component", type: i6$1.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: MatExpansionModule }, { kind: "component", type: i8.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "component", type: i8.MatExpansionPanelHeader, selector: "mat-expansion-panel-header", inputs: ["expandedHeight", "collapsedHeight", "tabIndex"] }, { kind: "directive", type: i8.MatExpansionPanelTitle, selector: "mat-panel-title" }, { kind: "directive", type: i8.MatExpansionPanelDescription, selector: "mat-panel-description" }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i5.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i10.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: MatDividerModule }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatTabsModule }, { kind: "component", type: i4.MatTab, selector: "mat-tab", inputs: ["disabled", "label", "aria-label", "aria-labelledby", "labelClass", "bodyClass", "id"], exportAs: ["matTab"] }, { kind: "component", type: i4.MatTabGroup, selector: "mat-tab-group", inputs: ["color", "fitInkBarToContent", "mat-stretch-tabs", "mat-align-tabs", "dynamicHeight", "selectedIndex", "headerPosition", "animationDuration", "contentTabIndex", "disablePagination", "disableRipple", "preserveContent", "backgroundColor", "aria-label", "aria-labelledby"], outputs: ["selectedIndexChange", "focusChange", "animationDone", "selectedTabChange"], exportAs: ["matTabGroup"] }, { kind: "ngmodule", type: MatCardModule }] });
20488
20969
  }
20489
20970
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: MessagesLocalizationEditorComponent, decorators: [{
20490
20971
  type: Component,
@@ -23063,7 +23544,7 @@ class FilterSettingsComponent {
23063
23544
  // In a real implementation, this would trigger schema reload in PraxisFilter
23064
23545
  }
23065
23546
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: FilterSettingsComponent, deps: [{ token: i1$1.FormBuilder }], target: i0.ɵɵFactoryTarget.Component });
23066
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.17", type: FilterSettingsComponent, isStandalone: true, selector: "filter-settings", inputs: { metadata: "metadata", metadataSource: "metadataSource", metadataLoading: "metadataLoading", metadataErrorMsg: "metadataErrorMsg", settings: "settings", configKey: "configKey" }, outputs: { settingsChange: "settingsChange" }, usesOnChanges: true, ngImport: i0, template: "<form [formGroup]=\"form\">\n <mat-tab-group (selectedTabChange)=\"onTabChange($event)\">\n <mat-tab label=\"Sempre Vis\u00EDveis\">\n <div class=\"always-visible-tab-flow\">\n <mat-form-field appearance=\"outline\" class=\"full-width\">\n <mat-label>Campos sempre vis\u00EDveis</mat-label>\n <mat-select\n formControlName=\"alwaysVisibleFields\"\n multiple\n >\n <mat-option\n [value]=\"meta.name\"\n *ngFor=\"let meta of filteredAlwaysVisibleMetadata(); trackBy: trackFieldMetadataByName\"\n >\n {{ meta.label || meta.name }}\n </mat-option>\n </mat-select>\n <mat-hint *ngIf=\"metadataLoading && metadataSource === 'filter-dto'\">\n Carregando campos do DTO de filtro...\n </mat-hint>\n <mat-error *ngIf=\"metadataErrorMsg\">{{ metadataErrorMsg }}</mat-error>\n <mat-hint\n *ngIf=\"!metadataLoading && !metadataErrorMsg && !metadata.length && metadataSource === 'filter-dto'\"\n >\n Nenhum campo do DTO de filtro dispon\u00EDvel para este recurso.\n </mat-hint>\n <mat-hint\n *ngIf=\"!metadataLoading && !metadataErrorMsg && metadata.length && !hasAlwaysVisibleMetadataResults() && alwaysVisibleFieldSearchText\"\n >\n Nenhum campo encontrado para \"{{ alwaysVisibleFieldSearchText }}\".\n </mat-hint>\n <button\n mat-icon-button\n matSuffix\n type=\"button\"\n class=\"help-icon-button\"\n matTooltip=\"Escolha os campos que aparecem sempre na barra de filtros.\"\n >\n <mat-icon>help_outline</mat-icon>\n </button>\n </mat-form-field>\n\n <mat-form-field appearance=\"outline\" class=\"full-width\">\n <mat-label>Buscar campo</mat-label>\n <input\n matInput\n [ngModel]=\"alwaysVisibleFieldSearchText\"\n (ngModelChange)=\"onAlwaysVisibleFieldSearchChange($event)\"\n [ngModelOptions]=\"{standalone: true}\"\n placeholder=\"Filtrar por nome ou label\"\n />\n <button\n mat-icon-button\n matSuffix\n type=\"button\"\n *ngIf=\"alwaysVisibleFieldSearchText\"\n (click)=\"clearAlwaysVisibleFieldSearch()\"\n aria-label=\"Limpar busca de campo\"\n >\n <mat-icon [praxisIcon]=\"'close'\"></mat-icon>\n </button>\n </mat-form-field>\n <p class=\"field-hint\">\n {{ alwaysVisibleSelectionCount() }} campo(s) selecionado(s).\n </p>\n <div class=\"always-visible-context\">\n <div class=\"always-visible-summary\" role=\"status\" aria-live=\"polite\">\n <div class=\"always-visible-summary-item\">\n <span class=\"summary-value\">{{ alwaysVisibleSelectionCount() }}</span>\n <span class=\"summary-label\">campos fixos</span>\n </div>\n <div class=\"always-visible-summary-item\">\n <span class=\"summary-value\">{{ activeAlwaysVisibleOverrideCount() }}</span>\n <span class=\"summary-label\">overrides ativos</span>\n </div>\n </div>\n <nav\n class=\"always-visible-quick-nav\"\n aria-label=\"Navega\u00E7\u00E3o r\u00E1pida da se\u00E7\u00E3o Sempre Vis\u00EDveis\"\n >\n <button\n mat-stroked-button\n type=\"button\"\n [class.quick-nav-active]=\"isAlwaysVisibleSectionActive('always-visible-order')\"\n [attr.aria-current]=\"isAlwaysVisibleSectionActive('always-visible-order') ? 'location' : null\"\n aria-controls=\"always-visible-order\"\n (click)=\"scrollToAlwaysVisibleSection('always-visible-order')\"\n >\n Ordem\n </button>\n <button\n mat-stroked-button\n type=\"button\"\n [class.quick-nav-active]=\"isAlwaysVisibleSectionActive('always-visible-metadata')\"\n [attr.aria-current]=\"isAlwaysVisibleSectionActive('always-visible-metadata') ? 'location' : null\"\n aria-controls=\"always-visible-metadata\"\n (click)=\"scrollToAlwaysVisibleSection('always-visible-metadata')\"\n >\n Metadados\n </button>\n <button\n mat-stroked-button\n type=\"button\"\n [class.quick-nav-active]=\"isAlwaysVisibleSectionActive('always-visible-json')\"\n [attr.aria-current]=\"isAlwaysVisibleSectionActive('always-visible-json') ? 'location' : null\"\n aria-controls=\"always-visible-json\"\n (click)=\"scrollToAlwaysVisibleSection('always-visible-json')\"\n >\n JSON\n </button>\n </nav>\n </div>\n\n <div\n id=\"always-visible-order\"\n class=\"options options-compact-flow always-visible-section-anchor\"\n [class.section-active]=\"isAlwaysVisibleSectionActive('always-visible-order')\"\n [style.--section-enter-delay]=\"sectionEnterDelay('always-visible-order')\"\n tabindex=\"-1\"\n (focusin)=\"onAlwaysVisibleSectionFocus('always-visible-order')\"\n >\n <div class=\"options-header\">\n <h4 class=\"section-title\">Ordem dos campos</h4>\n <p class=\"section-help\">\n Reordene no formato mais pr\u00F3ximo da toolbar real: faixa de a\u00E7\u00F5es, barra inline e grid.\n </p>\n </div>\n <div class=\"order-layout-toolbar\">\n <mat-button-toggle-group\n class=\"order-viewport-toggle-group\"\n [value]=\"orderPreviewViewport\"\n (change)=\"onAlwaysVisibleViewportChange($event.value)\"\n aria-label=\"Largura simulada da toolbar\"\n >\n <mat-button-toggle\n *ngFor=\"let viewport of alwaysVisibleViewports\"\n [value]=\"viewport\"\n [attr.aria-label]=\"alwaysVisibleViewportHint(viewport)\"\n >\n {{ alwaysVisibleViewportLabel(viewport) }}\n </mat-button-toggle>\n </mat-button-toggle-group>\n <span class=\"order-viewport-caption\">\n {{ alwaysVisibleViewportWidth() }}px\n </span>\n </div>\n <p class=\"section-help\">\n Ajuste o viewport para simular a quebra real das linhas na toolbar.\n </p>\n <div class=\"order-layout-viewport\">\n <div\n class=\"order-layout-frame\"\n [attr.data-viewport]=\"orderPreviewViewport\"\n [style.maxWidth.px]=\"alwaysVisibleViewportWidth()\"\n >\n <div class=\"order-layout-composer\" cdkDropListGroup>\n <section\n class=\"order-lane\"\n *ngFor=\"let lane of alwaysVisibleLayoutLanes\"\n [attr.data-lane]=\"lane\"\n >\n <ng-container *ngIf=\"alwaysVisibleLaneItems(lane) as laneItems\">\n <header class=\"order-lane-header\">\n <div class=\"order-lane-title-block\">\n <h5 class=\"order-lane-title\">{{ alwaysVisibleLaneLabel(lane) }}</h5>\n <p class=\"order-lane-help\">{{ alwaysVisibleLaneHint(lane) }}</p>\n </div>\n <span class=\"order-lane-count\">{{ laneItems.length }}</span>\n </header>\n <div\n cdkDropList\n class=\"order-lane-canvas\"\n [id]=\"alwaysVisibleLaneDropListId(lane)\"\n [class.is-empty]=\"!laneItems.length\"\n [cdkDropListData]=\"laneItems\"\n [cdkDropListEnterPredicate]=\"allowAlwaysVisibleLaneEnter\"\n cdkDropListOrientation=\"horizontal\"\n [attr.aria-label]=\"'Faixa ' + alwaysVisibleLaneLabel(lane)\"\n (cdkDropListDropped)=\"dropAlwaysVisibleLane(lane, $event)\"\n >\n <button\n type=\"button\"\n class=\"order-pill\"\n *ngFor=\"let item of laneItems; let i = index; trackBy: trackAlwaysVisibleLayoutItemByName\"\n cdkDrag\n [cdkDragData]=\"item\"\n [attr.aria-label]=\"alwaysVisibleLayoutItemAriaLabel(item, lane, i, laneItems.length)\"\n (keydown)=\"onAlwaysVisibleLaneItemKeydown($event, lane, item.name)\"\n >\n <mat-icon [praxisIcon]=\"'drag_indicator'\" cdkDragHandle></mat-icon>\n <span class=\"order-pill-label\">{{ item.label }}</span>\n <span class=\"order-pill-badges\">\n <span class=\"order-pill-chip\">{{ item.controlTypeLabel }}</span>\n <span class=\"order-pill-chip order-pill-chip-width\">{{ item.widthHint }}</span>\n <span class=\"order-pill-chip order-pill-chip-override\" *ngIf=\"item.hasOverride\">\n Override\n </span>\n </span>\n </button>\n <p class=\"order-lane-empty\" *ngIf=\"!laneItems.length\">\n {{ alwaysVisibleLaneEmptyHint(lane) }}\n </p>\n </div>\n </ng-container>\n </section>\n </div>\n </div>\n </div>\n <p class=\"field-hint\">\n Acessibilidade: use Alt/Ctrl + setas para reordenar dentro de cada faixa. O drag & drop n\u00E3o mistura faixas.\n </p>\n <p class=\"section-help\" *ngIf=\"!form.controls.alwaysVisibleFields.value?.length\">\n Nenhum campo selecionado. Use o seletor acima para adicionar.\n </p>\n </div>\n\n <mat-divider class=\"section-divider\" role=\"presentation\"></mat-divider>\n\n <div\n id=\"always-visible-metadata\"\n class=\"options options-compact-flow always-visible-section-anchor\"\n [class.section-active]=\"isAlwaysVisibleSectionActive('always-visible-metadata')\"\n [style.--section-enter-delay]=\"sectionEnterDelay('always-visible-metadata')\"\n tabindex=\"-1\"\n (focusin)=\"onAlwaysVisibleSectionFocus('always-visible-metadata')\"\n >\n <div class=\"options-header\">\n <h4 class=\"section-title\">Editor visual de metadados</h4>\n <p class=\"section-help\">\n Edite os principais ajustes dos campos sempre vis\u00EDveis no fluxo visual. Para propriedades avan\u00E7adas, use o JSON abaixo.\n </p>\n </div>\n <p class=\"section-help\" *ngIf=\"!form.controls.alwaysVisibleFields.value?.length\">\n Selecione campos em \u201CCampos sempre vis\u00EDveis\u201D para habilitar a edi\u00E7\u00E3o visual.\n </p>\n <div class=\"metadata-card-grid\" *ngIf=\"form.controls.alwaysVisibleFields.value?.length\">\n <article class=\"metadata-card\" *ngFor=\"let name of form.controls.alwaysVisibleFields.value\">\n <header class=\"metadata-card-header\">\n <div class=\"metadata-card-title\">\n <strong>{{ getFieldLabel(name) }}</strong>\n <span>{{ name }}</span>\n </div>\n <div class=\"metadata-card-badges\">\n <span class=\"metadata-chip\">{{ getAlwaysVisibleControlTypeLabel(name) }}</span>\n <span class=\"metadata-chip metadata-chip-override\" *ngIf=\"hasAlwaysVisibleOverride(name)\">\n Override ativo\n </span>\n </div>\n </header>\n <p class=\"metadata-card-summary\">{{ getAlwaysVisibleOverridePreview(name) }}</p>\n <div class=\"metadata-card-actions\">\n <button mat-stroked-button type=\"button\" (click)=\"openAlwaysVisibleMetadataEditor(name)\">\n <mat-icon [praxisIcon]=\"'tune'\"></mat-icon>\n Editar campo\n </button>\n <button\n mat-button\n type=\"button\"\n color=\"warn\"\n (click)=\"clearAlwaysVisibleOverride(name)\"\n [disabled]=\"!hasAlwaysVisibleOverride(name)\"\n >\n Limpar override\n </button>\n </div>\n </article>\n </div>\n </div>\n\n <mat-divider class=\"section-divider\" role=\"presentation\"></mat-divider>\n\n <div\n id=\"always-visible-json\"\n class=\"always-visible-section-anchor\"\n [class.section-active]=\"isAlwaysVisibleSectionActive('always-visible-json')\"\n [style.--section-enter-delay]=\"sectionEnterDelay('always-visible-json')\"\n tabindex=\"-1\"\n (focusin)=\"onAlwaysVisibleSectionFocus('always-visible-json')\"\n >\n <mat-expansion-panel\n class=\"options options-compact-flow options-advanced-json\"\n [expanded]=\"!!alwaysVisibleOverridesErrorMsg\"\n >\n <mat-expansion-panel-header>\n <mat-panel-title>Avan\u00E7ado (JSON opcional)</mat-panel-title>\n <mat-panel-description>Para ajustes n\u00E3o expostos no editor visual</mat-panel-description>\n </mat-expansion-panel-header>\n <div class=\"options-header\">\n <h4 class=\"section-title\">Modo avan\u00E7ado (JSON)</h4>\n <p class=\"section-help\">\n Use JSON para ajustes em lote ou propriedades ainda n\u00E3o expostas no editor visual.\n </p>\n </div>\n <mat-form-field appearance=\"outline\" class=\"full-width\">\n <mat-label>alwaysVisibleFieldMetadataOverrides (JSON)</mat-label>\n <textarea\n matInput\n rows=\"8\"\n [(ngModel)]=\"alwaysVisibleOverridesJsonText\"\n [ngModelOptions]=\"{standalone: true}\"\n ></textarea>\n </mat-form-field>\n <div class=\"actions\">\n <button mat-stroked-button type=\"button\" (click)=\"formatAlwaysVisibleOverridesJson()\">Formatar</button>\n <button mat-stroked-button color=\"primary\" type=\"button\" (click)=\"applyAlwaysVisibleOverridesJson()\">\n Validar e carregar no editor\n </button>\n </div>\n <p class=\"json-tip\">\n Esta a\u00E7\u00E3o n\u00E3o persiste a configura\u00E7\u00E3o. Para persistir, use \u201CSalvar &amp; Fechar\u201D no rodap\u00E9.\n </p>\n <p class=\"json-tip\">\n Exemplo:\n &#123;\"status\":&#123;\"controlType\":\"filter-select-inline\",\"clearButton\":&#123;\"enabled\":true&#125;,\"inlineAutoSize\":&#123;\"minWidth\":140,\"maxWidth\":280&#125;&#125;&#125;\n </p>\n <p *ngIf=\"alwaysVisibleOverridesErrorMsg\" class=\"json-error\" role=\"status\" aria-live=\"polite\">{{ alwaysVisibleOverridesErrorMsg }}</p>\n </mat-expansion-panel>\n </div>\n </div>\n </mat-tab>\n <mat-tab label=\"Layout\">\n <div class=\"options\">\n <div class=\"options-header\">\n <h4 class=\"section-title\">Grid e responsividade</h4>\n <p class=\"section-help\">\n Ajuste largura m\u00EDnima e n\u00FAmero de colunas por breakpoint. Em telas menores que 600px, o layout usa 1 coluna.\n </p>\n </div>\n <div class=\"layout-preview-section\" aria-live=\"polite\">\n <h5 class=\"layout-preview-title\">Pr\u00E9-visualiza\u00E7\u00E3o do grid</h5>\n <p class=\"section-help\">\n Simula\u00E7\u00E3o com {{ layoutPreviewFields.length }} campos e largura m\u00EDnima de {{ layoutMinWidth() }}px por campo.\n </p>\n <div class=\"layout-preview-cards\">\n <article class=\"layout-preview-card\">\n <div class=\"layout-preview-header\">\n <strong>Mobile</strong>\n <span>&lt;600px \u00B7 {{ layoutColsFor('sm') }} coluna</span>\n </div>\n <div class=\"layout-mini-grid\" [style.gridTemplateColumns]=\"'repeat(' + layoutColsFor('sm') + ', minmax(0, 1fr))'\">\n <span *ngFor=\"let field of layoutPreviewFields\">{{ field }}</span>\n </div>\n </article>\n <article class=\"layout-preview-card\">\n <div class=\"layout-preview-header\">\n <strong>Tablet</strong>\n <span>&ge;600px \u00B7 {{ layoutColsFor('md') }} colunas</span>\n </div>\n <div class=\"layout-mini-grid\" [style.gridTemplateColumns]=\"'repeat(' + layoutColsFor('md') + ', minmax(0, 1fr))'\">\n <span *ngFor=\"let field of layoutPreviewFields\">{{ field }}</span>\n </div>\n </article>\n <article class=\"layout-preview-card\">\n <div class=\"layout-preview-header\">\n <strong>Desktop</strong>\n <span>&ge;960px \u00B7 {{ layoutColsFor('lg') }} colunas</span>\n </div>\n <div class=\"layout-mini-grid\" [style.gridTemplateColumns]=\"'repeat(' + layoutColsFor('lg') + ', minmax(0, 1fr))'\">\n <span *ngFor=\"let field of layoutPreviewFields\">{{ field }}</span>\n </div>\n </article>\n </div>\n </div>\n <mat-form-field appearance=\"outline\" class=\"full-width\">\n <mat-label>Largura m\u00EDnima por campo (px)</mat-label>\n <input\n matInput\n type=\"number\"\n formControlName=\"alwaysMinWidth\"\n min=\"180\"\n max=\"480\"\n step=\"1\"\n inputmode=\"numeric\"\n praxisNumberWheelBlur\n (blur)=\"normalizeLayoutControl('alwaysMinWidth')\"\n />\n <button\n mat-icon-button\n matSuffix\n type=\"button\"\n class=\"help-icon-button\"\n aria-label=\"Ajuda sobre largura m\u00EDnima por campo\"\n matTooltip=\"Define a largura m\u00EDnima de cada campo no grid. Recomendado entre 200 e 300px.\"\n >\n <mat-icon>help_outline</mat-icon>\n </button>\n <mat-hint align=\"start\">Intervalo permitido: 180 a 480px.</mat-hint>\n <mat-hint align=\"end\">Recomendado: 200 a 300px.</mat-hint>\n <mat-error *ngIf=\"layoutControlError('alwaysMinWidth') as error\">{{ error }}</mat-error>\n </mat-form-field>\n <mat-form-field appearance=\"outline\" class=\"full-width\">\n <mat-label>Colunas em tablet (&ge;600px)</mat-label>\n <input\n matInput\n type=\"number\"\n formControlName=\"alwaysColsMd\"\n min=\"1\"\n max=\"3\"\n step=\"1\"\n inputmode=\"numeric\"\n praxisNumberWheelBlur\n (blur)=\"normalizeLayoutControl('alwaysColsMd')\"\n />\n <button\n mat-icon-button\n matSuffix\n type=\"button\"\n class=\"help-icon-button\"\n aria-label=\"Ajuda sobre colunas em tablet\"\n matTooltip=\"Define quantas colunas aparecem em telas m\u00E9dias (a partir de 600px).\"\n >\n <mat-icon>help_outline</mat-icon>\n </button>\n <mat-hint align=\"start\">Mobile (&lt;600px) usa 1 coluna.</mat-hint>\n <mat-hint align=\"end\">Intervalo: 1 a 3 colunas.</mat-hint>\n <mat-error *ngIf=\"layoutControlError('alwaysColsMd') as error\">{{ error }}</mat-error>\n </mat-form-field>\n <mat-form-field appearance=\"outline\" class=\"full-width\">\n <mat-label>Colunas em desktop (&ge;960px)</mat-label>\n <input\n matInput\n type=\"number\"\n formControlName=\"alwaysColsLg\"\n min=\"1\"\n max=\"4\"\n step=\"1\"\n inputmode=\"numeric\"\n praxisNumberWheelBlur\n (blur)=\"normalizeLayoutControl('alwaysColsLg')\"\n />\n <button\n mat-icon-button\n matSuffix\n type=\"button\"\n class=\"help-icon-button\"\n aria-label=\"Ajuda sobre colunas em desktop\"\n matTooltip=\"Define quantas colunas aparecem em telas grandes (a partir de 960px).\"\n >\n <mat-icon>help_outline</mat-icon>\n </button>\n <mat-hint align=\"start\">Use mais colunas apenas quando houver espa\u00E7o.</mat-hint>\n <mat-hint align=\"end\">Intervalo: 1 a 4 colunas.</mat-hint>\n <mat-error *ngIf=\"layoutControlError('alwaysColsLg') as error\">{{ error }}</mat-error>\n </mat-form-field>\n </div>\n </mat-tab>\n <mat-tab label=\"Booleanos\">\n <div class=\"options\">\n <p class=\"section-help\" *ngIf=\"!hasBooleanFieldMetadata()\">\n Nenhum campo booleano foi detectado no schema atual. Estas prefer\u00EAncias ser\u00E3o aplicadas quando houver\n campos `toggle`/boolean no filtro.\n </p>\n <div class=\"toggle-preview-section\" *ngIf=\"hasBooleanFieldMetadata()\">\n <h4>Visualiza\u00E7\u00E3o dos Booleanos</h4>\n <p class=\"section-help\">Veja o comportamento dos booleanos inline (com texto ou compacto) e a posi\u00E7\u00E3o na barra.</p>\n <div class=\"preview-container\">\n <div class=\"preview-item\">\n <strong>Grade Principal</strong>\n <div class=\"mock-grid\" [class.with-booleans]=\"!form.controls.placeBooleansInActions.value\">\n <div class=\"mock-field\">Campo 1</div>\n <div class=\"mock-field\">Campo 2</div>\n <div class=\"mock-pill\" *ngIf=\"!form.controls.placeBooleansInActions.value\"\n [class.compact]=\"!form.controls.showToggleLabels.value\">\n <mat-slide-toggle [checked]=\"true\"></mat-slide-toggle>\n <span *ngIf=\"form.controls.showToggleLabels.value\">Ativo</span>\n </div>\n </div>\n </div>\n <div class=\"preview-item\">\n <strong>\u00C1rea de A\u00E7\u00F5es</strong>\n <div class=\"mock-actions\" [class.with-booleans]=\"form.controls.placeBooleansInActions.value\">\n <button mat-icon-button><mat-icon>search</mat-icon></button>\n <button mat-icon-button><mat-icon>tune</mat-icon></button>\n <div class=\"mock-pill\" *ngIf=\"form.controls.placeBooleansInActions.value\"\n [class.compact]=\"!form.controls.showToggleLabels.value\">\n <mat-slide-toggle [checked]=\"true\"></mat-slide-toggle>\n <span *ngIf=\"form.controls.showToggleLabels.value\">Ativo</span>\n </div>\n </div>\n </div>\n </div>\n </div>\n <mat-checkbox formControlName=\"placeBooleansInActions\">\n <mat-icon>swap_horiz</mat-icon>\n Posicionar booleanos na \u00E1rea de a\u00E7\u00F5es\n </mat-checkbox>\n <p class=\"field-hint\">Move os booleanos da grade para os bot\u00F5es de a\u00E7\u00E3o, liberando espa\u00E7o horizontal.</p>\n <mat-checkbox formControlName=\"showToggleLabels\">\n <mat-icon>text_fields</mat-icon>\n Mostrar texto nos booleanos inline\n </mat-checkbox>\n <p class=\"field-hint\">Quando desativado, os booleanos ficam em modo compacto (somente controle, sem texto).</p>\n </div>\n </mat-tab>\n <mat-tab label=\"Op\u00E7\u00F5es\">\n <div class=\"options\">\n <div class=\"options-header\">\n <h4 class=\"section-title\">Painel Avan\u00E7ado</h4>\n <p class=\"section-help\">Apar\u00EAncia e comportamento do painel de filtros avan\u00E7ados.</p>\n </div>\n <mat-form-field appearance=\"outline\" class=\"full-width\">\n <mat-label>Modo de abertura do Avan\u00E7ado</mat-label>\n <mat-select formControlName=\"advancedOpenMode\">\n <mat-option value=\"modal\">Modal (padr\u00E3o)</mat-option>\n <mat-option value=\"drawer\">Drawer (direita)</mat-option>\n </mat-select>\n <button\n mat-icon-button\n matSuffix\n type=\"button\"\n class=\"help-icon-button\"\n matTooltip=\"Escolha como o painel de filtros avan\u00E7ados ser\u00E1 exibido: centralizado ou lateral.\"\n >\n <mat-icon>help_outline</mat-icon>\n </button>\n </mat-form-field>\n\n <mat-checkbox formControlName=\"advancedClearButtonsEnabled\">\n Mostrar bot\u00E3o de limpar nos campos\n </mat-checkbox>\n <p class=\"field-hint\">\n Desative para ocultar o bot\u00E3o de limpar nos campos do painel avan\u00E7ado.\n </p>\n\n <mat-checkbox formControlName=\"useInlineSearchableSelectVariant\">\n Compactar selects com busca/async/autocomplete na barra inline\n </mat-checkbox>\n <p class=\"field-hint\">\n Usa os componentes inline dedicados para searchable-select, async-select e autocomplete (com busca/pagina\u00E7\u00E3o). O lookup de entidade inline \u00E9 configurado por controlType expl\u00EDcito (`filter-entity-lookup-inline`).\n </p>\n\n <mat-checkbox formControlName=\"useInlineRangeVariant\">\n Compactar range slider na barra inline\n </mat-checkbox>\n <p class=\"field-hint\">\n Usa o componente inline em formato chip + popover para rangeSlider (single e faixa).\n </p>\n\n <mat-checkbox formControlName=\"useInlineDateVariant\">\n Compactar campos de data na barra inline\n </mat-checkbox>\n <p class=\"field-hint\">\n Usa o componente inline dedicado para date/dateInput/datepicker, com largura por conte\u00FAdo e placeholder compacto.\n </p>\n\n <mat-checkbox formControlName=\"useInlineDateRangeVariant\">\n Compactar intervalo de datas na barra inline\n </mat-checkbox>\n <p class=\"field-hint\">\n Usa o componente inline dedicado para dateRange/daterange. Recomendado habilitar ap\u00F3s validar o fluxo no contexto real.\n </p>\n\n <mat-checkbox formControlName=\"useInlineTimeVariant\">\n Compactar campos de horario na barra inline\n </mat-checkbox>\n <p class=\"field-hint\">\n Usa o componente inline dedicado para time/timePicker, com largura por conteudo e clear rapido.\n </p>\n\n <mat-checkbox formControlName=\"useInlineTimeRangeVariant\">\n Compactar intervalo de horario na barra inline\n </mat-checkbox>\n <p class=\"field-hint\">\n Usa variante inline para timeRange/timerange. Recomendado habilitar apos validar o fluxo no contexto real.\n </p>\n\n <mat-checkbox formControlName=\"useInlineTreeSelectVariant\">\n Compactar tree select na barra inline\n </mat-checkbox>\n <p class=\"field-hint\">\n Usa variante inline para treeSelect na faixa compacta de filtros. multiSelectTree mant\u00E9m o componente dedicado.\n </p>\n\n <mat-checkbox formControlName=\"confirmTagDelete\">Confirmar exclus\u00E3o de atalho</mat-checkbox>\n <p class=\"field-hint\">Solicita confirma\u00E7\u00E3o antes de apagar atalhos salvos.</p>\n\n <div class=\"options\">\n <h4>Tema dos Atalhos (Tags)</h4>\n\n <!-- Preview Section -->\n <div class=\"preview-section\" [class.mdc-theme-dark]=\"previewDarkMode\" [class.dark-mode]=\"previewDarkMode\">\n <div class=\"preview-controls\">\n <span class=\"preview-label\">Pr\u00E9-visualiza\u00E7\u00E3o</span>\n <button mat-icon-button (click)=\"previewDarkMode = !previewDarkMode\"\n [matTooltip]=\"previewDarkMode ? 'Mudar para fundo claro' : 'Mudar para fundo escuro'\">\n <mat-icon>{{ previewDarkMode ? 'light_mode' : 'dark_mode' }}</mat-icon>\n </button>\n </div>\n\n <div class=\"preview-chips praxis-filter-tags\"\n [class.outlined]=\"form.controls.tagVariant.value === 'outlined'\">\n <mat-chip-set>\n <!-- Inactive Chip -->\n <mat-chip\n [color]=\"form.controls.tagVariant.value === 'outlined' ? null : (form.controls.tagColor.value === 'basic' ? null : form.controls.tagColor.value)\"\n [highlighted]=\"form.controls.tagVariant.value === 'filled' && form.controls.tagColor.value !== 'basic'\">\n Atalho Inativo\n </mat-chip>\n\n <!-- Active Chip -->\n <mat-chip class=\"active\" [color]=\"form.controls.tagVariant.value === 'outlined' ? null : 'accent'\"\n [highlighted]=\"form.controls.tagVariant.value === 'filled'\">\n <mat-icon matChipAvatar>check</mat-icon>\n Atalho Ativo\n <button matChipTrailingIcon mat-icon-button\n [color]=\"form.controls.tagButtonColor.value === 'basic' ? null : form.controls.tagButtonColor.value\">\n <mat-icon>arrow_drop_down</mat-icon>\n </button>\n </mat-chip>\n </mat-chip-set>\n </div>\n\n <div class=\"contrast-warning\" *ngIf=\"getContrastWarning() as warning\">\n <mat-icon>warning</mat-icon>\n <span>{{ warning }}</span>\n </div>\n </div>\n\n <!-- Reordered Fields -->\n <mat-form-field appearance=\"outline\">\n <mat-label>Variante do atalho</mat-label>\n <mat-select formControlName=\"tagVariant\">\n <mat-option value=\"filled\">Filled (Preenchido)</mat-option>\n <mat-option value=\"outlined\">Outlined (Contorno)</mat-option>\n </mat-select>\n <button\n mat-icon-button\n matSuffix\n type=\"button\"\n class=\"help-icon-button\"\n matTooltip=\"Define o estilo base do atalho.\"\n >\n <mat-icon>help_outline</mat-icon>\n </button>\n </mat-form-field>\n\n <mat-form-field appearance=\"outline\">\n <mat-label>Cor do atalho</mat-label>\n <mat-select formControlName=\"tagColor\">\n <mat-option value=\"primary\">Primary</mat-option>\n <mat-option value=\"accent\">Accent</mat-option>\n <mat-option value=\"warn\">Warn</mat-option>\n <mat-option value=\"basic\">Basic</mat-option>\n </mat-select>\n <button\n mat-icon-button\n matSuffix\n type=\"button\"\n class=\"help-icon-button\"\n matTooltip=\"Cor de fundo (Filled) ou de contorno (Outlined).\"\n >\n <mat-icon>help_outline</mat-icon>\n </button>\n </mat-form-field>\n\n <mat-form-field appearance=\"outline\">\n <mat-label>Cor do bot\u00E3o do menu do atalho</mat-label>\n <mat-select formControlName=\"tagButtonColor\">\n <mat-option value=\"basic\">Basic</mat-option>\n <mat-option value=\"primary\">Primary</mat-option>\n <mat-option value=\"accent\">Accent</mat-option>\n <mat-option value=\"warn\">Warn</mat-option>\n </mat-select>\n <button\n mat-icon-button\n matSuffix\n type=\"button\"\n class=\"help-icon-button\"\n matTooltip=\"Cor do bot\u00E3o de dropdown dentro do atalho ativo.\"\n >\n <mat-icon>help_outline</mat-icon>\n </button>\n </mat-form-field>\n </div>\n\n <div class=\"options\">\n <h4>Tema dos bot\u00F5es de a\u00E7\u00E3o</h4>\n <mat-form-field appearance=\"outline\">\n <mat-label>Cor dos bot\u00F5es</mat-label>\n <mat-select formControlName=\"actionsButtonColor\">\n <mat-option value=\"basic\">Basic</mat-option>\n <mat-option value=\"primary\">Primary</mat-option>\n <mat-option value=\"accent\">Accent</mat-option>\n <mat-option value=\"warn\">Warn</mat-option>\n </mat-select>\n </mat-form-field>\n <mat-form-field appearance=\"outline\">\n <mat-label>Variante dos bot\u00F5es</mat-label>\n <mat-select formControlName=\"actionsVariant\">\n <mat-option value=\"standard\">Standard</mat-option>\n <mat-option value=\"outlined\">Outlined</mat-option>\n </mat-select>\n </mat-form-field>\n </div>\n\n <div class=\"options\">\n <h4>Predefini\u00E7\u00F5es de tema</h4>\n <div class=\"preset-grid\">\n <button\n type=\"button\"\n class=\"preset-card\"\n *ngFor=\"let p of presets\"\n (click)=\"applyPreset(p.key)\"\n [attr.aria-label]=\"'Aplicar predefini\u00E7\u00E3o: ' + p.label\"\n >\n <div class=\"preset-preview\" [ngClass]=\"p.previewClass\"></div>\n <div class=\"preset-info\">\n <span class=\"preset-name\">{{ p.label }}</span>\n <span class=\"preset-desc\">{{ p.description }}</span>\n </div>\n </button>\n </div>\n <button mat-button color=\"warn\" (click)=\"resetPreferences()\" class=\"restore-btn\">\n Restaurar padr\u00E3o\n </button>\n </div>\n </div>\n </mat-tab>\n @if (configKey) {\n <mat-tab label=\"Atalhos\">\n <div class=\"options\">\n <p class=\"section-help\">Os atalhos s\u00E3o salvos por chave de configura\u00E7\u00E3o e compartilhados entre sess\u00F5es.</p>\n <div class=\"tags-header\">\n <span><strong>Atalhos salvos</strong></span>\n <span class=\"spacer\"></span>\n <button mat-stroked-button color=\"warn\" (click)=\"clearTags()\">Apagar tudo</button>\n </div>\n <div class=\"new-tag\">\n <mat-form-field appearance=\"outline\" class=\"full-width\">\n <mat-label>R\u00F3tulo do novo atalho</mat-label>\n <input matInput [(ngModel)]=\"newTagLabel\" [ngModelOptions]=\"{standalone: true}\" />\n </mat-form-field>\n <mat-form-field appearance=\"outline\" class=\"full-width\">\n <mat-label>Patch (JSON, opcional)</mat-label>\n <textarea matInput rows=\"3\" [(ngModel)]=\"newTagPatchText\" [ngModelOptions]=\"{standalone: true}\"></textarea>\n </mat-form-field>\n <div>\n <button mat-stroked-button color=\"primary\" (click)=\"addTag()\">Adicionar</button>\n @if (hasCurrentDto()) {\n <button mat-stroked-button (click)=\"addTagFromCurrent()\">Adicionar a partir dos filtros atuais</button>\n }\n </div>\n <div>\n <button mat-stroked-button color=\"primary\" (click)=\"importTags()\">Importar</button>\n <button mat-stroked-button (click)=\"loadTags()\">Recarregar</button>\n <button mat-stroked-button (click)=\"saveTags()\">Salvar</button>\n </div>\n </div>\n </div>\n </mat-tab>\n }\n <mat-tab label=\"JSON\">\n <div class=\"options\">\n <p><strong>Configura\u00E7\u00E3o atual (somente leitura)</strong></p>\n <mat-form-field appearance=\"outline\" class=\"full-width\">\n <mat-label>Atual</mat-label>\n <textarea matInput rows=\"8\" [value]=\"effectiveJson\" readonly></textarea>\n </mat-form-field>\n\n <p><strong>Editar JSON</strong></p>\n <mat-form-field appearance=\"outline\" class=\"full-width\">\n <mat-label>JSON</mat-label>\n <textarea matInput rows=\"12\" [(ngModel)]=\"settingsJsonText\" [ngModelOptions]=\"{standalone: true}\"></textarea>\n </mat-form-field>\n <div class=\"actions\">\n <button mat-stroked-button (click)=\"onJsonReload()\">Recarregar do formul\u00E1rio</button>\n <button mat-stroked-button (click)=\"onJsonFormat()\">Formatar</button>\n <button mat-stroked-button color=\"primary\" (click)=\"onJsonApply()\">Carregar JSON no formul\u00E1rio</button>\n </div>\n <p class=\"json-tip\">\n Dica: esta a\u00E7\u00E3o apenas atualiza o editor local. Para persistir, use os bot\u00F5es Aplicar ou\n Salvar &amp; Fechar no rodap\u00E9 do painel.\n </p>\n <p *ngIf=\"jsonErrorMsg\" class=\"json-error\" role=\"status\" aria-live=\"polite\">{{ jsonErrorMsg }}</p>\n </div>\n </mat-tab>\n <mat-tab label=\"Comportamento\">\n <div class=\"options\">\n <mat-checkbox formControlName=\"allowSaveTags\">Permitir salvar atalhos</mat-checkbox>\n </div>\n </mat-tab>\n <mat-tab label=\"Avan\u00E7ado\">\n <div class=\"options\">\n <mat-form-field appearance=\"outline\" class=\"full-width\">\n <mat-label>Debounce de altera\u00E7\u00F5es (ms)</mat-label>\n <input matInput type=\"number\" formControlName=\"changeDebounceMs\" min=\"100\" max=\"1000\" />\n @if (form.controls.changeDebounceMs.invalid) { <mat-error>Valor deve estar entre 100 e 1000</mat-error> }\n </mat-form-field>\n <div class=\"actions\">\n <button mat-stroked-button color=\"warn\" (click)=\"resetPreferences()\">\n <mat-icon [praxisIcon]=\"'restart_alt'\"></mat-icon>\n Redefinir prefer\u00EAncias do filtro\n </button>\n <button mat-stroked-button color=\"accent\" (click)=\"clearPersistedFilters()\">\n <mat-icon [praxisIcon]=\"'clear_all'\"></mat-icon>\n Limpar filtros salvos\n </button>\n <button mat-stroked-button (click)=\"forceSchemaReload()\">\n <mat-icon [praxisIcon]=\"'refresh'\"></mat-icon>\n For\u00E7ar recarregamento do schema\n </button>\n </div>\n <mat-form-field appearance=\"outline\" class=\"full-width\">\n <mat-label>N\u00EDvel de log</mat-label>\n <mat-select formControlName=\"logLevel\">\n <mat-option value=\"none\">Nenhum</mat-option>\n <mat-option value=\"error\">Erro</mat-option>\n <mat-option value=\"warn\">Aviso</mat-option>\n <mat-option value=\"info\">Info</mat-option>\n <mat-option value=\"debug\">Debug</mat-option>\n </mat-select>\n <button\n mat-icon-button\n matSuffix\n type=\"button\"\n class=\"help-icon-button\"\n matTooltip=\"Persistido no contrato para integra\u00E7\u00E3o host. Sem efeito direto no runtime atual do filtro.\"\n >\n <mat-icon>help_outline</mat-icon>\n </button>\n </mat-form-field>\n <mat-checkbox formControlName=\"enablePerformanceMetrics\">Habilitar m\u00E9tricas de performance</mat-checkbox>\n <p class=\"field-hint\">Prefer\u00EAncia persistida para integra\u00E7\u00E3o host. Sem efeito direto no runtime atual do filtro.</p>\n </div>\n </mat-tab>\n </mat-tab-group>\n</form>\n", styles: [":host{display:block;min-width:0}.full-width{width:100%}.always-visible-tab-flow{display:flex;flex-direction:column;gap:4px}.always-visible-context{position:sticky;top:0;z-index:2;display:flex;flex-direction:column;gap:6px;padding:8px;border-radius:10px;border:1px solid var(--md-sys-color-outline-variant);background:color-mix(in srgb,var(--md-sys-color-surface-container-high) 88%,transparent);-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px)}.always-visible-summary{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px;padding:8px 10px;border:1px solid var(--md-sys-color-outline-variant);border-radius:10px;background:var(--md-sys-color-surface-container-low)}.always-visible-summary-item{display:flex;align-items:baseline;gap:6px;min-width:0}.summary-value{font-size:1rem;font-weight:700;color:var(--md-sys-color-primary)}.summary-label{font-size:.8rem;color:var(--md-sys-color-on-surface-variant);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.always-visible-quick-nav{display:flex;flex-wrap:wrap;gap:6px}.always-visible-quick-nav button{min-height:30px;font-size:.76rem;padding-inline:10px;transition:border-color .18s ease,background-color .18s ease,color .18s ease}.always-visible-quick-nav button.quick-nav-active{border-color:color-mix(in srgb,var(--md-sys-color-primary) 50%,var(--md-sys-color-outline-variant));background:color-mix(in srgb,var(--md-sys-color-primary-container) 34%,var(--md-sys-color-surface-container-low));color:var(--md-sys-color-primary)}.always-visible-section-anchor{scroll-margin-top:140px;opacity:0;transform:translateY(8px);animation:always-visible-section-enter .22s cubic-bezier(.2,0,0,1) forwards;animation-delay:var(--section-enter-delay, 0ms)}.always-visible-section-anchor.section-active,.always-visible-section-anchor.section-active .options-advanced-json{box-shadow:0 0 0 1px color-mix(in srgb,var(--md-sys-color-primary) 40%,transparent)}.always-visible-section-anchor:focus-visible{outline:2px solid var(--md-sys-color-primary);outline-offset:2px}@keyframes always-visible-section-enter{0%{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}.options{display:flex;flex-direction:column;gap:.75rem;padding:12px;width:100%;max-width:100%;min-width:0;box-sizing:border-box;border:1px solid var(--md-sys-color-outline-variant);border-radius:12px;background:var(--md-sys-color-surface-container)}.options .options{padding:0;border:0;border-radius:0;background:transparent}.options-compact-flow{gap:8px;padding-top:10px;padding-bottom:10px}.section-divider{margin:2px;border-top-style:dashed;border-top-color:var(--md-sys-color-outline-variant);opacity:.28}.options-advanced-json{display:block;padding:0;overflow:hidden}:host ::ng-deep .options-advanced-json .mat-expansion-panel-header{padding:0 12px;min-height:52px}:host ::ng-deep .options-advanced-json .mat-expansion-panel-body{padding:0 12px 12px}.options-header{display:flex;flex-direction:column;gap:6px}.section-title{margin:0;font-size:.95rem;font-weight:600;color:var(--md-sys-color-on-surface)}.section-help{margin:0;font-size:.85rem;color:var(--md-sys-color-on-surface);opacity:.84}.field-hint{margin:-4px 0 0;font-size:.8rem;color:var(--md-sys-color-on-surface);opacity:.78}.help-icon-button{--mdc-icon-button-state-layer-size: 28px;--mdc-icon-button-icon-size: 18px;width:28px;height:28px;padding:0;display:inline-flex;align-items:center;justify-content:center;vertical-align:middle}.help-icon-button mat-icon{font-size:18px;line-height:18px;width:18px;height:18px}.order-layout-toolbar{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:8px}.order-viewport-toggle-group{max-width:100%}.order-viewport-caption{display:inline-flex;align-items:center;min-height:28px;padding:0 10px;border-radius:999px;border:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container-lowest);font-size:.75rem;font-weight:600;color:var(--md-sys-color-on-surface-variant)}.order-layout-viewport{width:100%;display:flex;justify-content:center;padding:10px;border-radius:14px;border:1px solid var(--md-sys-color-outline-variant);background:color-mix(in srgb,var(--md-sys-color-surface-container-high) 74%,transparent)}.order-layout-frame{width:100%;transition:max-width .18s ease}.order-layout-frame[data-viewport=tablet] .order-lane-canvas{gap:7px}.order-layout-frame[data-viewport=mobile] .order-lane-canvas{gap:6px;padding:7px}.order-layout-frame[data-viewport=mobile] .order-pill{width:100%;max-width:100%;border-radius:12px}.order-layout-composer{display:flex;flex-direction:column;gap:9px}.order-lane{display:flex;flex-direction:column;gap:6px}.order-lane-header{display:flex;align-items:flex-start;justify-content:space-between;gap:10px}.order-lane-title-block{display:flex;flex-direction:column;gap:2px;min-width:0}.order-lane-title{margin:0;font-size:.85rem;font-weight:600;color:var(--md-sys-color-on-surface)}.order-lane-help{margin:0;font-size:.76rem;color:var(--md-sys-color-on-surface-variant)}.order-lane-count{display:inline-flex;align-items:center;justify-content:center;min-width:24px;height:24px;border-radius:999px;border:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container-low);color:var(--md-sys-color-on-surface-variant);font-size:.76rem;font-weight:600;padding:0 8px}.order-lane-canvas{display:flex;flex-wrap:wrap;align-items:center;gap:8px;min-height:56px;padding:8px;border:1px dashed var(--md-sys-color-outline-variant);border-radius:12px;background:var(--md-sys-color-surface-container-low)}.order-lane-canvas.cdk-drop-list-dragging{border-color:color-mix(in srgb,var(--md-sys-color-primary) 45%,var(--md-sys-color-outline-variant))}.order-lane[data-lane=actions] .order-lane-canvas{background:color-mix(in srgb,var(--md-sys-color-secondary-container) 28%,var(--md-sys-color-surface-container-low))}.order-lane[data-lane=inline] .order-lane-canvas{background:color-mix(in srgb,var(--md-sys-color-primary-container) 22%,var(--md-sys-color-surface-container-low))}.order-lane[data-lane=grid] .order-lane-canvas{background:color-mix(in srgb,var(--md-sys-color-tertiary-container) 18%,var(--md-sys-color-surface-container-low))}.order-lane-canvas.is-empty{justify-content:flex-start}.order-pill{display:inline-flex;align-items:center;gap:8px;max-width:min(100%,520px);min-height:38px;border:1px solid var(--md-sys-color-outline-variant);border-radius:999px;background:var(--md-sys-color-surface-container-high);color:var(--md-sys-color-on-surface);padding:4px 8px;box-sizing:border-box;cursor:grab;font:inherit;text-align:left}.order-pill:hover{border-color:var(--md-sys-color-outline)}.order-pill:focus-visible{outline:2px solid var(--md-sys-color-primary);outline-offset:2px}.order-pill mat-icon{opacity:.75}.order-pill-label{min-width:0;max-width:190px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:.86rem;font-weight:500}.order-pill-badges{display:inline-flex;flex-wrap:wrap;align-items:center;gap:4px}.order-pill-chip{display:inline-flex;align-items:center;border-radius:999px;border:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container-lowest);color:var(--md-sys-color-on-surface-variant);font-size:.7rem;font-weight:600;padding:1px 7px;white-space:nowrap}.order-pill-chip-width{font-weight:500;opacity:.86}.order-pill-chip-override{border-color:color-mix(in srgb,var(--md-sys-color-primary) 42%,var(--md-sys-color-outline-variant));color:var(--md-sys-color-primary)}.order-lane-empty{margin:0;font-size:.78rem;color:var(--md-sys-color-on-surface-variant)}.order-pill.cdk-drag-preview{box-shadow:var(--md-sys-elevation-level2)}.order-pill.cdk-drag-placeholder{opacity:.45}.layout-preview-section{display:flex;flex-direction:column;gap:10px;padding:12px;border:1px solid var(--md-sys-color-outline-variant);border-radius:10px;background:var(--md-sys-color-surface-container-low);min-width:0}.layout-preview-title{margin:0;font-size:.95rem;font-weight:600;color:var(--md-sys-color-on-surface)}.layout-preview-cards{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:10px;min-width:0}.layout-preview-card{display:flex;flex-direction:column;gap:8px;padding:10px;border:1px solid var(--md-sys-color-outline-variant);border-radius:8px;background:var(--md-sys-color-surface-container);min-width:0}.layout-preview-header{display:flex;flex-direction:column;gap:2px}.layout-preview-header strong{font-size:.85rem;color:var(--md-sys-color-on-surface)}.layout-preview-header span{font-size:.78rem;color:var(--md-sys-color-on-surface-variant)}.layout-mini-grid{display:grid;gap:6px;min-width:0}.layout-mini-grid span{display:block;min-width:0;padding:6px 8px;border-radius:6px;background:var(--md-sys-color-primary-container);color:var(--md-sys-color-on-primary-container);font-size:.75rem;text-align:center;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.tags-header{display:flex;align-items:center;gap:8px}.spacer{flex:1 1 auto}.new-tag{display:flex;flex-direction:column;gap:8px}.preset-row{display:flex;flex-wrap:wrap;gap:8px}.option-with-preview{display:flex;align-items:center;gap:8px}.preview-card{width:20px;height:20px;background:var(--md-sys-color-surface-container-high);border:1px solid var(--md-sys-color-outline-variant);border-radius:4px}.preview-frosted{width:20px;height:20px;background:var(--md-sys-color-surface-container);-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);border:1px solid var(--md-sys-color-outline-variant);border-radius:4px}.toggle-preview-section{margin-bottom:1.5rem;padding:1rem;background:var(--md-sys-color-surface-container-low);border-radius:8px;border:1px solid var(--md-sys-color-outline-variant)}.toggle-preview-section h4{margin:0 0 1rem;font-size:1.1rem;color:var(--md-sys-color-on-surface)}.preview-container{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:1rem}.preview-item{text-align:center}.preview-item strong{display:block;margin-bottom:.5rem;font-weight:500}.mock-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));align-items:center;gap:8px;padding:8px;background:var(--md-sys-color-surface);border:1px solid var(--md-sys-color-outline);border-radius:8px;min-height:72px}.mock-grid.with-booleans{grid-template-columns:repeat(3,minmax(0,1fr))}.mock-field{padding:4px 8px;background:var(--md-sys-color-primary-container);border-radius:6px;font-size:.8rem;text-align:center}.mock-actions{display:flex;align-items:center;gap:8px;padding:8px;background:var(--md-sys-color-surface);border:1px solid var(--md-sys-color-outline);border-radius:8px;min-height:48px}.mock-actions button{width:34px;height:34px}.mock-pill{display:flex;align-items:center;gap:8px;min-height:34px;padding:0 10px;border-radius:999px;border:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container-high);color:var(--md-sys-color-on-surface-variant);font-size:.82rem;justify-self:start}.mock-pill.compact{padding-inline:8px;gap:0}.mock-pill mat-slide-toggle{--mdc-switch-selected-track-color: var(--md-sys-color-primary);--mdc-switch-selected-handle-color: var(--md-sys-color-on-primary);transform:scale(.8);pointer-events:none}.mock-pill span{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font-weight:500}.preview-section{display:flex;flex-direction:column;gap:16px;padding:16px;background:var(--md-sys-color-surface-container-low);border:1px solid var(--md-sys-color-outline-variant);border-radius:8px;margin-bottom:16px;box-shadow:var(--md-sys-elevation-level1);transition:background-color .3s,color .3s}.preview-section.dark-mode{background:var(--md-sys-color-surface-container-low);color:var(--md-sys-color-on-surface);border-color:var(--md-sys-color-outline-variant)}.preview-section.dark-mode .preview-label{color:var(--md-sys-color-on-surface-variant)}.preview-controls{display:flex;justify-content:space-between;align-items:center}.preview-label{font-weight:500;font-size:.9rem;color:var(--md-sys-color-on-surface-variant)}.preview-chips{display:flex;justify-content:center;padding:16px 0}.praxis-filter-tags.outlined .mat-mdc-chip{background:transparent!important;--mat-chip-outline-width: 1px;--mat-chip-outline-color: var(--md-sys-color-outline-variant);box-shadow:inset 0 0 0 var(--mat-chip-outline-width) var(--mat-chip-outline-color)}.praxis-filter-tags.outlined mat-chip.active .mat-mdc-chip,.praxis-filter-tags.outlined .mat-mdc-chip.mat-mdc-chip-highlighted{--mat-chip-outline-color: var(--md-sys-color-primary) !important;box-shadow:inset 0 0 0 var(--mat-chip-outline-width) var(--mat-chip-outline-color)!important}.praxis-filter-tags.outlined mat-chip[ng-reflect-color=primary] .mat-mdc-chip{--mat-chip-outline-color: var(--md-sys-color-primary)}.praxis-filter-tags.outlined mat-chip[ng-reflect-color=accent] .mat-mdc-chip{--mat-chip-outline-color: var(--md-sys-color-tertiary)}.praxis-filter-tags.outlined mat-chip[ng-reflect-color=warn] .mat-mdc-chip{--mat-chip-outline-color: var(--md-sys-color-error)}.praxis-filter-tags .mat-mdc-standard-chip .mdc-evolution-chip__text-label{display:flex;align-items:center;gap:4px}.contrast-warning{display:flex;align-items:center;gap:8px;padding:8px 12px;background:var(--md-sys-color-error-container);color:var(--md-sys-color-on-error-container);border-radius:4px;font-size:.85rem}.contrast-warning mat-icon{font-size:20px;width:20px;height:20px}.preset-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(140px,1fr));gap:12px;margin-bottom:12px}.preset-card{display:flex;width:100%;flex-direction:column;gap:8px;padding:12px;text-align:left;font:inherit;color:inherit;background:transparent;border:1px solid var(--md-sys-color-outline-variant);border-radius:8px;cursor:pointer;transition:all .2s}.preset-card:hover{background:var(--md-sys-color-surface-container-high);border-color:var(--md-sys-color-outline)}.preset-card:focus-visible{outline:2px solid var(--md-sys-color-primary);outline-offset:2px}.preset-preview{height:24px;border-radius:4px;background:var(--md-sys-color-surface-variant)}.preset-preview.preview-minimal{background:transparent;border:1px solid var(--md-sys-color-outline)}.preset-preview.preview-primary{background:var(--md-sys-color-primary-container)}.preset-preview.preview-accent{background:var(--md-sys-color-tertiary-container)}.preset-preview.preview-warn{background:var(--md-sys-color-error-container)}.preset-info{display:flex;flex-direction:column}.preset-name{font-weight:500;font-size:.9rem}.preset-desc{font-size:.75rem;opacity:.7}.restore-btn{align-self:flex-start}.metadata-card-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:10px}.metadata-card{display:flex;flex-direction:column;gap:10px;padding:12px;border-radius:10px;border:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container-low)}.metadata-card-header{display:flex;justify-content:space-between;align-items:flex-start;gap:10px}.metadata-card-title{display:flex;flex-direction:column;min-width:0}.metadata-card-title strong{font-size:.92rem;color:var(--md-sys-color-on-surface)}.metadata-card-title span{font-size:.78rem;color:var(--md-sys-color-on-surface-variant);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.metadata-card-badges{display:flex;flex-wrap:wrap;justify-content:flex-end;gap:6px}.metadata-chip{display:inline-flex;align-items:center;border-radius:999px;border:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container);color:var(--md-sys-color-on-surface-variant);font-size:.78rem;font-weight:500;padding:2px 8px;white-space:nowrap}.metadata-chip-override{border-color:color-mix(in srgb,var(--md-sys-color-primary) 40%,var(--md-sys-color-outline-variant));color:var(--md-sys-color-primary);background:color-mix(in srgb,var(--md-sys-color-primary-container) 38%,var(--md-sys-color-surface-container))}.metadata-card-summary{margin:0;font-size:.8rem;color:var(--md-sys-color-on-surface-variant)}.metadata-card-actions{display:flex;flex-wrap:wrap;gap:6px}.metadata-card-actions button{display:inline-flex;align-items:center;gap:4px}.metadata-card-actions button:focus-visible{outline:2px solid var(--md-sys-color-primary);outline-offset:1px}:host ::ng-deep .metadata-card-actions button[disabled]{opacity:.62}.json-tip{margin:6px 0 0;font-size:.85rem;color:var(--md-sys-color-on-surface-variant)}.json-error{margin-top:6px;font-size:.85rem;color:var(--md-sys-color-error)}@media(prefers-reduced-motion:reduce){.always-visible-section-anchor{animation:none;opacity:1;transform:none}.always-visible-quick-nav button{transition:none}}@media(max-width:680px){.order-layout-toolbar{flex-direction:column;align-items:stretch}.order-viewport-caption{align-self:flex-start}.order-layout-viewport{padding:8px}.always-visible-context{position:static;-webkit-backdrop-filter:none;backdrop-filter:none}.always-visible-summary{grid-template-columns:1fr}.always-visible-quick-nav{display:grid;grid-template-columns:repeat(3,minmax(0,1fr))}.order-pill{width:100%;max-width:100%}.order-pill-label{max-width:none}.order-pill-badges{display:none}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { kind: "directive", type: i1$1.MaxValidator, selector: "input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]", inputs: ["max"] }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MatTabsModule }, { kind: "component", type: i4.MatTab, selector: "mat-tab", inputs: ["disabled", "label", "aria-label", "aria-labelledby", "labelClass", "bodyClass", "id"], exportAs: ["matTab"] }, { kind: "component", type: i4.MatTabGroup, selector: "mat-tab-group", inputs: ["color", "fitInkBarToContent", "mat-stretch-tabs", "mat-align-tabs", "dynamicHeight", "selectedIndex", "headerPosition", "animationDuration", "contentTabIndex", "disablePagination", "disableRipple", "preserveContent", "backgroundColor", "aria-label", "aria-labelledby"], outputs: ["selectedIndexChange", "focusChange", "animationDone", "selectedTabChange"], exportAs: ["matTabGroup"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i6.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i6.MatLabel, selector: "mat-label" }, { kind: "directive", type: i6.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "directive", type: i6.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "directive", type: i6.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i5$2.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: i5$2.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i7.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: MatCheckboxModule }, { kind: "component", type: i9.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "ngmodule", type: MatListModule }, { kind: "component", type: i10$2.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3.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: "component", type: i3.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatButtonToggleModule }, { kind: "directive", type: i15$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: i15$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: MatIconModule }, { kind: "component", type: i5.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }, { kind: "ngmodule", type: DragDropModule }, { kind: "directive", type: i13.CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer", "cdkDropListHasAnchor"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: i13.CdkDropListGroup, selector: "[cdkDropListGroup]", inputs: ["cdkDropListGroupDisabled"], exportAs: ["cdkDropListGroup"] }, { kind: "directive", type: i13.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "directive", type: i13.CdkDragHandle, selector: "[cdkDragHandle]", inputs: ["cdkDragHandleDisabled"] }, { kind: "ngmodule", type: MatSlideToggleModule }, { kind: "component", type: i6$1.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: i10.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: MatChipsModule }, { kind: "component", type: i15.MatChip, selector: "mat-basic-chip, [mat-basic-chip], mat-chip, [mat-chip]", inputs: ["role", "id", "aria-label", "aria-description", "value", "color", "removable", "highlighted", "disableRipple", "disabled"], outputs: ["removed", "destroyed"], exportAs: ["matChip"] }, { kind: "directive", type: i15.MatChipAvatar, selector: "mat-chip-avatar, [matChipAvatar]" }, { kind: "component", type: i15.MatChipSet, selector: "mat-chip-set", inputs: ["disabled", "role", "tabIndex"] }, { kind: "directive", type: i15.MatChipTrailingIcon, selector: "mat-chip-trailing-icon, [matChipTrailingIcon]" }, { kind: "ngmodule", type: MatDividerModule }, { kind: "ngmodule", type: MatExpansionModule }, { kind: "component", type: i8.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "component", type: i8.MatExpansionPanelHeader, selector: "mat-expansion-panel-header", inputs: ["expandedHeight", "collapsedHeight", "tabIndex"] }, { kind: "directive", type: i8.MatExpansionPanelTitle, selector: "mat-panel-title" }, { kind: "directive", type: i8.MatExpansionPanelDescription, selector: "mat-panel-description" }, { kind: "directive", type: PraxisNumberWheelBlurDirective, selector: "input[type=number][praxisNumberWheelBlur]" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
23547
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.17", type: FilterSettingsComponent, isStandalone: true, selector: "filter-settings", inputs: { metadata: "metadata", metadataSource: "metadataSource", metadataLoading: "metadataLoading", metadataErrorMsg: "metadataErrorMsg", settings: "settings", configKey: "configKey" }, outputs: { settingsChange: "settingsChange" }, usesOnChanges: true, ngImport: i0, template: "<form [formGroup]=\"form\">\n <mat-tab-group (selectedTabChange)=\"onTabChange($event)\">\n <mat-tab label=\"Sempre Vis\u00EDveis\">\n <div class=\"always-visible-tab-flow\">\n <mat-form-field appearance=\"outline\" class=\"full-width\">\n <mat-label>Campos sempre vis\u00EDveis</mat-label>\n <mat-select\n formControlName=\"alwaysVisibleFields\"\n multiple\n >\n <mat-option\n [value]=\"meta.name\"\n *ngFor=\"let meta of filteredAlwaysVisibleMetadata(); trackBy: trackFieldMetadataByName\"\n >\n {{ meta.label || meta.name }}\n </mat-option>\n </mat-select>\n <mat-hint *ngIf=\"metadataLoading && metadataSource === 'filter-dto'\">\n Carregando campos do DTO de filtro...\n </mat-hint>\n <mat-error *ngIf=\"metadataErrorMsg\">{{ metadataErrorMsg }}</mat-error>\n <mat-hint\n *ngIf=\"!metadataLoading && !metadataErrorMsg && !metadata.length && metadataSource === 'filter-dto'\"\n >\n Nenhum campo do DTO de filtro dispon\u00EDvel para este recurso.\n </mat-hint>\n <mat-hint\n *ngIf=\"!metadataLoading && !metadataErrorMsg && metadata.length && !hasAlwaysVisibleMetadataResults() && alwaysVisibleFieldSearchText\"\n >\n Nenhum campo encontrado para \"{{ alwaysVisibleFieldSearchText }}\".\n </mat-hint>\n <button\n mat-icon-button\n matSuffix\n type=\"button\"\n class=\"help-icon-button\"\n matTooltip=\"Escolha os campos que aparecem sempre na barra de filtros.\"\n >\n <mat-icon>help_outline</mat-icon>\n </button>\n </mat-form-field>\n\n <mat-form-field appearance=\"outline\" class=\"full-width\">\n <mat-label>Buscar campo</mat-label>\n <input\n matInput\n [ngModel]=\"alwaysVisibleFieldSearchText\"\n (ngModelChange)=\"onAlwaysVisibleFieldSearchChange($event)\"\n [ngModelOptions]=\"{standalone: true}\"\n placeholder=\"Filtrar por nome ou label\"\n />\n <button\n mat-icon-button\n matSuffix\n type=\"button\"\n *ngIf=\"alwaysVisibleFieldSearchText\"\n (click)=\"clearAlwaysVisibleFieldSearch()\"\n aria-label=\"Limpar busca de campo\"\n >\n <mat-icon [praxisIcon]=\"'close'\"></mat-icon>\n </button>\n </mat-form-field>\n <p class=\"field-hint\">\n {{ alwaysVisibleSelectionCount() }} campo(s) selecionado(s).\n </p>\n <div class=\"always-visible-context\">\n <div class=\"always-visible-summary\" role=\"status\" aria-live=\"polite\">\n <div class=\"always-visible-summary-item\">\n <span class=\"summary-value\">{{ alwaysVisibleSelectionCount() }}</span>\n <span class=\"summary-label\">campos fixos</span>\n </div>\n <div class=\"always-visible-summary-item\">\n <span class=\"summary-value\">{{ activeAlwaysVisibleOverrideCount() }}</span>\n <span class=\"summary-label\">overrides ativos</span>\n </div>\n </div>\n <nav\n class=\"always-visible-quick-nav\"\n aria-label=\"Navega\u00E7\u00E3o r\u00E1pida da se\u00E7\u00E3o Sempre Vis\u00EDveis\"\n >\n <button\n mat-stroked-button\n type=\"button\"\n [class.quick-nav-active]=\"isAlwaysVisibleSectionActive('always-visible-order')\"\n [attr.aria-current]=\"isAlwaysVisibleSectionActive('always-visible-order') ? 'location' : null\"\n aria-controls=\"always-visible-order\"\n (click)=\"scrollToAlwaysVisibleSection('always-visible-order')\"\n >\n Ordem\n </button>\n <button\n mat-stroked-button\n type=\"button\"\n [class.quick-nav-active]=\"isAlwaysVisibleSectionActive('always-visible-metadata')\"\n [attr.aria-current]=\"isAlwaysVisibleSectionActive('always-visible-metadata') ? 'location' : null\"\n aria-controls=\"always-visible-metadata\"\n (click)=\"scrollToAlwaysVisibleSection('always-visible-metadata')\"\n >\n Metadados\n </button>\n <button\n mat-stroked-button\n type=\"button\"\n [class.quick-nav-active]=\"isAlwaysVisibleSectionActive('always-visible-json')\"\n [attr.aria-current]=\"isAlwaysVisibleSectionActive('always-visible-json') ? 'location' : null\"\n aria-controls=\"always-visible-json\"\n (click)=\"scrollToAlwaysVisibleSection('always-visible-json')\"\n >\n JSON\n </button>\n </nav>\n </div>\n\n <div\n id=\"always-visible-order\"\n class=\"options options-compact-flow always-visible-section-anchor\"\n [class.section-active]=\"isAlwaysVisibleSectionActive('always-visible-order')\"\n [style.--section-enter-delay]=\"sectionEnterDelay('always-visible-order')\"\n tabindex=\"-1\"\n (focusin)=\"onAlwaysVisibleSectionFocus('always-visible-order')\"\n >\n <div class=\"options-header\">\n <h4 class=\"section-title\">Ordem dos campos</h4>\n <p class=\"section-help\">\n Reordene no formato mais pr\u00F3ximo da toolbar real: faixa de a\u00E7\u00F5es, barra inline e grid.\n </p>\n </div>\n <div class=\"order-layout-toolbar\">\n <mat-button-toggle-group\n class=\"order-viewport-toggle-group\"\n [value]=\"orderPreviewViewport\"\n (change)=\"onAlwaysVisibleViewportChange($event.value)\"\n aria-label=\"Largura simulada da toolbar\"\n >\n <mat-button-toggle\n *ngFor=\"let viewport of alwaysVisibleViewports\"\n [value]=\"viewport\"\n [attr.aria-label]=\"alwaysVisibleViewportHint(viewport)\"\n >\n {{ alwaysVisibleViewportLabel(viewport) }}\n </mat-button-toggle>\n </mat-button-toggle-group>\n <span class=\"order-viewport-caption\">\n {{ alwaysVisibleViewportWidth() }}px\n </span>\n </div>\n <p class=\"section-help\">\n Ajuste o viewport para simular a quebra real das linhas na toolbar.\n </p>\n <div class=\"order-layout-viewport\">\n <div\n class=\"order-layout-frame\"\n [attr.data-viewport]=\"orderPreviewViewport\"\n [style.maxWidth.px]=\"alwaysVisibleViewportWidth()\"\n >\n <div class=\"order-layout-composer\" cdkDropListGroup>\n <section\n class=\"order-lane\"\n *ngFor=\"let lane of alwaysVisibleLayoutLanes\"\n [attr.data-lane]=\"lane\"\n >\n <ng-container *ngIf=\"alwaysVisibleLaneItems(lane) as laneItems\">\n <header class=\"order-lane-header\">\n <div class=\"order-lane-title-block\">\n <h5 class=\"order-lane-title\">{{ alwaysVisibleLaneLabel(lane) }}</h5>\n <p class=\"order-lane-help\">{{ alwaysVisibleLaneHint(lane) }}</p>\n </div>\n <span class=\"order-lane-count\">{{ laneItems.length }}</span>\n </header>\n <div\n cdkDropList\n class=\"order-lane-canvas\"\n [id]=\"alwaysVisibleLaneDropListId(lane)\"\n [class.is-empty]=\"!laneItems.length\"\n [cdkDropListData]=\"laneItems\"\n [cdkDropListEnterPredicate]=\"allowAlwaysVisibleLaneEnter\"\n cdkDropListOrientation=\"horizontal\"\n [attr.aria-label]=\"'Faixa ' + alwaysVisibleLaneLabel(lane)\"\n (cdkDropListDropped)=\"dropAlwaysVisibleLane(lane, $event)\"\n >\n <button\n type=\"button\"\n class=\"order-pill\"\n *ngFor=\"let item of laneItems; let i = index; trackBy: trackAlwaysVisibleLayoutItemByName\"\n cdkDrag\n [cdkDragData]=\"item\"\n [attr.aria-label]=\"alwaysVisibleLayoutItemAriaLabel(item, lane, i, laneItems.length)\"\n (keydown)=\"onAlwaysVisibleLaneItemKeydown($event, lane, item.name)\"\n >\n <mat-icon [praxisIcon]=\"'drag_indicator'\" cdkDragHandle></mat-icon>\n <span class=\"order-pill-label\">{{ item.label }}</span>\n <span class=\"order-pill-badges\">\n <span class=\"order-pill-chip\">{{ item.controlTypeLabel }}</span>\n <span class=\"order-pill-chip order-pill-chip-width\">{{ item.widthHint }}</span>\n <span class=\"order-pill-chip order-pill-chip-override\" *ngIf=\"item.hasOverride\">\n Override\n </span>\n </span>\n </button>\n <p class=\"order-lane-empty\" *ngIf=\"!laneItems.length\">\n {{ alwaysVisibleLaneEmptyHint(lane) }}\n </p>\n </div>\n </ng-container>\n </section>\n </div>\n </div>\n </div>\n <p class=\"field-hint\">\n Acessibilidade: use Alt/Ctrl + setas para reordenar dentro de cada faixa. O drag & drop n\u00E3o mistura faixas.\n </p>\n <p class=\"section-help\" *ngIf=\"!form.controls.alwaysVisibleFields.value?.length\">\n Nenhum campo selecionado. Use o seletor acima para adicionar.\n </p>\n </div>\n\n <mat-divider class=\"section-divider\" role=\"presentation\"></mat-divider>\n\n <div\n id=\"always-visible-metadata\"\n class=\"options options-compact-flow always-visible-section-anchor\"\n [class.section-active]=\"isAlwaysVisibleSectionActive('always-visible-metadata')\"\n [style.--section-enter-delay]=\"sectionEnterDelay('always-visible-metadata')\"\n tabindex=\"-1\"\n (focusin)=\"onAlwaysVisibleSectionFocus('always-visible-metadata')\"\n >\n <div class=\"options-header\">\n <h4 class=\"section-title\">Editor visual de metadados</h4>\n <p class=\"section-help\">\n Edite os principais ajustes dos campos sempre vis\u00EDveis no fluxo visual. Para propriedades avan\u00E7adas, use o JSON abaixo.\n </p>\n </div>\n <p class=\"section-help\" *ngIf=\"!form.controls.alwaysVisibleFields.value?.length\">\n Selecione campos em \u201CCampos sempre vis\u00EDveis\u201D para habilitar a edi\u00E7\u00E3o visual.\n </p>\n <div class=\"metadata-card-grid\" *ngIf=\"form.controls.alwaysVisibleFields.value?.length\">\n <article class=\"metadata-card\" *ngFor=\"let name of form.controls.alwaysVisibleFields.value\">\n <header class=\"metadata-card-header\">\n <div class=\"metadata-card-title\">\n <strong>{{ getFieldLabel(name) }}</strong>\n <span>{{ name }}</span>\n </div>\n <div class=\"metadata-card-badges\">\n <span class=\"metadata-chip\">{{ getAlwaysVisibleControlTypeLabel(name) }}</span>\n <span class=\"metadata-chip metadata-chip-override\" *ngIf=\"hasAlwaysVisibleOverride(name)\">\n Override ativo\n </span>\n </div>\n </header>\n <p class=\"metadata-card-summary\">{{ getAlwaysVisibleOverridePreview(name) }}</p>\n <div class=\"metadata-card-actions\">\n <button mat-stroked-button type=\"button\" (click)=\"openAlwaysVisibleMetadataEditor(name)\">\n <mat-icon [praxisIcon]=\"'tune'\"></mat-icon>\n Editar campo\n </button>\n <button\n mat-button\n type=\"button\"\n color=\"warn\"\n (click)=\"clearAlwaysVisibleOverride(name)\"\n [disabled]=\"!hasAlwaysVisibleOverride(name)\"\n >\n Limpar override\n </button>\n </div>\n </article>\n </div>\n </div>\n\n <mat-divider class=\"section-divider\" role=\"presentation\"></mat-divider>\n\n <div\n id=\"always-visible-json\"\n class=\"always-visible-section-anchor\"\n [class.section-active]=\"isAlwaysVisibleSectionActive('always-visible-json')\"\n [style.--section-enter-delay]=\"sectionEnterDelay('always-visible-json')\"\n tabindex=\"-1\"\n (focusin)=\"onAlwaysVisibleSectionFocus('always-visible-json')\"\n >\n <mat-expansion-panel\n class=\"options options-compact-flow options-advanced-json\"\n [expanded]=\"!!alwaysVisibleOverridesErrorMsg\"\n >\n <mat-expansion-panel-header>\n <mat-panel-title>Avan\u00E7ado (JSON opcional)</mat-panel-title>\n <mat-panel-description>Para ajustes n\u00E3o expostos no editor visual</mat-panel-description>\n </mat-expansion-panel-header>\n <div class=\"options-header\">\n <h4 class=\"section-title\">Modo avan\u00E7ado (JSON)</h4>\n <p class=\"section-help\">\n Use JSON para ajustes em lote ou propriedades ainda n\u00E3o expostas no editor visual.\n </p>\n </div>\n <mat-form-field appearance=\"outline\" class=\"full-width\">\n <mat-label>alwaysVisibleFieldMetadataOverrides (JSON)</mat-label>\n <textarea\n matInput\n rows=\"8\"\n [(ngModel)]=\"alwaysVisibleOverridesJsonText\"\n [ngModelOptions]=\"{standalone: true}\"\n ></textarea>\n </mat-form-field>\n <div class=\"actions\">\n <button mat-stroked-button type=\"button\" (click)=\"formatAlwaysVisibleOverridesJson()\">Formatar</button>\n <button mat-stroked-button color=\"primary\" type=\"button\" (click)=\"applyAlwaysVisibleOverridesJson()\">\n Validar e carregar no editor\n </button>\n </div>\n <p class=\"json-tip\">\n Esta a\u00E7\u00E3o n\u00E3o persiste a configura\u00E7\u00E3o. Para persistir, use \u201CSalvar &amp; Fechar\u201D no rodap\u00E9.\n </p>\n <p class=\"json-tip\">\n Exemplo:\n &#123;\"status\":&#123;\"controlType\":\"filter-select-inline\",\"clearButton\":&#123;\"enabled\":true&#125;,\"inlineAutoSize\":&#123;\"minWidth\":140,\"maxWidth\":280&#125;&#125;&#125;\n </p>\n <p *ngIf=\"alwaysVisibleOverridesErrorMsg\" class=\"json-error\" role=\"status\" aria-live=\"polite\">{{ alwaysVisibleOverridesErrorMsg }}</p>\n </mat-expansion-panel>\n </div>\n </div>\n </mat-tab>\n <mat-tab label=\"Layout\">\n <div class=\"options\">\n <div class=\"options-header\">\n <h4 class=\"section-title\">Grid e responsividade</h4>\n <p class=\"section-help\">\n Ajuste largura m\u00EDnima e n\u00FAmero de colunas por breakpoint. Em telas menores que 600px, o layout usa 1 coluna.\n </p>\n </div>\n <div class=\"layout-preview-section\" aria-live=\"polite\">\n <h5 class=\"layout-preview-title\">Pr\u00E9-visualiza\u00E7\u00E3o do grid</h5>\n <p class=\"section-help\">\n Simula\u00E7\u00E3o com {{ layoutPreviewFields.length }} campos e largura m\u00EDnima de {{ layoutMinWidth() }}px por campo.\n </p>\n <div class=\"layout-preview-cards\">\n <article class=\"layout-preview-card\">\n <div class=\"layout-preview-header\">\n <strong>Mobile</strong>\n <span>&lt;600px \u00B7 {{ layoutColsFor('sm') }} coluna</span>\n </div>\n <div class=\"layout-mini-grid\" [style.gridTemplateColumns]=\"'repeat(' + layoutColsFor('sm') + ', minmax(0, 1fr))'\">\n <span *ngFor=\"let field of layoutPreviewFields\">{{ field }}</span>\n </div>\n </article>\n <article class=\"layout-preview-card\">\n <div class=\"layout-preview-header\">\n <strong>Tablet</strong>\n <span>&ge;600px \u00B7 {{ layoutColsFor('md') }} colunas</span>\n </div>\n <div class=\"layout-mini-grid\" [style.gridTemplateColumns]=\"'repeat(' + layoutColsFor('md') + ', minmax(0, 1fr))'\">\n <span *ngFor=\"let field of layoutPreviewFields\">{{ field }}</span>\n </div>\n </article>\n <article class=\"layout-preview-card\">\n <div class=\"layout-preview-header\">\n <strong>Desktop</strong>\n <span>&ge;960px \u00B7 {{ layoutColsFor('lg') }} colunas</span>\n </div>\n <div class=\"layout-mini-grid\" [style.gridTemplateColumns]=\"'repeat(' + layoutColsFor('lg') + ', minmax(0, 1fr))'\">\n <span *ngFor=\"let field of layoutPreviewFields\">{{ field }}</span>\n </div>\n </article>\n </div>\n </div>\n <mat-form-field appearance=\"outline\" class=\"full-width\">\n <mat-label>Largura m\u00EDnima por campo (px)</mat-label>\n <input\n matInput\n type=\"number\"\n formControlName=\"alwaysMinWidth\"\n min=\"180\"\n max=\"480\"\n step=\"1\"\n inputmode=\"numeric\"\n praxisNumberWheelBlur\n (blur)=\"normalizeLayoutControl('alwaysMinWidth')\"\n />\n <button\n mat-icon-button\n matSuffix\n type=\"button\"\n class=\"help-icon-button\"\n aria-label=\"Ajuda sobre largura m\u00EDnima por campo\"\n matTooltip=\"Define a largura m\u00EDnima de cada campo no grid. Recomendado entre 200 e 300px.\"\n >\n <mat-icon>help_outline</mat-icon>\n </button>\n <mat-hint align=\"start\">Intervalo permitido: 180 a 480px.</mat-hint>\n <mat-hint align=\"end\">Recomendado: 200 a 300px.</mat-hint>\n <mat-error *ngIf=\"layoutControlError('alwaysMinWidth') as error\">{{ error }}</mat-error>\n </mat-form-field>\n <mat-form-field appearance=\"outline\" class=\"full-width\">\n <mat-label>Colunas em tablet (&ge;600px)</mat-label>\n <input\n matInput\n type=\"number\"\n formControlName=\"alwaysColsMd\"\n min=\"1\"\n max=\"3\"\n step=\"1\"\n inputmode=\"numeric\"\n praxisNumberWheelBlur\n (blur)=\"normalizeLayoutControl('alwaysColsMd')\"\n />\n <button\n mat-icon-button\n matSuffix\n type=\"button\"\n class=\"help-icon-button\"\n aria-label=\"Ajuda sobre colunas em tablet\"\n matTooltip=\"Define quantas colunas aparecem em telas m\u00E9dias (a partir de 600px).\"\n >\n <mat-icon>help_outline</mat-icon>\n </button>\n <mat-hint align=\"start\">Mobile (&lt;600px) usa 1 coluna.</mat-hint>\n <mat-hint align=\"end\">Intervalo: 1 a 3 colunas.</mat-hint>\n <mat-error *ngIf=\"layoutControlError('alwaysColsMd') as error\">{{ error }}</mat-error>\n </mat-form-field>\n <mat-form-field appearance=\"outline\" class=\"full-width\">\n <mat-label>Colunas em desktop (&ge;960px)</mat-label>\n <input\n matInput\n type=\"number\"\n formControlName=\"alwaysColsLg\"\n min=\"1\"\n max=\"4\"\n step=\"1\"\n inputmode=\"numeric\"\n praxisNumberWheelBlur\n (blur)=\"normalizeLayoutControl('alwaysColsLg')\"\n />\n <button\n mat-icon-button\n matSuffix\n type=\"button\"\n class=\"help-icon-button\"\n aria-label=\"Ajuda sobre colunas em desktop\"\n matTooltip=\"Define quantas colunas aparecem em telas grandes (a partir de 960px).\"\n >\n <mat-icon>help_outline</mat-icon>\n </button>\n <mat-hint align=\"start\">Use mais colunas apenas quando houver espa\u00E7o.</mat-hint>\n <mat-hint align=\"end\">Intervalo: 1 a 4 colunas.</mat-hint>\n <mat-error *ngIf=\"layoutControlError('alwaysColsLg') as error\">{{ error }}</mat-error>\n </mat-form-field>\n </div>\n </mat-tab>\n <mat-tab label=\"Booleanos\">\n <div class=\"options\">\n <p class=\"section-help\" *ngIf=\"!hasBooleanFieldMetadata()\">\n Nenhum campo booleano foi detectado no schema atual. Estas prefer\u00EAncias ser\u00E3o aplicadas quando houver\n campos `toggle`/boolean no filtro.\n </p>\n <div class=\"toggle-preview-section\" *ngIf=\"hasBooleanFieldMetadata()\">\n <h4>Visualiza\u00E7\u00E3o dos Booleanos</h4>\n <p class=\"section-help\">Veja o comportamento dos booleanos inline (com texto ou compacto) e a posi\u00E7\u00E3o na barra.</p>\n <div class=\"preview-container\">\n <div class=\"preview-item\">\n <strong>Grade Principal</strong>\n <div class=\"mock-grid\" [class.with-booleans]=\"!form.controls.placeBooleansInActions.value\">\n <div class=\"mock-field\">Campo 1</div>\n <div class=\"mock-field\">Campo 2</div>\n <div class=\"mock-pill\" *ngIf=\"!form.controls.placeBooleansInActions.value\"\n [class.compact]=\"!form.controls.showToggleLabels.value\">\n <mat-slide-toggle [checked]=\"true\"></mat-slide-toggle>\n <span *ngIf=\"form.controls.showToggleLabels.value\">Ativo</span>\n </div>\n </div>\n </div>\n <div class=\"preview-item\">\n <strong>\u00C1rea de A\u00E7\u00F5es</strong>\n <div class=\"mock-actions\" [class.with-booleans]=\"form.controls.placeBooleansInActions.value\">\n <button mat-icon-button><mat-icon>search</mat-icon></button>\n <button mat-icon-button><mat-icon>tune</mat-icon></button>\n <div class=\"mock-pill\" *ngIf=\"form.controls.placeBooleansInActions.value\"\n [class.compact]=\"!form.controls.showToggleLabels.value\">\n <mat-slide-toggle [checked]=\"true\"></mat-slide-toggle>\n <span *ngIf=\"form.controls.showToggleLabels.value\">Ativo</span>\n </div>\n </div>\n </div>\n </div>\n </div>\n <mat-checkbox formControlName=\"placeBooleansInActions\">\n <mat-icon>swap_horiz</mat-icon>\n Posicionar booleanos na \u00E1rea de a\u00E7\u00F5es\n </mat-checkbox>\n <p class=\"field-hint\">Move os booleanos da grade para os bot\u00F5es de a\u00E7\u00E3o, liberando espa\u00E7o horizontal.</p>\n <mat-checkbox formControlName=\"showToggleLabels\">\n <mat-icon>text_fields</mat-icon>\n Mostrar texto nos booleanos inline\n </mat-checkbox>\n <p class=\"field-hint\">Quando desativado, os booleanos ficam em modo compacto (somente controle, sem texto).</p>\n </div>\n </mat-tab>\n <mat-tab label=\"Op\u00E7\u00F5es\">\n <div class=\"options\">\n <div class=\"options-header\">\n <h4 class=\"section-title\">Painel Avan\u00E7ado</h4>\n <p class=\"section-help\">Apar\u00EAncia e comportamento do painel de filtros avan\u00E7ados.</p>\n </div>\n <mat-form-field appearance=\"outline\" class=\"full-width\">\n <mat-label>Modo de abertura do Avan\u00E7ado</mat-label>\n <mat-select formControlName=\"advancedOpenMode\">\n <mat-option value=\"modal\">Modal (padr\u00E3o)</mat-option>\n <mat-option value=\"drawer\">Drawer (direita)</mat-option>\n </mat-select>\n <button\n mat-icon-button\n matSuffix\n type=\"button\"\n class=\"help-icon-button\"\n matTooltip=\"Escolha como o painel de filtros avan\u00E7ados ser\u00E1 exibido: centralizado ou lateral.\"\n >\n <mat-icon>help_outline</mat-icon>\n </button>\n </mat-form-field>\n\n <mat-checkbox formControlName=\"advancedClearButtonsEnabled\">\n Mostrar bot\u00E3o de limpar nos campos\n </mat-checkbox>\n <p class=\"field-hint\">\n Desative para ocultar o bot\u00E3o de limpar nos campos do painel avan\u00E7ado.\n </p>\n\n <mat-checkbox formControlName=\"useInlineSearchableSelectVariant\">\n Compactar selects com busca/async/autocomplete na barra inline\n </mat-checkbox>\n <p class=\"field-hint\">\n Usa os componentes inline dedicados para searchable-select, async-select e autocomplete (com busca/pagina\u00E7\u00E3o). O lookup de entidade inline \u00E9 configurado por controlType expl\u00EDcito (`filter-entity-lookup-inline`).\n </p>\n\n <mat-checkbox formControlName=\"useInlineRangeVariant\">\n Compactar range slider na barra inline\n </mat-checkbox>\n <p class=\"field-hint\">\n Usa o componente inline em formato chip + popover para rangeSlider (single e faixa).\n </p>\n\n <mat-checkbox formControlName=\"useInlineDateVariant\">\n Compactar campos de data na barra inline\n </mat-checkbox>\n <p class=\"field-hint\">\n Usa o componente inline dedicado para date/dateInput/datepicker, com largura por conte\u00FAdo e placeholder compacto.\n </p>\n\n <mat-checkbox formControlName=\"useInlineDateRangeVariant\">\n Compactar intervalo de datas na barra inline\n </mat-checkbox>\n <p class=\"field-hint\">\n Usa o componente inline dedicado para dateRange/daterange. Recomendado habilitar ap\u00F3s validar o fluxo no contexto real.\n </p>\n\n <mat-checkbox formControlName=\"useInlineTimeVariant\">\n Compactar campos de horario na barra inline\n </mat-checkbox>\n <p class=\"field-hint\">\n Usa o componente inline dedicado para time/timePicker, com largura por conteudo e clear rapido.\n </p>\n\n <mat-checkbox formControlName=\"useInlineTimeRangeVariant\">\n Compactar intervalo de horario na barra inline\n </mat-checkbox>\n <p class=\"field-hint\">\n Usa variante inline para timeRange/timerange. Recomendado habilitar apos validar o fluxo no contexto real.\n </p>\n\n <mat-checkbox formControlName=\"useInlineTreeSelectVariant\">\n Compactar tree select na barra inline\n </mat-checkbox>\n <p class=\"field-hint\">\n Usa variante inline para treeSelect na faixa compacta de filtros. multiSelectTree mant\u00E9m o componente dedicado.\n </p>\n\n <mat-checkbox formControlName=\"confirmTagDelete\">Confirmar exclus\u00E3o de atalho</mat-checkbox>\n <p class=\"field-hint\">Solicita confirma\u00E7\u00E3o antes de apagar atalhos salvos.</p>\n\n <div class=\"options\">\n <h4>Tema dos Atalhos (Tags)</h4>\n\n <!-- Preview Section -->\n <div class=\"preview-section\" [class.mdc-theme-dark]=\"previewDarkMode\" [class.dark-mode]=\"previewDarkMode\">\n <div class=\"preview-controls\">\n <span class=\"preview-label\">Pr\u00E9-visualiza\u00E7\u00E3o</span>\n <button mat-icon-button (click)=\"previewDarkMode = !previewDarkMode\"\n [matTooltip]=\"previewDarkMode ? 'Mudar para fundo claro' : 'Mudar para fundo escuro'\">\n <mat-icon>{{ previewDarkMode ? 'light_mode' : 'dark_mode' }}</mat-icon>\n </button>\n </div>\n\n <div class=\"preview-chips praxis-filter-tags\"\n [class.outlined]=\"form.controls.tagVariant.value === 'outlined'\">\n <mat-chip-set>\n <!-- Inactive Chip -->\n <mat-chip\n [color]=\"form.controls.tagVariant.value === 'outlined' ? null : (form.controls.tagColor.value === 'basic' ? null : form.controls.tagColor.value)\"\n [highlighted]=\"form.controls.tagVariant.value === 'filled' && form.controls.tagColor.value !== 'basic'\">\n Atalho Inativo\n </mat-chip>\n\n <!-- Active Chip -->\n <mat-chip class=\"active\" [color]=\"form.controls.tagVariant.value === 'outlined' ? null : 'accent'\"\n [highlighted]=\"form.controls.tagVariant.value === 'filled'\">\n <mat-icon matChipAvatar>check</mat-icon>\n Atalho Ativo\n <button matChipTrailingIcon mat-icon-button\n [color]=\"form.controls.tagButtonColor.value === 'basic' ? null : form.controls.tagButtonColor.value\">\n <mat-icon>arrow_drop_down</mat-icon>\n </button>\n </mat-chip>\n </mat-chip-set>\n </div>\n\n <div class=\"contrast-warning\" *ngIf=\"getContrastWarning() as warning\">\n <mat-icon>warning</mat-icon>\n <span>{{ warning }}</span>\n </div>\n </div>\n\n <!-- Reordered Fields -->\n <mat-form-field appearance=\"outline\">\n <mat-label>Variante do atalho</mat-label>\n <mat-select formControlName=\"tagVariant\">\n <mat-option value=\"filled\">Filled (Preenchido)</mat-option>\n <mat-option value=\"outlined\">Outlined (Contorno)</mat-option>\n </mat-select>\n <button\n mat-icon-button\n matSuffix\n type=\"button\"\n class=\"help-icon-button\"\n matTooltip=\"Define o estilo base do atalho.\"\n >\n <mat-icon>help_outline</mat-icon>\n </button>\n </mat-form-field>\n\n <mat-form-field appearance=\"outline\">\n <mat-label>Cor do atalho</mat-label>\n <mat-select formControlName=\"tagColor\">\n <mat-option value=\"primary\">Primary</mat-option>\n <mat-option value=\"accent\">Accent</mat-option>\n <mat-option value=\"warn\">Warn</mat-option>\n <mat-option value=\"basic\">Basic</mat-option>\n </mat-select>\n <button\n mat-icon-button\n matSuffix\n type=\"button\"\n class=\"help-icon-button\"\n matTooltip=\"Cor de fundo (Filled) ou de contorno (Outlined).\"\n >\n <mat-icon>help_outline</mat-icon>\n </button>\n </mat-form-field>\n\n <mat-form-field appearance=\"outline\">\n <mat-label>Cor do bot\u00E3o do menu do atalho</mat-label>\n <mat-select formControlName=\"tagButtonColor\">\n <mat-option value=\"basic\">Basic</mat-option>\n <mat-option value=\"primary\">Primary</mat-option>\n <mat-option value=\"accent\">Accent</mat-option>\n <mat-option value=\"warn\">Warn</mat-option>\n </mat-select>\n <button\n mat-icon-button\n matSuffix\n type=\"button\"\n class=\"help-icon-button\"\n matTooltip=\"Cor do bot\u00E3o de dropdown dentro do atalho ativo.\"\n >\n <mat-icon>help_outline</mat-icon>\n </button>\n </mat-form-field>\n </div>\n\n <div class=\"options\">\n <h4>Tema dos bot\u00F5es de a\u00E7\u00E3o</h4>\n <mat-form-field appearance=\"outline\">\n <mat-label>Cor dos bot\u00F5es</mat-label>\n <mat-select formControlName=\"actionsButtonColor\">\n <mat-option value=\"basic\">Basic</mat-option>\n <mat-option value=\"primary\">Primary</mat-option>\n <mat-option value=\"accent\">Accent</mat-option>\n <mat-option value=\"warn\">Warn</mat-option>\n </mat-select>\n </mat-form-field>\n <mat-form-field appearance=\"outline\">\n <mat-label>Variante dos bot\u00F5es</mat-label>\n <mat-select formControlName=\"actionsVariant\">\n <mat-option value=\"standard\">Standard</mat-option>\n <mat-option value=\"outlined\">Outlined</mat-option>\n </mat-select>\n </mat-form-field>\n </div>\n\n <div class=\"options\">\n <h4>Predefini\u00E7\u00F5es de tema</h4>\n <div class=\"preset-grid\">\n <button\n type=\"button\"\n class=\"preset-card\"\n *ngFor=\"let p of presets\"\n (click)=\"applyPreset(p.key)\"\n [attr.aria-label]=\"'Aplicar predefini\u00E7\u00E3o: ' + p.label\"\n >\n <div class=\"preset-preview\" [ngClass]=\"p.previewClass\"></div>\n <div class=\"preset-info\">\n <span class=\"preset-name\">{{ p.label }}</span>\n <span class=\"preset-desc\">{{ p.description }}</span>\n </div>\n </button>\n </div>\n <button mat-button color=\"warn\" (click)=\"resetPreferences()\" class=\"restore-btn\">\n Restaurar padr\u00E3o\n </button>\n </div>\n </div>\n </mat-tab>\n @if (configKey) {\n <mat-tab label=\"Atalhos\">\n <div class=\"options\">\n <p class=\"section-help\">Os atalhos s\u00E3o salvos por chave de configura\u00E7\u00E3o e compartilhados entre sess\u00F5es.</p>\n <div class=\"tags-header\">\n <span><strong>Atalhos salvos</strong></span>\n <span class=\"spacer\"></span>\n <button mat-stroked-button color=\"warn\" (click)=\"clearTags()\">Apagar tudo</button>\n </div>\n <div class=\"new-tag\">\n <mat-form-field appearance=\"outline\" class=\"full-width\">\n <mat-label>R\u00F3tulo do novo atalho</mat-label>\n <input matInput [(ngModel)]=\"newTagLabel\" [ngModelOptions]=\"{standalone: true}\" />\n </mat-form-field>\n <mat-form-field appearance=\"outline\" class=\"full-width\">\n <mat-label>Patch (JSON, opcional)</mat-label>\n <textarea matInput rows=\"3\" [(ngModel)]=\"newTagPatchText\" [ngModelOptions]=\"{standalone: true}\"></textarea>\n </mat-form-field>\n <div>\n <button mat-stroked-button color=\"primary\" (click)=\"addTag()\">Adicionar</button>\n @if (hasCurrentDto()) {\n <button mat-stroked-button (click)=\"addTagFromCurrent()\">Adicionar a partir dos filtros atuais</button>\n }\n </div>\n <div>\n <button mat-stroked-button color=\"primary\" (click)=\"importTags()\">Importar</button>\n <button mat-stroked-button (click)=\"loadTags()\">Recarregar</button>\n <button mat-stroked-button (click)=\"saveTags()\">Salvar</button>\n </div>\n </div>\n </div>\n </mat-tab>\n }\n <mat-tab label=\"JSON\">\n <div class=\"options\">\n <p><strong>Configura\u00E7\u00E3o atual (somente leitura)</strong></p>\n <mat-form-field appearance=\"outline\" class=\"full-width\">\n <mat-label>Atual</mat-label>\n <textarea matInput rows=\"8\" [value]=\"effectiveJson\" readonly></textarea>\n </mat-form-field>\n\n <p><strong>Editar JSON</strong></p>\n <mat-form-field appearance=\"outline\" class=\"full-width\">\n <mat-label>JSON</mat-label>\n <textarea matInput rows=\"12\" [(ngModel)]=\"settingsJsonText\" [ngModelOptions]=\"{standalone: true}\"></textarea>\n </mat-form-field>\n <div class=\"actions\">\n <button mat-stroked-button (click)=\"onJsonReload()\">Recarregar do formul\u00E1rio</button>\n <button mat-stroked-button (click)=\"onJsonFormat()\">Formatar</button>\n <button mat-stroked-button color=\"primary\" (click)=\"onJsonApply()\">Carregar JSON no formul\u00E1rio</button>\n </div>\n <p class=\"json-tip\">\n Dica: esta a\u00E7\u00E3o apenas atualiza o editor local. Para persistir, use os bot\u00F5es Aplicar ou\n Salvar &amp; Fechar no rodap\u00E9 do painel.\n </p>\n <p *ngIf=\"jsonErrorMsg\" class=\"json-error\" role=\"status\" aria-live=\"polite\">{{ jsonErrorMsg }}</p>\n </div>\n </mat-tab>\n <mat-tab label=\"Comportamento\">\n <div class=\"options\">\n <mat-checkbox formControlName=\"allowSaveTags\">Permitir salvar atalhos</mat-checkbox>\n </div>\n </mat-tab>\n <mat-tab label=\"Avan\u00E7ado\">\n <div class=\"options\">\n <mat-form-field appearance=\"outline\" class=\"full-width\">\n <mat-label>Debounce de altera\u00E7\u00F5es (ms)</mat-label>\n <input matInput type=\"number\" formControlName=\"changeDebounceMs\" min=\"100\" max=\"1000\" />\n @if (form.controls.changeDebounceMs.invalid) { <mat-error>Valor deve estar entre 100 e 1000</mat-error> }\n </mat-form-field>\n <div class=\"actions\">\n <button mat-stroked-button color=\"warn\" (click)=\"resetPreferences()\">\n <mat-icon [praxisIcon]=\"'restart_alt'\"></mat-icon>\n Redefinir prefer\u00EAncias do filtro\n </button>\n <button mat-stroked-button color=\"accent\" (click)=\"clearPersistedFilters()\">\n <mat-icon [praxisIcon]=\"'clear_all'\"></mat-icon>\n Limpar filtros salvos\n </button>\n <button mat-stroked-button (click)=\"forceSchemaReload()\">\n <mat-icon [praxisIcon]=\"'refresh'\"></mat-icon>\n For\u00E7ar recarregamento do schema\n </button>\n </div>\n <mat-form-field appearance=\"outline\" class=\"full-width\">\n <mat-label>N\u00EDvel de log</mat-label>\n <mat-select formControlName=\"logLevel\">\n <mat-option value=\"none\">Nenhum</mat-option>\n <mat-option value=\"error\">Erro</mat-option>\n <mat-option value=\"warn\">Aviso</mat-option>\n <mat-option value=\"info\">Info</mat-option>\n <mat-option value=\"debug\">Debug</mat-option>\n </mat-select>\n <button\n mat-icon-button\n matSuffix\n type=\"button\"\n class=\"help-icon-button\"\n matTooltip=\"Persistido no contrato para integra\u00E7\u00E3o host. Sem efeito direto no runtime atual do filtro.\"\n >\n <mat-icon>help_outline</mat-icon>\n </button>\n </mat-form-field>\n <mat-checkbox formControlName=\"enablePerformanceMetrics\">Habilitar m\u00E9tricas de performance</mat-checkbox>\n <p class=\"field-hint\">Prefer\u00EAncia persistida para integra\u00E7\u00E3o host. Sem efeito direto no runtime atual do filtro.</p>\n </div>\n </mat-tab>\n </mat-tab-group>\n</form>\n", styles: [":host{display:block;min-width:0}.full-width{width:100%}.always-visible-tab-flow{display:flex;flex-direction:column;gap:4px}.always-visible-context{position:sticky;top:0;z-index:2;display:flex;flex-direction:column;gap:6px;padding:8px;border-radius:10px;border:1px solid var(--md-sys-color-outline-variant);background:color-mix(in srgb,var(--md-sys-color-surface-container-high) 88%,transparent);-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px)}.always-visible-summary{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px;padding:8px 10px;border:1px solid var(--md-sys-color-outline-variant);border-radius:10px;background:var(--md-sys-color-surface-container-low)}.always-visible-summary-item{display:flex;align-items:baseline;gap:6px;min-width:0}.summary-value{font-size:1rem;font-weight:700;color:var(--md-sys-color-primary)}.summary-label{font-size:.8rem;color:var(--md-sys-color-on-surface-variant);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.always-visible-quick-nav{display:flex;flex-wrap:wrap;gap:6px}.always-visible-quick-nav button{min-height:30px;font-size:.76rem;padding-inline:10px;transition:border-color .18s ease,background-color .18s ease,color .18s ease}.always-visible-quick-nav button.quick-nav-active{border-color:color-mix(in srgb,var(--md-sys-color-primary) 50%,var(--md-sys-color-outline-variant));background:color-mix(in srgb,var(--md-sys-color-primary-container) 34%,var(--md-sys-color-surface-container-low));color:var(--md-sys-color-primary)}.always-visible-section-anchor{scroll-margin-top:140px;opacity:0;transform:translateY(8px);animation:always-visible-section-enter .22s cubic-bezier(.2,0,0,1) forwards;animation-delay:var(--section-enter-delay, 0ms)}.always-visible-section-anchor.section-active,.always-visible-section-anchor.section-active .options-advanced-json{box-shadow:0 0 0 1px color-mix(in srgb,var(--md-sys-color-primary) 40%,transparent)}.always-visible-section-anchor:focus-visible{outline:2px solid var(--md-sys-color-primary);outline-offset:2px}@keyframes always-visible-section-enter{0%{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}.options{display:flex;flex-direction:column;gap:.75rem;padding:12px;width:100%;max-width:100%;min-width:0;box-sizing:border-box;border:1px solid var(--md-sys-color-outline-variant);border-radius:12px;background:var(--md-sys-color-surface-container)}.options .options{padding:0;border:0;border-radius:0;background:transparent}.options-compact-flow{gap:8px;padding-top:10px;padding-bottom:10px}.section-divider{margin:2px;border-top-style:dashed;border-top-color:var(--md-sys-color-outline-variant);opacity:.28}.options-advanced-json{display:block;padding:0;overflow:hidden}:host ::ng-deep .options-advanced-json .mat-expansion-panel-header{padding:0 12px;min-height:52px}:host ::ng-deep .options-advanced-json .mat-expansion-panel-body{padding:0 12px 12px}.options-header{display:flex;flex-direction:column;gap:6px}.section-title{margin:0;font-size:.95rem;font-weight:600;color:var(--md-sys-color-on-surface)}.section-help{margin:0;font-size:.85rem;color:var(--md-sys-color-on-surface);opacity:.84}.field-hint{margin:-4px 0 0;font-size:.8rem;color:var(--md-sys-color-on-surface);opacity:.78}.help-icon-button{--mdc-icon-button-state-layer-size: 28px;--mdc-icon-button-icon-size: 18px;width:28px;height:28px;padding:0;display:inline-flex;align-items:center;justify-content:center;vertical-align:middle}.help-icon-button mat-icon{font-size:18px;line-height:18px;width:18px;height:18px}.order-layout-toolbar{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:8px}.order-viewport-toggle-group{max-width:100%}.order-viewport-caption{display:inline-flex;align-items:center;min-height:28px;padding:0 10px;border-radius:999px;border:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container-lowest);font-size:.75rem;font-weight:600;color:var(--md-sys-color-on-surface-variant)}.order-layout-viewport{width:100%;display:flex;justify-content:center;padding:10px;border-radius:14px;border:1px solid var(--md-sys-color-outline-variant);background:color-mix(in srgb,var(--md-sys-color-surface-container-high) 74%,transparent)}.order-layout-frame{width:100%;transition:max-width .18s ease}.order-layout-frame[data-viewport=tablet] .order-lane-canvas{gap:7px}.order-layout-frame[data-viewport=mobile] .order-lane-canvas{gap:6px;padding:7px}.order-layout-frame[data-viewport=mobile] .order-pill{width:100%;max-width:100%;border-radius:12px}.order-layout-composer{display:flex;flex-direction:column;gap:9px}.order-lane{display:flex;flex-direction:column;gap:6px}.order-lane-header{display:flex;align-items:flex-start;justify-content:space-between;gap:10px}.order-lane-title-block{display:flex;flex-direction:column;gap:2px;min-width:0}.order-lane-title{margin:0;font-size:.85rem;font-weight:600;color:var(--md-sys-color-on-surface)}.order-lane-help{margin:0;font-size:.76rem;color:var(--md-sys-color-on-surface-variant)}.order-lane-count{display:inline-flex;align-items:center;justify-content:center;min-width:24px;height:24px;border-radius:999px;border:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container-low);color:var(--md-sys-color-on-surface-variant);font-size:.76rem;font-weight:600;padding:0 8px}.order-lane-canvas{display:flex;flex-wrap:wrap;align-items:center;gap:8px;min-height:56px;padding:8px;border:1px dashed var(--md-sys-color-outline-variant);border-radius:12px;background:var(--md-sys-color-surface-container-low)}.order-lane-canvas.cdk-drop-list-dragging{border-color:color-mix(in srgb,var(--md-sys-color-primary) 45%,var(--md-sys-color-outline-variant))}.order-lane[data-lane=actions] .order-lane-canvas{background:color-mix(in srgb,var(--md-sys-color-secondary-container) 28%,var(--md-sys-color-surface-container-low))}.order-lane[data-lane=inline] .order-lane-canvas{background:color-mix(in srgb,var(--md-sys-color-primary-container) 22%,var(--md-sys-color-surface-container-low))}.order-lane[data-lane=grid] .order-lane-canvas{background:color-mix(in srgb,var(--md-sys-color-tertiary-container) 18%,var(--md-sys-color-surface-container-low))}.order-lane-canvas.is-empty{justify-content:flex-start}.order-pill{display:inline-flex;align-items:center;gap:8px;max-width:min(100%,520px);min-height:38px;border:1px solid var(--md-sys-color-outline-variant);border-radius:999px;background:var(--md-sys-color-surface-container-high);color:var(--md-sys-color-on-surface);padding:4px 8px;box-sizing:border-box;cursor:grab;font:inherit;text-align:left}.order-pill:hover{border-color:var(--md-sys-color-outline)}.order-pill:focus-visible{outline:2px solid var(--md-sys-color-primary);outline-offset:2px}.order-pill mat-icon{opacity:.75}.order-pill-label{min-width:0;max-width:190px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:.86rem;font-weight:500}.order-pill-badges{display:inline-flex;flex-wrap:wrap;align-items:center;gap:4px}.order-pill-chip{display:inline-flex;align-items:center;border-radius:999px;border:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container-lowest);color:var(--md-sys-color-on-surface-variant);font-size:.7rem;font-weight:600;padding:1px 7px;white-space:nowrap}.order-pill-chip-width{font-weight:500;opacity:.86}.order-pill-chip-override{border-color:color-mix(in srgb,var(--md-sys-color-primary) 42%,var(--md-sys-color-outline-variant));color:var(--md-sys-color-primary)}.order-lane-empty{margin:0;font-size:.78rem;color:var(--md-sys-color-on-surface-variant)}.order-pill.cdk-drag-preview{box-shadow:var(--md-sys-elevation-level2)}.order-pill.cdk-drag-placeholder{opacity:.45}.layout-preview-section{display:flex;flex-direction:column;gap:10px;padding:12px;border:1px solid var(--md-sys-color-outline-variant);border-radius:10px;background:var(--md-sys-color-surface-container-low);min-width:0}.layout-preview-title{margin:0;font-size:.95rem;font-weight:600;color:var(--md-sys-color-on-surface)}.layout-preview-cards{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:10px;min-width:0}.layout-preview-card{display:flex;flex-direction:column;gap:8px;padding:10px;border:1px solid var(--md-sys-color-outline-variant);border-radius:8px;background:var(--md-sys-color-surface-container);min-width:0}.layout-preview-header{display:flex;flex-direction:column;gap:2px}.layout-preview-header strong{font-size:.85rem;color:var(--md-sys-color-on-surface)}.layout-preview-header span{font-size:.78rem;color:var(--md-sys-color-on-surface-variant)}.layout-mini-grid{display:grid;gap:6px;min-width:0}.layout-mini-grid span{display:block;min-width:0;padding:6px 8px;border-radius:6px;background:var(--md-sys-color-primary-container);color:var(--md-sys-color-on-primary-container);font-size:.75rem;text-align:center;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.tags-header{display:flex;align-items:center;gap:8px}.spacer{flex:1 1 auto}.new-tag{display:flex;flex-direction:column;gap:8px}.preset-row{display:flex;flex-wrap:wrap;gap:8px}.option-with-preview{display:flex;align-items:center;gap:8px}.preview-card{width:20px;height:20px;background:var(--md-sys-color-surface-container-high);border:1px solid var(--md-sys-color-outline-variant);border-radius:4px}.preview-frosted{width:20px;height:20px;background:var(--md-sys-color-surface-container);-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);border:1px solid var(--md-sys-color-outline-variant);border-radius:4px}.toggle-preview-section{margin-bottom:1.5rem;padding:1rem;background:var(--md-sys-color-surface-container-low);border-radius:8px;border:1px solid var(--md-sys-color-outline-variant)}.toggle-preview-section h4{margin:0 0 1rem;font-size:1.1rem;color:var(--md-sys-color-on-surface)}.preview-container{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:1rem}.preview-item{text-align:center}.preview-item strong{display:block;margin-bottom:.5rem;font-weight:500}.mock-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));align-items:center;gap:8px;padding:8px;background:var(--md-sys-color-surface);border:1px solid var(--md-sys-color-outline);border-radius:8px;min-height:72px}.mock-grid.with-booleans{grid-template-columns:repeat(3,minmax(0,1fr))}.mock-field{padding:4px 8px;background:var(--md-sys-color-primary-container);border-radius:6px;font-size:.8rem;text-align:center}.mock-actions{display:flex;align-items:center;gap:8px;padding:8px;background:var(--md-sys-color-surface);border:1px solid var(--md-sys-color-outline);border-radius:8px;min-height:48px}.mock-actions button{width:34px;height:34px}.mock-pill{display:flex;align-items:center;gap:8px;min-height:34px;padding:0 10px;border-radius:999px;border:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container-high);color:var(--md-sys-color-on-surface-variant);font-size:.82rem;justify-self:start}.mock-pill.compact{padding-inline:8px;gap:0}.mock-pill mat-slide-toggle{--mdc-switch-selected-track-color: var(--md-sys-color-primary);--mdc-switch-selected-handle-color: var(--md-sys-color-on-primary);transform:scale(.8);pointer-events:none}.mock-pill span{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font-weight:500}.preview-section{display:flex;flex-direction:column;gap:16px;padding:16px;background:var(--md-sys-color-surface-container-low);border:1px solid var(--md-sys-color-outline-variant);border-radius:8px;margin-bottom:16px;box-shadow:var(--md-sys-elevation-level1);transition:background-color .3s,color .3s}.preview-section.dark-mode{background:var(--md-sys-color-surface-container-low);color:var(--md-sys-color-on-surface);border-color:var(--md-sys-color-outline-variant)}.preview-section.dark-mode .preview-label{color:var(--md-sys-color-on-surface-variant)}.preview-controls{display:flex;justify-content:space-between;align-items:center}.preview-label{font-weight:500;font-size:.9rem;color:var(--md-sys-color-on-surface-variant)}.preview-chips{display:flex;justify-content:center;padding:16px 0}.praxis-filter-tags.outlined .mat-mdc-chip{background:transparent!important;--mat-chip-outline-width: 1px;--mat-chip-outline-color: var(--md-sys-color-outline-variant);box-shadow:inset 0 0 0 var(--mat-chip-outline-width) var(--mat-chip-outline-color)}.praxis-filter-tags.outlined mat-chip.active .mat-mdc-chip,.praxis-filter-tags.outlined .mat-mdc-chip.mat-mdc-chip-highlighted{--mat-chip-outline-color: var(--md-sys-color-primary) !important;box-shadow:inset 0 0 0 var(--mat-chip-outline-width) var(--mat-chip-outline-color)!important}.praxis-filter-tags.outlined mat-chip[ng-reflect-color=primary] .mat-mdc-chip{--mat-chip-outline-color: var(--md-sys-color-primary)}.praxis-filter-tags.outlined mat-chip[ng-reflect-color=accent] .mat-mdc-chip{--mat-chip-outline-color: var(--md-sys-color-tertiary)}.praxis-filter-tags.outlined mat-chip[ng-reflect-color=warn] .mat-mdc-chip{--mat-chip-outline-color: var(--md-sys-color-error)}.praxis-filter-tags .mat-mdc-standard-chip .mdc-evolution-chip__text-label{display:flex;align-items:center;gap:4px}.contrast-warning{display:flex;align-items:center;gap:8px;padding:8px 12px;background:var(--md-sys-color-error-container);color:var(--md-sys-color-on-error-container);border-radius:4px;font-size:.85rem}.contrast-warning mat-icon{font-size:20px;width:20px;height:20px}.preset-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(140px,1fr));gap:12px;margin-bottom:12px}.preset-card{display:flex;width:100%;flex-direction:column;gap:8px;padding:12px;text-align:left;font:inherit;color:inherit;background:transparent;border:1px solid var(--md-sys-color-outline-variant);border-radius:8px;cursor:pointer;transition:all .2s}.preset-card:hover{background:var(--md-sys-color-surface-container-high);border-color:var(--md-sys-color-outline)}.preset-card:focus-visible{outline:2px solid var(--md-sys-color-primary);outline-offset:2px}.preset-preview{height:24px;border-radius:4px;background:var(--md-sys-color-surface-variant)}.preset-preview.preview-minimal{background:transparent;border:1px solid var(--md-sys-color-outline)}.preset-preview.preview-primary{background:var(--md-sys-color-primary-container)}.preset-preview.preview-accent{background:var(--md-sys-color-tertiary-container)}.preset-preview.preview-warn{background:var(--md-sys-color-error-container)}.preset-info{display:flex;flex-direction:column}.preset-name{font-weight:500;font-size:.9rem}.preset-desc{font-size:.75rem;opacity:.7}.restore-btn{align-self:flex-start}.metadata-card-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:10px}.metadata-card{display:flex;flex-direction:column;gap:10px;padding:12px;border-radius:10px;border:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container-low)}.metadata-card-header{display:flex;justify-content:space-between;align-items:flex-start;gap:10px}.metadata-card-title{display:flex;flex-direction:column;min-width:0}.metadata-card-title strong{font-size:.92rem;color:var(--md-sys-color-on-surface)}.metadata-card-title span{font-size:.78rem;color:var(--md-sys-color-on-surface-variant);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.metadata-card-badges{display:flex;flex-wrap:wrap;justify-content:flex-end;gap:6px}.metadata-chip{display:inline-flex;align-items:center;border-radius:999px;border:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container);color:var(--md-sys-color-on-surface-variant);font-size:.78rem;font-weight:500;padding:2px 8px;white-space:nowrap}.metadata-chip-override{border-color:color-mix(in srgb,var(--md-sys-color-primary) 40%,var(--md-sys-color-outline-variant));color:var(--md-sys-color-primary);background:color-mix(in srgb,var(--md-sys-color-primary-container) 38%,var(--md-sys-color-surface-container))}.metadata-card-summary{margin:0;font-size:.8rem;color:var(--md-sys-color-on-surface-variant)}.metadata-card-actions{display:flex;flex-wrap:wrap;gap:6px}.metadata-card-actions button{display:inline-flex;align-items:center;gap:4px}.metadata-card-actions button:focus-visible{outline:2px solid var(--md-sys-color-primary);outline-offset:1px}:host ::ng-deep .metadata-card-actions button[disabled]{opacity:.62}.json-tip{margin:6px 0 0;font-size:.85rem;color:var(--md-sys-color-on-surface-variant)}.json-error{margin-top:6px;font-size:.85rem;color:var(--md-sys-color-error)}@media(prefers-reduced-motion:reduce){.always-visible-section-anchor{animation:none;opacity:1;transform:none}.always-visible-quick-nav button{transition:none}}@media(max-width:680px){.order-layout-toolbar{flex-direction:column;align-items:stretch}.order-viewport-caption{align-self:flex-start}.order-layout-viewport{padding:8px}.always-visible-context{position:static;-webkit-backdrop-filter:none;backdrop-filter:none}.always-visible-summary{grid-template-columns:1fr}.always-visible-quick-nav{display:grid;grid-template-columns:repeat(3,minmax(0,1fr))}.order-pill{width:100%;max-width:100%}.order-pill-label{max-width:none}.order-pill-badges{display:none}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { kind: "directive", type: i1$1.MaxValidator, selector: "input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]", inputs: ["max"] }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MatTabsModule }, { kind: "component", type: i4.MatTab, selector: "mat-tab", inputs: ["disabled", "label", "aria-label", "aria-labelledby", "labelClass", "bodyClass", "id"], exportAs: ["matTab"] }, { kind: "component", type: i4.MatTabGroup, selector: "mat-tab-group", inputs: ["color", "fitInkBarToContent", "mat-stretch-tabs", "mat-align-tabs", "dynamicHeight", "selectedIndex", "headerPosition", "animationDuration", "contentTabIndex", "disablePagination", "disableRipple", "preserveContent", "backgroundColor", "aria-label", "aria-labelledby"], outputs: ["selectedIndexChange", "focusChange", "animationDone", "selectedTabChange"], exportAs: ["matTabGroup"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i6.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i6.MatLabel, selector: "mat-label" }, { kind: "directive", type: i6.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "directive", type: i6.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "directive", type: i6.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i5$1.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: i5$1.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i7.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: MatCheckboxModule }, { kind: "component", type: i9.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "ngmodule", type: MatListModule }, { kind: "component", type: i10$2.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3.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: "component", type: i3.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatButtonToggleModule }, { kind: "directive", type: i15$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: i15$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: MatIconModule }, { kind: "component", type: i5.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }, { kind: "ngmodule", type: DragDropModule }, { kind: "directive", type: i12.CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer", "cdkDropListHasAnchor"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: i12.CdkDropListGroup, selector: "[cdkDropListGroup]", inputs: ["cdkDropListGroupDisabled"], exportAs: ["cdkDropListGroup"] }, { kind: "directive", type: i12.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "directive", type: i12.CdkDragHandle, selector: "[cdkDragHandle]", inputs: ["cdkDragHandleDisabled"] }, { kind: "ngmodule", type: MatSlideToggleModule }, { kind: "component", type: i6$1.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: i10.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: MatChipsModule }, { kind: "component", type: i15.MatChip, selector: "mat-basic-chip, [mat-basic-chip], mat-chip, [mat-chip]", inputs: ["role", "id", "aria-label", "aria-description", "value", "color", "removable", "highlighted", "disableRipple", "disabled"], outputs: ["removed", "destroyed"], exportAs: ["matChip"] }, { kind: "directive", type: i15.MatChipAvatar, selector: "mat-chip-avatar, [matChipAvatar]" }, { kind: "component", type: i15.MatChipSet, selector: "mat-chip-set", inputs: ["disabled", "role", "tabIndex"] }, { kind: "directive", type: i15.MatChipTrailingIcon, selector: "mat-chip-trailing-icon, [matChipTrailingIcon]" }, { kind: "ngmodule", type: MatDividerModule }, { kind: "ngmodule", type: MatExpansionModule }, { kind: "component", type: i8.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "component", type: i8.MatExpansionPanelHeader, selector: "mat-expansion-panel-header", inputs: ["expandedHeight", "collapsedHeight", "tabIndex"] }, { kind: "directive", type: i8.MatExpansionPanelTitle, selector: "mat-panel-title" }, { kind: "directive", type: i8.MatExpansionPanelDescription, selector: "mat-panel-description" }, { kind: "directive", type: PraxisNumberWheelBlurDirective, selector: "input[type=number][praxisNumberWheelBlur]" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
23067
23548
  }
23068
23549
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: FilterSettingsComponent, decorators: [{
23069
23550
  type: Component,
@@ -23274,7 +23755,7 @@ class HeaderAppearanceEditorComponent {
23274
23755
  </mat-card-content>
23275
23756
  </mat-card>
23276
23757
  </div>
23277
- `, isInline: true, styles: [".header-editor{display:block}.header-editor-card{border:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container-low)}.header-editor-title{display:inline-flex;align-items:center;gap:8px}.header-editor-note{grid-column:1 / -1;margin:0 0 8px;font-size:.85rem;color:var(--md-sys-color-on-surface-variant)}.help-icon-button{--mdc-icon-button-state-layer-size: 28px;--mdc-icon-button-icon-size: 18px;width:28px;height:28px;padding:0;display:inline-flex;align-items:center;justify-content:center;vertical-align:middle}.help-icon-button mat-icon{font-size:18px;line-height:18px;width:18px;height:18px}.grid{display:grid;grid-template-columns:1fr;gap:16px}.header-editor-section{display:flex;flex-direction:column;gap:12px;padding:12px;border:1px solid var(--md-sys-color-outline-variant);border-radius:10px;background:var(--md-sys-color-surface-container)}.header-editor-section-title{margin:0;font-size:.95rem;font-weight:600;color:var(--md-sys-color-on-surface)}.header-editor-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:12px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { kind: "directive", type: i1$1.MaxValidator, selector: "input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]", inputs: ["max"] }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i6.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i6.MatLabel, selector: "mat-label" }, { kind: "directive", type: i6.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i7.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: i5$2.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: i5$2.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatSlideToggleModule }, { kind: "ngmodule", type: MatCardModule }, { kind: "component", type: i10$1.MatCard, selector: "mat-card", inputs: ["appearance"], exportAs: ["matCard"] }, { kind: "directive", type: i10$1.MatCardContent, selector: "mat-card-content" }, { kind: "component", type: i10$1.MatCardHeader, selector: "mat-card-header" }, { kind: "directive", type: i10$1.MatCardSubtitle, selector: "mat-card-subtitle, [mat-card-subtitle], [matCardSubtitle]" }, { kind: "directive", type: i10$1.MatCardTitle, selector: "mat-card-title, [mat-card-title], [matCardTitle]" }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i5.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i10.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
23758
+ `, isInline: true, styles: [".header-editor{display:block}.header-editor-card{border:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container-low)}.header-editor-title{display:inline-flex;align-items:center;gap:8px}.header-editor-note{grid-column:1 / -1;margin:0 0 8px;font-size:.85rem;color:var(--md-sys-color-on-surface-variant)}.help-icon-button{--mdc-icon-button-state-layer-size: 28px;--mdc-icon-button-icon-size: 18px;width:28px;height:28px;padding:0;display:inline-flex;align-items:center;justify-content:center;vertical-align:middle}.help-icon-button mat-icon{font-size:18px;line-height:18px;width:18px;height:18px}.grid{display:grid;grid-template-columns:1fr;gap:16px}.header-editor-section{display:flex;flex-direction:column;gap:12px;padding:12px;border:1px solid var(--md-sys-color-outline-variant);border-radius:10px;background:var(--md-sys-color-surface-container)}.header-editor-section-title{margin:0;font-size:.95rem;font-weight:600;color:var(--md-sys-color-on-surface)}.header-editor-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:12px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { kind: "directive", type: i1$1.MaxValidator, selector: "input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]", inputs: ["max"] }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i6.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i6.MatLabel, selector: "mat-label" }, { kind: "directive", type: i6.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i7.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: i5$1.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: i5$1.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatSlideToggleModule }, { kind: "ngmodule", type: MatCardModule }, { kind: "component", type: i10$1.MatCard, selector: "mat-card", inputs: ["appearance"], exportAs: ["matCard"] }, { kind: "directive", type: i10$1.MatCardContent, selector: "mat-card-content" }, { kind: "component", type: i10$1.MatCardHeader, selector: "mat-card-header" }, { kind: "directive", type: i10$1.MatCardSubtitle, selector: "mat-card-subtitle, [mat-card-subtitle], [matCardSubtitle]" }, { kind: "directive", type: i10$1.MatCardTitle, selector: "mat-card-title, [mat-card-title], [matCardTitle]" }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i5.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i10.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
23278
23759
  }
23279
23760
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: HeaderAppearanceEditorComponent, decorators: [{
23280
23761
  type: Component,
@@ -23805,7 +24286,7 @@ class CrudIntegrationEditorComponent {
23805
24286
 
23806
24287
  <div class="hint">As alterações são salvas junto com a ação "Salvar" do painel.</div>
23807
24288
  </div>
23808
- `, isInline: true, styles: [":host{--cie-on-surface-variant: var(--md-sys-color-on-surface-variant)}.crud-editor{display:block;width:100%;padding:8px}.config-section{padding:16px}.form-grid{display:grid;grid-template-columns:repeat(2,minmax(220px,1fr));gap:12px;align-items:center}.form-grid .mat-mdc-form-field{width:100%}.actions-list{display:flex;flex-direction:column;gap:8px}.action-row{display:grid;grid-template-columns:160px 160px 1fr 1fr;gap:8px;align-items:center}.action-name{font-weight:600}.hint{margin-top:8px;color:var(--cie-on-surface-variant)}.section-icon{margin-right:8px;color:var(--md-sys-color-primary)}.help-icon-button{--mdc-icon-button-state-layer-size: 28px;--mdc-icon-button-icon-size: 18px;width:28px;height:28px;padding:0;display:inline-flex;align-items:center;justify-content:center;vertical-align:middle}.help-icon-button mat-icon{font-size:18px;line-height:18px;width:18px;height:18px}mat-form-field{width:100%}mat-expansion-panel{margin-bottom:8px;border-radius:8px;overflow:hidden}mat-expansion-panel-header{min-height:56px}mat-panel-description{color:var(--md-sys-color-on-surface-variant)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i6.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i6.MatLabel, selector: "mat-label" }, { kind: "directive", type: i6.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "directive", type: i6.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i7.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: i5$2.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: i5$2.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatSlideToggleModule }, { kind: "component", type: i6$1.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: MatExpansionModule }, { kind: "component", type: i8.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "component", type: i8.MatExpansionPanelHeader, selector: "mat-expansion-panel-header", inputs: ["expandedHeight", "collapsedHeight", "tabIndex"] }, { kind: "directive", type: i8.MatExpansionPanelTitle, selector: "mat-panel-title" }, { kind: "directive", type: i8.MatExpansionPanelDescription, selector: "mat-panel-description" }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i5.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3.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: "component", type: i3.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i10.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }] });
24289
+ `, isInline: true, styles: [":host{--cie-on-surface-variant: var(--md-sys-color-on-surface-variant)}.crud-editor{display:block;width:100%;padding:8px}.config-section{padding:16px}.form-grid{display:grid;grid-template-columns:repeat(2,minmax(220px,1fr));gap:12px;align-items:center}.form-grid .mat-mdc-form-field{width:100%}.actions-list{display:flex;flex-direction:column;gap:8px}.action-row{display:grid;grid-template-columns:160px 160px 1fr 1fr;gap:8px;align-items:center}.action-name{font-weight:600}.hint{margin-top:8px;color:var(--cie-on-surface-variant)}.section-icon{margin-right:8px;color:var(--md-sys-color-primary)}.help-icon-button{--mdc-icon-button-state-layer-size: 28px;--mdc-icon-button-icon-size: 18px;width:28px;height:28px;padding:0;display:inline-flex;align-items:center;justify-content:center;vertical-align:middle}.help-icon-button mat-icon{font-size:18px;line-height:18px;width:18px;height:18px}mat-form-field{width:100%}mat-expansion-panel{margin-bottom:8px;border-radius:8px;overflow:hidden}mat-expansion-panel-header{min-height:56px}mat-panel-description{color:var(--md-sys-color-on-surface-variant)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i6.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i6.MatLabel, selector: "mat-label" }, { kind: "directive", type: i6.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "directive", type: i6.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i7.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: i5$1.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: i5$1.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatSlideToggleModule }, { kind: "component", type: i6$1.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: MatExpansionModule }, { kind: "component", type: i8.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "component", type: i8.MatExpansionPanelHeader, selector: "mat-expansion-panel-header", inputs: ["expandedHeight", "collapsedHeight", "tabIndex"] }, { kind: "directive", type: i8.MatExpansionPanelTitle, selector: "mat-panel-title" }, { kind: "directive", type: i8.MatExpansionPanelDescription, selector: "mat-panel-description" }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i5.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3.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: "component", type: i3.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i10.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }] });
23809
24290
  }
23810
24291
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: CrudIntegrationEditorComponent, decorators: [{
23811
24292
  type: Component,
@@ -24367,7 +24848,7 @@ class ConfirmDialogAppearanceEditorComponent {
24367
24848
  this.configChange.emit(next);
24368
24849
  }
24369
24850
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: ConfirmDialogAppearanceEditorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
24370
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.17", type: ConfirmDialogAppearanceEditorComponent, isStandalone: true, selector: "confirm-dialog-appearance-editor", inputs: { config: "config" }, outputs: { configChange: "configChange" }, ngImport: i0, template: "<mat-accordion multi>\n <mat-expansion-panel expanded>\n <mat-expansion-panel-header>\n <mat-panel-title><mat-icon [praxisIcon]=\"'tune'\"></mat-icon>&nbsp;Apar\u00EAncia & Comportamento</mat-panel-title>\n <mat-panel-description> Tema, alinhamento e heran\u00E7a de presets </mat-panel-description>\n </mat-expansion-panel-header>\n <div class=\"dialog-editor-grid\">\n <p class=\"dialog-editor-note\">\n Preced\u00EAncia: <strong>preset global</strong> \u2192 <strong>variante (delete)</strong> \u2192 <strong>override local</strong> (esta aba). Campos em branco herdam o valor do preset selecionado.\n </p>\n <mat-form-field appearance=\"outline\">\n <mat-label>Tema</mat-label>\n <mat-select [ngModel]=\"deleteDialog.themeColor\" (ngModelChange)=\"update('themeColor', $event)\">\n <mat-option [value]=\"undefined\">Padr\u00E3o</mat-option>\n <mat-option value=\"light\">Claro</mat-option>\n <mat-option value=\"dark\">Escuro</mat-option>\n <mat-option value=\"primary\">Prim\u00E1rio</mat-option>\n </mat-select>\n <button\n mat-icon-button\n matSuffix\n type=\"button\"\n class=\"help-icon-button\"\n matTooltip=\"For\u00E7a o tema do di\u00E1logo quando necess\u00E1rio.\"\n >\n <mat-icon>help_outline</mat-icon>\n </button>\n </mat-form-field>\n <mat-form-field appearance=\"outline\">\n <mat-label>Alinhamento das a\u00E7\u00F5es</mat-label>\n <mat-select [ngModel]=\"deleteDialog.actionsLayout\" (ngModelChange)=\"update('actionsLayout', $event)\">\n <mat-option value=\"start\">Alinhado \u00E0 esquerda</mat-option>\n <mat-option value=\"center\">Centralizado</mat-option>\n <mat-option value=\"end\">Alinhado \u00E0 direita</mat-option>\n <mat-option value=\"stretched\">Estendido (preencher)</mat-option>\n </mat-select>\n <button\n mat-icon-button\n matSuffix\n type=\"button\"\n class=\"help-icon-button\"\n matTooltip=\"Define como os bot\u00F5es se distribuem no rodap\u00E9.\"\n >\n <mat-icon>help_outline</mat-icon>\n </button>\n </mat-form-field>\n <mat-slide-toggle class=\"dialog-span\" [ngModel]=\"deleteDialog.hasBackdrop\" (ngModelChange)=\"update('hasBackdrop', $event)\">Mostrar backdrop</mat-slide-toggle>\n <mat-slide-toggle class=\"dialog-span\" [ngModel]=\"deleteDialog.disableClose\" (ngModelChange)=\"update('disableClose', $event)\">Desabilitar fechar (ESC/clique)</mat-slide-toggle>\n </div>\n </mat-expansion-panel>\n\n <mat-expansion-panel>\n <mat-expansion-panel-header>\n <mat-panel-title><mat-icon [praxisIcon]=\"'aspect_ratio'\"></mat-icon>&nbsp;Dimens\u00F5es</mat-panel-title>\n <mat-panel-description> Largura/altura e limites </mat-panel-description>\n </mat-expansion-panel-header>\n <div class=\"dialog-editor-grid\">\n <p class=\"dialog-editor-note dialog-span\">\n Dica: use presets para manter consist\u00EAncia entre di\u00E1logos; valores manuais sobrescrevem o preset.\n </p>\n <mat-form-field appearance=\"outline\">\n <mat-label>Tamanho (preset)</mat-label>\n <mat-select [ngModel]=\"selectedSizePreset\" (ngModelChange)=\"setSizePreset($event)\">\n <mat-option value=\"default\">Herdar (preset global)</mat-option>\n <mat-option value=\"sm\">sm (360px)</mat-option>\n <mat-option value=\"md\">md (420px)</mat-option>\n <mat-option value=\"lg\">lg (640px)</mat-option>\n <mat-option value=\"xl\">xl (800px)</mat-option>\n <mat-option value=\"tall\">tall (640px \u00D7 70vh)</mat-option>\n <mat-option value=\"full\">full (90vw \u00D7 90vh)</mat-option>\n <mat-option value=\"fluid\">fluid (100% \u00D7 80vh)</mat-option>\n </mat-select>\n </mat-form-field>\n <mat-form-field appearance=\"outline\">\n <mat-label>Largura (width)</mat-label>\n <input matInput [placeholder]=\"getInheritedValue('width') || 'ex.: 420px'\" [ngModel]=\"deleteDialog.width\" (ngModelChange)=\"update('width', $event)\" />\n <mat-hint *ngIf=\"!deleteDialog.width && getInheritedValue('width')\">Herdado: {{ getInheritedValue('width') }}</mat-hint>\n </mat-form-field>\n <mat-form-field appearance=\"outline\">\n <mat-label>Altura (height)</mat-label>\n <input matInput [placeholder]=\"getInheritedValue('height') || 'ex.: auto'\" [ngModel]=\"deleteDialog.height\" (ngModelChange)=\"update('height', $event)\" />\n <mat-hint *ngIf=\"!deleteDialog.height && getInheritedValue('height')\">Herdado: {{ getInheritedValue('height') }}</mat-hint>\n </mat-form-field>\n <mat-form-field appearance=\"outline\"><mat-label>Largura m\u00EDnima (minWidth)</mat-label><input matInput placeholder=\"ex.: 320px\" [ngModel]=\"deleteDialog.minWidth\" (ngModelChange)=\"update('minWidth', $event)\" /></mat-form-field>\n <mat-form-field appearance=\"outline\"><mat-label>Largura m\u00E1xima (maxWidth)</mat-label><input matInput placeholder=\"ex.: 90vw\" [ngModel]=\"deleteDialog.maxWidth\" (ngModelChange)=\"update('maxWidth', $event)\" /></mat-form-field>\n <mat-form-field appearance=\"outline\"><mat-label>Altura m\u00EDnima (minHeight)</mat-label><input matInput placeholder=\"ex.: 200px\" [ngModel]=\"deleteDialog.minHeight\" (ngModelChange)=\"update('minHeight', $event)\" /></mat-form-field>\n <mat-form-field appearance=\"outline\"><mat-label>Altura m\u00E1xima (maxHeight)</mat-label><input matInput [placeholder]=\"getInheritedValue('maxHeight') || 'ex.: 80vh'\" [ngModel]=\"deleteDialog.maxHeight\" (ngModelChange)=\"update('maxHeight', $event)\" /></mat-form-field>\n </div>\n </mat-expansion-panel>\n\n <mat-expansion-panel>\n <mat-expansion-panel-header>\n <mat-panel-title><mat-icon>animation</mat-icon>&nbsp;Anima\u00E7\u00E3o</mat-panel-title>\n <mat-panel-description> Tipo, dire\u00E7\u00E3o, dura\u00E7\u00E3o </mat-panel-description>\n </mat-expansion-panel-header>\n <div class=\"dialog-editor-grid\">\n <mat-form-field appearance=\"outline\">\n <mat-label>Tipo</mat-label>\n <mat-select [ngModel]=\"deleteDialog.animation?.type\" (ngModelChange)=\"update('animation.type', $event)\">\n <mat-option [value]=\"undefined\">Padr\u00E3o (translate)</mat-option>\n <mat-option value=\"translate\">translate</mat-option>\n <mat-option value=\"slide\">slide</mat-option>\n <mat-option value=\"fade\">fade</mat-option>\n <mat-option value=\"expand\">expand</mat-option>\n <mat-option value=\"zoom\">zoom</mat-option>\n </mat-select>\n </mat-form-field>\n <mat-form-field appearance=\"outline\">\n <mat-label>Dire\u00E7\u00E3o</mat-label>\n <mat-select [ngModel]=\"deleteDialog.animation?.direction\" (ngModelChange)=\"update('animation.direction', $event)\">\n <mat-option [value]=\"undefined\">Padr\u00E3o</mat-option>\n <mat-option value=\"up\">para cima</mat-option>\n <mat-option value=\"down\">para baixo</mat-option>\n <mat-option value=\"left\">para a esquerda</mat-option>\n <mat-option value=\"right\">para a direita</mat-option>\n </mat-select>\n </mat-form-field>\n <mat-form-field appearance=\"outline\">\n <mat-label>Dura\u00E7\u00E3o (ms)</mat-label>\n <input matInput type=\"number\" [ngModel]=\"deleteDialog.animation?.duration\" (ngModelChange)=\"update('animation.duration', $event)\" />\n </mat-form-field>\n <mat-form-field appearance=\"outline\">\n <mat-label>Easing</mat-label>\n <input matInput placeholder=\"cubic-bezier(...)\" [ngModel]=\"deleteDialog.animation?.easing\" (ngModelChange)=\"update('animation.easing', $event)\" />\n </mat-form-field>\n <p class=\"dialog-editor-note dialog-span\">\n Sugest\u00E3o: mantenha dura\u00E7\u00E3o entre 160\u2013240ms para a\u00E7\u00F5es r\u00E1pidas.\n </p>\n </div>\n </mat-expansion-panel>\n\n <mat-expansion-panel>\n <mat-expansion-panel-header>\n <mat-panel-title><mat-icon>palette</mat-icon>&nbsp;Estilos (tokens)</mat-panel-title>\n <mat-panel-description> Apar\u00EAncia do cont\u00EAiner e conte\u00FAdo </mat-panel-description>\n </mat-expansion-panel-header>\n <div class=\"dialog-editor-grid\">\n <p class=\"dialog-editor-note dialog-span\">\n Prefira tokens M3 (ex.: <code>var(--md-sys-color-surface-container-high)</code>) para suportar light/dark.\n </p>\n <mat-form-field appearance=\"outline\"><mat-label>Border radius (shape)</mat-label><input matInput placeholder=\"ex.: 12px\" [ngModel]=\"deleteDialog.styles?.containerShape\" (ngModelChange)=\"update('styles.containerShape', $event)\" /></mat-form-field>\n <mat-form-field appearance=\"outline\"><mat-label>Padding a\u00E7\u00F5es</mat-label><input matInput placeholder=\"12px 16px\" [ngModel]=\"deleteDialog.styles?.actionsPadding\" (ngModelChange)=\"update('styles.actionsPadding', $event)\" /></mat-form-field>\n <mat-form-field appearance=\"outline\"><mat-label>Padding conte\u00FAdo</mat-label><input matInput placeholder=\"16px\" [ngModel]=\"deleteDialog.styles?.contentPadding\" (ngModelChange)=\"update('styles.contentPadding', $event)\" /></mat-form-field>\n <mat-form-field appearance=\"outline\"><mat-label>Padding t\u00EDtulo</mat-label><input matInput placeholder=\"12px 16px\" [ngModel]=\"deleteDialog.styles?.headlinePadding\" (ngModelChange)=\"update('styles.headlinePadding', $event)\" /></mat-form-field>\n <mat-form-field appearance=\"outline\"><mat-label>Padding conte\u00FAdo (com a\u00E7\u00F5es)</mat-label><input matInput placeholder=\"16px\" [ngModel]=\"deleteDialog.styles?.withActionsContentPadding\" (ngModelChange)=\"update('styles.withActionsContentPadding', $event)\" /></mat-form-field>\n <mat-form-field appearance=\"outline\"><mat-label>Cor do cont\u00EAiner</mat-label><input matInput placeholder=\"#262626\" [ngModel]=\"deleteDialog.styles?.containerColor\" (ngModelChange)=\"update('styles.containerColor', $event)\" /></mat-form-field>\n <mat-form-field appearance=\"outline\"><mat-label>Cor do t\u00EDtulo</mat-label><input matInput placeholder=\"var(--md-sys-color-on-surface)\" [ngModel]=\"deleteDialog.styles?.subheadColor\" (ngModelChange)=\"update('styles.subheadColor', $event)\" /></mat-form-field>\n <mat-form-field appearance=\"outline\"><mat-label>Cor do conte\u00FAdo</mat-label><input matInput placeholder=\"var(--md-sys-color-on-surface-variant)\" [ngModel]=\"deleteDialog.styles?.supportingTextColor\" (ngModelChange)=\"update('styles.supportingTextColor', $event)\" /></mat-form-field>\n </div>\n </mat-expansion-panel>\n\n <mat-expansion-panel>\n <mat-expansion-panel-header>\n <mat-panel-title><mat-icon>open_with</mat-icon>&nbsp;Posi\u00E7\u00E3o</mat-panel-title>\n <mat-panel-description> Offsets opcionais </mat-panel-description>\n </mat-expansion-panel-header>\n <div class=\"dialog-editor-grid\">\n <p class=\"dialog-editor-note dialog-span\">\n Use offsets apenas quando o di\u00E1logo precisar ancorar em regi\u00F5es espec\u00EDficas da tela.\n </p>\n <mat-form-field appearance=\"outline\"><mat-label>Top</mat-label><input matInput placeholder=\"ex.: 10vh\" [ngModel]=\"deleteDialog.position?.top\" (ngModelChange)=\"update('position.top', $event)\" /></mat-form-field>\n <mat-form-field appearance=\"outline\"><mat-label>Right</mat-label><input matInput placeholder=\"ex.: 24px\" [ngModel]=\"deleteDialog.position?.right\" (ngModelChange)=\"update('position.right', $event)\" /></mat-form-field>\n <mat-form-field appearance=\"outline\"><mat-label>Bottom</mat-label><input matInput placeholder=\"ex.: 10vh\" [ngModel]=\"deleteDialog.position?.bottom\" (ngModelChange)=\"update('position.bottom', $event)\" /></mat-form-field>\n <mat-form-field appearance=\"outline\"><mat-label>Left</mat-label><input matInput placeholder=\"ex.: 24px\" [ngModel]=\"deleteDialog.position?.left\" (ngModelChange)=\"update('position.left', $event)\" /></mat-form-field>\n </div>\n </mat-expansion-panel>\n\n <mat-expansion-panel>\n <mat-expansion-panel-header>\n <mat-panel-title><mat-icon>code</mat-icon>&nbsp;Classes & Avan\u00E7ado</mat-panel-title>\n <mat-panel-description> CSS e z-index </mat-panel-description>\n </mat-expansion-panel-header>\n <div class=\"dialog-editor-grid\">\n <mat-form-field appearance=\"outline\"><mat-label>Classe do painel</mat-label><input matInput placeholder=\"ex.: my-panel\" [ngModel]=\"deleteDialog.panelClass\" (ngModelChange)=\"update('panelClass', $event)\" /></mat-form-field>\n <mat-form-field appearance=\"outline\"><mat-label>Classe do backdrop</mat-label><input matInput placeholder=\"ex.: my-backdrop\" [ngModel]=\"deleteDialog.backdropClass\" (ngModelChange)=\"update('backdropClass', $event)\" /></mat-form-field>\n <mat-form-field appearance=\"outline\"><mat-label>z-index</mat-label><input matInput type=\"number\" placeholder=\"ex.: 1200\" [ngModel]=\"deleteDialog.zIndex\" (ngModelChange)=\"update('zIndex', $event)\" /></mat-form-field>\n <div class=\"dialog-editor-actions\">\n <button mat-stroked-button color=\"primary\" (click)=\"resetOverrides()\">Resetar overrides</button>\n <span class=\"dialog-editor-actions-note\">Remove os valores locais para herdar do preset selecionado ou do preset global.</span>\n </div>\n </div>\n </mat-expansion-panel>\n</mat-accordion>\n", styles: [".dialog-editor-grid{display:grid;grid-template-columns:repeat(2,minmax(240px,1fr));gap:12px}.subgroup{grid-column:1/-1;display:grid;grid-template-columns:repeat(2,minmax(240px,1fr));gap:12px}h3{margin:0 0 8px;grid-column:1/-1}h4{margin:12px 0 0;grid-column:1/-1;font-weight:600}.dialog-editor-note{grid-column:1/-1;margin:0 0 8px;font-size:.85rem;color:var(--md-sys-color-on-surface-variant)}.dialog-editor-actions{grid-column:1/-1;display:flex;gap:8px;align-items:center;margin-top:8px}.dialog-editor-actions-note{font-size:.85rem;color:var(--md-sys-color-on-surface-variant)}.dialog-span{grid-column:1/-1}.help-icon-button{--mdc-icon-button-state-layer-size: 28px;--mdc-icon-button-icon-size: 18px;width:28px;height:28px;padding:0;display:inline-flex;align-items:center;justify-content:center;vertical-align:middle}.help-icon-button mat-icon{font-size:18px;line-height:18px;width:18px;height:18px}@media(max-width:900px){.dialog-editor-grid{grid-template-columns:1fr}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i6.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i6.MatLabel, selector: "mat-label" }, { kind: "directive", type: i6.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "directive", type: i6.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i7.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: i5$2.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: i5$2.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatSlideToggleModule }, { kind: "component", type: i6$1.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: MatButtonModule }, { kind: "component", type: i3.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: "component", type: i3.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatExpansionModule }, { kind: "directive", type: i8.MatAccordion, selector: "mat-accordion", inputs: ["hideToggle", "displayMode", "togglePosition"], exportAs: ["matAccordion"] }, { kind: "component", type: i8.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "component", type: i8.MatExpansionPanelHeader, selector: "mat-expansion-panel-header", inputs: ["expandedHeight", "collapsedHeight", "tabIndex"] }, { kind: "directive", type: i8.MatExpansionPanelTitle, selector: "mat-panel-title" }, { kind: "directive", type: i8.MatExpansionPanelDescription, selector: "mat-panel-description" }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i5.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }] });
24851
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.17", type: ConfirmDialogAppearanceEditorComponent, isStandalone: true, selector: "confirm-dialog-appearance-editor", inputs: { config: "config" }, outputs: { configChange: "configChange" }, ngImport: i0, template: "<mat-accordion multi>\n <mat-expansion-panel expanded>\n <mat-expansion-panel-header>\n <mat-panel-title><mat-icon [praxisIcon]=\"'tune'\"></mat-icon>&nbsp;Apar\u00EAncia & Comportamento</mat-panel-title>\n <mat-panel-description> Tema, alinhamento e heran\u00E7a de presets </mat-panel-description>\n </mat-expansion-panel-header>\n <div class=\"dialog-editor-grid\">\n <p class=\"dialog-editor-note\">\n Preced\u00EAncia: <strong>preset global</strong> \u2192 <strong>variante (delete)</strong> \u2192 <strong>override local</strong> (esta aba). Campos em branco herdam o valor do preset selecionado.\n </p>\n <mat-form-field appearance=\"outline\">\n <mat-label>Tema</mat-label>\n <mat-select [ngModel]=\"deleteDialog.themeColor\" (ngModelChange)=\"update('themeColor', $event)\">\n <mat-option [value]=\"undefined\">Padr\u00E3o</mat-option>\n <mat-option value=\"light\">Claro</mat-option>\n <mat-option value=\"dark\">Escuro</mat-option>\n <mat-option value=\"primary\">Prim\u00E1rio</mat-option>\n </mat-select>\n <button\n mat-icon-button\n matSuffix\n type=\"button\"\n class=\"help-icon-button\"\n matTooltip=\"For\u00E7a o tema do di\u00E1logo quando necess\u00E1rio.\"\n >\n <mat-icon>help_outline</mat-icon>\n </button>\n </mat-form-field>\n <mat-form-field appearance=\"outline\">\n <mat-label>Alinhamento das a\u00E7\u00F5es</mat-label>\n <mat-select [ngModel]=\"deleteDialog.actionsLayout\" (ngModelChange)=\"update('actionsLayout', $event)\">\n <mat-option value=\"start\">Alinhado \u00E0 esquerda</mat-option>\n <mat-option value=\"center\">Centralizado</mat-option>\n <mat-option value=\"end\">Alinhado \u00E0 direita</mat-option>\n <mat-option value=\"stretched\">Estendido (preencher)</mat-option>\n </mat-select>\n <button\n mat-icon-button\n matSuffix\n type=\"button\"\n class=\"help-icon-button\"\n matTooltip=\"Define como os bot\u00F5es se distribuem no rodap\u00E9.\"\n >\n <mat-icon>help_outline</mat-icon>\n </button>\n </mat-form-field>\n <mat-slide-toggle class=\"dialog-span\" [ngModel]=\"deleteDialog.hasBackdrop\" (ngModelChange)=\"update('hasBackdrop', $event)\">Mostrar backdrop</mat-slide-toggle>\n <mat-slide-toggle class=\"dialog-span\" [ngModel]=\"deleteDialog.disableClose\" (ngModelChange)=\"update('disableClose', $event)\">Desabilitar fechar (ESC/clique)</mat-slide-toggle>\n </div>\n </mat-expansion-panel>\n\n <mat-expansion-panel>\n <mat-expansion-panel-header>\n <mat-panel-title><mat-icon [praxisIcon]=\"'aspect_ratio'\"></mat-icon>&nbsp;Dimens\u00F5es</mat-panel-title>\n <mat-panel-description> Largura/altura e limites </mat-panel-description>\n </mat-expansion-panel-header>\n <div class=\"dialog-editor-grid\">\n <p class=\"dialog-editor-note dialog-span\">\n Dica: use presets para manter consist\u00EAncia entre di\u00E1logos; valores manuais sobrescrevem o preset.\n </p>\n <mat-form-field appearance=\"outline\">\n <mat-label>Tamanho (preset)</mat-label>\n <mat-select [ngModel]=\"selectedSizePreset\" (ngModelChange)=\"setSizePreset($event)\">\n <mat-option value=\"default\">Herdar (preset global)</mat-option>\n <mat-option value=\"sm\">sm (360px)</mat-option>\n <mat-option value=\"md\">md (420px)</mat-option>\n <mat-option value=\"lg\">lg (640px)</mat-option>\n <mat-option value=\"xl\">xl (800px)</mat-option>\n <mat-option value=\"tall\">tall (640px \u00D7 70vh)</mat-option>\n <mat-option value=\"full\">full (90vw \u00D7 90vh)</mat-option>\n <mat-option value=\"fluid\">fluid (100% \u00D7 80vh)</mat-option>\n </mat-select>\n </mat-form-field>\n <mat-form-field appearance=\"outline\">\n <mat-label>Largura (width)</mat-label>\n <input matInput [placeholder]=\"getInheritedValue('width') || 'ex.: 420px'\" [ngModel]=\"deleteDialog.width\" (ngModelChange)=\"update('width', $event)\" />\n <mat-hint *ngIf=\"!deleteDialog.width && getInheritedValue('width')\">Herdado: {{ getInheritedValue('width') }}</mat-hint>\n </mat-form-field>\n <mat-form-field appearance=\"outline\">\n <mat-label>Altura (height)</mat-label>\n <input matInput [placeholder]=\"getInheritedValue('height') || 'ex.: auto'\" [ngModel]=\"deleteDialog.height\" (ngModelChange)=\"update('height', $event)\" />\n <mat-hint *ngIf=\"!deleteDialog.height && getInheritedValue('height')\">Herdado: {{ getInheritedValue('height') }}</mat-hint>\n </mat-form-field>\n <mat-form-field appearance=\"outline\"><mat-label>Largura m\u00EDnima (minWidth)</mat-label><input matInput placeholder=\"ex.: 320px\" [ngModel]=\"deleteDialog.minWidth\" (ngModelChange)=\"update('minWidth', $event)\" /></mat-form-field>\n <mat-form-field appearance=\"outline\"><mat-label>Largura m\u00E1xima (maxWidth)</mat-label><input matInput placeholder=\"ex.: 90vw\" [ngModel]=\"deleteDialog.maxWidth\" (ngModelChange)=\"update('maxWidth', $event)\" /></mat-form-field>\n <mat-form-field appearance=\"outline\"><mat-label>Altura m\u00EDnima (minHeight)</mat-label><input matInput placeholder=\"ex.: 200px\" [ngModel]=\"deleteDialog.minHeight\" (ngModelChange)=\"update('minHeight', $event)\" /></mat-form-field>\n <mat-form-field appearance=\"outline\"><mat-label>Altura m\u00E1xima (maxHeight)</mat-label><input matInput [placeholder]=\"getInheritedValue('maxHeight') || 'ex.: 80vh'\" [ngModel]=\"deleteDialog.maxHeight\" (ngModelChange)=\"update('maxHeight', $event)\" /></mat-form-field>\n </div>\n </mat-expansion-panel>\n\n <mat-expansion-panel>\n <mat-expansion-panel-header>\n <mat-panel-title><mat-icon>animation</mat-icon>&nbsp;Anima\u00E7\u00E3o</mat-panel-title>\n <mat-panel-description> Tipo, dire\u00E7\u00E3o, dura\u00E7\u00E3o </mat-panel-description>\n </mat-expansion-panel-header>\n <div class=\"dialog-editor-grid\">\n <mat-form-field appearance=\"outline\">\n <mat-label>Tipo</mat-label>\n <mat-select [ngModel]=\"deleteDialog.animation?.type\" (ngModelChange)=\"update('animation.type', $event)\">\n <mat-option [value]=\"undefined\">Padr\u00E3o (translate)</mat-option>\n <mat-option value=\"translate\">translate</mat-option>\n <mat-option value=\"slide\">slide</mat-option>\n <mat-option value=\"fade\">fade</mat-option>\n <mat-option value=\"expand\">expand</mat-option>\n <mat-option value=\"zoom\">zoom</mat-option>\n </mat-select>\n </mat-form-field>\n <mat-form-field appearance=\"outline\">\n <mat-label>Dire\u00E7\u00E3o</mat-label>\n <mat-select [ngModel]=\"deleteDialog.animation?.direction\" (ngModelChange)=\"update('animation.direction', $event)\">\n <mat-option [value]=\"undefined\">Padr\u00E3o</mat-option>\n <mat-option value=\"up\">para cima</mat-option>\n <mat-option value=\"down\">para baixo</mat-option>\n <mat-option value=\"left\">para a esquerda</mat-option>\n <mat-option value=\"right\">para a direita</mat-option>\n </mat-select>\n </mat-form-field>\n <mat-form-field appearance=\"outline\">\n <mat-label>Dura\u00E7\u00E3o (ms)</mat-label>\n <input matInput type=\"number\" [ngModel]=\"deleteDialog.animation?.duration\" (ngModelChange)=\"update('animation.duration', $event)\" />\n </mat-form-field>\n <mat-form-field appearance=\"outline\">\n <mat-label>Easing</mat-label>\n <input matInput placeholder=\"cubic-bezier(...)\" [ngModel]=\"deleteDialog.animation?.easing\" (ngModelChange)=\"update('animation.easing', $event)\" />\n </mat-form-field>\n <p class=\"dialog-editor-note dialog-span\">\n Sugest\u00E3o: mantenha dura\u00E7\u00E3o entre 160\u2013240ms para a\u00E7\u00F5es r\u00E1pidas.\n </p>\n </div>\n </mat-expansion-panel>\n\n <mat-expansion-panel>\n <mat-expansion-panel-header>\n <mat-panel-title><mat-icon>palette</mat-icon>&nbsp;Estilos (tokens)</mat-panel-title>\n <mat-panel-description> Apar\u00EAncia do cont\u00EAiner e conte\u00FAdo </mat-panel-description>\n </mat-expansion-panel-header>\n <div class=\"dialog-editor-grid\">\n <p class=\"dialog-editor-note dialog-span\">\n Prefira tokens M3 (ex.: <code>var(--md-sys-color-surface-container-high)</code>) para suportar light/dark.\n </p>\n <mat-form-field appearance=\"outline\"><mat-label>Border radius (shape)</mat-label><input matInput placeholder=\"ex.: 12px\" [ngModel]=\"deleteDialog.styles?.containerShape\" (ngModelChange)=\"update('styles.containerShape', $event)\" /></mat-form-field>\n <mat-form-field appearance=\"outline\"><mat-label>Padding a\u00E7\u00F5es</mat-label><input matInput placeholder=\"12px 16px\" [ngModel]=\"deleteDialog.styles?.actionsPadding\" (ngModelChange)=\"update('styles.actionsPadding', $event)\" /></mat-form-field>\n <mat-form-field appearance=\"outline\"><mat-label>Padding conte\u00FAdo</mat-label><input matInput placeholder=\"16px\" [ngModel]=\"deleteDialog.styles?.contentPadding\" (ngModelChange)=\"update('styles.contentPadding', $event)\" /></mat-form-field>\n <mat-form-field appearance=\"outline\"><mat-label>Padding t\u00EDtulo</mat-label><input matInput placeholder=\"12px 16px\" [ngModel]=\"deleteDialog.styles?.headlinePadding\" (ngModelChange)=\"update('styles.headlinePadding', $event)\" /></mat-form-field>\n <mat-form-field appearance=\"outline\"><mat-label>Padding conte\u00FAdo (com a\u00E7\u00F5es)</mat-label><input matInput placeholder=\"16px\" [ngModel]=\"deleteDialog.styles?.withActionsContentPadding\" (ngModelChange)=\"update('styles.withActionsContentPadding', $event)\" /></mat-form-field>\n <mat-form-field appearance=\"outline\"><mat-label>Cor do cont\u00EAiner</mat-label><input matInput placeholder=\"#262626\" [ngModel]=\"deleteDialog.styles?.containerColor\" (ngModelChange)=\"update('styles.containerColor', $event)\" /></mat-form-field>\n <mat-form-field appearance=\"outline\"><mat-label>Cor do t\u00EDtulo</mat-label><input matInput placeholder=\"var(--md-sys-color-on-surface)\" [ngModel]=\"deleteDialog.styles?.subheadColor\" (ngModelChange)=\"update('styles.subheadColor', $event)\" /></mat-form-field>\n <mat-form-field appearance=\"outline\"><mat-label>Cor do conte\u00FAdo</mat-label><input matInput placeholder=\"var(--md-sys-color-on-surface-variant)\" [ngModel]=\"deleteDialog.styles?.supportingTextColor\" (ngModelChange)=\"update('styles.supportingTextColor', $event)\" /></mat-form-field>\n </div>\n </mat-expansion-panel>\n\n <mat-expansion-panel>\n <mat-expansion-panel-header>\n <mat-panel-title><mat-icon>open_with</mat-icon>&nbsp;Posi\u00E7\u00E3o</mat-panel-title>\n <mat-panel-description> Offsets opcionais </mat-panel-description>\n </mat-expansion-panel-header>\n <div class=\"dialog-editor-grid\">\n <p class=\"dialog-editor-note dialog-span\">\n Use offsets apenas quando o di\u00E1logo precisar ancorar em regi\u00F5es espec\u00EDficas da tela.\n </p>\n <mat-form-field appearance=\"outline\"><mat-label>Top</mat-label><input matInput placeholder=\"ex.: 10vh\" [ngModel]=\"deleteDialog.position?.top\" (ngModelChange)=\"update('position.top', $event)\" /></mat-form-field>\n <mat-form-field appearance=\"outline\"><mat-label>Right</mat-label><input matInput placeholder=\"ex.: 24px\" [ngModel]=\"deleteDialog.position?.right\" (ngModelChange)=\"update('position.right', $event)\" /></mat-form-field>\n <mat-form-field appearance=\"outline\"><mat-label>Bottom</mat-label><input matInput placeholder=\"ex.: 10vh\" [ngModel]=\"deleteDialog.position?.bottom\" (ngModelChange)=\"update('position.bottom', $event)\" /></mat-form-field>\n <mat-form-field appearance=\"outline\"><mat-label>Left</mat-label><input matInput placeholder=\"ex.: 24px\" [ngModel]=\"deleteDialog.position?.left\" (ngModelChange)=\"update('position.left', $event)\" /></mat-form-field>\n </div>\n </mat-expansion-panel>\n\n <mat-expansion-panel>\n <mat-expansion-panel-header>\n <mat-panel-title><mat-icon>code</mat-icon>&nbsp;Classes & Avan\u00E7ado</mat-panel-title>\n <mat-panel-description> CSS e z-index </mat-panel-description>\n </mat-expansion-panel-header>\n <div class=\"dialog-editor-grid\">\n <mat-form-field appearance=\"outline\"><mat-label>Classe do painel</mat-label><input matInput placeholder=\"ex.: my-panel\" [ngModel]=\"deleteDialog.panelClass\" (ngModelChange)=\"update('panelClass', $event)\" /></mat-form-field>\n <mat-form-field appearance=\"outline\"><mat-label>Classe do backdrop</mat-label><input matInput placeholder=\"ex.: my-backdrop\" [ngModel]=\"deleteDialog.backdropClass\" (ngModelChange)=\"update('backdropClass', $event)\" /></mat-form-field>\n <mat-form-field appearance=\"outline\"><mat-label>z-index</mat-label><input matInput type=\"number\" placeholder=\"ex.: 1200\" [ngModel]=\"deleteDialog.zIndex\" (ngModelChange)=\"update('zIndex', $event)\" /></mat-form-field>\n <div class=\"dialog-editor-actions\">\n <button mat-stroked-button color=\"primary\" (click)=\"resetOverrides()\">Resetar overrides</button>\n <span class=\"dialog-editor-actions-note\">Remove os valores locais para herdar do preset selecionado ou do preset global.</span>\n </div>\n </div>\n </mat-expansion-panel>\n</mat-accordion>\n", styles: [".dialog-editor-grid{display:grid;grid-template-columns:repeat(2,minmax(240px,1fr));gap:12px}.subgroup{grid-column:1/-1;display:grid;grid-template-columns:repeat(2,minmax(240px,1fr));gap:12px}h3{margin:0 0 8px;grid-column:1/-1}h4{margin:12px 0 0;grid-column:1/-1;font-weight:600}.dialog-editor-note{grid-column:1/-1;margin:0 0 8px;font-size:.85rem;color:var(--md-sys-color-on-surface-variant)}.dialog-editor-actions{grid-column:1/-1;display:flex;gap:8px;align-items:center;margin-top:8px}.dialog-editor-actions-note{font-size:.85rem;color:var(--md-sys-color-on-surface-variant)}.dialog-span{grid-column:1/-1}.help-icon-button{--mdc-icon-button-state-layer-size: 28px;--mdc-icon-button-icon-size: 18px;width:28px;height:28px;padding:0;display:inline-flex;align-items:center;justify-content:center;vertical-align:middle}.help-icon-button mat-icon{font-size:18px;line-height:18px;width:18px;height:18px}@media(max-width:900px){.dialog-editor-grid{grid-template-columns:1fr}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i6.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i6.MatLabel, selector: "mat-label" }, { kind: "directive", type: i6.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "directive", type: i6.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i7.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: i5$1.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: i5$1.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatSlideToggleModule }, { kind: "component", type: i6$1.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: MatButtonModule }, { kind: "component", type: i3.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: "component", type: i3.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatExpansionModule }, { kind: "directive", type: i8.MatAccordion, selector: "mat-accordion", inputs: ["hideToggle", "displayMode", "togglePosition"], exportAs: ["matAccordion"] }, { kind: "component", type: i8.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "component", type: i8.MatExpansionPanelHeader, selector: "mat-expansion-panel-header", inputs: ["expandedHeight", "collapsedHeight", "tabIndex"] }, { kind: "directive", type: i8.MatExpansionPanelTitle, selector: "mat-panel-title" }, { kind: "directive", type: i8.MatExpansionPanelDescription, selector: "mat-panel-description" }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i5.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }] });
24371
24852
  }
24372
24853
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: ConfirmDialogAppearanceEditorComponent, decorators: [{
24373
24854
  type: Component,
@@ -27175,7 +27656,7 @@ class TableRulesEditorComponent {
27175
27656
 
27176
27657
  </mat-accordion>
27177
27658
  </div>
27178
- `, isInline: true, styles: [".rules-editor{display:flex;flex-direction:column;gap:12px}.block{border:1px solid var(--md-sys-color-outline-variant);border-radius:12px;background:linear-gradient(180deg,var(--md-sys-color-surface-container-low),var(--md-sys-color-surface));-webkit-backdrop-filter:saturate(140%) blur(2px);backdrop-filter:saturate(140%) blur(2px);transition:all .2s ease}.block.is-expanded{box-shadow:var(--md-sys-elevation-level2)}.block-header{display:flex;align-items:center;gap:8px;padding:6px 12px;min-height:40px;background:linear-gradient(180deg,var(--md-sys-color-surface-container-low),var(--md-sys-color-surface));border-bottom:1px solid var(--md-sys-color-outline-variant);transition:all .2s ease}.block-title{font-weight:600;font-size:.95rem;letter-spacing:.5px;display:flex;align-items:center;gap:6px}.block-subtitle{opacity:.7;font-size:.8rem;margin-left:8px}.block-body{padding:12px;display:flex;flex-direction:column;gap:12px}.a-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:12px}.mode-tabs{--mat-tab-header-inactive-label-text-color: var(--md-sys-color-on-surface-variant)}.basic-grid{display:grid;grid-template-columns:repeat(3,minmax(180px,1fr));gap:12px;align-items:start}.rules-grid mat-form-field:nth-of-type(1){grid-column:1}.rules-grid mat-form-field:nth-of-type(2){grid-column:2}.rules-grid .value-host{grid-column:3;min-width:0}@media(max-width:991.98px){.basic-grid{grid-template-columns:repeat(auto-fit,minmax(220px,1fr))}.rules-grid .value-host{grid-column:1 / -1}}.basic-grid .mat-mdc-form-field .mdc-floating-label{font-size:.85rem}.spacer{flex:1}.effects-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:12px}.quick-effects{display:block}.qe-row{display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:12px;align-items:start}.qe-group{display:flex;flex-direction:column;gap:6px}.qe-title{font-size:.85rem;opacity:.8}.qe-inline{display:flex;gap:8px;align-items:center;flex-wrap:wrap}.qe-presets{display:grid;grid-template-columns:repeat(auto-fill,minmax(32px,1fr));gap:8px;align-items:center;max-width:280px}.qe-presets .mat-mdc-icon-button.mat-mdc-button-base{justify-self:start}.qe-presets .mat-stroked-button{grid-column:1 / -1;justify-self:start}.qe-inline .mat-mdc-icon-button.mat-mdc-button-base{width:32px;height:32px;padding:0}.qe-inline .mat-mdc-icon-button .mat-icon{font-size:18px;line-height:32px;width:18px;height:18px;transition:all .2s ease}.qe-label{display:flex;gap:6px;align-items:center;font-size:.85rem}.qe-number{width:84px;padding:6px}.qe-suffix{opacity:.7}.qe-select{width:120px}.qe-text{min-width:160px;padding:6px}.qe-toggle-group{display:flex;align-items:center;gap:8px;flex-wrap:wrap}.qe-desc{font-size:.8rem;opacity:.75}.effects-preview{grid-column:1 / -1}.effects-preview-box{display:flex;align-items:center;gap:8px;border:1px dashed var(--md-sys-color-outline-variant);border-radius:6px;padding:6px 8px;background:var(--md-sys-color-surface-container-low);width:100%;min-height:36px;transition:all .2s ease}.pfx-badge-preview{display:inline-flex;align-items:center;gap:4px;padding:2px 6px;border-radius:999px;font-size:12px;line-height:16px;transition:all .2s ease}.pfx-badge-preview.v-filled.c-primary{background:var(--md-sys-color-primary-container);color:var(--md-sys-color-on-primary-container)}.pfx-badge-preview.v-filled.c-accent{background:var(--md-sys-color-secondary-container);color:var(--md-sys-color-on-secondary-container)}.pfx-badge-preview.v-filled.c-warn{background:var(--md-sys-color-error-container);color:var(--md-sys-color-on-error-container)}.pfx-badge-preview.v-outlined{border:1px solid var(--md-sys-color-outline-variant)}.pfx-badge-preview.v-soft{background:var(--md-sys-color-surface-container-highest)}.dsl-box .full{width:100%}.range-grid{display:grid;grid-template-columns:repeat(2,minmax(160px,1fr));gap:12px;align-items:center}.no-value-hint{align-self:center;opacity:.7;font-size:.85rem}.errors{background:var(--md-sys-color-error-container);color:var(--md-sys-color-on-error-container);padding:8px 12px;border:1px solid var(--md-sys-color-error);border-radius:6px}.group-card{border:1px solid var(--md-sys-color-outline-variant);padding:8px 12px;border-radius:10px;display:flex;flex-direction:column;gap:8px;background:var(--md-sys-color-surface-container-lowest);transition:all .2s ease}.group-header,.group-actions{display:flex;gap:8px;align-items:center}.group-list{display:grid;gap:6px}.group-item{display:flex;align-items:center;justify-content:space-between;gap:8px;padding:6px 8px;border:1px solid var(--md-sys-color-outline-variant);border-radius:6px;background:var(--md-sys-color-surface-container-low);transition:all .2s ease}.item-main{display:flex;align-items:center;gap:8px}.drag-handle{cursor:grab;opacity:.7}.expr{font-family:monospace;font-size:.85rem}.group-footer{display:flex;gap:8px;align-items:center}.subgroups{display:grid;gap:8px;margin-top:8px}.subgroup{border:1px dashed var(--md-sys-color-outline-variant);border-radius:6px;padding:6px 8px;background:var(--md-sys-color-surface-container-low);transition:all .2s ease}.sub-header{display:flex;align-items:center;gap:8px}.sub-body{display:flex;align-items:center;justify-content:space-between;gap:12px}.rules-list .list-header{padding:4px 0}.rule-item .rule-content{display:flex;gap:12px;align-items:center;justify-content:space-between;width:100%}.rule-main{display:flex;flex-direction:column;gap:6px;min-width:0}.rule-cond{font-family:monospace;font-size:.9rem;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%}.chip{display:inline-block;padding:2px 6px;border:1px solid var(--md-sys-color-outline-variant);border-radius:10px;font-size:12px;margin-right:6px}.rule-actions{display:flex;gap:6px;align-items:center}.preview{background:var(--md-sys-color-surface-container-low);padding:8px 12px;border:1px solid var(--md-sys-color-outline-variant);border-radius:6px}.preview-rows{display:grid;gap:6px}.p-row{display:flex;align-items:center;gap:8px}.row-title{width:72px;opacity:.7}.row-effects{display:flex;gap:6px;flex-wrap:wrap}.visually-hidden{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.rules-nav-chips{margin-bottom:6px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1$2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i1$2.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i1$2.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "directive", type: i1$2.NgSwitchDefault, selector: "[ngSwitchDefault]" }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i6.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i6.MatLabel, selector: "mat-label" }, { kind: "directive", type: i6.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i7.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: i5$2.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: i5$2.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3.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: "component", type: i3.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i5.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatButtonToggleModule }, { kind: "directive", type: i15$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: i15$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: MatSlideToggleModule }, { kind: "component", type: i6$1.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: MatListModule }, { kind: "component", type: i11.MatList, selector: "mat-list", exportAs: ["matList"] }, { kind: "component", type: i11.MatListItem, selector: "mat-list-item, a[mat-list-item], button[mat-list-item]", inputs: ["activated"], exportAs: ["matListItem"] }, { kind: "ngmodule", type: MatDividerModule }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i10.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: MatDatepickerModule }, { kind: "component", type: i15$2.MatDatepicker, selector: "mat-datepicker", exportAs: ["matDatepicker"] }, { kind: "directive", type: i15$2.MatDatepickerInput, selector: "input[matDatepicker]", inputs: ["matDatepicker", "min", "max", "matDatepickerFilter"], exportAs: ["matDatepickerInput"] }, { kind: "ngmodule", type: MatNativeDateModule }, { kind: "ngmodule", type: MatChipsModule }, { kind: "component", type: i15.MatChip, selector: "mat-basic-chip, [mat-basic-chip], mat-chip, [mat-chip]", inputs: ["role", "id", "aria-label", "aria-description", "value", "color", "removable", "highlighted", "disableRipple", "disabled"], outputs: ["removed", "destroyed"], exportAs: ["matChip"] }, { kind: "component", type: i15.MatChipListbox, selector: "mat-chip-listbox", inputs: ["multiple", "aria-orientation", "selectable", "compareWith", "required", "hideSingleSelectionIndicator", "value"], outputs: ["change"] }, { kind: "component", type: i15.MatChipOption, selector: "mat-basic-chip-option, [mat-basic-chip-option], mat-chip-option, [mat-chip-option]", inputs: ["selectable", "selected"], outputs: ["selectionChange"] }, { kind: "ngmodule", type: MatAutocompleteModule }, { kind: "component", type: i17.MatAutocomplete, selector: "mat-autocomplete", inputs: ["aria-label", "aria-labelledby", "displayWith", "autoActiveFirstOption", "autoSelectActiveOption", "requireSelection", "panelWidth", "disableRipple", "class", "hideSingleSelectionIndicator"], outputs: ["optionSelected", "opened", "closed", "optionActivated"], exportAs: ["matAutocomplete"] }, { kind: "directive", type: i17.MatAutocompleteTrigger, selector: "input[matAutocomplete], textarea[matAutocomplete]", inputs: ["matAutocomplete", "matAutocompletePosition", "matAutocompleteConnectedTo", "autocomplete", "matAutocompleteDisabled"], exportAs: ["matAutocompleteTrigger"] }, { kind: "ngmodule", type: MatMenuModule }, { kind: "ngmodule", type: MatTabsModule }, { kind: "component", type: i4.MatTab, selector: "mat-tab", inputs: ["disabled", "label", "aria-label", "aria-labelledby", "labelClass", "bodyClass", "id"], exportAs: ["matTab"] }, { kind: "component", type: i4.MatTabGroup, selector: "mat-tab-group", inputs: ["color", "fitInkBarToContent", "mat-stretch-tabs", "mat-align-tabs", "dynamicHeight", "selectedIndex", "headerPosition", "animationDuration", "contentTabIndex", "disablePagination", "disableRipple", "preserveContent", "backgroundColor", "aria-label", "aria-labelledby"], outputs: ["selectedIndexChange", "focusChange", "animationDone", "selectedTabChange"], exportAs: ["matTabGroup"] }, { kind: "ngmodule", type: DragDropModule }, { kind: "directive", type: i13.CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer", "cdkDropListHasAnchor"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: i13.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "directive", type: i13.CdkDragHandle, selector: "[cdkDragHandle]", inputs: ["cdkDragHandleDisabled"] }, { kind: "directive", type: DynamicFieldLoaderDirective, selector: "[dynamicFieldLoader]", inputs: ["fields", "formGroup", "enableExternalControlBinding", "itemTemplate", "debugTrace", "debugTraceLabel", "readonlyMode", "disabledMode", "presentationMode", "visible", "canvasMode"], outputs: ["componentsCreated", "fieldCreated", "fieldDestroyed", "renderError", "canvasMouseEnter", "canvasMouseLeave", "canvasClick"] }, { kind: "ngmodule", type: MatExpansionModule }, { kind: "directive", type: i8.MatAccordion, selector: "mat-accordion", inputs: ["hideToggle", "displayMode", "togglePosition"], exportAs: ["matAccordion"] }, { kind: "component", type: i8.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "component", type: i8.MatExpansionPanelHeader, selector: "mat-expansion-panel-header", inputs: ["expandedHeight", "collapsedHeight", "tabIndex"] }, { kind: "directive", type: i8.MatExpansionPanelTitle, selector: "mat-panel-title" }, { kind: "directive", type: i8.MatExpansionPanelDescription, selector: "mat-panel-description" }, { kind: "component", type: TableConfigToolbarComponent, selector: "pfx-table-config-toolbar", inputs: ["applyDisabled", "ariaLabel", "exportLabel", "importLabel", "resetLabel", "resetLabelShort", "applyLabel"], outputs: ["export", "import", "reset", "apply"] }, { kind: "component", type: RuleEffectsPanelComponent, selector: "praxis-rule-effects-panel", inputs: ["scope", "value"], outputs: ["valueChange", "apply", "reset"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
27659
+ `, isInline: true, styles: [".rules-editor{display:flex;flex-direction:column;gap:12px}.block{border:1px solid var(--md-sys-color-outline-variant);border-radius:12px;background:linear-gradient(180deg,var(--md-sys-color-surface-container-low),var(--md-sys-color-surface));-webkit-backdrop-filter:saturate(140%) blur(2px);backdrop-filter:saturate(140%) blur(2px);transition:all .2s ease}.block.is-expanded{box-shadow:var(--md-sys-elevation-level2)}.block-header{display:flex;align-items:center;gap:8px;padding:6px 12px;min-height:40px;background:linear-gradient(180deg,var(--md-sys-color-surface-container-low),var(--md-sys-color-surface));border-bottom:1px solid var(--md-sys-color-outline-variant);transition:all .2s ease}.block-title{font-weight:600;font-size:.95rem;letter-spacing:.5px;display:flex;align-items:center;gap:6px}.block-subtitle{opacity:.7;font-size:.8rem;margin-left:8px}.block-body{padding:12px;display:flex;flex-direction:column;gap:12px}.a-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:12px}.mode-tabs{--mat-tab-header-inactive-label-text-color: var(--md-sys-color-on-surface-variant)}.basic-grid{display:grid;grid-template-columns:repeat(3,minmax(180px,1fr));gap:12px;align-items:start}.rules-grid mat-form-field:nth-of-type(1){grid-column:1}.rules-grid mat-form-field:nth-of-type(2){grid-column:2}.rules-grid .value-host{grid-column:3;min-width:0}@media(max-width:991.98px){.basic-grid{grid-template-columns:repeat(auto-fit,minmax(220px,1fr))}.rules-grid .value-host{grid-column:1 / -1}}.basic-grid .mat-mdc-form-field .mdc-floating-label{font-size:.85rem}.spacer{flex:1}.effects-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:12px}.quick-effects{display:block}.qe-row{display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:12px;align-items:start}.qe-group{display:flex;flex-direction:column;gap:6px}.qe-title{font-size:.85rem;opacity:.8}.qe-inline{display:flex;gap:8px;align-items:center;flex-wrap:wrap}.qe-presets{display:grid;grid-template-columns:repeat(auto-fill,minmax(32px,1fr));gap:8px;align-items:center;max-width:280px}.qe-presets .mat-mdc-icon-button.mat-mdc-button-base{justify-self:start}.qe-presets .mat-stroked-button{grid-column:1 / -1;justify-self:start}.qe-inline .mat-mdc-icon-button.mat-mdc-button-base{width:32px;height:32px;padding:0}.qe-inline .mat-mdc-icon-button .mat-icon{font-size:18px;line-height:32px;width:18px;height:18px;transition:all .2s ease}.qe-label{display:flex;gap:6px;align-items:center;font-size:.85rem}.qe-number{width:84px;padding:6px}.qe-suffix{opacity:.7}.qe-select{width:120px}.qe-text{min-width:160px;padding:6px}.qe-toggle-group{display:flex;align-items:center;gap:8px;flex-wrap:wrap}.qe-desc{font-size:.8rem;opacity:.75}.effects-preview{grid-column:1 / -1}.effects-preview-box{display:flex;align-items:center;gap:8px;border:1px dashed var(--md-sys-color-outline-variant);border-radius:6px;padding:6px 8px;background:var(--md-sys-color-surface-container-low);width:100%;min-height:36px;transition:all .2s ease}.pfx-badge-preview{display:inline-flex;align-items:center;gap:4px;padding:2px 6px;border-radius:999px;font-size:12px;line-height:16px;transition:all .2s ease}.pfx-badge-preview.v-filled.c-primary{background:var(--md-sys-color-primary-container);color:var(--md-sys-color-on-primary-container)}.pfx-badge-preview.v-filled.c-accent{background:var(--md-sys-color-secondary-container);color:var(--md-sys-color-on-secondary-container)}.pfx-badge-preview.v-filled.c-warn{background:var(--md-sys-color-error-container);color:var(--md-sys-color-on-error-container)}.pfx-badge-preview.v-outlined{border:1px solid var(--md-sys-color-outline-variant)}.pfx-badge-preview.v-soft{background:var(--md-sys-color-surface-container-highest)}.dsl-box .full{width:100%}.range-grid{display:grid;grid-template-columns:repeat(2,minmax(160px,1fr));gap:12px;align-items:center}.no-value-hint{align-self:center;opacity:.7;font-size:.85rem}.errors{background:var(--md-sys-color-error-container);color:var(--md-sys-color-on-error-container);padding:8px 12px;border:1px solid var(--md-sys-color-error);border-radius:6px}.group-card{border:1px solid var(--md-sys-color-outline-variant);padding:8px 12px;border-radius:10px;display:flex;flex-direction:column;gap:8px;background:var(--md-sys-color-surface-container-lowest);transition:all .2s ease}.group-header,.group-actions{display:flex;gap:8px;align-items:center}.group-list{display:grid;gap:6px}.group-item{display:flex;align-items:center;justify-content:space-between;gap:8px;padding:6px 8px;border:1px solid var(--md-sys-color-outline-variant);border-radius:6px;background:var(--md-sys-color-surface-container-low);transition:all .2s ease}.item-main{display:flex;align-items:center;gap:8px}.drag-handle{cursor:grab;opacity:.7}.expr{font-family:monospace;font-size:.85rem}.group-footer{display:flex;gap:8px;align-items:center}.subgroups{display:grid;gap:8px;margin-top:8px}.subgroup{border:1px dashed var(--md-sys-color-outline-variant);border-radius:6px;padding:6px 8px;background:var(--md-sys-color-surface-container-low);transition:all .2s ease}.sub-header{display:flex;align-items:center;gap:8px}.sub-body{display:flex;align-items:center;justify-content:space-between;gap:12px}.rules-list .list-header{padding:4px 0}.rule-item .rule-content{display:flex;gap:12px;align-items:center;justify-content:space-between;width:100%}.rule-main{display:flex;flex-direction:column;gap:6px;min-width:0}.rule-cond{font-family:monospace;font-size:.9rem;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%}.chip{display:inline-block;padding:2px 6px;border:1px solid var(--md-sys-color-outline-variant);border-radius:10px;font-size:12px;margin-right:6px}.rule-actions{display:flex;gap:6px;align-items:center}.preview{background:var(--md-sys-color-surface-container-low);padding:8px 12px;border:1px solid var(--md-sys-color-outline-variant);border-radius:6px}.preview-rows{display:grid;gap:6px}.p-row{display:flex;align-items:center;gap:8px}.row-title{width:72px;opacity:.7}.row-effects{display:flex;gap:6px;flex-wrap:wrap}.visually-hidden{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.rules-nav-chips{margin-bottom:6px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1$2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i1$2.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i1$2.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "directive", type: i1$2.NgSwitchDefault, selector: "[ngSwitchDefault]" }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i6.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i6.MatLabel, selector: "mat-label" }, { kind: "directive", type: i6.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i7.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: i5$1.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: i5$1.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3.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: "component", type: i3.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i5.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatButtonToggleModule }, { kind: "directive", type: i15$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: i15$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: MatSlideToggleModule }, { kind: "component", type: i6$1.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: MatListModule }, { kind: "component", type: i11.MatList, selector: "mat-list", exportAs: ["matList"] }, { kind: "component", type: i11.MatListItem, selector: "mat-list-item, a[mat-list-item], button[mat-list-item]", inputs: ["activated"], exportAs: ["matListItem"] }, { kind: "ngmodule", type: MatDividerModule }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i10.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: MatDatepickerModule }, { kind: "component", type: i15$3.MatDatepicker, selector: "mat-datepicker", exportAs: ["matDatepicker"] }, { kind: "directive", type: i15$3.MatDatepickerInput, selector: "input[matDatepicker]", inputs: ["matDatepicker", "min", "max", "matDatepickerFilter"], exportAs: ["matDatepickerInput"] }, { kind: "ngmodule", type: MatNativeDateModule }, { kind: "ngmodule", type: MatChipsModule }, { kind: "component", type: i15.MatChip, selector: "mat-basic-chip, [mat-basic-chip], mat-chip, [mat-chip]", inputs: ["role", "id", "aria-label", "aria-description", "value", "color", "removable", "highlighted", "disableRipple", "disabled"], outputs: ["removed", "destroyed"], exportAs: ["matChip"] }, { kind: "component", type: i15.MatChipListbox, selector: "mat-chip-listbox", inputs: ["multiple", "aria-orientation", "selectable", "compareWith", "required", "hideSingleSelectionIndicator", "value"], outputs: ["change"] }, { kind: "component", type: i15.MatChipOption, selector: "mat-basic-chip-option, [mat-basic-chip-option], mat-chip-option, [mat-chip-option]", inputs: ["selectable", "selected"], outputs: ["selectionChange"] }, { kind: "ngmodule", type: MatAutocompleteModule }, { kind: "component", type: i17$1.MatAutocomplete, selector: "mat-autocomplete", inputs: ["aria-label", "aria-labelledby", "displayWith", "autoActiveFirstOption", "autoSelectActiveOption", "requireSelection", "panelWidth", "disableRipple", "class", "hideSingleSelectionIndicator"], outputs: ["optionSelected", "opened", "closed", "optionActivated"], exportAs: ["matAutocomplete"] }, { kind: "directive", type: i17$1.MatAutocompleteTrigger, selector: "input[matAutocomplete], textarea[matAutocomplete]", inputs: ["matAutocomplete", "matAutocompletePosition", "matAutocompleteConnectedTo", "autocomplete", "matAutocompleteDisabled"], exportAs: ["matAutocompleteTrigger"] }, { kind: "ngmodule", type: MatMenuModule }, { kind: "ngmodule", type: MatTabsModule }, { kind: "component", type: i4.MatTab, selector: "mat-tab", inputs: ["disabled", "label", "aria-label", "aria-labelledby", "labelClass", "bodyClass", "id"], exportAs: ["matTab"] }, { kind: "component", type: i4.MatTabGroup, selector: "mat-tab-group", inputs: ["color", "fitInkBarToContent", "mat-stretch-tabs", "mat-align-tabs", "dynamicHeight", "selectedIndex", "headerPosition", "animationDuration", "contentTabIndex", "disablePagination", "disableRipple", "preserveContent", "backgroundColor", "aria-label", "aria-labelledby"], outputs: ["selectedIndexChange", "focusChange", "animationDone", "selectedTabChange"], exportAs: ["matTabGroup"] }, { kind: "ngmodule", type: DragDropModule }, { kind: "directive", type: i12.CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer", "cdkDropListHasAnchor"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: i12.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "directive", type: i12.CdkDragHandle, selector: "[cdkDragHandle]", inputs: ["cdkDragHandleDisabled"] }, { kind: "directive", type: DynamicFieldLoaderDirective, selector: "[dynamicFieldLoader]", inputs: ["fields", "formGroup", "enableExternalControlBinding", "itemTemplate", "debugTrace", "debugTraceLabel", "readonlyMode", "disabledMode", "presentationMode", "visible", "canvasMode"], outputs: ["componentsCreated", "fieldCreated", "fieldDestroyed", "renderError", "canvasMouseEnter", "canvasMouseLeave", "canvasClick"] }, { kind: "ngmodule", type: MatExpansionModule }, { kind: "directive", type: i8.MatAccordion, selector: "mat-accordion", inputs: ["hideToggle", "displayMode", "togglePosition"], exportAs: ["matAccordion"] }, { kind: "component", type: i8.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "component", type: i8.MatExpansionPanelHeader, selector: "mat-expansion-panel-header", inputs: ["expandedHeight", "collapsedHeight", "tabIndex"] }, { kind: "directive", type: i8.MatExpansionPanelTitle, selector: "mat-panel-title" }, { kind: "directive", type: i8.MatExpansionPanelDescription, selector: "mat-panel-description" }, { kind: "component", type: TableConfigToolbarComponent, selector: "pfx-table-config-toolbar", inputs: ["applyDisabled", "ariaLabel", "exportLabel", "importLabel", "resetLabel", "resetLabelShort", "applyLabel"], outputs: ["export", "import", "reset", "apply"] }, { kind: "component", type: RuleEffectsPanelComponent, selector: "praxis-rule-effects-panel", inputs: ["scope", "value"], outputs: ["valueChange", "apply", "reset"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
27179
27660
  }
27180
27661
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: TableRulesEditorComponent, decorators: [{
27181
27662
  type: Component,
@@ -28796,7 +29277,7 @@ class PraxisTableConfigEditor {
28796
29277
  this.behaviorFeedbackBurstTypes.clear();
28797
29278
  }
28798
29279
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: PraxisTableConfigEditor, deps: [{ token: i0.ChangeDetectorRef }, { token: i1.TableConfigService }], target: i0.ɵɵFactoryTarget.Component });
28799
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.17", type: PraxisTableConfigEditor, isStandalone: true, selector: "praxis-table-config-editor", providers: [TableConfigService], viewQueries: [{ propertyName: "filterSettingsEditor", first: true, predicate: ["tableFilterSettingsRef"], descendants: true }, { propertyName: "behaviorEditor", first: true, predicate: BehaviorConfigEditorComponent, descendants: true }, { propertyName: "crudEditorSetter", first: true, predicate: ["crudEditorRef"], descendants: true }], ngImport: i0, template: " <mat-tab-group class=\"config-tabs\" [(selectedIndex)]=\"activeSectionIndex\">\n <mat-tab *ngFor=\"let section of sections\">\n <ng-template mat-tab-label>\n @if (section.icon) { <mat-icon [praxisIcon]=\"section.icon\"></mat-icon> }\n <span [attr.data-testid]=\"'config-tab-' + section.id\">{{ section.label }}</span>\n </ng-template>\n <div class=\"tab-content\">\n <ng-container [ngSwitch]=\"section.id\">\n <div *ngSwitchCase=\"'connect'\" class=\"connect-grid\">\n <mat-form-field appearance=\"outline\">\n <mat-label>Recurso</mat-label>\n <input matInput [(ngModel)]=\"resourcePath\" (ngModelChange)=\"onResourcePathChange($event)\" placeholder=\"ex.: employees\" />\n <mat-icon matSuffix>link</mat-icon>\n </mat-form-field>\n <mat-form-field appearance=\"outline\">\n <mat-label>Chave prim\u00E1ria</mat-label>\n <input matInput [(ngModel)]=\"idField\" (ngModelChange)=\"onIdFieldChange($event)\" placeholder=\"ex.: id, uuid, codigo\" />\n <mat-icon matSuffix>fingerprint</mat-icon>\n </mat-form-field>\n <p class=\"connect-note\">Defina o recurso da API e, se necess\u00E1rio, a chave prim\u00E1ria.</p>\n\n <!-- Diverg\u00EAncia: idField -->\n @if (idFieldDiverges) { <div class=\"alert alert--warning connect-alert\">\n <mat-icon class=\"alert__icon\">warning</mat-icon>\n <div class=\"alert__text connect-alert__text\">\n A chave prim\u00E1ria no servidor diverge da configura\u00E7\u00E3o atual.\n <span class=\"connect-alert__meta\">(config: {{ idField || 'id' }} | servidor: {{ serverIdField || 'id' }})</span>\n </div>\n <button mat-stroked-button color=\"primary\" type=\"button\" (click)=\"onReconcileIdField()\">Reconciliar</button>\n </div> }\n\n <!-- Diverg\u00EAncia: serverHash -->\n @if (schemaHashDiverges) { <div class=\"alert alert--info connect-alert\">\n <mat-icon class=\"alert__icon\">info</mat-icon>\n <div class=\"alert__text connect-alert__text\">\n O schema no servidor foi atualizado desde a \u00FAltima sincroniza\u00E7\u00E3o.\n </div>\n <button mat-stroked-button color=\"primary\" type=\"button\" (click)=\"onAcceptServerHash()\">Atualizar metadados</button>\n </div> }\n </div>\n\n <div *ngSwitchCase=\"'overview'\" class=\"overview-grid\">\n <div class=\"overview-row\">\n <mat-form-field appearance=\"outline\" class=\"hs-field\">\n <mat-label>Scroll Horizontal</mat-label>\n <mat-select [(ngModel)]=\"horizontalScroll\" (ngModelChange)=\"onHorizontalScrollChange($event)\">\n <mat-option value=\"auto\">Auto (padr\u00E3o)</mat-option>\n <mat-option value=\"wrap\">Wrap (quebrar linhas)</mat-option>\n <mat-option value=\"none\">Host controla</mat-option>\n </mat-select>\n </mat-form-field>\n <div class=\"help small\">Controla como a tabela lida com largura horizontal e barra de rolagem.</div>\n </div>\n @if (isEffectiveLocalMode()) { <div class=\"alert alert--info overview-mode-alert\">\n <mat-icon class=\"alert__icon\">info</mat-icon>\n <div class=\"alert__text\">\n Modo local efetivo ativo: estrat\u00E9gias de pagina\u00E7\u00E3o e ordena\u00E7\u00E3o em servidor ficam bloqueadas e s\u00E3o salvas como cliente.\n </div>\n </div> }\n <behavior-config-editor\n [config]=\"editedConfig\"\n [resourcePath]=\"resourcePath\"\n [forceClientStrategies]=\"isEffectiveLocalMode()\"\n (configChange)=\"onBehaviorConfigChange($event)\"\n (behaviorChange)=\"onBehaviorChange($event)\"\n ></behavior-config-editor>\n </div>\n\n <columns-config-editor\n *ngSwitchCase=\"'columns'\"\n [config]=\"editedConfig\"\n (configChange)=\"onColumnsConfigChange($event)\"\n (columnChange)=\"onColumnChange($event)\"\n ></columns-config-editor>\n\n <table-rules-editor\n *ngSwitchCase=\"'rules'\"\n [config]=\"editedConfig\"\n [resourcePath]=\"resourcePath\"\n (configChange)=\"onRulesConfigChange($event)\"\n ></table-rules-editor>\n\n <header-appearance-editor\n *ngSwitchCase=\"'header'\"\n [config]=\"editedConfig\"\n (configChange)=\"onColumnsConfigChange($event)\"\n ></header-appearance-editor>\n\n <toolbar-actions-editor\n *ngSwitchCase=\"'toolbar'\"\n [config]=\"editedConfig\"\n (configChange)=\"onToolbarActionsConfigChange($event)\"\n (toolbarActionsChange)=\"onToolbarActionsChange($event)\"\n ></toolbar-actions-editor>\n\n <!-- Aba extra para integra\u00E7\u00F5es CRUD (vis\u00EDvel quando em contexto CRUD) -->\n <crud-integration-editor\n #crudEditorRef\n *ngSwitchCase=\"'crud'\"\n [tableId]=\"crudContext?.tableId || 'default'\"\n [crudContext]=\"crudContext\"\n [componentKeyId]=\"crudContext?.componentKeyId\"\n ></crud-integration-editor>\n\n <filter-settings\n #tableFilterSettingsRef\n *ngSwitchCase=\"'filters'\"\n [metadata]=\"getFilterSettingsMetas()\"\n [metadataSource]=\"isUsingFilterDtoMetas() ? 'filter-dto' : 'columns'\"\n [metadataLoading]=\"filterDtoMetasLoading\"\n [metadataErrorMsg]=\"filterDtoMetasErrorMsg\"\n [settings]=\"\n editedConfig.behavior?.filtering?.advancedFilters?.settings\n \"\n (settingsChange)=\"onFilterSettingsChange($event)\"\n ></filter-settings>\n\n <messages-localization-editor\n *ngSwitchCase=\"'messages'\"\n [config]=\"editedConfig\"\n (configChange)=\"onMessagesLocalizationConfigChange($event)\"\n (messagesLocalizationChange)=\"\n onMessagesLocalizationChange($event)\n \"\n ></messages-localization-editor>\n\n <confirm-dialog-appearance-editor\n *ngSwitchCase=\"'dialogs'\"\n [config]=\"editedConfig\"\n (configChange)=\"onJsonConfigChange($event)\"\n ></confirm-dialog-appearance-editor>\n\n\n <json-config-editor\n *ngSwitchCase=\"'json'\"\n [config]=\"editedConfig\"\n (configChange)=\"onJsonConfigChange($event)\"\n (editorEvent)=\"onJsonEditorEvent($event)\"\n ></json-config-editor>\n </ng-container>\n </div>\n </mat-tab>\n </mat-tab-group>\n@if (statusMessage) { <div class=\"config-editor-status\">\n <span\n class=\"status-text\"\n [class.error]=\"hasErrors\"\n [class.success]=\"hasSuccess\"\n >{{ statusMessage }}</span\n >\n </div> }\n", styles: ["@charset \"UTF-8\";.config-tabs{flex:1 1 auto;display:flex;flex-direction:column}.config-tabs .mat-mdc-tab{min-width:120px}.config-tabs .mat-mdc-tab-body-wrapper,.config-tabs .mat-mdc-tab-group-container{flex:1 1 auto;min-height:0}.config-tabs .mat-mdc-tab-body-content{height:100%;min-height:0;overflow:visible}.tab-content{display:flex;flex-direction:column;flex:1 1 auto;min-height:0;padding:8px 8px 56px;box-sizing:border-box;overflow:visible}.overview-grid{display:grid;grid-template-columns:1fr;gap:12px}.overview-grid .overview-row{display:grid;grid-template-columns:280px 1fr;align-items:end;gap:12px}.overview-grid .overview-row .help.small{opacity:.75;font-size:12px}.overview-mode-alert{align-items:center}.connect-grid{display:grid;gap:12px;padding:8px;grid-template-columns:1fr 240px;align-items:start}.connect-note{grid-column:1/-1;margin:0;font-size:12px;color:var(--md-sys-color-on-surface-variant)}.connect-alert{grid-column:1/-1;align-items:center}.connect-alert__text{flex:1}.connect-alert__meta{opacity:.85}.educational-card{margin-bottom:24px;background:var(--md-sys-color-surface-container-low);border-left:4px solid var(--md-sys-color-primary);flex-shrink:0}.config-editor-status{padding:12px 16px;margin-top:auto;border-top:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container);flex-shrink:0;position:relative}.status-text{font-size:.875rem;line-height:1.2}.status-text.error{color:var(--md-sys-color-error)}.status-text.success{color:var(--md-sys-color-primary)}@media(max-width:768px){.tab-content{padding:8px}.config-editor-status{padding:12px 16px}.connect-grid{grid-template-columns:1fr}.overview-grid .overview-row{grid-template-columns:1fr;align-items:start}:host{display:flex;flex-direction:column;flex:1 1 auto;min-height:0}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$2.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i1$2.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i5.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatTabsModule }, { kind: "directive", type: i4.MatTabLabel, selector: "[mat-tab-label], [matTabLabel]" }, { kind: "component", type: i4.MatTab, selector: "mat-tab", inputs: ["disabled", "label", "aria-label", "aria-labelledby", "labelClass", "bodyClass", "id"], exportAs: ["matTab"] }, { kind: "component", type: i4.MatTabGroup, selector: "mat-tab-group", inputs: ["color", "fitInkBarToContent", "mat-stretch-tabs", "mat-align-tabs", "dynamicHeight", "selectedIndex", "headerPosition", "animationDuration", "contentTabIndex", "disablePagination", "disableRipple", "preserveContent", "backgroundColor", "aria-label", "aria-labelledby"], outputs: ["selectedIndexChange", "focusChange", "animationDone", "selectedTabChange"], exportAs: ["matTabGroup"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i6.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i6.MatLabel, selector: "mat-label" }, { kind: "directive", type: i6.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i7.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: i5$2.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: i5$2.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }, { kind: "component", type: JsonConfigEditorComponent, selector: "json-config-editor", inputs: ["config"], outputs: ["configChange", "validationChange", "editorEvent"] }, { kind: "component", type: ColumnsConfigEditorComponent, selector: "columns-config-editor", inputs: ["config"], outputs: ["configChange", "columnChange"] }, { kind: "component", type: BehaviorConfigEditorComponent, selector: "behavior-config-editor", inputs: ["config", "resourcePath", "forceClientStrategies"], outputs: ["configChange", "behaviorChange"] }, { kind: "component", type: HeaderAppearanceEditorComponent, selector: "header-appearance-editor", inputs: ["config"], outputs: ["configChange"] }, { kind: "component", type: ToolbarActionsEditorComponent, selector: "toolbar-actions-editor", inputs: ["config"], outputs: ["configChange", "toolbarActionsChange"] }, { kind: "component", type: MessagesLocalizationEditorComponent, selector: "messages-localization-editor", inputs: ["config"], outputs: ["configChange", "messagesLocalizationChange"] }, { kind: "component", type: FilterSettingsComponent, selector: "filter-settings", inputs: ["metadata", "metadataSource", "metadataLoading", "metadataErrorMsg", "settings", "configKey"], outputs: ["settingsChange"] }, { kind: "component", type: CrudIntegrationEditorComponent, selector: "crud-integration-editor", inputs: ["tableId", "crudContext", "componentKeyId"] }, { kind: "component", type: ConfirmDialogAppearanceEditorComponent, selector: "confirm-dialog-appearance-editor", inputs: ["config"], outputs: ["configChange"] }, { kind: "component", type: TableRulesEditorComponent, selector: "table-rules-editor", inputs: ["config", "resourcePath", "fields", "i18nRules", "dslFunctionRegistry", "debugLogs", "debugLevel"], outputs: ["configChange"] }] });
29280
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.17", type: PraxisTableConfigEditor, isStandalone: true, selector: "praxis-table-config-editor", providers: [TableConfigService], viewQueries: [{ propertyName: "filterSettingsEditor", first: true, predicate: ["tableFilterSettingsRef"], descendants: true }, { propertyName: "behaviorEditor", first: true, predicate: BehaviorConfigEditorComponent, descendants: true }, { propertyName: "crudEditorSetter", first: true, predicate: ["crudEditorRef"], descendants: true }], ngImport: i0, template: " <mat-tab-group class=\"config-tabs\" [(selectedIndex)]=\"activeSectionIndex\">\n <mat-tab *ngFor=\"let section of sections\">\n <ng-template mat-tab-label>\n @if (section.icon) { <mat-icon [praxisIcon]=\"section.icon\"></mat-icon> }\n <span [attr.data-testid]=\"'config-tab-' + section.id\">{{ section.label }}</span>\n </ng-template>\n <div class=\"tab-content\">\n <ng-container [ngSwitch]=\"section.id\">\n <div *ngSwitchCase=\"'connect'\" class=\"connect-grid\">\n <mat-form-field appearance=\"outline\">\n <mat-label>Recurso</mat-label>\n <input matInput [(ngModel)]=\"resourcePath\" (ngModelChange)=\"onResourcePathChange($event)\" placeholder=\"ex.: employees\" />\n <mat-icon matSuffix>link</mat-icon>\n </mat-form-field>\n <mat-form-field appearance=\"outline\">\n <mat-label>Chave prim\u00E1ria</mat-label>\n <input matInput [(ngModel)]=\"idField\" (ngModelChange)=\"onIdFieldChange($event)\" placeholder=\"ex.: id, uuid, codigo\" />\n <mat-icon matSuffix>fingerprint</mat-icon>\n </mat-form-field>\n <p class=\"connect-note\">Defina o recurso da API e, se necess\u00E1rio, a chave prim\u00E1ria.</p>\n\n <!-- Diverg\u00EAncia: idField -->\n @if (idFieldDiverges) { <div class=\"alert alert--warning connect-alert\">\n <mat-icon class=\"alert__icon\">warning</mat-icon>\n <div class=\"alert__text connect-alert__text\">\n A chave prim\u00E1ria no servidor diverge da configura\u00E7\u00E3o atual.\n <span class=\"connect-alert__meta\">(config: {{ idField || 'id' }} | servidor: {{ serverIdField || 'id' }})</span>\n </div>\n <button mat-stroked-button color=\"primary\" type=\"button\" (click)=\"onReconcileIdField()\">Reconciliar</button>\n </div> }\n\n <!-- Diverg\u00EAncia: serverHash -->\n @if (schemaHashDiverges) { <div class=\"alert alert--info connect-alert\">\n <mat-icon class=\"alert__icon\">info</mat-icon>\n <div class=\"alert__text connect-alert__text\">\n O schema no servidor foi atualizado desde a \u00FAltima sincroniza\u00E7\u00E3o.\n </div>\n <button mat-stroked-button color=\"primary\" type=\"button\" (click)=\"onAcceptServerHash()\">Atualizar metadados</button>\n </div> }\n </div>\n\n <div *ngSwitchCase=\"'overview'\" class=\"overview-grid\">\n <div class=\"overview-row\">\n <mat-form-field appearance=\"outline\" class=\"hs-field\">\n <mat-label>Scroll Horizontal</mat-label>\n <mat-select [(ngModel)]=\"horizontalScroll\" (ngModelChange)=\"onHorizontalScrollChange($event)\">\n <mat-option value=\"auto\">Auto (padr\u00E3o)</mat-option>\n <mat-option value=\"wrap\">Wrap (quebrar linhas)</mat-option>\n <mat-option value=\"none\">Host controla</mat-option>\n </mat-select>\n </mat-form-field>\n <div class=\"help small\">Controla como a tabela lida com largura horizontal e barra de rolagem.</div>\n </div>\n @if (isEffectiveLocalMode()) { <div class=\"alert alert--info overview-mode-alert\">\n <mat-icon class=\"alert__icon\">info</mat-icon>\n <div class=\"alert__text\">\n Modo local efetivo ativo: estrat\u00E9gias de pagina\u00E7\u00E3o e ordena\u00E7\u00E3o em servidor ficam bloqueadas e s\u00E3o salvas como cliente.\n </div>\n </div> }\n <behavior-config-editor\n [config]=\"editedConfig\"\n [resourcePath]=\"resourcePath\"\n [forceClientStrategies]=\"isEffectiveLocalMode()\"\n (configChange)=\"onBehaviorConfigChange($event)\"\n (behaviorChange)=\"onBehaviorChange($event)\"\n ></behavior-config-editor>\n </div>\n\n <columns-config-editor\n *ngSwitchCase=\"'columns'\"\n [config]=\"editedConfig\"\n (configChange)=\"onColumnsConfigChange($event)\"\n (columnChange)=\"onColumnChange($event)\"\n ></columns-config-editor>\n\n <table-rules-editor\n *ngSwitchCase=\"'rules'\"\n [config]=\"editedConfig\"\n [resourcePath]=\"resourcePath\"\n (configChange)=\"onRulesConfigChange($event)\"\n ></table-rules-editor>\n\n <header-appearance-editor\n *ngSwitchCase=\"'header'\"\n [config]=\"editedConfig\"\n (configChange)=\"onColumnsConfigChange($event)\"\n ></header-appearance-editor>\n\n <toolbar-actions-editor\n *ngSwitchCase=\"'toolbar'\"\n [config]=\"editedConfig\"\n (configChange)=\"onToolbarActionsConfigChange($event)\"\n (toolbarActionsChange)=\"onToolbarActionsChange($event)\"\n ></toolbar-actions-editor>\n\n <!-- Aba extra para integra\u00E7\u00F5es CRUD (vis\u00EDvel quando em contexto CRUD) -->\n <crud-integration-editor\n #crudEditorRef\n *ngSwitchCase=\"'crud'\"\n [tableId]=\"crudContext?.tableId || 'default'\"\n [crudContext]=\"crudContext\"\n [componentKeyId]=\"crudContext?.componentKeyId\"\n ></crud-integration-editor>\n\n <filter-settings\n #tableFilterSettingsRef\n *ngSwitchCase=\"'filters'\"\n [metadata]=\"getFilterSettingsMetas()\"\n [metadataSource]=\"isUsingFilterDtoMetas() ? 'filter-dto' : 'columns'\"\n [metadataLoading]=\"filterDtoMetasLoading\"\n [metadataErrorMsg]=\"filterDtoMetasErrorMsg\"\n [settings]=\"\n editedConfig.behavior?.filtering?.advancedFilters?.settings\n \"\n (settingsChange)=\"onFilterSettingsChange($event)\"\n ></filter-settings>\n\n <messages-localization-editor\n *ngSwitchCase=\"'messages'\"\n [config]=\"editedConfig\"\n (configChange)=\"onMessagesLocalizationConfigChange($event)\"\n (messagesLocalizationChange)=\"\n onMessagesLocalizationChange($event)\n \"\n ></messages-localization-editor>\n\n <confirm-dialog-appearance-editor\n *ngSwitchCase=\"'dialogs'\"\n [config]=\"editedConfig\"\n (configChange)=\"onJsonConfigChange($event)\"\n ></confirm-dialog-appearance-editor>\n\n\n <json-config-editor\n *ngSwitchCase=\"'json'\"\n [config]=\"editedConfig\"\n (configChange)=\"onJsonConfigChange($event)\"\n (editorEvent)=\"onJsonEditorEvent($event)\"\n ></json-config-editor>\n </ng-container>\n </div>\n </mat-tab>\n </mat-tab-group>\n@if (statusMessage) { <div class=\"config-editor-status\">\n <span\n class=\"status-text\"\n [class.error]=\"hasErrors\"\n [class.success]=\"hasSuccess\"\n >{{ statusMessage }}</span\n >\n </div> }\n", styles: ["@charset \"UTF-8\";.config-tabs{flex:1 1 auto;display:flex;flex-direction:column}.config-tabs .mat-mdc-tab{min-width:120px}.config-tabs .mat-mdc-tab-body-wrapper,.config-tabs .mat-mdc-tab-group-container{flex:1 1 auto;min-height:0}.config-tabs .mat-mdc-tab-body-content{height:100%;min-height:0;overflow:visible}.tab-content{display:flex;flex-direction:column;flex:1 1 auto;min-height:0;padding:8px 8px 56px;box-sizing:border-box;overflow:visible}.overview-grid{display:grid;grid-template-columns:1fr;gap:12px}.overview-grid .overview-row{display:grid;grid-template-columns:280px 1fr;align-items:end;gap:12px}.overview-grid .overview-row .help.small{opacity:.75;font-size:12px}.overview-mode-alert{align-items:center}.connect-grid{display:grid;gap:12px;padding:8px;grid-template-columns:1fr 240px;align-items:start}.connect-note{grid-column:1/-1;margin:0;font-size:12px;color:var(--md-sys-color-on-surface-variant)}.connect-alert{grid-column:1/-1;align-items:center}.connect-alert__text{flex:1}.connect-alert__meta{opacity:.85}.educational-card{margin-bottom:24px;background:var(--md-sys-color-surface-container-low);border-left:4px solid var(--md-sys-color-primary);flex-shrink:0}.config-editor-status{padding:12px 16px;margin-top:auto;border-top:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container);flex-shrink:0;position:relative}.status-text{font-size:.875rem;line-height:1.2}.status-text.error{color:var(--md-sys-color-error)}.status-text.success{color:var(--md-sys-color-primary)}@media(max-width:768px){.tab-content{padding:8px}.config-editor-status{padding:12px 16px}.connect-grid{grid-template-columns:1fr}.overview-grid .overview-row{grid-template-columns:1fr;align-items:start}:host{display:flex;flex-direction:column;flex:1 1 auto;min-height:0}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$2.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i1$2.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i5.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatTabsModule }, { kind: "directive", type: i4.MatTabLabel, selector: "[mat-tab-label], [matTabLabel]" }, { kind: "component", type: i4.MatTab, selector: "mat-tab", inputs: ["disabled", "label", "aria-label", "aria-labelledby", "labelClass", "bodyClass", "id"], exportAs: ["matTab"] }, { kind: "component", type: i4.MatTabGroup, selector: "mat-tab-group", inputs: ["color", "fitInkBarToContent", "mat-stretch-tabs", "mat-align-tabs", "dynamicHeight", "selectedIndex", "headerPosition", "animationDuration", "contentTabIndex", "disablePagination", "disableRipple", "preserveContent", "backgroundColor", "aria-label", "aria-labelledby"], outputs: ["selectedIndexChange", "focusChange", "animationDone", "selectedTabChange"], exportAs: ["matTabGroup"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i6.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i6.MatLabel, selector: "mat-label" }, { kind: "directive", type: i6.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i7.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: i5$1.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: i5$1.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }, { kind: "component", type: JsonConfigEditorComponent, selector: "json-config-editor", inputs: ["config"], outputs: ["configChange", "validationChange", "editorEvent"] }, { kind: "component", type: ColumnsConfigEditorComponent, selector: "columns-config-editor", inputs: ["config"], outputs: ["configChange", "columnChange"] }, { kind: "component", type: BehaviorConfigEditorComponent, selector: "behavior-config-editor", inputs: ["config", "resourcePath", "forceClientStrategies"], outputs: ["configChange", "behaviorChange"] }, { kind: "component", type: HeaderAppearanceEditorComponent, selector: "header-appearance-editor", inputs: ["config"], outputs: ["configChange"] }, { kind: "component", type: ToolbarActionsEditorComponent, selector: "toolbar-actions-editor", inputs: ["config"], outputs: ["configChange", "toolbarActionsChange"] }, { kind: "component", type: MessagesLocalizationEditorComponent, selector: "messages-localization-editor", inputs: ["config"], outputs: ["configChange", "messagesLocalizationChange"] }, { kind: "component", type: FilterSettingsComponent, selector: "filter-settings", inputs: ["metadata", "metadataSource", "metadataLoading", "metadataErrorMsg", "settings", "configKey"], outputs: ["settingsChange"] }, { kind: "component", type: CrudIntegrationEditorComponent, selector: "crud-integration-editor", inputs: ["tableId", "crudContext", "componentKeyId"] }, { kind: "component", type: ConfirmDialogAppearanceEditorComponent, selector: "confirm-dialog-appearance-editor", inputs: ["config"], outputs: ["configChange"] }, { kind: "component", type: TableRulesEditorComponent, selector: "table-rules-editor", inputs: ["config", "resourcePath", "fields", "i18nRules", "dslFunctionRegistry", "debugLogs", "debugLevel"], outputs: ["configChange"] }] });
28800
29281
  }
28801
29282
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: PraxisTableConfigEditor, decorators: [{
28802
29283
  type: Component,
@@ -32312,7 +32793,7 @@ class PraxisFilter {
32312
32793
  }
32313
32794
  }
32314
32795
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: PraxisFilter, deps: [{ token: i1.GenericCrudService }, { token: ASYNC_CONFIG_STORAGE }, { token: i0.DestroyRef }, { token: FilterConfigService }, { token: i3$1.SettingsPanelService }, { token: i2$1.MatSnackBar }, { token: i1$3.MatDialog }, { token: i0.ChangeDetectorRef }, { token: i0.NgZone }, { token: i1.DynamicFormService }, { token: i1.SchemaNormalizerService }, { token: i1.ComponentKeyService }, { token: i6$2.ActivatedRoute, optional: true }, { token: i1.LoggerService, optional: true }], target: i0.ɵɵFactoryTarget.Component });
32315
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.17", type: PraxisFilter, isStandalone: true, selector: "praxis-filter", inputs: { resourcePath: "resourcePath", fieldMetadata: "fieldMetadata", filterId: "filterId", formId: "formId", componentInstanceId: "componentInstanceId", mode: "mode", notifyIfOutdated: "notifyIfOutdated", snoozeMs: "snoozeMs", autoOpenSettingsOnOutdated: "autoOpenSettingsOnOutdated", editModeEnabled: "editModeEnabled", value: "value", alwaysVisibleFields: "alwaysVisibleFields", alwaysVisibleFieldMetadataOverrides: "alwaysVisibleFieldMetadataOverrides", selectedFieldIds: "selectedFieldIds", tags: "tags", allowSaveTags: "allowSaveTags", persistenceKey: "persistenceKey", i18n: "i18n", changeDebounceMs: "changeDebounceMs", showFilterSettings: "showFilterSettings", confirmTagDelete: "confirmTagDelete", placeBooleansInActions: "placeBooleansInActions", showToggleLabels: "showToggleLabels", useInlineSelectVariant: "useInlineSelectVariant", useInlineSearchableSelectVariant: "useInlineSearchableSelectVariant", useInlineMultiSelectVariant: "useInlineMultiSelectVariant", useInlineInputVariant: "useInlineInputVariant", useInlineToggleVariant: "useInlineToggleVariant", useInlineRangeVariant: "useInlineRangeVariant", useInlineDateVariant: "useInlineDateVariant", useInlineDateRangeVariant: "useInlineDateRangeVariant", useInlineTimeVariant: "useInlineTimeVariant", useInlineTimeRangeVariant: "useInlineTimeRangeVariant", useInlineTreeSelectVariant: "useInlineTreeSelectVariant", alwaysMinWidth: "alwaysMinWidth", alwaysColsMd: "alwaysColsMd", alwaysColsLg: "alwaysColsLg", tagColor: "tagColor", tagVariant: "tagVariant", tagButtonColor: "tagButtonColor", actionsButtonColor: "actionsButtonColor", actionsVariant: "actionsVariant", overlayVariant: "overlayVariant", overlayBackdrop: "overlayBackdrop", advancedOpenMode: "advancedOpenMode", advancedClearButtonsEnabled: "advancedClearButtonsEnabled" }, outputs: { submit: "submit", change: "change", clear: "clear", modeChange: "modeChange", requestSearch: "requestSearch", tagsChange: "tagsChange", selectedFieldIdsChange: "selectedFieldIdsChange", metaChanged: "metaChanged", schemaStatusChange: "schemaStatusChange" }, host: { listeners: { "window:resize": "onWindowResize()", "document:keydown": "onGlobalKeydown($event)" }, properties: { "style.--pfx-always-min": "alwaysMinWidth + \"px\"", "style.--pfx-always-cols-md": "alwaysColsMd", "style.--pfx-always-cols-lg": "alwaysColsLg" } }, viewQueries: [{ propertyName: "anchorRef", first: true, predicate: ["anchorRef"], descendants: true, read: CdkOverlayOrigin }, { propertyName: "addAnchor", first: true, predicate: ["addAnchor"], descendants: true, read: CdkOverlayOrigin }, { propertyName: "advancedButton", first: true, predicate: ["advancedButton"], descendants: true, read: ElementRef }], usesOnChanges: true, ngImport: i0, template: "<mat-progress-bar *ngIf=\"saving\" mode=\"indeterminate\"></mat-progress-bar>\n<div class=\"schema-error-banner\" *ngIf=\"schemaError\" role=\"alert\" aria-live=\"polite\">\n <mat-icon [praxisIcon]=\"'error_outline'\" aria-hidden=\"true\"></mat-icon>\n <span class=\"schema-error-message\">{{ i18nLabels.errorLoadingFilters || 'Erro ao carregar filtros.' }}</span>\n <button\n mat-stroked-button\n class=\"schema-error-retry\"\n type=\"button\"\n (click)=\"retrySchemaLoad()\"\n [attr.aria-label]=\"i18nLabels.retry || 'Tentar novamente'\"\n >\n {{ i18nLabels.retry || 'Tentar novamente' }}\n </button>\n</div>\n\n<form class=\"praxis-filter-bar\" [class.is-open]=\"advancedOpen\"\n [class.has-compact]=\"compactSelectedMetas.length || compactAlwaysVisibleMetas.length\"\n (submit)=\"onSubmit(); $event.preventDefault()\">\n <div class=\"inline-actions\" [class.actions-outlined]=\"actionsVariant==='outlined'\">\n <div class=\"actions-anchor\" #anchorRef=\"cdkOverlayOrigin\" cdkOverlayOrigin></div>\n <div class=\"inline-toggles\" *ngIf=\"toggleMetas.length\">\n <ng-container dynamicFieldLoader [fields]=\"toggleMetas\" [formGroup]=\"alwaysForm\"\n (componentsCreated)=\"onToggleComponents($event)\"></ng-container>\n </div>\n\n <div class=\"action-cluster action-cluster--query\">\n <button mat-icon-button class=\"cluster-btn\" [color]=\"actionsButtonColor==='basic'? null : actionsButtonColor\" type=\"button\"\n (click)=\"onSubmit()\" [attr.aria-label]=\"i18nLabels.apply\">\n <mat-icon [praxisIcon]=\"'search'\"></mat-icon>\n </button>\n <button #advancedButton mat-icon-button class=\"cluster-btn\" [color]=\"actionsButtonColor==='basic'? null : actionsButtonColor\" type=\"button\"\n [matBadge]=\"activeFiltersCount\" [matBadgeHidden]=\"!activeFiltersCount\" matBadgeSize=\"small\"\n matBadgeColor=\"primary\" [matBadgeOverlap]=\"false\" (click)=\"toggleAdvanced()\"\n [attr.aria-label]=\"getAdvancedAriaLabel()\" [attr.aria-expanded]=\"advancedOpen\"\n [attr.aria-controls]=\"advancedPanelId\">\n <mat-icon [praxisIcon]=\"'filter_alt'\"></mat-icon>\n </button>\n </div>\n\n <div class=\"action-cluster action-cluster--manage\">\n <mat-select #addSelect multiple panelClass=\"praxis-add-select-panel\" panelWidth=\"min(340px, calc(100vw - 24px))\" [value]=\"selectedFieldIds\"\n [aria-label]=\"getAddAriaLabel()\" (openedChange)=\"onAddOpened($event)\"\n (selectionChange)=\"onAddSelectionChange(addSelect.value)\">\n <mat-select-trigger>\n <span class=\"add-trigger\" [matBadge]=\"selectedFieldIds.length || 0\"\n [matBadgeHidden]=\"!(selectedFieldIds.length)\" matBadgeSize=\"small\" matBadgeColor=\"primary\"\n [matBadgeOverlap]=\"false\">\n <mat-icon>add</mat-icon>\n <span class=\"add-trigger-label\">{{ getAddTriggerLabel() }}</span>\n </span>\n </mat-select-trigger>\n <mat-option disabled class=\"add-search\">\n <mat-form-field appearance=\"outline\" subscriptSizing=\"dynamic\">\n <mat-label>{{ i18nLabels.filtersSearch || i18nLabels.searchPlaceholder }}</mat-label>\n <input matInput (input)=\"onAddQuery(($any($event.target)).value)\" />\n </mat-form-field>\n </mat-option>\n <mat-option class=\"add-select-all\" (click)=\"toggleSelectAll()\"\n [class.partial]=\"isSomeSelected() && !isAllSelected()\">\n {{ i18nLabels.selectAll || 'Selecionar todos' }}<span class=\"select-all-partial\" *ngIf=\"isSomeSelected() && !isAllSelected()\">\n {{ i18nLabels.selectAllPartial || '(parcial)' }}</span>\n </mat-option>\n <mat-option *ngFor=\"let it of addItems; trackBy: trackById\" [value]=\"it.id\">\n {{ it.label }}\n </mat-option>\n </mat-select>\n\n <button mat-icon-button class=\"cluster-btn separator-before\" [color]=\"actionsButtonColor==='basic'? null : actionsButtonColor\"\n type=\"button\" (click)=\"openSettings()\" *ngIf=\"showFilterSettings\" [matBadge]=\"schemaOutdated ? '!' : ''\"\n [matBadgeHidden]=\"!schemaOutdated\" matBadgeColor=\"warn\" matBadgeSize=\"small\" matBadgePosition=\"above after\"\n [matTooltip]=\"schemaOutdated ? 'Schema do servidor mudou \u2014 Reconciliar' : i18nLabels.settings\"\n matTooltipPosition=\"below\" [attr.aria-label]=\"getSettingsAriaLabel()\">\n <mat-icon [praxisIcon]=\"'settings'\"></mat-icon>\n </button>\n </div>\n\n <span class=\"sr-only\" aria-live=\"polite\">{{ getAddAriaLabel() }}</span>\n </div>\n\n <div class=\"compact-fields\" *ngIf=\"compactSelectedMetas.length || compactAlwaysVisibleMetas.length\">\n <ng-container *ngIf=\"compactSelectedMetas.length\" dynamicFieldLoader [fields]=\"compactSelectedMetas\"\n [formGroup]=\"alwaysForm\" (componentsCreated)=\"onSelectedComponents($event)\"></ng-container>\n <ng-container *ngIf=\"compactAlwaysVisibleMetas.length\" dynamicFieldLoader [fields]=\"compactAlwaysVisibleMetas\"\n [formGroup]=\"alwaysForm\" (componentsCreated)=\"onAlwaysComponents($event)\"></ng-container>\n </div>\n\n <div class=\"fields-grid\" *ngIf=\"gridSelectedMetas.length || gridAlwaysVisibleMetas.length\">\n <ng-container *ngIf=\"gridSelectedMetas.length\" dynamicFieldLoader [fields]=\"gridSelectedMetas\" [formGroup]=\"alwaysForm\"\n (componentsCreated)=\"onSelectedComponents($event)\"></ng-container>\n <ng-container *ngIf=\"gridAlwaysVisibleMetas.length\" dynamicFieldLoader [fields]=\"gridAlwaysVisibleMetas\"\n [formGroup]=\"alwaysForm\" (componentsCreated)=\"onAlwaysComponents($event)\"></ng-container>\n </div>\n\n <span class=\"sr-only\" aria-live=\"polite\">\n {{ activeFiltersCount ? (activeFiltersCount + ' filtros ativos') : '' }}\n </span>\n <button type=\"submit\" class=\"hidden-submit\" aria-hidden=\"true\" tabindex=\"-1\"></button>\n</form>\n\n<div class=\"praxis-filter-tags\" *ngIf=\"displayedTags.length\" [class.outlined]=\"tagVariant==='outlined'\">\n <mat-chip-set [attr.aria-label]=\"i18nLabels.shortcutsLabel || 'Atalhos'\">\n <mat-chip *ngFor=\"let tag of displayedTags\" [class.active]=\"isActiveTag(tag)\"\n [color]=\"tagVariant === 'outlined' ? null : (isActiveTag(tag) ? 'accent' : (tagColor === 'basic' ? null : tagColor))\"\n [highlighted]=\"tagVariant === 'filled' && tagColor !== 'basic'\" (click)=\"applyTag(tag)\"\n (keydown.enter)=\"applyTag(tag)\" (keydown.space)=\"applyTag(tag)\" tabindex=\"0\" role=\"button\"\n [attr.aria-pressed]=\"isActiveTag(tag)\">\n <ng-container *ngIf=\"editingTagId !== tag.id; else editChip\">\n <span class=\"chip-leading\" *ngIf=\"isActiveTag(tag)\">\n <mat-icon class=\"leading-check\">check</mat-icon>\n </span>\n <span class=\"chip-label\">{{ tag.label }}</span>\n <span class=\"chip-trailing\" *ngIf=\"isUserTag(tag); else roTag\">\n <button mat-icon-button [color]=\"tagButtonColor === 'basic' ? null : tagButtonColor\"\n [matMenuTriggerFor]=\"tagMenu\" (click)=\"$event.stopPropagation()\" [attr.aria-label]=\"getTagActionsAriaLabel(tag)\">\n <mat-icon>more_vert</mat-icon>\n </button>\n <mat-menu #tagMenu=\"matMenu\" xPosition=\"before\">\n <button mat-menu-item (click)=\"startEditTag(tag, $event)\">\n <mat-icon>edit</mat-icon>\n <span>{{ i18nLabels.renameShortcut }}</span>\n </button>\n <button mat-menu-item (click)=\"deleteTag(tag)\">\n <mat-icon>delete</mat-icon>\n <span>{{ i18nLabels.removeShortcut }}</span>\n </button>\n </mat-menu>\n </span>\n <ng-template #roTag>\n <span class=\"chip-readonly\" [matTooltip]=\"i18nLabels.readonlyShortcut\">\n <mat-icon>lock</mat-icon>\n </span>\n </ng-template>\n </ng-container>\n <ng-template #editChip>\n <input matInput class=\"chip-editor\" [formControl]=\"editingTagLabel\" autofocus\n [matTooltip]=\"'Enter para salvar, Esc para cancelar'\" matTooltipPosition=\"below\"\n (keydown.enter)=\"commitEditTag(tag, $event)\" (keydown.escape)=\"cancelEditTag($event)\"\n (blur)=\"commitEditTag(tag, $event)\" (click)=\"$event.stopPropagation()\" />\n </ng-template>\n </mat-chip>\n </mat-chip-set>\n</div>\n", styles: ["@charset \"UTF-8\";:root{--pfx-filter-h: 38px;--pfx-filter-align-offset: 2px;--pfx-gap-x: 12px;--pfx-gap-y: 8px;--pfx-always-max-desktop: 380px;--pfx-slider-span-desktop: 2;--pfx-advanced-pad-x: 24px;--pfx-field-min: 280px;--pfx-overlay-margin-y: 16px;--pfx-overlay-margin-x: 16px}:host-context(.theme-light){--pfx-surface-border: var(--md-sys-color-outline)}:host{--border-color: var(--md-sys-color-outline-variant);--border-color-hover: var(--md-sys-color-outline);--pfx-overlay-surface: var(--md-sys-color-surface-container);--pfx-overlay-surface-elev: var(--md-sys-color-surface-container-high);--pfx-overlay-surface-variant: var(--md-sys-color-surface-variant);--pfx-overlay-on-surface: var(--md-sys-color-on-surface);--pfx-overlay-on-surface-variant: var(--md-sys-color-on-surface-variant);display:block;width:100%;min-width:0;flex:1 1 auto}.schema-error-banner{display:flex;align-items:center;gap:8px;margin:0 0 8px;padding:8px 10px;border-radius:10px;border:1px solid color-mix(in srgb,var(--md-sys-color-error) 50%,transparent);background:color-mix(in srgb,var(--md-sys-color-error-container) 85%,transparent);color:var(--md-sys-color-on-error-container)}.schema-error-message{min-width:0;flex:1 1 auto;font-size:.8125rem}:host ::ng-deep .schema-error-retry.mat-mdc-outlined-button{--mdc-outlined-button-outline-color: color-mix( in srgb, var(--md-sys-color-error) 55%, var(--md-sys-color-outline) )}.praxis-filter-bar{display:grid;width:100%;grid-template-columns:minmax(0,1fr) auto;column-gap:6px;row-gap:6px;align-items:start}.inline-actions .actions-anchor{width:0;height:0;overflow:hidden}.inline-actions{grid-column:2;grid-row:1;flex:0 0 auto;display:flex;gap:6px;justify-self:end;align-self:start;width:fit-content;white-space:nowrap;height:var(--pfx-filter-h);align-items:center;padding:0 2px}.action-cluster{flex:0 0 auto;display:inline-flex;align-items:center;gap:2px;min-height:36px;padding:2px;border-radius:999px;border:1px solid var(--pfx-surface-border, var(--md-sys-color-outline-variant));background:var(--md-sys-color-surface-container-highest)}.action-cluster--query{border-color:var(--md-sys-color-outline-variant);border-color:color-mix(in srgb,var(--md-sys-color-primary) 35%,var(--md-sys-color-outline-variant));background:var(--md-sys-color-surface-container-high)}:host ::ng-deep .action-cluster .mat-mdc-icon-button,:host ::ng-deep .action-cluster .cluster-btn.mat-mdc-icon-button{width:32px;height:32px;padding:0;--mat-icon-button-state-layer-size: 32px}.inline-actions.actions-outlined button.mat-mdc-icon-button{border:1px solid var(--pfx-surface-border, var(--md-sys-color-outline-variant));border-radius:50%}.inline-actions.actions-outlined .action-cluster button.mat-mdc-icon-button{border-color:transparent}.inline-actions mat-icon{width:20px;height:20px;font-size:20px}.fields-grid{grid-column:1;grid-row:1;display:grid;grid-template-columns:repeat(auto-fit,minmax(var(--pfx-always-min, 220px),1fr));grid-auto-flow:row dense;gap:6px}.compact-fields{display:flex;flex-wrap:wrap;justify-content:flex-start;align-content:flex-start;align-items:center;gap:6px;min-width:0}:host ::ng-deep .compact-fields .pfx-field-shell,:host ::ng-deep .compact-fields .pfx-field-shell-wrapper,:host ::ng-deep .compact-fields .pfx-field-shell-host{--pfx-field-shell-width: fit-content;--pfx-field-shell-field-width: auto;width:fit-content!important;max-width:100%;min-width:0;flex:0 0 auto!important}:host ::ng-deep .compact-fields>.pfx-field-shell,:host ::ng-deep .compact-fields>praxis-field-shell{flex:0 0 auto!important;width:fit-content!important;max-width:100%;min-width:0}:host ::ng-deep .compact-fields .pfx-field-shell .mat-mdc-form-field{width:auto!important;max-width:100%;margin-bottom:0}:host ::ng-deep .compact-fields .pfx-field-shell[data-control-type=filter-date-range-inline] .mat-mdc-form-field{width:var(--pdx-inline-date-range-shell-width, auto)!important;max-width:none!important}.praxis-filter-bar.has-compact .compact-fields{grid-column:1;grid-row:1}.praxis-filter-bar.has-compact .fields-grid{grid-column:1/-1;grid-row:2}:host ::ng-deep .fields-grid .pfx-field-shell[data-control-type=slider] mat-slider,:host ::ng-deep .fields-grid .pfx-field-shell[data-control-type=range-slider] mat-slider,:host ::ng-deep .fields-grid .pfx-field-shell[data-control-type=rangeSlider] mat-slider{width:100%;display:block}:host ::ng-deep .fields-grid .pfx-field-shell[data-control-type=slider] .pdx-slider-wrapper,:host ::ng-deep .fields-grid .pfx-field-shell[data-control-type=range-slider] .pdx-slider-wrapper,:host ::ng-deep .fields-grid .pfx-field-shell[data-control-type=rangeSlider] .pdx-slider-wrapper{padding-top:2px}:host ::ng-deep .fields-grid .pfx-field-shell[data-control-type=range-slider] .pdx-range-slider-container,:host ::ng-deep .fields-grid .pfx-field-shell[data-control-type=rangeSlider] .pdx-range-slider-container{padding:2px 0 0}:host ::ng-deep .fields-grid .pfx-field-shell[data-control-type=range-slider] .pdx-slider-label,:host ::ng-deep .fields-grid .pfx-field-shell[data-control-type=rangeSlider] .pdx-slider-label{margin-bottom:4px;line-height:1.15}:host ::ng-deep .fields-grid .mat-mdc-text-field-wrapper.mdc-text-field--outlined{min-height:var(--pfx-filter-h);align-items:center}:host ::ng-deep .fields-grid .mat-mdc-form-field-infix{min-height:var(--pfx-filter-h)}:host ::ng-deep .fields-grid .mat-mdc-select-trigger{height:var(--pfx-filter-h);align-items:center}:host ::ng-deep .fields-grid .mat-mdc-form-field{width:100%}:host ::ng-deep .fields-grid .pfx-field-shell[data-control-type=filter-select-inline]{justify-self:start}:host ::ng-deep .fields-grid .pfx-field-shell[data-control-type=filter-select-inline] .mat-mdc-form-field{width:auto;min-width:0;max-width:100%}:host ::ng-deep .fields-grid .pfx-field-shell[data-control-type=filter-searchable-select-inline]{justify-self:start}:host ::ng-deep .fields-grid .pfx-field-shell[data-control-type=filter-searchable-select-inline] .mat-mdc-form-field{width:auto;min-width:0;max-width:100%}:host ::ng-deep .fields-grid .pfx-field-shell[data-control-type=filter-multiselect-inline]{justify-self:start}:host ::ng-deep .fields-grid .pfx-field-shell[data-control-type=filter-multiselect-inline] .mat-mdc-form-field{width:auto;min-width:0;max-width:100%}:host ::ng-deep .fields-grid .pfx-field-shell[data-control-type=filter-input-inline]{justify-self:start}:host ::ng-deep .fields-grid .pfx-field-shell[data-control-type=filter-input-inline] .mat-mdc-form-field{width:auto;min-width:0;max-width:100%}:host ::ng-deep .fields-grid .pfx-field-shell[data-control-type=filter-toggle-inline]{justify-self:start}:host ::ng-deep .fields-grid .pfx-field-shell[data-control-type=filter-toggle-inline] .mat-mdc-form-field{width:auto;min-width:0;max-width:100%}:host ::ng-deep .fields-grid .pfx-field-shell[data-control-type=filter-range-inline]{justify-self:start}:host ::ng-deep .compact-fields .pfx-field-shell[data-control-type=filter-range-inline]{max-width:min(340px,100%)}:host ::ng-deep .fields-grid .pfx-field-shell[data-control-type=filter-date-inline]{justify-self:start}:host ::ng-deep .fields-grid .pfx-field-shell[data-control-type=filter-date-inline] .mat-mdc-form-field{width:auto;min-width:0;max-width:100%}:host ::ng-deep .fields-grid .pfx-field-shell[data-control-type=filter-date-range-inline]{justify-self:start}:host ::ng-deep .fields-grid .pfx-field-shell[data-control-type=filter-date-range-inline] .mat-mdc-form-field{width:auto;min-width:0;max-width:100%}:host ::ng-deep .fields-grid .mat-mdc-form-field-subscript-wrapper{min-height:0;margin-top:0}:host ::ng-deep .fields-grid .mat-mdc-form-field{margin-bottom:0}.praxis-filter-tags.outlined .mat-mdc-chip{background:transparent!important;--mat-chip-outline-width: 1px;--mat-chip-outline-color: var(--md-sys-color-outline-variant);box-shadow:inset 0 0 0 var(--mat-chip-outline-width) var(--mat-chip-outline-color)}.praxis-filter-tags.outlined mat-chip.active .mat-mdc-chip,.praxis-filter-tags.outlined .mat-mdc-chip.mat-mdc-chip-highlighted{--mat-chip-outline-color: var(--md-sys-color-primary) !important;box-shadow:inset 0 0 0 var(--mat-chip-outline-width) var(--mat-chip-outline-color)!important}.praxis-filter-tags .mat-mdc-standard-chip .mdc-evolution-chip__text-label{display:flex;align-items:center;justify-content:center;gap:4px;line-height:1.2;font-size:.875rem}.praxis-filter-tags .chip-leading,.praxis-filter-tags .chip-trailing{display:inline-flex;align-items:center}.praxis-filter-tags .leading-check{width:18px;height:18px;font-size:18px;line-height:1}.praxis-filter-tags .chip-label{position:relative;top:-6px}.praxis-filter-tags .chip-trailing .mat-mdc-icon-button{width:28px;height:28px;padding:0;display:flex;align-items:center;justify-content:center;line-height:28px}.praxis-filter-tags .mat-mdc-standard-chip{--mat-chip-container-height: 36px}.praxis-filter-advanced{display:flex;flex-direction:column;min-width:400px;max-width:90vw;min-height:260px;max-height:min(80vh,720px);margin:var(--pfx-overlay-margin-y) var(--pfx-overlay-margin-x);background-color:var(--pfx-overlay-surface)!important;background:var(--pfx-overlay-surface)!important;color:var(--pfx-overlay-on-surface);border:1px solid var(--border-color);border-radius:12px;box-shadow:var(--md-sys-elevation-level3)}.advanced-header{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:14px var(--pfx-advanced-pad-x) 10px;border-bottom:1px solid var(--border-color);background:var(--pfx-overlay-surface)}.advanced-title-block{display:flex;flex-direction:column;gap:2px}.advanced-title{font-size:1rem;font-weight:600;color:var(--pfx-overlay-on-surface)}.advanced-subtitle{font-size:.85rem;color:var(--pfx-overlay-on-surface-variant)}.advanced-close{align-self:flex-start}.praxis-filter-overlay.mobile .praxis-filter-advanced{height:100vh;max-height:100vh;margin:0;border-radius:0}:host ::ng-deep .praxis-overlay-backdrop{background:var(--md-sys-color-scrim);-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px)}:host ::ng-deep .praxis-filter-overlay.frosted .praxis-filter-advanced{background:var(--pfx-overlay-surface-variant)!important;-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);border-color:var(--border-color)}:host ::ng-deep .praxis-filter-overlay.frosted .advanced-header,:host ::ng-deep .praxis-filter-overlay.frosted .advanced-actions{background:var(--pfx-overlay-surface-variant)!important}.advanced-body{padding:12px var(--pfx-advanced-pad-x) 72px;overflow:auto;flex:1 1 auto;overscroll-behavior:contain}:host ::ng-deep .praxis-filter-advanced .praxis-filter-form .filter-row{display:grid!important;grid-template-columns:repeat(auto-fit,minmax(var(--pfx-field-min),1fr));gap:var(--pfx-gap-y) var(--pfx-gap-x)}:host ::ng-deep .praxis-filter-advanced .praxis-filter-form .filter-column{min-width:0}:host ::ng-deep .praxis-filter-advanced .praxis-filter-form .filter-column .mat-mdc-form-field{width:100%}.advanced-actions{position:sticky;bottom:0;z-index:2;display:flex;justify-content:flex-end;gap:8px;padding:var(--pfx-gap-y) var(--pfx-advanced-pad-x);background-color:var(--pfx-overlay-surface)!important;background:var(--pfx-overlay-surface)!important;border-top:1px solid var(--border-color);box-shadow:0 -1px 0 var(--md-sys-color-outline-variant)}.advanced-actions .mat-mdc-button-base{height:40px}.advanced-actions .mat-mdc-raised-button.mat-primary{background:var(--md-sys-color-primary);color:var(--md-sys-color-on-primary)}:host ::ng-deep .praxis-filter-advanced .mat-mdc-text-field-wrapper.mdc-text-field--outlined{--mdc-outlined-text-field-outline-color: var(--border-color);--mdc-outlined-text-field-hover-outline-color: var(--border-color-hover);--mdc-outlined-text-field-focus-outline-color: var(--md-sys-color-primary);--mdc-outlined-text-field-label-text-color: var(--pfx-overlay-on-surface-variant);--mdc-outlined-text-field-input-text-color: var(--pfx-overlay-on-surface);--mdc-outlined-text-field-container-color: var(--pfx-overlay-surface)}:host ::ng-deep .praxis-filter-advanced .mat-mdc-select-trigger,:host ::ng-deep .praxis-filter-advanced .mat-mdc-form-field-subscript-wrapper,:host ::ng-deep .praxis-filter-advanced .mat-mdc-form-field-infix{color:var(--pfx-overlay-on-surface)}@media(min-width:600px){.fields-grid{gap:6px 8px}:host ::ng-deep .praxis-filter-advanced .praxis-filter-form .filter-row{grid-template-columns:repeat(2,minmax(0,1fr))}}@media(min-width:960px){.fields-grid{gap:6px 10px}}@media(min-width:1200px){.fields-grid{grid-template-columns:repeat(auto-fit,minmax(var(--pfx-always-min, 220px),var(--pfx-always-max-desktop, 380px)));justify-content:start;align-content:start}:host ::ng-deep .fields-grid .pfx-field-shell[data-control-type=slider],:host ::ng-deep .fields-grid .pfx-field-shell[data-control-type=range-slider],:host ::ng-deep .fields-grid .pfx-field-shell[data-control-type=rangeSlider],:host ::ng-deep .fields-grid .pfx-field-shell[data-control-type=rangeslider]{grid-column:span var(--pfx-slider-span-desktop, 2)}}.inline-toggles{display:flex;align-items:center;gap:8px;margin:0 4px 0 6px}:host ::ng-deep .inline-actions .mat-mdc-slide-toggle{height:var(--pfx-filter-h);display:flex;align-items:center}:host ::ng-deep .inline-actions .mat-mdc-slide-toggle .mdc-form-field{align-items:center}::ng-deep .praxis-filter-overlay .praxis-filter-advanced .praxis-filter-form .filter-row{display:grid!important;gap:var(--pfx-gap-y, 1px) var(--pfx-gap-x, 6px)}@media(min-width:600px){::ng-deep .praxis-filter-overlay .praxis-filter-advanced .praxis-filter-form .filter-row{grid-template-columns:repeat(2,minmax(0,1fr))}}.sr-only{position:absolute!important;width:1px!important;height:1px!important;margin:-1px!important;overflow:hidden!important;clip:rect(0,0,0,0)!important}.hidden-submit{position:absolute!important;width:0!important;height:0!important;padding:0!important;margin:0!important;border:0!important;opacity:0!important;pointer-events:none!important;clip:rect(0 0 0 0)!important;clip-path:inset(50%)!important;overflow:hidden!important}:host ::ng-deep .inline-actions [matBadge] .mat-badge-content{top:-6px;right:-6px}.praxis-filter-bar :where(.mat-mdc-slide-toggle .mdc-switch__icons){display:none!important}.praxis-filter-bar{--mdc-switch-unselected-icon-size: 0px;--mdc-switch-selected-icon-size: 0px;--pfx-always-min: 220px}.praxis-filter-card{display:flex;flex-direction:column;gap:6px;padding:8px 12px;border-radius:12px;border:1px solid var(--pfx-surface-border, var(--md-sys-color-outline-variant));background:var(--md-sys-color-surface-container);color:var(--md-sys-color-on-surface)}:host ::ng-deep .praxis-add-select-panel{width:min(340px,100vw - 24px)!important;min-width:min(280px,100vw - 24px)!important;max-width:calc(100vw - 24px)!important;max-height:min(56vh,420px);margin-top:8px;padding:6px 0;border-radius:14px;overflow:auto;background:var(--md-sys-color-surface-container-highest);border:1px solid var(--pfx-surface-border, var(--md-sys-color-outline-variant));box-shadow:var(--md-sys-elevation-level3)}:host ::ng-deep .cdk-overlay-pane:has(.praxis-add-select-panel){width:auto!important;min-width:0!important;max-width:calc(100vw - 24px)!important}:host ::ng-deep .praxis-add-select-panel .mat-mdc-option{min-height:36px}:host ::ng-deep .praxis-add-select-panel .add-search{position:sticky;top:0;background:var(--md-sys-color-surface-container-highest);z-index:1;padding:0 8px 6px;cursor:default}:host ::ng-deep .praxis-add-select-panel .add-search .mat-mdc-form-field{width:100%}:host ::ng-deep .praxis-add-select-panel .add-search .mat-mdc-form-field-subscript-wrapper{display:none}.inline-actions .add-trigger{display:inline-flex;align-items:center;gap:6px;height:32px;width:100%;max-width:100%;min-width:0;padding:0 10px;border-radius:0;border:0;background:transparent;overflow:visible}:host ::ng-deep .inline-actions .add-trigger mat-icon{width:18px;height:18px;font-size:18px;flex:0 0 auto}.inline-actions .add-trigger-label{display:inline-block;flex:1 1 auto;min-width:0;max-width:100%;text-align:left;direction:ltr;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:.82rem;line-height:1}:host ::ng-deep .action-cluster--manage .mat-mdc-select{flex:0 0 auto;width:180px;min-width:0;max-width:180px}:host ::ng-deep .action-cluster--manage .mat-mdc-select-trigger{min-height:32px;padding:0}:host ::ng-deep .action-cluster--manage .mat-mdc-select-value,:host ::ng-deep .action-cluster--manage .mat-mdc-select-value-text,:host ::ng-deep .action-cluster--manage .mat-mdc-select-min-line{width:auto;min-width:0;max-width:100%;display:inline-flex;align-items:center;justify-content:flex-start;overflow:visible}.praxis-filter-card .summary-header{display:flex;align-items:center;gap:10px}.praxis-filter-card .summary-avatar{width:32px;height:32px;border-radius:50%;object-fit:cover}.praxis-filter-card .summary-title{font-weight:600}.praxis-filter-card .summary-subtitle{opacity:.8;font-size:.875rem}.praxis-filter-card .summary-badges{display:flex;flex-wrap:wrap;gap:6px}.praxis-filter-card .summary-badges span{display:inline-flex;align-items:center;padding:2px 8px;border-radius:999px;background:var(--md-sys-color-primary-container);border:1px solid var(--md-sys-color-outline-variant);color:var(--md-sys-color-on-primary-container);font-size:12px}.praxis-filter-card .card-actions{display:flex;gap:8px}:host ::ng-deep .inline-actions .mat-mdc-select-arrow-wrapper{display:none}.inline-actions .add-filter-btn{height:36px;border-radius:18px;padding:0 16px 0 12px}.inline-actions .add-filter-btn mat-icon{margin-right:8px;margin-left:-4px}:host ::ng-deep .praxis-add-select-panel .add-select-all.partial .select-all-partial{opacity:.7;font-style:italic}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i6.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i6.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i7.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: MatButtonModule }, { kind: "component", type: i3.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: "component", type: i3.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatChipsModule }, { kind: "component", type: i15.MatChip, selector: "mat-basic-chip, [mat-basic-chip], mat-chip, [mat-chip]", inputs: ["role", "id", "aria-label", "aria-description", "value", "color", "removable", "highlighted", "disableRipple", "disabled"], outputs: ["removed", "destroyed"], exportAs: ["matChip"] }, { kind: "component", type: i15.MatChipSet, selector: "mat-chip-set", inputs: ["disabled", "role", "tabIndex"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i5.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }, { kind: "ngmodule", type: MatBadgeModule }, { kind: "directive", type: i14.MatBadge, selector: "[matBadge]", inputs: ["matBadgeColor", "matBadgeOverlap", "matBadgeDisabled", "matBadgePosition", "matBadge", "matBadgeDescription", "matBadgeSize", "matBadgeHidden"] }, { kind: "ngmodule", type: MatProgressBarModule }, { kind: "component", type: i15$3.MatProgressBar, selector: "mat-progress-bar", inputs: ["color", "value", "bufferValue", "mode"], outputs: ["animationEnd"], exportAs: ["matProgressBar"] }, { kind: "ngmodule", type: MatSnackBarModule }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i10.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i5$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: i5$1.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i5$1.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "directive", type: DynamicFieldLoaderDirective, selector: "[dynamicFieldLoader]", inputs: ["fields", "formGroup", "enableExternalControlBinding", "itemTemplate", "debugTrace", "debugTraceLabel", "readonlyMode", "disabledMode", "presentationMode", "visible", "canvasMode"], outputs: ["componentsCreated", "fieldCreated", "fieldDestroyed", "renderError", "canvasMouseEnter", "canvasMouseLeave", "canvasClick"] }, { kind: "ngmodule", type: OverlayModule }, { kind: "directive", type: i12.CdkOverlayOrigin, selector: "[cdk-overlay-origin], [overlay-origin], [cdkOverlayOrigin]", exportAs: ["cdkOverlayOrigin"] }, { kind: "ngmodule", type: MatDialogModule }, { kind: "ngmodule", type: A11yModule }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i5$2.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: "directive", type: i5$2.MatSelectTrigger, selector: "mat-select-trigger" }, { kind: "component", type: i5$2.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatOptionModule }] });
32796
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.17", type: PraxisFilter, isStandalone: true, selector: "praxis-filter", inputs: { resourcePath: "resourcePath", fieldMetadata: "fieldMetadata", filterId: "filterId", formId: "formId", componentInstanceId: "componentInstanceId", mode: "mode", notifyIfOutdated: "notifyIfOutdated", snoozeMs: "snoozeMs", autoOpenSettingsOnOutdated: "autoOpenSettingsOnOutdated", editModeEnabled: "editModeEnabled", value: "value", alwaysVisibleFields: "alwaysVisibleFields", alwaysVisibleFieldMetadataOverrides: "alwaysVisibleFieldMetadataOverrides", selectedFieldIds: "selectedFieldIds", tags: "tags", allowSaveTags: "allowSaveTags", persistenceKey: "persistenceKey", i18n: "i18n", changeDebounceMs: "changeDebounceMs", showFilterSettings: "showFilterSettings", confirmTagDelete: "confirmTagDelete", placeBooleansInActions: "placeBooleansInActions", showToggleLabels: "showToggleLabels", useInlineSelectVariant: "useInlineSelectVariant", useInlineSearchableSelectVariant: "useInlineSearchableSelectVariant", useInlineMultiSelectVariant: "useInlineMultiSelectVariant", useInlineInputVariant: "useInlineInputVariant", useInlineToggleVariant: "useInlineToggleVariant", useInlineRangeVariant: "useInlineRangeVariant", useInlineDateVariant: "useInlineDateVariant", useInlineDateRangeVariant: "useInlineDateRangeVariant", useInlineTimeVariant: "useInlineTimeVariant", useInlineTimeRangeVariant: "useInlineTimeRangeVariant", useInlineTreeSelectVariant: "useInlineTreeSelectVariant", alwaysMinWidth: "alwaysMinWidth", alwaysColsMd: "alwaysColsMd", alwaysColsLg: "alwaysColsLg", tagColor: "tagColor", tagVariant: "tagVariant", tagButtonColor: "tagButtonColor", actionsButtonColor: "actionsButtonColor", actionsVariant: "actionsVariant", overlayVariant: "overlayVariant", overlayBackdrop: "overlayBackdrop", advancedOpenMode: "advancedOpenMode", advancedClearButtonsEnabled: "advancedClearButtonsEnabled" }, outputs: { submit: "submit", change: "change", clear: "clear", modeChange: "modeChange", requestSearch: "requestSearch", tagsChange: "tagsChange", selectedFieldIdsChange: "selectedFieldIdsChange", metaChanged: "metaChanged", schemaStatusChange: "schemaStatusChange" }, host: { listeners: { "window:resize": "onWindowResize()", "document:keydown": "onGlobalKeydown($event)" }, properties: { "style.--pfx-always-min": "alwaysMinWidth + \"px\"", "style.--pfx-always-cols-md": "alwaysColsMd", "style.--pfx-always-cols-lg": "alwaysColsLg" } }, viewQueries: [{ propertyName: "anchorRef", first: true, predicate: ["anchorRef"], descendants: true, read: CdkOverlayOrigin }, { propertyName: "addAnchor", first: true, predicate: ["addAnchor"], descendants: true, read: CdkOverlayOrigin }, { propertyName: "advancedButton", first: true, predicate: ["advancedButton"], descendants: true, read: ElementRef }], usesOnChanges: true, ngImport: i0, template: "<mat-progress-bar *ngIf=\"saving\" mode=\"indeterminate\"></mat-progress-bar>\n<div class=\"schema-error-banner\" *ngIf=\"schemaError\" role=\"alert\" aria-live=\"polite\">\n <mat-icon [praxisIcon]=\"'error_outline'\" aria-hidden=\"true\"></mat-icon>\n <span class=\"schema-error-message\">{{ i18nLabels.errorLoadingFilters || 'Erro ao carregar filtros.' }}</span>\n <button\n mat-stroked-button\n class=\"schema-error-retry\"\n type=\"button\"\n (click)=\"retrySchemaLoad()\"\n [attr.aria-label]=\"i18nLabels.retry || 'Tentar novamente'\"\n >\n {{ i18nLabels.retry || 'Tentar novamente' }}\n </button>\n</div>\n\n<form class=\"praxis-filter-bar\" [class.is-open]=\"advancedOpen\"\n [class.has-compact]=\"compactSelectedMetas.length || compactAlwaysVisibleMetas.length\"\n (submit)=\"onSubmit(); $event.preventDefault()\">\n <div class=\"inline-actions\" [class.actions-outlined]=\"actionsVariant==='outlined'\">\n <div class=\"actions-anchor\" #anchorRef=\"cdkOverlayOrigin\" cdkOverlayOrigin></div>\n <div class=\"inline-toggles\" *ngIf=\"toggleMetas.length\">\n <ng-container dynamicFieldLoader [fields]=\"toggleMetas\" [formGroup]=\"alwaysForm\"\n (componentsCreated)=\"onToggleComponents($event)\"></ng-container>\n </div>\n\n <div class=\"action-cluster action-cluster--query\">\n <button mat-icon-button class=\"cluster-btn\" [color]=\"actionsButtonColor==='basic'? null : actionsButtonColor\" type=\"button\"\n (click)=\"onSubmit()\" [attr.aria-label]=\"i18nLabels.apply\">\n <mat-icon [praxisIcon]=\"'search'\"></mat-icon>\n </button>\n <button #advancedButton mat-icon-button class=\"cluster-btn\" [color]=\"actionsButtonColor==='basic'? null : actionsButtonColor\" type=\"button\"\n [matBadge]=\"activeFiltersCount\" [matBadgeHidden]=\"!activeFiltersCount\" matBadgeSize=\"small\"\n matBadgeColor=\"primary\" [matBadgeOverlap]=\"false\" (click)=\"toggleAdvanced()\"\n [attr.aria-label]=\"getAdvancedAriaLabel()\" [attr.aria-expanded]=\"advancedOpen\"\n [attr.aria-controls]=\"advancedPanelId\">\n <mat-icon [praxisIcon]=\"'filter_alt'\"></mat-icon>\n </button>\n </div>\n\n <div class=\"action-cluster action-cluster--manage\">\n <mat-select #addSelect multiple panelClass=\"praxis-add-select-panel\" panelWidth=\"min(340px, calc(100vw - 24px))\" [value]=\"selectedFieldIds\"\n [aria-label]=\"getAddAriaLabel()\" (openedChange)=\"onAddOpened($event)\"\n (selectionChange)=\"onAddSelectionChange(addSelect.value)\">\n <mat-select-trigger>\n <span class=\"add-trigger\" [matBadge]=\"selectedFieldIds.length || 0\"\n [matBadgeHidden]=\"!(selectedFieldIds.length)\" matBadgeSize=\"small\" matBadgeColor=\"primary\"\n [matBadgeOverlap]=\"false\">\n <mat-icon>add</mat-icon>\n <span class=\"add-trigger-label\">{{ getAddTriggerLabel() }}</span>\n </span>\n </mat-select-trigger>\n <mat-option disabled class=\"add-search\">\n <mat-form-field appearance=\"outline\" subscriptSizing=\"dynamic\">\n <mat-label>{{ i18nLabels.filtersSearch || i18nLabels.searchPlaceholder }}</mat-label>\n <input matInput (input)=\"onAddQuery(($any($event.target)).value)\" />\n </mat-form-field>\n </mat-option>\n <mat-option class=\"add-select-all\" (click)=\"toggleSelectAll()\"\n [class.partial]=\"isSomeSelected() && !isAllSelected()\">\n {{ i18nLabels.selectAll || 'Selecionar todos' }}<span class=\"select-all-partial\" *ngIf=\"isSomeSelected() && !isAllSelected()\">\n {{ i18nLabels.selectAllPartial || '(parcial)' }}</span>\n </mat-option>\n <mat-option *ngFor=\"let it of addItems; trackBy: trackById\" [value]=\"it.id\">\n {{ it.label }}\n </mat-option>\n </mat-select>\n\n <button mat-icon-button class=\"cluster-btn separator-before\" [color]=\"actionsButtonColor==='basic'? null : actionsButtonColor\"\n type=\"button\" (click)=\"openSettings()\" *ngIf=\"showFilterSettings\" [matBadge]=\"schemaOutdated ? '!' : ''\"\n [matBadgeHidden]=\"!schemaOutdated\" matBadgeColor=\"warn\" matBadgeSize=\"small\" matBadgePosition=\"above after\"\n [matTooltip]=\"schemaOutdated ? 'Schema do servidor mudou \u2014 Reconciliar' : i18nLabels.settings\"\n matTooltipPosition=\"below\" [attr.aria-label]=\"getSettingsAriaLabel()\">\n <mat-icon [praxisIcon]=\"'settings'\"></mat-icon>\n </button>\n </div>\n\n <span class=\"sr-only\" aria-live=\"polite\">{{ getAddAriaLabel() }}</span>\n </div>\n\n <div class=\"compact-fields\" *ngIf=\"compactSelectedMetas.length || compactAlwaysVisibleMetas.length\">\n <ng-container *ngIf=\"compactSelectedMetas.length\" dynamicFieldLoader [fields]=\"compactSelectedMetas\"\n [formGroup]=\"alwaysForm\" (componentsCreated)=\"onSelectedComponents($event)\"></ng-container>\n <ng-container *ngIf=\"compactAlwaysVisibleMetas.length\" dynamicFieldLoader [fields]=\"compactAlwaysVisibleMetas\"\n [formGroup]=\"alwaysForm\" (componentsCreated)=\"onAlwaysComponents($event)\"></ng-container>\n </div>\n\n <div class=\"fields-grid\" *ngIf=\"gridSelectedMetas.length || gridAlwaysVisibleMetas.length\">\n <ng-container *ngIf=\"gridSelectedMetas.length\" dynamicFieldLoader [fields]=\"gridSelectedMetas\" [formGroup]=\"alwaysForm\"\n (componentsCreated)=\"onSelectedComponents($event)\"></ng-container>\n <ng-container *ngIf=\"gridAlwaysVisibleMetas.length\" dynamicFieldLoader [fields]=\"gridAlwaysVisibleMetas\"\n [formGroup]=\"alwaysForm\" (componentsCreated)=\"onAlwaysComponents($event)\"></ng-container>\n </div>\n\n <span class=\"sr-only\" aria-live=\"polite\">\n {{ activeFiltersCount ? (activeFiltersCount + ' filtros ativos') : '' }}\n </span>\n <button type=\"submit\" class=\"hidden-submit\" aria-hidden=\"true\" tabindex=\"-1\"></button>\n</form>\n\n<div class=\"praxis-filter-tags\" *ngIf=\"displayedTags.length\" [class.outlined]=\"tagVariant==='outlined'\">\n <mat-chip-set [attr.aria-label]=\"i18nLabels.shortcutsLabel || 'Atalhos'\">\n <mat-chip *ngFor=\"let tag of displayedTags\" [class.active]=\"isActiveTag(tag)\"\n [color]=\"tagVariant === 'outlined' ? null : (isActiveTag(tag) ? 'accent' : (tagColor === 'basic' ? null : tagColor))\"\n [highlighted]=\"tagVariant === 'filled' && tagColor !== 'basic'\" (click)=\"applyTag(tag)\"\n (keydown.enter)=\"applyTag(tag)\" (keydown.space)=\"applyTag(tag)\" tabindex=\"0\" role=\"button\"\n [attr.aria-pressed]=\"isActiveTag(tag)\">\n <ng-container *ngIf=\"editingTagId !== tag.id; else editChip\">\n <span class=\"chip-leading\" *ngIf=\"isActiveTag(tag)\">\n <mat-icon class=\"leading-check\">check</mat-icon>\n </span>\n <span class=\"chip-label\">{{ tag.label }}</span>\n <span class=\"chip-trailing\" *ngIf=\"isUserTag(tag); else roTag\">\n <button mat-icon-button [color]=\"tagButtonColor === 'basic' ? null : tagButtonColor\"\n [matMenuTriggerFor]=\"tagMenu\" (click)=\"$event.stopPropagation()\" [attr.aria-label]=\"getTagActionsAriaLabel(tag)\">\n <mat-icon>more_vert</mat-icon>\n </button>\n <mat-menu #tagMenu=\"matMenu\" xPosition=\"before\">\n <button mat-menu-item (click)=\"startEditTag(tag, $event)\">\n <mat-icon>edit</mat-icon>\n <span>{{ i18nLabels.renameShortcut }}</span>\n </button>\n <button mat-menu-item (click)=\"deleteTag(tag)\">\n <mat-icon>delete</mat-icon>\n <span>{{ i18nLabels.removeShortcut }}</span>\n </button>\n </mat-menu>\n </span>\n <ng-template #roTag>\n <span class=\"chip-readonly\" [matTooltip]=\"i18nLabels.readonlyShortcut\">\n <mat-icon>lock</mat-icon>\n </span>\n </ng-template>\n </ng-container>\n <ng-template #editChip>\n <input matInput class=\"chip-editor\" [formControl]=\"editingTagLabel\" autofocus\n [matTooltip]=\"'Enter para salvar, Esc para cancelar'\" matTooltipPosition=\"below\"\n (keydown.enter)=\"commitEditTag(tag, $event)\" (keydown.escape)=\"cancelEditTag($event)\"\n (blur)=\"commitEditTag(tag, $event)\" (click)=\"$event.stopPropagation()\" />\n </ng-template>\n </mat-chip>\n </mat-chip-set>\n</div>\n", styles: ["@charset \"UTF-8\";:root{--pfx-filter-h: 38px;--pfx-filter-align-offset: 2px;--pfx-gap-x: 12px;--pfx-gap-y: 8px;--pfx-always-max-desktop: 380px;--pfx-slider-span-desktop: 2;--pfx-advanced-pad-x: 24px;--pfx-field-min: 280px;--pfx-overlay-margin-y: 16px;--pfx-overlay-margin-x: 16px}:host-context(.theme-light){--pfx-surface-border: var(--md-sys-color-outline)}:host{--border-color: var(--md-sys-color-outline-variant);--border-color-hover: var(--md-sys-color-outline);--pfx-overlay-surface: var(--md-sys-color-surface-container);--pfx-overlay-surface-elev: var(--md-sys-color-surface-container-high);--pfx-overlay-surface-variant: var(--md-sys-color-surface-variant);--pfx-overlay-on-surface: var(--md-sys-color-on-surface);--pfx-overlay-on-surface-variant: var(--md-sys-color-on-surface-variant);display:block;width:100%;min-width:0;flex:1 1 auto}.schema-error-banner{display:flex;align-items:center;gap:8px;margin:0 0 8px;padding:8px 10px;border-radius:10px;border:1px solid color-mix(in srgb,var(--md-sys-color-error) 50%,transparent);background:color-mix(in srgb,var(--md-sys-color-error-container) 85%,transparent);color:var(--md-sys-color-on-error-container)}.schema-error-message{min-width:0;flex:1 1 auto;font-size:.8125rem}:host ::ng-deep .schema-error-retry.mat-mdc-outlined-button{--mdc-outlined-button-outline-color: color-mix( in srgb, var(--md-sys-color-error) 55%, var(--md-sys-color-outline) )}.praxis-filter-bar{display:grid;width:100%;grid-template-columns:minmax(0,1fr) auto;column-gap:6px;row-gap:6px;align-items:start}.inline-actions .actions-anchor{width:0;height:0;overflow:hidden}.inline-actions{grid-column:2;grid-row:1;flex:0 0 auto;display:flex;gap:6px;justify-self:end;align-self:start;width:fit-content;white-space:nowrap;height:var(--pfx-filter-h);align-items:center;padding:0 2px}.action-cluster{flex:0 0 auto;display:inline-flex;align-items:center;gap:2px;min-height:36px;padding:2px;border-radius:999px;border:1px solid var(--pfx-surface-border, var(--md-sys-color-outline-variant));background:var(--md-sys-color-surface-container-highest)}.action-cluster--query{border-color:var(--md-sys-color-outline-variant);border-color:color-mix(in srgb,var(--md-sys-color-primary) 35%,var(--md-sys-color-outline-variant));background:var(--md-sys-color-surface-container-high)}:host ::ng-deep .action-cluster .mat-mdc-icon-button,:host ::ng-deep .action-cluster .cluster-btn.mat-mdc-icon-button{width:32px;height:32px;padding:0;--mat-icon-button-state-layer-size: 32px}.inline-actions.actions-outlined button.mat-mdc-icon-button{border:1px solid var(--pfx-surface-border, var(--md-sys-color-outline-variant));border-radius:50%}.inline-actions.actions-outlined .action-cluster button.mat-mdc-icon-button{border-color:transparent}.inline-actions mat-icon{width:20px;height:20px;font-size:20px}.fields-grid{grid-column:1;grid-row:1;display:grid;grid-template-columns:repeat(auto-fit,minmax(var(--pfx-always-min, 220px),1fr));grid-auto-flow:row dense;gap:6px}.compact-fields{display:flex;flex-wrap:wrap;justify-content:flex-start;align-content:flex-start;align-items:center;gap:6px;min-width:0}:host ::ng-deep .compact-fields .pfx-field-shell,:host ::ng-deep .compact-fields .pfx-field-shell-wrapper,:host ::ng-deep .compact-fields .pfx-field-shell-host{--pfx-field-shell-width: fit-content;--pfx-field-shell-field-width: auto;width:fit-content!important;max-width:100%;min-width:0;flex:0 0 auto!important}:host ::ng-deep .compact-fields>.pfx-field-shell,:host ::ng-deep .compact-fields>praxis-field-shell{flex:0 0 auto!important;width:fit-content!important;max-width:100%;min-width:0}:host ::ng-deep .compact-fields .pfx-field-shell .mat-mdc-form-field{width:auto!important;max-width:100%;margin-bottom:0}:host ::ng-deep .compact-fields .pfx-field-shell[data-control-type=filter-date-range-inline] .mat-mdc-form-field{width:var(--pdx-inline-date-range-shell-width, auto)!important;max-width:none!important}.praxis-filter-bar.has-compact .compact-fields{grid-column:1;grid-row:1}.praxis-filter-bar.has-compact .fields-grid{grid-column:1/-1;grid-row:2}:host ::ng-deep .fields-grid .pfx-field-shell[data-control-type=slider] mat-slider,:host ::ng-deep .fields-grid .pfx-field-shell[data-control-type=range-slider] mat-slider,:host ::ng-deep .fields-grid .pfx-field-shell[data-control-type=rangeSlider] mat-slider{width:100%;display:block}:host ::ng-deep .fields-grid .pfx-field-shell[data-control-type=slider] .pdx-slider-wrapper,:host ::ng-deep .fields-grid .pfx-field-shell[data-control-type=range-slider] .pdx-slider-wrapper,:host ::ng-deep .fields-grid .pfx-field-shell[data-control-type=rangeSlider] .pdx-slider-wrapper{padding-top:2px}:host ::ng-deep .fields-grid .pfx-field-shell[data-control-type=range-slider] .pdx-range-slider-container,:host ::ng-deep .fields-grid .pfx-field-shell[data-control-type=rangeSlider] .pdx-range-slider-container{padding:2px 0 0}:host ::ng-deep .fields-grid .pfx-field-shell[data-control-type=range-slider] .pdx-slider-label,:host ::ng-deep .fields-grid .pfx-field-shell[data-control-type=rangeSlider] .pdx-slider-label{margin-bottom:4px;line-height:1.15}:host ::ng-deep .fields-grid .mat-mdc-text-field-wrapper.mdc-text-field--outlined{min-height:var(--pfx-filter-h);align-items:center}:host ::ng-deep .fields-grid .mat-mdc-form-field-infix{min-height:var(--pfx-filter-h)}:host ::ng-deep .fields-grid .mat-mdc-select-trigger{height:var(--pfx-filter-h);align-items:center}:host ::ng-deep .fields-grid .mat-mdc-form-field{width:100%}:host ::ng-deep .fields-grid .pfx-field-shell[data-control-type=filter-select-inline]{justify-self:start}:host ::ng-deep .fields-grid .pfx-field-shell[data-control-type=filter-select-inline] .mat-mdc-form-field{width:auto;min-width:0;max-width:100%}:host ::ng-deep .fields-grid .pfx-field-shell[data-control-type=filter-searchable-select-inline]{justify-self:start}:host ::ng-deep .fields-grid .pfx-field-shell[data-control-type=filter-searchable-select-inline] .mat-mdc-form-field{width:auto;min-width:0;max-width:100%}:host ::ng-deep .fields-grid .pfx-field-shell[data-control-type=filter-multiselect-inline]{justify-self:start}:host ::ng-deep .fields-grid .pfx-field-shell[data-control-type=filter-multiselect-inline] .mat-mdc-form-field{width:auto;min-width:0;max-width:100%}:host ::ng-deep .fields-grid .pfx-field-shell[data-control-type=filter-input-inline]{justify-self:start}:host ::ng-deep .fields-grid .pfx-field-shell[data-control-type=filter-input-inline] .mat-mdc-form-field{width:auto;min-width:0;max-width:100%}:host ::ng-deep .fields-grid .pfx-field-shell[data-control-type=filter-toggle-inline]{justify-self:start}:host ::ng-deep .fields-grid .pfx-field-shell[data-control-type=filter-toggle-inline] .mat-mdc-form-field{width:auto;min-width:0;max-width:100%}:host ::ng-deep .fields-grid .pfx-field-shell[data-control-type=filter-range-inline]{justify-self:start}:host ::ng-deep .compact-fields .pfx-field-shell[data-control-type=filter-range-inline]{max-width:min(340px,100%)}:host ::ng-deep .fields-grid .pfx-field-shell[data-control-type=filter-date-inline]{justify-self:start}:host ::ng-deep .fields-grid .pfx-field-shell[data-control-type=filter-date-inline] .mat-mdc-form-field{width:auto;min-width:0;max-width:100%}:host ::ng-deep .fields-grid .pfx-field-shell[data-control-type=filter-date-range-inline]{justify-self:start}:host ::ng-deep .fields-grid .pfx-field-shell[data-control-type=filter-date-range-inline] .mat-mdc-form-field{width:auto;min-width:0;max-width:100%}:host ::ng-deep .fields-grid .mat-mdc-form-field-subscript-wrapper{min-height:0;margin-top:0}:host ::ng-deep .fields-grid .mat-mdc-form-field{margin-bottom:0}.praxis-filter-tags.outlined .mat-mdc-chip{background:transparent!important;--mat-chip-outline-width: 1px;--mat-chip-outline-color: var(--md-sys-color-outline-variant);box-shadow:inset 0 0 0 var(--mat-chip-outline-width) var(--mat-chip-outline-color)}.praxis-filter-tags.outlined mat-chip.active .mat-mdc-chip,.praxis-filter-tags.outlined .mat-mdc-chip.mat-mdc-chip-highlighted{--mat-chip-outline-color: var(--md-sys-color-primary) !important;box-shadow:inset 0 0 0 var(--mat-chip-outline-width) var(--mat-chip-outline-color)!important}.praxis-filter-tags .mat-mdc-standard-chip .mdc-evolution-chip__text-label{display:flex;align-items:center;justify-content:center;gap:4px;line-height:1.2;font-size:.875rem}.praxis-filter-tags .chip-leading,.praxis-filter-tags .chip-trailing{display:inline-flex;align-items:center}.praxis-filter-tags .leading-check{width:18px;height:18px;font-size:18px;line-height:1}.praxis-filter-tags .chip-label{position:relative;top:-6px}.praxis-filter-tags .chip-trailing .mat-mdc-icon-button{width:28px;height:28px;padding:0;display:flex;align-items:center;justify-content:center;line-height:28px}.praxis-filter-tags .mat-mdc-standard-chip{--mat-chip-container-height: 36px}.praxis-filter-advanced{display:flex;flex-direction:column;min-width:400px;max-width:90vw;min-height:260px;max-height:min(80vh,720px);margin:var(--pfx-overlay-margin-y) var(--pfx-overlay-margin-x);background-color:var(--pfx-overlay-surface)!important;background:var(--pfx-overlay-surface)!important;color:var(--pfx-overlay-on-surface);border:1px solid var(--border-color);border-radius:12px;box-shadow:var(--md-sys-elevation-level3)}.advanced-header{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:14px var(--pfx-advanced-pad-x) 10px;border-bottom:1px solid var(--border-color);background:var(--pfx-overlay-surface)}.advanced-title-block{display:flex;flex-direction:column;gap:2px}.advanced-title{font-size:1rem;font-weight:600;color:var(--pfx-overlay-on-surface)}.advanced-subtitle{font-size:.85rem;color:var(--pfx-overlay-on-surface-variant)}.advanced-close{align-self:flex-start}.praxis-filter-overlay.mobile .praxis-filter-advanced{height:100vh;max-height:100vh;margin:0;border-radius:0}:host ::ng-deep .praxis-overlay-backdrop{background:var(--md-sys-color-scrim);-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px)}:host ::ng-deep .praxis-filter-overlay.frosted .praxis-filter-advanced{background:var(--pfx-overlay-surface-variant)!important;-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);border-color:var(--border-color)}:host ::ng-deep .praxis-filter-overlay.frosted .advanced-header,:host ::ng-deep .praxis-filter-overlay.frosted .advanced-actions{background:var(--pfx-overlay-surface-variant)!important}.advanced-body{padding:12px var(--pfx-advanced-pad-x) 72px;overflow:auto;flex:1 1 auto;overscroll-behavior:contain}:host ::ng-deep .praxis-filter-advanced .praxis-filter-form .filter-row{display:grid!important;grid-template-columns:repeat(auto-fit,minmax(var(--pfx-field-min),1fr));gap:var(--pfx-gap-y) var(--pfx-gap-x)}:host ::ng-deep .praxis-filter-advanced .praxis-filter-form .filter-column{min-width:0}:host ::ng-deep .praxis-filter-advanced .praxis-filter-form .filter-column .mat-mdc-form-field{width:100%}.advanced-actions{position:sticky;bottom:0;z-index:2;display:flex;justify-content:flex-end;gap:8px;padding:var(--pfx-gap-y) var(--pfx-advanced-pad-x);background-color:var(--pfx-overlay-surface)!important;background:var(--pfx-overlay-surface)!important;border-top:1px solid var(--border-color);box-shadow:0 -1px 0 var(--md-sys-color-outline-variant)}.advanced-actions .mat-mdc-button-base{height:40px}.advanced-actions .mat-mdc-raised-button.mat-primary{background:var(--md-sys-color-primary);color:var(--md-sys-color-on-primary)}:host ::ng-deep .praxis-filter-advanced .mat-mdc-text-field-wrapper.mdc-text-field--outlined{--mdc-outlined-text-field-outline-color: var(--border-color);--mdc-outlined-text-field-hover-outline-color: var(--border-color-hover);--mdc-outlined-text-field-focus-outline-color: var(--md-sys-color-primary);--mdc-outlined-text-field-label-text-color: var(--pfx-overlay-on-surface-variant);--mdc-outlined-text-field-input-text-color: var(--pfx-overlay-on-surface);--mdc-outlined-text-field-container-color: var(--pfx-overlay-surface)}:host ::ng-deep .praxis-filter-advanced .mat-mdc-select-trigger,:host ::ng-deep .praxis-filter-advanced .mat-mdc-form-field-subscript-wrapper,:host ::ng-deep .praxis-filter-advanced .mat-mdc-form-field-infix{color:var(--pfx-overlay-on-surface)}@media(min-width:600px){.fields-grid{gap:6px 8px}:host ::ng-deep .praxis-filter-advanced .praxis-filter-form .filter-row{grid-template-columns:repeat(2,minmax(0,1fr))}}@media(min-width:960px){.fields-grid{gap:6px 10px}}@media(min-width:1200px){.fields-grid{grid-template-columns:repeat(auto-fit,minmax(var(--pfx-always-min, 220px),var(--pfx-always-max-desktop, 380px)));justify-content:start;align-content:start}:host ::ng-deep .fields-grid .pfx-field-shell[data-control-type=slider],:host ::ng-deep .fields-grid .pfx-field-shell[data-control-type=range-slider],:host ::ng-deep .fields-grid .pfx-field-shell[data-control-type=rangeSlider],:host ::ng-deep .fields-grid .pfx-field-shell[data-control-type=rangeslider]{grid-column:span var(--pfx-slider-span-desktop, 2)}}.inline-toggles{display:flex;align-items:center;gap:8px;margin:0 4px 0 6px}:host ::ng-deep .inline-actions .mat-mdc-slide-toggle{height:var(--pfx-filter-h);display:flex;align-items:center}:host ::ng-deep .inline-actions .mat-mdc-slide-toggle .mdc-form-field{align-items:center}::ng-deep .praxis-filter-overlay .praxis-filter-advanced .praxis-filter-form .filter-row{display:grid!important;gap:var(--pfx-gap-y, 1px) var(--pfx-gap-x, 6px)}@media(min-width:600px){::ng-deep .praxis-filter-overlay .praxis-filter-advanced .praxis-filter-form .filter-row{grid-template-columns:repeat(2,minmax(0,1fr))}}.sr-only{position:absolute!important;width:1px!important;height:1px!important;margin:-1px!important;overflow:hidden!important;clip:rect(0,0,0,0)!important}.hidden-submit{position:absolute!important;width:0!important;height:0!important;padding:0!important;margin:0!important;border:0!important;opacity:0!important;pointer-events:none!important;clip:rect(0 0 0 0)!important;clip-path:inset(50%)!important;overflow:hidden!important}:host ::ng-deep .inline-actions [matBadge] .mat-badge-content{top:-6px;right:-6px}.praxis-filter-bar :where(.mat-mdc-slide-toggle .mdc-switch__icons){display:none!important}.praxis-filter-bar{--mdc-switch-unselected-icon-size: 0px;--mdc-switch-selected-icon-size: 0px;--pfx-always-min: 220px}.praxis-filter-card{display:flex;flex-direction:column;gap:6px;padding:8px 12px;border-radius:12px;border:1px solid var(--pfx-surface-border, var(--md-sys-color-outline-variant));background:var(--md-sys-color-surface-container);color:var(--md-sys-color-on-surface)}:host ::ng-deep .praxis-add-select-panel{width:min(340px,100vw - 24px)!important;min-width:min(280px,100vw - 24px)!important;max-width:calc(100vw - 24px)!important;max-height:min(56vh,420px);margin-top:8px;padding:6px 0;border-radius:14px;overflow:auto;background:var(--md-sys-color-surface-container-highest);border:1px solid var(--pfx-surface-border, var(--md-sys-color-outline-variant));box-shadow:var(--md-sys-elevation-level3)}:host ::ng-deep .cdk-overlay-pane:has(.praxis-add-select-panel){width:auto!important;min-width:0!important;max-width:calc(100vw - 24px)!important}:host ::ng-deep .praxis-add-select-panel .mat-mdc-option{min-height:36px}:host ::ng-deep .praxis-add-select-panel .add-search{position:sticky;top:0;background:var(--md-sys-color-surface-container-highest);z-index:1;padding:0 8px 6px;cursor:default}:host ::ng-deep .praxis-add-select-panel .add-search .mat-mdc-form-field{width:100%}:host ::ng-deep .praxis-add-select-panel .add-search .mat-mdc-form-field-subscript-wrapper{display:none}.inline-actions .add-trigger{display:inline-flex;align-items:center;gap:6px;height:32px;width:100%;max-width:100%;min-width:0;padding:0 10px;border-radius:0;border:0;background:transparent;overflow:visible}:host ::ng-deep .inline-actions .add-trigger mat-icon{width:18px;height:18px;font-size:18px;flex:0 0 auto}.inline-actions .add-trigger-label{display:inline-block;flex:1 1 auto;min-width:0;max-width:100%;text-align:left;direction:ltr;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:.82rem;line-height:1}:host ::ng-deep .action-cluster--manage .mat-mdc-select{flex:0 0 auto;width:180px;min-width:0;max-width:180px}:host ::ng-deep .action-cluster--manage .mat-mdc-select-trigger{min-height:32px;padding:0}:host ::ng-deep .action-cluster--manage .mat-mdc-select-value,:host ::ng-deep .action-cluster--manage .mat-mdc-select-value-text,:host ::ng-deep .action-cluster--manage .mat-mdc-select-min-line{width:auto;min-width:0;max-width:100%;display:inline-flex;align-items:center;justify-content:flex-start;overflow:visible}.praxis-filter-card .summary-header{display:flex;align-items:center;gap:10px}.praxis-filter-card .summary-avatar{width:32px;height:32px;border-radius:50%;object-fit:cover}.praxis-filter-card .summary-title{font-weight:600}.praxis-filter-card .summary-subtitle{opacity:.8;font-size:.875rem}.praxis-filter-card .summary-badges{display:flex;flex-wrap:wrap;gap:6px}.praxis-filter-card .summary-badges span{display:inline-flex;align-items:center;padding:2px 8px;border-radius:999px;background:var(--md-sys-color-primary-container);border:1px solid var(--md-sys-color-outline-variant);color:var(--md-sys-color-on-primary-container);font-size:12px}.praxis-filter-card .card-actions{display:flex;gap:8px}:host ::ng-deep .inline-actions .mat-mdc-select-arrow-wrapper{display:none}.inline-actions .add-filter-btn{height:36px;border-radius:18px;padding:0 16px 0 12px}.inline-actions .add-filter-btn mat-icon{margin-right:8px;margin-left:-4px}:host ::ng-deep .praxis-add-select-panel .add-select-all.partial .select-all-partial{opacity:.7;font-style:italic}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i6.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i6.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i7.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: MatButtonModule }, { kind: "component", type: i3.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: "component", type: i3.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatChipsModule }, { kind: "component", type: i15.MatChip, selector: "mat-basic-chip, [mat-basic-chip], mat-chip, [mat-chip]", inputs: ["role", "id", "aria-label", "aria-description", "value", "color", "removable", "highlighted", "disableRipple", "disabled"], outputs: ["removed", "destroyed"], exportAs: ["matChip"] }, { kind: "component", type: i15.MatChipSet, selector: "mat-chip-set", inputs: ["disabled", "role", "tabIndex"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i5.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }, { kind: "ngmodule", type: MatBadgeModule }, { kind: "directive", type: i15$2.MatBadge, selector: "[matBadge]", inputs: ["matBadgeColor", "matBadgeOverlap", "matBadgeDisabled", "matBadgePosition", "matBadge", "matBadgeDescription", "matBadgeSize", "matBadgeHidden"] }, { kind: "ngmodule", type: MatProgressBarModule }, { kind: "component", type: i15$4.MatProgressBar, selector: "mat-progress-bar", inputs: ["color", "value", "bufferValue", "mode"], outputs: ["animationEnd"], exportAs: ["matProgressBar"] }, { kind: "ngmodule", type: MatSnackBarModule }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i10.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i17.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: i17.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i17.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "directive", type: DynamicFieldLoaderDirective, selector: "[dynamicFieldLoader]", inputs: ["fields", "formGroup", "enableExternalControlBinding", "itemTemplate", "debugTrace", "debugTraceLabel", "readonlyMode", "disabledMode", "presentationMode", "visible", "canvasMode"], outputs: ["componentsCreated", "fieldCreated", "fieldDestroyed", "renderError", "canvasMouseEnter", "canvasMouseLeave", "canvasClick"] }, { kind: "ngmodule", type: OverlayModule }, { kind: "directive", type: i11$1.CdkOverlayOrigin, selector: "[cdk-overlay-origin], [overlay-origin], [cdkOverlayOrigin]", exportAs: ["cdkOverlayOrigin"] }, { kind: "ngmodule", type: MatDialogModule }, { kind: "ngmodule", type: A11yModule }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i5$1.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: "directive", type: i5$1.MatSelectTrigger, selector: "mat-select-trigger" }, { kind: "component", type: i5$1.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatOptionModule }] });
32316
32797
  }
32317
32798
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: PraxisFilter, decorators: [{
32318
32799
  type: Component,
@@ -40006,7 +40487,7 @@ class PraxisTable {
40006
40487
  const max = this.getRatingMax(row, column);
40007
40488
  if (!isFinite(n))
40008
40489
  return 0;
40009
- return Math.max(0, Math.min(max, n));
40490
+ return this.normalizeTableRatingValue(n, max);
40010
40491
  }
40011
40492
  getRatingMax(_row, column) {
40012
40493
  const cfg = this.getEffectiveRenderer(_row, column)?.rating;
@@ -40029,10 +40510,9 @@ class PraxisTable {
40029
40510
  (column.header || null);
40030
40511
  return label === null || label === undefined || label === '' ? undefined : label;
40031
40512
  }
40032
- getRatingReadonly(_row, column) {
40033
- const r = this.getEffectiveRenderer(_row, column)?.rating;
40034
- // Em tabela preferimos sempre readonly para evitar foco no click da linha, mas permitimos override.
40035
- return r?.readonly !== false;
40513
+ normalizeTableRatingValue(value, max) {
40514
+ const clamped = Math.max(0, Math.min(max, value));
40515
+ return Math.round(clamped * 2) / 2;
40036
40516
  }
40037
40517
  // Avatar
40038
40518
  getAvatarSrc(row, column) {
@@ -40930,7 +41410,7 @@ class PraxisTable {
40930
41410
  TableDefaultsProvider,
40931
41411
  FilterConfigService,
40932
41412
  DataFormattingService
40933
- ], queries: [{ propertyName: "toolbar", first: true, predicate: PraxisTableToolbar, descendants: true }, { propertyName: "projectedFilter", first: true, predicate: ["projectedFilter"], descendants: true }], viewQueries: [{ propertyName: "paginator", first: true, predicate: MatPaginator, descendants: true }, { propertyName: "sort", first: true, predicate: MatSort, descendants: true }, { propertyName: "materialTable", first: true, predicate: MatTable, descendants: true }, { propertyName: "internalFilter", first: true, predicate: PraxisFilter, descendants: true }], usesOnChanges: true, ngImport: i0, template: "@if (shouldShowEmptyState()) {\n <praxis-empty-state-card\n icon=\"link\"\n [title]=\"'Conecte a tabela \u00E0 fonte de dados'\"\n [description]=\"'Informe a rota do recurso da API para carregar colunas e dados automaticamente.'\"\n [primaryAction]=\"{ label: 'Conectar \u00E0 fonte de dados', icon: 'bolt', action: openQuickConnect.bind(this) }\"\n ></praxis-empty-state-card>\n}\n\n<!-- Error State with Quick Connect CTA -->\n@if (isRemoteMode() && (schemaError || dataError)) {\n<div class=\"ptable-error\" role=\"alert\" aria-live=\"assertive\">\n <mat-icon color=\"warn\" aria-hidden=\"true\">error</mat-icon>\n <div class=\"ptable-error__content\">\n <div class=\"ptable-error__title\">Erro</div>\n <div>{{ errorMessage || 'Ocorreu um erro ao carregar a tabela.' }}</div>\n </div>\n <button mat-flat-button color=\"primary\" (click)=\"openQuickConnect()\">\n <mat-icon>bolt</mat-icon>\n Conectar a recurso\n </button>\n @if (!schemaError) { <button mat-stroked-button (click)=\"retryData()\">Tentar novamente</button> }\n @if (schemaError) { <button mat-stroked-button (click)=\"reloadSchema()\">Recarregar colunas</button> }\n </div>\n}\n\n<!-- Inline banner for schema change (only in edit mode) -->\n@if (shouldShowOutdatedInline()) {\n<div class=\"ptable-info-banner\" role=\"status\" aria-live=\"polite\">\n <div class=\"text\">O schema do servidor mudou. Reconciliar agora?</div>\n <div class=\"actions\">\n <button mat-stroked-button color=\"primary\" (click)=\"onReconcileRequested()\">\n <mat-icon>sync</mat-icon>\n Reconciliar\n </button>\n <button mat-button (click)=\"onSnoozeOutdated()\">Lembrar depois</button>\n <button mat-button (click)=\"onIgnoreOutdated()\">Ignorar</button>\n </div>\n </div>\n}\n\n@if (shouldRenderDataSurface() && !schemaError && !dataError && toolbarV2) {\n <div class=\"praxis-table-header\" [class.edit-mode]=\"editModeEnabled\" [class.stacked]=\"showToolbar\">\n @if (showToolbar && shouldShowToolbarTopPlacement()) {\n <praxis-table-toolbar\n [config]=\"config\"\n [backgroundColor]=\"getToolbarActionsBackgroundColor()\"\n [style.--pfx-filter-h]=\"getToolbarLayoutHeightHostStyle()\"\n [dslContext]=\"getToolbarDslContext()\"\n [dslFunctionRegistry]=\"dslFunctionRegistry\"\n [showActionsGroup]=\"shouldShowToolbarActionsTop()\"\n [showMobileActions]=\"shouldShowToolbarActionsTop()\"\n (toolbarAction)=\"onToolbarAction($event)\"\n (reset)=\"onResetPreferences()\"\n >\n @if (shouldRenderAdvancedFilter()) {\n <praxis-filter\n advancedFilter\n [resourcePath]=\"getAdvancedFilterResourcePath()\"\n [filterId]=\"tableId\"\n [formId]=\"tableId\"\n [persistenceKey]=\"getAdvancedFilterPersistenceKey()\"\n [fieldMetadata]=\"getAdvancedFilterFieldMetadata()\"\n [editModeEnabled]=\"editModeEnabled\"\n \n [alwaysVisibleFields]=\"config.behavior?.filtering?.advancedFilters?.settings?.alwaysVisibleFields\"\n [alwaysVisibleFieldMetadataOverrides]=\"config.behavior?.filtering?.advancedFilters?.settings?.alwaysVisibleFieldMetadataOverrides ?? {}\"\n [selectedFieldIds]=\"config.behavior?.filtering?.advancedFilters?.settings?.selectedFieldIds ?? []\"\n [allowSaveTags]=\"config.behavior?.filtering?.advancedFilters?.settings?.allowSaveTags\"\n [changeDebounceMs]=\"config.behavior?.filtering?.advancedFilters?.settings?.changeDebounceMs ?? 300\"\n [i18n]=\"getFilterI18n()\"\n [mode]=\"'filter'\"\n [showFilterSettings]=\"editModeEnabled\"\n (submit)=\"onAdvancedFilterSubmit($event)\"\n (clear)=\"onAdvancedFilterClear()\"\n ></praxis-filter>\n }\n <ng-content select=\"[advancedFilter]\" />\n <ng-content select=\"[toolbar]\" />\n \n <!-- AI Assistant in Toolbar -->\n @defer (on idle) {\n @if (aiAdapter) {\n <praxis-ai-assistant [adapter]=\"aiAdapter\" end-actions></praxis-ai-assistant>\n }\n }\n\n @if (editModeEnabled) {\n <button end-actions mat-icon-button color=\"primary\" data-role=\"table-settings\" data-testid=\"table-settings-trigger\"\n (click)=\"openTableSettings()\" aria-label=\"Configura\u00E7\u00F5es\"\n [matBadge]=\"schemaOutdated ? '!' : ''\"\n [matBadgeHidden]=\"!schemaOutdated\"\n matBadgeColor=\"warn\" matBadgeSize=\"small\" matBadgePosition=\"above after\"\n [matTooltip]=\"schemaOutdated ? 'Schema do servidor mudou \u2014 Reconciliar' : 'Configura\u00E7\u00F5es'\"\n matTooltipPosition=\"below\">\n <mat-icon>settings</mat-icon>\n </button>\n }\n </praxis-table-toolbar>\n }\n @if (!showToolbar && editModeEnabled) {\n <div class=\"ptable-header-actions\">\n @defer (on idle) {\n @if (aiAdapter) {\n <praxis-ai-assistant [adapter]=\"aiAdapter\"></praxis-ai-assistant>\n }\n }\n <button mat-icon-button color=\"primary\" data-role=\"table-settings\" data-testid=\"table-settings-trigger\" (click)=\"openTableSettings()\" aria-label=\"Configura\u00E7\u00F5es\"\n [matBadge]=\"schemaOutdated ? '!' : ''\"\n [matBadgeHidden]=\"!schemaOutdated\"\n matBadgeColor=\"warn\" matBadgeSize=\"small\" matBadgePosition=\"above after\"\n [matTooltip]=\"schemaOutdated ? 'Schema do servidor mudou \u2014 Reconciliar' : 'Configura\u00E7\u00F5es'\"\n matTooltipPosition=\"below\">\n <mat-icon>settings</mat-icon>\n </button>\n @if (isRemoteMode()) {\n <button mat-icon-button (click)=\"disconnect()\" aria-label=\"Desconectar\" matTooltip=\"Desconectar da fonte de dados\">\n <mat-icon>link_off</mat-icon>\n </button>\n }\n </div>\n }\n </div>\n} @else {\n @if (shouldRenderDataSurface() && !schemaError && !dataError) {\n @if (showToolbar && shouldShowToolbarTopPlacement()) {\n <praxis-table-toolbar\n [config]=\"config\"\n [backgroundColor]=\"getToolbarActionsBackgroundColor()\"\n [style.--pfx-filter-h]=\"getToolbarLayoutHeightHostStyle()\"\n [dslContext]=\"getToolbarDslContext()\"\n [dslFunctionRegistry]=\"dslFunctionRegistry\"\n [showActionsGroup]=\"shouldShowToolbarActionsTop()\"\n [showMobileActions]=\"shouldShowToolbarActionsTop()\"\n (toolbarAction)=\"onToolbarAction($event)\"\n (reset)=\"onResetPreferences()\"\n >\n @if (shouldRenderAdvancedFilter()) {\n <praxis-filter\n advancedFilter\n [resourcePath]=\"getAdvancedFilterResourcePath()\"\n [filterId]=\"tableId\"\n [formId]=\"tableId\"\n [persistenceKey]=\"getAdvancedFilterPersistenceKey()\"\n [fieldMetadata]=\"getAdvancedFilterFieldMetadata()\"\n [editModeEnabled]=\"editModeEnabled\"\n \n [alwaysVisibleFields]=\"config.behavior?.filtering?.advancedFilters?.settings?.alwaysVisibleFields\"\n [alwaysVisibleFieldMetadataOverrides]=\"config.behavior?.filtering?.advancedFilters?.settings?.alwaysVisibleFieldMetadataOverrides ?? {}\"\n [selectedFieldIds]=\"config.behavior?.filtering?.advancedFilters?.settings?.selectedFieldIds ?? []\"\n [allowSaveTags]=\"config.behavior?.filtering?.advancedFilters?.settings?.allowSaveTags\"\n [changeDebounceMs]=\"config.behavior?.filtering?.advancedFilters?.settings?.changeDebounceMs ?? 300\"\n [i18n]=\"getFilterI18n()\"\n [mode]=\"'filter'\"\n [showFilterSettings]=\"editModeEnabled\"\n (submit)=\"onAdvancedFilterSubmit($event)\"\n (clear)=\"onAdvancedFilterClear()\"\n ></praxis-filter>\n }\n <ng-content select=\"[advancedFilter]\" />\n <ng-content select=\"[toolbar]\" />\n @defer (on idle) {\n @if (aiAdapter) {\n <praxis-ai-assistant [adapter]=\"aiAdapter\" end-actions></praxis-ai-assistant>\n }\n }\n @if (editModeEnabled) {\n <button end-actions mat-icon-button color=\"primary\" data-role=\"table-settings\" data-testid=\"table-settings-trigger\"\n (click)=\"openTableSettings()\" aria-label=\"Configura\u00E7\u00F5es\"\n [matBadge]=\"schemaOutdated ? '!' : ''\"\n [matBadgeHidden]=\"!schemaOutdated\"\n matBadgeColor=\"warn\" matBadgeSize=\"small\" matBadgePosition=\"above after\"\n [matTooltip]=\"schemaOutdated ? 'Schema do servidor mudou \u2014 Reconciliar' : 'Configura\u00E7\u00F5es'\"\n matTooltipPosition=\"below\">\n <mat-icon>settings</mat-icon>\n </button>\n }\n </praxis-table-toolbar>\n }\n @if (!showToolbar && editModeEnabled) {\n <div class=\"ptable-header-actions\">\n <button mat-icon-button color=\"primary\" data-role=\"table-settings\" data-testid=\"table-settings-trigger\" (click)=\"openTableSettings()\" aria-label=\"Configura\u00E7\u00F5es\"\n [matBadge]=\"schemaOutdated ? '!' : ''\"\n [matBadgeHidden]=\"!schemaOutdated\"\n matBadgeColor=\"warn\" matBadgeSize=\"small\" matBadgePosition=\"above after\"\n [matTooltip]=\"schemaOutdated ? 'Schema do servidor mudou \u2014 Reconciliar' : 'Configura\u00E7\u00F5es'\"\n matTooltipPosition=\"below\">\n <mat-icon>settings</mat-icon>\n </button>\n </div>\n }\n }\n}\n<div class=\"px-scroll-viewport\"\n cdkScrollable\n [class.scroll-auto]=\"horizontalScroll === 'auto'\"\n [class.scroll-wrap]=\"horizontalScroll === 'wrap'\"\n [class.scroll-none]=\"horizontalScroll === 'none'\">\n\n@if (shouldRenderDataSurface() && !schemaError && !dataError) {\n<div class=\"praxis-visually-hidden-status\" role=\"status\" aria-live=\"polite\" aria-atomic=\"true\">\n {{ columnReorderStatusMessage }}\n</div>\n@if (columnReorderVisualStatusMessage) {\n <div class=\"praxis-column-reorder-status\" role=\"note\">\n {{ columnReorderVisualStatusMessage }}\n </div>\n}\n<table\n mat-table\n data-testid=\"table-column-drag-drop-list\"\n [dataSource]=\"dataSource\"\n [multiTemplateDataRows]=\"isRowExpansionRuntimeEnabled()\"\n cdkDropList\n [cdkDropListDisabled]=\"!isColumnDraggingEnabled()\"\n [cdkDropListData]=\"visibleDataColumnsForDrag\"\n cdkDropListOrientation=\"horizontal\"\n (cdkDropListDropped)=\"onColumnDrop($event)\"\n matSort\n (matSortChange)=\"onSortChange($event)\"\n [matSortDisabled]=\"!getSortingEnabled()\"\n [ngClass]=\"getTableElevationClassName()\"\n [class.table-stack-top]=\"showToolbar\"\n [class.pfx-column-drag-enabled]=\"isColumnDraggingEnabled()\"\n [class.pfx-column-drag-indicator]=\"isColumnDragIndicatorEnabled()\"\n>\n @if (config.behavior?.selection?.enabled) {\n <ng-container\n matColumnDef=\"_select\"\n >\n <th mat-header-cell *matHeaderCellDef>\n @if (canSelectAll()) {\n <mat-checkbox\n (change)=\"masterToggle()\"\n [checked]=\"isAllSelected()\"\n [indeterminate]=\"selection.hasValue() && !isAllSelected()\"\n ></mat-checkbox>\n }\n </th>\n <td mat-cell *matCellDef=\"let row\">\n <mat-checkbox\n (click)=\"$event.stopPropagation()\"\n (change)=\"toggleRow(row)\"\n [checked]=\"selection.isSelected(row)\"\n ></mat-checkbox>\n </td>\n </ng-container>\n }\n @if (isRowExpansionRuntimeEnabled()) {\n <ng-container matColumnDef=\"_expander\">\n <th mat-header-cell *matHeaderCellDef class=\"pfx-expansion-col-header\">\n <span class=\"praxis-visually-hidden-status\">Expandir detalhes da linha</span>\n </th>\n <td mat-cell *matCellDef=\"let row; let i = index\" class=\"pfx-expansion-col-cell\">\n <button\n mat-icon-button\n class=\"pfx-expansion-toggle\"\n [disabled]=\"!isRowExpandable(row, i) || !isExpansionIconTriggerEnabled()\"\n [attr.aria-expanded]=\"isRowExpanded(row, i) ? 'true' : 'false'\"\n [attr.aria-controls]=\"getRowExpansionDetailId(row, i)\"\n [attr.aria-label]=\"getRowExpansionToggleAriaLabel(row, i)\"\n (click)=\"onExpansionToggleFromIcon(row, i, $event)\"\n (keydown)=\"onExpansionToggleKeydown($event, row, i)\"\n >\n <mat-icon>{{ isRowExpanded(row, i) ? 'expand_less' : 'expand_more' }}</mat-icon>\n </button>\n </td>\n </ng-container>\n }\n @for (column of visibleColumns; track column.field) {\n <ng-container\n [matColumnDef]=\"column.field\"\n [sticky]=\"column.sticky === true || column.sticky === 'start'\"\n [stickyEnd]=\"column.sticky === 'end'\"\n >\n <th\n mat-header-cell\n *matHeaderCellDef\n mat-sort-header\n cdkDrag\n [cdkDragData]=\"column\"\n cdkDragLockAxis=\"x\"\n cdkDragPreviewClass=\"pfx-column-drag-preview\"\n (cdkDragStarted)=\"onColumnDragStarted(column)\"\n (cdkDragEnded)=\"onColumnDragEnded($event, column)\"\n (keydown)=\"onColumnDragHandleKeydown($event, column)\"\n [cdkDragDisabled]=\"!isColumnDraggingEnabled() || !isColumnDraggable(column)\"\n [class.praxis-header-draggable]=\"isColumnDraggingEnabled() && isColumnDraggable(column)\"\n [disabled]=\"!getSortingEnabled() || column.sortable === false\"\n [style.text-align]=\"getColumnTextAlignStyle(column)\"\n [style.width]=\"getColumnWidthStyle(column)\"\n [attr.style]=\"getColumnHeaderAttrStyle(column)\"\n [attr.aria-label]=\"isColumnDraggingEnabled() && isColumnDraggable(column) ? getColumnDragHandleAriaLabel(column) : null\"\n [matTooltip]=\"isColumnDraggingEnabled() && isColumnDraggable(column) ? getColumnDragHandleTooltip(column) : null\"\n matTooltipPosition=\"above\"\n matTooltipClass=\"praxis-tooltip\"\n >\n <span class=\"praxis-header-label\" data-testid=\"column-header-label\">{{ column.header }}</span>\n @if (isColumnDraggingEnabled() && isColumnDraggable(column)) {\n <span\n class=\"praxis-column-drag-handle\"\n data-testid=\"column-drag-handle\"\n [attr.data-column-field]=\"column.field\"\n aria-hidden=\"true\"\n >\n <mat-icon [praxisIcon]=\"'drag_indicator'\"></mat-icon>\n </span>\n }\n </th>\n <td\n mat-cell\n *matCellDef=\"let element\"\n [style.text-align]=\"getColumnTextAlignStyle(column)\"\n [style.width]=\"getColumnWidthStyle(column)\"\n [attr.style]=\"getColumnCellAttrStyle(column)\"\n [ngClass]=\"getCellClasses(element, column)\"\n [ngStyle]=\"getCellNgStyle(element, column)\"\n >\n <div\n class=\"pfx-cell-content\"\n [ngClass]=\"getCellContentClasses(element, column)\"\n [ngStyle]=\"getCellContentNgStyle(element, column)\"\n >\n <ng-container [ngSwitch]=\"getEffectiveRendererType(element, column)\">\n <!-- Icon renderer -->\n <ng-container *ngSwitchCase=\"'icon'\">\n <mat-icon\n [color]=\"getIconColor(element, column) || null\"\n [ngStyle]=\"getIconStyle(element, column)\"\n [attr.aria-label]=\"getIconAriaLabel(element, column) || null\"\n >{{ getIconName(element, column) }}</mat-icon\n >\n </ng-container>\n\n <!-- Image renderer -->\n <ng-container *ngSwitchCase=\"'image'\">\n <img\n class=\"pfx-cell-image\"\n [src]=\"getImageSrc(element, column)\"\n [attr.alt]=\"getImageAlt(element, column) || ''\"\n [attr.loading]=\"getImageLazy(element, column) ? 'lazy' : null\"\n [style.width.px]=\"getImageWidth(element, column)\"\n [style.height.px]=\"getImageHeight(element, column)\"\n [class.shape-rounded]=\"getImageShape(element, column) === 'rounded'\"\n [class.shape-circle]=\"getImageShape(element, column) === 'circle'\"\n [style.object-fit]=\"getImageFit(element, column)\"\n />\n </ng-container>\n\n <!-- Badge renderer -->\n <ng-container *ngSwitchCase=\"'badge'\">\n <span class=\"pfx-badge\" [ngClass]=\"getBadgeClasses(element, column)\">\n @if (getBadgeIcon(element, column); as bi) { <mat-icon class=\"pfx-badge-icon\">{{ bi }}</mat-icon> }\n <span class=\"pfx-badge-text\">{{ getBadgeText(element, column) }}</span>\n </span>\n </ng-container>\n\n <!-- Link renderer -->\n <ng-container *ngSwitchCase=\"'link'\">\n <a\n class=\"pfx-link\"\n [attr.href]=\"getLinkHref(element, column) || null\"\n [attr.target]=\"getLinkTarget(element, column) || null\"\n [attr.rel]=\"getLinkRel(element, column) || null\"\n (click)=\"$event.stopPropagation()\"\n >{{ getLinkText(element, column) }}</a\n >\n </ng-container>\n\n <!-- Button renderer -->\n <ng-container *ngSwitchCase=\"'button'\">\n <ng-container [ngSwitch]=\"getButtonVariant(element, column)\">\n <button\n *ngSwitchCase=\"'outlined'\"\n mat-stroked-button\n [color]=\"getButtonColor(element, column) || null\"\n [disabled]=\"isButtonDisabled(element, column)\"\n [attr.aria-label]=\"getButtonAriaLabel(element, column) || getButtonLabel(element, column)\"\n (click)=\"onButtonClick(element, column, $event)\"\n >\n @if (getButtonIcon(element, column); as bi) { <mat-icon>{{ bi }}</mat-icon> }\n {{ getButtonLabel(element, column) }}\n </button>\n <button\n *ngSwitchCase=\"'text'\"\n mat-button\n [color]=\"getButtonColor(element, column) || null\"\n [disabled]=\"isButtonDisabled(element, column)\"\n [attr.aria-label]=\"getButtonAriaLabel(element, column) || getButtonLabel(element, column)\"\n (click)=\"onButtonClick(element, column, $event)\"\n >\n @if (getButtonIcon(element, column); as bi) { <mat-icon>{{ bi }}</mat-icon> }\n {{ getButtonLabel(element, column) }}\n </button>\n <button\n *ngSwitchDefault\n mat-flat-button\n [color]=\"getButtonColor(element, column) || null\"\n [disabled]=\"isButtonDisabled(element, column)\"\n [attr.aria-label]=\"getButtonAriaLabel(element, column) || getButtonLabel(element, column)\"\n (click)=\"onButtonClick(element, column, $event)\"\n >\n @if (getButtonIcon(element, column); as bi) { <mat-icon>{{ bi }}</mat-icon> }\n {{ getButtonLabel(element, column) }}\n </button>\n </ng-container>\n </ng-container>\n\n <!-- Chip renderer -->\n <ng-container *ngSwitchCase=\"'chip'\">\n <span class=\"pfx-chip\" [ngClass]=\"getChipClasses(element, column)\">\n @if (getChipIcon(element, column); as ci) { <mat-icon class=\"pfx-chip-icon\">{{ ci }}</mat-icon> }\n <span class=\"pfx-chip-text\">{{ getChipText(element, column) }}</span>\n </span>\n </ng-container>\n\n <!-- Progress renderer -->\n <ng-container *ngSwitchCase=\"'progress'\">\n <div class=\"pfx-progress\">\n <div class=\"pfx-progress-bar\" [style.width.%]=\"getProgressWidthPercentStyle(element, column)\" [style.background]=\"getProgressBackgroundStyle(element, column)\"></div>\n @if (getProgressShowLabel(element, column)) { <div class=\"pfx-progress-label\">{{ getProgressValue(element, column) }}%</div> }\n </div>\n </ng-container>\n\n <!-- Avatar renderer -->\n <ng-container *ngSwitchCase=\"'avatar'\">\n @if (getAvatarSrc(element, column); as asrc) {\n <img class=\"pfx-avatar\" [src]=\"asrc\" [attr.alt]=\"getAvatarAlt(element, column) || ''\" [ngStyle]=\"getAvatarStyle(element, column)\" [class.shape-rounded]=\"getAvatarShape(element, column) === 'rounded'\" [class.shape-circle]=\"getAvatarShape(element, column) === 'circle'\" loading=\"lazy\" />\n } @else {\n <span class=\"pfx-avatar pfx-avatar--initials\" [ngStyle]=\"getAvatarStyle(element, column)\" [class.shape-rounded]=\"getAvatarShape(element, column) === 'rounded'\" [class.shape-circle]=\"getAvatarShape(element, column) === 'circle'\">{{ getAvatarInitials(element, column) }}</span>\n }\n </ng-container>\n\n <!-- Toggle renderer -->\n <ng-container *ngSwitchCase=\"'toggle'\">\n <mat-slide-toggle\n [checked]=\"getToggleState(element, column)\"\n [disabled]=\"isToggleDisabled(element, column)\"\n [attr.aria-label]=\"getToggleAriaLabel(element, column) || 'Alternar'\"\n (change)=\"onToggleChange(element, column, $event)\"\n (click)=\"$event.stopPropagation()\"\n ></mat-slide-toggle>\n </ng-container>\n\n <!-- Menu renderer -->\n <ng-container *ngSwitchCase=\"'menu'\">\n <button mat-icon-button [matMenuTriggerFor]=\"menuRef\" (click)=\"$event.stopPropagation()\" [attr.aria-label]=\"getMenuAriaLabel(element, column) || 'Menu'\">\n <mat-icon>more_vert</mat-icon>\n </button>\n <mat-menu #menuRef=\"matMenu\">\n <button mat-menu-item *ngFor=\"let it of getMenuItems(element, column)\" (click)=\"onMenuItemClick(it, element, $event)\" [disabled]=\"!it.__visible\" >\n @if (it.icon) { <mat-icon>{{ it.icon }}</mat-icon> }\n <span>{{ it.label }}</span>\n </button>\n </mat-menu>\n </ng-container>\n\n <!-- Rating renderer -->\n <ng-container *ngSwitchCase=\"'rating'\">\n <pdx-material-rating\n class=\"pfx-rating-cell\"\n [itemsCount]=\"getRatingMax(element, column)\"\n [ngModel]=\"getRatingValue(element, column)\"\n [readonlyMode]=\"getRatingReadonly(element, column)\"\n [presentationMode]=\"true\"\n [size]=\"getRatingSize(element, column)\"\n [ratingColor]=\"getRatingColor(element, column)\"\n [outlineColor]=\"getRatingOutlineColor(element, column)\"\n [ariaLabel]=\"getRatingAriaLabel(element, column) || column.header\"\n [tabIndex]=\"-1\">\n </pdx-material-rating>\n </ng-container>\n\n <!-- HTML renderer (sanitizado) -->\n <ng-container *ngSwitchCase=\"'html'\">\n <span [innerHTML]=\"getSafeHtml(element, column)\"></span>\n </ng-container>\n\n <!-- Compose renderer -->\n <ng-container *ngSwitchCase=\"'compose'\">\n <span class=\"pfx-cell-compose\" [ngClass]=\"getComposeClasses(element, column)\" [ngStyle]=\"getComposeGapStyle(element, column)\">\n <ng-container *ngFor=\"let it of getComposeItems(element, column)\">\n <ng-container [ngSwitch]=\"getItemEffectiveType(element, column, it)\">\n <!-- Reuse helpers by projecting item as faux column -->\n <ng-container *ngSwitchCase=\"'icon'\">\n <mat-icon [color]=\"getIconColor(element, asItemColumn(column, it)) || null\" [ngStyle]=\"getIconStyle(element, asItemColumn(column, it))\" [attr.aria-label]=\"getIconAriaLabel(element, asItemColumn(column, it)) || null\">{{ getIconName(element, asItemColumn(column, it)) }}</mat-icon>\n </ng-container>\n <ng-container *ngSwitchCase=\"'image'\">\n <img class=\"pfx-cell-image\" [src]=\"getImageSrc(element, asItemColumn(column, it))\" [attr.alt]=\"getImageAlt(element, asItemColumn(column, it)) || ''\" [attr.loading]=\"getImageLazy(element, asItemColumn(column, it)) ? 'lazy' : null\" [style.width.px]=\"getImageWidth(element, asItemColumn(column, it))\" [style.height.px]=\"getImageHeight(element, asItemColumn(column, it))\" [class.shape-rounded]=\"getImageShape(element, asItemColumn(column, it)) === 'rounded'\" [class.shape-circle]=\"getImageShape(element, asItemColumn(column, it)) === 'circle'\" [style.object-fit]=\"getImageFit(element, asItemColumn(column, it))\" />\n </ng-container>\n <ng-container *ngSwitchCase=\"'badge'\">\n <span class=\"pfx-badge\" [ngClass]=\"getBadgeClasses(element, asItemColumn(column, it))\">@if (getBadgeIcon(element, asItemColumn(column, it)); as bi) { <mat-icon class=\"pfx-badge-icon\">{{ bi }}</mat-icon> }<span class=\"pfx-badge-text\">{{ getBadgeText(element, asItemColumn(column, it)) }}</span></span>\n </ng-container>\n <ng-container *ngSwitchCase=\"'link'\">\n <a class=\"pfx-link\" [attr.href]=\"getLinkHref(element, asItemColumn(column, it)) || null\" [attr.target]=\"getLinkTarget(element, asItemColumn(column, it)) || null\" [attr.rel]=\"getLinkRel(element, asItemColumn(column, it)) || null\" (click)=\"$event.stopPropagation()\">{{ getLinkText(element, asItemColumn(column, it)) }}</a>\n </ng-container>\n <ng-container *ngSwitchCase=\"'button'\">\n <ng-container [ngSwitch]=\"getButtonVariant(element, asItemColumn(column, it))\">\n <button *ngSwitchCase=\"'outlined'\" mat-stroked-button [color]=\"getButtonColor(element, asItemColumn(column, it)) || null\" [disabled]=\"isButtonDisabled(element, asItemColumn(column, it))\" [attr.aria-label]=\"getButtonAriaLabel(element, asItemColumn(column, it)) || getButtonLabel(element, asItemColumn(column, it))\" (click)=\"onButtonClick(element, asItemColumn(column, it), $event)\">@if (getButtonIcon(element, asItemColumn(column, it)); as bi) { <mat-icon>{{ bi }}</mat-icon> }{{ getButtonLabel(element, asItemColumn(column, it)) }}</button>\n <button *ngSwitchCase=\"'text'\" mat-button [color]=\"getButtonColor(element, asItemColumn(column, it)) || null\" [disabled]=\"isButtonDisabled(element, asItemColumn(column, it))\" [attr.aria-label]=\"getButtonAriaLabel(element, asItemColumn(column, it)) || getButtonLabel(element, asItemColumn(column, it))\" (click)=\"onButtonClick(element, asItemColumn(column, it), $event)\">@if (getButtonIcon(element, asItemColumn(column, it)); as bi) { <mat-icon>{{ bi }}</mat-icon> }{{ getButtonLabel(element, asItemColumn(column, it)) }}</button>\n <button *ngSwitchDefault mat-flat-button [color]=\"getButtonColor(element, asItemColumn(column, it)) || null\" [disabled]=\"isButtonDisabled(element, asItemColumn(column, it))\" [attr.aria-label]=\"getButtonAriaLabel(element, asItemColumn(column, it)) || getButtonLabel(element, asItemColumn(column, it))\" (click)=\"onButtonClick(element, asItemColumn(column, it), $event)\">@if (getButtonIcon(element, asItemColumn(column, it)); as bi) { <mat-icon>{{ bi }}</mat-icon> }{{ getButtonLabel(element, asItemColumn(column, it)) }}</button>\n </ng-container>\n </ng-container>\n <ng-container *ngSwitchCase=\"'chip'\">\n <span class=\"pfx-chip\" [ngClass]=\"getChipClasses(element, asItemColumn(column, it))\">@if (getChipIcon(element, asItemColumn(column, it)); as ci) { <mat-icon class=\"pfx-chip-icon\">{{ ci }}</mat-icon> }<span class=\"pfx-chip-text\">{{ getChipText(element, asItemColumn(column, it)) }}</span></span>\n </ng-container>\n <ng-container *ngSwitchCase=\"'progress'\">\n <div class=\"pfx-progress\"><div class=\"pfx-progress-bar\" [style.width.%]=\"getProgressWidthPercentStyle(element, asItemColumn(column, it))\" [style.background]=\"getProgressBackgroundStyle(element, asItemColumn(column, it))\"></div>@if (getProgressShowLabel(element, asItemColumn(column, it))) { <div class=\"pfx-progress-label\">{{ getProgressValue(element, asItemColumn(column, it)) }}%</div> }</div>\n </ng-container>\n <ng-container *ngSwitchCase=\"'avatar'\">\n @if (getAvatarSrc(element, asItemColumn(column, it)); as asrc) {\n <img class=\"pfx-avatar\" [src]=\"asrc\" [attr.alt]=\"getAvatarAlt(element, asItemColumn(column, it)) || ''\" [ngStyle]=\"getAvatarStyle(element, asItemColumn(column, it))\" [class.shape-rounded]=\"getAvatarShape(element, asItemColumn(column, it)) === 'rounded'\" [class.shape-circle]=\"getAvatarShape(element, asItemColumn(column, it)) === 'circle'\" loading=\"lazy\" />\n } @else {\n <span class=\"pfx-avatar pfx-avatar--initials\" [ngStyle]=\"getAvatarStyle(element, asItemColumn(column, it))\" [class.shape-rounded]=\"getAvatarShape(element, asItemColumn(column, it)) === 'rounded'\" [class.shape-circle]=\"getAvatarShape(element, asItemColumn(column, it)) === 'circle'\">{{ getAvatarInitials(element, asItemColumn(column, it)) }}</span>\n }\n </ng-container>\n <ng-container *ngSwitchCase=\"'toggle'\">\n <mat-slide-toggle [checked]=\"getToggleState(element, asItemColumn(column, it))\" [disabled]=\"isToggleDisabled(element, asItemColumn(column, it))\" [attr.aria-label]=\"getToggleAriaLabel(element, asItemColumn(column, it)) || 'Alternar'\" (change)=\"onToggleChange(element, asItemColumn(column, it), $event)\" (click)=\"$event.stopPropagation()\"></mat-slide-toggle>\n </ng-container>\n <ng-container *ngSwitchCase=\"'menu'\">\n <button mat-icon-button [matMenuTriggerFor]=\"menuRef\" (click)=\"$event.stopPropagation()\" [attr.aria-label]=\"getMenuAriaLabel(element, asItemColumn(column, it)) || 'Menu'\"><mat-icon>more_vert</mat-icon></button>\n <mat-menu #menuRef=\"matMenu\">\n <button mat-menu-item *ngFor=\"let mi of getMenuItems(element, asItemColumn(column, it))\" (click)=\"onMenuItemClick(mi, element, $event)\" [disabled]=\"!mi.__visible\">\n @if (mi.icon) { <mat-icon>{{ mi.icon }}</mat-icon> }\n <span>{{ mi.label }}</span>\n </button>\n </mat-menu>\n </ng-container>\n <ng-container *ngSwitchCase=\"'rating'\">\n <pdx-material-rating\n class=\"pfx-rating-cell\"\n [itemsCount]=\"getRatingMax(element, asItemColumn(column, it))\"\n [ngModel]=\"getRatingValue(element, asItemColumn(column, it))\"\n [readonlyMode]=\"getRatingReadonly(element, asItemColumn(column, it))\"\n [presentationMode]=\"true\"\n [size]=\"getRatingSize(element, asItemColumn(column, it))\"\n [ratingColor]=\"getRatingColor(element, asItemColumn(column, it))\"\n [outlineColor]=\"getRatingOutlineColor(element, asItemColumn(column, it))\"\n [ariaLabel]=\"getRatingAriaLabel(element, asItemColumn(column, it)) || column.header\"\n [tabIndex]=\"-1\">\n </pdx-material-rating>\n </ng-container>\n <ng-container *ngSwitchCase=\"'html'\">\n <span [innerHTML]=\"getSafeHtml(element, asItemColumn(column, it))\"></span>\n </ng-container>\n <!-- Value item: render base cell text alongside visuals -->\n <ng-container *ngSwitchCase=\"'value'\">\n <span class=\"pfx-cell-value\">{{ getComposeItemValue(element, column, it) }}</span>\n </ng-container>\n </ng-container>\n </ng-container>\n </span>\n </ng-container>\n\n <!-- Default text rendering -->\n <ng-container *ngSwitchDefault>\n {{ getCellValue(element, column) }}\n </ng-container>\n </ng-container>\n </div>\n </td>\n </ng-container>\n }\n @if (config.actions?.row?.enabled) {\n <ng-container matColumnDef=\"_actions\" [sticky]=\"config.actions?.row?.sticky === true || config.actions?.row?.sticky === 'start'\" [stickyEnd]=\"config.actions?.row?.sticky === 'end'\">\n <th mat-header-cell *matHeaderCellDef #actionsHeaderCell [style.width]=\"getRowActionsWidthStyle()\" class=\"praxis-actions-header\" [class.align-start]=\"getActionsHeaderAlign() === 'start'\" [class.align-center]=\"getActionsHeaderAlign() === 'center'\" [class.align-end]=\"getActionsHeaderAlign() === 'end'\">\n <div class=\"praxis-actions-header__content\" [matTooltip]=\"getActionsHeaderTooltip() || ''\" [matTooltipDisabled]=\"!getActionsHeaderTooltip()\">\n @if (getActionsHeaderIcon(); as hi) { <mat-icon [praxisIcon]=\"hi\"></mat-icon> }\n @if (getActionsHeaderLabel(); as hl) { <span class=\"label\">{{ hl }}</span> }\n </div>\n </th>\n <td\n mat-cell\n *matCellDef=\"let row\"\n class=\"praxis-actions-cell\"\n [class.dense]=\"dense\"\n [style.width]=\"getRowActionsWidthStyle()\"\n >\n <div class=\"praxis-actions-cell__content\">\n <!-- A\u00E7\u00F5es inline -->\n <!-- Inline actions: icons mode -->\n @if (config.actions?.row?.display === 'icons' || !config.actions?.row?.display) {\n <ng-container *ngFor=\"let a of getInlineRowActions(row); trackBy: trackAction\">\n <button\n mat-icon-button\n class=\"praxis-icon-btn\"\n [disabled]=\"isActionDisabled(a, row)\"\n (click)=\"onRowAction(getActionId(a), row, $event)\"\n [matTooltip]=\"a.label || getActionId(a)\"\n matTooltipPosition=\"above\"\n matTooltipClass=\"praxis-tooltip\"\n [attr.aria-label]=\"a.label || getActionId(a)\"\n [color]=\"a.color || null\"\n >\n <mat-icon [praxisIcon]=\"a.icon\"></mat-icon>\n </button>\n </ng-container>\n }\n\n <!-- Inline actions: buttons mode (show label + icon) -->\n @if (config.actions?.row?.display === 'buttons') {\n <ng-container *ngFor=\"let a of getInlineRowActions(row); trackBy: trackAction\">\n <button\n mat-flat-button\n class=\"praxis-row-btn\"\n [disabled]=\"isActionDisabled(a, row)\"\n (click)=\"onRowAction(getActionId(a), row, $event)\"\n [attr.aria-label]=\"a.label || getActionId(a)\"\n [color]=\"a.color || null\"\n >\n <mat-icon [praxisIcon]=\"a.icon\"></mat-icon>\n <span>{{ a.label || getActionId(a) }}</span>\n </button>\n </ng-container>\n }\n\n <!-- Menu de overflow -->\n @if (hasOverflowRowActions(row)) {\n <button\n mat-icon-button\n class=\"praxis-icon-btn praxis-more-btn\"\n [matMenuTriggerFor]=\"rowMoreMenu\"\n [color]=\"getRowMenuButtonColor() || null\"\n aria-label=\"Mais a\u00E7\u00F5es\"\n >\n <mat-icon [praxisIcon]=\"getRowMenuIcon()\"></mat-icon>\n </button>\n }\n <mat-menu #rowMoreMenu=\"matMenu\" xPosition=\"before\">\n <ng-container\n *ngFor=\"let a of getOverflowRowActions(row); trackBy: trackAction\"\n >\n <button\n mat-menu-item\n (click)=\"onRowAction(getActionId(a), row, $event)\"\n [disabled]=\"isActionDisabled(a, row)\"\n >\n <mat-icon [color]=\"a.color || null\" [praxisIcon]=\"a.icon\"></mat-icon>\n <span>{{ a.label || getActionId(a) }}</span>\n </button>\n </ng-container>\n </mat-menu>\n </div>\n </td>\n </ng-container>\n }\n\n <tr\n mat-header-row\n *matHeaderRowDef=\"displayedColumns\"\n ></tr>\n @if (!isVirtualized()) {\n <tr\n mat-row\n *matRowDef=\"let row; let i = index; columns: displayedColumns\"\n [class.pfx-row-selected]=\"selection.isSelected(row)\"\n [class.pfx-row-expanded]=\"isRowExpansionRuntimeEnabled() && isRowExpanded(row, i)\"\n [attr.aria-selected]=\"config.behavior?.selection?.enabled ? (selection.isSelected(row) ? 'true' : 'false') : null\"\n [attr.aria-expanded]=\"isRowExpansionRuntimeEnabled() ? (isRowExpanded(row, i) ? 'true' : 'false') : null\"\n [ngClass]=\"getRowClasses(row)\"\n [ngStyle]=\"getRowNgStyle(row)\"\n [matTooltip]=\"getRowTooltip(row) || null\"\n [matTooltipDisabled]=\"!getRowTooltip(row)\"\n [matTooltipPosition]=\"getRowTooltipPosition(row)\"\n [matTooltipShowDelay]=\"getRowTooltipShowDelay(row)\"\n (click)=\"onRowClicked(row, i, $event)\"\n (dblclick)=\"onRowDoubleClicked(row, i)\"\n ></tr>\n @if (isRowExpansionRuntimeEnabled()) {\n <ng-container matColumnDef=\"_detail\">\n <td\n mat-cell\n *matCellDef=\"let row; let i = index\"\n class=\"pfx-expansion-detail-cell\"\n [attr.colspan]=\"displayedColumns.length\"\n >\n <section\n class=\"pfx-expansion-detail-panel\"\n [attr.id]=\"getRowExpansionDetailId(row, i)\"\n role=\"region\"\n [attr.aria-label]=\"getRowExpansionRegionAriaLabel(row, i)\"\n [attr.aria-busy]=\"getExpansionDetailViewState(row, i).status === 'loading' ? 'true' : 'false'\"\n >\n @let detailState = getExpansionDetailViewState(row, i);\n @if (detailState.status === 'loading') {\n <div class=\"pfx-expansion-detail-message\" role=\"status\" aria-live=\"polite\">\n Carregando detail schema...\n </div>\n } @else if (detailState.status !== 'ready') {\n <div\n class=\"pfx-expansion-detail-message pfx-expansion-detail-message--error\"\n role=\"alert\"\n aria-live=\"assertive\"\n aria-atomic=\"true\"\n >\n {{ detailState.message || 'Detail indispon\u00EDvel para esta linha.' }}\n </div>\n } @else {\n @if (getExpansionDetailLayout(detailState.schema) === 'tabs') {\n @let detailTabs = getExpansionDetailTabs(detailState.schema);\n @if (detailTabs.length) {\n <div class=\"pfx-expansion-detail-tabs\" role=\"tablist\" aria-label=\"Se\u00E7\u00F5es do detail\">\n @for (tab of detailTabs; track $index; let tabIndex = $index) {\n <button\n type=\"button\"\n class=\"pfx-expansion-detail-tab-btn\"\n role=\"tab\"\n [attr.id]=\"getExpansionDetailTabId(row, i, tab, tabIndex)\"\n [attr.aria-controls]=\"getExpansionDetailPanelId(row, i, tab, tabIndex)\"\n [attr.aria-selected]=\"isExpansionDetailTabActive(row, i, tab, tabIndex, detailTabs) ? 'true' : 'false'\"\n [attr.tabindex]=\"isExpansionDetailTabActive(row, i, tab, tabIndex, detailTabs) ? '0' : '-1'\"\n [class.is-active]=\"isExpansionDetailTabActive(row, i, tab, tabIndex, detailTabs)\"\n (click)=\"onExpansionDetailTabSelect(row, i, tab, tabIndex, $event)\"\n (keydown)=\"onExpansionDetailTabKeydown($event, row, i, tabIndex, detailTabs)\"\n >\n {{ getExpansionDetailNodeTitle(tab, 'Tab') }}\n </button>\n }\n </div>\n @for (tab of detailTabs; track $index; let tabIndex = $index) {\n @if (isExpansionDetailTabActive(row, i, tab, tabIndex, detailTabs)) {\n <div\n class=\"pfx-expansion-detail-tab-panel\"\n role=\"tabpanel\"\n [attr.id]=\"getExpansionDetailPanelId(row, i, tab, tabIndex)\"\n [attr.aria-labelledby]=\"getExpansionDetailTabId(row, i, tab, tabIndex)\"\n >\n @for (childNode of getExpansionDetailNodeChildren(tab); track $index) {\n <ng-container\n *ngTemplateOutlet=\"\n expansionDetailNodeTemplate;\n context: { $implicit: childNode, row: row, index: i }\n \"\n ></ng-container>\n }\n </div>\n }\n }\n } @else {\n <div class=\"pfx-expansion-detail-message\">\n Schema em layout tabs sem abas v\u00E1lidas.\n </div>\n }\n } @else {\n <div class=\"pfx-expansion-detail-stack\">\n @for (node of getExpansionDetailItems(detailState.schema); track $index) {\n <ng-container\n *ngTemplateOutlet=\"\n expansionDetailNodeTemplate;\n context: { $implicit: node, row: row, index: i }\n \"\n ></ng-container>\n }\n </div>\n }\n }\n\n <ng-template #expansionDetailNodeTemplate let-node let-row=\"row\" let-index=\"index\">\n @switch (getExpansionDetailNodeType(node)) {\n @case ('card') {\n <article class=\"pfx-expansion-node pfx-expansion-node-card\">\n <header class=\"pfx-expansion-node-card__header\">\n <h5 class=\"pfx-expansion-node-card__title\">\n {{ getExpansionDetailNodeTitle(node, 'Card') }}\n </h5>\n @if (node?.subtitle) {\n <p class=\"pfx-expansion-node-card__subtitle\">{{ node?.subtitle }}</p>\n }\n </header>\n @for (childNode of getExpansionDetailNodeChildren(node); track $index) {\n <ng-container\n *ngTemplateOutlet=\"\n expansionDetailNodeTemplate;\n context: { $implicit: childNode, row: row, index: index }\n \"\n ></ng-container>\n }\n </article>\n }\n @case ('value') {\n <div class=\"pfx-expansion-node pfx-expansion-node-value\">\n <span class=\"pfx-expansion-node-value__label\">\n {{ getExpansionDetailNodeTitle(node, 'Valor') }}\n </span>\n <strong class=\"pfx-expansion-node-value__content\">\n {{ getExpansionDetailValue(row, node) }}\n </strong>\n </div>\n }\n @case ('list') {\n <section class=\"pfx-expansion-node pfx-expansion-node-list\">\n <h6 class=\"pfx-expansion-node-list__title\">\n {{ getExpansionDetailNodeTitle(node, 'Lista') }}\n </h6>\n @let listItems = getExpansionDetailListItems(row, node);\n @if (listItems.length) {\n <ul>\n @for (entry of listItems; track $index) {\n <li>{{ entry }}</li>\n }\n </ul>\n } @else {\n <p class=\"pfx-expansion-node-placeholder\">Sem itens.</p>\n }\n </section>\n }\n @case ('richText') {\n <div\n class=\"pfx-expansion-node pfx-expansion-node-richtext\"\n [innerHTML]=\"getExpansionDetailRichText(node)\"\n ></div>\n }\n @case ('formRef') {\n <div class=\"pfx-expansion-node pfx-expansion-node-placeholder\">\n Formul\u00E1rio referenciado: <code>{{ node?.schemaId || node?.id || 'sem-id' }}</code>\n </div>\n }\n @case ('tableRef') {\n <div class=\"pfx-expansion-node pfx-expansion-node-placeholder\">\n Tabela referenciada: <code>{{ node?.schemaId || node?.id || 'sem-id' }}</code>\n </div>\n }\n @case ('chartRef') {\n <div class=\"pfx-expansion-node pfx-expansion-node-placeholder\">\n Gr\u00E1fico referenciado: <code>{{ node?.schemaId || node?.id || 'sem-id' }}</code>\n </div>\n }\n @case ('templateRef') {\n <div class=\"pfx-expansion-node pfx-expansion-node-placeholder\">\n Template referenciado: <code>{{ node?.id || node?.templateId || 'sem-id' }}</code>\n </div>\n }\n @case ('action') {\n <div class=\"pfx-expansion-node pfx-expansion-node-placeholder\">\n A\u00E7\u00E3o declarada: <code>{{ node?.id || node?.actionId || 'sem-id' }}</code>\n </div>\n }\n @case ('tab') {\n <div class=\"pfx-expansion-node pfx-expansion-node-placeholder\">\n Node <code>tab</code> fora de contexto de tabs.\n </div>\n }\n @default {\n <div class=\"pfx-expansion-node pfx-expansion-node-placeholder\">\n Node n\u00E3o suportado: <code>{{ getExpansionDetailNodeType(node) }}</code>\n </div>\n }\n }\n </ng-template>\n </section>\n </td>\n </ng-container>\n <tr\n mat-row\n *matRowDef=\"let row; columns: expansionDetailRowColumns; when: isExpansionDetailRow\"\n class=\"pfx-expansion-detail-row\"\n ></tr>\n }\n }\n</table>\n}\n\n<!-- Virtual rows path (header preserved above) -->\n@if (shouldRenderDataSurface() && !schemaError && !dataError && isVirtualized()) {\n <cdk-virtual-scroll-viewport\n class=\"ptable-viewport\"\n [itemSize]=\"getVirtItemHeight()\"\n [minBufferPx]=\"getVirtBufferSize() * getVirtItemHeight()\"\n [maxBufferPx]=\"getVirtBufferSize() * getVirtItemHeight() * 2\"\n [style.minHeight]=\"getVirtMinHeightHostStyle()\"\n >\n <table\n class=\"mat-mdc-table\"\n [ngClass]=\"getTableElevationClassName()\"\n [style.width]=\"getVirtualTableWidthStyle()\"\n >\n <tbody>\n <tr class=\"mat-mdc-row\"\n *cdkVirtualFor=\"let row of dataSource.data; let i = index; trackBy: trackByRow\"\n [class.pfx-row-selected]=\"selection.isSelected(row)\"\n [attr.aria-selected]=\"config.behavior?.selection?.enabled ? (selection.isSelected(row) ? 'true' : 'false') : null\"\n [ngClass]=\"getRowClasses(row)\"\n [ngStyle]=\"getRowNgStyle(row)\"\n [matTooltip]=\"getRowTooltip(row) || null\"\n [matTooltipDisabled]=\"!getRowTooltip(row)\"\n [matTooltipPosition]=\"getRowTooltipPosition(row)\"\n [matTooltipShowDelay]=\"getRowTooltipShowDelay(row)\"\n (click)=\"onRowClicked(row, i, $event)\"\n (dblclick)=\"onRowDoubleClicked(row, i)\">\n <!-- Selection column -->\n @if (config.behavior?.selection?.enabled) { <td class=\"mat-mdc-cell\">\n <mat-checkbox\n (click)=\"$event.stopPropagation()\"\n (change)=\"toggleRow(row)\"\n [checked]=\"selection.isSelected(row)\">\n </mat-checkbox>\n </td> }\n <!-- Data columns -->\n @for (column of visibleColumns; track column.field) {\n <td class=\"mat-mdc-cell\"\n [style.text-align]=\"getColumnTextAlignStyle(column)\"\n [style.width]=\"getColumnWidthStyle(column)\"\n [attr.style]=\"getColumnCellAttrStyle(column)\"\n [ngClass]=\"getCellClasses(row, column)\"\n [ngStyle]=\"getCellNgStyle(row, column)\">\n <div\n class=\"pfx-cell-content\"\n [ngClass]=\"getCellContentClasses(row, column)\"\n [ngStyle]=\"getCellContentNgStyle(row, column)\"\n >\n <ng-container [ngSwitch]=\"getEffectiveRendererType(row, column)\">\n <ng-container *ngSwitchCase=\"'icon'\">\n <mat-icon [color]=\"getIconColor(row, column) || null\"\n [ngStyle]=\"getIconStyle(row, column)\"\n [attr.aria-label]=\"getIconAriaLabel(row, column) || null\">\n {{ getIconName(row, column) }}\n </mat-icon>\n </ng-container>\n <ng-container *ngSwitchCase=\"'image'\">\n <img class=\"pfx-cell-image\"\n [src]=\"getImageSrc(row, column)\"\n [attr.alt]=\"getImageAlt(row, column) || ''\"\n [attr.loading]=\"getImageLazy(row, column) ? 'lazy' : null\"\n [style.width.px]=\"getImageWidth(row, column)\"\n [style.height.px]=\"getImageHeight(row, column)\"\n [class.shape-rounded]=\"getImageShape(row, column) === 'rounded'\"\n [class.shape-circle]=\"getImageShape(row, column) === 'circle'\"\n [style.object-fit]=\"getImageFit(row, column)\" />\n </ng-container>\n <ng-container *ngSwitchCase=\"'badge'\">\n <span class=\"pfx-badge\" [ngClass]=\"getBadgeClasses(row, column)\">\n @if (getBadgeIcon(row, column); as bi) { <mat-icon class=\"pfx-badge-icon\">{{ bi }}</mat-icon> }\n <span class=\"pfx-badge-text\">{{ getBadgeText(row, column) }}</span>\n </span>\n </ng-container>\n <ng-container *ngSwitchDefault>\n {{ getCellValue(row, column) }}\n </ng-container>\n </ng-container>\n </div>\n </td>\n }\n\n <!-- Actions column -->\n @if (config.actions?.row?.enabled) {\n <td class=\"mat-mdc-cell praxis-actions-cell\" [class.dense]=\"dense\" [style.width]=\"getRowActionsWidthStyle()\">\n <div class=\"praxis-actions-cell__content\">\n @if (config.actions?.row?.display === 'icons' || !config.actions?.row?.display) {\n <ng-container *ngFor=\"let a of getInlineRowActions(row); trackBy: trackAction\">\n <button mat-icon-button class=\"praxis-icon-btn\"\n [disabled]=\"isActionDisabled(a, row)\"\n (click)=\"onRowAction(getActionId(a), row, $event)\"\n [matTooltip]=\"a.label || getActionId(a)\"\n matTooltipPosition=\"above\"\n matTooltipClass=\"praxis-tooltip\"\n [attr.aria-label]=\"a.label || getActionId(a)\"\n [color]=\"a.color || null\">\n <mat-icon [praxisIcon]=\"a.icon\"></mat-icon>\n </button>\n </ng-container>\n }\n @if (config.actions?.row?.display === 'buttons') {\n <ng-container *ngFor=\"let a of getInlineRowActions(row); trackBy: trackAction\">\n <button mat-flat-button class=\"praxis-row-btn\"\n [disabled]=\"isActionDisabled(a, row)\"\n (click)=\"onRowAction(getActionId(a), row, $event)\"\n [attr.aria-label]=\"a.label || getActionId(a)\"\n [color]=\"a.color || null\">\n <mat-icon [praxisIcon]=\"a.icon\"></mat-icon>\n <span>{{ a.label || getActionId(a) }}</span>\n </button>\n </ng-container>\n }\n @if (hasOverflowRowActions(row)) {\n <button mat-icon-button class=\"praxis-icon-btn praxis-more-btn\"\n [matMenuTriggerFor]=\"rowMoreMenuV\"\n [color]=\"getRowMenuButtonColor() || null\"\n aria-label=\"Mais a\u00E7\u00F5es\">\n <mat-icon [praxisIcon]=\"getRowMenuIcon()\"></mat-icon>\n </button>\n }\n <mat-menu #rowMoreMenuV=\"matMenu\" xPosition=\"before\">\n <ng-container *ngFor=\"let a of getOverflowRowActions(row); trackBy: trackAction\">\n <button mat-menu-item (click)=\"onRowAction(getActionId(a), row, $event)\" [disabled]=\"isActionDisabled(a, row)\">\n <mat-icon [color]=\"a.color || null\" [praxisIcon]=\"a.icon\"></mat-icon>\n <span>{{ a.label || getActionId(a) }}</span>\n </button>\n </ng-container>\n </mat-menu>\n </div>\n </td>\n }\n </tr>\n </tbody>\n </table>\n </cdk-virtual-scroll-viewport>\n}\n\n</div>\n@if (\n shouldRenderDataSurface()\n && !schemaError\n && !dataError\n && shouldRenderFloatingBulkActions()\n && getFloatingBulkActions().length\n && !shouldHideFloatingBulkActions()\n) {\n <div [class]=\"'praxis-floating-bulk-actions ' + getFloatingBulkPositionClass()\">\n @for (action of getFloatingBulkActions(); track getActionId(action)) {\n <button\n mat-mini-fab\n [color]=\"action.color || 'primary'\"\n [disabled]=\"isFloatingBulkActionDisabled(action)\"\n (click)=\"onToolbarAction({ action: getActionId(action), actionConfig: action })\"\n [attr.aria-label]=\"action.label || getActionId(action)\"\n [matTooltip]=\"action.label || getActionId(action)\"\n matTooltipPosition=\"left\"\n >\n <mat-icon [praxisIcon]=\"action.icon || 'done_all'\"></mat-icon>\n </button>\n }\n </div>\n}\n<!-- Barra de a\u00E7\u00F5es no rodap\u00E9 (opcional) -->\n@if (shouldRenderDataSurface() && !schemaError && !dataError && showToolbar && shouldRenderFooterToolbar()) {\n <praxis-table-toolbar\n [config]=\"config\"\n [backgroundColor]=\"getToolbarActionsBackgroundColor()\"\n [style.--pfx-filter-h]=\"getToolbarLayoutHeightHostStyle()\"\n [class.footer-flat]=\"hasBottomPaginator()\"\n class=\"praxis-toolbar-footer\"\n placement=\"footer\"\n [showMain]=\"shouldShowFooterToolbarMain()\"\n [showEndActions]=\"shouldShowFooterToolbarEndActions()\"\n [showReset]=\"shouldShowFooterToolbarReset()\"\n [showActionsGroup]=\"shouldShowToolbarActionsBottom()\"\n [showMobileActions]=\"shouldShowToolbarActionsBottom()\"\n [dslContext]=\"getToolbarDslContext()\"\n [dslFunctionRegistry]=\"dslFunctionRegistry\"\n (toolbarAction)=\"onToolbarAction($event)\"\n >\n <praxis-filter\n *ngIf=\"shouldShowFooterToolbarMain() && shouldRenderAdvancedFilter()\"\n advancedFilter\n [resourcePath]=\"getAdvancedFilterResourcePath()\"\n [filterId]=\"tableId\"\n [formId]=\"tableId\"\n [persistenceKey]=\"getAdvancedFilterPersistenceKey()\"\n [fieldMetadata]=\"getAdvancedFilterFieldMetadata()\"\n [editModeEnabled]=\"editModeEnabled\"\n [alwaysVisibleFields]=\"config.behavior?.filtering?.advancedFilters?.settings?.alwaysVisibleFields\"\n [alwaysVisibleFieldMetadataOverrides]=\"config.behavior?.filtering?.advancedFilters?.settings?.alwaysVisibleFieldMetadataOverrides ?? {}\"\n [selectedFieldIds]=\"config.behavior?.filtering?.advancedFilters?.settings?.selectedFieldIds ?? []\"\n [allowSaveTags]=\"config.behavior?.filtering?.advancedFilters?.settings?.allowSaveTags\"\n [changeDebounceMs]=\"config.behavior?.filtering?.advancedFilters?.settings?.changeDebounceMs ?? 300\"\n [i18n]=\"getFilterI18n()\"\n [mode]=\"'filter'\"\n [showFilterSettings]=\"editModeEnabled\"\n (submit)=\"onAdvancedFilterSubmit($event)\"\n (clear)=\"onAdvancedFilterClear()\"\n ></praxis-filter>\n <ng-container *ngIf=\"shouldShowFooterToolbarMain() && shouldRenderAdvancedFilter()\">\n <ng-content select=\"[advancedFilter]\"></ng-content>\n </ng-container>\n <ng-container *ngIf=\"shouldShowFooterToolbarMain() && shouldRenderAdvancedFilter()\">\n <ng-content select=\"[toolbar]\"></ng-content>\n </ng-container>\n @if (shouldShowFooterToolbarMain() && shouldRenderAdvancedFilter()) {\n @defer (on idle) {\n @if (aiAdapter) {\n <praxis-ai-assistant\n [adapter]=\"aiAdapter\"\n end-actions\n ></praxis-ai-assistant>\n }\n }\n }\n <button\n *ngIf=\"shouldShowFooterToolbarMain() && shouldRenderAdvancedFilter() && editModeEnabled\"\n end-actions\n mat-icon-button\n color=\"primary\"\n data-role=\"table-settings\"\n data-testid=\"table-settings-trigger\"\n (click)=\"openTableSettings()\"\n aria-label=\"Configura\u00E7\u00F5es\"\n [matBadge]=\"schemaOutdated ? '!' : ''\"\n [matBadgeHidden]=\"!schemaOutdated\"\n matBadgeColor=\"warn\"\n matBadgeSize=\"small\"\n matBadgePosition=\"above after\"\n [matTooltip]=\"schemaOutdated ? 'Schema do servidor mudou \u2014 Reconciliar' : 'Configura\u00E7\u00F5es'\"\n matTooltipPosition=\"below\"\n >\n <mat-icon>settings</mat-icon>\n </button>\n </praxis-table-toolbar>\n}\n<!-- Paginadores (top/bottom) -->\n@if (shouldRenderDataSurface() && !schemaError && !dataError && getPaginationEnabled() && (config.behavior?.pagination?.position === 'top' || config.behavior?.pagination?.position === 'both')) {\n <mat-paginator\n [length]=\"getPaginationLength()\"\n [pageSize]=\"getPaginationPageSize()\"\n [pageSizeOptions]=\"getPaginationPageSizeOptions()\"\n [showFirstLastButtons]=\"getPaginationShowFirstLast()\"\n (page)=\"onPageChange($event)\"\n [class.compact]=\"config.behavior?.pagination?.style === 'compact'\"\n >\n </mat-paginator>\n}\n\n@if (shouldRenderDataSurface() && !schemaError && !dataError && getPaginationEnabled() && (config.behavior?.pagination?.position === 'bottom' || config.behavior?.pagination?.position === 'both' || !config.behavior?.pagination?.position)) {\n <mat-paginator\n [length]=\"getPaginationLength()\"\n [pageSize]=\"getPaginationPageSize()\"\n [pageSizeOptions]=\"getPaginationPageSizeOptions()\"\n [showFirstLastButtons]=\"getPaginationShowFirstLast()\"\n (page)=\"onPageChange($event)\"\n [class.compact]=\"config.behavior?.pagination?.style === 'compact'\"\n [class.footer-stack]=\"shouldShowToolbarActionsBottom()\"\n >\n </mat-paginator>\n}\n", styles: ["@charset \"UTF-8\";table{width:100%}.praxis-visually-hidden-status{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}.praxis-column-reorder-status{margin:8px 0;padding:10px 12px;border-radius:8px;border:1px solid var(--p-table-border-color);background:var(--p-table-row-hover-bg);color:var(--p-table-header-fg);font-size:12px;line-height:1.4;box-shadow:0 4px 12px #00000014;animation:pfx-column-reorder-status-in var(--p-table-drag-status-enter-duration, .18s) var(--p-table-motion-easing, cubic-bezier(0, 0, .2, 1))}@keyframes pfx-column-reorder-status-in{0%{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:translateY(0)}}.praxis-actions-cell{height:100%;padding-inline:12px;white-space:nowrap}.pfx-expansion-col-header,.pfx-expansion-col-cell{width:52px;min-width:52px;text-align:center}.pfx-expansion-toggle{width:40px;height:40px}.pfx-expansion-toggle:focus-visible{outline:2px solid var(--md-sys-color-primary);outline-offset:2px}.pfx-expansion-detail-row{background:var(--md-sys-color-surface-container-low)}.pfx-expansion-detail-cell{padding:0!important;border-bottom:1px solid var(--p-table-border-color)}.pfx-expansion-detail-panel{padding:12px 16px;border-left:3px solid var(--md-sys-color-primary)}.pfx-expansion-detail-schema{margin:0;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:12px;line-height:1.4;white-space:pre-wrap;word-break:break-word;color:var(--md-sys-color-on-surface-variant)}.pfx-expansion-detail-message{font-size:13px;color:var(--md-sys-color-on-surface-variant)}.pfx-expansion-detail-message--error{color:var(--md-sys-color-error)}.pfx-expansion-detail-stack{display:grid;gap:10px}.pfx-expansion-detail-tabs{display:flex;flex-wrap:wrap;gap:8px;margin-bottom:10px}.pfx-expansion-detail-tab-btn{border:1px solid var(--p-table-border-color);background:var(--md-sys-color-surface);color:var(--md-sys-color-on-surface);border-radius:999px;padding:6px 12px;font-size:12px;line-height:1.2;cursor:pointer}.pfx-expansion-detail-tab-btn.is-active{border-color:var(--md-sys-color-primary);color:var(--md-sys-color-primary);font-weight:600}.pfx-expansion-detail-tab-btn:focus-visible{outline:2px solid var(--md-sys-color-primary);outline-offset:2px}.pfx-expansion-detail-tab-panel{display:grid;gap:10px}.pfx-expansion-node{border:1px solid var(--p-table-border-color);border-radius:8px;padding:10px 12px;background:var(--md-sys-color-surface)}.pfx-expansion-node-card__header{margin-bottom:8px}.pfx-expansion-node-card__title{margin:0;font-size:14px;line-height:1.3}.pfx-expansion-node-card__subtitle{margin:4px 0 0;font-size:12px;color:var(--md-sys-color-on-surface-variant)}.pfx-expansion-node-value{display:flex;align-items:baseline;gap:8px}.pfx-expansion-node-value__label{color:var(--md-sys-color-on-surface-variant);font-size:12px}.pfx-expansion-node-value__content{font-size:14px}.pfx-expansion-node-list__title{margin:0 0 6px;font-size:13px}.pfx-expansion-node-list ul{margin:0;padding-left:18px}.pfx-expansion-node-richtext :where(p,ul,ol,h1,h2,h3,h4,h5,h6){margin-top:0;margin-bottom:8px}.pfx-expansion-node-placeholder{font-size:12px;color:var(--md-sys-color-on-surface-variant)}:host.density-compact{--p-header-padding: 8px 12px;--p-cell-padding: 8px 12px;--p-actions-btn-size: 32px;--p-actions-icon-size: 18px}:host.density-comfortable{--p-header-padding: 12px 16px;--p-cell-padding: 12px 16px;--p-actions-btn-size: 40px;--p-actions-icon-size: 22px}:host.density-spacious{--p-header-padding: 16px 20px;--p-cell-padding: 16px 20px;--p-actions-btn-size: 44px;--p-actions-icon-size: 24px}:host.density-compact ::ng-deep .mat-mdc-cell{padding:var(--p-cell-padding, 8px 12px)}:host.density-comfortable ::ng-deep .mat-mdc-cell{padding:var(--p-cell-padding, 12px 16px)}:host.density-spacious ::ng-deep .mat-mdc-cell{padding:var(--p-cell-padding, 16px 20px)}:host.density-compact .praxis-actions-cell{padding-inline:8px}:host.density-spacious .praxis-actions-cell{padding-inline:16px}.praxis-actions-cell__content{display:flex;align-items:center;justify-content:flex-end;gap:8px;width:100%}.praxis-actions-cell.dense .praxis-actions-cell__content{gap:6px}.praxis-icon-btn{width:var(--p-actions-btn-size, 40px);height:var(--p-actions-btn-size, 40px);border:0;background:transparent;padding:0;display:inline-flex;align-items:center;justify-content:center;border-radius:9999px;cursor:pointer;--mat-icon-button-state-layer-size: var(--p-actions-btn-size, 40px)}.praxis-icon-btn:hover{background:var(--md-sys-color-surface-variant)}.praxis-icon-btn:focus-visible{outline:2px solid var(--md-sys-color-primary);outline-offset:2px}.praxis-icon-btn mat-icon,.praxis-icon-btn .mat-icon{font-size:var(--p-actions-icon-size, 22px);width:var(--p-actions-icon-size, 22px);height:var(--p-actions-icon-size, 22px);line-height:var(--p-actions-icon-size, 22px)}.praxis-more-btn{width:var(--p-actions-more-btn-size, var(--p-actions-btn-size, 40px));height:var(--p-actions-more-btn-size, var(--p-actions-btn-size, 40px));--mat-icon-button-state-layer-size: var(--p-actions-more-btn-size, var(--p-actions-btn-size, 40px));background-image:var(--p-actions-more-btn-gradient, none);background-size:100% 100%;background-repeat:no-repeat}.praxis-more-btn mat-icon,.praxis-more-btn .mat-icon{font-size:var(--p-actions-more-icon-size, var(--p-actions-icon-size, 22px));width:var(--p-actions-more-icon-size, var(--p-actions-icon-size, 22px));height:var(--p-actions-more-icon-size, var(--p-actions-icon-size, 22px));line-height:var(--p-actions-more-icon-size, var(--p-actions-icon-size, 22px));color:var(--p-actions-more-icon-color);background-image:var(--p-actions-more-icon-gradient, none);-webkit-background-clip:text;background-clip:text}.praxis-icon-btn.destructive mat-icon{color:var(--md-sys-color-error)}.mat-mdc-tooltip.praxis-tooltip{margin-top:-8px;margin-bottom:8px}.spacer{flex:1 1 auto}.praxis-table-header{display:flex;flex-wrap:wrap;align-items:flex-start;gap:8px;margin:16px 0 12px;width:100%;clear:both;position:relative}.praxis-table-header.stacked{margin:0}.praxis-table-header>praxis-table-toolbar{flex:1 0 100%}.praxis-floating-bulk-actions{position:fixed;z-index:1001;display:inline-flex;align-items:center;gap:8px;padding:8px;border-radius:999px;background:var(--md-sys-color-surface-container-highest);box-shadow:0 8px 20px #00000029}.praxis-floating-bulk-actions.pos-bottom-right{right:20px;bottom:20px}.praxis-floating-bulk-actions.pos-bottom-left{left:20px;bottom:20px}.praxis-floating-bulk-actions.pos-top-right{right:20px;top:20px}.praxis-floating-bulk-actions.pos-top-left{left:20px;top:20px}@media(max-width:768px){.praxis-floating-bulk-actions{gap:6px;padding:6px}.praxis-floating-bulk-actions.pos-bottom-right{right:12px;left:auto;bottom:12px}.praxis-floating-bulk-actions.pos-bottom-left{left:12px;right:auto;bottom:12px}.praxis-floating-bulk-actions.pos-top-right{right:12px;left:auto;top:12px}.praxis-floating-bulk-actions.pos-top-left{left:12px;right:auto;top:12px}}:host{display:block;width:100%;min-width:0;max-width:100%;--pfx-toolbar-pad-y: 6px;--pfx-toolbar-pad-x: 12px;--p-table-bg: var(--md-sys-color-surface-container-highest);--p-table-text-color: var(--md-sys-color-on-surface);--p-table-header-bg: var(--md-sys-color-surface-container-highest);--p-table-header-fg: var(--md-sys-color-on-surface);--p-table-border-color: var(--md-sys-color-outline-variant);--p-table-row-even-bg: var(--md-sys-color-surface-container);--p-table-row-hover-bg: var(--md-sys-color-surface-container-high);--p-table-row-selected-bg: var(--md-sys-color-primary-container);--p-table-badge-soft-primary-bg: var(--md-sys-color-primary-container);--p-table-badge-soft-primary-fg: var(--md-sys-color-on-primary-container);--p-table-badge-soft-accent-bg: var(--md-sys-color-secondary-container);--p-table-badge-soft-accent-fg: var(--md-sys-color-on-secondary-container);--p-table-badge-soft-warn-bg: var(--md-sys-color-error-container);--p-table-badge-soft-warn-fg: var(--md-sys-color-on-error-container);--p-table-state-success-bg: var(--md-sys-color-tertiary-container);--p-table-state-success-fg: var(--md-sys-color-on-tertiary-container);--p-table-state-warning-bg: var(--md-sys-color-secondary-container);--p-table-state-warning-fg: var(--md-sys-color-on-secondary-container);--p-table-state-danger-bg: var(--md-sys-color-error-container);--p-table-state-danger-fg: var(--md-sys-color-on-error-container);--p-table-state-highlight-bg: var(--md-sys-color-primary-container);--p-table-state-highlight-fg: var(--md-sys-color-on-primary-container);--p-table-drag-handle-size: 14px;--p-table-drag-handle-color: var(--md-sys-color-on-surface-variant);--p-table-drag-handle-hover-color: var(--md-sys-color-on-surface);--p-table-drag-handle-base-opacity: 0;--p-table-drag-handle-visible-opacity: .72;--p-table-drag-handle-active-opacity: 1;--p-table-drag-handle-transition-duration: .16s;--p-table-reorder-transition-duration: .16s;--p-table-drag-preview-scale: 1.01;--p-table-drag-status-enter-duration: .18s;--p-table-drag-preview-shadow: 0 14px 32px rgba(0, 0, 0, .28), 0 0 0 1px var(--p-table-border-color)}:host ::ng-deep .mat-mdc-table{background:var(--p-table-bg);color:var(--p-table-text-color);border-radius:12px 12px 0 0;width:100%;box-shadow:var(--p-table-surface-shadow);transition:box-shadow var(--p-table-selection-transition-duration, .18s) var(--p-table-motion-easing, cubic-bezier(0, 0, .2, 1))}:host ::ng-deep .mat-mdc-table:hover{box-shadow:var(--p-table-surface-shadow-hover, var(--p-table-surface-shadow))}:host ::ng-deep .mat-mdc-table.table-stack-top{border-top-left-radius:0;border-top-right-radius:0}:host ::ng-deep .praxis-toolbar-footer{border:0 solid var(--p-table-border-color);border-top:0;border-radius:0;background:var(--p-table-bg)}:host ::ng-deep .mat-mdc-paginator.footer-stack{border-top-left-radius:0;border-top-right-radius:0;border-top:0}:host ::ng-deep .mat-mdc-paginator.footer-stack .mat-mdc-paginator-container{padding:8px 12px}:host [data-role=table-settings].mat-mdc-icon-button{--mdc-icon-button-icon-color: var(--md-sys-color-primary);color:var(--md-sys-color-primary)}.pfx-link{color:var(--md-sys-color-primary);text-decoration:underline;cursor:pointer}.pfx-chip{display:inline-flex;align-items:center;gap:4px;padding:2px 8px;border-radius:10px;font-size:12px;line-height:1;border:1px solid transparent}.pfx-chip-icon{font-size:14px;width:14px;height:14px}.pfx-chip--outlined{background:transparent;border-color:var(--md-sys-color-outline-variant);color:var(--md-sys-color-on-surface)}.pfx-chip--filled-primary{background:var(--md-sys-color-primary);color:var(--md-sys-color-on-primary)}.pfx-chip--filled-accent{background:var(--md-sys-color-secondary);color:var(--md-sys-color-on-secondary)}.pfx-chip--filled-warn{background:var(--md-sys-color-error);color:var(--md-sys-color-on-error)}.pfx-chip--soft-primary{background:var(--p-table-badge-soft-primary-bg);color:var(--p-table-badge-soft-primary-fg)}.pfx-chip--soft-accent{background:var(--p-table-badge-soft-accent-bg);color:var(--p-table-badge-soft-accent-fg)}.pfx-chip--soft-warn{background:var(--p-table-badge-soft-warn-bg);color:var(--p-table-badge-soft-warn-fg)}.pfx-progress{position:relative;width:100%;max-width:140px;height:8px;background:var(--md-sys-color-surface-container-highest);border-radius:4px;overflow:hidden;display:inline-block;vertical-align:middle}.pfx-progress-bar{height:100%;background:var(--md-sys-color-primary);transition:width .2s ease}.pfx-progress-label{margin-left:8px;font-size:12px;opacity:.8;display:inline-block;vertical-align:middle}.pfx-avatar{display:inline-flex;align-items:center;justify-content:center;background:var(--md-sys-color-surface-container);color:var(--md-sys-color-on-surface);border-radius:4px;overflow:hidden;font-weight:600}.pfx-avatar.shape-rounded{border-radius:8px}.pfx-avatar.shape-circle{border-radius:999px}.pfx-avatar--initials{text-transform:uppercase;font-size:12px}.pfx-cell-compose{display:inline-flex;align-items:center;gap:6px}.pfx-cell-compose.dir-col{flex-direction:column;align-items:stretch}.pfx-cell-compose.align-start{justify-content:flex-start}.pfx-cell-compose.align-center{justify-content:center}.pfx-cell-compose.align-end{justify-content:flex-end}.pfx-cell-compose.wrap{flex-wrap:wrap}.pfx-cell-compose.ellipsis{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.px-scroll-viewport{width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch;overscroll-behavior-x:contain}.px-scroll-viewport.scroll-none{overflow-x:visible}.px-scroll-viewport.scroll-auto ::ng-deep .mat-mdc-table{width:max-content;min-width:100%}.px-scroll-viewport.scroll-wrap ::ng-deep .mat-mdc-header-cell,.px-scroll-viewport.scroll-wrap ::ng-deep .mat-mdc-cell{white-space:normal;text-overflow:initial}.px-scroll-viewport.scroll-wrap ::ng-deep .mat-mdc-table{width:100%}:host ::ng-deep .mat-mdc-header-row{position:sticky;top:0;z-index:1;background:var(--p-table-header-bg);color:var(--p-table-header-fg);box-shadow:var(--p-table-header-shadow, 0 1px 0 var(--p-table-border-color));border-bottom:1px solid var(--p-table-border-color)}:host ::ng-deep .mat-mdc-header-cell,:host ::ng-deep .mat-sort-header-content,:host ::ng-deep .mat-mdc-header-row .mat-icon{color:var(--p-table-header-fg)!important;font-weight:600}:host ::ng-deep .mat-mdc-header-cell.mat-sort-header-sorted .mat-sort-header-arrow,:host ::ng-deep .mat-mdc-header-cell:hover .mat-sort-header-arrow{color:var(--p-table-header-fg)!important}:host ::ng-deep .mat-mdc-header-cell.mat-sort-header-sorted .mat-sort-header-arrow .mat-sort-header-indicator,:host ::ng-deep .mat-mdc-header-cell.mat-sort-header-sorted .mat-sort-header-arrow .mat-sort-header-stem,:host ::ng-deep .mat-mdc-header-cell.mat-sort-header-sorted .mat-sort-header-arrow .mat-sort-header-pointer,:host ::ng-deep .mat-mdc-header-cell.mat-sort-header-sorted .mat-sort-header-arrow .mat-sort-header-pointer-left,:host ::ng-deep .mat-mdc-header-cell.mat-sort-header-sorted .mat-sort-header-arrow .mat-sort-header-pointer-right{border-color:var(--p-table-header-fg)!important;background:var(--p-table-header-fg)!important}:host ::ng-deep .mat-mdc-header-cell{padding:var(--p-header-padding, 12px 16px)!important;font-size:var(--p-header-font-size, inherit);font-weight:var(--p-header-font-weight, 600);letter-spacing:var(--p-header-letter-spacing, normal);text-transform:var(--p-header-text-transform, none);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}:host ::ng-deep .pfx-column-drag-enabled .mat-mdc-header-cell.praxis-header-draggable .mat-sort-header-container{display:flex;align-items:center;width:100%;gap:8px;cursor:inherit}:host ::ng-deep .pfx-column-drag-enabled .mat-mdc-header-cell.praxis-header-draggable{-webkit-user-select:none;user-select:none;cursor:grab}:host ::ng-deep .pfx-column-drag-enabled .mat-mdc-header-cell.praxis-header-draggable.cdk-drag-dragging{cursor:grabbing}:host ::ng-deep .pfx-column-drag-enabled .mat-mdc-header-cell.praxis-header-draggable .mat-sort-header-content{display:inline-flex;align-items:center;gap:8px;flex:1 1 auto;min-width:0}:host ::ng-deep .pfx-column-drag-enabled .mat-mdc-header-cell .praxis-header-label{display:inline-flex;align-items:center;flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis}:host ::ng-deep .pfx-column-drag-enabled .mat-mdc-header-cell .praxis-column-drag-handle{-webkit-appearance:none;appearance:none;border:0;background:transparent;color:var(--p-table-drag-handle-color);width:var(--p-table-drag-handle-size);min-width:var(--p-table-drag-handle-size);height:var(--p-table-drag-handle-size);padding:0;display:inline-flex;align-items:center;justify-content:center;border-radius:0;cursor:inherit;pointer-events:none;touch-action:none;opacity:var(--p-table-drag-handle-base-opacity, 0);transform:none;transition:opacity var(--p-table-drag-handle-transition-duration, .16s) var(--p-table-motion-easing, cubic-bezier(0, 0, .2, 1)),color var(--p-table-drag-handle-transition-duration, .16s) var(--p-table-motion-easing, cubic-bezier(0, 0, .2, 1))}:host ::ng-deep .pfx-column-drag-enabled .mat-mdc-header-cell.praxis-header-draggable:hover .praxis-column-drag-handle,:host ::ng-deep .pfx-column-drag-enabled .mat-mdc-header-cell.praxis-header-draggable:focus-within .praxis-column-drag-handle{opacity:var(--p-table-drag-handle-visible-opacity, .72);color:var(--p-table-drag-handle-hover-color, var(--p-table-drag-handle-color))}:host ::ng-deep .pfx-column-drag-enabled .mat-mdc-header-cell .praxis-column-drag-handle:active{opacity:var(--p-table-drag-handle-active-opacity, 1);cursor:grabbing}:host ::ng-deep .pfx-column-drag-enabled .mat-mdc-header-cell .praxis-column-drag-handle .mat-icon{font-size:14px;width:14px;height:14px;line-height:14px;transition:transform .18s var(--p-table-motion-easing, cubic-bezier(0, 0, .2, 1))}:host ::ng-deep .pfx-column-drag-enabled .mat-mdc-header-cell.praxis-header-draggable:hover .praxis-column-drag-handle .mat-icon{transform:none}:host ::ng-deep .pfx-column-drag-indicator .cdk-drop-list-dragging .mat-mdc-header-cell:not(.cdk-drag-placeholder){transition:transform var(--p-table-reorder-transition-duration, .18s) var(--p-table-motion-easing, cubic-bezier(0, 0, .2, 1))}:host ::ng-deep .pfx-column-drag-indicator .mat-mdc-header-cell.cdk-drag-animating{transition:transform var(--p-table-reorder-transition-duration, .16s) var(--p-table-motion-easing, cubic-bezier(0, 0, .2, 1))}.pfx-column-drag-preview{box-sizing:border-box;border-radius:10px;border:1px solid var(--p-table-border-color);background:linear-gradient(135deg,var(--p-table-header-bg) 0%,var(--p-table-row-hover-bg) 100%);color:var(--p-table-header-fg);box-shadow:var(--p-table-drag-preview-shadow);transform:scale(var(--p-table-drag-preview-scale, 1.01));pointer-events:none;z-index:1000}.pfx-column-drag-preview .praxis-column-drag-handle,.pfx-column-drag-preview .mat-sort-header-arrow,.pfx-column-drag-preview .mat-sort-header-indicator,.pfx-column-drag-preview .mat-sort-header-stem,.pfx-column-drag-preview .mat-sort-header-pointer,.pfx-column-drag-preview .mat-sort-header-pointer-left,.pfx-column-drag-preview .mat-sort-header-pointer-right{display:none!important}.pfx-column-drag-preview .mat-sort-header-container{padding-right:0!important}.pfx-column-drag-preview .mat-sort-header-content,.pfx-column-drag-preview .praxis-header-label{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}:host ::ng-deep .pfx-column-drag-indicator .cdk-drag-placeholder{opacity:1;border:1px dashed var(--p-table-border-color);background:var(--p-table-row-hover-bg)}:host ::ng-deep .pfx-column-drag-indicator .cdk-drag-placeholder *{opacity:0}:host ::ng-deep .pfx-column-drag-indicator .mat-mdc-header-cell.cdk-drag-dragging{opacity:.58}@media(prefers-reduced-motion:reduce){:host ::ng-deep .pfx-column-drag-indicator .cdk-drop-list-dragging .mat-mdc-header-cell:not(.cdk-drag-placeholder){transition:none}:host ::ng-deep .pfx-column-drag-enabled .mat-mdc-header-cell .praxis-column-drag-handle,:host ::ng-deep .pfx-column-drag-enabled .mat-mdc-header-cell .praxis-column-drag-handle .mat-icon,.pfx-column-drag-preview{transition:none;transform:none}.praxis-column-reorder-status{animation:none}:host ::ng-deep .mat-mdc-row{transition:none}:host ::ng-deep .mat-mdc-table{transition:none}}.praxis-actions-header{text-align:right}.praxis-actions-header.align-start{text-align:left}.praxis-actions-header.align-center{text-align:center}.praxis-actions-header.align-end{text-align:right}.praxis-actions-header .praxis-actions-header__content{display:inline-flex;align-items:center;gap:var(--p-actions-header-gap, 6px);color:var(--p-actions-header-color, inherit)}.praxis-actions-header .praxis-actions-header__content .mat-icon{font-size:18px;width:18px;height:18px;line-height:18px}:host ::ng-deep .mat-mdc-header-cell .mat-sort-header-container{padding-right:20px}:host ::ng-deep .pfx-column-drag-enabled .mat-mdc-header-cell.praxis-header-draggable .mat-sort-header-container{padding-right:12px}@media(pointer:coarse){:host{--p-table-drag-handle-size: 18px;--p-table-drag-handle-base-opacity: .56;--p-table-drag-handle-visible-opacity: .92}}:host ::ng-deep .mat-mdc-cell{color:var(--p-table-text-color);font-size:var(--p-cell-font-size, inherit);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}:host ::ng-deep .mat-mdc-cell .pfx-cell-content,:host ::ng-deep .mat-cell .pfx-cell-content{display:inline-flex;align-items:center;gap:6px;width:100%;min-width:0;overflow:hidden}:host ::ng-deep .pfx-cell-content.pfx-cell-anim{animation-duration:var(--pfx-cell-anim-duration, .8s);animation-delay:var(--pfx-cell-anim-delay, 0ms);animation-fill-mode:both;animation-timing-function:ease-in-out}:host ::ng-deep .pfx-cell-content.pfx-cell-anim.pfx-cell-anim--once{animation-iteration-count:1}:host ::ng-deep .pfx-cell-content.pfx-cell-anim.pfx-cell-anim--loop{animation-iteration-count:infinite}:host ::ng-deep .pfx-cell-content.pfx-cell-anim.pfx-cell-anim--count{animation-iteration-count:var(--pfx-cell-anim-iteration-count, 1)}:host ::ng-deep .pfx-cell-content.pfx-cell-anim.pfx-cell-anim--on-hover{animation-play-state:paused}:host ::ng-deep .mat-mdc-cell:hover .pfx-cell-content.pfx-cell-anim.pfx-cell-anim--on-hover,:host ::ng-deep .mat-cell:hover .pfx-cell-content.pfx-cell-anim.pfx-cell-anim--on-hover{animation-play-state:running}:host ::ng-deep .pfx-cell-content.pfx-cell-anim.pfx-cell-anim--pulse{animation-name:pfx-cell-pulse}:host ::ng-deep .pfx-cell-content.pfx-cell-anim.pfx-cell-anim--blink{animation-name:pfx-cell-blink}:host ::ng-deep .pfx-cell-content.pfx-cell-anim.pfx-cell-anim--grow{animation-name:pfx-cell-grow}:host ::ng-deep .pfx-cell-content.pfx-cell-anim.pfx-cell-anim--fade{animation-name:pfx-cell-fade}:host ::ng-deep .pfx-cell-content.pfx-cell-anim.pfx-cell-anim--slide-in{animation-name:pfx-cell-slide-in}:host ::ng-deep .pfx-cell-content.pfx-cell-anim.pfx-cell-anim--border-pulse{animation-name:pfx-cell-border-pulse}@keyframes pfx-cell-pulse{0%{transform:scale(1)}50%{transform:scale(var(--pfx-cell-anim-scale-peak, 1.015))}to{transform:scale(1)}}@keyframes pfx-cell-blink{0%,49%{opacity:1}50%,to{opacity:var(--pfx-cell-anim-min-opacity, .35)}}@keyframes pfx-cell-grow{0%{transform:scale(.985)}to{transform:scale(1)}}@keyframes pfx-cell-fade{0%{opacity:0}to{opacity:1}}@keyframes pfx-cell-slide-in{0%{opacity:0;transform:translateY(var(--pfx-cell-anim-slide-distance, 4px))}to{opacity:1;transform:translateY(0)}}@keyframes pfx-cell-border-pulse{0%,to{box-shadow:inset 0 0 rgba(var(--pfx-cell-anim-border-rgb, 25, 118, 210),0)}50%{box-shadow:inset 0 0 0 2px rgba(var(--pfx-cell-anim-border-rgb, 25, 118, 210),var(--pfx-cell-anim-border-strength, .3))}}@media(prefers-reduced-motion:reduce){:host ::ng-deep .pfx-cell-content.pfx-cell-anim{animation:none!important}}:host ::ng-deep .mat-mdc-row:hover{background:var(--p-table-row-hover-bg)}:host ::ng-deep .mat-mdc-row{transition:background-color var(--p-table-hover-transition-duration, .18s) var(--p-table-motion-easing, cubic-bezier(0, 0, .2, 1)),box-shadow var(--p-table-selection-transition-duration, .18s) var(--p-table-motion-easing, cubic-bezier(0, 0, .2, 1))}:host ::ng-deep .mat-mdc-row.pfx-row-anim{animation-duration:var(--pfx-row-anim-duration, .8s);animation-delay:var(--pfx-row-anim-delay, 0ms);animation-fill-mode:both;animation-timing-function:ease-in-out}:host ::ng-deep .mat-mdc-row.pfx-row-anim.pfx-row-anim--once{animation-iteration-count:1}:host ::ng-deep .mat-mdc-row.pfx-row-anim.pfx-row-anim--loop{animation-iteration-count:infinite}:host ::ng-deep .mat-mdc-row.pfx-row-anim.pfx-row-anim--count{animation-iteration-count:var(--pfx-row-anim-iteration-count, 1)}:host ::ng-deep .mat-mdc-row.pfx-row-anim.pfx-row-anim--on-hover{animation-play-state:paused}:host ::ng-deep .mat-mdc-row.pfx-row-anim.pfx-row-anim--on-hover:hover{animation-play-state:running}:host ::ng-deep .mat-mdc-row.pfx-row-anim.pfx-row-anim--pulse{animation-name:pfx-row-pulse}:host ::ng-deep .mat-mdc-row.pfx-row-anim.pfx-row-anim--blink{animation-name:pfx-row-blink}:host ::ng-deep .mat-mdc-row.pfx-row-anim.pfx-row-anim--grow{animation-name:pfx-row-grow}:host ::ng-deep .mat-mdc-row.pfx-row-anim.pfx-row-anim--fade{animation-name:pfx-row-fade}:host ::ng-deep .mat-mdc-row.pfx-row-anim.pfx-row-anim--slide-in{animation-name:pfx-row-slide-in}:host ::ng-deep .mat-mdc-row.pfx-row-anim.pfx-row-anim--border-pulse{animation-name:pfx-row-border-pulse}@keyframes pfx-row-pulse{0%{transform:scale(1)}50%{transform:scale(var(--pfx-row-anim-scale-peak, 1.015))}to{transform:scale(1)}}@keyframes pfx-row-blink{0%,49%{opacity:1}50%,to{opacity:var(--pfx-row-anim-min-opacity, .35)}}@keyframes pfx-row-grow{0%{transform:scale(.985)}to{transform:scale(1)}}@keyframes pfx-row-fade{0%{opacity:0}to{opacity:1}}@keyframes pfx-row-slide-in{0%{opacity:0;transform:translateY(var(--pfx-row-anim-slide-distance, 4px))}to{opacity:1;transform:translateY(0)}}@keyframes pfx-row-border-pulse{0%,to{box-shadow:inset 0 0 rgba(var(--pfx-row-anim-border-rgb, 25, 118, 210),0)}50%{box-shadow:inset 0 0 0 2px rgba(var(--pfx-row-anim-border-rgb, 25, 118, 210),var(--pfx-row-anim-border-strength, .3))}}@media(prefers-reduced-motion:reduce){:host ::ng-deep .mat-mdc-row.pfx-row-anim{animation:none!important}}:host ::ng-deep .mat-mdc-row:nth-child(2n){background:var(--p-table-row-even-bg)}:host ::ng-deep .mat-mdc-row:nth-child(2n):hover{background:var(--p-table-row-hover-bg)}:host ::ng-deep .mat-mdc-row.pfx-row-selected,:host ::ng-deep .mat-mdc-row.pfx-row-selected:hover{background:var(--p-table-row-selected-bg)}:host.row-borders ::ng-deep .mat-mdc-row .mat-mdc-cell{border-bottom:1px solid var(--p-table-border-color)}:host.row-borders ::ng-deep .mat-mdc-header-row .mat-mdc-header-cell{border-bottom:none}:host.col-borders ::ng-deep .mat-mdc-header-row .mat-mdc-header-cell,:host.col-borders ::ng-deep .mat-mdc-row .mat-mdc-cell{border-right:1px solid var(--p-table-border-color)}:host.col-borders ::ng-deep .mat-mdc-header-row .mat-mdc-header-cell:last-child,:host.col-borders ::ng-deep .mat-mdc-row .mat-mdc-cell:last-child{border-right:none}.ptable-error{display:flex;align-items:center;gap:12px;padding:12px;margin:8px 0;border:1px solid var(--md-sys-color-error);border-radius:8px}.ptable-error__content{flex:1}.ptable-error__title{font-weight:600}.ptable-info-banner{display:flex;gap:12px;align-items:center;padding:8px 12px;margin:8px 0;border-radius:8px;border:1px solid var(--md-sys-color-primary);background:var(--md-sys-color-primary-container);color:var(--md-sys-color-on-primary-container)}.ptable-info-banner .text{flex:1;font-weight:600}.ptable-info-banner .actions{display:flex;gap:8px}.pfx-cell-image{display:inline-block;vertical-align:middle;background:var(--md-sys-color-surface-variant);border:1px solid var(--md-sys-color-outline-variant)}.pfx-cell-image.shape-rounded{border-radius:8px}.pfx-cell-image.shape-circle{border-radius:9999px}.pfx-badge{display:inline-flex;align-items:center;gap:6px;line-height:1;padding:4px 8px;border-radius:9999px;font-size:12px;font-weight:600;border:1px solid transparent}.pfx-badge .pfx-badge-icon{font-size:16px;width:16px;height:16px}.pfx-badge--filled-primary{background:var(--md-sys-color-primary);color:var(--md-sys-color-on-primary)}.pfx-badge--filled-accent{background:var(--md-sys-color-secondary);color:var(--md-sys-color-on-secondary)}.pfx-badge--filled-warn{background:var(--md-sys-color-error);color:var(--md-sys-color-on-error)}.pfx-badge--outlined{background:transparent;border-color:var(--md-sys-color-outline-variant);color:inherit}.pfx-badge--soft-primary{background:var(--p-table-badge-soft-primary-bg);color:var(--p-table-badge-soft-primary-fg)}.pfx-badge--soft-accent{background:var(--p-table-badge-soft-accent-bg);color:var(--p-table-badge-soft-accent-fg)}.pfx-badge--soft-warn{background:var(--p-table-badge-soft-warn-bg);color:var(--p-table-badge-soft-warn-fg)}.row--success,.row--success td,td.row--success{background-color:var(--p-table-state-success-bg)!important;color:var(--p-table-state-success-fg)!important}.row--warning,.row--warning td,td.row--warning{background-color:var(--p-table-state-warning-bg)!important;color:var(--p-table-state-warning-fg)!important}.row--danger,.row--danger td,td.row--danger{background-color:var(--p-table-state-danger-bg)!important;color:var(--p-table-state-danger-fg)!important}.row--highlight,.row--highlight td,td.row--highlight{background-color:var(--p-table-state-highlight-bg)!important;color:var(--p-table-state-highlight-fg)!important;font-weight:600}.row--muted,.row--muted td,td.row--muted{opacity:.7;filter:saturate(.6)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1$2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i1$2.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: i1$2.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i1$2.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "directive", type: i1$2.NgSwitchDefault, selector: "[ngSwitchDefault]" }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: ScrollingModule }, { kind: "directive", type: i11$1.CdkScrollable, selector: "[cdk-scrollable], [cdkScrollable]" }, { kind: "directive", type: i12.ɵɵCdkFixedSizeVirtualScroll, selector: "cdk-virtual-scroll-viewport[itemSize]", inputs: ["itemSize", "minBufferPx", "maxBufferPx"] }, { kind: "directive", type: i12.ɵɵCdkVirtualForOf, selector: "[cdkVirtualFor][cdkVirtualForOf]", inputs: ["cdkVirtualForOf", "cdkVirtualForTrackBy", "cdkVirtualForTemplate", "cdkVirtualForTemplateCacheSize"] }, { kind: "component", type: i12.ɵɵCdkVirtualScrollViewport, selector: "cdk-virtual-scroll-viewport", inputs: ["orientation", "appendOnly"], outputs: ["scrolledIndexChange"] }, { kind: "ngmodule", type: DragDropModule }, { kind: "directive", type: i13.CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer", "cdkDropListHasAnchor"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: i13.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "ngmodule", type: MatBadgeModule }, { kind: "directive", type: i14.MatBadge, selector: "[matBadge]", inputs: ["matBadgeColor", "matBadgeOverlap", "matBadgeDisabled", "matBadgePosition", "matBadge", "matBadgeDescription", "matBadgeSize", "matBadgeHidden"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3.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: "component", type: i3.MatMiniFabButton, selector: "button[mat-mini-fab], a[mat-mini-fab], button[matMiniFab], a[matMiniFab]", exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i3.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatCheckboxModule }, { kind: "component", type: i9.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i5.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i5$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: i5$1.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i5$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: MatPaginatorModule }, { kind: "component", type: i19.MatPaginator, selector: "mat-paginator", inputs: ["color", "pageIndex", "length", "pageSize", "pageSizeOptions", "hidePageSize", "showFirstLastButtons", "selectConfig", "disabled"], outputs: ["page"], exportAs: ["matPaginator"] }, { kind: "ngmodule", type: MatSlideToggleModule }, { kind: "component", type: i6$1.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: MatSnackBarModule }, { kind: "ngmodule", type: MatSortModule }, { kind: "directive", type: i21.MatSort, selector: "[matSort]", inputs: ["matSortActive", "matSortStart", "matSortDirection", "matSortDisableClear", "matSortDisabled"], outputs: ["matSortChange"], exportAs: ["matSort"] }, { kind: "component", type: i21.MatSortHeader, selector: "[mat-sort-header]", inputs: ["mat-sort-header", "arrowPosition", "start", "disabled", "sortActionDescription", "disableClear"], exportAs: ["matSortHeader"] }, { kind: "ngmodule", type: MatTableModule }, { kind: "component", type: i8$1.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i8$1.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i8$1.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i8$1.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i8$1.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i8$1.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i8$1.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i8$1.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i8$1.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i8$1.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i10.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: PraxisFilter, selector: "praxis-filter", inputs: ["resourcePath", "fieldMetadata", "filterId", "formId", "componentInstanceId", "mode", "notifyIfOutdated", "snoozeMs", "autoOpenSettingsOnOutdated", "editModeEnabled", "value", "alwaysVisibleFields", "alwaysVisibleFieldMetadataOverrides", "selectedFieldIds", "tags", "allowSaveTags", "persistenceKey", "i18n", "changeDebounceMs", "showFilterSettings", "confirmTagDelete", "placeBooleansInActions", "showToggleLabels", "useInlineSelectVariant", "useInlineSearchableSelectVariant", "useInlineMultiSelectVariant", "useInlineInputVariant", "useInlineToggleVariant", "useInlineRangeVariant", "useInlineDateVariant", "useInlineDateRangeVariant", "useInlineTimeVariant", "useInlineTimeRangeVariant", "useInlineTreeSelectVariant", "alwaysMinWidth", "alwaysColsMd", "alwaysColsLg", "tagColor", "tagVariant", "tagButtonColor", "actionsButtonColor", "actionsVariant", "overlayVariant", "overlayBackdrop", "advancedOpenMode", "advancedClearButtonsEnabled"], outputs: ["submit", "change", "clear", "modeChange", "requestSearch", "tagsChange", "selectedFieldIdsChange", "metaChanged", "schemaStatusChange"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }, { kind: "component", type: PraxisTableToolbar, selector: "praxis-table-toolbar", inputs: ["config", "backgroundColor", "placement", "showMain", "showActionsGroup", "showEndActions", "showMobileActions", "showReset", "dslContext", "dslFunctionRegistry"], outputs: ["toolbarAction", "reset"] }, { kind: "component", type: EmptyStateCardComponent, selector: "praxis-empty-state-card", inputs: ["icon", "title", "description", "primaryAction", "secondaryActions", "inline", "tone"] }, { kind: "component", type: MaterialRatingComponent, selector: "pdx-material-rating", inputs: ["itemsCount", "selection", "precision", "allowHalf", "icon", "svgIcon", "svgIconOutline", "outlineIcon", "disabled", "readonlyMode", "presentationMode", "tabindex", "size", "ariaLabel", "ratingColor", "outlineColor"] }], deferBlockDependencies: [() => [import('@praxisui/ai').then(m => m.PraxisAiAssistantComponent)], () => [import('@praxisui/ai').then(m => m.PraxisAiAssistantComponent)], () => [import('@praxisui/ai').then(m => m.PraxisAiAssistantComponent)], () => [import('@praxisui/ai').then(m => m.PraxisAiAssistantComponent)]] });
41413
+ ], queries: [{ propertyName: "toolbar", first: true, predicate: PraxisTableToolbar, descendants: true }, { propertyName: "projectedFilter", first: true, predicate: ["projectedFilter"], descendants: true }], viewQueries: [{ propertyName: "paginator", first: true, predicate: MatPaginator, descendants: true }, { propertyName: "sort", first: true, predicate: MatSort, descendants: true }, { propertyName: "materialTable", first: true, predicate: MatTable, descendants: true }, { propertyName: "internalFilter", first: true, predicate: PraxisFilter, descendants: true }], usesOnChanges: true, ngImport: i0, template: "@if (shouldShowEmptyState()) {\n <praxis-empty-state-card\n icon=\"link\"\n [title]=\"'Conecte a tabela \u00E0 fonte de dados'\"\n [description]=\"'Informe a rota do recurso da API para carregar colunas e dados automaticamente.'\"\n [primaryAction]=\"{ label: 'Conectar \u00E0 fonte de dados', icon: 'bolt', action: openQuickConnect.bind(this) }\"\n ></praxis-empty-state-card>\n}\n\n<!-- Error State with Quick Connect CTA -->\n@if (isRemoteMode() && (schemaError || dataError)) {\n<div class=\"ptable-error\" role=\"alert\" aria-live=\"assertive\">\n <mat-icon color=\"warn\" aria-hidden=\"true\">error</mat-icon>\n <div class=\"ptable-error__content\">\n <div class=\"ptable-error__title\">Erro</div>\n <div>{{ errorMessage || 'Ocorreu um erro ao carregar a tabela.' }}</div>\n </div>\n <button mat-flat-button color=\"primary\" (click)=\"openQuickConnect()\">\n <mat-icon>bolt</mat-icon>\n Conectar a recurso\n </button>\n @if (!schemaError) { <button mat-stroked-button (click)=\"retryData()\">Tentar novamente</button> }\n @if (schemaError) { <button mat-stroked-button (click)=\"reloadSchema()\">Recarregar colunas</button> }\n </div>\n}\n\n<!-- Inline banner for schema change (only in edit mode) -->\n@if (shouldShowOutdatedInline()) {\n<div class=\"ptable-info-banner\" role=\"status\" aria-live=\"polite\">\n <div class=\"text\">O schema do servidor mudou. Reconciliar agora?</div>\n <div class=\"actions\">\n <button mat-stroked-button color=\"primary\" (click)=\"onReconcileRequested()\">\n <mat-icon>sync</mat-icon>\n Reconciliar\n </button>\n <button mat-button (click)=\"onSnoozeOutdated()\">Lembrar depois</button>\n <button mat-button (click)=\"onIgnoreOutdated()\">Ignorar</button>\n </div>\n </div>\n}\n\n@if (shouldRenderDataSurface() && !schemaError && !dataError && toolbarV2) {\n <div class=\"praxis-table-header\" [class.edit-mode]=\"editModeEnabled\" [class.stacked]=\"showToolbar\">\n @if (showToolbar && shouldShowToolbarTopPlacement()) {\n <praxis-table-toolbar\n [config]=\"config\"\n [backgroundColor]=\"getToolbarActionsBackgroundColor()\"\n [style.--pfx-filter-h]=\"getToolbarLayoutHeightHostStyle()\"\n [dslContext]=\"getToolbarDslContext()\"\n [dslFunctionRegistry]=\"dslFunctionRegistry\"\n [showActionsGroup]=\"shouldShowToolbarActionsTop()\"\n [showMobileActions]=\"shouldShowToolbarActionsTop()\"\n (toolbarAction)=\"onToolbarAction($event)\"\n (reset)=\"onResetPreferences()\"\n >\n @if (shouldRenderAdvancedFilter()) {\n <praxis-filter\n advancedFilter\n [resourcePath]=\"getAdvancedFilterResourcePath()\"\n [filterId]=\"tableId\"\n [formId]=\"tableId\"\n [persistenceKey]=\"getAdvancedFilterPersistenceKey()\"\n [fieldMetadata]=\"getAdvancedFilterFieldMetadata()\"\n [editModeEnabled]=\"editModeEnabled\"\n \n [alwaysVisibleFields]=\"config.behavior?.filtering?.advancedFilters?.settings?.alwaysVisibleFields\"\n [alwaysVisibleFieldMetadataOverrides]=\"config.behavior?.filtering?.advancedFilters?.settings?.alwaysVisibleFieldMetadataOverrides ?? {}\"\n [selectedFieldIds]=\"config.behavior?.filtering?.advancedFilters?.settings?.selectedFieldIds ?? []\"\n [allowSaveTags]=\"config.behavior?.filtering?.advancedFilters?.settings?.allowSaveTags\"\n [changeDebounceMs]=\"config.behavior?.filtering?.advancedFilters?.settings?.changeDebounceMs ?? 300\"\n [i18n]=\"getFilterI18n()\"\n [mode]=\"'filter'\"\n [showFilterSettings]=\"editModeEnabled\"\n (submit)=\"onAdvancedFilterSubmit($event)\"\n (clear)=\"onAdvancedFilterClear()\"\n ></praxis-filter>\n }\n <ng-content select=\"[advancedFilter]\" />\n <ng-content select=\"[toolbar]\" />\n \n <!-- AI Assistant in Toolbar -->\n @defer (on idle) {\n @if (aiAdapter) {\n <praxis-ai-assistant [adapter]=\"aiAdapter\" end-actions></praxis-ai-assistant>\n }\n }\n\n @if (editModeEnabled) {\n <button end-actions mat-icon-button color=\"primary\" data-role=\"table-settings\" data-testid=\"table-settings-trigger\"\n (click)=\"openTableSettings()\" aria-label=\"Configura\u00E7\u00F5es\"\n [matBadge]=\"schemaOutdated ? '!' : ''\"\n [matBadgeHidden]=\"!schemaOutdated\"\n matBadgeColor=\"warn\" matBadgeSize=\"small\" matBadgePosition=\"above after\"\n [matTooltip]=\"schemaOutdated ? 'Schema do servidor mudou \u2014 Reconciliar' : 'Configura\u00E7\u00F5es'\"\n matTooltipPosition=\"below\">\n <mat-icon>settings</mat-icon>\n </button>\n }\n </praxis-table-toolbar>\n }\n @if (!showToolbar && editModeEnabled) {\n <div class=\"ptable-header-actions\">\n @defer (on idle) {\n @if (aiAdapter) {\n <praxis-ai-assistant [adapter]=\"aiAdapter\"></praxis-ai-assistant>\n }\n }\n <button mat-icon-button color=\"primary\" data-role=\"table-settings\" data-testid=\"table-settings-trigger\" (click)=\"openTableSettings()\" aria-label=\"Configura\u00E7\u00F5es\"\n [matBadge]=\"schemaOutdated ? '!' : ''\"\n [matBadgeHidden]=\"!schemaOutdated\"\n matBadgeColor=\"warn\" matBadgeSize=\"small\" matBadgePosition=\"above after\"\n [matTooltip]=\"schemaOutdated ? 'Schema do servidor mudou \u2014 Reconciliar' : 'Configura\u00E7\u00F5es'\"\n matTooltipPosition=\"below\">\n <mat-icon>settings</mat-icon>\n </button>\n @if (isRemoteMode()) {\n <button mat-icon-button (click)=\"disconnect()\" aria-label=\"Desconectar\" matTooltip=\"Desconectar da fonte de dados\">\n <mat-icon>link_off</mat-icon>\n </button>\n }\n </div>\n }\n </div>\n} @else {\n @if (shouldRenderDataSurface() && !schemaError && !dataError) {\n @if (showToolbar && shouldShowToolbarTopPlacement()) {\n <praxis-table-toolbar\n [config]=\"config\"\n [backgroundColor]=\"getToolbarActionsBackgroundColor()\"\n [style.--pfx-filter-h]=\"getToolbarLayoutHeightHostStyle()\"\n [dslContext]=\"getToolbarDslContext()\"\n [dslFunctionRegistry]=\"dslFunctionRegistry\"\n [showActionsGroup]=\"shouldShowToolbarActionsTop()\"\n [showMobileActions]=\"shouldShowToolbarActionsTop()\"\n (toolbarAction)=\"onToolbarAction($event)\"\n (reset)=\"onResetPreferences()\"\n >\n @if (shouldRenderAdvancedFilter()) {\n <praxis-filter\n advancedFilter\n [resourcePath]=\"getAdvancedFilterResourcePath()\"\n [filterId]=\"tableId\"\n [formId]=\"tableId\"\n [persistenceKey]=\"getAdvancedFilterPersistenceKey()\"\n [fieldMetadata]=\"getAdvancedFilterFieldMetadata()\"\n [editModeEnabled]=\"editModeEnabled\"\n \n [alwaysVisibleFields]=\"config.behavior?.filtering?.advancedFilters?.settings?.alwaysVisibleFields\"\n [alwaysVisibleFieldMetadataOverrides]=\"config.behavior?.filtering?.advancedFilters?.settings?.alwaysVisibleFieldMetadataOverrides ?? {}\"\n [selectedFieldIds]=\"config.behavior?.filtering?.advancedFilters?.settings?.selectedFieldIds ?? []\"\n [allowSaveTags]=\"config.behavior?.filtering?.advancedFilters?.settings?.allowSaveTags\"\n [changeDebounceMs]=\"config.behavior?.filtering?.advancedFilters?.settings?.changeDebounceMs ?? 300\"\n [i18n]=\"getFilterI18n()\"\n [mode]=\"'filter'\"\n [showFilterSettings]=\"editModeEnabled\"\n (submit)=\"onAdvancedFilterSubmit($event)\"\n (clear)=\"onAdvancedFilterClear()\"\n ></praxis-filter>\n }\n <ng-content select=\"[advancedFilter]\" />\n <ng-content select=\"[toolbar]\" />\n @defer (on idle) {\n @if (aiAdapter) {\n <praxis-ai-assistant [adapter]=\"aiAdapter\" end-actions></praxis-ai-assistant>\n }\n }\n @if (editModeEnabled) {\n <button end-actions mat-icon-button color=\"primary\" data-role=\"table-settings\" data-testid=\"table-settings-trigger\"\n (click)=\"openTableSettings()\" aria-label=\"Configura\u00E7\u00F5es\"\n [matBadge]=\"schemaOutdated ? '!' : ''\"\n [matBadgeHidden]=\"!schemaOutdated\"\n matBadgeColor=\"warn\" matBadgeSize=\"small\" matBadgePosition=\"above after\"\n [matTooltip]=\"schemaOutdated ? 'Schema do servidor mudou \u2014 Reconciliar' : 'Configura\u00E7\u00F5es'\"\n matTooltipPosition=\"below\">\n <mat-icon>settings</mat-icon>\n </button>\n }\n </praxis-table-toolbar>\n }\n @if (!showToolbar && editModeEnabled) {\n <div class=\"ptable-header-actions\">\n <button mat-icon-button color=\"primary\" data-role=\"table-settings\" data-testid=\"table-settings-trigger\" (click)=\"openTableSettings()\" aria-label=\"Configura\u00E7\u00F5es\"\n [matBadge]=\"schemaOutdated ? '!' : ''\"\n [matBadgeHidden]=\"!schemaOutdated\"\n matBadgeColor=\"warn\" matBadgeSize=\"small\" matBadgePosition=\"above after\"\n [matTooltip]=\"schemaOutdated ? 'Schema do servidor mudou \u2014 Reconciliar' : 'Configura\u00E7\u00F5es'\"\n matTooltipPosition=\"below\">\n <mat-icon>settings</mat-icon>\n </button>\n </div>\n }\n }\n}\n<div class=\"px-scroll-viewport\"\n cdkScrollable\n [class.scroll-auto]=\"horizontalScroll === 'auto'\"\n [class.scroll-wrap]=\"horizontalScroll === 'wrap'\"\n [class.scroll-none]=\"horizontalScroll === 'none'\">\n\n@if (shouldRenderDataSurface() && !schemaError && !dataError) {\n<div class=\"praxis-visually-hidden-status\" role=\"status\" aria-live=\"polite\" aria-atomic=\"true\">\n {{ columnReorderStatusMessage }}\n</div>\n@if (columnReorderVisualStatusMessage) {\n <div class=\"praxis-column-reorder-status\" role=\"note\">\n {{ columnReorderVisualStatusMessage }}\n </div>\n}\n<table\n mat-table\n data-testid=\"table-column-drag-drop-list\"\n [dataSource]=\"dataSource\"\n [multiTemplateDataRows]=\"isRowExpansionRuntimeEnabled()\"\n cdkDropList\n [cdkDropListDisabled]=\"!isColumnDraggingEnabled()\"\n [cdkDropListData]=\"visibleDataColumnsForDrag\"\n cdkDropListOrientation=\"horizontal\"\n (cdkDropListDropped)=\"onColumnDrop($event)\"\n matSort\n (matSortChange)=\"onSortChange($event)\"\n [matSortDisabled]=\"!getSortingEnabled()\"\n [ngClass]=\"getTableElevationClassName()\"\n [class.table-stack-top]=\"showToolbar\"\n [class.pfx-column-drag-enabled]=\"isColumnDraggingEnabled()\"\n [class.pfx-column-drag-indicator]=\"isColumnDragIndicatorEnabled()\"\n>\n @if (config.behavior?.selection?.enabled) {\n <ng-container\n matColumnDef=\"_select\"\n >\n <th mat-header-cell *matHeaderCellDef>\n @if (canSelectAll()) {\n <mat-checkbox\n (change)=\"masterToggle()\"\n [checked]=\"isAllSelected()\"\n [indeterminate]=\"selection.hasValue() && !isAllSelected()\"\n ></mat-checkbox>\n }\n </th>\n <td mat-cell *matCellDef=\"let row\">\n <mat-checkbox\n (click)=\"$event.stopPropagation()\"\n (change)=\"toggleRow(row)\"\n [checked]=\"selection.isSelected(row)\"\n ></mat-checkbox>\n </td>\n </ng-container>\n }\n @if (isRowExpansionRuntimeEnabled()) {\n <ng-container matColumnDef=\"_expander\">\n <th mat-header-cell *matHeaderCellDef class=\"pfx-expansion-col-header\">\n <span class=\"praxis-visually-hidden-status\">Expandir detalhes da linha</span>\n </th>\n <td mat-cell *matCellDef=\"let row; let i = index\" class=\"pfx-expansion-col-cell\">\n <button\n mat-icon-button\n class=\"pfx-expansion-toggle\"\n [disabled]=\"!isRowExpandable(row, i) || !isExpansionIconTriggerEnabled()\"\n [attr.aria-expanded]=\"isRowExpanded(row, i) ? 'true' : 'false'\"\n [attr.aria-controls]=\"getRowExpansionDetailId(row, i)\"\n [attr.aria-label]=\"getRowExpansionToggleAriaLabel(row, i)\"\n (click)=\"onExpansionToggleFromIcon(row, i, $event)\"\n (keydown)=\"onExpansionToggleKeydown($event, row, i)\"\n >\n <mat-icon>{{ isRowExpanded(row, i) ? 'expand_less' : 'expand_more' }}</mat-icon>\n </button>\n </td>\n </ng-container>\n }\n @for (column of visibleColumns; track column.field) {\n <ng-container\n [matColumnDef]=\"column.field\"\n [sticky]=\"column.sticky === true || column.sticky === 'start'\"\n [stickyEnd]=\"column.sticky === 'end'\"\n >\n <th\n mat-header-cell\n *matHeaderCellDef\n mat-sort-header\n cdkDrag\n [cdkDragData]=\"column\"\n cdkDragLockAxis=\"x\"\n cdkDragPreviewClass=\"pfx-column-drag-preview\"\n (cdkDragStarted)=\"onColumnDragStarted(column)\"\n (cdkDragEnded)=\"onColumnDragEnded($event, column)\"\n (keydown)=\"onColumnDragHandleKeydown($event, column)\"\n [cdkDragDisabled]=\"!isColumnDraggingEnabled() || !isColumnDraggable(column)\"\n [class.praxis-header-draggable]=\"isColumnDraggingEnabled() && isColumnDraggable(column)\"\n [disabled]=\"!getSortingEnabled() || column.sortable === false\"\n [style.text-align]=\"getColumnTextAlignStyle(column)\"\n [style.width]=\"getColumnWidthStyle(column)\"\n [attr.style]=\"getColumnHeaderAttrStyle(column)\"\n [attr.aria-label]=\"isColumnDraggingEnabled() && isColumnDraggable(column) ? getColumnDragHandleAriaLabel(column) : null\"\n [matTooltip]=\"isColumnDraggingEnabled() && isColumnDraggable(column) ? getColumnDragHandleTooltip(column) : null\"\n matTooltipPosition=\"above\"\n matTooltipClass=\"praxis-tooltip\"\n >\n <span class=\"praxis-header-label\" data-testid=\"column-header-label\">{{ column.header }}</span>\n @if (isColumnDraggingEnabled() && isColumnDraggable(column)) {\n <span\n class=\"praxis-column-drag-handle\"\n data-testid=\"column-drag-handle\"\n [attr.data-column-field]=\"column.field\"\n aria-hidden=\"true\"\n >\n <mat-icon [praxisIcon]=\"'drag_indicator'\"></mat-icon>\n </span>\n }\n </th>\n <td\n mat-cell\n *matCellDef=\"let element\"\n [style.text-align]=\"getColumnTextAlignStyle(column)\"\n [style.width]=\"getColumnWidthStyle(column)\"\n [attr.style]=\"getColumnCellAttrStyle(column)\"\n [ngClass]=\"getCellClasses(element, column)\"\n [ngStyle]=\"getCellNgStyle(element, column)\"\n >\n <div\n class=\"pfx-cell-content\"\n [ngClass]=\"getCellContentClasses(element, column)\"\n [ngStyle]=\"getCellContentNgStyle(element, column)\"\n >\n <ng-container [ngSwitch]=\"getEffectiveRendererType(element, column)\">\n <!-- Icon renderer -->\n <ng-container *ngSwitchCase=\"'icon'\">\n <mat-icon\n [color]=\"getIconColor(element, column) || null\"\n [ngStyle]=\"getIconStyle(element, column)\"\n [attr.aria-label]=\"getIconAriaLabel(element, column) || null\"\n >{{ getIconName(element, column) }}</mat-icon\n >\n </ng-container>\n\n <!-- Image renderer -->\n <ng-container *ngSwitchCase=\"'image'\">\n <img\n class=\"pfx-cell-image\"\n [src]=\"getImageSrc(element, column)\"\n [attr.alt]=\"getImageAlt(element, column) || ''\"\n [attr.loading]=\"getImageLazy(element, column) ? 'lazy' : null\"\n [style.width.px]=\"getImageWidth(element, column)\"\n [style.height.px]=\"getImageHeight(element, column)\"\n [class.shape-rounded]=\"getImageShape(element, column) === 'rounded'\"\n [class.shape-circle]=\"getImageShape(element, column) === 'circle'\"\n [style.object-fit]=\"getImageFit(element, column)\"\n />\n </ng-container>\n\n <!-- Badge renderer -->\n <ng-container *ngSwitchCase=\"'badge'\">\n <span class=\"pfx-badge\" [ngClass]=\"getBadgeClasses(element, column)\">\n @if (getBadgeIcon(element, column); as bi) { <mat-icon class=\"pfx-badge-icon\">{{ bi }}</mat-icon> }\n <span class=\"pfx-badge-text\">{{ getBadgeText(element, column) }}</span>\n </span>\n </ng-container>\n\n <!-- Link renderer -->\n <ng-container *ngSwitchCase=\"'link'\">\n <a\n class=\"pfx-link\"\n [attr.href]=\"getLinkHref(element, column) || null\"\n [attr.target]=\"getLinkTarget(element, column) || null\"\n [attr.rel]=\"getLinkRel(element, column) || null\"\n (click)=\"$event.stopPropagation()\"\n >{{ getLinkText(element, column) }}</a\n >\n </ng-container>\n\n <!-- Button renderer -->\n <ng-container *ngSwitchCase=\"'button'\">\n <ng-container [ngSwitch]=\"getButtonVariant(element, column)\">\n <button\n *ngSwitchCase=\"'outlined'\"\n mat-stroked-button\n [color]=\"getButtonColor(element, column) || null\"\n [disabled]=\"isButtonDisabled(element, column)\"\n [attr.aria-label]=\"getButtonAriaLabel(element, column) || getButtonLabel(element, column)\"\n (click)=\"onButtonClick(element, column, $event)\"\n >\n @if (getButtonIcon(element, column); as bi) { <mat-icon>{{ bi }}</mat-icon> }\n {{ getButtonLabel(element, column) }}\n </button>\n <button\n *ngSwitchCase=\"'text'\"\n mat-button\n [color]=\"getButtonColor(element, column) || null\"\n [disabled]=\"isButtonDisabled(element, column)\"\n [attr.aria-label]=\"getButtonAriaLabel(element, column) || getButtonLabel(element, column)\"\n (click)=\"onButtonClick(element, column, $event)\"\n >\n @if (getButtonIcon(element, column); as bi) { <mat-icon>{{ bi }}</mat-icon> }\n {{ getButtonLabel(element, column) }}\n </button>\n <button\n *ngSwitchDefault\n mat-flat-button\n [color]=\"getButtonColor(element, column) || null\"\n [disabled]=\"isButtonDisabled(element, column)\"\n [attr.aria-label]=\"getButtonAriaLabel(element, column) || getButtonLabel(element, column)\"\n (click)=\"onButtonClick(element, column, $event)\"\n >\n @if (getButtonIcon(element, column); as bi) { <mat-icon>{{ bi }}</mat-icon> }\n {{ getButtonLabel(element, column) }}\n </button>\n </ng-container>\n </ng-container>\n\n <!-- Chip renderer -->\n <ng-container *ngSwitchCase=\"'chip'\">\n <span class=\"pfx-chip\" [ngClass]=\"getChipClasses(element, column)\">\n @if (getChipIcon(element, column); as ci) { <mat-icon class=\"pfx-chip-icon\">{{ ci }}</mat-icon> }\n <span class=\"pfx-chip-text\">{{ getChipText(element, column) }}</span>\n </span>\n </ng-container>\n\n <!-- Progress renderer -->\n <ng-container *ngSwitchCase=\"'progress'\">\n <div class=\"pfx-progress\">\n <div class=\"pfx-progress-bar\" [style.width.%]=\"getProgressWidthPercentStyle(element, column)\" [style.background]=\"getProgressBackgroundStyle(element, column)\"></div>\n @if (getProgressShowLabel(element, column)) { <div class=\"pfx-progress-label\">{{ getProgressValue(element, column) }}%</div> }\n </div>\n </ng-container>\n\n <!-- Avatar renderer -->\n <ng-container *ngSwitchCase=\"'avatar'\">\n @if (getAvatarSrc(element, column); as asrc) {\n <img class=\"pfx-avatar\" [src]=\"asrc\" [attr.alt]=\"getAvatarAlt(element, column) || ''\" [ngStyle]=\"getAvatarStyle(element, column)\" [class.shape-rounded]=\"getAvatarShape(element, column) === 'rounded'\" [class.shape-circle]=\"getAvatarShape(element, column) === 'circle'\" loading=\"lazy\" />\n } @else {\n <span class=\"pfx-avatar pfx-avatar--initials\" [ngStyle]=\"getAvatarStyle(element, column)\" [class.shape-rounded]=\"getAvatarShape(element, column) === 'rounded'\" [class.shape-circle]=\"getAvatarShape(element, column) === 'circle'\">{{ getAvatarInitials(element, column) }}</span>\n }\n </ng-container>\n\n <!-- Toggle renderer -->\n <ng-container *ngSwitchCase=\"'toggle'\">\n <mat-slide-toggle\n [checked]=\"getToggleState(element, column)\"\n [disabled]=\"isToggleDisabled(element, column)\"\n [attr.aria-label]=\"getToggleAriaLabel(element, column) || 'Alternar'\"\n (change)=\"onToggleChange(element, column, $event)\"\n (click)=\"$event.stopPropagation()\"\n ></mat-slide-toggle>\n </ng-container>\n\n <!-- Menu renderer -->\n <ng-container *ngSwitchCase=\"'menu'\">\n <button mat-icon-button [matMenuTriggerFor]=\"menuRef\" (click)=\"$event.stopPropagation()\" [attr.aria-label]=\"getMenuAriaLabel(element, column) || 'Menu'\">\n <mat-icon>more_vert</mat-icon>\n </button>\n <mat-menu #menuRef=\"matMenu\">\n <button mat-menu-item *ngFor=\"let it of getMenuItems(element, column)\" (click)=\"onMenuItemClick(it, element, $event)\" [disabled]=\"!it.__visible\" >\n @if (it.icon) { <mat-icon>{{ it.icon }}</mat-icon> }\n <span>{{ it.label }}</span>\n </button>\n </mat-menu>\n </ng-container>\n\n <!-- Rating renderer -->\n <ng-container *ngSwitchCase=\"'rating'\">\n <praxis-table-rating\n class=\"pfx-rating-cell\"\n [itemsCount]=\"getRatingMax(element, column)\"\n [value]=\"getRatingValue(element, column)\"\n [size]=\"getRatingSize(element, column)\"\n [ratingColor]=\"getRatingColor(element, column)\"\n [outlineColor]=\"getRatingOutlineColor(element, column)\"\n [ariaLabel]=\"getRatingAriaLabel(element, column) || column.header\">\n </praxis-table-rating>\n </ng-container>\n\n <!-- HTML renderer (sanitizado) -->\n <ng-container *ngSwitchCase=\"'html'\">\n <span [innerHTML]=\"getSafeHtml(element, column)\"></span>\n </ng-container>\n\n <!-- Compose renderer -->\n <ng-container *ngSwitchCase=\"'compose'\">\n <span class=\"pfx-cell-compose\" [ngClass]=\"getComposeClasses(element, column)\" [ngStyle]=\"getComposeGapStyle(element, column)\">\n <ng-container *ngFor=\"let it of getComposeItems(element, column)\">\n <ng-container [ngSwitch]=\"getItemEffectiveType(element, column, it)\">\n <!-- Reuse helpers by projecting item as faux column -->\n <ng-container *ngSwitchCase=\"'icon'\">\n <mat-icon [color]=\"getIconColor(element, asItemColumn(column, it)) || null\" [ngStyle]=\"getIconStyle(element, asItemColumn(column, it))\" [attr.aria-label]=\"getIconAriaLabel(element, asItemColumn(column, it)) || null\">{{ getIconName(element, asItemColumn(column, it)) }}</mat-icon>\n </ng-container>\n <ng-container *ngSwitchCase=\"'image'\">\n <img class=\"pfx-cell-image\" [src]=\"getImageSrc(element, asItemColumn(column, it))\" [attr.alt]=\"getImageAlt(element, asItemColumn(column, it)) || ''\" [attr.loading]=\"getImageLazy(element, asItemColumn(column, it)) ? 'lazy' : null\" [style.width.px]=\"getImageWidth(element, asItemColumn(column, it))\" [style.height.px]=\"getImageHeight(element, asItemColumn(column, it))\" [class.shape-rounded]=\"getImageShape(element, asItemColumn(column, it)) === 'rounded'\" [class.shape-circle]=\"getImageShape(element, asItemColumn(column, it)) === 'circle'\" [style.object-fit]=\"getImageFit(element, asItemColumn(column, it))\" />\n </ng-container>\n <ng-container *ngSwitchCase=\"'badge'\">\n <span class=\"pfx-badge\" [ngClass]=\"getBadgeClasses(element, asItemColumn(column, it))\">@if (getBadgeIcon(element, asItemColumn(column, it)); as bi) { <mat-icon class=\"pfx-badge-icon\">{{ bi }}</mat-icon> }<span class=\"pfx-badge-text\">{{ getBadgeText(element, asItemColumn(column, it)) }}</span></span>\n </ng-container>\n <ng-container *ngSwitchCase=\"'link'\">\n <a class=\"pfx-link\" [attr.href]=\"getLinkHref(element, asItemColumn(column, it)) || null\" [attr.target]=\"getLinkTarget(element, asItemColumn(column, it)) || null\" [attr.rel]=\"getLinkRel(element, asItemColumn(column, it)) || null\" (click)=\"$event.stopPropagation()\">{{ getLinkText(element, asItemColumn(column, it)) }}</a>\n </ng-container>\n <ng-container *ngSwitchCase=\"'button'\">\n <ng-container [ngSwitch]=\"getButtonVariant(element, asItemColumn(column, it))\">\n <button *ngSwitchCase=\"'outlined'\" mat-stroked-button [color]=\"getButtonColor(element, asItemColumn(column, it)) || null\" [disabled]=\"isButtonDisabled(element, asItemColumn(column, it))\" [attr.aria-label]=\"getButtonAriaLabel(element, asItemColumn(column, it)) || getButtonLabel(element, asItemColumn(column, it))\" (click)=\"onButtonClick(element, asItemColumn(column, it), $event)\">@if (getButtonIcon(element, asItemColumn(column, it)); as bi) { <mat-icon>{{ bi }}</mat-icon> }{{ getButtonLabel(element, asItemColumn(column, it)) }}</button>\n <button *ngSwitchCase=\"'text'\" mat-button [color]=\"getButtonColor(element, asItemColumn(column, it)) || null\" [disabled]=\"isButtonDisabled(element, asItemColumn(column, it))\" [attr.aria-label]=\"getButtonAriaLabel(element, asItemColumn(column, it)) || getButtonLabel(element, asItemColumn(column, it))\" (click)=\"onButtonClick(element, asItemColumn(column, it), $event)\">@if (getButtonIcon(element, asItemColumn(column, it)); as bi) { <mat-icon>{{ bi }}</mat-icon> }{{ getButtonLabel(element, asItemColumn(column, it)) }}</button>\n <button *ngSwitchDefault mat-flat-button [color]=\"getButtonColor(element, asItemColumn(column, it)) || null\" [disabled]=\"isButtonDisabled(element, asItemColumn(column, it))\" [attr.aria-label]=\"getButtonAriaLabel(element, asItemColumn(column, it)) || getButtonLabel(element, asItemColumn(column, it))\" (click)=\"onButtonClick(element, asItemColumn(column, it), $event)\">@if (getButtonIcon(element, asItemColumn(column, it)); as bi) { <mat-icon>{{ bi }}</mat-icon> }{{ getButtonLabel(element, asItemColumn(column, it)) }}</button>\n </ng-container>\n </ng-container>\n <ng-container *ngSwitchCase=\"'chip'\">\n <span class=\"pfx-chip\" [ngClass]=\"getChipClasses(element, asItemColumn(column, it))\">@if (getChipIcon(element, asItemColumn(column, it)); as ci) { <mat-icon class=\"pfx-chip-icon\">{{ ci }}</mat-icon> }<span class=\"pfx-chip-text\">{{ getChipText(element, asItemColumn(column, it)) }}</span></span>\n </ng-container>\n <ng-container *ngSwitchCase=\"'progress'\">\n <div class=\"pfx-progress\"><div class=\"pfx-progress-bar\" [style.width.%]=\"getProgressWidthPercentStyle(element, asItemColumn(column, it))\" [style.background]=\"getProgressBackgroundStyle(element, asItemColumn(column, it))\"></div>@if (getProgressShowLabel(element, asItemColumn(column, it))) { <div class=\"pfx-progress-label\">{{ getProgressValue(element, asItemColumn(column, it)) }}%</div> }</div>\n </ng-container>\n <ng-container *ngSwitchCase=\"'avatar'\">\n @if (getAvatarSrc(element, asItemColumn(column, it)); as asrc) {\n <img class=\"pfx-avatar\" [src]=\"asrc\" [attr.alt]=\"getAvatarAlt(element, asItemColumn(column, it)) || ''\" [ngStyle]=\"getAvatarStyle(element, asItemColumn(column, it))\" [class.shape-rounded]=\"getAvatarShape(element, asItemColumn(column, it)) === 'rounded'\" [class.shape-circle]=\"getAvatarShape(element, asItemColumn(column, it)) === 'circle'\" loading=\"lazy\" />\n } @else {\n <span class=\"pfx-avatar pfx-avatar--initials\" [ngStyle]=\"getAvatarStyle(element, asItemColumn(column, it))\" [class.shape-rounded]=\"getAvatarShape(element, asItemColumn(column, it)) === 'rounded'\" [class.shape-circle]=\"getAvatarShape(element, asItemColumn(column, it)) === 'circle'\">{{ getAvatarInitials(element, asItemColumn(column, it)) }}</span>\n }\n </ng-container>\n <ng-container *ngSwitchCase=\"'toggle'\">\n <mat-slide-toggle [checked]=\"getToggleState(element, asItemColumn(column, it))\" [disabled]=\"isToggleDisabled(element, asItemColumn(column, it))\" [attr.aria-label]=\"getToggleAriaLabel(element, asItemColumn(column, it)) || 'Alternar'\" (change)=\"onToggleChange(element, asItemColumn(column, it), $event)\" (click)=\"$event.stopPropagation()\"></mat-slide-toggle>\n </ng-container>\n <ng-container *ngSwitchCase=\"'menu'\">\n <button mat-icon-button [matMenuTriggerFor]=\"menuRef\" (click)=\"$event.stopPropagation()\" [attr.aria-label]=\"getMenuAriaLabel(element, asItemColumn(column, it)) || 'Menu'\"><mat-icon>more_vert</mat-icon></button>\n <mat-menu #menuRef=\"matMenu\">\n <button mat-menu-item *ngFor=\"let mi of getMenuItems(element, asItemColumn(column, it))\" (click)=\"onMenuItemClick(mi, element, $event)\" [disabled]=\"!mi.__visible\">\n @if (mi.icon) { <mat-icon>{{ mi.icon }}</mat-icon> }\n <span>{{ mi.label }}</span>\n </button>\n </mat-menu>\n </ng-container>\n <ng-container *ngSwitchCase=\"'rating'\">\n <praxis-table-rating\n class=\"pfx-rating-cell\"\n [itemsCount]=\"getRatingMax(element, asItemColumn(column, it))\"\n [value]=\"getRatingValue(element, asItemColumn(column, it))\"\n [size]=\"getRatingSize(element, asItemColumn(column, it))\"\n [ratingColor]=\"getRatingColor(element, asItemColumn(column, it))\"\n [outlineColor]=\"getRatingOutlineColor(element, asItemColumn(column, it))\"\n [ariaLabel]=\"getRatingAriaLabel(element, asItemColumn(column, it)) || column.header\">\n </praxis-table-rating>\n </ng-container>\n <ng-container *ngSwitchCase=\"'html'\">\n <span [innerHTML]=\"getSafeHtml(element, asItemColumn(column, it))\"></span>\n </ng-container>\n <!-- Value item: render base cell text alongside visuals -->\n <ng-container *ngSwitchCase=\"'value'\">\n <span class=\"pfx-cell-value\">{{ getComposeItemValue(element, column, it) }}</span>\n </ng-container>\n </ng-container>\n </ng-container>\n </span>\n </ng-container>\n\n <!-- Default text rendering -->\n <ng-container *ngSwitchDefault>\n {{ getCellValue(element, column) }}\n </ng-container>\n </ng-container>\n </div>\n </td>\n </ng-container>\n }\n @if (config.actions?.row?.enabled) {\n <ng-container matColumnDef=\"_actions\" [sticky]=\"config.actions?.row?.sticky === true || config.actions?.row?.sticky === 'start'\" [stickyEnd]=\"config.actions?.row?.sticky === 'end'\">\n <th mat-header-cell *matHeaderCellDef #actionsHeaderCell [style.width]=\"getRowActionsWidthStyle()\" class=\"praxis-actions-header\" [class.align-start]=\"getActionsHeaderAlign() === 'start'\" [class.align-center]=\"getActionsHeaderAlign() === 'center'\" [class.align-end]=\"getActionsHeaderAlign() === 'end'\">\n <div class=\"praxis-actions-header__content\" [matTooltip]=\"getActionsHeaderTooltip() || ''\" [matTooltipDisabled]=\"!getActionsHeaderTooltip()\">\n @if (getActionsHeaderIcon(); as hi) { <mat-icon [praxisIcon]=\"hi\"></mat-icon> }\n @if (getActionsHeaderLabel(); as hl) { <span class=\"label\">{{ hl }}</span> }\n </div>\n </th>\n <td\n mat-cell\n *matCellDef=\"let row\"\n class=\"praxis-actions-cell\"\n [class.dense]=\"dense\"\n [style.width]=\"getRowActionsWidthStyle()\"\n >\n <div class=\"praxis-actions-cell__content\">\n <!-- A\u00E7\u00F5es inline -->\n <!-- Inline actions: icons mode -->\n @if (config.actions?.row?.display === 'icons' || !config.actions?.row?.display) {\n <ng-container *ngFor=\"let a of getInlineRowActions(row); trackBy: trackAction\">\n <button\n mat-icon-button\n class=\"praxis-icon-btn\"\n [disabled]=\"isActionDisabled(a, row)\"\n (click)=\"onRowAction(getActionId(a), row, $event)\"\n [matTooltip]=\"a.label || getActionId(a)\"\n matTooltipPosition=\"above\"\n matTooltipClass=\"praxis-tooltip\"\n [attr.aria-label]=\"a.label || getActionId(a)\"\n [color]=\"a.color || null\"\n >\n <mat-icon [praxisIcon]=\"a.icon\"></mat-icon>\n </button>\n </ng-container>\n }\n\n <!-- Inline actions: buttons mode (show label + icon) -->\n @if (config.actions?.row?.display === 'buttons') {\n <ng-container *ngFor=\"let a of getInlineRowActions(row); trackBy: trackAction\">\n <button\n mat-flat-button\n class=\"praxis-row-btn\"\n [disabled]=\"isActionDisabled(a, row)\"\n (click)=\"onRowAction(getActionId(a), row, $event)\"\n [attr.aria-label]=\"a.label || getActionId(a)\"\n [color]=\"a.color || null\"\n >\n <mat-icon [praxisIcon]=\"a.icon\"></mat-icon>\n <span>{{ a.label || getActionId(a) }}</span>\n </button>\n </ng-container>\n }\n\n <!-- Menu de overflow -->\n @if (hasOverflowRowActions(row)) {\n <button\n mat-icon-button\n class=\"praxis-icon-btn praxis-more-btn\"\n [matMenuTriggerFor]=\"rowMoreMenu\"\n [color]=\"getRowMenuButtonColor() || null\"\n aria-label=\"Mais a\u00E7\u00F5es\"\n >\n <mat-icon [praxisIcon]=\"getRowMenuIcon()\"></mat-icon>\n </button>\n }\n <mat-menu #rowMoreMenu=\"matMenu\" xPosition=\"before\">\n <ng-container\n *ngFor=\"let a of getOverflowRowActions(row); trackBy: trackAction\"\n >\n <button\n mat-menu-item\n (click)=\"onRowAction(getActionId(a), row, $event)\"\n [disabled]=\"isActionDisabled(a, row)\"\n >\n <mat-icon [color]=\"a.color || null\" [praxisIcon]=\"a.icon\"></mat-icon>\n <span>{{ a.label || getActionId(a) }}</span>\n </button>\n </ng-container>\n </mat-menu>\n </div>\n </td>\n </ng-container>\n }\n\n <tr\n mat-header-row\n *matHeaderRowDef=\"displayedColumns\"\n ></tr>\n @if (!isVirtualized()) {\n <tr\n mat-row\n *matRowDef=\"let row; let i = index; columns: displayedColumns\"\n [class.pfx-row-selected]=\"selection.isSelected(row)\"\n [class.pfx-row-expanded]=\"isRowExpansionRuntimeEnabled() && isRowExpanded(row, i)\"\n [attr.aria-selected]=\"config.behavior?.selection?.enabled ? (selection.isSelected(row) ? 'true' : 'false') : null\"\n [attr.aria-expanded]=\"isRowExpansionRuntimeEnabled() ? (isRowExpanded(row, i) ? 'true' : 'false') : null\"\n [ngClass]=\"getRowClasses(row)\"\n [ngStyle]=\"getRowNgStyle(row)\"\n [matTooltip]=\"getRowTooltip(row) || null\"\n [matTooltipDisabled]=\"!getRowTooltip(row)\"\n [matTooltipPosition]=\"getRowTooltipPosition(row)\"\n [matTooltipShowDelay]=\"getRowTooltipShowDelay(row)\"\n (click)=\"onRowClicked(row, i, $event)\"\n (dblclick)=\"onRowDoubleClicked(row, i)\"\n ></tr>\n @if (isRowExpansionRuntimeEnabled()) {\n <ng-container matColumnDef=\"_detail\">\n <td\n mat-cell\n *matCellDef=\"let row; let i = index\"\n class=\"pfx-expansion-detail-cell\"\n [attr.colspan]=\"displayedColumns.length\"\n >\n <section\n class=\"pfx-expansion-detail-panel\"\n [attr.id]=\"getRowExpansionDetailId(row, i)\"\n role=\"region\"\n [attr.aria-label]=\"getRowExpansionRegionAriaLabel(row, i)\"\n [attr.aria-busy]=\"getExpansionDetailViewState(row, i).status === 'loading' ? 'true' : 'false'\"\n >\n @let detailState = getExpansionDetailViewState(row, i);\n @if (detailState.status === 'loading') {\n <div class=\"pfx-expansion-detail-message\" role=\"status\" aria-live=\"polite\">\n Carregando detail schema...\n </div>\n } @else if (detailState.status !== 'ready') {\n <div\n class=\"pfx-expansion-detail-message pfx-expansion-detail-message--error\"\n role=\"alert\"\n aria-live=\"assertive\"\n aria-atomic=\"true\"\n >\n {{ detailState.message || 'Detail indispon\u00EDvel para esta linha.' }}\n </div>\n } @else {\n @if (getExpansionDetailLayout(detailState.schema) === 'tabs') {\n @let detailTabs = getExpansionDetailTabs(detailState.schema);\n @if (detailTabs.length) {\n <div class=\"pfx-expansion-detail-tabs\" role=\"tablist\" aria-label=\"Se\u00E7\u00F5es do detail\">\n @for (tab of detailTabs; track $index; let tabIndex = $index) {\n <button\n type=\"button\"\n class=\"pfx-expansion-detail-tab-btn\"\n role=\"tab\"\n [attr.id]=\"getExpansionDetailTabId(row, i, tab, tabIndex)\"\n [attr.aria-controls]=\"getExpansionDetailPanelId(row, i, tab, tabIndex)\"\n [attr.aria-selected]=\"isExpansionDetailTabActive(row, i, tab, tabIndex, detailTabs) ? 'true' : 'false'\"\n [attr.tabindex]=\"isExpansionDetailTabActive(row, i, tab, tabIndex, detailTabs) ? '0' : '-1'\"\n [class.is-active]=\"isExpansionDetailTabActive(row, i, tab, tabIndex, detailTabs)\"\n (click)=\"onExpansionDetailTabSelect(row, i, tab, tabIndex, $event)\"\n (keydown)=\"onExpansionDetailTabKeydown($event, row, i, tabIndex, detailTabs)\"\n >\n {{ getExpansionDetailNodeTitle(tab, 'Tab') }}\n </button>\n }\n </div>\n @for (tab of detailTabs; track $index; let tabIndex = $index) {\n @if (isExpansionDetailTabActive(row, i, tab, tabIndex, detailTabs)) {\n <div\n class=\"pfx-expansion-detail-tab-panel\"\n role=\"tabpanel\"\n [attr.id]=\"getExpansionDetailPanelId(row, i, tab, tabIndex)\"\n [attr.aria-labelledby]=\"getExpansionDetailTabId(row, i, tab, tabIndex)\"\n >\n @for (childNode of getExpansionDetailNodeChildren(tab); track $index) {\n <ng-container\n *ngTemplateOutlet=\"\n expansionDetailNodeTemplate;\n context: { $implicit: childNode, row: row, index: i }\n \"\n ></ng-container>\n }\n </div>\n }\n }\n } @else {\n <div class=\"pfx-expansion-detail-message\">\n Schema em layout tabs sem abas v\u00E1lidas.\n </div>\n }\n } @else {\n <div class=\"pfx-expansion-detail-stack\">\n @for (node of getExpansionDetailItems(detailState.schema); track $index) {\n <ng-container\n *ngTemplateOutlet=\"\n expansionDetailNodeTemplate;\n context: { $implicit: node, row: row, index: i }\n \"\n ></ng-container>\n }\n </div>\n }\n }\n\n <ng-template #expansionDetailNodeTemplate let-node let-row=\"row\" let-index=\"index\">\n @switch (getExpansionDetailNodeType(node)) {\n @case ('card') {\n <article class=\"pfx-expansion-node pfx-expansion-node-card\">\n <header class=\"pfx-expansion-node-card__header\">\n <h5 class=\"pfx-expansion-node-card__title\">\n {{ getExpansionDetailNodeTitle(node, 'Card') }}\n </h5>\n @if (node?.subtitle) {\n <p class=\"pfx-expansion-node-card__subtitle\">{{ node?.subtitle }}</p>\n }\n </header>\n @for (childNode of getExpansionDetailNodeChildren(node); track $index) {\n <ng-container\n *ngTemplateOutlet=\"\n expansionDetailNodeTemplate;\n context: { $implicit: childNode, row: row, index: index }\n \"\n ></ng-container>\n }\n </article>\n }\n @case ('value') {\n <div class=\"pfx-expansion-node pfx-expansion-node-value\">\n <span class=\"pfx-expansion-node-value__label\">\n {{ getExpansionDetailNodeTitle(node, 'Valor') }}\n </span>\n <strong class=\"pfx-expansion-node-value__content\">\n {{ getExpansionDetailValue(row, node) }}\n </strong>\n </div>\n }\n @case ('list') {\n <section class=\"pfx-expansion-node pfx-expansion-node-list\">\n <h6 class=\"pfx-expansion-node-list__title\">\n {{ getExpansionDetailNodeTitle(node, 'Lista') }}\n </h6>\n @let listItems = getExpansionDetailListItems(row, node);\n @if (listItems.length) {\n <ul>\n @for (entry of listItems; track $index) {\n <li>{{ entry }}</li>\n }\n </ul>\n } @else {\n <p class=\"pfx-expansion-node-placeholder\">Sem itens.</p>\n }\n </section>\n }\n @case ('richText') {\n <div\n class=\"pfx-expansion-node pfx-expansion-node-richtext\"\n [innerHTML]=\"getExpansionDetailRichText(node)\"\n ></div>\n }\n @case ('formRef') {\n <div class=\"pfx-expansion-node pfx-expansion-node-placeholder\">\n Formul\u00E1rio referenciado: <code>{{ node?.schemaId || node?.id || 'sem-id' }}</code>\n </div>\n }\n @case ('tableRef') {\n <div class=\"pfx-expansion-node pfx-expansion-node-placeholder\">\n Tabela referenciada: <code>{{ node?.schemaId || node?.id || 'sem-id' }}</code>\n </div>\n }\n @case ('chartRef') {\n <div class=\"pfx-expansion-node pfx-expansion-node-placeholder\">\n Gr\u00E1fico referenciado: <code>{{ node?.schemaId || node?.id || 'sem-id' }}</code>\n </div>\n }\n @case ('templateRef') {\n <div class=\"pfx-expansion-node pfx-expansion-node-placeholder\">\n Template referenciado: <code>{{ node?.id || node?.templateId || 'sem-id' }}</code>\n </div>\n }\n @case ('action') {\n <div class=\"pfx-expansion-node pfx-expansion-node-placeholder\">\n A\u00E7\u00E3o declarada: <code>{{ node?.id || node?.actionId || 'sem-id' }}</code>\n </div>\n }\n @case ('tab') {\n <div class=\"pfx-expansion-node pfx-expansion-node-placeholder\">\n Node <code>tab</code> fora de contexto de tabs.\n </div>\n }\n @default {\n <div class=\"pfx-expansion-node pfx-expansion-node-placeholder\">\n Node n\u00E3o suportado: <code>{{ getExpansionDetailNodeType(node) }}</code>\n </div>\n }\n }\n </ng-template>\n </section>\n </td>\n </ng-container>\n <tr\n mat-row\n *matRowDef=\"let row; columns: expansionDetailRowColumns; when: isExpansionDetailRow\"\n class=\"pfx-expansion-detail-row\"\n ></tr>\n }\n }\n</table>\n}\n\n<!-- Virtual rows path (header preserved above) -->\n@if (shouldRenderDataSurface() && !schemaError && !dataError && isVirtualized()) {\n <cdk-virtual-scroll-viewport\n class=\"ptable-viewport\"\n [itemSize]=\"getVirtItemHeight()\"\n [minBufferPx]=\"getVirtBufferSize() * getVirtItemHeight()\"\n [maxBufferPx]=\"getVirtBufferSize() * getVirtItemHeight() * 2\"\n [style.minHeight]=\"getVirtMinHeightHostStyle()\"\n >\n <table\n class=\"mat-mdc-table\"\n [ngClass]=\"getTableElevationClassName()\"\n [style.width]=\"getVirtualTableWidthStyle()\"\n >\n <tbody>\n <tr class=\"mat-mdc-row\"\n *cdkVirtualFor=\"let row of dataSource.data; let i = index; trackBy: trackByRow\"\n [class.pfx-row-selected]=\"selection.isSelected(row)\"\n [attr.aria-selected]=\"config.behavior?.selection?.enabled ? (selection.isSelected(row) ? 'true' : 'false') : null\"\n [ngClass]=\"getRowClasses(row)\"\n [ngStyle]=\"getRowNgStyle(row)\"\n [matTooltip]=\"getRowTooltip(row) || null\"\n [matTooltipDisabled]=\"!getRowTooltip(row)\"\n [matTooltipPosition]=\"getRowTooltipPosition(row)\"\n [matTooltipShowDelay]=\"getRowTooltipShowDelay(row)\"\n (click)=\"onRowClicked(row, i, $event)\"\n (dblclick)=\"onRowDoubleClicked(row, i)\">\n <!-- Selection column -->\n @if (config.behavior?.selection?.enabled) { <td class=\"mat-mdc-cell\">\n <mat-checkbox\n (click)=\"$event.stopPropagation()\"\n (change)=\"toggleRow(row)\"\n [checked]=\"selection.isSelected(row)\">\n </mat-checkbox>\n </td> }\n <!-- Data columns -->\n @for (column of visibleColumns; track column.field) {\n <td class=\"mat-mdc-cell\"\n [style.text-align]=\"getColumnTextAlignStyle(column)\"\n [style.width]=\"getColumnWidthStyle(column)\"\n [attr.style]=\"getColumnCellAttrStyle(column)\"\n [ngClass]=\"getCellClasses(row, column)\"\n [ngStyle]=\"getCellNgStyle(row, column)\">\n <div\n class=\"pfx-cell-content\"\n [ngClass]=\"getCellContentClasses(row, column)\"\n [ngStyle]=\"getCellContentNgStyle(row, column)\"\n >\n <ng-container [ngSwitch]=\"getEffectiveRendererType(row, column)\">\n <ng-container *ngSwitchCase=\"'icon'\">\n <mat-icon [color]=\"getIconColor(row, column) || null\"\n [ngStyle]=\"getIconStyle(row, column)\"\n [attr.aria-label]=\"getIconAriaLabel(row, column) || null\">\n {{ getIconName(row, column) }}\n </mat-icon>\n </ng-container>\n <ng-container *ngSwitchCase=\"'image'\">\n <img class=\"pfx-cell-image\"\n [src]=\"getImageSrc(row, column)\"\n [attr.alt]=\"getImageAlt(row, column) || ''\"\n [attr.loading]=\"getImageLazy(row, column) ? 'lazy' : null\"\n [style.width.px]=\"getImageWidth(row, column)\"\n [style.height.px]=\"getImageHeight(row, column)\"\n [class.shape-rounded]=\"getImageShape(row, column) === 'rounded'\"\n [class.shape-circle]=\"getImageShape(row, column) === 'circle'\"\n [style.object-fit]=\"getImageFit(row, column)\" />\n </ng-container>\n <ng-container *ngSwitchCase=\"'badge'\">\n <span class=\"pfx-badge\" [ngClass]=\"getBadgeClasses(row, column)\">\n @if (getBadgeIcon(row, column); as bi) { <mat-icon class=\"pfx-badge-icon\">{{ bi }}</mat-icon> }\n <span class=\"pfx-badge-text\">{{ getBadgeText(row, column) }}</span>\n </span>\n </ng-container>\n <ng-container *ngSwitchDefault>\n {{ getCellValue(row, column) }}\n </ng-container>\n </ng-container>\n </div>\n </td>\n }\n\n <!-- Actions column -->\n @if (config.actions?.row?.enabled) {\n <td class=\"mat-mdc-cell praxis-actions-cell\" [class.dense]=\"dense\" [style.width]=\"getRowActionsWidthStyle()\">\n <div class=\"praxis-actions-cell__content\">\n @if (config.actions?.row?.display === 'icons' || !config.actions?.row?.display) {\n <ng-container *ngFor=\"let a of getInlineRowActions(row); trackBy: trackAction\">\n <button mat-icon-button class=\"praxis-icon-btn\"\n [disabled]=\"isActionDisabled(a, row)\"\n (click)=\"onRowAction(getActionId(a), row, $event)\"\n [matTooltip]=\"a.label || getActionId(a)\"\n matTooltipPosition=\"above\"\n matTooltipClass=\"praxis-tooltip\"\n [attr.aria-label]=\"a.label || getActionId(a)\"\n [color]=\"a.color || null\">\n <mat-icon [praxisIcon]=\"a.icon\"></mat-icon>\n </button>\n </ng-container>\n }\n @if (config.actions?.row?.display === 'buttons') {\n <ng-container *ngFor=\"let a of getInlineRowActions(row); trackBy: trackAction\">\n <button mat-flat-button class=\"praxis-row-btn\"\n [disabled]=\"isActionDisabled(a, row)\"\n (click)=\"onRowAction(getActionId(a), row, $event)\"\n [attr.aria-label]=\"a.label || getActionId(a)\"\n [color]=\"a.color || null\">\n <mat-icon [praxisIcon]=\"a.icon\"></mat-icon>\n <span>{{ a.label || getActionId(a) }}</span>\n </button>\n </ng-container>\n }\n @if (hasOverflowRowActions(row)) {\n <button mat-icon-button class=\"praxis-icon-btn praxis-more-btn\"\n [matMenuTriggerFor]=\"rowMoreMenuV\"\n [color]=\"getRowMenuButtonColor() || null\"\n aria-label=\"Mais a\u00E7\u00F5es\">\n <mat-icon [praxisIcon]=\"getRowMenuIcon()\"></mat-icon>\n </button>\n }\n <mat-menu #rowMoreMenuV=\"matMenu\" xPosition=\"before\">\n <ng-container *ngFor=\"let a of getOverflowRowActions(row); trackBy: trackAction\">\n <button mat-menu-item (click)=\"onRowAction(getActionId(a), row, $event)\" [disabled]=\"isActionDisabled(a, row)\">\n <mat-icon [color]=\"a.color || null\" [praxisIcon]=\"a.icon\"></mat-icon>\n <span>{{ a.label || getActionId(a) }}</span>\n </button>\n </ng-container>\n </mat-menu>\n </div>\n </td>\n }\n </tr>\n </tbody>\n </table>\n </cdk-virtual-scroll-viewport>\n}\n\n</div>\n@if (\n shouldRenderDataSurface()\n && !schemaError\n && !dataError\n && shouldRenderFloatingBulkActions()\n && getFloatingBulkActions().length\n && !shouldHideFloatingBulkActions()\n) {\n <div [class]=\"'praxis-floating-bulk-actions ' + getFloatingBulkPositionClass()\">\n @for (action of getFloatingBulkActions(); track getActionId(action)) {\n <button\n mat-mini-fab\n [color]=\"action.color || 'primary'\"\n [disabled]=\"isFloatingBulkActionDisabled(action)\"\n (click)=\"onToolbarAction({ action: getActionId(action), actionConfig: action })\"\n [attr.aria-label]=\"action.label || getActionId(action)\"\n [matTooltip]=\"action.label || getActionId(action)\"\n matTooltipPosition=\"left\"\n >\n <mat-icon [praxisIcon]=\"action.icon || 'done_all'\"></mat-icon>\n </button>\n }\n </div>\n}\n<!-- Barra de a\u00E7\u00F5es no rodap\u00E9 (opcional) -->\n@if (shouldRenderDataSurface() && !schemaError && !dataError && showToolbar && shouldRenderFooterToolbar()) {\n <praxis-table-toolbar\n [config]=\"config\"\n [backgroundColor]=\"getToolbarActionsBackgroundColor()\"\n [style.--pfx-filter-h]=\"getToolbarLayoutHeightHostStyle()\"\n [class.footer-flat]=\"hasBottomPaginator()\"\n class=\"praxis-toolbar-footer\"\n placement=\"footer\"\n [showMain]=\"shouldShowFooterToolbarMain()\"\n [showEndActions]=\"shouldShowFooterToolbarEndActions()\"\n [showReset]=\"shouldShowFooterToolbarReset()\"\n [showActionsGroup]=\"shouldShowToolbarActionsBottom()\"\n [showMobileActions]=\"shouldShowToolbarActionsBottom()\"\n [dslContext]=\"getToolbarDslContext()\"\n [dslFunctionRegistry]=\"dslFunctionRegistry\"\n (toolbarAction)=\"onToolbarAction($event)\"\n >\n <praxis-filter\n *ngIf=\"shouldShowFooterToolbarMain() && shouldRenderAdvancedFilter()\"\n advancedFilter\n [resourcePath]=\"getAdvancedFilterResourcePath()\"\n [filterId]=\"tableId\"\n [formId]=\"tableId\"\n [persistenceKey]=\"getAdvancedFilterPersistenceKey()\"\n [fieldMetadata]=\"getAdvancedFilterFieldMetadata()\"\n [editModeEnabled]=\"editModeEnabled\"\n [alwaysVisibleFields]=\"config.behavior?.filtering?.advancedFilters?.settings?.alwaysVisibleFields\"\n [alwaysVisibleFieldMetadataOverrides]=\"config.behavior?.filtering?.advancedFilters?.settings?.alwaysVisibleFieldMetadataOverrides ?? {}\"\n [selectedFieldIds]=\"config.behavior?.filtering?.advancedFilters?.settings?.selectedFieldIds ?? []\"\n [allowSaveTags]=\"config.behavior?.filtering?.advancedFilters?.settings?.allowSaveTags\"\n [changeDebounceMs]=\"config.behavior?.filtering?.advancedFilters?.settings?.changeDebounceMs ?? 300\"\n [i18n]=\"getFilterI18n()\"\n [mode]=\"'filter'\"\n [showFilterSettings]=\"editModeEnabled\"\n (submit)=\"onAdvancedFilterSubmit($event)\"\n (clear)=\"onAdvancedFilterClear()\"\n ></praxis-filter>\n <ng-container *ngIf=\"shouldShowFooterToolbarMain() && shouldRenderAdvancedFilter()\">\n <ng-content select=\"[advancedFilter]\"></ng-content>\n </ng-container>\n <ng-container *ngIf=\"shouldShowFooterToolbarMain() && shouldRenderAdvancedFilter()\">\n <ng-content select=\"[toolbar]\"></ng-content>\n </ng-container>\n @if (shouldShowFooterToolbarMain() && shouldRenderAdvancedFilter()) {\n @defer (on idle) {\n @if (aiAdapter) {\n <praxis-ai-assistant\n [adapter]=\"aiAdapter\"\n end-actions\n ></praxis-ai-assistant>\n }\n }\n }\n <button\n *ngIf=\"shouldShowFooterToolbarMain() && shouldRenderAdvancedFilter() && editModeEnabled\"\n end-actions\n mat-icon-button\n color=\"primary\"\n data-role=\"table-settings\"\n data-testid=\"table-settings-trigger\"\n (click)=\"openTableSettings()\"\n aria-label=\"Configura\u00E7\u00F5es\"\n [matBadge]=\"schemaOutdated ? '!' : ''\"\n [matBadgeHidden]=\"!schemaOutdated\"\n matBadgeColor=\"warn\"\n matBadgeSize=\"small\"\n matBadgePosition=\"above after\"\n [matTooltip]=\"schemaOutdated ? 'Schema do servidor mudou \u2014 Reconciliar' : 'Configura\u00E7\u00F5es'\"\n matTooltipPosition=\"below\"\n >\n <mat-icon>settings</mat-icon>\n </button>\n </praxis-table-toolbar>\n}\n<!-- Paginadores (top/bottom) -->\n@if (shouldRenderDataSurface() && !schemaError && !dataError && getPaginationEnabled() && (config.behavior?.pagination?.position === 'top' || config.behavior?.pagination?.position === 'both')) {\n <mat-paginator\n [length]=\"getPaginationLength()\"\n [pageSize]=\"getPaginationPageSize()\"\n [pageSizeOptions]=\"getPaginationPageSizeOptions()\"\n [showFirstLastButtons]=\"getPaginationShowFirstLast()\"\n (page)=\"onPageChange($event)\"\n [class.compact]=\"config.behavior?.pagination?.style === 'compact'\"\n >\n </mat-paginator>\n}\n\n@if (shouldRenderDataSurface() && !schemaError && !dataError && getPaginationEnabled() && (config.behavior?.pagination?.position === 'bottom' || config.behavior?.pagination?.position === 'both' || !config.behavior?.pagination?.position)) {\n <mat-paginator\n [length]=\"getPaginationLength()\"\n [pageSize]=\"getPaginationPageSize()\"\n [pageSizeOptions]=\"getPaginationPageSizeOptions()\"\n [showFirstLastButtons]=\"getPaginationShowFirstLast()\"\n (page)=\"onPageChange($event)\"\n [class.compact]=\"config.behavior?.pagination?.style === 'compact'\"\n [class.footer-stack]=\"shouldShowToolbarActionsBottom()\"\n >\n </mat-paginator>\n}\n", styles: ["@charset \"UTF-8\";table{width:100%}.praxis-visually-hidden-status{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}.praxis-column-reorder-status{margin:8px 0;padding:10px 12px;border-radius:8px;border:1px solid var(--p-table-border-color);background:var(--p-table-row-hover-bg);color:var(--p-table-header-fg);font-size:12px;line-height:1.4;box-shadow:0 4px 12px #00000014;animation:pfx-column-reorder-status-in var(--p-table-drag-status-enter-duration, .18s) var(--p-table-motion-easing, cubic-bezier(0, 0, .2, 1))}@keyframes pfx-column-reorder-status-in{0%{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:translateY(0)}}.praxis-actions-cell{height:100%;padding-inline:12px;white-space:nowrap}.pfx-expansion-col-header,.pfx-expansion-col-cell{width:52px;min-width:52px;text-align:center}.pfx-expansion-toggle{width:40px;height:40px}.pfx-expansion-toggle:focus-visible{outline:2px solid var(--md-sys-color-primary);outline-offset:2px}.pfx-expansion-detail-row{background:var(--md-sys-color-surface-container-low)}.pfx-expansion-detail-cell{padding:0!important;border-bottom:1px solid var(--p-table-border-color)}.pfx-expansion-detail-panel{padding:12px 16px;border-left:3px solid var(--md-sys-color-primary)}.pfx-expansion-detail-schema{margin:0;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:12px;line-height:1.4;white-space:pre-wrap;word-break:break-word;color:var(--md-sys-color-on-surface-variant)}.pfx-expansion-detail-message{font-size:13px;color:var(--md-sys-color-on-surface-variant)}.pfx-expansion-detail-message--error{color:var(--md-sys-color-error)}.pfx-expansion-detail-stack{display:grid;gap:10px}.pfx-expansion-detail-tabs{display:flex;flex-wrap:wrap;gap:8px;margin-bottom:10px}.pfx-expansion-detail-tab-btn{border:1px solid var(--p-table-border-color);background:var(--md-sys-color-surface);color:var(--md-sys-color-on-surface);border-radius:999px;padding:6px 12px;font-size:12px;line-height:1.2;cursor:pointer}.pfx-expansion-detail-tab-btn.is-active{border-color:var(--md-sys-color-primary);color:var(--md-sys-color-primary);font-weight:600}.pfx-expansion-detail-tab-btn:focus-visible{outline:2px solid var(--md-sys-color-primary);outline-offset:2px}.pfx-expansion-detail-tab-panel{display:grid;gap:10px}.pfx-expansion-node{border:1px solid var(--p-table-border-color);border-radius:8px;padding:10px 12px;background:var(--md-sys-color-surface)}.pfx-expansion-node-card__header{margin-bottom:8px}.pfx-expansion-node-card__title{margin:0;font-size:14px;line-height:1.3}.pfx-expansion-node-card__subtitle{margin:4px 0 0;font-size:12px;color:var(--md-sys-color-on-surface-variant)}.pfx-expansion-node-value{display:flex;align-items:baseline;gap:8px}.pfx-expansion-node-value__label{color:var(--md-sys-color-on-surface-variant);font-size:12px}.pfx-expansion-node-value__content{font-size:14px}.pfx-expansion-node-list__title{margin:0 0 6px;font-size:13px}.pfx-expansion-node-list ul{margin:0;padding-left:18px}.pfx-expansion-node-richtext :where(p,ul,ol,h1,h2,h3,h4,h5,h6){margin-top:0;margin-bottom:8px}.pfx-expansion-node-placeholder{font-size:12px;color:var(--md-sys-color-on-surface-variant)}:host.density-compact{--p-header-padding: 8px 12px;--p-cell-padding: 8px 12px;--p-actions-btn-size: 32px;--p-actions-icon-size: 18px}:host.density-comfortable{--p-header-padding: 12px 16px;--p-cell-padding: 12px 16px;--p-actions-btn-size: 40px;--p-actions-icon-size: 22px}:host.density-spacious{--p-header-padding: 16px 20px;--p-cell-padding: 16px 20px;--p-actions-btn-size: 44px;--p-actions-icon-size: 24px}:host.density-compact ::ng-deep .mat-mdc-cell{padding:var(--p-cell-padding, 8px 12px)}:host.density-comfortable ::ng-deep .mat-mdc-cell{padding:var(--p-cell-padding, 12px 16px)}:host.density-spacious ::ng-deep .mat-mdc-cell{padding:var(--p-cell-padding, 16px 20px)}:host.density-compact .praxis-actions-cell{padding-inline:8px}:host.density-spacious .praxis-actions-cell{padding-inline:16px}.praxis-actions-cell__content{display:flex;align-items:center;justify-content:flex-end;gap:8px;width:100%}.praxis-actions-cell.dense .praxis-actions-cell__content{gap:6px}.praxis-icon-btn{width:var(--p-actions-btn-size, 40px);height:var(--p-actions-btn-size, 40px);border:0;background:transparent;padding:0;display:inline-flex;align-items:center;justify-content:center;border-radius:9999px;cursor:pointer;--mat-icon-button-state-layer-size: var(--p-actions-btn-size, 40px)}.praxis-icon-btn:hover{background:var(--md-sys-color-surface-variant)}.praxis-icon-btn:focus-visible{outline:2px solid var(--md-sys-color-primary);outline-offset:2px}.praxis-icon-btn mat-icon,.praxis-icon-btn .mat-icon{font-size:var(--p-actions-icon-size, 22px);width:var(--p-actions-icon-size, 22px);height:var(--p-actions-icon-size, 22px);line-height:var(--p-actions-icon-size, 22px)}.praxis-more-btn{width:var(--p-actions-more-btn-size, var(--p-actions-btn-size, 40px));height:var(--p-actions-more-btn-size, var(--p-actions-btn-size, 40px));--mat-icon-button-state-layer-size: var(--p-actions-more-btn-size, var(--p-actions-btn-size, 40px));background-image:var(--p-actions-more-btn-gradient, none);background-size:100% 100%;background-repeat:no-repeat}.praxis-more-btn mat-icon,.praxis-more-btn .mat-icon{font-size:var(--p-actions-more-icon-size, var(--p-actions-icon-size, 22px));width:var(--p-actions-more-icon-size, var(--p-actions-icon-size, 22px));height:var(--p-actions-more-icon-size, var(--p-actions-icon-size, 22px));line-height:var(--p-actions-more-icon-size, var(--p-actions-icon-size, 22px));color:var(--p-actions-more-icon-color);background-image:var(--p-actions-more-icon-gradient, none);-webkit-background-clip:text;background-clip:text}.praxis-icon-btn.destructive mat-icon{color:var(--md-sys-color-error)}.mat-mdc-tooltip.praxis-tooltip{margin-top:-8px;margin-bottom:8px}.spacer{flex:1 1 auto}.praxis-table-header{display:flex;flex-wrap:wrap;align-items:flex-start;gap:8px;margin:16px 0 12px;width:100%;clear:both;position:relative}.praxis-table-header.stacked{margin:0}.praxis-table-header>praxis-table-toolbar{flex:1 0 100%}.praxis-floating-bulk-actions{position:fixed;z-index:1001;display:inline-flex;align-items:center;gap:8px;padding:8px;border-radius:999px;background:var(--md-sys-color-surface-container-highest);box-shadow:0 8px 20px #00000029}.praxis-floating-bulk-actions.pos-bottom-right{right:20px;bottom:20px}.praxis-floating-bulk-actions.pos-bottom-left{left:20px;bottom:20px}.praxis-floating-bulk-actions.pos-top-right{right:20px;top:20px}.praxis-floating-bulk-actions.pos-top-left{left:20px;top:20px}@media(max-width:768px){.praxis-floating-bulk-actions{gap:6px;padding:6px}.praxis-floating-bulk-actions.pos-bottom-right{right:12px;left:auto;bottom:12px}.praxis-floating-bulk-actions.pos-bottom-left{left:12px;right:auto;bottom:12px}.praxis-floating-bulk-actions.pos-top-right{right:12px;left:auto;top:12px}.praxis-floating-bulk-actions.pos-top-left{left:12px;right:auto;top:12px}}:host{display:block;width:100%;min-width:0;max-width:100%;--pfx-toolbar-pad-y: 6px;--pfx-toolbar-pad-x: 12px;--p-table-bg: var(--md-sys-color-surface-container-highest);--p-table-text-color: var(--md-sys-color-on-surface);--p-table-header-bg: var(--md-sys-color-surface-container-highest);--p-table-header-fg: var(--md-sys-color-on-surface);--p-table-border-color: var(--md-sys-color-outline-variant);--p-table-row-even-bg: var(--md-sys-color-surface-container);--p-table-row-hover-bg: var(--md-sys-color-surface-container-high);--p-table-row-selected-bg: var(--md-sys-color-primary-container);--p-table-badge-soft-primary-bg: var(--md-sys-color-primary-container);--p-table-badge-soft-primary-fg: var(--md-sys-color-on-primary-container);--p-table-badge-soft-accent-bg: var(--md-sys-color-secondary-container);--p-table-badge-soft-accent-fg: var(--md-sys-color-on-secondary-container);--p-table-badge-soft-warn-bg: var(--md-sys-color-error-container);--p-table-badge-soft-warn-fg: var(--md-sys-color-on-error-container);--p-table-state-success-bg: var(--md-sys-color-tertiary-container);--p-table-state-success-fg: var(--md-sys-color-on-tertiary-container);--p-table-state-warning-bg: var(--md-sys-color-secondary-container);--p-table-state-warning-fg: var(--md-sys-color-on-secondary-container);--p-table-state-danger-bg: var(--md-sys-color-error-container);--p-table-state-danger-fg: var(--md-sys-color-on-error-container);--p-table-state-highlight-bg: var(--md-sys-color-primary-container);--p-table-state-highlight-fg: var(--md-sys-color-on-primary-container);--p-table-drag-handle-size: 14px;--p-table-drag-handle-color: var(--md-sys-color-on-surface-variant);--p-table-drag-handle-hover-color: var(--md-sys-color-on-surface);--p-table-drag-handle-base-opacity: 0;--p-table-drag-handle-visible-opacity: .72;--p-table-drag-handle-active-opacity: 1;--p-table-drag-handle-transition-duration: .16s;--p-table-reorder-transition-duration: .16s;--p-table-drag-preview-scale: 1.01;--p-table-drag-status-enter-duration: .18s;--p-table-drag-preview-shadow: 0 14px 32px rgba(0, 0, 0, .28), 0 0 0 1px var(--p-table-border-color)}:host ::ng-deep .mat-mdc-table{background:var(--p-table-bg);color:var(--p-table-text-color);border-radius:12px 12px 0 0;width:100%;box-shadow:var(--p-table-surface-shadow);transition:box-shadow var(--p-table-selection-transition-duration, .18s) var(--p-table-motion-easing, cubic-bezier(0, 0, .2, 1))}:host ::ng-deep .mat-mdc-table:hover{box-shadow:var(--p-table-surface-shadow-hover, var(--p-table-surface-shadow))}:host ::ng-deep .mat-mdc-table.table-stack-top{border-top-left-radius:0;border-top-right-radius:0}:host ::ng-deep .praxis-toolbar-footer{border:0 solid var(--p-table-border-color);border-top:0;border-radius:0;background:var(--p-table-bg)}:host ::ng-deep .mat-mdc-paginator.footer-stack{border-top-left-radius:0;border-top-right-radius:0;border-top:0}:host ::ng-deep .mat-mdc-paginator.footer-stack .mat-mdc-paginator-container{padding:8px 12px}:host [data-role=table-settings].mat-mdc-icon-button{--mdc-icon-button-icon-color: var(--md-sys-color-primary);color:var(--md-sys-color-primary)}.pfx-link{color:var(--md-sys-color-primary);text-decoration:underline;cursor:pointer}.pfx-chip{display:inline-flex;align-items:center;gap:4px;padding:2px 8px;border-radius:10px;font-size:12px;line-height:1;border:1px solid transparent}.pfx-chip-icon{font-size:14px;width:14px;height:14px}.pfx-chip--outlined{background:transparent;border-color:var(--md-sys-color-outline-variant);color:var(--md-sys-color-on-surface)}.pfx-chip--filled-primary{background:var(--md-sys-color-primary);color:var(--md-sys-color-on-primary)}.pfx-chip--filled-accent{background:var(--md-sys-color-secondary);color:var(--md-sys-color-on-secondary)}.pfx-chip--filled-warn{background:var(--md-sys-color-error);color:var(--md-sys-color-on-error)}.pfx-chip--soft-primary{background:var(--p-table-badge-soft-primary-bg);color:var(--p-table-badge-soft-primary-fg)}.pfx-chip--soft-accent{background:var(--p-table-badge-soft-accent-bg);color:var(--p-table-badge-soft-accent-fg)}.pfx-chip--soft-warn{background:var(--p-table-badge-soft-warn-bg);color:var(--p-table-badge-soft-warn-fg)}.pfx-progress{position:relative;width:100%;max-width:140px;height:8px;background:var(--md-sys-color-surface-container-highest);border-radius:4px;overflow:hidden;display:inline-block;vertical-align:middle}.pfx-progress-bar{height:100%;background:var(--md-sys-color-primary);transition:width .2s ease}.pfx-progress-label{margin-left:8px;font-size:12px;opacity:.8;display:inline-block;vertical-align:middle}.pfx-avatar{display:inline-flex;align-items:center;justify-content:center;background:var(--md-sys-color-surface-container);color:var(--md-sys-color-on-surface);border-radius:4px;overflow:hidden;font-weight:600}.pfx-avatar.shape-rounded{border-radius:8px}.pfx-avatar.shape-circle{border-radius:999px}.pfx-avatar--initials{text-transform:uppercase;font-size:12px}.pfx-cell-compose{display:inline-flex;align-items:center;gap:6px}.pfx-cell-compose.dir-col{flex-direction:column;align-items:stretch}.pfx-cell-compose.align-start{justify-content:flex-start}.pfx-cell-compose.align-center{justify-content:center}.pfx-cell-compose.align-end{justify-content:flex-end}.pfx-cell-compose.wrap{flex-wrap:wrap}.pfx-cell-compose.ellipsis{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.px-scroll-viewport{width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch;overscroll-behavior-x:contain}.px-scroll-viewport.scroll-none{overflow-x:visible}.px-scroll-viewport.scroll-auto ::ng-deep .mat-mdc-table{width:max-content;min-width:100%}.px-scroll-viewport.scroll-wrap ::ng-deep .mat-mdc-header-cell,.px-scroll-viewport.scroll-wrap ::ng-deep .mat-mdc-cell{white-space:normal;text-overflow:initial}.px-scroll-viewport.scroll-wrap ::ng-deep .mat-mdc-table{width:100%}:host ::ng-deep .mat-mdc-header-row{position:sticky;top:0;z-index:1;background:var(--p-table-header-bg);color:var(--p-table-header-fg);box-shadow:var(--p-table-header-shadow, 0 1px 0 var(--p-table-border-color));border-bottom:1px solid var(--p-table-border-color)}:host ::ng-deep .mat-mdc-header-cell,:host ::ng-deep .mat-sort-header-content,:host ::ng-deep .mat-mdc-header-row .mat-icon{color:var(--p-table-header-fg)!important;font-weight:600}:host ::ng-deep .mat-mdc-header-cell.mat-sort-header-sorted .mat-sort-header-arrow,:host ::ng-deep .mat-mdc-header-cell:hover .mat-sort-header-arrow{color:var(--p-table-header-fg)!important}:host ::ng-deep .mat-mdc-header-cell.mat-sort-header-sorted .mat-sort-header-arrow .mat-sort-header-indicator,:host ::ng-deep .mat-mdc-header-cell.mat-sort-header-sorted .mat-sort-header-arrow .mat-sort-header-stem,:host ::ng-deep .mat-mdc-header-cell.mat-sort-header-sorted .mat-sort-header-arrow .mat-sort-header-pointer,:host ::ng-deep .mat-mdc-header-cell.mat-sort-header-sorted .mat-sort-header-arrow .mat-sort-header-pointer-left,:host ::ng-deep .mat-mdc-header-cell.mat-sort-header-sorted .mat-sort-header-arrow .mat-sort-header-pointer-right{border-color:var(--p-table-header-fg)!important;background:var(--p-table-header-fg)!important}:host ::ng-deep .mat-mdc-header-cell{padding:var(--p-header-padding, 12px 16px)!important;font-size:var(--p-header-font-size, inherit);font-weight:var(--p-header-font-weight, 600);letter-spacing:var(--p-header-letter-spacing, normal);text-transform:var(--p-header-text-transform, none);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}:host ::ng-deep .pfx-column-drag-enabled .mat-mdc-header-cell.praxis-header-draggable .mat-sort-header-container{display:flex;align-items:center;width:100%;gap:8px;cursor:inherit}:host ::ng-deep .pfx-column-drag-enabled .mat-mdc-header-cell.praxis-header-draggable{-webkit-user-select:none;user-select:none;cursor:grab}:host ::ng-deep .pfx-column-drag-enabled .mat-mdc-header-cell.praxis-header-draggable.cdk-drag-dragging{cursor:grabbing}:host ::ng-deep .pfx-column-drag-enabled .mat-mdc-header-cell.praxis-header-draggable .mat-sort-header-content{display:inline-flex;align-items:center;gap:8px;flex:1 1 auto;min-width:0}:host ::ng-deep .pfx-column-drag-enabled .mat-mdc-header-cell .praxis-header-label{display:inline-flex;align-items:center;flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis}:host ::ng-deep .pfx-column-drag-enabled .mat-mdc-header-cell .praxis-column-drag-handle{-webkit-appearance:none;appearance:none;border:0;background:transparent;color:var(--p-table-drag-handle-color);width:var(--p-table-drag-handle-size);min-width:var(--p-table-drag-handle-size);height:var(--p-table-drag-handle-size);padding:0;display:inline-flex;align-items:center;justify-content:center;border-radius:0;cursor:inherit;pointer-events:none;touch-action:none;opacity:var(--p-table-drag-handle-base-opacity, 0);transform:none;transition:opacity var(--p-table-drag-handle-transition-duration, .16s) var(--p-table-motion-easing, cubic-bezier(0, 0, .2, 1)),color var(--p-table-drag-handle-transition-duration, .16s) var(--p-table-motion-easing, cubic-bezier(0, 0, .2, 1))}:host ::ng-deep .pfx-column-drag-enabled .mat-mdc-header-cell.praxis-header-draggable:hover .praxis-column-drag-handle,:host ::ng-deep .pfx-column-drag-enabled .mat-mdc-header-cell.praxis-header-draggable:focus-within .praxis-column-drag-handle{opacity:var(--p-table-drag-handle-visible-opacity, .72);color:var(--p-table-drag-handle-hover-color, var(--p-table-drag-handle-color))}:host ::ng-deep .pfx-column-drag-enabled .mat-mdc-header-cell .praxis-column-drag-handle:active{opacity:var(--p-table-drag-handle-active-opacity, 1);cursor:grabbing}:host ::ng-deep .pfx-column-drag-enabled .mat-mdc-header-cell .praxis-column-drag-handle .mat-icon{font-size:14px;width:14px;height:14px;line-height:14px;transition:transform .18s var(--p-table-motion-easing, cubic-bezier(0, 0, .2, 1))}:host ::ng-deep .pfx-column-drag-enabled .mat-mdc-header-cell.praxis-header-draggable:hover .praxis-column-drag-handle .mat-icon{transform:none}:host ::ng-deep .pfx-column-drag-indicator .cdk-drop-list-dragging .mat-mdc-header-cell:not(.cdk-drag-placeholder){transition:transform var(--p-table-reorder-transition-duration, .18s) var(--p-table-motion-easing, cubic-bezier(0, 0, .2, 1))}:host ::ng-deep .pfx-column-drag-indicator .mat-mdc-header-cell.cdk-drag-animating{transition:transform var(--p-table-reorder-transition-duration, .16s) var(--p-table-motion-easing, cubic-bezier(0, 0, .2, 1))}.pfx-column-drag-preview{box-sizing:border-box;border-radius:10px;border:1px solid var(--p-table-border-color);background:linear-gradient(135deg,var(--p-table-header-bg) 0%,var(--p-table-row-hover-bg) 100%);color:var(--p-table-header-fg);box-shadow:var(--p-table-drag-preview-shadow);transform:scale(var(--p-table-drag-preview-scale, 1.01));pointer-events:none;z-index:1000}.pfx-column-drag-preview .praxis-column-drag-handle,.pfx-column-drag-preview .mat-sort-header-arrow,.pfx-column-drag-preview .mat-sort-header-indicator,.pfx-column-drag-preview .mat-sort-header-stem,.pfx-column-drag-preview .mat-sort-header-pointer,.pfx-column-drag-preview .mat-sort-header-pointer-left,.pfx-column-drag-preview .mat-sort-header-pointer-right{display:none!important}.pfx-column-drag-preview .mat-sort-header-container{padding-right:0!important}.pfx-column-drag-preview .mat-sort-header-content,.pfx-column-drag-preview .praxis-header-label{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}:host ::ng-deep .pfx-column-drag-indicator .cdk-drag-placeholder{opacity:1;border:1px dashed var(--p-table-border-color);background:var(--p-table-row-hover-bg)}:host ::ng-deep .pfx-column-drag-indicator .cdk-drag-placeholder *{opacity:0}:host ::ng-deep .pfx-column-drag-indicator .mat-mdc-header-cell.cdk-drag-dragging{opacity:.58}@media(prefers-reduced-motion:reduce){:host ::ng-deep .pfx-column-drag-indicator .cdk-drop-list-dragging .mat-mdc-header-cell:not(.cdk-drag-placeholder){transition:none}:host ::ng-deep .pfx-column-drag-enabled .mat-mdc-header-cell .praxis-column-drag-handle,:host ::ng-deep .pfx-column-drag-enabled .mat-mdc-header-cell .praxis-column-drag-handle .mat-icon,.pfx-column-drag-preview{transition:none;transform:none}.praxis-column-reorder-status{animation:none}:host ::ng-deep .mat-mdc-row{transition:none}:host ::ng-deep .mat-mdc-table{transition:none}}.praxis-actions-header{text-align:right}.praxis-actions-header.align-start{text-align:left}.praxis-actions-header.align-center{text-align:center}.praxis-actions-header.align-end{text-align:right}.praxis-actions-header .praxis-actions-header__content{display:inline-flex;align-items:center;gap:var(--p-actions-header-gap, 6px);color:var(--p-actions-header-color, inherit)}.praxis-actions-header .praxis-actions-header__content .mat-icon{font-size:18px;width:18px;height:18px;line-height:18px}:host ::ng-deep .mat-mdc-header-cell .mat-sort-header-container{padding-right:20px}:host ::ng-deep .pfx-column-drag-enabled .mat-mdc-header-cell.praxis-header-draggable .mat-sort-header-container{padding-right:12px}@media(pointer:coarse){:host{--p-table-drag-handle-size: 18px;--p-table-drag-handle-base-opacity: .56;--p-table-drag-handle-visible-opacity: .92}}:host ::ng-deep .mat-mdc-cell{color:var(--p-table-text-color);font-size:var(--p-cell-font-size, inherit);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}:host ::ng-deep .mat-mdc-cell .pfx-cell-content,:host ::ng-deep .mat-cell .pfx-cell-content{display:inline-flex;align-items:center;gap:6px;width:100%;min-width:0;overflow:hidden}:host ::ng-deep .pfx-cell-content.pfx-cell-anim{animation-duration:var(--pfx-cell-anim-duration, .8s);animation-delay:var(--pfx-cell-anim-delay, 0ms);animation-fill-mode:both;animation-timing-function:ease-in-out}:host ::ng-deep .pfx-cell-content.pfx-cell-anim.pfx-cell-anim--once{animation-iteration-count:1}:host ::ng-deep .pfx-cell-content.pfx-cell-anim.pfx-cell-anim--loop{animation-iteration-count:infinite}:host ::ng-deep .pfx-cell-content.pfx-cell-anim.pfx-cell-anim--count{animation-iteration-count:var(--pfx-cell-anim-iteration-count, 1)}:host ::ng-deep .pfx-cell-content.pfx-cell-anim.pfx-cell-anim--on-hover{animation-play-state:paused}:host ::ng-deep .mat-mdc-cell:hover .pfx-cell-content.pfx-cell-anim.pfx-cell-anim--on-hover,:host ::ng-deep .mat-cell:hover .pfx-cell-content.pfx-cell-anim.pfx-cell-anim--on-hover{animation-play-state:running}:host ::ng-deep .pfx-cell-content.pfx-cell-anim.pfx-cell-anim--pulse{animation-name:pfx-cell-pulse}:host ::ng-deep .pfx-cell-content.pfx-cell-anim.pfx-cell-anim--blink{animation-name:pfx-cell-blink}:host ::ng-deep .pfx-cell-content.pfx-cell-anim.pfx-cell-anim--grow{animation-name:pfx-cell-grow}:host ::ng-deep .pfx-cell-content.pfx-cell-anim.pfx-cell-anim--fade{animation-name:pfx-cell-fade}:host ::ng-deep .pfx-cell-content.pfx-cell-anim.pfx-cell-anim--slide-in{animation-name:pfx-cell-slide-in}:host ::ng-deep .pfx-cell-content.pfx-cell-anim.pfx-cell-anim--border-pulse{animation-name:pfx-cell-border-pulse}@keyframes pfx-cell-pulse{0%{transform:scale(1)}50%{transform:scale(var(--pfx-cell-anim-scale-peak, 1.015))}to{transform:scale(1)}}@keyframes pfx-cell-blink{0%,49%{opacity:1}50%,to{opacity:var(--pfx-cell-anim-min-opacity, .35)}}@keyframes pfx-cell-grow{0%{transform:scale(.985)}to{transform:scale(1)}}@keyframes pfx-cell-fade{0%{opacity:0}to{opacity:1}}@keyframes pfx-cell-slide-in{0%{opacity:0;transform:translateY(var(--pfx-cell-anim-slide-distance, 4px))}to{opacity:1;transform:translateY(0)}}@keyframes pfx-cell-border-pulse{0%,to{box-shadow:inset 0 0 rgba(var(--pfx-cell-anim-border-rgb, 25, 118, 210),0)}50%{box-shadow:inset 0 0 0 2px rgba(var(--pfx-cell-anim-border-rgb, 25, 118, 210),var(--pfx-cell-anim-border-strength, .3))}}@media(prefers-reduced-motion:reduce){:host ::ng-deep .pfx-cell-content.pfx-cell-anim{animation:none!important}}:host ::ng-deep .mat-mdc-row:hover{background:var(--p-table-row-hover-bg)}:host ::ng-deep .mat-mdc-row{transition:background-color var(--p-table-hover-transition-duration, .18s) var(--p-table-motion-easing, cubic-bezier(0, 0, .2, 1)),box-shadow var(--p-table-selection-transition-duration, .18s) var(--p-table-motion-easing, cubic-bezier(0, 0, .2, 1))}:host ::ng-deep .mat-mdc-row.pfx-row-anim{animation-duration:var(--pfx-row-anim-duration, .8s);animation-delay:var(--pfx-row-anim-delay, 0ms);animation-fill-mode:both;animation-timing-function:ease-in-out}:host ::ng-deep .mat-mdc-row.pfx-row-anim.pfx-row-anim--once{animation-iteration-count:1}:host ::ng-deep .mat-mdc-row.pfx-row-anim.pfx-row-anim--loop{animation-iteration-count:infinite}:host ::ng-deep .mat-mdc-row.pfx-row-anim.pfx-row-anim--count{animation-iteration-count:var(--pfx-row-anim-iteration-count, 1)}:host ::ng-deep .mat-mdc-row.pfx-row-anim.pfx-row-anim--on-hover{animation-play-state:paused}:host ::ng-deep .mat-mdc-row.pfx-row-anim.pfx-row-anim--on-hover:hover{animation-play-state:running}:host ::ng-deep .mat-mdc-row.pfx-row-anim.pfx-row-anim--pulse{animation-name:pfx-row-pulse}:host ::ng-deep .mat-mdc-row.pfx-row-anim.pfx-row-anim--blink{animation-name:pfx-row-blink}:host ::ng-deep .mat-mdc-row.pfx-row-anim.pfx-row-anim--grow{animation-name:pfx-row-grow}:host ::ng-deep .mat-mdc-row.pfx-row-anim.pfx-row-anim--fade{animation-name:pfx-row-fade}:host ::ng-deep .mat-mdc-row.pfx-row-anim.pfx-row-anim--slide-in{animation-name:pfx-row-slide-in}:host ::ng-deep .mat-mdc-row.pfx-row-anim.pfx-row-anim--border-pulse{animation-name:pfx-row-border-pulse}@keyframes pfx-row-pulse{0%{transform:scale(1)}50%{transform:scale(var(--pfx-row-anim-scale-peak, 1.015))}to{transform:scale(1)}}@keyframes pfx-row-blink{0%,49%{opacity:1}50%,to{opacity:var(--pfx-row-anim-min-opacity, .35)}}@keyframes pfx-row-grow{0%{transform:scale(.985)}to{transform:scale(1)}}@keyframes pfx-row-fade{0%{opacity:0}to{opacity:1}}@keyframes pfx-row-slide-in{0%{opacity:0;transform:translateY(var(--pfx-row-anim-slide-distance, 4px))}to{opacity:1;transform:translateY(0)}}@keyframes pfx-row-border-pulse{0%,to{box-shadow:inset 0 0 rgba(var(--pfx-row-anim-border-rgb, 25, 118, 210),0)}50%{box-shadow:inset 0 0 0 2px rgba(var(--pfx-row-anim-border-rgb, 25, 118, 210),var(--pfx-row-anim-border-strength, .3))}}@media(prefers-reduced-motion:reduce){:host ::ng-deep .mat-mdc-row.pfx-row-anim{animation:none!important}}:host ::ng-deep .mat-mdc-row:nth-child(2n){background:var(--p-table-row-even-bg)}:host ::ng-deep .mat-mdc-row:nth-child(2n):hover{background:var(--p-table-row-hover-bg)}:host ::ng-deep .mat-mdc-row.pfx-row-selected,:host ::ng-deep .mat-mdc-row.pfx-row-selected:hover{background:var(--p-table-row-selected-bg)}:host.row-borders ::ng-deep .mat-mdc-row .mat-mdc-cell{border-bottom:1px solid var(--p-table-border-color)}:host.row-borders ::ng-deep .mat-mdc-header-row .mat-mdc-header-cell{border-bottom:none}:host.col-borders ::ng-deep .mat-mdc-header-row .mat-mdc-header-cell,:host.col-borders ::ng-deep .mat-mdc-row .mat-mdc-cell{border-right:1px solid var(--p-table-border-color)}:host.col-borders ::ng-deep .mat-mdc-header-row .mat-mdc-header-cell:last-child,:host.col-borders ::ng-deep .mat-mdc-row .mat-mdc-cell:last-child{border-right:none}.ptable-error{display:flex;align-items:center;gap:12px;padding:12px;margin:8px 0;border:1px solid var(--md-sys-color-error);border-radius:8px}.ptable-error__content{flex:1}.ptable-error__title{font-weight:600}.ptable-info-banner{display:flex;gap:12px;align-items:center;padding:8px 12px;margin:8px 0;border-radius:8px;border:1px solid var(--md-sys-color-primary);background:var(--md-sys-color-primary-container);color:var(--md-sys-color-on-primary-container)}.ptable-info-banner .text{flex:1;font-weight:600}.ptable-info-banner .actions{display:flex;gap:8px}.pfx-cell-image{display:inline-block;vertical-align:middle;background:var(--md-sys-color-surface-variant);border:1px solid var(--md-sys-color-outline-variant)}.pfx-cell-image.shape-rounded{border-radius:8px}.pfx-cell-image.shape-circle{border-radius:9999px}.pfx-badge{display:inline-flex;align-items:center;gap:6px;line-height:1;padding:4px 8px;border-radius:9999px;font-size:12px;font-weight:600;border:1px solid transparent}.pfx-badge .pfx-badge-icon{font-size:16px;width:16px;height:16px}.pfx-badge--filled-primary{background:var(--md-sys-color-primary);color:var(--md-sys-color-on-primary)}.pfx-badge--filled-accent{background:var(--md-sys-color-secondary);color:var(--md-sys-color-on-secondary)}.pfx-badge--filled-warn{background:var(--md-sys-color-error);color:var(--md-sys-color-on-error)}.pfx-badge--outlined{background:transparent;border-color:var(--md-sys-color-outline-variant);color:inherit}.pfx-badge--soft-primary{background:var(--p-table-badge-soft-primary-bg);color:var(--p-table-badge-soft-primary-fg)}.pfx-badge--soft-accent{background:var(--p-table-badge-soft-accent-bg);color:var(--p-table-badge-soft-accent-fg)}.pfx-badge--soft-warn{background:var(--p-table-badge-soft-warn-bg);color:var(--p-table-badge-soft-warn-fg)}.row--success,.row--success td,td.row--success{background-color:var(--p-table-state-success-bg)!important;color:var(--p-table-state-success-fg)!important}.row--warning,.row--warning td,td.row--warning{background-color:var(--p-table-state-warning-bg)!important;color:var(--p-table-state-warning-fg)!important}.row--danger,.row--danger td,td.row--danger{background-color:var(--p-table-state-danger-bg)!important;color:var(--p-table-state-danger-fg)!important}.row--highlight,.row--highlight td,td.row--highlight{background-color:var(--p-table-state-highlight-bg)!important;color:var(--p-table-state-highlight-fg)!important;font-weight:600}.row--muted,.row--muted td,td.row--muted{opacity:.7;filter:saturate(.6)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1$2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i1$2.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: i1$2.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i1$2.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "directive", type: i1$2.NgSwitchDefault, selector: "[ngSwitchDefault]" }, { kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: ScrollingModule }, { kind: "directive", type: i10$3.CdkScrollable, selector: "[cdk-scrollable], [cdkScrollable]" }, { kind: "directive", type: i11$1.ɵɵCdkFixedSizeVirtualScroll, selector: "cdk-virtual-scroll-viewport[itemSize]", inputs: ["itemSize", "minBufferPx", "maxBufferPx"] }, { kind: "directive", type: i11$1.ɵɵCdkVirtualForOf, selector: "[cdkVirtualFor][cdkVirtualForOf]", inputs: ["cdkVirtualForOf", "cdkVirtualForTrackBy", "cdkVirtualForTemplate", "cdkVirtualForTemplateCacheSize"] }, { kind: "component", type: i11$1.ɵɵCdkVirtualScrollViewport, selector: "cdk-virtual-scroll-viewport", inputs: ["orientation", "appendOnly"], outputs: ["scrolledIndexChange"] }, { kind: "ngmodule", type: DragDropModule }, { kind: "directive", type: i12.CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer", "cdkDropListHasAnchor"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: i12.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "ngmodule", type: MatBadgeModule }, { kind: "directive", type: i15$2.MatBadge, selector: "[matBadge]", inputs: ["matBadgeColor", "matBadgeOverlap", "matBadgeDisabled", "matBadgePosition", "matBadge", "matBadgeDescription", "matBadgeSize", "matBadgeHidden"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3.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: "component", type: i3.MatMiniFabButton, selector: "button[mat-mini-fab], a[mat-mini-fab], button[matMiniFab], a[matMiniFab]", exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i3.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatCheckboxModule }, { kind: "component", type: i9.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i5.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i17.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: i17.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i17.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: MatPaginatorModule }, { kind: "component", type: i18.MatPaginator, selector: "mat-paginator", inputs: ["color", "pageIndex", "length", "pageSize", "pageSizeOptions", "hidePageSize", "showFirstLastButtons", "selectConfig", "disabled"], outputs: ["page"], exportAs: ["matPaginator"] }, { kind: "ngmodule", type: MatSlideToggleModule }, { kind: "component", type: i6$1.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: MatSnackBarModule }, { kind: "ngmodule", type: MatSortModule }, { kind: "directive", type: i20.MatSort, selector: "[matSort]", inputs: ["matSortActive", "matSortStart", "matSortDirection", "matSortDisableClear", "matSortDisabled"], outputs: ["matSortChange"], exportAs: ["matSort"] }, { kind: "component", type: i20.MatSortHeader, selector: "[mat-sort-header]", inputs: ["mat-sort-header", "arrowPosition", "start", "disabled", "sortActionDescription", "disableClear"], exportAs: ["matSortHeader"] }, { kind: "ngmodule", type: MatTableModule }, { kind: "component", type: i8$1.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i8$1.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i8$1.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i8$1.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i8$1.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i8$1.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i8$1.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i8$1.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i8$1.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i8$1.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i10.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: PraxisFilter, selector: "praxis-filter", inputs: ["resourcePath", "fieldMetadata", "filterId", "formId", "componentInstanceId", "mode", "notifyIfOutdated", "snoozeMs", "autoOpenSettingsOnOutdated", "editModeEnabled", "value", "alwaysVisibleFields", "alwaysVisibleFieldMetadataOverrides", "selectedFieldIds", "tags", "allowSaveTags", "persistenceKey", "i18n", "changeDebounceMs", "showFilterSettings", "confirmTagDelete", "placeBooleansInActions", "showToggleLabels", "useInlineSelectVariant", "useInlineSearchableSelectVariant", "useInlineMultiSelectVariant", "useInlineInputVariant", "useInlineToggleVariant", "useInlineRangeVariant", "useInlineDateVariant", "useInlineDateRangeVariant", "useInlineTimeVariant", "useInlineTimeRangeVariant", "useInlineTreeSelectVariant", "alwaysMinWidth", "alwaysColsMd", "alwaysColsLg", "tagColor", "tagVariant", "tagButtonColor", "actionsButtonColor", "actionsVariant", "overlayVariant", "overlayBackdrop", "advancedOpenMode", "advancedClearButtonsEnabled"], outputs: ["submit", "change", "clear", "modeChange", "requestSearch", "tagsChange", "selectedFieldIdsChange", "metaChanged", "schemaStatusChange"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }, { kind: "component", type: PraxisTableToolbar, selector: "praxis-table-toolbar", inputs: ["config", "backgroundColor", "placement", "showMain", "showActionsGroup", "showEndActions", "showMobileActions", "showReset", "dslContext", "dslFunctionRegistry"], outputs: ["toolbarAction", "reset"] }, { kind: "component", type: EmptyStateCardComponent, selector: "praxis-empty-state-card", inputs: ["icon", "title", "description", "primaryAction", "secondaryActions", "inline", "tone"] }, { kind: "component", type: TableRatingCellComponent, selector: "praxis-table-rating", inputs: ["itemsCount", "value", "size", "ratingColor", "outlineColor", "ariaLabel"] }], deferBlockDependencies: [() => [import('@praxisui/ai').then(m => m.PraxisAiAssistantComponent)], () => [import('@praxisui/ai').then(m => m.PraxisAiAssistantComponent)], () => [import('@praxisui/ai').then(m => m.PraxisAiAssistantComponent)], () => [import('@praxisui/ai').then(m => m.PraxisAiAssistantComponent)]] });
40934
41414
  }
40935
41415
  i0.ɵɵngDeclareClassMetadataAsync({ minVersion: "18.0.0", version: "20.3.17", ngImport: i0, type: PraxisTable, resolveDeferredDeps: () => [import('@praxisui/ai').then(m => m.PraxisAiAssistantComponent)], resolveMetadata: PraxisAiAssistantComponent => ({ decorators: [{
40936
41416
  type: Component,
@@ -40955,13 +41435,13 @@ i0.ɵɵngDeclareClassMetadataAsync({ minVersion: "18.0.0", version: "20.3.17", n
40955
41435
  PraxisIconDirective,
40956
41436
  PraxisTableToolbar,
40957
41437
  EmptyStateCardComponent,
40958
- MaterialRatingComponent,
41438
+ TableRatingCellComponent,
40959
41439
  ], providers: [
40960
41440
  GenericCrudService,
40961
41441
  TableDefaultsProvider,
40962
41442
  FilterConfigService,
40963
41443
  DataFormattingService
40964
- ], template: "@if (shouldShowEmptyState()) {\n <praxis-empty-state-card\n icon=\"link\"\n [title]=\"'Conecte a tabela \u00E0 fonte de dados'\"\n [description]=\"'Informe a rota do recurso da API para carregar colunas e dados automaticamente.'\"\n [primaryAction]=\"{ label: 'Conectar \u00E0 fonte de dados', icon: 'bolt', action: openQuickConnect.bind(this) }\"\n ></praxis-empty-state-card>\n}\n\n<!-- Error State with Quick Connect CTA -->\n@if (isRemoteMode() && (schemaError || dataError)) {\n<div class=\"ptable-error\" role=\"alert\" aria-live=\"assertive\">\n <mat-icon color=\"warn\" aria-hidden=\"true\">error</mat-icon>\n <div class=\"ptable-error__content\">\n <div class=\"ptable-error__title\">Erro</div>\n <div>{{ errorMessage || 'Ocorreu um erro ao carregar a tabela.' }}</div>\n </div>\n <button mat-flat-button color=\"primary\" (click)=\"openQuickConnect()\">\n <mat-icon>bolt</mat-icon>\n Conectar a recurso\n </button>\n @if (!schemaError) { <button mat-stroked-button (click)=\"retryData()\">Tentar novamente</button> }\n @if (schemaError) { <button mat-stroked-button (click)=\"reloadSchema()\">Recarregar colunas</button> }\n </div>\n}\n\n<!-- Inline banner for schema change (only in edit mode) -->\n@if (shouldShowOutdatedInline()) {\n<div class=\"ptable-info-banner\" role=\"status\" aria-live=\"polite\">\n <div class=\"text\">O schema do servidor mudou. Reconciliar agora?</div>\n <div class=\"actions\">\n <button mat-stroked-button color=\"primary\" (click)=\"onReconcileRequested()\">\n <mat-icon>sync</mat-icon>\n Reconciliar\n </button>\n <button mat-button (click)=\"onSnoozeOutdated()\">Lembrar depois</button>\n <button mat-button (click)=\"onIgnoreOutdated()\">Ignorar</button>\n </div>\n </div>\n}\n\n@if (shouldRenderDataSurface() && !schemaError && !dataError && toolbarV2) {\n <div class=\"praxis-table-header\" [class.edit-mode]=\"editModeEnabled\" [class.stacked]=\"showToolbar\">\n @if (showToolbar && shouldShowToolbarTopPlacement()) {\n <praxis-table-toolbar\n [config]=\"config\"\n [backgroundColor]=\"getToolbarActionsBackgroundColor()\"\n [style.--pfx-filter-h]=\"getToolbarLayoutHeightHostStyle()\"\n [dslContext]=\"getToolbarDslContext()\"\n [dslFunctionRegistry]=\"dslFunctionRegistry\"\n [showActionsGroup]=\"shouldShowToolbarActionsTop()\"\n [showMobileActions]=\"shouldShowToolbarActionsTop()\"\n (toolbarAction)=\"onToolbarAction($event)\"\n (reset)=\"onResetPreferences()\"\n >\n @if (shouldRenderAdvancedFilter()) {\n <praxis-filter\n advancedFilter\n [resourcePath]=\"getAdvancedFilterResourcePath()\"\n [filterId]=\"tableId\"\n [formId]=\"tableId\"\n [persistenceKey]=\"getAdvancedFilterPersistenceKey()\"\n [fieldMetadata]=\"getAdvancedFilterFieldMetadata()\"\n [editModeEnabled]=\"editModeEnabled\"\n \n [alwaysVisibleFields]=\"config.behavior?.filtering?.advancedFilters?.settings?.alwaysVisibleFields\"\n [alwaysVisibleFieldMetadataOverrides]=\"config.behavior?.filtering?.advancedFilters?.settings?.alwaysVisibleFieldMetadataOverrides ?? {}\"\n [selectedFieldIds]=\"config.behavior?.filtering?.advancedFilters?.settings?.selectedFieldIds ?? []\"\n [allowSaveTags]=\"config.behavior?.filtering?.advancedFilters?.settings?.allowSaveTags\"\n [changeDebounceMs]=\"config.behavior?.filtering?.advancedFilters?.settings?.changeDebounceMs ?? 300\"\n [i18n]=\"getFilterI18n()\"\n [mode]=\"'filter'\"\n [showFilterSettings]=\"editModeEnabled\"\n (submit)=\"onAdvancedFilterSubmit($event)\"\n (clear)=\"onAdvancedFilterClear()\"\n ></praxis-filter>\n }\n <ng-content select=\"[advancedFilter]\" />\n <ng-content select=\"[toolbar]\" />\n \n <!-- AI Assistant in Toolbar -->\n @defer (on idle) {\n @if (aiAdapter) {\n <praxis-ai-assistant [adapter]=\"aiAdapter\" end-actions></praxis-ai-assistant>\n }\n }\n\n @if (editModeEnabled) {\n <button end-actions mat-icon-button color=\"primary\" data-role=\"table-settings\" data-testid=\"table-settings-trigger\"\n (click)=\"openTableSettings()\" aria-label=\"Configura\u00E7\u00F5es\"\n [matBadge]=\"schemaOutdated ? '!' : ''\"\n [matBadgeHidden]=\"!schemaOutdated\"\n matBadgeColor=\"warn\" matBadgeSize=\"small\" matBadgePosition=\"above after\"\n [matTooltip]=\"schemaOutdated ? 'Schema do servidor mudou \u2014 Reconciliar' : 'Configura\u00E7\u00F5es'\"\n matTooltipPosition=\"below\">\n <mat-icon>settings</mat-icon>\n </button>\n }\n </praxis-table-toolbar>\n }\n @if (!showToolbar && editModeEnabled) {\n <div class=\"ptable-header-actions\">\n @defer (on idle) {\n @if (aiAdapter) {\n <praxis-ai-assistant [adapter]=\"aiAdapter\"></praxis-ai-assistant>\n }\n }\n <button mat-icon-button color=\"primary\" data-role=\"table-settings\" data-testid=\"table-settings-trigger\" (click)=\"openTableSettings()\" aria-label=\"Configura\u00E7\u00F5es\"\n [matBadge]=\"schemaOutdated ? '!' : ''\"\n [matBadgeHidden]=\"!schemaOutdated\"\n matBadgeColor=\"warn\" matBadgeSize=\"small\" matBadgePosition=\"above after\"\n [matTooltip]=\"schemaOutdated ? 'Schema do servidor mudou \u2014 Reconciliar' : 'Configura\u00E7\u00F5es'\"\n matTooltipPosition=\"below\">\n <mat-icon>settings</mat-icon>\n </button>\n @if (isRemoteMode()) {\n <button mat-icon-button (click)=\"disconnect()\" aria-label=\"Desconectar\" matTooltip=\"Desconectar da fonte de dados\">\n <mat-icon>link_off</mat-icon>\n </button>\n }\n </div>\n }\n </div>\n} @else {\n @if (shouldRenderDataSurface() && !schemaError && !dataError) {\n @if (showToolbar && shouldShowToolbarTopPlacement()) {\n <praxis-table-toolbar\n [config]=\"config\"\n [backgroundColor]=\"getToolbarActionsBackgroundColor()\"\n [style.--pfx-filter-h]=\"getToolbarLayoutHeightHostStyle()\"\n [dslContext]=\"getToolbarDslContext()\"\n [dslFunctionRegistry]=\"dslFunctionRegistry\"\n [showActionsGroup]=\"shouldShowToolbarActionsTop()\"\n [showMobileActions]=\"shouldShowToolbarActionsTop()\"\n (toolbarAction)=\"onToolbarAction($event)\"\n (reset)=\"onResetPreferences()\"\n >\n @if (shouldRenderAdvancedFilter()) {\n <praxis-filter\n advancedFilter\n [resourcePath]=\"getAdvancedFilterResourcePath()\"\n [filterId]=\"tableId\"\n [formId]=\"tableId\"\n [persistenceKey]=\"getAdvancedFilterPersistenceKey()\"\n [fieldMetadata]=\"getAdvancedFilterFieldMetadata()\"\n [editModeEnabled]=\"editModeEnabled\"\n \n [alwaysVisibleFields]=\"config.behavior?.filtering?.advancedFilters?.settings?.alwaysVisibleFields\"\n [alwaysVisibleFieldMetadataOverrides]=\"config.behavior?.filtering?.advancedFilters?.settings?.alwaysVisibleFieldMetadataOverrides ?? {}\"\n [selectedFieldIds]=\"config.behavior?.filtering?.advancedFilters?.settings?.selectedFieldIds ?? []\"\n [allowSaveTags]=\"config.behavior?.filtering?.advancedFilters?.settings?.allowSaveTags\"\n [changeDebounceMs]=\"config.behavior?.filtering?.advancedFilters?.settings?.changeDebounceMs ?? 300\"\n [i18n]=\"getFilterI18n()\"\n [mode]=\"'filter'\"\n [showFilterSettings]=\"editModeEnabled\"\n (submit)=\"onAdvancedFilterSubmit($event)\"\n (clear)=\"onAdvancedFilterClear()\"\n ></praxis-filter>\n }\n <ng-content select=\"[advancedFilter]\" />\n <ng-content select=\"[toolbar]\" />\n @defer (on idle) {\n @if (aiAdapter) {\n <praxis-ai-assistant [adapter]=\"aiAdapter\" end-actions></praxis-ai-assistant>\n }\n }\n @if (editModeEnabled) {\n <button end-actions mat-icon-button color=\"primary\" data-role=\"table-settings\" data-testid=\"table-settings-trigger\"\n (click)=\"openTableSettings()\" aria-label=\"Configura\u00E7\u00F5es\"\n [matBadge]=\"schemaOutdated ? '!' : ''\"\n [matBadgeHidden]=\"!schemaOutdated\"\n matBadgeColor=\"warn\" matBadgeSize=\"small\" matBadgePosition=\"above after\"\n [matTooltip]=\"schemaOutdated ? 'Schema do servidor mudou \u2014 Reconciliar' : 'Configura\u00E7\u00F5es'\"\n matTooltipPosition=\"below\">\n <mat-icon>settings</mat-icon>\n </button>\n }\n </praxis-table-toolbar>\n }\n @if (!showToolbar && editModeEnabled) {\n <div class=\"ptable-header-actions\">\n <button mat-icon-button color=\"primary\" data-role=\"table-settings\" data-testid=\"table-settings-trigger\" (click)=\"openTableSettings()\" aria-label=\"Configura\u00E7\u00F5es\"\n [matBadge]=\"schemaOutdated ? '!' : ''\"\n [matBadgeHidden]=\"!schemaOutdated\"\n matBadgeColor=\"warn\" matBadgeSize=\"small\" matBadgePosition=\"above after\"\n [matTooltip]=\"schemaOutdated ? 'Schema do servidor mudou \u2014 Reconciliar' : 'Configura\u00E7\u00F5es'\"\n matTooltipPosition=\"below\">\n <mat-icon>settings</mat-icon>\n </button>\n </div>\n }\n }\n}\n<div class=\"px-scroll-viewport\"\n cdkScrollable\n [class.scroll-auto]=\"horizontalScroll === 'auto'\"\n [class.scroll-wrap]=\"horizontalScroll === 'wrap'\"\n [class.scroll-none]=\"horizontalScroll === 'none'\">\n\n@if (shouldRenderDataSurface() && !schemaError && !dataError) {\n<div class=\"praxis-visually-hidden-status\" role=\"status\" aria-live=\"polite\" aria-atomic=\"true\">\n {{ columnReorderStatusMessage }}\n</div>\n@if (columnReorderVisualStatusMessage) {\n <div class=\"praxis-column-reorder-status\" role=\"note\">\n {{ columnReorderVisualStatusMessage }}\n </div>\n}\n<table\n mat-table\n data-testid=\"table-column-drag-drop-list\"\n [dataSource]=\"dataSource\"\n [multiTemplateDataRows]=\"isRowExpansionRuntimeEnabled()\"\n cdkDropList\n [cdkDropListDisabled]=\"!isColumnDraggingEnabled()\"\n [cdkDropListData]=\"visibleDataColumnsForDrag\"\n cdkDropListOrientation=\"horizontal\"\n (cdkDropListDropped)=\"onColumnDrop($event)\"\n matSort\n (matSortChange)=\"onSortChange($event)\"\n [matSortDisabled]=\"!getSortingEnabled()\"\n [ngClass]=\"getTableElevationClassName()\"\n [class.table-stack-top]=\"showToolbar\"\n [class.pfx-column-drag-enabled]=\"isColumnDraggingEnabled()\"\n [class.pfx-column-drag-indicator]=\"isColumnDragIndicatorEnabled()\"\n>\n @if (config.behavior?.selection?.enabled) {\n <ng-container\n matColumnDef=\"_select\"\n >\n <th mat-header-cell *matHeaderCellDef>\n @if (canSelectAll()) {\n <mat-checkbox\n (change)=\"masterToggle()\"\n [checked]=\"isAllSelected()\"\n [indeterminate]=\"selection.hasValue() && !isAllSelected()\"\n ></mat-checkbox>\n }\n </th>\n <td mat-cell *matCellDef=\"let row\">\n <mat-checkbox\n (click)=\"$event.stopPropagation()\"\n (change)=\"toggleRow(row)\"\n [checked]=\"selection.isSelected(row)\"\n ></mat-checkbox>\n </td>\n </ng-container>\n }\n @if (isRowExpansionRuntimeEnabled()) {\n <ng-container matColumnDef=\"_expander\">\n <th mat-header-cell *matHeaderCellDef class=\"pfx-expansion-col-header\">\n <span class=\"praxis-visually-hidden-status\">Expandir detalhes da linha</span>\n </th>\n <td mat-cell *matCellDef=\"let row; let i = index\" class=\"pfx-expansion-col-cell\">\n <button\n mat-icon-button\n class=\"pfx-expansion-toggle\"\n [disabled]=\"!isRowExpandable(row, i) || !isExpansionIconTriggerEnabled()\"\n [attr.aria-expanded]=\"isRowExpanded(row, i) ? 'true' : 'false'\"\n [attr.aria-controls]=\"getRowExpansionDetailId(row, i)\"\n [attr.aria-label]=\"getRowExpansionToggleAriaLabel(row, i)\"\n (click)=\"onExpansionToggleFromIcon(row, i, $event)\"\n (keydown)=\"onExpansionToggleKeydown($event, row, i)\"\n >\n <mat-icon>{{ isRowExpanded(row, i) ? 'expand_less' : 'expand_more' }}</mat-icon>\n </button>\n </td>\n </ng-container>\n }\n @for (column of visibleColumns; track column.field) {\n <ng-container\n [matColumnDef]=\"column.field\"\n [sticky]=\"column.sticky === true || column.sticky === 'start'\"\n [stickyEnd]=\"column.sticky === 'end'\"\n >\n <th\n mat-header-cell\n *matHeaderCellDef\n mat-sort-header\n cdkDrag\n [cdkDragData]=\"column\"\n cdkDragLockAxis=\"x\"\n cdkDragPreviewClass=\"pfx-column-drag-preview\"\n (cdkDragStarted)=\"onColumnDragStarted(column)\"\n (cdkDragEnded)=\"onColumnDragEnded($event, column)\"\n (keydown)=\"onColumnDragHandleKeydown($event, column)\"\n [cdkDragDisabled]=\"!isColumnDraggingEnabled() || !isColumnDraggable(column)\"\n [class.praxis-header-draggable]=\"isColumnDraggingEnabled() && isColumnDraggable(column)\"\n [disabled]=\"!getSortingEnabled() || column.sortable === false\"\n [style.text-align]=\"getColumnTextAlignStyle(column)\"\n [style.width]=\"getColumnWidthStyle(column)\"\n [attr.style]=\"getColumnHeaderAttrStyle(column)\"\n [attr.aria-label]=\"isColumnDraggingEnabled() && isColumnDraggable(column) ? getColumnDragHandleAriaLabel(column) : null\"\n [matTooltip]=\"isColumnDraggingEnabled() && isColumnDraggable(column) ? getColumnDragHandleTooltip(column) : null\"\n matTooltipPosition=\"above\"\n matTooltipClass=\"praxis-tooltip\"\n >\n <span class=\"praxis-header-label\" data-testid=\"column-header-label\">{{ column.header }}</span>\n @if (isColumnDraggingEnabled() && isColumnDraggable(column)) {\n <span\n class=\"praxis-column-drag-handle\"\n data-testid=\"column-drag-handle\"\n [attr.data-column-field]=\"column.field\"\n aria-hidden=\"true\"\n >\n <mat-icon [praxisIcon]=\"'drag_indicator'\"></mat-icon>\n </span>\n }\n </th>\n <td\n mat-cell\n *matCellDef=\"let element\"\n [style.text-align]=\"getColumnTextAlignStyle(column)\"\n [style.width]=\"getColumnWidthStyle(column)\"\n [attr.style]=\"getColumnCellAttrStyle(column)\"\n [ngClass]=\"getCellClasses(element, column)\"\n [ngStyle]=\"getCellNgStyle(element, column)\"\n >\n <div\n class=\"pfx-cell-content\"\n [ngClass]=\"getCellContentClasses(element, column)\"\n [ngStyle]=\"getCellContentNgStyle(element, column)\"\n >\n <ng-container [ngSwitch]=\"getEffectiveRendererType(element, column)\">\n <!-- Icon renderer -->\n <ng-container *ngSwitchCase=\"'icon'\">\n <mat-icon\n [color]=\"getIconColor(element, column) || null\"\n [ngStyle]=\"getIconStyle(element, column)\"\n [attr.aria-label]=\"getIconAriaLabel(element, column) || null\"\n >{{ getIconName(element, column) }}</mat-icon\n >\n </ng-container>\n\n <!-- Image renderer -->\n <ng-container *ngSwitchCase=\"'image'\">\n <img\n class=\"pfx-cell-image\"\n [src]=\"getImageSrc(element, column)\"\n [attr.alt]=\"getImageAlt(element, column) || ''\"\n [attr.loading]=\"getImageLazy(element, column) ? 'lazy' : null\"\n [style.width.px]=\"getImageWidth(element, column)\"\n [style.height.px]=\"getImageHeight(element, column)\"\n [class.shape-rounded]=\"getImageShape(element, column) === 'rounded'\"\n [class.shape-circle]=\"getImageShape(element, column) === 'circle'\"\n [style.object-fit]=\"getImageFit(element, column)\"\n />\n </ng-container>\n\n <!-- Badge renderer -->\n <ng-container *ngSwitchCase=\"'badge'\">\n <span class=\"pfx-badge\" [ngClass]=\"getBadgeClasses(element, column)\">\n @if (getBadgeIcon(element, column); as bi) { <mat-icon class=\"pfx-badge-icon\">{{ bi }}</mat-icon> }\n <span class=\"pfx-badge-text\">{{ getBadgeText(element, column) }}</span>\n </span>\n </ng-container>\n\n <!-- Link renderer -->\n <ng-container *ngSwitchCase=\"'link'\">\n <a\n class=\"pfx-link\"\n [attr.href]=\"getLinkHref(element, column) || null\"\n [attr.target]=\"getLinkTarget(element, column) || null\"\n [attr.rel]=\"getLinkRel(element, column) || null\"\n (click)=\"$event.stopPropagation()\"\n >{{ getLinkText(element, column) }}</a\n >\n </ng-container>\n\n <!-- Button renderer -->\n <ng-container *ngSwitchCase=\"'button'\">\n <ng-container [ngSwitch]=\"getButtonVariant(element, column)\">\n <button\n *ngSwitchCase=\"'outlined'\"\n mat-stroked-button\n [color]=\"getButtonColor(element, column) || null\"\n [disabled]=\"isButtonDisabled(element, column)\"\n [attr.aria-label]=\"getButtonAriaLabel(element, column) || getButtonLabel(element, column)\"\n (click)=\"onButtonClick(element, column, $event)\"\n >\n @if (getButtonIcon(element, column); as bi) { <mat-icon>{{ bi }}</mat-icon> }\n {{ getButtonLabel(element, column) }}\n </button>\n <button\n *ngSwitchCase=\"'text'\"\n mat-button\n [color]=\"getButtonColor(element, column) || null\"\n [disabled]=\"isButtonDisabled(element, column)\"\n [attr.aria-label]=\"getButtonAriaLabel(element, column) || getButtonLabel(element, column)\"\n (click)=\"onButtonClick(element, column, $event)\"\n >\n @if (getButtonIcon(element, column); as bi) { <mat-icon>{{ bi }}</mat-icon> }\n {{ getButtonLabel(element, column) }}\n </button>\n <button\n *ngSwitchDefault\n mat-flat-button\n [color]=\"getButtonColor(element, column) || null\"\n [disabled]=\"isButtonDisabled(element, column)\"\n [attr.aria-label]=\"getButtonAriaLabel(element, column) || getButtonLabel(element, column)\"\n (click)=\"onButtonClick(element, column, $event)\"\n >\n @if (getButtonIcon(element, column); as bi) { <mat-icon>{{ bi }}</mat-icon> }\n {{ getButtonLabel(element, column) }}\n </button>\n </ng-container>\n </ng-container>\n\n <!-- Chip renderer -->\n <ng-container *ngSwitchCase=\"'chip'\">\n <span class=\"pfx-chip\" [ngClass]=\"getChipClasses(element, column)\">\n @if (getChipIcon(element, column); as ci) { <mat-icon class=\"pfx-chip-icon\">{{ ci }}</mat-icon> }\n <span class=\"pfx-chip-text\">{{ getChipText(element, column) }}</span>\n </span>\n </ng-container>\n\n <!-- Progress renderer -->\n <ng-container *ngSwitchCase=\"'progress'\">\n <div class=\"pfx-progress\">\n <div class=\"pfx-progress-bar\" [style.width.%]=\"getProgressWidthPercentStyle(element, column)\" [style.background]=\"getProgressBackgroundStyle(element, column)\"></div>\n @if (getProgressShowLabel(element, column)) { <div class=\"pfx-progress-label\">{{ getProgressValue(element, column) }}%</div> }\n </div>\n </ng-container>\n\n <!-- Avatar renderer -->\n <ng-container *ngSwitchCase=\"'avatar'\">\n @if (getAvatarSrc(element, column); as asrc) {\n <img class=\"pfx-avatar\" [src]=\"asrc\" [attr.alt]=\"getAvatarAlt(element, column) || ''\" [ngStyle]=\"getAvatarStyle(element, column)\" [class.shape-rounded]=\"getAvatarShape(element, column) === 'rounded'\" [class.shape-circle]=\"getAvatarShape(element, column) === 'circle'\" loading=\"lazy\" />\n } @else {\n <span class=\"pfx-avatar pfx-avatar--initials\" [ngStyle]=\"getAvatarStyle(element, column)\" [class.shape-rounded]=\"getAvatarShape(element, column) === 'rounded'\" [class.shape-circle]=\"getAvatarShape(element, column) === 'circle'\">{{ getAvatarInitials(element, column) }}</span>\n }\n </ng-container>\n\n <!-- Toggle renderer -->\n <ng-container *ngSwitchCase=\"'toggle'\">\n <mat-slide-toggle\n [checked]=\"getToggleState(element, column)\"\n [disabled]=\"isToggleDisabled(element, column)\"\n [attr.aria-label]=\"getToggleAriaLabel(element, column) || 'Alternar'\"\n (change)=\"onToggleChange(element, column, $event)\"\n (click)=\"$event.stopPropagation()\"\n ></mat-slide-toggle>\n </ng-container>\n\n <!-- Menu renderer -->\n <ng-container *ngSwitchCase=\"'menu'\">\n <button mat-icon-button [matMenuTriggerFor]=\"menuRef\" (click)=\"$event.stopPropagation()\" [attr.aria-label]=\"getMenuAriaLabel(element, column) || 'Menu'\">\n <mat-icon>more_vert</mat-icon>\n </button>\n <mat-menu #menuRef=\"matMenu\">\n <button mat-menu-item *ngFor=\"let it of getMenuItems(element, column)\" (click)=\"onMenuItemClick(it, element, $event)\" [disabled]=\"!it.__visible\" >\n @if (it.icon) { <mat-icon>{{ it.icon }}</mat-icon> }\n <span>{{ it.label }}</span>\n </button>\n </mat-menu>\n </ng-container>\n\n <!-- Rating renderer -->\n <ng-container *ngSwitchCase=\"'rating'\">\n <pdx-material-rating\n class=\"pfx-rating-cell\"\n [itemsCount]=\"getRatingMax(element, column)\"\n [ngModel]=\"getRatingValue(element, column)\"\n [readonlyMode]=\"getRatingReadonly(element, column)\"\n [presentationMode]=\"true\"\n [size]=\"getRatingSize(element, column)\"\n [ratingColor]=\"getRatingColor(element, column)\"\n [outlineColor]=\"getRatingOutlineColor(element, column)\"\n [ariaLabel]=\"getRatingAriaLabel(element, column) || column.header\"\n [tabIndex]=\"-1\">\n </pdx-material-rating>\n </ng-container>\n\n <!-- HTML renderer (sanitizado) -->\n <ng-container *ngSwitchCase=\"'html'\">\n <span [innerHTML]=\"getSafeHtml(element, column)\"></span>\n </ng-container>\n\n <!-- Compose renderer -->\n <ng-container *ngSwitchCase=\"'compose'\">\n <span class=\"pfx-cell-compose\" [ngClass]=\"getComposeClasses(element, column)\" [ngStyle]=\"getComposeGapStyle(element, column)\">\n <ng-container *ngFor=\"let it of getComposeItems(element, column)\">\n <ng-container [ngSwitch]=\"getItemEffectiveType(element, column, it)\">\n <!-- Reuse helpers by projecting item as faux column -->\n <ng-container *ngSwitchCase=\"'icon'\">\n <mat-icon [color]=\"getIconColor(element, asItemColumn(column, it)) || null\" [ngStyle]=\"getIconStyle(element, asItemColumn(column, it))\" [attr.aria-label]=\"getIconAriaLabel(element, asItemColumn(column, it)) || null\">{{ getIconName(element, asItemColumn(column, it)) }}</mat-icon>\n </ng-container>\n <ng-container *ngSwitchCase=\"'image'\">\n <img class=\"pfx-cell-image\" [src]=\"getImageSrc(element, asItemColumn(column, it))\" [attr.alt]=\"getImageAlt(element, asItemColumn(column, it)) || ''\" [attr.loading]=\"getImageLazy(element, asItemColumn(column, it)) ? 'lazy' : null\" [style.width.px]=\"getImageWidth(element, asItemColumn(column, it))\" [style.height.px]=\"getImageHeight(element, asItemColumn(column, it))\" [class.shape-rounded]=\"getImageShape(element, asItemColumn(column, it)) === 'rounded'\" [class.shape-circle]=\"getImageShape(element, asItemColumn(column, it)) === 'circle'\" [style.object-fit]=\"getImageFit(element, asItemColumn(column, it))\" />\n </ng-container>\n <ng-container *ngSwitchCase=\"'badge'\">\n <span class=\"pfx-badge\" [ngClass]=\"getBadgeClasses(element, asItemColumn(column, it))\">@if (getBadgeIcon(element, asItemColumn(column, it)); as bi) { <mat-icon class=\"pfx-badge-icon\">{{ bi }}</mat-icon> }<span class=\"pfx-badge-text\">{{ getBadgeText(element, asItemColumn(column, it)) }}</span></span>\n </ng-container>\n <ng-container *ngSwitchCase=\"'link'\">\n <a class=\"pfx-link\" [attr.href]=\"getLinkHref(element, asItemColumn(column, it)) || null\" [attr.target]=\"getLinkTarget(element, asItemColumn(column, it)) || null\" [attr.rel]=\"getLinkRel(element, asItemColumn(column, it)) || null\" (click)=\"$event.stopPropagation()\">{{ getLinkText(element, asItemColumn(column, it)) }}</a>\n </ng-container>\n <ng-container *ngSwitchCase=\"'button'\">\n <ng-container [ngSwitch]=\"getButtonVariant(element, asItemColumn(column, it))\">\n <button *ngSwitchCase=\"'outlined'\" mat-stroked-button [color]=\"getButtonColor(element, asItemColumn(column, it)) || null\" [disabled]=\"isButtonDisabled(element, asItemColumn(column, it))\" [attr.aria-label]=\"getButtonAriaLabel(element, asItemColumn(column, it)) || getButtonLabel(element, asItemColumn(column, it))\" (click)=\"onButtonClick(element, asItemColumn(column, it), $event)\">@if (getButtonIcon(element, asItemColumn(column, it)); as bi) { <mat-icon>{{ bi }}</mat-icon> }{{ getButtonLabel(element, asItemColumn(column, it)) }}</button>\n <button *ngSwitchCase=\"'text'\" mat-button [color]=\"getButtonColor(element, asItemColumn(column, it)) || null\" [disabled]=\"isButtonDisabled(element, asItemColumn(column, it))\" [attr.aria-label]=\"getButtonAriaLabel(element, asItemColumn(column, it)) || getButtonLabel(element, asItemColumn(column, it))\" (click)=\"onButtonClick(element, asItemColumn(column, it), $event)\">@if (getButtonIcon(element, asItemColumn(column, it)); as bi) { <mat-icon>{{ bi }}</mat-icon> }{{ getButtonLabel(element, asItemColumn(column, it)) }}</button>\n <button *ngSwitchDefault mat-flat-button [color]=\"getButtonColor(element, asItemColumn(column, it)) || null\" [disabled]=\"isButtonDisabled(element, asItemColumn(column, it))\" [attr.aria-label]=\"getButtonAriaLabel(element, asItemColumn(column, it)) || getButtonLabel(element, asItemColumn(column, it))\" (click)=\"onButtonClick(element, asItemColumn(column, it), $event)\">@if (getButtonIcon(element, asItemColumn(column, it)); as bi) { <mat-icon>{{ bi }}</mat-icon> }{{ getButtonLabel(element, asItemColumn(column, it)) }}</button>\n </ng-container>\n </ng-container>\n <ng-container *ngSwitchCase=\"'chip'\">\n <span class=\"pfx-chip\" [ngClass]=\"getChipClasses(element, asItemColumn(column, it))\">@if (getChipIcon(element, asItemColumn(column, it)); as ci) { <mat-icon class=\"pfx-chip-icon\">{{ ci }}</mat-icon> }<span class=\"pfx-chip-text\">{{ getChipText(element, asItemColumn(column, it)) }}</span></span>\n </ng-container>\n <ng-container *ngSwitchCase=\"'progress'\">\n <div class=\"pfx-progress\"><div class=\"pfx-progress-bar\" [style.width.%]=\"getProgressWidthPercentStyle(element, asItemColumn(column, it))\" [style.background]=\"getProgressBackgroundStyle(element, asItemColumn(column, it))\"></div>@if (getProgressShowLabel(element, asItemColumn(column, it))) { <div class=\"pfx-progress-label\">{{ getProgressValue(element, asItemColumn(column, it)) }}%</div> }</div>\n </ng-container>\n <ng-container *ngSwitchCase=\"'avatar'\">\n @if (getAvatarSrc(element, asItemColumn(column, it)); as asrc) {\n <img class=\"pfx-avatar\" [src]=\"asrc\" [attr.alt]=\"getAvatarAlt(element, asItemColumn(column, it)) || ''\" [ngStyle]=\"getAvatarStyle(element, asItemColumn(column, it))\" [class.shape-rounded]=\"getAvatarShape(element, asItemColumn(column, it)) === 'rounded'\" [class.shape-circle]=\"getAvatarShape(element, asItemColumn(column, it)) === 'circle'\" loading=\"lazy\" />\n } @else {\n <span class=\"pfx-avatar pfx-avatar--initials\" [ngStyle]=\"getAvatarStyle(element, asItemColumn(column, it))\" [class.shape-rounded]=\"getAvatarShape(element, asItemColumn(column, it)) === 'rounded'\" [class.shape-circle]=\"getAvatarShape(element, asItemColumn(column, it)) === 'circle'\">{{ getAvatarInitials(element, asItemColumn(column, it)) }}</span>\n }\n </ng-container>\n <ng-container *ngSwitchCase=\"'toggle'\">\n <mat-slide-toggle [checked]=\"getToggleState(element, asItemColumn(column, it))\" [disabled]=\"isToggleDisabled(element, asItemColumn(column, it))\" [attr.aria-label]=\"getToggleAriaLabel(element, asItemColumn(column, it)) || 'Alternar'\" (change)=\"onToggleChange(element, asItemColumn(column, it), $event)\" (click)=\"$event.stopPropagation()\"></mat-slide-toggle>\n </ng-container>\n <ng-container *ngSwitchCase=\"'menu'\">\n <button mat-icon-button [matMenuTriggerFor]=\"menuRef\" (click)=\"$event.stopPropagation()\" [attr.aria-label]=\"getMenuAriaLabel(element, asItemColumn(column, it)) || 'Menu'\"><mat-icon>more_vert</mat-icon></button>\n <mat-menu #menuRef=\"matMenu\">\n <button mat-menu-item *ngFor=\"let mi of getMenuItems(element, asItemColumn(column, it))\" (click)=\"onMenuItemClick(mi, element, $event)\" [disabled]=\"!mi.__visible\">\n @if (mi.icon) { <mat-icon>{{ mi.icon }}</mat-icon> }\n <span>{{ mi.label }}</span>\n </button>\n </mat-menu>\n </ng-container>\n <ng-container *ngSwitchCase=\"'rating'\">\n <pdx-material-rating\n class=\"pfx-rating-cell\"\n [itemsCount]=\"getRatingMax(element, asItemColumn(column, it))\"\n [ngModel]=\"getRatingValue(element, asItemColumn(column, it))\"\n [readonlyMode]=\"getRatingReadonly(element, asItemColumn(column, it))\"\n [presentationMode]=\"true\"\n [size]=\"getRatingSize(element, asItemColumn(column, it))\"\n [ratingColor]=\"getRatingColor(element, asItemColumn(column, it))\"\n [outlineColor]=\"getRatingOutlineColor(element, asItemColumn(column, it))\"\n [ariaLabel]=\"getRatingAriaLabel(element, asItemColumn(column, it)) || column.header\"\n [tabIndex]=\"-1\">\n </pdx-material-rating>\n </ng-container>\n <ng-container *ngSwitchCase=\"'html'\">\n <span [innerHTML]=\"getSafeHtml(element, asItemColumn(column, it))\"></span>\n </ng-container>\n <!-- Value item: render base cell text alongside visuals -->\n <ng-container *ngSwitchCase=\"'value'\">\n <span class=\"pfx-cell-value\">{{ getComposeItemValue(element, column, it) }}</span>\n </ng-container>\n </ng-container>\n </ng-container>\n </span>\n </ng-container>\n\n <!-- Default text rendering -->\n <ng-container *ngSwitchDefault>\n {{ getCellValue(element, column) }}\n </ng-container>\n </ng-container>\n </div>\n </td>\n </ng-container>\n }\n @if (config.actions?.row?.enabled) {\n <ng-container matColumnDef=\"_actions\" [sticky]=\"config.actions?.row?.sticky === true || config.actions?.row?.sticky === 'start'\" [stickyEnd]=\"config.actions?.row?.sticky === 'end'\">\n <th mat-header-cell *matHeaderCellDef #actionsHeaderCell [style.width]=\"getRowActionsWidthStyle()\" class=\"praxis-actions-header\" [class.align-start]=\"getActionsHeaderAlign() === 'start'\" [class.align-center]=\"getActionsHeaderAlign() === 'center'\" [class.align-end]=\"getActionsHeaderAlign() === 'end'\">\n <div class=\"praxis-actions-header__content\" [matTooltip]=\"getActionsHeaderTooltip() || ''\" [matTooltipDisabled]=\"!getActionsHeaderTooltip()\">\n @if (getActionsHeaderIcon(); as hi) { <mat-icon [praxisIcon]=\"hi\"></mat-icon> }\n @if (getActionsHeaderLabel(); as hl) { <span class=\"label\">{{ hl }}</span> }\n </div>\n </th>\n <td\n mat-cell\n *matCellDef=\"let row\"\n class=\"praxis-actions-cell\"\n [class.dense]=\"dense\"\n [style.width]=\"getRowActionsWidthStyle()\"\n >\n <div class=\"praxis-actions-cell__content\">\n <!-- A\u00E7\u00F5es inline -->\n <!-- Inline actions: icons mode -->\n @if (config.actions?.row?.display === 'icons' || !config.actions?.row?.display) {\n <ng-container *ngFor=\"let a of getInlineRowActions(row); trackBy: trackAction\">\n <button\n mat-icon-button\n class=\"praxis-icon-btn\"\n [disabled]=\"isActionDisabled(a, row)\"\n (click)=\"onRowAction(getActionId(a), row, $event)\"\n [matTooltip]=\"a.label || getActionId(a)\"\n matTooltipPosition=\"above\"\n matTooltipClass=\"praxis-tooltip\"\n [attr.aria-label]=\"a.label || getActionId(a)\"\n [color]=\"a.color || null\"\n >\n <mat-icon [praxisIcon]=\"a.icon\"></mat-icon>\n </button>\n </ng-container>\n }\n\n <!-- Inline actions: buttons mode (show label + icon) -->\n @if (config.actions?.row?.display === 'buttons') {\n <ng-container *ngFor=\"let a of getInlineRowActions(row); trackBy: trackAction\">\n <button\n mat-flat-button\n class=\"praxis-row-btn\"\n [disabled]=\"isActionDisabled(a, row)\"\n (click)=\"onRowAction(getActionId(a), row, $event)\"\n [attr.aria-label]=\"a.label || getActionId(a)\"\n [color]=\"a.color || null\"\n >\n <mat-icon [praxisIcon]=\"a.icon\"></mat-icon>\n <span>{{ a.label || getActionId(a) }}</span>\n </button>\n </ng-container>\n }\n\n <!-- Menu de overflow -->\n @if (hasOverflowRowActions(row)) {\n <button\n mat-icon-button\n class=\"praxis-icon-btn praxis-more-btn\"\n [matMenuTriggerFor]=\"rowMoreMenu\"\n [color]=\"getRowMenuButtonColor() || null\"\n aria-label=\"Mais a\u00E7\u00F5es\"\n >\n <mat-icon [praxisIcon]=\"getRowMenuIcon()\"></mat-icon>\n </button>\n }\n <mat-menu #rowMoreMenu=\"matMenu\" xPosition=\"before\">\n <ng-container\n *ngFor=\"let a of getOverflowRowActions(row); trackBy: trackAction\"\n >\n <button\n mat-menu-item\n (click)=\"onRowAction(getActionId(a), row, $event)\"\n [disabled]=\"isActionDisabled(a, row)\"\n >\n <mat-icon [color]=\"a.color || null\" [praxisIcon]=\"a.icon\"></mat-icon>\n <span>{{ a.label || getActionId(a) }}</span>\n </button>\n </ng-container>\n </mat-menu>\n </div>\n </td>\n </ng-container>\n }\n\n <tr\n mat-header-row\n *matHeaderRowDef=\"displayedColumns\"\n ></tr>\n @if (!isVirtualized()) {\n <tr\n mat-row\n *matRowDef=\"let row; let i = index; columns: displayedColumns\"\n [class.pfx-row-selected]=\"selection.isSelected(row)\"\n [class.pfx-row-expanded]=\"isRowExpansionRuntimeEnabled() && isRowExpanded(row, i)\"\n [attr.aria-selected]=\"config.behavior?.selection?.enabled ? (selection.isSelected(row) ? 'true' : 'false') : null\"\n [attr.aria-expanded]=\"isRowExpansionRuntimeEnabled() ? (isRowExpanded(row, i) ? 'true' : 'false') : null\"\n [ngClass]=\"getRowClasses(row)\"\n [ngStyle]=\"getRowNgStyle(row)\"\n [matTooltip]=\"getRowTooltip(row) || null\"\n [matTooltipDisabled]=\"!getRowTooltip(row)\"\n [matTooltipPosition]=\"getRowTooltipPosition(row)\"\n [matTooltipShowDelay]=\"getRowTooltipShowDelay(row)\"\n (click)=\"onRowClicked(row, i, $event)\"\n (dblclick)=\"onRowDoubleClicked(row, i)\"\n ></tr>\n @if (isRowExpansionRuntimeEnabled()) {\n <ng-container matColumnDef=\"_detail\">\n <td\n mat-cell\n *matCellDef=\"let row; let i = index\"\n class=\"pfx-expansion-detail-cell\"\n [attr.colspan]=\"displayedColumns.length\"\n >\n <section\n class=\"pfx-expansion-detail-panel\"\n [attr.id]=\"getRowExpansionDetailId(row, i)\"\n role=\"region\"\n [attr.aria-label]=\"getRowExpansionRegionAriaLabel(row, i)\"\n [attr.aria-busy]=\"getExpansionDetailViewState(row, i).status === 'loading' ? 'true' : 'false'\"\n >\n @let detailState = getExpansionDetailViewState(row, i);\n @if (detailState.status === 'loading') {\n <div class=\"pfx-expansion-detail-message\" role=\"status\" aria-live=\"polite\">\n Carregando detail schema...\n </div>\n } @else if (detailState.status !== 'ready') {\n <div\n class=\"pfx-expansion-detail-message pfx-expansion-detail-message--error\"\n role=\"alert\"\n aria-live=\"assertive\"\n aria-atomic=\"true\"\n >\n {{ detailState.message || 'Detail indispon\u00EDvel para esta linha.' }}\n </div>\n } @else {\n @if (getExpansionDetailLayout(detailState.schema) === 'tabs') {\n @let detailTabs = getExpansionDetailTabs(detailState.schema);\n @if (detailTabs.length) {\n <div class=\"pfx-expansion-detail-tabs\" role=\"tablist\" aria-label=\"Se\u00E7\u00F5es do detail\">\n @for (tab of detailTabs; track $index; let tabIndex = $index) {\n <button\n type=\"button\"\n class=\"pfx-expansion-detail-tab-btn\"\n role=\"tab\"\n [attr.id]=\"getExpansionDetailTabId(row, i, tab, tabIndex)\"\n [attr.aria-controls]=\"getExpansionDetailPanelId(row, i, tab, tabIndex)\"\n [attr.aria-selected]=\"isExpansionDetailTabActive(row, i, tab, tabIndex, detailTabs) ? 'true' : 'false'\"\n [attr.tabindex]=\"isExpansionDetailTabActive(row, i, tab, tabIndex, detailTabs) ? '0' : '-1'\"\n [class.is-active]=\"isExpansionDetailTabActive(row, i, tab, tabIndex, detailTabs)\"\n (click)=\"onExpansionDetailTabSelect(row, i, tab, tabIndex, $event)\"\n (keydown)=\"onExpansionDetailTabKeydown($event, row, i, tabIndex, detailTabs)\"\n >\n {{ getExpansionDetailNodeTitle(tab, 'Tab') }}\n </button>\n }\n </div>\n @for (tab of detailTabs; track $index; let tabIndex = $index) {\n @if (isExpansionDetailTabActive(row, i, tab, tabIndex, detailTabs)) {\n <div\n class=\"pfx-expansion-detail-tab-panel\"\n role=\"tabpanel\"\n [attr.id]=\"getExpansionDetailPanelId(row, i, tab, tabIndex)\"\n [attr.aria-labelledby]=\"getExpansionDetailTabId(row, i, tab, tabIndex)\"\n >\n @for (childNode of getExpansionDetailNodeChildren(tab); track $index) {\n <ng-container\n *ngTemplateOutlet=\"\n expansionDetailNodeTemplate;\n context: { $implicit: childNode, row: row, index: i }\n \"\n ></ng-container>\n }\n </div>\n }\n }\n } @else {\n <div class=\"pfx-expansion-detail-message\">\n Schema em layout tabs sem abas v\u00E1lidas.\n </div>\n }\n } @else {\n <div class=\"pfx-expansion-detail-stack\">\n @for (node of getExpansionDetailItems(detailState.schema); track $index) {\n <ng-container\n *ngTemplateOutlet=\"\n expansionDetailNodeTemplate;\n context: { $implicit: node, row: row, index: i }\n \"\n ></ng-container>\n }\n </div>\n }\n }\n\n <ng-template #expansionDetailNodeTemplate let-node let-row=\"row\" let-index=\"index\">\n @switch (getExpansionDetailNodeType(node)) {\n @case ('card') {\n <article class=\"pfx-expansion-node pfx-expansion-node-card\">\n <header class=\"pfx-expansion-node-card__header\">\n <h5 class=\"pfx-expansion-node-card__title\">\n {{ getExpansionDetailNodeTitle(node, 'Card') }}\n </h5>\n @if (node?.subtitle) {\n <p class=\"pfx-expansion-node-card__subtitle\">{{ node?.subtitle }}</p>\n }\n </header>\n @for (childNode of getExpansionDetailNodeChildren(node); track $index) {\n <ng-container\n *ngTemplateOutlet=\"\n expansionDetailNodeTemplate;\n context: { $implicit: childNode, row: row, index: index }\n \"\n ></ng-container>\n }\n </article>\n }\n @case ('value') {\n <div class=\"pfx-expansion-node pfx-expansion-node-value\">\n <span class=\"pfx-expansion-node-value__label\">\n {{ getExpansionDetailNodeTitle(node, 'Valor') }}\n </span>\n <strong class=\"pfx-expansion-node-value__content\">\n {{ getExpansionDetailValue(row, node) }}\n </strong>\n </div>\n }\n @case ('list') {\n <section class=\"pfx-expansion-node pfx-expansion-node-list\">\n <h6 class=\"pfx-expansion-node-list__title\">\n {{ getExpansionDetailNodeTitle(node, 'Lista') }}\n </h6>\n @let listItems = getExpansionDetailListItems(row, node);\n @if (listItems.length) {\n <ul>\n @for (entry of listItems; track $index) {\n <li>{{ entry }}</li>\n }\n </ul>\n } @else {\n <p class=\"pfx-expansion-node-placeholder\">Sem itens.</p>\n }\n </section>\n }\n @case ('richText') {\n <div\n class=\"pfx-expansion-node pfx-expansion-node-richtext\"\n [innerHTML]=\"getExpansionDetailRichText(node)\"\n ></div>\n }\n @case ('formRef') {\n <div class=\"pfx-expansion-node pfx-expansion-node-placeholder\">\n Formul\u00E1rio referenciado: <code>{{ node?.schemaId || node?.id || 'sem-id' }}</code>\n </div>\n }\n @case ('tableRef') {\n <div class=\"pfx-expansion-node pfx-expansion-node-placeholder\">\n Tabela referenciada: <code>{{ node?.schemaId || node?.id || 'sem-id' }}</code>\n </div>\n }\n @case ('chartRef') {\n <div class=\"pfx-expansion-node pfx-expansion-node-placeholder\">\n Gr\u00E1fico referenciado: <code>{{ node?.schemaId || node?.id || 'sem-id' }}</code>\n </div>\n }\n @case ('templateRef') {\n <div class=\"pfx-expansion-node pfx-expansion-node-placeholder\">\n Template referenciado: <code>{{ node?.id || node?.templateId || 'sem-id' }}</code>\n </div>\n }\n @case ('action') {\n <div class=\"pfx-expansion-node pfx-expansion-node-placeholder\">\n A\u00E7\u00E3o declarada: <code>{{ node?.id || node?.actionId || 'sem-id' }}</code>\n </div>\n }\n @case ('tab') {\n <div class=\"pfx-expansion-node pfx-expansion-node-placeholder\">\n Node <code>tab</code> fora de contexto de tabs.\n </div>\n }\n @default {\n <div class=\"pfx-expansion-node pfx-expansion-node-placeholder\">\n Node n\u00E3o suportado: <code>{{ getExpansionDetailNodeType(node) }}</code>\n </div>\n }\n }\n </ng-template>\n </section>\n </td>\n </ng-container>\n <tr\n mat-row\n *matRowDef=\"let row; columns: expansionDetailRowColumns; when: isExpansionDetailRow\"\n class=\"pfx-expansion-detail-row\"\n ></tr>\n }\n }\n</table>\n}\n\n<!-- Virtual rows path (header preserved above) -->\n@if (shouldRenderDataSurface() && !schemaError && !dataError && isVirtualized()) {\n <cdk-virtual-scroll-viewport\n class=\"ptable-viewport\"\n [itemSize]=\"getVirtItemHeight()\"\n [minBufferPx]=\"getVirtBufferSize() * getVirtItemHeight()\"\n [maxBufferPx]=\"getVirtBufferSize() * getVirtItemHeight() * 2\"\n [style.minHeight]=\"getVirtMinHeightHostStyle()\"\n >\n <table\n class=\"mat-mdc-table\"\n [ngClass]=\"getTableElevationClassName()\"\n [style.width]=\"getVirtualTableWidthStyle()\"\n >\n <tbody>\n <tr class=\"mat-mdc-row\"\n *cdkVirtualFor=\"let row of dataSource.data; let i = index; trackBy: trackByRow\"\n [class.pfx-row-selected]=\"selection.isSelected(row)\"\n [attr.aria-selected]=\"config.behavior?.selection?.enabled ? (selection.isSelected(row) ? 'true' : 'false') : null\"\n [ngClass]=\"getRowClasses(row)\"\n [ngStyle]=\"getRowNgStyle(row)\"\n [matTooltip]=\"getRowTooltip(row) || null\"\n [matTooltipDisabled]=\"!getRowTooltip(row)\"\n [matTooltipPosition]=\"getRowTooltipPosition(row)\"\n [matTooltipShowDelay]=\"getRowTooltipShowDelay(row)\"\n (click)=\"onRowClicked(row, i, $event)\"\n (dblclick)=\"onRowDoubleClicked(row, i)\">\n <!-- Selection column -->\n @if (config.behavior?.selection?.enabled) { <td class=\"mat-mdc-cell\">\n <mat-checkbox\n (click)=\"$event.stopPropagation()\"\n (change)=\"toggleRow(row)\"\n [checked]=\"selection.isSelected(row)\">\n </mat-checkbox>\n </td> }\n <!-- Data columns -->\n @for (column of visibleColumns; track column.field) {\n <td class=\"mat-mdc-cell\"\n [style.text-align]=\"getColumnTextAlignStyle(column)\"\n [style.width]=\"getColumnWidthStyle(column)\"\n [attr.style]=\"getColumnCellAttrStyle(column)\"\n [ngClass]=\"getCellClasses(row, column)\"\n [ngStyle]=\"getCellNgStyle(row, column)\">\n <div\n class=\"pfx-cell-content\"\n [ngClass]=\"getCellContentClasses(row, column)\"\n [ngStyle]=\"getCellContentNgStyle(row, column)\"\n >\n <ng-container [ngSwitch]=\"getEffectiveRendererType(row, column)\">\n <ng-container *ngSwitchCase=\"'icon'\">\n <mat-icon [color]=\"getIconColor(row, column) || null\"\n [ngStyle]=\"getIconStyle(row, column)\"\n [attr.aria-label]=\"getIconAriaLabel(row, column) || null\">\n {{ getIconName(row, column) }}\n </mat-icon>\n </ng-container>\n <ng-container *ngSwitchCase=\"'image'\">\n <img class=\"pfx-cell-image\"\n [src]=\"getImageSrc(row, column)\"\n [attr.alt]=\"getImageAlt(row, column) || ''\"\n [attr.loading]=\"getImageLazy(row, column) ? 'lazy' : null\"\n [style.width.px]=\"getImageWidth(row, column)\"\n [style.height.px]=\"getImageHeight(row, column)\"\n [class.shape-rounded]=\"getImageShape(row, column) === 'rounded'\"\n [class.shape-circle]=\"getImageShape(row, column) === 'circle'\"\n [style.object-fit]=\"getImageFit(row, column)\" />\n </ng-container>\n <ng-container *ngSwitchCase=\"'badge'\">\n <span class=\"pfx-badge\" [ngClass]=\"getBadgeClasses(row, column)\">\n @if (getBadgeIcon(row, column); as bi) { <mat-icon class=\"pfx-badge-icon\">{{ bi }}</mat-icon> }\n <span class=\"pfx-badge-text\">{{ getBadgeText(row, column) }}</span>\n </span>\n </ng-container>\n <ng-container *ngSwitchDefault>\n {{ getCellValue(row, column) }}\n </ng-container>\n </ng-container>\n </div>\n </td>\n }\n\n <!-- Actions column -->\n @if (config.actions?.row?.enabled) {\n <td class=\"mat-mdc-cell praxis-actions-cell\" [class.dense]=\"dense\" [style.width]=\"getRowActionsWidthStyle()\">\n <div class=\"praxis-actions-cell__content\">\n @if (config.actions?.row?.display === 'icons' || !config.actions?.row?.display) {\n <ng-container *ngFor=\"let a of getInlineRowActions(row); trackBy: trackAction\">\n <button mat-icon-button class=\"praxis-icon-btn\"\n [disabled]=\"isActionDisabled(a, row)\"\n (click)=\"onRowAction(getActionId(a), row, $event)\"\n [matTooltip]=\"a.label || getActionId(a)\"\n matTooltipPosition=\"above\"\n matTooltipClass=\"praxis-tooltip\"\n [attr.aria-label]=\"a.label || getActionId(a)\"\n [color]=\"a.color || null\">\n <mat-icon [praxisIcon]=\"a.icon\"></mat-icon>\n </button>\n </ng-container>\n }\n @if (config.actions?.row?.display === 'buttons') {\n <ng-container *ngFor=\"let a of getInlineRowActions(row); trackBy: trackAction\">\n <button mat-flat-button class=\"praxis-row-btn\"\n [disabled]=\"isActionDisabled(a, row)\"\n (click)=\"onRowAction(getActionId(a), row, $event)\"\n [attr.aria-label]=\"a.label || getActionId(a)\"\n [color]=\"a.color || null\">\n <mat-icon [praxisIcon]=\"a.icon\"></mat-icon>\n <span>{{ a.label || getActionId(a) }}</span>\n </button>\n </ng-container>\n }\n @if (hasOverflowRowActions(row)) {\n <button mat-icon-button class=\"praxis-icon-btn praxis-more-btn\"\n [matMenuTriggerFor]=\"rowMoreMenuV\"\n [color]=\"getRowMenuButtonColor() || null\"\n aria-label=\"Mais a\u00E7\u00F5es\">\n <mat-icon [praxisIcon]=\"getRowMenuIcon()\"></mat-icon>\n </button>\n }\n <mat-menu #rowMoreMenuV=\"matMenu\" xPosition=\"before\">\n <ng-container *ngFor=\"let a of getOverflowRowActions(row); trackBy: trackAction\">\n <button mat-menu-item (click)=\"onRowAction(getActionId(a), row, $event)\" [disabled]=\"isActionDisabled(a, row)\">\n <mat-icon [color]=\"a.color || null\" [praxisIcon]=\"a.icon\"></mat-icon>\n <span>{{ a.label || getActionId(a) }}</span>\n </button>\n </ng-container>\n </mat-menu>\n </div>\n </td>\n }\n </tr>\n </tbody>\n </table>\n </cdk-virtual-scroll-viewport>\n}\n\n</div>\n@if (\n shouldRenderDataSurface()\n && !schemaError\n && !dataError\n && shouldRenderFloatingBulkActions()\n && getFloatingBulkActions().length\n && !shouldHideFloatingBulkActions()\n) {\n <div [class]=\"'praxis-floating-bulk-actions ' + getFloatingBulkPositionClass()\">\n @for (action of getFloatingBulkActions(); track getActionId(action)) {\n <button\n mat-mini-fab\n [color]=\"action.color || 'primary'\"\n [disabled]=\"isFloatingBulkActionDisabled(action)\"\n (click)=\"onToolbarAction({ action: getActionId(action), actionConfig: action })\"\n [attr.aria-label]=\"action.label || getActionId(action)\"\n [matTooltip]=\"action.label || getActionId(action)\"\n matTooltipPosition=\"left\"\n >\n <mat-icon [praxisIcon]=\"action.icon || 'done_all'\"></mat-icon>\n </button>\n }\n </div>\n}\n<!-- Barra de a\u00E7\u00F5es no rodap\u00E9 (opcional) -->\n@if (shouldRenderDataSurface() && !schemaError && !dataError && showToolbar && shouldRenderFooterToolbar()) {\n <praxis-table-toolbar\n [config]=\"config\"\n [backgroundColor]=\"getToolbarActionsBackgroundColor()\"\n [style.--pfx-filter-h]=\"getToolbarLayoutHeightHostStyle()\"\n [class.footer-flat]=\"hasBottomPaginator()\"\n class=\"praxis-toolbar-footer\"\n placement=\"footer\"\n [showMain]=\"shouldShowFooterToolbarMain()\"\n [showEndActions]=\"shouldShowFooterToolbarEndActions()\"\n [showReset]=\"shouldShowFooterToolbarReset()\"\n [showActionsGroup]=\"shouldShowToolbarActionsBottom()\"\n [showMobileActions]=\"shouldShowToolbarActionsBottom()\"\n [dslContext]=\"getToolbarDslContext()\"\n [dslFunctionRegistry]=\"dslFunctionRegistry\"\n (toolbarAction)=\"onToolbarAction($event)\"\n >\n <praxis-filter\n *ngIf=\"shouldShowFooterToolbarMain() && shouldRenderAdvancedFilter()\"\n advancedFilter\n [resourcePath]=\"getAdvancedFilterResourcePath()\"\n [filterId]=\"tableId\"\n [formId]=\"tableId\"\n [persistenceKey]=\"getAdvancedFilterPersistenceKey()\"\n [fieldMetadata]=\"getAdvancedFilterFieldMetadata()\"\n [editModeEnabled]=\"editModeEnabled\"\n [alwaysVisibleFields]=\"config.behavior?.filtering?.advancedFilters?.settings?.alwaysVisibleFields\"\n [alwaysVisibleFieldMetadataOverrides]=\"config.behavior?.filtering?.advancedFilters?.settings?.alwaysVisibleFieldMetadataOverrides ?? {}\"\n [selectedFieldIds]=\"config.behavior?.filtering?.advancedFilters?.settings?.selectedFieldIds ?? []\"\n [allowSaveTags]=\"config.behavior?.filtering?.advancedFilters?.settings?.allowSaveTags\"\n [changeDebounceMs]=\"config.behavior?.filtering?.advancedFilters?.settings?.changeDebounceMs ?? 300\"\n [i18n]=\"getFilterI18n()\"\n [mode]=\"'filter'\"\n [showFilterSettings]=\"editModeEnabled\"\n (submit)=\"onAdvancedFilterSubmit($event)\"\n (clear)=\"onAdvancedFilterClear()\"\n ></praxis-filter>\n <ng-container *ngIf=\"shouldShowFooterToolbarMain() && shouldRenderAdvancedFilter()\">\n <ng-content select=\"[advancedFilter]\"></ng-content>\n </ng-container>\n <ng-container *ngIf=\"shouldShowFooterToolbarMain() && shouldRenderAdvancedFilter()\">\n <ng-content select=\"[toolbar]\"></ng-content>\n </ng-container>\n @if (shouldShowFooterToolbarMain() && shouldRenderAdvancedFilter()) {\n @defer (on idle) {\n @if (aiAdapter) {\n <praxis-ai-assistant\n [adapter]=\"aiAdapter\"\n end-actions\n ></praxis-ai-assistant>\n }\n }\n }\n <button\n *ngIf=\"shouldShowFooterToolbarMain() && shouldRenderAdvancedFilter() && editModeEnabled\"\n end-actions\n mat-icon-button\n color=\"primary\"\n data-role=\"table-settings\"\n data-testid=\"table-settings-trigger\"\n (click)=\"openTableSettings()\"\n aria-label=\"Configura\u00E7\u00F5es\"\n [matBadge]=\"schemaOutdated ? '!' : ''\"\n [matBadgeHidden]=\"!schemaOutdated\"\n matBadgeColor=\"warn\"\n matBadgeSize=\"small\"\n matBadgePosition=\"above after\"\n [matTooltip]=\"schemaOutdated ? 'Schema do servidor mudou \u2014 Reconciliar' : 'Configura\u00E7\u00F5es'\"\n matTooltipPosition=\"below\"\n >\n <mat-icon>settings</mat-icon>\n </button>\n </praxis-table-toolbar>\n}\n<!-- Paginadores (top/bottom) -->\n@if (shouldRenderDataSurface() && !schemaError && !dataError && getPaginationEnabled() && (config.behavior?.pagination?.position === 'top' || config.behavior?.pagination?.position === 'both')) {\n <mat-paginator\n [length]=\"getPaginationLength()\"\n [pageSize]=\"getPaginationPageSize()\"\n [pageSizeOptions]=\"getPaginationPageSizeOptions()\"\n [showFirstLastButtons]=\"getPaginationShowFirstLast()\"\n (page)=\"onPageChange($event)\"\n [class.compact]=\"config.behavior?.pagination?.style === 'compact'\"\n >\n </mat-paginator>\n}\n\n@if (shouldRenderDataSurface() && !schemaError && !dataError && getPaginationEnabled() && (config.behavior?.pagination?.position === 'bottom' || config.behavior?.pagination?.position === 'both' || !config.behavior?.pagination?.position)) {\n <mat-paginator\n [length]=\"getPaginationLength()\"\n [pageSize]=\"getPaginationPageSize()\"\n [pageSizeOptions]=\"getPaginationPageSizeOptions()\"\n [showFirstLastButtons]=\"getPaginationShowFirstLast()\"\n (page)=\"onPageChange($event)\"\n [class.compact]=\"config.behavior?.pagination?.style === 'compact'\"\n [class.footer-stack]=\"shouldShowToolbarActionsBottom()\"\n >\n </mat-paginator>\n}\n", styles: ["@charset \"UTF-8\";table{width:100%}.praxis-visually-hidden-status{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}.praxis-column-reorder-status{margin:8px 0;padding:10px 12px;border-radius:8px;border:1px solid var(--p-table-border-color);background:var(--p-table-row-hover-bg);color:var(--p-table-header-fg);font-size:12px;line-height:1.4;box-shadow:0 4px 12px #00000014;animation:pfx-column-reorder-status-in var(--p-table-drag-status-enter-duration, .18s) var(--p-table-motion-easing, cubic-bezier(0, 0, .2, 1))}@keyframes pfx-column-reorder-status-in{0%{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:translateY(0)}}.praxis-actions-cell{height:100%;padding-inline:12px;white-space:nowrap}.pfx-expansion-col-header,.pfx-expansion-col-cell{width:52px;min-width:52px;text-align:center}.pfx-expansion-toggle{width:40px;height:40px}.pfx-expansion-toggle:focus-visible{outline:2px solid var(--md-sys-color-primary);outline-offset:2px}.pfx-expansion-detail-row{background:var(--md-sys-color-surface-container-low)}.pfx-expansion-detail-cell{padding:0!important;border-bottom:1px solid var(--p-table-border-color)}.pfx-expansion-detail-panel{padding:12px 16px;border-left:3px solid var(--md-sys-color-primary)}.pfx-expansion-detail-schema{margin:0;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:12px;line-height:1.4;white-space:pre-wrap;word-break:break-word;color:var(--md-sys-color-on-surface-variant)}.pfx-expansion-detail-message{font-size:13px;color:var(--md-sys-color-on-surface-variant)}.pfx-expansion-detail-message--error{color:var(--md-sys-color-error)}.pfx-expansion-detail-stack{display:grid;gap:10px}.pfx-expansion-detail-tabs{display:flex;flex-wrap:wrap;gap:8px;margin-bottom:10px}.pfx-expansion-detail-tab-btn{border:1px solid var(--p-table-border-color);background:var(--md-sys-color-surface);color:var(--md-sys-color-on-surface);border-radius:999px;padding:6px 12px;font-size:12px;line-height:1.2;cursor:pointer}.pfx-expansion-detail-tab-btn.is-active{border-color:var(--md-sys-color-primary);color:var(--md-sys-color-primary);font-weight:600}.pfx-expansion-detail-tab-btn:focus-visible{outline:2px solid var(--md-sys-color-primary);outline-offset:2px}.pfx-expansion-detail-tab-panel{display:grid;gap:10px}.pfx-expansion-node{border:1px solid var(--p-table-border-color);border-radius:8px;padding:10px 12px;background:var(--md-sys-color-surface)}.pfx-expansion-node-card__header{margin-bottom:8px}.pfx-expansion-node-card__title{margin:0;font-size:14px;line-height:1.3}.pfx-expansion-node-card__subtitle{margin:4px 0 0;font-size:12px;color:var(--md-sys-color-on-surface-variant)}.pfx-expansion-node-value{display:flex;align-items:baseline;gap:8px}.pfx-expansion-node-value__label{color:var(--md-sys-color-on-surface-variant);font-size:12px}.pfx-expansion-node-value__content{font-size:14px}.pfx-expansion-node-list__title{margin:0 0 6px;font-size:13px}.pfx-expansion-node-list ul{margin:0;padding-left:18px}.pfx-expansion-node-richtext :where(p,ul,ol,h1,h2,h3,h4,h5,h6){margin-top:0;margin-bottom:8px}.pfx-expansion-node-placeholder{font-size:12px;color:var(--md-sys-color-on-surface-variant)}:host.density-compact{--p-header-padding: 8px 12px;--p-cell-padding: 8px 12px;--p-actions-btn-size: 32px;--p-actions-icon-size: 18px}:host.density-comfortable{--p-header-padding: 12px 16px;--p-cell-padding: 12px 16px;--p-actions-btn-size: 40px;--p-actions-icon-size: 22px}:host.density-spacious{--p-header-padding: 16px 20px;--p-cell-padding: 16px 20px;--p-actions-btn-size: 44px;--p-actions-icon-size: 24px}:host.density-compact ::ng-deep .mat-mdc-cell{padding:var(--p-cell-padding, 8px 12px)}:host.density-comfortable ::ng-deep .mat-mdc-cell{padding:var(--p-cell-padding, 12px 16px)}:host.density-spacious ::ng-deep .mat-mdc-cell{padding:var(--p-cell-padding, 16px 20px)}:host.density-compact .praxis-actions-cell{padding-inline:8px}:host.density-spacious .praxis-actions-cell{padding-inline:16px}.praxis-actions-cell__content{display:flex;align-items:center;justify-content:flex-end;gap:8px;width:100%}.praxis-actions-cell.dense .praxis-actions-cell__content{gap:6px}.praxis-icon-btn{width:var(--p-actions-btn-size, 40px);height:var(--p-actions-btn-size, 40px);border:0;background:transparent;padding:0;display:inline-flex;align-items:center;justify-content:center;border-radius:9999px;cursor:pointer;--mat-icon-button-state-layer-size: var(--p-actions-btn-size, 40px)}.praxis-icon-btn:hover{background:var(--md-sys-color-surface-variant)}.praxis-icon-btn:focus-visible{outline:2px solid var(--md-sys-color-primary);outline-offset:2px}.praxis-icon-btn mat-icon,.praxis-icon-btn .mat-icon{font-size:var(--p-actions-icon-size, 22px);width:var(--p-actions-icon-size, 22px);height:var(--p-actions-icon-size, 22px);line-height:var(--p-actions-icon-size, 22px)}.praxis-more-btn{width:var(--p-actions-more-btn-size, var(--p-actions-btn-size, 40px));height:var(--p-actions-more-btn-size, var(--p-actions-btn-size, 40px));--mat-icon-button-state-layer-size: var(--p-actions-more-btn-size, var(--p-actions-btn-size, 40px));background-image:var(--p-actions-more-btn-gradient, none);background-size:100% 100%;background-repeat:no-repeat}.praxis-more-btn mat-icon,.praxis-more-btn .mat-icon{font-size:var(--p-actions-more-icon-size, var(--p-actions-icon-size, 22px));width:var(--p-actions-more-icon-size, var(--p-actions-icon-size, 22px));height:var(--p-actions-more-icon-size, var(--p-actions-icon-size, 22px));line-height:var(--p-actions-more-icon-size, var(--p-actions-icon-size, 22px));color:var(--p-actions-more-icon-color);background-image:var(--p-actions-more-icon-gradient, none);-webkit-background-clip:text;background-clip:text}.praxis-icon-btn.destructive mat-icon{color:var(--md-sys-color-error)}.mat-mdc-tooltip.praxis-tooltip{margin-top:-8px;margin-bottom:8px}.spacer{flex:1 1 auto}.praxis-table-header{display:flex;flex-wrap:wrap;align-items:flex-start;gap:8px;margin:16px 0 12px;width:100%;clear:both;position:relative}.praxis-table-header.stacked{margin:0}.praxis-table-header>praxis-table-toolbar{flex:1 0 100%}.praxis-floating-bulk-actions{position:fixed;z-index:1001;display:inline-flex;align-items:center;gap:8px;padding:8px;border-radius:999px;background:var(--md-sys-color-surface-container-highest);box-shadow:0 8px 20px #00000029}.praxis-floating-bulk-actions.pos-bottom-right{right:20px;bottom:20px}.praxis-floating-bulk-actions.pos-bottom-left{left:20px;bottom:20px}.praxis-floating-bulk-actions.pos-top-right{right:20px;top:20px}.praxis-floating-bulk-actions.pos-top-left{left:20px;top:20px}@media(max-width:768px){.praxis-floating-bulk-actions{gap:6px;padding:6px}.praxis-floating-bulk-actions.pos-bottom-right{right:12px;left:auto;bottom:12px}.praxis-floating-bulk-actions.pos-bottom-left{left:12px;right:auto;bottom:12px}.praxis-floating-bulk-actions.pos-top-right{right:12px;left:auto;top:12px}.praxis-floating-bulk-actions.pos-top-left{left:12px;right:auto;top:12px}}:host{display:block;width:100%;min-width:0;max-width:100%;--pfx-toolbar-pad-y: 6px;--pfx-toolbar-pad-x: 12px;--p-table-bg: var(--md-sys-color-surface-container-highest);--p-table-text-color: var(--md-sys-color-on-surface);--p-table-header-bg: var(--md-sys-color-surface-container-highest);--p-table-header-fg: var(--md-sys-color-on-surface);--p-table-border-color: var(--md-sys-color-outline-variant);--p-table-row-even-bg: var(--md-sys-color-surface-container);--p-table-row-hover-bg: var(--md-sys-color-surface-container-high);--p-table-row-selected-bg: var(--md-sys-color-primary-container);--p-table-badge-soft-primary-bg: var(--md-sys-color-primary-container);--p-table-badge-soft-primary-fg: var(--md-sys-color-on-primary-container);--p-table-badge-soft-accent-bg: var(--md-sys-color-secondary-container);--p-table-badge-soft-accent-fg: var(--md-sys-color-on-secondary-container);--p-table-badge-soft-warn-bg: var(--md-sys-color-error-container);--p-table-badge-soft-warn-fg: var(--md-sys-color-on-error-container);--p-table-state-success-bg: var(--md-sys-color-tertiary-container);--p-table-state-success-fg: var(--md-sys-color-on-tertiary-container);--p-table-state-warning-bg: var(--md-sys-color-secondary-container);--p-table-state-warning-fg: var(--md-sys-color-on-secondary-container);--p-table-state-danger-bg: var(--md-sys-color-error-container);--p-table-state-danger-fg: var(--md-sys-color-on-error-container);--p-table-state-highlight-bg: var(--md-sys-color-primary-container);--p-table-state-highlight-fg: var(--md-sys-color-on-primary-container);--p-table-drag-handle-size: 14px;--p-table-drag-handle-color: var(--md-sys-color-on-surface-variant);--p-table-drag-handle-hover-color: var(--md-sys-color-on-surface);--p-table-drag-handle-base-opacity: 0;--p-table-drag-handle-visible-opacity: .72;--p-table-drag-handle-active-opacity: 1;--p-table-drag-handle-transition-duration: .16s;--p-table-reorder-transition-duration: .16s;--p-table-drag-preview-scale: 1.01;--p-table-drag-status-enter-duration: .18s;--p-table-drag-preview-shadow: 0 14px 32px rgba(0, 0, 0, .28), 0 0 0 1px var(--p-table-border-color)}:host ::ng-deep .mat-mdc-table{background:var(--p-table-bg);color:var(--p-table-text-color);border-radius:12px 12px 0 0;width:100%;box-shadow:var(--p-table-surface-shadow);transition:box-shadow var(--p-table-selection-transition-duration, .18s) var(--p-table-motion-easing, cubic-bezier(0, 0, .2, 1))}:host ::ng-deep .mat-mdc-table:hover{box-shadow:var(--p-table-surface-shadow-hover, var(--p-table-surface-shadow))}:host ::ng-deep .mat-mdc-table.table-stack-top{border-top-left-radius:0;border-top-right-radius:0}:host ::ng-deep .praxis-toolbar-footer{border:0 solid var(--p-table-border-color);border-top:0;border-radius:0;background:var(--p-table-bg)}:host ::ng-deep .mat-mdc-paginator.footer-stack{border-top-left-radius:0;border-top-right-radius:0;border-top:0}:host ::ng-deep .mat-mdc-paginator.footer-stack .mat-mdc-paginator-container{padding:8px 12px}:host [data-role=table-settings].mat-mdc-icon-button{--mdc-icon-button-icon-color: var(--md-sys-color-primary);color:var(--md-sys-color-primary)}.pfx-link{color:var(--md-sys-color-primary);text-decoration:underline;cursor:pointer}.pfx-chip{display:inline-flex;align-items:center;gap:4px;padding:2px 8px;border-radius:10px;font-size:12px;line-height:1;border:1px solid transparent}.pfx-chip-icon{font-size:14px;width:14px;height:14px}.pfx-chip--outlined{background:transparent;border-color:var(--md-sys-color-outline-variant);color:var(--md-sys-color-on-surface)}.pfx-chip--filled-primary{background:var(--md-sys-color-primary);color:var(--md-sys-color-on-primary)}.pfx-chip--filled-accent{background:var(--md-sys-color-secondary);color:var(--md-sys-color-on-secondary)}.pfx-chip--filled-warn{background:var(--md-sys-color-error);color:var(--md-sys-color-on-error)}.pfx-chip--soft-primary{background:var(--p-table-badge-soft-primary-bg);color:var(--p-table-badge-soft-primary-fg)}.pfx-chip--soft-accent{background:var(--p-table-badge-soft-accent-bg);color:var(--p-table-badge-soft-accent-fg)}.pfx-chip--soft-warn{background:var(--p-table-badge-soft-warn-bg);color:var(--p-table-badge-soft-warn-fg)}.pfx-progress{position:relative;width:100%;max-width:140px;height:8px;background:var(--md-sys-color-surface-container-highest);border-radius:4px;overflow:hidden;display:inline-block;vertical-align:middle}.pfx-progress-bar{height:100%;background:var(--md-sys-color-primary);transition:width .2s ease}.pfx-progress-label{margin-left:8px;font-size:12px;opacity:.8;display:inline-block;vertical-align:middle}.pfx-avatar{display:inline-flex;align-items:center;justify-content:center;background:var(--md-sys-color-surface-container);color:var(--md-sys-color-on-surface);border-radius:4px;overflow:hidden;font-weight:600}.pfx-avatar.shape-rounded{border-radius:8px}.pfx-avatar.shape-circle{border-radius:999px}.pfx-avatar--initials{text-transform:uppercase;font-size:12px}.pfx-cell-compose{display:inline-flex;align-items:center;gap:6px}.pfx-cell-compose.dir-col{flex-direction:column;align-items:stretch}.pfx-cell-compose.align-start{justify-content:flex-start}.pfx-cell-compose.align-center{justify-content:center}.pfx-cell-compose.align-end{justify-content:flex-end}.pfx-cell-compose.wrap{flex-wrap:wrap}.pfx-cell-compose.ellipsis{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.px-scroll-viewport{width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch;overscroll-behavior-x:contain}.px-scroll-viewport.scroll-none{overflow-x:visible}.px-scroll-viewport.scroll-auto ::ng-deep .mat-mdc-table{width:max-content;min-width:100%}.px-scroll-viewport.scroll-wrap ::ng-deep .mat-mdc-header-cell,.px-scroll-viewport.scroll-wrap ::ng-deep .mat-mdc-cell{white-space:normal;text-overflow:initial}.px-scroll-viewport.scroll-wrap ::ng-deep .mat-mdc-table{width:100%}:host ::ng-deep .mat-mdc-header-row{position:sticky;top:0;z-index:1;background:var(--p-table-header-bg);color:var(--p-table-header-fg);box-shadow:var(--p-table-header-shadow, 0 1px 0 var(--p-table-border-color));border-bottom:1px solid var(--p-table-border-color)}:host ::ng-deep .mat-mdc-header-cell,:host ::ng-deep .mat-sort-header-content,:host ::ng-deep .mat-mdc-header-row .mat-icon{color:var(--p-table-header-fg)!important;font-weight:600}:host ::ng-deep .mat-mdc-header-cell.mat-sort-header-sorted .mat-sort-header-arrow,:host ::ng-deep .mat-mdc-header-cell:hover .mat-sort-header-arrow{color:var(--p-table-header-fg)!important}:host ::ng-deep .mat-mdc-header-cell.mat-sort-header-sorted .mat-sort-header-arrow .mat-sort-header-indicator,:host ::ng-deep .mat-mdc-header-cell.mat-sort-header-sorted .mat-sort-header-arrow .mat-sort-header-stem,:host ::ng-deep .mat-mdc-header-cell.mat-sort-header-sorted .mat-sort-header-arrow .mat-sort-header-pointer,:host ::ng-deep .mat-mdc-header-cell.mat-sort-header-sorted .mat-sort-header-arrow .mat-sort-header-pointer-left,:host ::ng-deep .mat-mdc-header-cell.mat-sort-header-sorted .mat-sort-header-arrow .mat-sort-header-pointer-right{border-color:var(--p-table-header-fg)!important;background:var(--p-table-header-fg)!important}:host ::ng-deep .mat-mdc-header-cell{padding:var(--p-header-padding, 12px 16px)!important;font-size:var(--p-header-font-size, inherit);font-weight:var(--p-header-font-weight, 600);letter-spacing:var(--p-header-letter-spacing, normal);text-transform:var(--p-header-text-transform, none);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}:host ::ng-deep .pfx-column-drag-enabled .mat-mdc-header-cell.praxis-header-draggable .mat-sort-header-container{display:flex;align-items:center;width:100%;gap:8px;cursor:inherit}:host ::ng-deep .pfx-column-drag-enabled .mat-mdc-header-cell.praxis-header-draggable{-webkit-user-select:none;user-select:none;cursor:grab}:host ::ng-deep .pfx-column-drag-enabled .mat-mdc-header-cell.praxis-header-draggable.cdk-drag-dragging{cursor:grabbing}:host ::ng-deep .pfx-column-drag-enabled .mat-mdc-header-cell.praxis-header-draggable .mat-sort-header-content{display:inline-flex;align-items:center;gap:8px;flex:1 1 auto;min-width:0}:host ::ng-deep .pfx-column-drag-enabled .mat-mdc-header-cell .praxis-header-label{display:inline-flex;align-items:center;flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis}:host ::ng-deep .pfx-column-drag-enabled .mat-mdc-header-cell .praxis-column-drag-handle{-webkit-appearance:none;appearance:none;border:0;background:transparent;color:var(--p-table-drag-handle-color);width:var(--p-table-drag-handle-size);min-width:var(--p-table-drag-handle-size);height:var(--p-table-drag-handle-size);padding:0;display:inline-flex;align-items:center;justify-content:center;border-radius:0;cursor:inherit;pointer-events:none;touch-action:none;opacity:var(--p-table-drag-handle-base-opacity, 0);transform:none;transition:opacity var(--p-table-drag-handle-transition-duration, .16s) var(--p-table-motion-easing, cubic-bezier(0, 0, .2, 1)),color var(--p-table-drag-handle-transition-duration, .16s) var(--p-table-motion-easing, cubic-bezier(0, 0, .2, 1))}:host ::ng-deep .pfx-column-drag-enabled .mat-mdc-header-cell.praxis-header-draggable:hover .praxis-column-drag-handle,:host ::ng-deep .pfx-column-drag-enabled .mat-mdc-header-cell.praxis-header-draggable:focus-within .praxis-column-drag-handle{opacity:var(--p-table-drag-handle-visible-opacity, .72);color:var(--p-table-drag-handle-hover-color, var(--p-table-drag-handle-color))}:host ::ng-deep .pfx-column-drag-enabled .mat-mdc-header-cell .praxis-column-drag-handle:active{opacity:var(--p-table-drag-handle-active-opacity, 1);cursor:grabbing}:host ::ng-deep .pfx-column-drag-enabled .mat-mdc-header-cell .praxis-column-drag-handle .mat-icon{font-size:14px;width:14px;height:14px;line-height:14px;transition:transform .18s var(--p-table-motion-easing, cubic-bezier(0, 0, .2, 1))}:host ::ng-deep .pfx-column-drag-enabled .mat-mdc-header-cell.praxis-header-draggable:hover .praxis-column-drag-handle .mat-icon{transform:none}:host ::ng-deep .pfx-column-drag-indicator .cdk-drop-list-dragging .mat-mdc-header-cell:not(.cdk-drag-placeholder){transition:transform var(--p-table-reorder-transition-duration, .18s) var(--p-table-motion-easing, cubic-bezier(0, 0, .2, 1))}:host ::ng-deep .pfx-column-drag-indicator .mat-mdc-header-cell.cdk-drag-animating{transition:transform var(--p-table-reorder-transition-duration, .16s) var(--p-table-motion-easing, cubic-bezier(0, 0, .2, 1))}.pfx-column-drag-preview{box-sizing:border-box;border-radius:10px;border:1px solid var(--p-table-border-color);background:linear-gradient(135deg,var(--p-table-header-bg) 0%,var(--p-table-row-hover-bg) 100%);color:var(--p-table-header-fg);box-shadow:var(--p-table-drag-preview-shadow);transform:scale(var(--p-table-drag-preview-scale, 1.01));pointer-events:none;z-index:1000}.pfx-column-drag-preview .praxis-column-drag-handle,.pfx-column-drag-preview .mat-sort-header-arrow,.pfx-column-drag-preview .mat-sort-header-indicator,.pfx-column-drag-preview .mat-sort-header-stem,.pfx-column-drag-preview .mat-sort-header-pointer,.pfx-column-drag-preview .mat-sort-header-pointer-left,.pfx-column-drag-preview .mat-sort-header-pointer-right{display:none!important}.pfx-column-drag-preview .mat-sort-header-container{padding-right:0!important}.pfx-column-drag-preview .mat-sort-header-content,.pfx-column-drag-preview .praxis-header-label{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}:host ::ng-deep .pfx-column-drag-indicator .cdk-drag-placeholder{opacity:1;border:1px dashed var(--p-table-border-color);background:var(--p-table-row-hover-bg)}:host ::ng-deep .pfx-column-drag-indicator .cdk-drag-placeholder *{opacity:0}:host ::ng-deep .pfx-column-drag-indicator .mat-mdc-header-cell.cdk-drag-dragging{opacity:.58}@media(prefers-reduced-motion:reduce){:host ::ng-deep .pfx-column-drag-indicator .cdk-drop-list-dragging .mat-mdc-header-cell:not(.cdk-drag-placeholder){transition:none}:host ::ng-deep .pfx-column-drag-enabled .mat-mdc-header-cell .praxis-column-drag-handle,:host ::ng-deep .pfx-column-drag-enabled .mat-mdc-header-cell .praxis-column-drag-handle .mat-icon,.pfx-column-drag-preview{transition:none;transform:none}.praxis-column-reorder-status{animation:none}:host ::ng-deep .mat-mdc-row{transition:none}:host ::ng-deep .mat-mdc-table{transition:none}}.praxis-actions-header{text-align:right}.praxis-actions-header.align-start{text-align:left}.praxis-actions-header.align-center{text-align:center}.praxis-actions-header.align-end{text-align:right}.praxis-actions-header .praxis-actions-header__content{display:inline-flex;align-items:center;gap:var(--p-actions-header-gap, 6px);color:var(--p-actions-header-color, inherit)}.praxis-actions-header .praxis-actions-header__content .mat-icon{font-size:18px;width:18px;height:18px;line-height:18px}:host ::ng-deep .mat-mdc-header-cell .mat-sort-header-container{padding-right:20px}:host ::ng-deep .pfx-column-drag-enabled .mat-mdc-header-cell.praxis-header-draggable .mat-sort-header-container{padding-right:12px}@media(pointer:coarse){:host{--p-table-drag-handle-size: 18px;--p-table-drag-handle-base-opacity: .56;--p-table-drag-handle-visible-opacity: .92}}:host ::ng-deep .mat-mdc-cell{color:var(--p-table-text-color);font-size:var(--p-cell-font-size, inherit);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}:host ::ng-deep .mat-mdc-cell .pfx-cell-content,:host ::ng-deep .mat-cell .pfx-cell-content{display:inline-flex;align-items:center;gap:6px;width:100%;min-width:0;overflow:hidden}:host ::ng-deep .pfx-cell-content.pfx-cell-anim{animation-duration:var(--pfx-cell-anim-duration, .8s);animation-delay:var(--pfx-cell-anim-delay, 0ms);animation-fill-mode:both;animation-timing-function:ease-in-out}:host ::ng-deep .pfx-cell-content.pfx-cell-anim.pfx-cell-anim--once{animation-iteration-count:1}:host ::ng-deep .pfx-cell-content.pfx-cell-anim.pfx-cell-anim--loop{animation-iteration-count:infinite}:host ::ng-deep .pfx-cell-content.pfx-cell-anim.pfx-cell-anim--count{animation-iteration-count:var(--pfx-cell-anim-iteration-count, 1)}:host ::ng-deep .pfx-cell-content.pfx-cell-anim.pfx-cell-anim--on-hover{animation-play-state:paused}:host ::ng-deep .mat-mdc-cell:hover .pfx-cell-content.pfx-cell-anim.pfx-cell-anim--on-hover,:host ::ng-deep .mat-cell:hover .pfx-cell-content.pfx-cell-anim.pfx-cell-anim--on-hover{animation-play-state:running}:host ::ng-deep .pfx-cell-content.pfx-cell-anim.pfx-cell-anim--pulse{animation-name:pfx-cell-pulse}:host ::ng-deep .pfx-cell-content.pfx-cell-anim.pfx-cell-anim--blink{animation-name:pfx-cell-blink}:host ::ng-deep .pfx-cell-content.pfx-cell-anim.pfx-cell-anim--grow{animation-name:pfx-cell-grow}:host ::ng-deep .pfx-cell-content.pfx-cell-anim.pfx-cell-anim--fade{animation-name:pfx-cell-fade}:host ::ng-deep .pfx-cell-content.pfx-cell-anim.pfx-cell-anim--slide-in{animation-name:pfx-cell-slide-in}:host ::ng-deep .pfx-cell-content.pfx-cell-anim.pfx-cell-anim--border-pulse{animation-name:pfx-cell-border-pulse}@keyframes pfx-cell-pulse{0%{transform:scale(1)}50%{transform:scale(var(--pfx-cell-anim-scale-peak, 1.015))}to{transform:scale(1)}}@keyframes pfx-cell-blink{0%,49%{opacity:1}50%,to{opacity:var(--pfx-cell-anim-min-opacity, .35)}}@keyframes pfx-cell-grow{0%{transform:scale(.985)}to{transform:scale(1)}}@keyframes pfx-cell-fade{0%{opacity:0}to{opacity:1}}@keyframes pfx-cell-slide-in{0%{opacity:0;transform:translateY(var(--pfx-cell-anim-slide-distance, 4px))}to{opacity:1;transform:translateY(0)}}@keyframes pfx-cell-border-pulse{0%,to{box-shadow:inset 0 0 rgba(var(--pfx-cell-anim-border-rgb, 25, 118, 210),0)}50%{box-shadow:inset 0 0 0 2px rgba(var(--pfx-cell-anim-border-rgb, 25, 118, 210),var(--pfx-cell-anim-border-strength, .3))}}@media(prefers-reduced-motion:reduce){:host ::ng-deep .pfx-cell-content.pfx-cell-anim{animation:none!important}}:host ::ng-deep .mat-mdc-row:hover{background:var(--p-table-row-hover-bg)}:host ::ng-deep .mat-mdc-row{transition:background-color var(--p-table-hover-transition-duration, .18s) var(--p-table-motion-easing, cubic-bezier(0, 0, .2, 1)),box-shadow var(--p-table-selection-transition-duration, .18s) var(--p-table-motion-easing, cubic-bezier(0, 0, .2, 1))}:host ::ng-deep .mat-mdc-row.pfx-row-anim{animation-duration:var(--pfx-row-anim-duration, .8s);animation-delay:var(--pfx-row-anim-delay, 0ms);animation-fill-mode:both;animation-timing-function:ease-in-out}:host ::ng-deep .mat-mdc-row.pfx-row-anim.pfx-row-anim--once{animation-iteration-count:1}:host ::ng-deep .mat-mdc-row.pfx-row-anim.pfx-row-anim--loop{animation-iteration-count:infinite}:host ::ng-deep .mat-mdc-row.pfx-row-anim.pfx-row-anim--count{animation-iteration-count:var(--pfx-row-anim-iteration-count, 1)}:host ::ng-deep .mat-mdc-row.pfx-row-anim.pfx-row-anim--on-hover{animation-play-state:paused}:host ::ng-deep .mat-mdc-row.pfx-row-anim.pfx-row-anim--on-hover:hover{animation-play-state:running}:host ::ng-deep .mat-mdc-row.pfx-row-anim.pfx-row-anim--pulse{animation-name:pfx-row-pulse}:host ::ng-deep .mat-mdc-row.pfx-row-anim.pfx-row-anim--blink{animation-name:pfx-row-blink}:host ::ng-deep .mat-mdc-row.pfx-row-anim.pfx-row-anim--grow{animation-name:pfx-row-grow}:host ::ng-deep .mat-mdc-row.pfx-row-anim.pfx-row-anim--fade{animation-name:pfx-row-fade}:host ::ng-deep .mat-mdc-row.pfx-row-anim.pfx-row-anim--slide-in{animation-name:pfx-row-slide-in}:host ::ng-deep .mat-mdc-row.pfx-row-anim.pfx-row-anim--border-pulse{animation-name:pfx-row-border-pulse}@keyframes pfx-row-pulse{0%{transform:scale(1)}50%{transform:scale(var(--pfx-row-anim-scale-peak, 1.015))}to{transform:scale(1)}}@keyframes pfx-row-blink{0%,49%{opacity:1}50%,to{opacity:var(--pfx-row-anim-min-opacity, .35)}}@keyframes pfx-row-grow{0%{transform:scale(.985)}to{transform:scale(1)}}@keyframes pfx-row-fade{0%{opacity:0}to{opacity:1}}@keyframes pfx-row-slide-in{0%{opacity:0;transform:translateY(var(--pfx-row-anim-slide-distance, 4px))}to{opacity:1;transform:translateY(0)}}@keyframes pfx-row-border-pulse{0%,to{box-shadow:inset 0 0 rgba(var(--pfx-row-anim-border-rgb, 25, 118, 210),0)}50%{box-shadow:inset 0 0 0 2px rgba(var(--pfx-row-anim-border-rgb, 25, 118, 210),var(--pfx-row-anim-border-strength, .3))}}@media(prefers-reduced-motion:reduce){:host ::ng-deep .mat-mdc-row.pfx-row-anim{animation:none!important}}:host ::ng-deep .mat-mdc-row:nth-child(2n){background:var(--p-table-row-even-bg)}:host ::ng-deep .mat-mdc-row:nth-child(2n):hover{background:var(--p-table-row-hover-bg)}:host ::ng-deep .mat-mdc-row.pfx-row-selected,:host ::ng-deep .mat-mdc-row.pfx-row-selected:hover{background:var(--p-table-row-selected-bg)}:host.row-borders ::ng-deep .mat-mdc-row .mat-mdc-cell{border-bottom:1px solid var(--p-table-border-color)}:host.row-borders ::ng-deep .mat-mdc-header-row .mat-mdc-header-cell{border-bottom:none}:host.col-borders ::ng-deep .mat-mdc-header-row .mat-mdc-header-cell,:host.col-borders ::ng-deep .mat-mdc-row .mat-mdc-cell{border-right:1px solid var(--p-table-border-color)}:host.col-borders ::ng-deep .mat-mdc-header-row .mat-mdc-header-cell:last-child,:host.col-borders ::ng-deep .mat-mdc-row .mat-mdc-cell:last-child{border-right:none}.ptable-error{display:flex;align-items:center;gap:12px;padding:12px;margin:8px 0;border:1px solid var(--md-sys-color-error);border-radius:8px}.ptable-error__content{flex:1}.ptable-error__title{font-weight:600}.ptable-info-banner{display:flex;gap:12px;align-items:center;padding:8px 12px;margin:8px 0;border-radius:8px;border:1px solid var(--md-sys-color-primary);background:var(--md-sys-color-primary-container);color:var(--md-sys-color-on-primary-container)}.ptable-info-banner .text{flex:1;font-weight:600}.ptable-info-banner .actions{display:flex;gap:8px}.pfx-cell-image{display:inline-block;vertical-align:middle;background:var(--md-sys-color-surface-variant);border:1px solid var(--md-sys-color-outline-variant)}.pfx-cell-image.shape-rounded{border-radius:8px}.pfx-cell-image.shape-circle{border-radius:9999px}.pfx-badge{display:inline-flex;align-items:center;gap:6px;line-height:1;padding:4px 8px;border-radius:9999px;font-size:12px;font-weight:600;border:1px solid transparent}.pfx-badge .pfx-badge-icon{font-size:16px;width:16px;height:16px}.pfx-badge--filled-primary{background:var(--md-sys-color-primary);color:var(--md-sys-color-on-primary)}.pfx-badge--filled-accent{background:var(--md-sys-color-secondary);color:var(--md-sys-color-on-secondary)}.pfx-badge--filled-warn{background:var(--md-sys-color-error);color:var(--md-sys-color-on-error)}.pfx-badge--outlined{background:transparent;border-color:var(--md-sys-color-outline-variant);color:inherit}.pfx-badge--soft-primary{background:var(--p-table-badge-soft-primary-bg);color:var(--p-table-badge-soft-primary-fg)}.pfx-badge--soft-accent{background:var(--p-table-badge-soft-accent-bg);color:var(--p-table-badge-soft-accent-fg)}.pfx-badge--soft-warn{background:var(--p-table-badge-soft-warn-bg);color:var(--p-table-badge-soft-warn-fg)}.row--success,.row--success td,td.row--success{background-color:var(--p-table-state-success-bg)!important;color:var(--p-table-state-success-fg)!important}.row--warning,.row--warning td,td.row--warning{background-color:var(--p-table-state-warning-bg)!important;color:var(--p-table-state-warning-fg)!important}.row--danger,.row--danger td,td.row--danger{background-color:var(--p-table-state-danger-bg)!important;color:var(--p-table-state-danger-fg)!important}.row--highlight,.row--highlight td,td.row--highlight{background-color:var(--p-table-state-highlight-bg)!important;color:var(--p-table-state-highlight-fg)!important;font-weight:600}.row--muted,.row--muted td,td.row--muted{opacity:.7;filter:saturate(.6)}\n"] }]
41444
+ ], template: "@if (shouldShowEmptyState()) {\n <praxis-empty-state-card\n icon=\"link\"\n [title]=\"'Conecte a tabela \u00E0 fonte de dados'\"\n [description]=\"'Informe a rota do recurso da API para carregar colunas e dados automaticamente.'\"\n [primaryAction]=\"{ label: 'Conectar \u00E0 fonte de dados', icon: 'bolt', action: openQuickConnect.bind(this) }\"\n ></praxis-empty-state-card>\n}\n\n<!-- Error State with Quick Connect CTA -->\n@if (isRemoteMode() && (schemaError || dataError)) {\n<div class=\"ptable-error\" role=\"alert\" aria-live=\"assertive\">\n <mat-icon color=\"warn\" aria-hidden=\"true\">error</mat-icon>\n <div class=\"ptable-error__content\">\n <div class=\"ptable-error__title\">Erro</div>\n <div>{{ errorMessage || 'Ocorreu um erro ao carregar a tabela.' }}</div>\n </div>\n <button mat-flat-button color=\"primary\" (click)=\"openQuickConnect()\">\n <mat-icon>bolt</mat-icon>\n Conectar a recurso\n </button>\n @if (!schemaError) { <button mat-stroked-button (click)=\"retryData()\">Tentar novamente</button> }\n @if (schemaError) { <button mat-stroked-button (click)=\"reloadSchema()\">Recarregar colunas</button> }\n </div>\n}\n\n<!-- Inline banner for schema change (only in edit mode) -->\n@if (shouldShowOutdatedInline()) {\n<div class=\"ptable-info-banner\" role=\"status\" aria-live=\"polite\">\n <div class=\"text\">O schema do servidor mudou. Reconciliar agora?</div>\n <div class=\"actions\">\n <button mat-stroked-button color=\"primary\" (click)=\"onReconcileRequested()\">\n <mat-icon>sync</mat-icon>\n Reconciliar\n </button>\n <button mat-button (click)=\"onSnoozeOutdated()\">Lembrar depois</button>\n <button mat-button (click)=\"onIgnoreOutdated()\">Ignorar</button>\n </div>\n </div>\n}\n\n@if (shouldRenderDataSurface() && !schemaError && !dataError && toolbarV2) {\n <div class=\"praxis-table-header\" [class.edit-mode]=\"editModeEnabled\" [class.stacked]=\"showToolbar\">\n @if (showToolbar && shouldShowToolbarTopPlacement()) {\n <praxis-table-toolbar\n [config]=\"config\"\n [backgroundColor]=\"getToolbarActionsBackgroundColor()\"\n [style.--pfx-filter-h]=\"getToolbarLayoutHeightHostStyle()\"\n [dslContext]=\"getToolbarDslContext()\"\n [dslFunctionRegistry]=\"dslFunctionRegistry\"\n [showActionsGroup]=\"shouldShowToolbarActionsTop()\"\n [showMobileActions]=\"shouldShowToolbarActionsTop()\"\n (toolbarAction)=\"onToolbarAction($event)\"\n (reset)=\"onResetPreferences()\"\n >\n @if (shouldRenderAdvancedFilter()) {\n <praxis-filter\n advancedFilter\n [resourcePath]=\"getAdvancedFilterResourcePath()\"\n [filterId]=\"tableId\"\n [formId]=\"tableId\"\n [persistenceKey]=\"getAdvancedFilterPersistenceKey()\"\n [fieldMetadata]=\"getAdvancedFilterFieldMetadata()\"\n [editModeEnabled]=\"editModeEnabled\"\n \n [alwaysVisibleFields]=\"config.behavior?.filtering?.advancedFilters?.settings?.alwaysVisibleFields\"\n [alwaysVisibleFieldMetadataOverrides]=\"config.behavior?.filtering?.advancedFilters?.settings?.alwaysVisibleFieldMetadataOverrides ?? {}\"\n [selectedFieldIds]=\"config.behavior?.filtering?.advancedFilters?.settings?.selectedFieldIds ?? []\"\n [allowSaveTags]=\"config.behavior?.filtering?.advancedFilters?.settings?.allowSaveTags\"\n [changeDebounceMs]=\"config.behavior?.filtering?.advancedFilters?.settings?.changeDebounceMs ?? 300\"\n [i18n]=\"getFilterI18n()\"\n [mode]=\"'filter'\"\n [showFilterSettings]=\"editModeEnabled\"\n (submit)=\"onAdvancedFilterSubmit($event)\"\n (clear)=\"onAdvancedFilterClear()\"\n ></praxis-filter>\n }\n <ng-content select=\"[advancedFilter]\" />\n <ng-content select=\"[toolbar]\" />\n \n <!-- AI Assistant in Toolbar -->\n @defer (on idle) {\n @if (aiAdapter) {\n <praxis-ai-assistant [adapter]=\"aiAdapter\" end-actions></praxis-ai-assistant>\n }\n }\n\n @if (editModeEnabled) {\n <button end-actions mat-icon-button color=\"primary\" data-role=\"table-settings\" data-testid=\"table-settings-trigger\"\n (click)=\"openTableSettings()\" aria-label=\"Configura\u00E7\u00F5es\"\n [matBadge]=\"schemaOutdated ? '!' : ''\"\n [matBadgeHidden]=\"!schemaOutdated\"\n matBadgeColor=\"warn\" matBadgeSize=\"small\" matBadgePosition=\"above after\"\n [matTooltip]=\"schemaOutdated ? 'Schema do servidor mudou \u2014 Reconciliar' : 'Configura\u00E7\u00F5es'\"\n matTooltipPosition=\"below\">\n <mat-icon>settings</mat-icon>\n </button>\n }\n </praxis-table-toolbar>\n }\n @if (!showToolbar && editModeEnabled) {\n <div class=\"ptable-header-actions\">\n @defer (on idle) {\n @if (aiAdapter) {\n <praxis-ai-assistant [adapter]=\"aiAdapter\"></praxis-ai-assistant>\n }\n }\n <button mat-icon-button color=\"primary\" data-role=\"table-settings\" data-testid=\"table-settings-trigger\" (click)=\"openTableSettings()\" aria-label=\"Configura\u00E7\u00F5es\"\n [matBadge]=\"schemaOutdated ? '!' : ''\"\n [matBadgeHidden]=\"!schemaOutdated\"\n matBadgeColor=\"warn\" matBadgeSize=\"small\" matBadgePosition=\"above after\"\n [matTooltip]=\"schemaOutdated ? 'Schema do servidor mudou \u2014 Reconciliar' : 'Configura\u00E7\u00F5es'\"\n matTooltipPosition=\"below\">\n <mat-icon>settings</mat-icon>\n </button>\n @if (isRemoteMode()) {\n <button mat-icon-button (click)=\"disconnect()\" aria-label=\"Desconectar\" matTooltip=\"Desconectar da fonte de dados\">\n <mat-icon>link_off</mat-icon>\n </button>\n }\n </div>\n }\n </div>\n} @else {\n @if (shouldRenderDataSurface() && !schemaError && !dataError) {\n @if (showToolbar && shouldShowToolbarTopPlacement()) {\n <praxis-table-toolbar\n [config]=\"config\"\n [backgroundColor]=\"getToolbarActionsBackgroundColor()\"\n [style.--pfx-filter-h]=\"getToolbarLayoutHeightHostStyle()\"\n [dslContext]=\"getToolbarDslContext()\"\n [dslFunctionRegistry]=\"dslFunctionRegistry\"\n [showActionsGroup]=\"shouldShowToolbarActionsTop()\"\n [showMobileActions]=\"shouldShowToolbarActionsTop()\"\n (toolbarAction)=\"onToolbarAction($event)\"\n (reset)=\"onResetPreferences()\"\n >\n @if (shouldRenderAdvancedFilter()) {\n <praxis-filter\n advancedFilter\n [resourcePath]=\"getAdvancedFilterResourcePath()\"\n [filterId]=\"tableId\"\n [formId]=\"tableId\"\n [persistenceKey]=\"getAdvancedFilterPersistenceKey()\"\n [fieldMetadata]=\"getAdvancedFilterFieldMetadata()\"\n [editModeEnabled]=\"editModeEnabled\"\n \n [alwaysVisibleFields]=\"config.behavior?.filtering?.advancedFilters?.settings?.alwaysVisibleFields\"\n [alwaysVisibleFieldMetadataOverrides]=\"config.behavior?.filtering?.advancedFilters?.settings?.alwaysVisibleFieldMetadataOverrides ?? {}\"\n [selectedFieldIds]=\"config.behavior?.filtering?.advancedFilters?.settings?.selectedFieldIds ?? []\"\n [allowSaveTags]=\"config.behavior?.filtering?.advancedFilters?.settings?.allowSaveTags\"\n [changeDebounceMs]=\"config.behavior?.filtering?.advancedFilters?.settings?.changeDebounceMs ?? 300\"\n [i18n]=\"getFilterI18n()\"\n [mode]=\"'filter'\"\n [showFilterSettings]=\"editModeEnabled\"\n (submit)=\"onAdvancedFilterSubmit($event)\"\n (clear)=\"onAdvancedFilterClear()\"\n ></praxis-filter>\n }\n <ng-content select=\"[advancedFilter]\" />\n <ng-content select=\"[toolbar]\" />\n @defer (on idle) {\n @if (aiAdapter) {\n <praxis-ai-assistant [adapter]=\"aiAdapter\" end-actions></praxis-ai-assistant>\n }\n }\n @if (editModeEnabled) {\n <button end-actions mat-icon-button color=\"primary\" data-role=\"table-settings\" data-testid=\"table-settings-trigger\"\n (click)=\"openTableSettings()\" aria-label=\"Configura\u00E7\u00F5es\"\n [matBadge]=\"schemaOutdated ? '!' : ''\"\n [matBadgeHidden]=\"!schemaOutdated\"\n matBadgeColor=\"warn\" matBadgeSize=\"small\" matBadgePosition=\"above after\"\n [matTooltip]=\"schemaOutdated ? 'Schema do servidor mudou \u2014 Reconciliar' : 'Configura\u00E7\u00F5es'\"\n matTooltipPosition=\"below\">\n <mat-icon>settings</mat-icon>\n </button>\n }\n </praxis-table-toolbar>\n }\n @if (!showToolbar && editModeEnabled) {\n <div class=\"ptable-header-actions\">\n <button mat-icon-button color=\"primary\" data-role=\"table-settings\" data-testid=\"table-settings-trigger\" (click)=\"openTableSettings()\" aria-label=\"Configura\u00E7\u00F5es\"\n [matBadge]=\"schemaOutdated ? '!' : ''\"\n [matBadgeHidden]=\"!schemaOutdated\"\n matBadgeColor=\"warn\" matBadgeSize=\"small\" matBadgePosition=\"above after\"\n [matTooltip]=\"schemaOutdated ? 'Schema do servidor mudou \u2014 Reconciliar' : 'Configura\u00E7\u00F5es'\"\n matTooltipPosition=\"below\">\n <mat-icon>settings</mat-icon>\n </button>\n </div>\n }\n }\n}\n<div class=\"px-scroll-viewport\"\n cdkScrollable\n [class.scroll-auto]=\"horizontalScroll === 'auto'\"\n [class.scroll-wrap]=\"horizontalScroll === 'wrap'\"\n [class.scroll-none]=\"horizontalScroll === 'none'\">\n\n@if (shouldRenderDataSurface() && !schemaError && !dataError) {\n<div class=\"praxis-visually-hidden-status\" role=\"status\" aria-live=\"polite\" aria-atomic=\"true\">\n {{ columnReorderStatusMessage }}\n</div>\n@if (columnReorderVisualStatusMessage) {\n <div class=\"praxis-column-reorder-status\" role=\"note\">\n {{ columnReorderVisualStatusMessage }}\n </div>\n}\n<table\n mat-table\n data-testid=\"table-column-drag-drop-list\"\n [dataSource]=\"dataSource\"\n [multiTemplateDataRows]=\"isRowExpansionRuntimeEnabled()\"\n cdkDropList\n [cdkDropListDisabled]=\"!isColumnDraggingEnabled()\"\n [cdkDropListData]=\"visibleDataColumnsForDrag\"\n cdkDropListOrientation=\"horizontal\"\n (cdkDropListDropped)=\"onColumnDrop($event)\"\n matSort\n (matSortChange)=\"onSortChange($event)\"\n [matSortDisabled]=\"!getSortingEnabled()\"\n [ngClass]=\"getTableElevationClassName()\"\n [class.table-stack-top]=\"showToolbar\"\n [class.pfx-column-drag-enabled]=\"isColumnDraggingEnabled()\"\n [class.pfx-column-drag-indicator]=\"isColumnDragIndicatorEnabled()\"\n>\n @if (config.behavior?.selection?.enabled) {\n <ng-container\n matColumnDef=\"_select\"\n >\n <th mat-header-cell *matHeaderCellDef>\n @if (canSelectAll()) {\n <mat-checkbox\n (change)=\"masterToggle()\"\n [checked]=\"isAllSelected()\"\n [indeterminate]=\"selection.hasValue() && !isAllSelected()\"\n ></mat-checkbox>\n }\n </th>\n <td mat-cell *matCellDef=\"let row\">\n <mat-checkbox\n (click)=\"$event.stopPropagation()\"\n (change)=\"toggleRow(row)\"\n [checked]=\"selection.isSelected(row)\"\n ></mat-checkbox>\n </td>\n </ng-container>\n }\n @if (isRowExpansionRuntimeEnabled()) {\n <ng-container matColumnDef=\"_expander\">\n <th mat-header-cell *matHeaderCellDef class=\"pfx-expansion-col-header\">\n <span class=\"praxis-visually-hidden-status\">Expandir detalhes da linha</span>\n </th>\n <td mat-cell *matCellDef=\"let row; let i = index\" class=\"pfx-expansion-col-cell\">\n <button\n mat-icon-button\n class=\"pfx-expansion-toggle\"\n [disabled]=\"!isRowExpandable(row, i) || !isExpansionIconTriggerEnabled()\"\n [attr.aria-expanded]=\"isRowExpanded(row, i) ? 'true' : 'false'\"\n [attr.aria-controls]=\"getRowExpansionDetailId(row, i)\"\n [attr.aria-label]=\"getRowExpansionToggleAriaLabel(row, i)\"\n (click)=\"onExpansionToggleFromIcon(row, i, $event)\"\n (keydown)=\"onExpansionToggleKeydown($event, row, i)\"\n >\n <mat-icon>{{ isRowExpanded(row, i) ? 'expand_less' : 'expand_more' }}</mat-icon>\n </button>\n </td>\n </ng-container>\n }\n @for (column of visibleColumns; track column.field) {\n <ng-container\n [matColumnDef]=\"column.field\"\n [sticky]=\"column.sticky === true || column.sticky === 'start'\"\n [stickyEnd]=\"column.sticky === 'end'\"\n >\n <th\n mat-header-cell\n *matHeaderCellDef\n mat-sort-header\n cdkDrag\n [cdkDragData]=\"column\"\n cdkDragLockAxis=\"x\"\n cdkDragPreviewClass=\"pfx-column-drag-preview\"\n (cdkDragStarted)=\"onColumnDragStarted(column)\"\n (cdkDragEnded)=\"onColumnDragEnded($event, column)\"\n (keydown)=\"onColumnDragHandleKeydown($event, column)\"\n [cdkDragDisabled]=\"!isColumnDraggingEnabled() || !isColumnDraggable(column)\"\n [class.praxis-header-draggable]=\"isColumnDraggingEnabled() && isColumnDraggable(column)\"\n [disabled]=\"!getSortingEnabled() || column.sortable === false\"\n [style.text-align]=\"getColumnTextAlignStyle(column)\"\n [style.width]=\"getColumnWidthStyle(column)\"\n [attr.style]=\"getColumnHeaderAttrStyle(column)\"\n [attr.aria-label]=\"isColumnDraggingEnabled() && isColumnDraggable(column) ? getColumnDragHandleAriaLabel(column) : null\"\n [matTooltip]=\"isColumnDraggingEnabled() && isColumnDraggable(column) ? getColumnDragHandleTooltip(column) : null\"\n matTooltipPosition=\"above\"\n matTooltipClass=\"praxis-tooltip\"\n >\n <span class=\"praxis-header-label\" data-testid=\"column-header-label\">{{ column.header }}</span>\n @if (isColumnDraggingEnabled() && isColumnDraggable(column)) {\n <span\n class=\"praxis-column-drag-handle\"\n data-testid=\"column-drag-handle\"\n [attr.data-column-field]=\"column.field\"\n aria-hidden=\"true\"\n >\n <mat-icon [praxisIcon]=\"'drag_indicator'\"></mat-icon>\n </span>\n }\n </th>\n <td\n mat-cell\n *matCellDef=\"let element\"\n [style.text-align]=\"getColumnTextAlignStyle(column)\"\n [style.width]=\"getColumnWidthStyle(column)\"\n [attr.style]=\"getColumnCellAttrStyle(column)\"\n [ngClass]=\"getCellClasses(element, column)\"\n [ngStyle]=\"getCellNgStyle(element, column)\"\n >\n <div\n class=\"pfx-cell-content\"\n [ngClass]=\"getCellContentClasses(element, column)\"\n [ngStyle]=\"getCellContentNgStyle(element, column)\"\n >\n <ng-container [ngSwitch]=\"getEffectiveRendererType(element, column)\">\n <!-- Icon renderer -->\n <ng-container *ngSwitchCase=\"'icon'\">\n <mat-icon\n [color]=\"getIconColor(element, column) || null\"\n [ngStyle]=\"getIconStyle(element, column)\"\n [attr.aria-label]=\"getIconAriaLabel(element, column) || null\"\n >{{ getIconName(element, column) }}</mat-icon\n >\n </ng-container>\n\n <!-- Image renderer -->\n <ng-container *ngSwitchCase=\"'image'\">\n <img\n class=\"pfx-cell-image\"\n [src]=\"getImageSrc(element, column)\"\n [attr.alt]=\"getImageAlt(element, column) || ''\"\n [attr.loading]=\"getImageLazy(element, column) ? 'lazy' : null\"\n [style.width.px]=\"getImageWidth(element, column)\"\n [style.height.px]=\"getImageHeight(element, column)\"\n [class.shape-rounded]=\"getImageShape(element, column) === 'rounded'\"\n [class.shape-circle]=\"getImageShape(element, column) === 'circle'\"\n [style.object-fit]=\"getImageFit(element, column)\"\n />\n </ng-container>\n\n <!-- Badge renderer -->\n <ng-container *ngSwitchCase=\"'badge'\">\n <span class=\"pfx-badge\" [ngClass]=\"getBadgeClasses(element, column)\">\n @if (getBadgeIcon(element, column); as bi) { <mat-icon class=\"pfx-badge-icon\">{{ bi }}</mat-icon> }\n <span class=\"pfx-badge-text\">{{ getBadgeText(element, column) }}</span>\n </span>\n </ng-container>\n\n <!-- Link renderer -->\n <ng-container *ngSwitchCase=\"'link'\">\n <a\n class=\"pfx-link\"\n [attr.href]=\"getLinkHref(element, column) || null\"\n [attr.target]=\"getLinkTarget(element, column) || null\"\n [attr.rel]=\"getLinkRel(element, column) || null\"\n (click)=\"$event.stopPropagation()\"\n >{{ getLinkText(element, column) }}</a\n >\n </ng-container>\n\n <!-- Button renderer -->\n <ng-container *ngSwitchCase=\"'button'\">\n <ng-container [ngSwitch]=\"getButtonVariant(element, column)\">\n <button\n *ngSwitchCase=\"'outlined'\"\n mat-stroked-button\n [color]=\"getButtonColor(element, column) || null\"\n [disabled]=\"isButtonDisabled(element, column)\"\n [attr.aria-label]=\"getButtonAriaLabel(element, column) || getButtonLabel(element, column)\"\n (click)=\"onButtonClick(element, column, $event)\"\n >\n @if (getButtonIcon(element, column); as bi) { <mat-icon>{{ bi }}</mat-icon> }\n {{ getButtonLabel(element, column) }}\n </button>\n <button\n *ngSwitchCase=\"'text'\"\n mat-button\n [color]=\"getButtonColor(element, column) || null\"\n [disabled]=\"isButtonDisabled(element, column)\"\n [attr.aria-label]=\"getButtonAriaLabel(element, column) || getButtonLabel(element, column)\"\n (click)=\"onButtonClick(element, column, $event)\"\n >\n @if (getButtonIcon(element, column); as bi) { <mat-icon>{{ bi }}</mat-icon> }\n {{ getButtonLabel(element, column) }}\n </button>\n <button\n *ngSwitchDefault\n mat-flat-button\n [color]=\"getButtonColor(element, column) || null\"\n [disabled]=\"isButtonDisabled(element, column)\"\n [attr.aria-label]=\"getButtonAriaLabel(element, column) || getButtonLabel(element, column)\"\n (click)=\"onButtonClick(element, column, $event)\"\n >\n @if (getButtonIcon(element, column); as bi) { <mat-icon>{{ bi }}</mat-icon> }\n {{ getButtonLabel(element, column) }}\n </button>\n </ng-container>\n </ng-container>\n\n <!-- Chip renderer -->\n <ng-container *ngSwitchCase=\"'chip'\">\n <span class=\"pfx-chip\" [ngClass]=\"getChipClasses(element, column)\">\n @if (getChipIcon(element, column); as ci) { <mat-icon class=\"pfx-chip-icon\">{{ ci }}</mat-icon> }\n <span class=\"pfx-chip-text\">{{ getChipText(element, column) }}</span>\n </span>\n </ng-container>\n\n <!-- Progress renderer -->\n <ng-container *ngSwitchCase=\"'progress'\">\n <div class=\"pfx-progress\">\n <div class=\"pfx-progress-bar\" [style.width.%]=\"getProgressWidthPercentStyle(element, column)\" [style.background]=\"getProgressBackgroundStyle(element, column)\"></div>\n @if (getProgressShowLabel(element, column)) { <div class=\"pfx-progress-label\">{{ getProgressValue(element, column) }}%</div> }\n </div>\n </ng-container>\n\n <!-- Avatar renderer -->\n <ng-container *ngSwitchCase=\"'avatar'\">\n @if (getAvatarSrc(element, column); as asrc) {\n <img class=\"pfx-avatar\" [src]=\"asrc\" [attr.alt]=\"getAvatarAlt(element, column) || ''\" [ngStyle]=\"getAvatarStyle(element, column)\" [class.shape-rounded]=\"getAvatarShape(element, column) === 'rounded'\" [class.shape-circle]=\"getAvatarShape(element, column) === 'circle'\" loading=\"lazy\" />\n } @else {\n <span class=\"pfx-avatar pfx-avatar--initials\" [ngStyle]=\"getAvatarStyle(element, column)\" [class.shape-rounded]=\"getAvatarShape(element, column) === 'rounded'\" [class.shape-circle]=\"getAvatarShape(element, column) === 'circle'\">{{ getAvatarInitials(element, column) }}</span>\n }\n </ng-container>\n\n <!-- Toggle renderer -->\n <ng-container *ngSwitchCase=\"'toggle'\">\n <mat-slide-toggle\n [checked]=\"getToggleState(element, column)\"\n [disabled]=\"isToggleDisabled(element, column)\"\n [attr.aria-label]=\"getToggleAriaLabel(element, column) || 'Alternar'\"\n (change)=\"onToggleChange(element, column, $event)\"\n (click)=\"$event.stopPropagation()\"\n ></mat-slide-toggle>\n </ng-container>\n\n <!-- Menu renderer -->\n <ng-container *ngSwitchCase=\"'menu'\">\n <button mat-icon-button [matMenuTriggerFor]=\"menuRef\" (click)=\"$event.stopPropagation()\" [attr.aria-label]=\"getMenuAriaLabel(element, column) || 'Menu'\">\n <mat-icon>more_vert</mat-icon>\n </button>\n <mat-menu #menuRef=\"matMenu\">\n <button mat-menu-item *ngFor=\"let it of getMenuItems(element, column)\" (click)=\"onMenuItemClick(it, element, $event)\" [disabled]=\"!it.__visible\" >\n @if (it.icon) { <mat-icon>{{ it.icon }}</mat-icon> }\n <span>{{ it.label }}</span>\n </button>\n </mat-menu>\n </ng-container>\n\n <!-- Rating renderer -->\n <ng-container *ngSwitchCase=\"'rating'\">\n <praxis-table-rating\n class=\"pfx-rating-cell\"\n [itemsCount]=\"getRatingMax(element, column)\"\n [value]=\"getRatingValue(element, column)\"\n [size]=\"getRatingSize(element, column)\"\n [ratingColor]=\"getRatingColor(element, column)\"\n [outlineColor]=\"getRatingOutlineColor(element, column)\"\n [ariaLabel]=\"getRatingAriaLabel(element, column) || column.header\">\n </praxis-table-rating>\n </ng-container>\n\n <!-- HTML renderer (sanitizado) -->\n <ng-container *ngSwitchCase=\"'html'\">\n <span [innerHTML]=\"getSafeHtml(element, column)\"></span>\n </ng-container>\n\n <!-- Compose renderer -->\n <ng-container *ngSwitchCase=\"'compose'\">\n <span class=\"pfx-cell-compose\" [ngClass]=\"getComposeClasses(element, column)\" [ngStyle]=\"getComposeGapStyle(element, column)\">\n <ng-container *ngFor=\"let it of getComposeItems(element, column)\">\n <ng-container [ngSwitch]=\"getItemEffectiveType(element, column, it)\">\n <!-- Reuse helpers by projecting item as faux column -->\n <ng-container *ngSwitchCase=\"'icon'\">\n <mat-icon [color]=\"getIconColor(element, asItemColumn(column, it)) || null\" [ngStyle]=\"getIconStyle(element, asItemColumn(column, it))\" [attr.aria-label]=\"getIconAriaLabel(element, asItemColumn(column, it)) || null\">{{ getIconName(element, asItemColumn(column, it)) }}</mat-icon>\n </ng-container>\n <ng-container *ngSwitchCase=\"'image'\">\n <img class=\"pfx-cell-image\" [src]=\"getImageSrc(element, asItemColumn(column, it))\" [attr.alt]=\"getImageAlt(element, asItemColumn(column, it)) || ''\" [attr.loading]=\"getImageLazy(element, asItemColumn(column, it)) ? 'lazy' : null\" [style.width.px]=\"getImageWidth(element, asItemColumn(column, it))\" [style.height.px]=\"getImageHeight(element, asItemColumn(column, it))\" [class.shape-rounded]=\"getImageShape(element, asItemColumn(column, it)) === 'rounded'\" [class.shape-circle]=\"getImageShape(element, asItemColumn(column, it)) === 'circle'\" [style.object-fit]=\"getImageFit(element, asItemColumn(column, it))\" />\n </ng-container>\n <ng-container *ngSwitchCase=\"'badge'\">\n <span class=\"pfx-badge\" [ngClass]=\"getBadgeClasses(element, asItemColumn(column, it))\">@if (getBadgeIcon(element, asItemColumn(column, it)); as bi) { <mat-icon class=\"pfx-badge-icon\">{{ bi }}</mat-icon> }<span class=\"pfx-badge-text\">{{ getBadgeText(element, asItemColumn(column, it)) }}</span></span>\n </ng-container>\n <ng-container *ngSwitchCase=\"'link'\">\n <a class=\"pfx-link\" [attr.href]=\"getLinkHref(element, asItemColumn(column, it)) || null\" [attr.target]=\"getLinkTarget(element, asItemColumn(column, it)) || null\" [attr.rel]=\"getLinkRel(element, asItemColumn(column, it)) || null\" (click)=\"$event.stopPropagation()\">{{ getLinkText(element, asItemColumn(column, it)) }}</a>\n </ng-container>\n <ng-container *ngSwitchCase=\"'button'\">\n <ng-container [ngSwitch]=\"getButtonVariant(element, asItemColumn(column, it))\">\n <button *ngSwitchCase=\"'outlined'\" mat-stroked-button [color]=\"getButtonColor(element, asItemColumn(column, it)) || null\" [disabled]=\"isButtonDisabled(element, asItemColumn(column, it))\" [attr.aria-label]=\"getButtonAriaLabel(element, asItemColumn(column, it)) || getButtonLabel(element, asItemColumn(column, it))\" (click)=\"onButtonClick(element, asItemColumn(column, it), $event)\">@if (getButtonIcon(element, asItemColumn(column, it)); as bi) { <mat-icon>{{ bi }}</mat-icon> }{{ getButtonLabel(element, asItemColumn(column, it)) }}</button>\n <button *ngSwitchCase=\"'text'\" mat-button [color]=\"getButtonColor(element, asItemColumn(column, it)) || null\" [disabled]=\"isButtonDisabled(element, asItemColumn(column, it))\" [attr.aria-label]=\"getButtonAriaLabel(element, asItemColumn(column, it)) || getButtonLabel(element, asItemColumn(column, it))\" (click)=\"onButtonClick(element, asItemColumn(column, it), $event)\">@if (getButtonIcon(element, asItemColumn(column, it)); as bi) { <mat-icon>{{ bi }}</mat-icon> }{{ getButtonLabel(element, asItemColumn(column, it)) }}</button>\n <button *ngSwitchDefault mat-flat-button [color]=\"getButtonColor(element, asItemColumn(column, it)) || null\" [disabled]=\"isButtonDisabled(element, asItemColumn(column, it))\" [attr.aria-label]=\"getButtonAriaLabel(element, asItemColumn(column, it)) || getButtonLabel(element, asItemColumn(column, it))\" (click)=\"onButtonClick(element, asItemColumn(column, it), $event)\">@if (getButtonIcon(element, asItemColumn(column, it)); as bi) { <mat-icon>{{ bi }}</mat-icon> }{{ getButtonLabel(element, asItemColumn(column, it)) }}</button>\n </ng-container>\n </ng-container>\n <ng-container *ngSwitchCase=\"'chip'\">\n <span class=\"pfx-chip\" [ngClass]=\"getChipClasses(element, asItemColumn(column, it))\">@if (getChipIcon(element, asItemColumn(column, it)); as ci) { <mat-icon class=\"pfx-chip-icon\">{{ ci }}</mat-icon> }<span class=\"pfx-chip-text\">{{ getChipText(element, asItemColumn(column, it)) }}</span></span>\n </ng-container>\n <ng-container *ngSwitchCase=\"'progress'\">\n <div class=\"pfx-progress\"><div class=\"pfx-progress-bar\" [style.width.%]=\"getProgressWidthPercentStyle(element, asItemColumn(column, it))\" [style.background]=\"getProgressBackgroundStyle(element, asItemColumn(column, it))\"></div>@if (getProgressShowLabel(element, asItemColumn(column, it))) { <div class=\"pfx-progress-label\">{{ getProgressValue(element, asItemColumn(column, it)) }}%</div> }</div>\n </ng-container>\n <ng-container *ngSwitchCase=\"'avatar'\">\n @if (getAvatarSrc(element, asItemColumn(column, it)); as asrc) {\n <img class=\"pfx-avatar\" [src]=\"asrc\" [attr.alt]=\"getAvatarAlt(element, asItemColumn(column, it)) || ''\" [ngStyle]=\"getAvatarStyle(element, asItemColumn(column, it))\" [class.shape-rounded]=\"getAvatarShape(element, asItemColumn(column, it)) === 'rounded'\" [class.shape-circle]=\"getAvatarShape(element, asItemColumn(column, it)) === 'circle'\" loading=\"lazy\" />\n } @else {\n <span class=\"pfx-avatar pfx-avatar--initials\" [ngStyle]=\"getAvatarStyle(element, asItemColumn(column, it))\" [class.shape-rounded]=\"getAvatarShape(element, asItemColumn(column, it)) === 'rounded'\" [class.shape-circle]=\"getAvatarShape(element, asItemColumn(column, it)) === 'circle'\">{{ getAvatarInitials(element, asItemColumn(column, it)) }}</span>\n }\n </ng-container>\n <ng-container *ngSwitchCase=\"'toggle'\">\n <mat-slide-toggle [checked]=\"getToggleState(element, asItemColumn(column, it))\" [disabled]=\"isToggleDisabled(element, asItemColumn(column, it))\" [attr.aria-label]=\"getToggleAriaLabel(element, asItemColumn(column, it)) || 'Alternar'\" (change)=\"onToggleChange(element, asItemColumn(column, it), $event)\" (click)=\"$event.stopPropagation()\"></mat-slide-toggle>\n </ng-container>\n <ng-container *ngSwitchCase=\"'menu'\">\n <button mat-icon-button [matMenuTriggerFor]=\"menuRef\" (click)=\"$event.stopPropagation()\" [attr.aria-label]=\"getMenuAriaLabel(element, asItemColumn(column, it)) || 'Menu'\"><mat-icon>more_vert</mat-icon></button>\n <mat-menu #menuRef=\"matMenu\">\n <button mat-menu-item *ngFor=\"let mi of getMenuItems(element, asItemColumn(column, it))\" (click)=\"onMenuItemClick(mi, element, $event)\" [disabled]=\"!mi.__visible\">\n @if (mi.icon) { <mat-icon>{{ mi.icon }}</mat-icon> }\n <span>{{ mi.label }}</span>\n </button>\n </mat-menu>\n </ng-container>\n <ng-container *ngSwitchCase=\"'rating'\">\n <praxis-table-rating\n class=\"pfx-rating-cell\"\n [itemsCount]=\"getRatingMax(element, asItemColumn(column, it))\"\n [value]=\"getRatingValue(element, asItemColumn(column, it))\"\n [size]=\"getRatingSize(element, asItemColumn(column, it))\"\n [ratingColor]=\"getRatingColor(element, asItemColumn(column, it))\"\n [outlineColor]=\"getRatingOutlineColor(element, asItemColumn(column, it))\"\n [ariaLabel]=\"getRatingAriaLabel(element, asItemColumn(column, it)) || column.header\">\n </praxis-table-rating>\n </ng-container>\n <ng-container *ngSwitchCase=\"'html'\">\n <span [innerHTML]=\"getSafeHtml(element, asItemColumn(column, it))\"></span>\n </ng-container>\n <!-- Value item: render base cell text alongside visuals -->\n <ng-container *ngSwitchCase=\"'value'\">\n <span class=\"pfx-cell-value\">{{ getComposeItemValue(element, column, it) }}</span>\n </ng-container>\n </ng-container>\n </ng-container>\n </span>\n </ng-container>\n\n <!-- Default text rendering -->\n <ng-container *ngSwitchDefault>\n {{ getCellValue(element, column) }}\n </ng-container>\n </ng-container>\n </div>\n </td>\n </ng-container>\n }\n @if (config.actions?.row?.enabled) {\n <ng-container matColumnDef=\"_actions\" [sticky]=\"config.actions?.row?.sticky === true || config.actions?.row?.sticky === 'start'\" [stickyEnd]=\"config.actions?.row?.sticky === 'end'\">\n <th mat-header-cell *matHeaderCellDef #actionsHeaderCell [style.width]=\"getRowActionsWidthStyle()\" class=\"praxis-actions-header\" [class.align-start]=\"getActionsHeaderAlign() === 'start'\" [class.align-center]=\"getActionsHeaderAlign() === 'center'\" [class.align-end]=\"getActionsHeaderAlign() === 'end'\">\n <div class=\"praxis-actions-header__content\" [matTooltip]=\"getActionsHeaderTooltip() || ''\" [matTooltipDisabled]=\"!getActionsHeaderTooltip()\">\n @if (getActionsHeaderIcon(); as hi) { <mat-icon [praxisIcon]=\"hi\"></mat-icon> }\n @if (getActionsHeaderLabel(); as hl) { <span class=\"label\">{{ hl }}</span> }\n </div>\n </th>\n <td\n mat-cell\n *matCellDef=\"let row\"\n class=\"praxis-actions-cell\"\n [class.dense]=\"dense\"\n [style.width]=\"getRowActionsWidthStyle()\"\n >\n <div class=\"praxis-actions-cell__content\">\n <!-- A\u00E7\u00F5es inline -->\n <!-- Inline actions: icons mode -->\n @if (config.actions?.row?.display === 'icons' || !config.actions?.row?.display) {\n <ng-container *ngFor=\"let a of getInlineRowActions(row); trackBy: trackAction\">\n <button\n mat-icon-button\n class=\"praxis-icon-btn\"\n [disabled]=\"isActionDisabled(a, row)\"\n (click)=\"onRowAction(getActionId(a), row, $event)\"\n [matTooltip]=\"a.label || getActionId(a)\"\n matTooltipPosition=\"above\"\n matTooltipClass=\"praxis-tooltip\"\n [attr.aria-label]=\"a.label || getActionId(a)\"\n [color]=\"a.color || null\"\n >\n <mat-icon [praxisIcon]=\"a.icon\"></mat-icon>\n </button>\n </ng-container>\n }\n\n <!-- Inline actions: buttons mode (show label + icon) -->\n @if (config.actions?.row?.display === 'buttons') {\n <ng-container *ngFor=\"let a of getInlineRowActions(row); trackBy: trackAction\">\n <button\n mat-flat-button\n class=\"praxis-row-btn\"\n [disabled]=\"isActionDisabled(a, row)\"\n (click)=\"onRowAction(getActionId(a), row, $event)\"\n [attr.aria-label]=\"a.label || getActionId(a)\"\n [color]=\"a.color || null\"\n >\n <mat-icon [praxisIcon]=\"a.icon\"></mat-icon>\n <span>{{ a.label || getActionId(a) }}</span>\n </button>\n </ng-container>\n }\n\n <!-- Menu de overflow -->\n @if (hasOverflowRowActions(row)) {\n <button\n mat-icon-button\n class=\"praxis-icon-btn praxis-more-btn\"\n [matMenuTriggerFor]=\"rowMoreMenu\"\n [color]=\"getRowMenuButtonColor() || null\"\n aria-label=\"Mais a\u00E7\u00F5es\"\n >\n <mat-icon [praxisIcon]=\"getRowMenuIcon()\"></mat-icon>\n </button>\n }\n <mat-menu #rowMoreMenu=\"matMenu\" xPosition=\"before\">\n <ng-container\n *ngFor=\"let a of getOverflowRowActions(row); trackBy: trackAction\"\n >\n <button\n mat-menu-item\n (click)=\"onRowAction(getActionId(a), row, $event)\"\n [disabled]=\"isActionDisabled(a, row)\"\n >\n <mat-icon [color]=\"a.color || null\" [praxisIcon]=\"a.icon\"></mat-icon>\n <span>{{ a.label || getActionId(a) }}</span>\n </button>\n </ng-container>\n </mat-menu>\n </div>\n </td>\n </ng-container>\n }\n\n <tr\n mat-header-row\n *matHeaderRowDef=\"displayedColumns\"\n ></tr>\n @if (!isVirtualized()) {\n <tr\n mat-row\n *matRowDef=\"let row; let i = index; columns: displayedColumns\"\n [class.pfx-row-selected]=\"selection.isSelected(row)\"\n [class.pfx-row-expanded]=\"isRowExpansionRuntimeEnabled() && isRowExpanded(row, i)\"\n [attr.aria-selected]=\"config.behavior?.selection?.enabled ? (selection.isSelected(row) ? 'true' : 'false') : null\"\n [attr.aria-expanded]=\"isRowExpansionRuntimeEnabled() ? (isRowExpanded(row, i) ? 'true' : 'false') : null\"\n [ngClass]=\"getRowClasses(row)\"\n [ngStyle]=\"getRowNgStyle(row)\"\n [matTooltip]=\"getRowTooltip(row) || null\"\n [matTooltipDisabled]=\"!getRowTooltip(row)\"\n [matTooltipPosition]=\"getRowTooltipPosition(row)\"\n [matTooltipShowDelay]=\"getRowTooltipShowDelay(row)\"\n (click)=\"onRowClicked(row, i, $event)\"\n (dblclick)=\"onRowDoubleClicked(row, i)\"\n ></tr>\n @if (isRowExpansionRuntimeEnabled()) {\n <ng-container matColumnDef=\"_detail\">\n <td\n mat-cell\n *matCellDef=\"let row; let i = index\"\n class=\"pfx-expansion-detail-cell\"\n [attr.colspan]=\"displayedColumns.length\"\n >\n <section\n class=\"pfx-expansion-detail-panel\"\n [attr.id]=\"getRowExpansionDetailId(row, i)\"\n role=\"region\"\n [attr.aria-label]=\"getRowExpansionRegionAriaLabel(row, i)\"\n [attr.aria-busy]=\"getExpansionDetailViewState(row, i).status === 'loading' ? 'true' : 'false'\"\n >\n @let detailState = getExpansionDetailViewState(row, i);\n @if (detailState.status === 'loading') {\n <div class=\"pfx-expansion-detail-message\" role=\"status\" aria-live=\"polite\">\n Carregando detail schema...\n </div>\n } @else if (detailState.status !== 'ready') {\n <div\n class=\"pfx-expansion-detail-message pfx-expansion-detail-message--error\"\n role=\"alert\"\n aria-live=\"assertive\"\n aria-atomic=\"true\"\n >\n {{ detailState.message || 'Detail indispon\u00EDvel para esta linha.' }}\n </div>\n } @else {\n @if (getExpansionDetailLayout(detailState.schema) === 'tabs') {\n @let detailTabs = getExpansionDetailTabs(detailState.schema);\n @if (detailTabs.length) {\n <div class=\"pfx-expansion-detail-tabs\" role=\"tablist\" aria-label=\"Se\u00E7\u00F5es do detail\">\n @for (tab of detailTabs; track $index; let tabIndex = $index) {\n <button\n type=\"button\"\n class=\"pfx-expansion-detail-tab-btn\"\n role=\"tab\"\n [attr.id]=\"getExpansionDetailTabId(row, i, tab, tabIndex)\"\n [attr.aria-controls]=\"getExpansionDetailPanelId(row, i, tab, tabIndex)\"\n [attr.aria-selected]=\"isExpansionDetailTabActive(row, i, tab, tabIndex, detailTabs) ? 'true' : 'false'\"\n [attr.tabindex]=\"isExpansionDetailTabActive(row, i, tab, tabIndex, detailTabs) ? '0' : '-1'\"\n [class.is-active]=\"isExpansionDetailTabActive(row, i, tab, tabIndex, detailTabs)\"\n (click)=\"onExpansionDetailTabSelect(row, i, tab, tabIndex, $event)\"\n (keydown)=\"onExpansionDetailTabKeydown($event, row, i, tabIndex, detailTabs)\"\n >\n {{ getExpansionDetailNodeTitle(tab, 'Tab') }}\n </button>\n }\n </div>\n @for (tab of detailTabs; track $index; let tabIndex = $index) {\n @if (isExpansionDetailTabActive(row, i, tab, tabIndex, detailTabs)) {\n <div\n class=\"pfx-expansion-detail-tab-panel\"\n role=\"tabpanel\"\n [attr.id]=\"getExpansionDetailPanelId(row, i, tab, tabIndex)\"\n [attr.aria-labelledby]=\"getExpansionDetailTabId(row, i, tab, tabIndex)\"\n >\n @for (childNode of getExpansionDetailNodeChildren(tab); track $index) {\n <ng-container\n *ngTemplateOutlet=\"\n expansionDetailNodeTemplate;\n context: { $implicit: childNode, row: row, index: i }\n \"\n ></ng-container>\n }\n </div>\n }\n }\n } @else {\n <div class=\"pfx-expansion-detail-message\">\n Schema em layout tabs sem abas v\u00E1lidas.\n </div>\n }\n } @else {\n <div class=\"pfx-expansion-detail-stack\">\n @for (node of getExpansionDetailItems(detailState.schema); track $index) {\n <ng-container\n *ngTemplateOutlet=\"\n expansionDetailNodeTemplate;\n context: { $implicit: node, row: row, index: i }\n \"\n ></ng-container>\n }\n </div>\n }\n }\n\n <ng-template #expansionDetailNodeTemplate let-node let-row=\"row\" let-index=\"index\">\n @switch (getExpansionDetailNodeType(node)) {\n @case ('card') {\n <article class=\"pfx-expansion-node pfx-expansion-node-card\">\n <header class=\"pfx-expansion-node-card__header\">\n <h5 class=\"pfx-expansion-node-card__title\">\n {{ getExpansionDetailNodeTitle(node, 'Card') }}\n </h5>\n @if (node?.subtitle) {\n <p class=\"pfx-expansion-node-card__subtitle\">{{ node?.subtitle }}</p>\n }\n </header>\n @for (childNode of getExpansionDetailNodeChildren(node); track $index) {\n <ng-container\n *ngTemplateOutlet=\"\n expansionDetailNodeTemplate;\n context: { $implicit: childNode, row: row, index: index }\n \"\n ></ng-container>\n }\n </article>\n }\n @case ('value') {\n <div class=\"pfx-expansion-node pfx-expansion-node-value\">\n <span class=\"pfx-expansion-node-value__label\">\n {{ getExpansionDetailNodeTitle(node, 'Valor') }}\n </span>\n <strong class=\"pfx-expansion-node-value__content\">\n {{ getExpansionDetailValue(row, node) }}\n </strong>\n </div>\n }\n @case ('list') {\n <section class=\"pfx-expansion-node pfx-expansion-node-list\">\n <h6 class=\"pfx-expansion-node-list__title\">\n {{ getExpansionDetailNodeTitle(node, 'Lista') }}\n </h6>\n @let listItems = getExpansionDetailListItems(row, node);\n @if (listItems.length) {\n <ul>\n @for (entry of listItems; track $index) {\n <li>{{ entry }}</li>\n }\n </ul>\n } @else {\n <p class=\"pfx-expansion-node-placeholder\">Sem itens.</p>\n }\n </section>\n }\n @case ('richText') {\n <div\n class=\"pfx-expansion-node pfx-expansion-node-richtext\"\n [innerHTML]=\"getExpansionDetailRichText(node)\"\n ></div>\n }\n @case ('formRef') {\n <div class=\"pfx-expansion-node pfx-expansion-node-placeholder\">\n Formul\u00E1rio referenciado: <code>{{ node?.schemaId || node?.id || 'sem-id' }}</code>\n </div>\n }\n @case ('tableRef') {\n <div class=\"pfx-expansion-node pfx-expansion-node-placeholder\">\n Tabela referenciada: <code>{{ node?.schemaId || node?.id || 'sem-id' }}</code>\n </div>\n }\n @case ('chartRef') {\n <div class=\"pfx-expansion-node pfx-expansion-node-placeholder\">\n Gr\u00E1fico referenciado: <code>{{ node?.schemaId || node?.id || 'sem-id' }}</code>\n </div>\n }\n @case ('templateRef') {\n <div class=\"pfx-expansion-node pfx-expansion-node-placeholder\">\n Template referenciado: <code>{{ node?.id || node?.templateId || 'sem-id' }}</code>\n </div>\n }\n @case ('action') {\n <div class=\"pfx-expansion-node pfx-expansion-node-placeholder\">\n A\u00E7\u00E3o declarada: <code>{{ node?.id || node?.actionId || 'sem-id' }}</code>\n </div>\n }\n @case ('tab') {\n <div class=\"pfx-expansion-node pfx-expansion-node-placeholder\">\n Node <code>tab</code> fora de contexto de tabs.\n </div>\n }\n @default {\n <div class=\"pfx-expansion-node pfx-expansion-node-placeholder\">\n Node n\u00E3o suportado: <code>{{ getExpansionDetailNodeType(node) }}</code>\n </div>\n }\n }\n </ng-template>\n </section>\n </td>\n </ng-container>\n <tr\n mat-row\n *matRowDef=\"let row; columns: expansionDetailRowColumns; when: isExpansionDetailRow\"\n class=\"pfx-expansion-detail-row\"\n ></tr>\n }\n }\n</table>\n}\n\n<!-- Virtual rows path (header preserved above) -->\n@if (shouldRenderDataSurface() && !schemaError && !dataError && isVirtualized()) {\n <cdk-virtual-scroll-viewport\n class=\"ptable-viewport\"\n [itemSize]=\"getVirtItemHeight()\"\n [minBufferPx]=\"getVirtBufferSize() * getVirtItemHeight()\"\n [maxBufferPx]=\"getVirtBufferSize() * getVirtItemHeight() * 2\"\n [style.minHeight]=\"getVirtMinHeightHostStyle()\"\n >\n <table\n class=\"mat-mdc-table\"\n [ngClass]=\"getTableElevationClassName()\"\n [style.width]=\"getVirtualTableWidthStyle()\"\n >\n <tbody>\n <tr class=\"mat-mdc-row\"\n *cdkVirtualFor=\"let row of dataSource.data; let i = index; trackBy: trackByRow\"\n [class.pfx-row-selected]=\"selection.isSelected(row)\"\n [attr.aria-selected]=\"config.behavior?.selection?.enabled ? (selection.isSelected(row) ? 'true' : 'false') : null\"\n [ngClass]=\"getRowClasses(row)\"\n [ngStyle]=\"getRowNgStyle(row)\"\n [matTooltip]=\"getRowTooltip(row) || null\"\n [matTooltipDisabled]=\"!getRowTooltip(row)\"\n [matTooltipPosition]=\"getRowTooltipPosition(row)\"\n [matTooltipShowDelay]=\"getRowTooltipShowDelay(row)\"\n (click)=\"onRowClicked(row, i, $event)\"\n (dblclick)=\"onRowDoubleClicked(row, i)\">\n <!-- Selection column -->\n @if (config.behavior?.selection?.enabled) { <td class=\"mat-mdc-cell\">\n <mat-checkbox\n (click)=\"$event.stopPropagation()\"\n (change)=\"toggleRow(row)\"\n [checked]=\"selection.isSelected(row)\">\n </mat-checkbox>\n </td> }\n <!-- Data columns -->\n @for (column of visibleColumns; track column.field) {\n <td class=\"mat-mdc-cell\"\n [style.text-align]=\"getColumnTextAlignStyle(column)\"\n [style.width]=\"getColumnWidthStyle(column)\"\n [attr.style]=\"getColumnCellAttrStyle(column)\"\n [ngClass]=\"getCellClasses(row, column)\"\n [ngStyle]=\"getCellNgStyle(row, column)\">\n <div\n class=\"pfx-cell-content\"\n [ngClass]=\"getCellContentClasses(row, column)\"\n [ngStyle]=\"getCellContentNgStyle(row, column)\"\n >\n <ng-container [ngSwitch]=\"getEffectiveRendererType(row, column)\">\n <ng-container *ngSwitchCase=\"'icon'\">\n <mat-icon [color]=\"getIconColor(row, column) || null\"\n [ngStyle]=\"getIconStyle(row, column)\"\n [attr.aria-label]=\"getIconAriaLabel(row, column) || null\">\n {{ getIconName(row, column) }}\n </mat-icon>\n </ng-container>\n <ng-container *ngSwitchCase=\"'image'\">\n <img class=\"pfx-cell-image\"\n [src]=\"getImageSrc(row, column)\"\n [attr.alt]=\"getImageAlt(row, column) || ''\"\n [attr.loading]=\"getImageLazy(row, column) ? 'lazy' : null\"\n [style.width.px]=\"getImageWidth(row, column)\"\n [style.height.px]=\"getImageHeight(row, column)\"\n [class.shape-rounded]=\"getImageShape(row, column) === 'rounded'\"\n [class.shape-circle]=\"getImageShape(row, column) === 'circle'\"\n [style.object-fit]=\"getImageFit(row, column)\" />\n </ng-container>\n <ng-container *ngSwitchCase=\"'badge'\">\n <span class=\"pfx-badge\" [ngClass]=\"getBadgeClasses(row, column)\">\n @if (getBadgeIcon(row, column); as bi) { <mat-icon class=\"pfx-badge-icon\">{{ bi }}</mat-icon> }\n <span class=\"pfx-badge-text\">{{ getBadgeText(row, column) }}</span>\n </span>\n </ng-container>\n <ng-container *ngSwitchDefault>\n {{ getCellValue(row, column) }}\n </ng-container>\n </ng-container>\n </div>\n </td>\n }\n\n <!-- Actions column -->\n @if (config.actions?.row?.enabled) {\n <td class=\"mat-mdc-cell praxis-actions-cell\" [class.dense]=\"dense\" [style.width]=\"getRowActionsWidthStyle()\">\n <div class=\"praxis-actions-cell__content\">\n @if (config.actions?.row?.display === 'icons' || !config.actions?.row?.display) {\n <ng-container *ngFor=\"let a of getInlineRowActions(row); trackBy: trackAction\">\n <button mat-icon-button class=\"praxis-icon-btn\"\n [disabled]=\"isActionDisabled(a, row)\"\n (click)=\"onRowAction(getActionId(a), row, $event)\"\n [matTooltip]=\"a.label || getActionId(a)\"\n matTooltipPosition=\"above\"\n matTooltipClass=\"praxis-tooltip\"\n [attr.aria-label]=\"a.label || getActionId(a)\"\n [color]=\"a.color || null\">\n <mat-icon [praxisIcon]=\"a.icon\"></mat-icon>\n </button>\n </ng-container>\n }\n @if (config.actions?.row?.display === 'buttons') {\n <ng-container *ngFor=\"let a of getInlineRowActions(row); trackBy: trackAction\">\n <button mat-flat-button class=\"praxis-row-btn\"\n [disabled]=\"isActionDisabled(a, row)\"\n (click)=\"onRowAction(getActionId(a), row, $event)\"\n [attr.aria-label]=\"a.label || getActionId(a)\"\n [color]=\"a.color || null\">\n <mat-icon [praxisIcon]=\"a.icon\"></mat-icon>\n <span>{{ a.label || getActionId(a) }}</span>\n </button>\n </ng-container>\n }\n @if (hasOverflowRowActions(row)) {\n <button mat-icon-button class=\"praxis-icon-btn praxis-more-btn\"\n [matMenuTriggerFor]=\"rowMoreMenuV\"\n [color]=\"getRowMenuButtonColor() || null\"\n aria-label=\"Mais a\u00E7\u00F5es\">\n <mat-icon [praxisIcon]=\"getRowMenuIcon()\"></mat-icon>\n </button>\n }\n <mat-menu #rowMoreMenuV=\"matMenu\" xPosition=\"before\">\n <ng-container *ngFor=\"let a of getOverflowRowActions(row); trackBy: trackAction\">\n <button mat-menu-item (click)=\"onRowAction(getActionId(a), row, $event)\" [disabled]=\"isActionDisabled(a, row)\">\n <mat-icon [color]=\"a.color || null\" [praxisIcon]=\"a.icon\"></mat-icon>\n <span>{{ a.label || getActionId(a) }}</span>\n </button>\n </ng-container>\n </mat-menu>\n </div>\n </td>\n }\n </tr>\n </tbody>\n </table>\n </cdk-virtual-scroll-viewport>\n}\n\n</div>\n@if (\n shouldRenderDataSurface()\n && !schemaError\n && !dataError\n && shouldRenderFloatingBulkActions()\n && getFloatingBulkActions().length\n && !shouldHideFloatingBulkActions()\n) {\n <div [class]=\"'praxis-floating-bulk-actions ' + getFloatingBulkPositionClass()\">\n @for (action of getFloatingBulkActions(); track getActionId(action)) {\n <button\n mat-mini-fab\n [color]=\"action.color || 'primary'\"\n [disabled]=\"isFloatingBulkActionDisabled(action)\"\n (click)=\"onToolbarAction({ action: getActionId(action), actionConfig: action })\"\n [attr.aria-label]=\"action.label || getActionId(action)\"\n [matTooltip]=\"action.label || getActionId(action)\"\n matTooltipPosition=\"left\"\n >\n <mat-icon [praxisIcon]=\"action.icon || 'done_all'\"></mat-icon>\n </button>\n }\n </div>\n}\n<!-- Barra de a\u00E7\u00F5es no rodap\u00E9 (opcional) -->\n@if (shouldRenderDataSurface() && !schemaError && !dataError && showToolbar && shouldRenderFooterToolbar()) {\n <praxis-table-toolbar\n [config]=\"config\"\n [backgroundColor]=\"getToolbarActionsBackgroundColor()\"\n [style.--pfx-filter-h]=\"getToolbarLayoutHeightHostStyle()\"\n [class.footer-flat]=\"hasBottomPaginator()\"\n class=\"praxis-toolbar-footer\"\n placement=\"footer\"\n [showMain]=\"shouldShowFooterToolbarMain()\"\n [showEndActions]=\"shouldShowFooterToolbarEndActions()\"\n [showReset]=\"shouldShowFooterToolbarReset()\"\n [showActionsGroup]=\"shouldShowToolbarActionsBottom()\"\n [showMobileActions]=\"shouldShowToolbarActionsBottom()\"\n [dslContext]=\"getToolbarDslContext()\"\n [dslFunctionRegistry]=\"dslFunctionRegistry\"\n (toolbarAction)=\"onToolbarAction($event)\"\n >\n <praxis-filter\n *ngIf=\"shouldShowFooterToolbarMain() && shouldRenderAdvancedFilter()\"\n advancedFilter\n [resourcePath]=\"getAdvancedFilterResourcePath()\"\n [filterId]=\"tableId\"\n [formId]=\"tableId\"\n [persistenceKey]=\"getAdvancedFilterPersistenceKey()\"\n [fieldMetadata]=\"getAdvancedFilterFieldMetadata()\"\n [editModeEnabled]=\"editModeEnabled\"\n [alwaysVisibleFields]=\"config.behavior?.filtering?.advancedFilters?.settings?.alwaysVisibleFields\"\n [alwaysVisibleFieldMetadataOverrides]=\"config.behavior?.filtering?.advancedFilters?.settings?.alwaysVisibleFieldMetadataOverrides ?? {}\"\n [selectedFieldIds]=\"config.behavior?.filtering?.advancedFilters?.settings?.selectedFieldIds ?? []\"\n [allowSaveTags]=\"config.behavior?.filtering?.advancedFilters?.settings?.allowSaveTags\"\n [changeDebounceMs]=\"config.behavior?.filtering?.advancedFilters?.settings?.changeDebounceMs ?? 300\"\n [i18n]=\"getFilterI18n()\"\n [mode]=\"'filter'\"\n [showFilterSettings]=\"editModeEnabled\"\n (submit)=\"onAdvancedFilterSubmit($event)\"\n (clear)=\"onAdvancedFilterClear()\"\n ></praxis-filter>\n <ng-container *ngIf=\"shouldShowFooterToolbarMain() && shouldRenderAdvancedFilter()\">\n <ng-content select=\"[advancedFilter]\"></ng-content>\n </ng-container>\n <ng-container *ngIf=\"shouldShowFooterToolbarMain() && shouldRenderAdvancedFilter()\">\n <ng-content select=\"[toolbar]\"></ng-content>\n </ng-container>\n @if (shouldShowFooterToolbarMain() && shouldRenderAdvancedFilter()) {\n @defer (on idle) {\n @if (aiAdapter) {\n <praxis-ai-assistant\n [adapter]=\"aiAdapter\"\n end-actions\n ></praxis-ai-assistant>\n }\n }\n }\n <button\n *ngIf=\"shouldShowFooterToolbarMain() && shouldRenderAdvancedFilter() && editModeEnabled\"\n end-actions\n mat-icon-button\n color=\"primary\"\n data-role=\"table-settings\"\n data-testid=\"table-settings-trigger\"\n (click)=\"openTableSettings()\"\n aria-label=\"Configura\u00E7\u00F5es\"\n [matBadge]=\"schemaOutdated ? '!' : ''\"\n [matBadgeHidden]=\"!schemaOutdated\"\n matBadgeColor=\"warn\"\n matBadgeSize=\"small\"\n matBadgePosition=\"above after\"\n [matTooltip]=\"schemaOutdated ? 'Schema do servidor mudou \u2014 Reconciliar' : 'Configura\u00E7\u00F5es'\"\n matTooltipPosition=\"below\"\n >\n <mat-icon>settings</mat-icon>\n </button>\n </praxis-table-toolbar>\n}\n<!-- Paginadores (top/bottom) -->\n@if (shouldRenderDataSurface() && !schemaError && !dataError && getPaginationEnabled() && (config.behavior?.pagination?.position === 'top' || config.behavior?.pagination?.position === 'both')) {\n <mat-paginator\n [length]=\"getPaginationLength()\"\n [pageSize]=\"getPaginationPageSize()\"\n [pageSizeOptions]=\"getPaginationPageSizeOptions()\"\n [showFirstLastButtons]=\"getPaginationShowFirstLast()\"\n (page)=\"onPageChange($event)\"\n [class.compact]=\"config.behavior?.pagination?.style === 'compact'\"\n >\n </mat-paginator>\n}\n\n@if (shouldRenderDataSurface() && !schemaError && !dataError && getPaginationEnabled() && (config.behavior?.pagination?.position === 'bottom' || config.behavior?.pagination?.position === 'both' || !config.behavior?.pagination?.position)) {\n <mat-paginator\n [length]=\"getPaginationLength()\"\n [pageSize]=\"getPaginationPageSize()\"\n [pageSizeOptions]=\"getPaginationPageSizeOptions()\"\n [showFirstLastButtons]=\"getPaginationShowFirstLast()\"\n (page)=\"onPageChange($event)\"\n [class.compact]=\"config.behavior?.pagination?.style === 'compact'\"\n [class.footer-stack]=\"shouldShowToolbarActionsBottom()\"\n >\n </mat-paginator>\n}\n", styles: ["@charset \"UTF-8\";table{width:100%}.praxis-visually-hidden-status{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}.praxis-column-reorder-status{margin:8px 0;padding:10px 12px;border-radius:8px;border:1px solid var(--p-table-border-color);background:var(--p-table-row-hover-bg);color:var(--p-table-header-fg);font-size:12px;line-height:1.4;box-shadow:0 4px 12px #00000014;animation:pfx-column-reorder-status-in var(--p-table-drag-status-enter-duration, .18s) var(--p-table-motion-easing, cubic-bezier(0, 0, .2, 1))}@keyframes pfx-column-reorder-status-in{0%{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:translateY(0)}}.praxis-actions-cell{height:100%;padding-inline:12px;white-space:nowrap}.pfx-expansion-col-header,.pfx-expansion-col-cell{width:52px;min-width:52px;text-align:center}.pfx-expansion-toggle{width:40px;height:40px}.pfx-expansion-toggle:focus-visible{outline:2px solid var(--md-sys-color-primary);outline-offset:2px}.pfx-expansion-detail-row{background:var(--md-sys-color-surface-container-low)}.pfx-expansion-detail-cell{padding:0!important;border-bottom:1px solid var(--p-table-border-color)}.pfx-expansion-detail-panel{padding:12px 16px;border-left:3px solid var(--md-sys-color-primary)}.pfx-expansion-detail-schema{margin:0;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:12px;line-height:1.4;white-space:pre-wrap;word-break:break-word;color:var(--md-sys-color-on-surface-variant)}.pfx-expansion-detail-message{font-size:13px;color:var(--md-sys-color-on-surface-variant)}.pfx-expansion-detail-message--error{color:var(--md-sys-color-error)}.pfx-expansion-detail-stack{display:grid;gap:10px}.pfx-expansion-detail-tabs{display:flex;flex-wrap:wrap;gap:8px;margin-bottom:10px}.pfx-expansion-detail-tab-btn{border:1px solid var(--p-table-border-color);background:var(--md-sys-color-surface);color:var(--md-sys-color-on-surface);border-radius:999px;padding:6px 12px;font-size:12px;line-height:1.2;cursor:pointer}.pfx-expansion-detail-tab-btn.is-active{border-color:var(--md-sys-color-primary);color:var(--md-sys-color-primary);font-weight:600}.pfx-expansion-detail-tab-btn:focus-visible{outline:2px solid var(--md-sys-color-primary);outline-offset:2px}.pfx-expansion-detail-tab-panel{display:grid;gap:10px}.pfx-expansion-node{border:1px solid var(--p-table-border-color);border-radius:8px;padding:10px 12px;background:var(--md-sys-color-surface)}.pfx-expansion-node-card__header{margin-bottom:8px}.pfx-expansion-node-card__title{margin:0;font-size:14px;line-height:1.3}.pfx-expansion-node-card__subtitle{margin:4px 0 0;font-size:12px;color:var(--md-sys-color-on-surface-variant)}.pfx-expansion-node-value{display:flex;align-items:baseline;gap:8px}.pfx-expansion-node-value__label{color:var(--md-sys-color-on-surface-variant);font-size:12px}.pfx-expansion-node-value__content{font-size:14px}.pfx-expansion-node-list__title{margin:0 0 6px;font-size:13px}.pfx-expansion-node-list ul{margin:0;padding-left:18px}.pfx-expansion-node-richtext :where(p,ul,ol,h1,h2,h3,h4,h5,h6){margin-top:0;margin-bottom:8px}.pfx-expansion-node-placeholder{font-size:12px;color:var(--md-sys-color-on-surface-variant)}:host.density-compact{--p-header-padding: 8px 12px;--p-cell-padding: 8px 12px;--p-actions-btn-size: 32px;--p-actions-icon-size: 18px}:host.density-comfortable{--p-header-padding: 12px 16px;--p-cell-padding: 12px 16px;--p-actions-btn-size: 40px;--p-actions-icon-size: 22px}:host.density-spacious{--p-header-padding: 16px 20px;--p-cell-padding: 16px 20px;--p-actions-btn-size: 44px;--p-actions-icon-size: 24px}:host.density-compact ::ng-deep .mat-mdc-cell{padding:var(--p-cell-padding, 8px 12px)}:host.density-comfortable ::ng-deep .mat-mdc-cell{padding:var(--p-cell-padding, 12px 16px)}:host.density-spacious ::ng-deep .mat-mdc-cell{padding:var(--p-cell-padding, 16px 20px)}:host.density-compact .praxis-actions-cell{padding-inline:8px}:host.density-spacious .praxis-actions-cell{padding-inline:16px}.praxis-actions-cell__content{display:flex;align-items:center;justify-content:flex-end;gap:8px;width:100%}.praxis-actions-cell.dense .praxis-actions-cell__content{gap:6px}.praxis-icon-btn{width:var(--p-actions-btn-size, 40px);height:var(--p-actions-btn-size, 40px);border:0;background:transparent;padding:0;display:inline-flex;align-items:center;justify-content:center;border-radius:9999px;cursor:pointer;--mat-icon-button-state-layer-size: var(--p-actions-btn-size, 40px)}.praxis-icon-btn:hover{background:var(--md-sys-color-surface-variant)}.praxis-icon-btn:focus-visible{outline:2px solid var(--md-sys-color-primary);outline-offset:2px}.praxis-icon-btn mat-icon,.praxis-icon-btn .mat-icon{font-size:var(--p-actions-icon-size, 22px);width:var(--p-actions-icon-size, 22px);height:var(--p-actions-icon-size, 22px);line-height:var(--p-actions-icon-size, 22px)}.praxis-more-btn{width:var(--p-actions-more-btn-size, var(--p-actions-btn-size, 40px));height:var(--p-actions-more-btn-size, var(--p-actions-btn-size, 40px));--mat-icon-button-state-layer-size: var(--p-actions-more-btn-size, var(--p-actions-btn-size, 40px));background-image:var(--p-actions-more-btn-gradient, none);background-size:100% 100%;background-repeat:no-repeat}.praxis-more-btn mat-icon,.praxis-more-btn .mat-icon{font-size:var(--p-actions-more-icon-size, var(--p-actions-icon-size, 22px));width:var(--p-actions-more-icon-size, var(--p-actions-icon-size, 22px));height:var(--p-actions-more-icon-size, var(--p-actions-icon-size, 22px));line-height:var(--p-actions-more-icon-size, var(--p-actions-icon-size, 22px));color:var(--p-actions-more-icon-color);background-image:var(--p-actions-more-icon-gradient, none);-webkit-background-clip:text;background-clip:text}.praxis-icon-btn.destructive mat-icon{color:var(--md-sys-color-error)}.mat-mdc-tooltip.praxis-tooltip{margin-top:-8px;margin-bottom:8px}.spacer{flex:1 1 auto}.praxis-table-header{display:flex;flex-wrap:wrap;align-items:flex-start;gap:8px;margin:16px 0 12px;width:100%;clear:both;position:relative}.praxis-table-header.stacked{margin:0}.praxis-table-header>praxis-table-toolbar{flex:1 0 100%}.praxis-floating-bulk-actions{position:fixed;z-index:1001;display:inline-flex;align-items:center;gap:8px;padding:8px;border-radius:999px;background:var(--md-sys-color-surface-container-highest);box-shadow:0 8px 20px #00000029}.praxis-floating-bulk-actions.pos-bottom-right{right:20px;bottom:20px}.praxis-floating-bulk-actions.pos-bottom-left{left:20px;bottom:20px}.praxis-floating-bulk-actions.pos-top-right{right:20px;top:20px}.praxis-floating-bulk-actions.pos-top-left{left:20px;top:20px}@media(max-width:768px){.praxis-floating-bulk-actions{gap:6px;padding:6px}.praxis-floating-bulk-actions.pos-bottom-right{right:12px;left:auto;bottom:12px}.praxis-floating-bulk-actions.pos-bottom-left{left:12px;right:auto;bottom:12px}.praxis-floating-bulk-actions.pos-top-right{right:12px;left:auto;top:12px}.praxis-floating-bulk-actions.pos-top-left{left:12px;right:auto;top:12px}}:host{display:block;width:100%;min-width:0;max-width:100%;--pfx-toolbar-pad-y: 6px;--pfx-toolbar-pad-x: 12px;--p-table-bg: var(--md-sys-color-surface-container-highest);--p-table-text-color: var(--md-sys-color-on-surface);--p-table-header-bg: var(--md-sys-color-surface-container-highest);--p-table-header-fg: var(--md-sys-color-on-surface);--p-table-border-color: var(--md-sys-color-outline-variant);--p-table-row-even-bg: var(--md-sys-color-surface-container);--p-table-row-hover-bg: var(--md-sys-color-surface-container-high);--p-table-row-selected-bg: var(--md-sys-color-primary-container);--p-table-badge-soft-primary-bg: var(--md-sys-color-primary-container);--p-table-badge-soft-primary-fg: var(--md-sys-color-on-primary-container);--p-table-badge-soft-accent-bg: var(--md-sys-color-secondary-container);--p-table-badge-soft-accent-fg: var(--md-sys-color-on-secondary-container);--p-table-badge-soft-warn-bg: var(--md-sys-color-error-container);--p-table-badge-soft-warn-fg: var(--md-sys-color-on-error-container);--p-table-state-success-bg: var(--md-sys-color-tertiary-container);--p-table-state-success-fg: var(--md-sys-color-on-tertiary-container);--p-table-state-warning-bg: var(--md-sys-color-secondary-container);--p-table-state-warning-fg: var(--md-sys-color-on-secondary-container);--p-table-state-danger-bg: var(--md-sys-color-error-container);--p-table-state-danger-fg: var(--md-sys-color-on-error-container);--p-table-state-highlight-bg: var(--md-sys-color-primary-container);--p-table-state-highlight-fg: var(--md-sys-color-on-primary-container);--p-table-drag-handle-size: 14px;--p-table-drag-handle-color: var(--md-sys-color-on-surface-variant);--p-table-drag-handle-hover-color: var(--md-sys-color-on-surface);--p-table-drag-handle-base-opacity: 0;--p-table-drag-handle-visible-opacity: .72;--p-table-drag-handle-active-opacity: 1;--p-table-drag-handle-transition-duration: .16s;--p-table-reorder-transition-duration: .16s;--p-table-drag-preview-scale: 1.01;--p-table-drag-status-enter-duration: .18s;--p-table-drag-preview-shadow: 0 14px 32px rgba(0, 0, 0, .28), 0 0 0 1px var(--p-table-border-color)}:host ::ng-deep .mat-mdc-table{background:var(--p-table-bg);color:var(--p-table-text-color);border-radius:12px 12px 0 0;width:100%;box-shadow:var(--p-table-surface-shadow);transition:box-shadow var(--p-table-selection-transition-duration, .18s) var(--p-table-motion-easing, cubic-bezier(0, 0, .2, 1))}:host ::ng-deep .mat-mdc-table:hover{box-shadow:var(--p-table-surface-shadow-hover, var(--p-table-surface-shadow))}:host ::ng-deep .mat-mdc-table.table-stack-top{border-top-left-radius:0;border-top-right-radius:0}:host ::ng-deep .praxis-toolbar-footer{border:0 solid var(--p-table-border-color);border-top:0;border-radius:0;background:var(--p-table-bg)}:host ::ng-deep .mat-mdc-paginator.footer-stack{border-top-left-radius:0;border-top-right-radius:0;border-top:0}:host ::ng-deep .mat-mdc-paginator.footer-stack .mat-mdc-paginator-container{padding:8px 12px}:host [data-role=table-settings].mat-mdc-icon-button{--mdc-icon-button-icon-color: var(--md-sys-color-primary);color:var(--md-sys-color-primary)}.pfx-link{color:var(--md-sys-color-primary);text-decoration:underline;cursor:pointer}.pfx-chip{display:inline-flex;align-items:center;gap:4px;padding:2px 8px;border-radius:10px;font-size:12px;line-height:1;border:1px solid transparent}.pfx-chip-icon{font-size:14px;width:14px;height:14px}.pfx-chip--outlined{background:transparent;border-color:var(--md-sys-color-outline-variant);color:var(--md-sys-color-on-surface)}.pfx-chip--filled-primary{background:var(--md-sys-color-primary);color:var(--md-sys-color-on-primary)}.pfx-chip--filled-accent{background:var(--md-sys-color-secondary);color:var(--md-sys-color-on-secondary)}.pfx-chip--filled-warn{background:var(--md-sys-color-error);color:var(--md-sys-color-on-error)}.pfx-chip--soft-primary{background:var(--p-table-badge-soft-primary-bg);color:var(--p-table-badge-soft-primary-fg)}.pfx-chip--soft-accent{background:var(--p-table-badge-soft-accent-bg);color:var(--p-table-badge-soft-accent-fg)}.pfx-chip--soft-warn{background:var(--p-table-badge-soft-warn-bg);color:var(--p-table-badge-soft-warn-fg)}.pfx-progress{position:relative;width:100%;max-width:140px;height:8px;background:var(--md-sys-color-surface-container-highest);border-radius:4px;overflow:hidden;display:inline-block;vertical-align:middle}.pfx-progress-bar{height:100%;background:var(--md-sys-color-primary);transition:width .2s ease}.pfx-progress-label{margin-left:8px;font-size:12px;opacity:.8;display:inline-block;vertical-align:middle}.pfx-avatar{display:inline-flex;align-items:center;justify-content:center;background:var(--md-sys-color-surface-container);color:var(--md-sys-color-on-surface);border-radius:4px;overflow:hidden;font-weight:600}.pfx-avatar.shape-rounded{border-radius:8px}.pfx-avatar.shape-circle{border-radius:999px}.pfx-avatar--initials{text-transform:uppercase;font-size:12px}.pfx-cell-compose{display:inline-flex;align-items:center;gap:6px}.pfx-cell-compose.dir-col{flex-direction:column;align-items:stretch}.pfx-cell-compose.align-start{justify-content:flex-start}.pfx-cell-compose.align-center{justify-content:center}.pfx-cell-compose.align-end{justify-content:flex-end}.pfx-cell-compose.wrap{flex-wrap:wrap}.pfx-cell-compose.ellipsis{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.px-scroll-viewport{width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch;overscroll-behavior-x:contain}.px-scroll-viewport.scroll-none{overflow-x:visible}.px-scroll-viewport.scroll-auto ::ng-deep .mat-mdc-table{width:max-content;min-width:100%}.px-scroll-viewport.scroll-wrap ::ng-deep .mat-mdc-header-cell,.px-scroll-viewport.scroll-wrap ::ng-deep .mat-mdc-cell{white-space:normal;text-overflow:initial}.px-scroll-viewport.scroll-wrap ::ng-deep .mat-mdc-table{width:100%}:host ::ng-deep .mat-mdc-header-row{position:sticky;top:0;z-index:1;background:var(--p-table-header-bg);color:var(--p-table-header-fg);box-shadow:var(--p-table-header-shadow, 0 1px 0 var(--p-table-border-color));border-bottom:1px solid var(--p-table-border-color)}:host ::ng-deep .mat-mdc-header-cell,:host ::ng-deep .mat-sort-header-content,:host ::ng-deep .mat-mdc-header-row .mat-icon{color:var(--p-table-header-fg)!important;font-weight:600}:host ::ng-deep .mat-mdc-header-cell.mat-sort-header-sorted .mat-sort-header-arrow,:host ::ng-deep .mat-mdc-header-cell:hover .mat-sort-header-arrow{color:var(--p-table-header-fg)!important}:host ::ng-deep .mat-mdc-header-cell.mat-sort-header-sorted .mat-sort-header-arrow .mat-sort-header-indicator,:host ::ng-deep .mat-mdc-header-cell.mat-sort-header-sorted .mat-sort-header-arrow .mat-sort-header-stem,:host ::ng-deep .mat-mdc-header-cell.mat-sort-header-sorted .mat-sort-header-arrow .mat-sort-header-pointer,:host ::ng-deep .mat-mdc-header-cell.mat-sort-header-sorted .mat-sort-header-arrow .mat-sort-header-pointer-left,:host ::ng-deep .mat-mdc-header-cell.mat-sort-header-sorted .mat-sort-header-arrow .mat-sort-header-pointer-right{border-color:var(--p-table-header-fg)!important;background:var(--p-table-header-fg)!important}:host ::ng-deep .mat-mdc-header-cell{padding:var(--p-header-padding, 12px 16px)!important;font-size:var(--p-header-font-size, inherit);font-weight:var(--p-header-font-weight, 600);letter-spacing:var(--p-header-letter-spacing, normal);text-transform:var(--p-header-text-transform, none);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}:host ::ng-deep .pfx-column-drag-enabled .mat-mdc-header-cell.praxis-header-draggable .mat-sort-header-container{display:flex;align-items:center;width:100%;gap:8px;cursor:inherit}:host ::ng-deep .pfx-column-drag-enabled .mat-mdc-header-cell.praxis-header-draggable{-webkit-user-select:none;user-select:none;cursor:grab}:host ::ng-deep .pfx-column-drag-enabled .mat-mdc-header-cell.praxis-header-draggable.cdk-drag-dragging{cursor:grabbing}:host ::ng-deep .pfx-column-drag-enabled .mat-mdc-header-cell.praxis-header-draggable .mat-sort-header-content{display:inline-flex;align-items:center;gap:8px;flex:1 1 auto;min-width:0}:host ::ng-deep .pfx-column-drag-enabled .mat-mdc-header-cell .praxis-header-label{display:inline-flex;align-items:center;flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis}:host ::ng-deep .pfx-column-drag-enabled .mat-mdc-header-cell .praxis-column-drag-handle{-webkit-appearance:none;appearance:none;border:0;background:transparent;color:var(--p-table-drag-handle-color);width:var(--p-table-drag-handle-size);min-width:var(--p-table-drag-handle-size);height:var(--p-table-drag-handle-size);padding:0;display:inline-flex;align-items:center;justify-content:center;border-radius:0;cursor:inherit;pointer-events:none;touch-action:none;opacity:var(--p-table-drag-handle-base-opacity, 0);transform:none;transition:opacity var(--p-table-drag-handle-transition-duration, .16s) var(--p-table-motion-easing, cubic-bezier(0, 0, .2, 1)),color var(--p-table-drag-handle-transition-duration, .16s) var(--p-table-motion-easing, cubic-bezier(0, 0, .2, 1))}:host ::ng-deep .pfx-column-drag-enabled .mat-mdc-header-cell.praxis-header-draggable:hover .praxis-column-drag-handle,:host ::ng-deep .pfx-column-drag-enabled .mat-mdc-header-cell.praxis-header-draggable:focus-within .praxis-column-drag-handle{opacity:var(--p-table-drag-handle-visible-opacity, .72);color:var(--p-table-drag-handle-hover-color, var(--p-table-drag-handle-color))}:host ::ng-deep .pfx-column-drag-enabled .mat-mdc-header-cell .praxis-column-drag-handle:active{opacity:var(--p-table-drag-handle-active-opacity, 1);cursor:grabbing}:host ::ng-deep .pfx-column-drag-enabled .mat-mdc-header-cell .praxis-column-drag-handle .mat-icon{font-size:14px;width:14px;height:14px;line-height:14px;transition:transform .18s var(--p-table-motion-easing, cubic-bezier(0, 0, .2, 1))}:host ::ng-deep .pfx-column-drag-enabled .mat-mdc-header-cell.praxis-header-draggable:hover .praxis-column-drag-handle .mat-icon{transform:none}:host ::ng-deep .pfx-column-drag-indicator .cdk-drop-list-dragging .mat-mdc-header-cell:not(.cdk-drag-placeholder){transition:transform var(--p-table-reorder-transition-duration, .18s) var(--p-table-motion-easing, cubic-bezier(0, 0, .2, 1))}:host ::ng-deep .pfx-column-drag-indicator .mat-mdc-header-cell.cdk-drag-animating{transition:transform var(--p-table-reorder-transition-duration, .16s) var(--p-table-motion-easing, cubic-bezier(0, 0, .2, 1))}.pfx-column-drag-preview{box-sizing:border-box;border-radius:10px;border:1px solid var(--p-table-border-color);background:linear-gradient(135deg,var(--p-table-header-bg) 0%,var(--p-table-row-hover-bg) 100%);color:var(--p-table-header-fg);box-shadow:var(--p-table-drag-preview-shadow);transform:scale(var(--p-table-drag-preview-scale, 1.01));pointer-events:none;z-index:1000}.pfx-column-drag-preview .praxis-column-drag-handle,.pfx-column-drag-preview .mat-sort-header-arrow,.pfx-column-drag-preview .mat-sort-header-indicator,.pfx-column-drag-preview .mat-sort-header-stem,.pfx-column-drag-preview .mat-sort-header-pointer,.pfx-column-drag-preview .mat-sort-header-pointer-left,.pfx-column-drag-preview .mat-sort-header-pointer-right{display:none!important}.pfx-column-drag-preview .mat-sort-header-container{padding-right:0!important}.pfx-column-drag-preview .mat-sort-header-content,.pfx-column-drag-preview .praxis-header-label{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}:host ::ng-deep .pfx-column-drag-indicator .cdk-drag-placeholder{opacity:1;border:1px dashed var(--p-table-border-color);background:var(--p-table-row-hover-bg)}:host ::ng-deep .pfx-column-drag-indicator .cdk-drag-placeholder *{opacity:0}:host ::ng-deep .pfx-column-drag-indicator .mat-mdc-header-cell.cdk-drag-dragging{opacity:.58}@media(prefers-reduced-motion:reduce){:host ::ng-deep .pfx-column-drag-indicator .cdk-drop-list-dragging .mat-mdc-header-cell:not(.cdk-drag-placeholder){transition:none}:host ::ng-deep .pfx-column-drag-enabled .mat-mdc-header-cell .praxis-column-drag-handle,:host ::ng-deep .pfx-column-drag-enabled .mat-mdc-header-cell .praxis-column-drag-handle .mat-icon,.pfx-column-drag-preview{transition:none;transform:none}.praxis-column-reorder-status{animation:none}:host ::ng-deep .mat-mdc-row{transition:none}:host ::ng-deep .mat-mdc-table{transition:none}}.praxis-actions-header{text-align:right}.praxis-actions-header.align-start{text-align:left}.praxis-actions-header.align-center{text-align:center}.praxis-actions-header.align-end{text-align:right}.praxis-actions-header .praxis-actions-header__content{display:inline-flex;align-items:center;gap:var(--p-actions-header-gap, 6px);color:var(--p-actions-header-color, inherit)}.praxis-actions-header .praxis-actions-header__content .mat-icon{font-size:18px;width:18px;height:18px;line-height:18px}:host ::ng-deep .mat-mdc-header-cell .mat-sort-header-container{padding-right:20px}:host ::ng-deep .pfx-column-drag-enabled .mat-mdc-header-cell.praxis-header-draggable .mat-sort-header-container{padding-right:12px}@media(pointer:coarse){:host{--p-table-drag-handle-size: 18px;--p-table-drag-handle-base-opacity: .56;--p-table-drag-handle-visible-opacity: .92}}:host ::ng-deep .mat-mdc-cell{color:var(--p-table-text-color);font-size:var(--p-cell-font-size, inherit);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}:host ::ng-deep .mat-mdc-cell .pfx-cell-content,:host ::ng-deep .mat-cell .pfx-cell-content{display:inline-flex;align-items:center;gap:6px;width:100%;min-width:0;overflow:hidden}:host ::ng-deep .pfx-cell-content.pfx-cell-anim{animation-duration:var(--pfx-cell-anim-duration, .8s);animation-delay:var(--pfx-cell-anim-delay, 0ms);animation-fill-mode:both;animation-timing-function:ease-in-out}:host ::ng-deep .pfx-cell-content.pfx-cell-anim.pfx-cell-anim--once{animation-iteration-count:1}:host ::ng-deep .pfx-cell-content.pfx-cell-anim.pfx-cell-anim--loop{animation-iteration-count:infinite}:host ::ng-deep .pfx-cell-content.pfx-cell-anim.pfx-cell-anim--count{animation-iteration-count:var(--pfx-cell-anim-iteration-count, 1)}:host ::ng-deep .pfx-cell-content.pfx-cell-anim.pfx-cell-anim--on-hover{animation-play-state:paused}:host ::ng-deep .mat-mdc-cell:hover .pfx-cell-content.pfx-cell-anim.pfx-cell-anim--on-hover,:host ::ng-deep .mat-cell:hover .pfx-cell-content.pfx-cell-anim.pfx-cell-anim--on-hover{animation-play-state:running}:host ::ng-deep .pfx-cell-content.pfx-cell-anim.pfx-cell-anim--pulse{animation-name:pfx-cell-pulse}:host ::ng-deep .pfx-cell-content.pfx-cell-anim.pfx-cell-anim--blink{animation-name:pfx-cell-blink}:host ::ng-deep .pfx-cell-content.pfx-cell-anim.pfx-cell-anim--grow{animation-name:pfx-cell-grow}:host ::ng-deep .pfx-cell-content.pfx-cell-anim.pfx-cell-anim--fade{animation-name:pfx-cell-fade}:host ::ng-deep .pfx-cell-content.pfx-cell-anim.pfx-cell-anim--slide-in{animation-name:pfx-cell-slide-in}:host ::ng-deep .pfx-cell-content.pfx-cell-anim.pfx-cell-anim--border-pulse{animation-name:pfx-cell-border-pulse}@keyframes pfx-cell-pulse{0%{transform:scale(1)}50%{transform:scale(var(--pfx-cell-anim-scale-peak, 1.015))}to{transform:scale(1)}}@keyframes pfx-cell-blink{0%,49%{opacity:1}50%,to{opacity:var(--pfx-cell-anim-min-opacity, .35)}}@keyframes pfx-cell-grow{0%{transform:scale(.985)}to{transform:scale(1)}}@keyframes pfx-cell-fade{0%{opacity:0}to{opacity:1}}@keyframes pfx-cell-slide-in{0%{opacity:0;transform:translateY(var(--pfx-cell-anim-slide-distance, 4px))}to{opacity:1;transform:translateY(0)}}@keyframes pfx-cell-border-pulse{0%,to{box-shadow:inset 0 0 rgba(var(--pfx-cell-anim-border-rgb, 25, 118, 210),0)}50%{box-shadow:inset 0 0 0 2px rgba(var(--pfx-cell-anim-border-rgb, 25, 118, 210),var(--pfx-cell-anim-border-strength, .3))}}@media(prefers-reduced-motion:reduce){:host ::ng-deep .pfx-cell-content.pfx-cell-anim{animation:none!important}}:host ::ng-deep .mat-mdc-row:hover{background:var(--p-table-row-hover-bg)}:host ::ng-deep .mat-mdc-row{transition:background-color var(--p-table-hover-transition-duration, .18s) var(--p-table-motion-easing, cubic-bezier(0, 0, .2, 1)),box-shadow var(--p-table-selection-transition-duration, .18s) var(--p-table-motion-easing, cubic-bezier(0, 0, .2, 1))}:host ::ng-deep .mat-mdc-row.pfx-row-anim{animation-duration:var(--pfx-row-anim-duration, .8s);animation-delay:var(--pfx-row-anim-delay, 0ms);animation-fill-mode:both;animation-timing-function:ease-in-out}:host ::ng-deep .mat-mdc-row.pfx-row-anim.pfx-row-anim--once{animation-iteration-count:1}:host ::ng-deep .mat-mdc-row.pfx-row-anim.pfx-row-anim--loop{animation-iteration-count:infinite}:host ::ng-deep .mat-mdc-row.pfx-row-anim.pfx-row-anim--count{animation-iteration-count:var(--pfx-row-anim-iteration-count, 1)}:host ::ng-deep .mat-mdc-row.pfx-row-anim.pfx-row-anim--on-hover{animation-play-state:paused}:host ::ng-deep .mat-mdc-row.pfx-row-anim.pfx-row-anim--on-hover:hover{animation-play-state:running}:host ::ng-deep .mat-mdc-row.pfx-row-anim.pfx-row-anim--pulse{animation-name:pfx-row-pulse}:host ::ng-deep .mat-mdc-row.pfx-row-anim.pfx-row-anim--blink{animation-name:pfx-row-blink}:host ::ng-deep .mat-mdc-row.pfx-row-anim.pfx-row-anim--grow{animation-name:pfx-row-grow}:host ::ng-deep .mat-mdc-row.pfx-row-anim.pfx-row-anim--fade{animation-name:pfx-row-fade}:host ::ng-deep .mat-mdc-row.pfx-row-anim.pfx-row-anim--slide-in{animation-name:pfx-row-slide-in}:host ::ng-deep .mat-mdc-row.pfx-row-anim.pfx-row-anim--border-pulse{animation-name:pfx-row-border-pulse}@keyframes pfx-row-pulse{0%{transform:scale(1)}50%{transform:scale(var(--pfx-row-anim-scale-peak, 1.015))}to{transform:scale(1)}}@keyframes pfx-row-blink{0%,49%{opacity:1}50%,to{opacity:var(--pfx-row-anim-min-opacity, .35)}}@keyframes pfx-row-grow{0%{transform:scale(.985)}to{transform:scale(1)}}@keyframes pfx-row-fade{0%{opacity:0}to{opacity:1}}@keyframes pfx-row-slide-in{0%{opacity:0;transform:translateY(var(--pfx-row-anim-slide-distance, 4px))}to{opacity:1;transform:translateY(0)}}@keyframes pfx-row-border-pulse{0%,to{box-shadow:inset 0 0 rgba(var(--pfx-row-anim-border-rgb, 25, 118, 210),0)}50%{box-shadow:inset 0 0 0 2px rgba(var(--pfx-row-anim-border-rgb, 25, 118, 210),var(--pfx-row-anim-border-strength, .3))}}@media(prefers-reduced-motion:reduce){:host ::ng-deep .mat-mdc-row.pfx-row-anim{animation:none!important}}:host ::ng-deep .mat-mdc-row:nth-child(2n){background:var(--p-table-row-even-bg)}:host ::ng-deep .mat-mdc-row:nth-child(2n):hover{background:var(--p-table-row-hover-bg)}:host ::ng-deep .mat-mdc-row.pfx-row-selected,:host ::ng-deep .mat-mdc-row.pfx-row-selected:hover{background:var(--p-table-row-selected-bg)}:host.row-borders ::ng-deep .mat-mdc-row .mat-mdc-cell{border-bottom:1px solid var(--p-table-border-color)}:host.row-borders ::ng-deep .mat-mdc-header-row .mat-mdc-header-cell{border-bottom:none}:host.col-borders ::ng-deep .mat-mdc-header-row .mat-mdc-header-cell,:host.col-borders ::ng-deep .mat-mdc-row .mat-mdc-cell{border-right:1px solid var(--p-table-border-color)}:host.col-borders ::ng-deep .mat-mdc-header-row .mat-mdc-header-cell:last-child,:host.col-borders ::ng-deep .mat-mdc-row .mat-mdc-cell:last-child{border-right:none}.ptable-error{display:flex;align-items:center;gap:12px;padding:12px;margin:8px 0;border:1px solid var(--md-sys-color-error);border-radius:8px}.ptable-error__content{flex:1}.ptable-error__title{font-weight:600}.ptable-info-banner{display:flex;gap:12px;align-items:center;padding:8px 12px;margin:8px 0;border-radius:8px;border:1px solid var(--md-sys-color-primary);background:var(--md-sys-color-primary-container);color:var(--md-sys-color-on-primary-container)}.ptable-info-banner .text{flex:1;font-weight:600}.ptable-info-banner .actions{display:flex;gap:8px}.pfx-cell-image{display:inline-block;vertical-align:middle;background:var(--md-sys-color-surface-variant);border:1px solid var(--md-sys-color-outline-variant)}.pfx-cell-image.shape-rounded{border-radius:8px}.pfx-cell-image.shape-circle{border-radius:9999px}.pfx-badge{display:inline-flex;align-items:center;gap:6px;line-height:1;padding:4px 8px;border-radius:9999px;font-size:12px;font-weight:600;border:1px solid transparent}.pfx-badge .pfx-badge-icon{font-size:16px;width:16px;height:16px}.pfx-badge--filled-primary{background:var(--md-sys-color-primary);color:var(--md-sys-color-on-primary)}.pfx-badge--filled-accent{background:var(--md-sys-color-secondary);color:var(--md-sys-color-on-secondary)}.pfx-badge--filled-warn{background:var(--md-sys-color-error);color:var(--md-sys-color-on-error)}.pfx-badge--outlined{background:transparent;border-color:var(--md-sys-color-outline-variant);color:inherit}.pfx-badge--soft-primary{background:var(--p-table-badge-soft-primary-bg);color:var(--p-table-badge-soft-primary-fg)}.pfx-badge--soft-accent{background:var(--p-table-badge-soft-accent-bg);color:var(--p-table-badge-soft-accent-fg)}.pfx-badge--soft-warn{background:var(--p-table-badge-soft-warn-bg);color:var(--p-table-badge-soft-warn-fg)}.row--success,.row--success td,td.row--success{background-color:var(--p-table-state-success-bg)!important;color:var(--p-table-state-success-fg)!important}.row--warning,.row--warning td,td.row--warning{background-color:var(--p-table-state-warning-bg)!important;color:var(--p-table-state-warning-fg)!important}.row--danger,.row--danger td,td.row--danger{background-color:var(--p-table-state-danger-bg)!important;color:var(--p-table-state-danger-fg)!important}.row--highlight,.row--highlight td,td.row--highlight{background-color:var(--p-table-state-highlight-bg)!important;color:var(--p-table-state-highlight-fg)!important;font-weight:600}.row--muted,.row--muted td,td.row--muted{opacity:.7;filter:saturate(.6)}\n"] }]
40965
41445
  }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: i3$1.SettingsPanelService }, { type: i1.GenericCrudService }, { type: TableDefaultsProvider }, { type: FilterConfigService }, { type: DataFormattingService }, { type: i6$3.PraxisDialog }, { type: i2$1.MatSnackBar }, { type: undefined, decorators: [{
40966
41446
  type: Inject,
40967
41447
  args: [ASYNC_CONFIG_STORAGE]
@@ -41758,7 +42238,6 @@ const TABLE_AI_CAPABILITIES = {
41758
42238
  { path: 'columns[].renderer.rating.valueExpr', category: 'renderer', valueKind: 'expression', description: 'Valor numérico.', dependsOn: 'columns[].renderer.rating' },
41759
42239
  { path: 'columns[].renderer.rating.max', category: 'renderer', valueKind: 'number', description: 'Máximo de estrelas (default 5).', dependsOn: 'columns[].renderer.rating' },
41760
42240
  { path: 'columns[].renderer.rating.color', category: 'renderer', valueKind: 'string', description: 'Cor das estrelas ativas.', dependsOn: 'columns[].renderer.rating' },
41761
- { path: 'columns[].renderer.rating.readonly', category: 'renderer', valueKind: 'boolean', description: 'Se true, apenas visualização.', dependsOn: 'columns[].renderer.rating' },
41762
42241
  { path: 'columns[].renderer.rating.outlineColor', category: 'renderer', valueKind: 'string', description: 'Cor das bordas das estrelas.', dependsOn: 'columns[].renderer.rating' },
41763
42242
  { path: 'columns[].renderer.rating.size', category: 'renderer', valueKind: 'enum', allowedValues: ENUMS.rendererRatingSize, description: 'Tamanho das estrelas.', dependsOn: 'columns[].renderer.rating' },
41764
42243
  { path: 'columns[].renderer.rating.ariaLabel', category: 'renderer', valueKind: 'string', description: 'Label acessível para a avaliação.', dependsOn: 'columns[].renderer.rating' },
@@ -41785,7 +42264,7 @@ const TABLE_AI_CAPABILITIES = {
41785
42264
  'item menu com itemsExpr',
41786
42265
  'item html com template e sanitize basic',
41787
42266
  'item image com srcField, fit cover e shape circle',
41788
- 'item rating com valueExpr, max e readonly'
42267
+ 'item rating com valueExpr, max, size e ariaLabel'
41789
42268
  ],
41790
42269
  },
41791
42270
  { path: 'columns[].renderer.compose.layout.gap', category: 'renderer', valueKind: 'number', description: 'Espacamento entre itens (px).', dependsOn: 'columns[].renderer.compose' },
@@ -41890,7 +42369,6 @@ const TABLE_AI_CAPABILITIES = {
41890
42369
  { path: 'columns[].conditionalRenderers[].renderer.rating.color', category: 'conditional', valueKind: 'string', description: 'Cor das estrelas.', dependsOn: 'columns[].conditionalRenderers[].renderer.rating' },
41891
42370
  { path: 'columns[].conditionalRenderers[].renderer.rating.outlineColor', category: 'conditional', valueKind: 'string', description: 'Cor da borda.', dependsOn: 'columns[].conditionalRenderers[].renderer.rating' },
41892
42371
  { path: 'columns[].conditionalRenderers[].renderer.rating.size', category: 'conditional', valueKind: 'enum', allowedValues: ENUMS.rendererRatingSize, description: 'Tamanho.', dependsOn: 'columns[].conditionalRenderers[].renderer.rating' },
41893
- { path: 'columns[].conditionalRenderers[].renderer.rating.readonly', category: 'conditional', valueKind: 'boolean', description: 'Readonly condicional.', dependsOn: 'columns[].conditionalRenderers[].renderer.rating' },
41894
42372
  { path: 'columns[].conditionalRenderers[].renderer.rating.ariaLabel', category: 'conditional', valueKind: 'string', description: 'Label acessível.', dependsOn: 'columns[].conditionalRenderers[].renderer.rating' },
41895
42373
  // Compose in Conditional
41896
42374
  { path: 'columns[].conditionalRenderers[].renderer.compose', category: 'conditional', valueKind: 'object', description: 'Compose condicional.', dependsOn: 'columns[].conditionalRenderers[].renderer.type' },