@praxisui/table 1.0.0-beta.40 → 1.0.0-beta.42

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.
@@ -32,7 +32,7 @@ import * as i13 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';
35
- import { LoggerService, createCorporateLoggerConfig, ConsoleLoggerSink, PraxisIconDirective, isTableConfigV2, GLOBAL_ACTION_SPEC_CATALOG, getGlobalActionUiSchema, INLINE_FILTER_CONTROL_TYPES, INLINE_FILTER_CONTROL_TYPE_VALUES, FieldControlType, INLINE_FILTER_ALIAS_TOKENS, normalizeControlTypeToken, ASYNC_CONFIG_STORAGE, resolveControlTypeAlias, mapFieldDefinitionsToMetadata, GenericCrudService, TableConfigService, createDefaultTableConfig, fillUndefined, GlobalConfigService, MemoryCacheAdapter, LocalStorageCacheAdapter, SchemaMetadataClient, buildSchemaId, fetchWithETag, ResourceQuickConnectComponent, PRAXIS_LOADING_CTX, CONNECTION_STORAGE, PRAXIS_LOADING_RENDERER, EmptyStateCardComponent, ComponentMetadataRegistry } from '@praxisui/core';
35
+ import { LoggerService, createCorporateLoggerConfig, ConsoleLoggerSink, PraxisIconDirective, isTableConfigV2, GLOBAL_ACTION_SPEC_CATALOG, getGlobalActionUiSchema, INLINE_FILTER_CONTROL_TYPES, INLINE_FILTER_CONTROL_TYPE_VALUES, FieldControlType, INLINE_FILTER_ALIAS_TOKENS, normalizeControlTypeToken, ASYNC_CONFIG_STORAGE, resolveControlTypeAlias, mapFieldDefinitionsToMetadata, GenericCrudService, TableConfigService, createDefaultTableConfig, fillUndefined, GlobalConfigService, buildSchemaId, MemoryCacheAdapter, LocalStorageCacheAdapter, SchemaMetadataClient, fetchWithETag, ResourceQuickConnectComponent, PRAXIS_LOADING_CTX, CONNECTION_STORAGE, PRAXIS_LOADING_RENDERER, EmptyStateCardComponent, ComponentMetadataRegistry } from '@praxisui/core';
36
36
  import * as i2 from '@angular/material/toolbar';
37
37
  import { MatToolbarModule } from '@angular/material/toolbar';
38
38
  import { FunctionRegistry, DslParser, DslValidator, ValidationSeverity, ValidationIssueType } from '@praxisui/specification';
@@ -1143,7 +1143,7 @@ function getActionId(action) {
1143
1143
 
1144
1144
  const TOOLBAR_SHORTCUT_HANDLED_FLAG = '__praxisTableToolbarShortcutHandled__';
1145
1145
  const BLOCKED_PATH_SEGMENTS$1 = new Set(['__proto__', 'prototype', 'constructor']);
1146
- function normalizeCorporateLoggerEnvironment$1(candidate) {
1146
+ function normalizeCorporateLoggerEnvironment$2(candidate) {
1147
1147
  const value = String(candidate || '')
1148
1148
  .trim()
1149
1149
  .toLowerCase();
@@ -1165,7 +1165,7 @@ function normalizeCorporateLoggerEnvironment$1(candidate) {
1165
1165
  return 'prod';
1166
1166
  }
1167
1167
  function createPraxisTableToolbarFallbackLogger(environment) {
1168
- return new LoggerService(createCorporateLoggerConfig(normalizeCorporateLoggerEnvironment$1(environment)), [new ConsoleLoggerSink()]);
1168
+ return new LoggerService(createCorporateLoggerConfig(normalizeCorporateLoggerEnvironment$2(environment)), [new ConsoleLoggerSink()]);
1169
1169
  }
1170
1170
  class PraxisTableToolbar {
1171
1171
  hostRef;
@@ -1277,7 +1277,7 @@ class PraxisTableToolbar {
1277
1277
  getLogger() {
1278
1278
  if (this.logger)
1279
1279
  return this.logger;
1280
- const runtimeEnvironment = normalizeCorporateLoggerEnvironment$1(this.resolveRuntimeEnvironment());
1280
+ const runtimeEnvironment = normalizeCorporateLoggerEnvironment$2(this.resolveRuntimeEnvironment());
1281
1281
  if (!this.fallbackLogger
1282
1282
  || this.fallbackLoggerEnvironment !== runtimeEnvironment) {
1283
1283
  this.fallbackLogger = createPraxisTableToolbarFallbackLogger(runtimeEnvironment);
@@ -1833,8 +1833,8 @@ class PraxisTableToolbar {
1833
1833
  return 'download';
1834
1834
  }
1835
1835
  }
1836
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: PraxisTableToolbar, deps: [{ token: i0.ElementRef }, { token: i1.LoggerService, optional: true }], target: i0.ɵɵFactoryTarget.Component });
1837
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.4", type: PraxisTableToolbar, isStandalone: true, selector: "praxis-table-toolbar", inputs: { config: "config", backgroundColor: "backgroundColor", placement: "placement", showMain: "showMain", showActionsGroup: "showActionsGroup", showEndActions: "showEndActions", showMobileActions: "showMobileActions", showReset: "showReset", dslContext: "dslContext", dslFunctionRegistry: "dslFunctionRegistry" }, outputs: { toolbarAction: "toolbarAction", reset: "reset" }, host: { listeners: { "document:keydown": "onDocumentKeydown($event)" }, properties: { "class.praxis-toolbar-footer": "placement === 'footer'" } }, usesOnChanges: true, ngImport: i0, template: `
1836
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: PraxisTableToolbar, deps: [{ token: i0.ElementRef }, { token: i1.LoggerService, optional: true }], target: i0.ɵɵFactoryTarget.Component });
1837
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.17", type: PraxisTableToolbar, isStandalone: true, selector: "praxis-table-toolbar", inputs: { config: "config", backgroundColor: "backgroundColor", placement: "placement", showMain: "showMain", showActionsGroup: "showActionsGroup", showEndActions: "showEndActions", showMobileActions: "showMobileActions", showReset: "showReset", dslContext: "dslContext", dslFunctionRegistry: "dslFunctionRegistry" }, outputs: { toolbarAction: "toolbarAction", reset: "reset" }, host: { listeners: { "document:keydown": "onDocumentKeydown($event)" }, properties: { "class.praxis-toolbar-footer": "placement === 'footer'" } }, usesOnChanges: true, ngImport: i0, template: `
1838
1838
  <mat-toolbar class="praxis-toolbar" [style.background]="backgroundColor || null">
1839
1839
  @if (showMain) {
1840
1840
  <div class="toolbar-main">
@@ -2194,7 +2194,7 @@ class PraxisTableToolbar {
2194
2194
  </mat-toolbar>
2195
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"] }] });
2196
2196
  }
2197
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: PraxisTableToolbar, decorators: [{
2197
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: PraxisTableToolbar, decorators: [{
2198
2198
  type: Component,
2199
2199
  args: [{ selector: 'praxis-table-toolbar', standalone: true, imports: [
2200
2200
  CommonModule,
@@ -2779,8 +2779,8 @@ class JsonConfigEditorComponent {
2779
2779
  });
2780
2780
  this.cdr.markForCheck();
2781
2781
  }
2782
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: JsonConfigEditorComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
2783
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.4", type: JsonConfigEditorComponent, isStandalone: true, selector: "json-config-editor", inputs: { config: "config" }, outputs: { configChange: "configChange", validationChange: "validationChange", editorEvent: "editorEvent" }, ngImport: i0, template: `
2782
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: JsonConfigEditorComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
2783
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.17", type: JsonConfigEditorComponent, isStandalone: true, selector: "json-config-editor", inputs: { config: "config" }, outputs: { configChange: "configChange", validationChange: "validationChange", editorEvent: "editorEvent" }, ngImport: i0, template: `
2784
2784
  <div class="json-config-editor">
2785
2785
  <!-- Educational Card -->
2786
2786
  <mat-card class="educational-card">
@@ -2829,7 +2829,7 @@ class JsonConfigEditorComponent {
2829
2829
  </div>
2830
2830
  `, isInline: true, styles: [".json-config-editor{display:flex;flex-direction:column;height:100%}.educational-card{margin-bottom:24px;background-color:var(--md-sys-color-surface-container-low);border-left:4px solid var(--md-sys-color-primary)}.educational-card .mat-mdc-card-header{padding-bottom:8px}.card-icon{background-color:var(--md-sys-color-primary-container);color:var(--md-sys-color-on-primary-container);font-size:20px;width:40px;height:40px;display:flex;align-items:center;justify-content:center}.educational-card .mat-mdc-card-title{font-size:1.1rem;font-weight:500;color:var(--md-sys-color-on-surface)}.educational-card .mat-mdc-card-content{color:var(--md-sys-color-on-surface-variant);line-height:1.5}.json-editor-section{flex:1;display:flex;flex-direction:column}.json-editor-toolbar{display:flex;gap:12px;margin-bottom:16px;padding:12px;background-color:var(--md-sys-color-surface-container-low);border-radius:8px;border:1px solid var(--md-sys-color-outline-variant)}.json-textarea-field{width:100%;flex:1}.json-textarea{font-family:Monaco,Menlo,Ubuntu Mono,Consolas,monospace!important;font-size:13px!important;line-height:1.4!important;height:100%!important;min-height:300px!important;white-space:pre!important;overflow-wrap:normal!important;overflow-x:auto!important;resize:none!important}.valid-hint{color:var(--md-sys-color-primary)!important}@media(max-width:768px){.json-editor-toolbar{flex-direction:column;gap:8px}.json-textarea{font-size:12px!important;min-height:300px!important}}\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.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: 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: "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.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "directive", type: i6.MatError, selector: "mat-error, [matError]", inputs: ["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: 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.MatCardTitle, selector: "mat-card-title, [mat-card-title], [matCardTitle]" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2831
2831
  }
2832
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: JsonConfigEditorComponent, decorators: [{
2832
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: JsonConfigEditorComponent, decorators: [{
2833
2833
  type: Component,
2834
2834
  args: [{ selector: 'json-config-editor', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [
2835
2835
  CommonModule,
@@ -3449,10 +3449,10 @@ class FormulaGeneratorService {
3449
3449
  }
3450
3450
  return current;
3451
3451
  }
3452
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: FormulaGeneratorService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
3453
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: FormulaGeneratorService, providedIn: 'root' });
3452
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: FormulaGeneratorService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
3453
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: FormulaGeneratorService, providedIn: 'root' });
3454
3454
  }
3455
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: FormulaGeneratorService, decorators: [{
3455
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: FormulaGeneratorService, decorators: [{
3456
3456
  type: Injectable,
3457
3457
  args: [{
3458
3458
  providedIn: 'root'
@@ -3661,8 +3661,8 @@ class VisualFormulaBuilderComponent {
3661
3661
  }
3662
3662
  });
3663
3663
  }
3664
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: VisualFormulaBuilderComponent, deps: [{ token: FormulaGeneratorService }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
3665
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.4", type: VisualFormulaBuilderComponent, isStandalone: true, selector: "visual-formula-builder", inputs: { availableDataSchema: "availableDataSchema", currentFormula: "currentFormula" }, outputs: { formulaChange: "formulaChange", generatedExpressionChange: "generatedExpressionChange" }, usesOnChanges: true, ngImport: i0, template: `
3664
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: VisualFormulaBuilderComponent, deps: [{ token: FormulaGeneratorService }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
3665
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.17", type: VisualFormulaBuilderComponent, isStandalone: true, selector: "visual-formula-builder", inputs: { availableDataSchema: "availableDataSchema", currentFormula: "currentFormula" }, outputs: { formulaChange: "formulaChange", generatedExpressionChange: "generatedExpressionChange" }, usesOnChanges: true, ngImport: i0, template: `
3666
3666
  <div class="visual-formula-builder">
3667
3667
  <!-- Formula Type Selection -->
3668
3668
  <mat-card class="formula-type-card">
@@ -4123,7 +4123,7 @@ class VisualFormulaBuilderComponent {
4123
4123
  </div>
4124
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: i14.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
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: VisualFormulaBuilderComponent, decorators: [{
4126
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: VisualFormulaBuilderComponent, decorators: [{
4127
4127
  type: Component,
4128
4128
  args: [{ selector: 'visual-formula-builder', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [
4129
4129
  CommonModule,
@@ -5442,8 +5442,8 @@ class ValueMappingEditorComponent {
5442
5442
  this.importError = '';
5443
5443
  this.cdr.markForCheck();
5444
5444
  }
5445
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: ValueMappingEditorComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: i1$3.MatDialog }, { token: i2$1.MatSnackBar }], target: i0.ɵɵFactoryTarget.Component });
5446
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.4", type: ValueMappingEditorComponent, isStandalone: true, selector: "value-mapping-editor", inputs: { currentMapping: "currentMapping", keyInputType: "keyInputType", labelKey: "labelKey", labelValue: "labelValue" }, outputs: { mappingChange: "mappingChange" }, usesOnChanges: true, ngImport: i0, template: `
5445
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: ValueMappingEditorComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: i1$3.MatDialog }, { token: i2$1.MatSnackBar }], target: i0.ɵɵFactoryTarget.Component });
5446
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.17", type: ValueMappingEditorComponent, isStandalone: true, selector: "value-mapping-editor", inputs: { currentMapping: "currentMapping", keyInputType: "keyInputType", labelKey: "labelKey", labelValue: "labelValue" }, outputs: { mappingChange: "mappingChange" }, usesOnChanges: true, ngImport: i0, template: `
5447
5447
  <div class="value-mapping-editor">
5448
5448
  <!-- Header with Import/Export Actions -->
5449
5449
  <div class="mapping-toolbar">
@@ -5614,7 +5614,7 @@ class ValueMappingEditorComponent {
5614
5614
  </div>
5615
5615
  `, isInline: true, styles: [":host{--vme-primary: var(--md-sys-color-primary);--vme-surface: var(--md-sys-color-surface);--vme-surface-container: var(--md-sys-color-surface-container);--vme-on-surface: var(--md-sys-color-on-surface);--vme-on-surface-variant: var(--md-sys-color-on-surface-variant);--vme-outline-variant: var(--md-sys-color-outline-variant);--vme-error: var(--md-sys-color-error);--vme-error-container: var(--md-sys-color-error-container);--vme-on-error-container: var(--md-sys-color-on-error-container)}.value-mapping-editor{display:flex;flex-direction:column;gap:16px}.mapping-toolbar{display:flex;justify-content:space-between;align-items:center;padding:12px 0;border-bottom:1px solid var(--vme-outline-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}.toolbar-title{display:flex;align-items:center;gap:8px}.title-icon{color:var(--vme-primary)}.toolbar-title h4{margin:0;font-size:1rem;font-weight:500}.mapping-count{color:var(--vme-on-surface-variant);font-size:.875rem}.toolbar-actions{display:flex;gap:8px}.toolbar-actions .mat-mdc-outlined-button.mdc-button--disabled{color:var(--vme-on-surface-variant);border-color:var(--vme-outline-variant);background:var(--vme-surface-container)}.toolbar-actions .mat-mdc-outlined-button.mdc-button--disabled .mat-icon{color:var(--vme-on-surface-variant)}.mappings-container{min-height:200px;border:1px solid var(--vme-outline-variant);border-radius:8px;overflow:hidden;background:var(--vme-surface)}.mappings-table{width:100%}.mappings-table .mat-mdc-header-row{background:var(--vme-surface-container)}.mappings-table .mat-mdc-header-cell{color:var(--vme-on-surface);font-weight:600;border-bottom-color:var(--vme-outline-variant)}.key-cell,.value-cell{padding:8px 12px}.key-input,.value-input{width:100%}.key-input .mat-mdc-form-field-infix,.value-input .mat-mdc-form-field-infix{min-height:40px}.boolean-key-container{display:flex;align-items:center;min-height:40px}.error-input{border-color:var(--vme-error)!important}.actions-header{width:80px;text-align:center}.actions-cell{text-align:center;padding:8px}.empty-state{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:48px 24px;text-align:center;color:var(--vme-on-surface-variant)}.empty-icon{font-size:48px;width:48px;height:48px;margin-bottom:16px;opacity:.5}.empty-state h4{margin:0 0 8px;font-weight:500}.empty-state p{margin:0;font-size:.875rem}.add-mapping-section{display:flex;justify-content:center;padding:16px 0}.add-mapping-button{display:flex;align-items:center;gap:8px}.import-panel{margin-top:16px}.import-content{padding:16px 0}.json-input{width:100%;margin-bottom:16px}.json-textarea{font-family:Monaco,Menlo,Ubuntu Mono,Consolas,monospace!important;font-size:13px!important;line-height:1.4!important}.import-actions{display:flex;gap:8px;justify-content:flex-end}.import-error{display:flex;align-items:center;gap:8px;margin-top:16px;padding:12px;background-color:var(--vme-error-container);color:var(--vme-on-error-container);border-radius:4px;font-size:.875rem}@media(max-width:768px){.mapping-toolbar{flex-direction:column;gap:12px;align-items:stretch}.toolbar-actions{justify-content:center}.mappings-table,.key-input,.value-input{font-size:.875rem}}\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.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: 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.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: 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: 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: 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: MatDialogModule }, { kind: "ngmodule", type: MatSnackBarModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
5616
5616
  }
5617
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: ValueMappingEditorComponent, decorators: [{
5617
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: ValueMappingEditorComponent, decorators: [{
5618
5618
  type: Component,
5619
5619
  args: [{ selector: 'value-mapping-editor', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [
5620
5620
  CommonModule,
@@ -6353,10 +6353,10 @@ class DataFormattingService {
6353
6353
  const fmt = formatString.trim();
6354
6354
  return !!(fmt && columnType !== 'custom');
6355
6355
  }
6356
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: DataFormattingService, deps: [{ token: i1$2.DatePipe }, { token: i1$2.DecimalPipe }, { token: i1$2.CurrencyPipe }, { token: i1$2.PercentPipe }, { token: i1$2.UpperCasePipe }, { token: i1$2.LowerCasePipe }, { token: i1$2.TitleCasePipe }, { token: LOCALE_ID }], target: i0.ɵɵFactoryTarget.Injectable });
6357
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: DataFormattingService, providedIn: 'root' });
6356
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: DataFormattingService, deps: [{ token: i1$2.DatePipe }, { token: i1$2.DecimalPipe }, { token: i1$2.CurrencyPipe }, { token: i1$2.PercentPipe }, { token: i1$2.UpperCasePipe }, { token: i1$2.LowerCasePipe }, { token: i1$2.TitleCasePipe }, { token: LOCALE_ID }], target: i0.ɵɵFactoryTarget.Injectable });
6357
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: DataFormattingService, providedIn: 'root' });
6358
6358
  }
6359
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: DataFormattingService, decorators: [{
6359
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: DataFormattingService, decorators: [{
6360
6360
  type: Injectable,
6361
6361
  args: [{
6362
6362
  providedIn: 'root',
@@ -6790,8 +6790,8 @@ class DataFormatterComponent {
6790
6790
  const hasInvalidLetters = /[A-WYZa-wyz]/.test(fmt);
6791
6791
  return hasMaskTokens && !hasInvalidLetters;
6792
6792
  }
6793
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: DataFormatterComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: DataFormattingService }], target: i0.ɵɵFactoryTarget.Component });
6794
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.4", type: DataFormatterComponent, isStandalone: true, selector: "data-formatter", inputs: { columnType: "columnType", currentFormat: "currentFormat" }, outputs: { formatChange: "formatChange" }, usesOnChanges: true, ngImport: i0, template: `
6793
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: DataFormatterComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: DataFormattingService }], target: i0.ɵɵFactoryTarget.Component });
6794
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.17", type: DataFormatterComponent, isStandalone: true, selector: "data-formatter", inputs: { columnType: "columnType", currentFormat: "currentFormat" }, outputs: { formatChange: "formatChange" }, usesOnChanges: true, ngImport: i0, template: `
6795
6795
  <div class="data-formatter">
6796
6796
  <!-- Header -->
6797
6797
  <div class="formatter-header">
@@ -7115,7 +7115,7 @@ class DataFormatterComponent {
7115
7115
  </div>
7116
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: i14.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
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: DataFormatterComponent, decorators: [{
7118
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: DataFormatterComponent, decorators: [{
7119
7119
  type: Component,
7120
7120
  args: [{ selector: 'data-formatter', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [
7121
7121
  CommonModule,
@@ -9729,8 +9729,8 @@ class ColumnsConfigEditorComponent {
9729
9729
  // this.currentFieldSchemas = this.fieldSchemaAdapter.adaptTableConfigToFieldSchema({ columns: this.columns });
9730
9730
  // this.generateSampleData();
9731
9731
  }
9732
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: ColumnsConfigEditorComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
9733
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.4", type: ColumnsConfigEditorComponent, isStandalone: true, selector: "columns-config-editor", inputs: { config: "config" }, outputs: { configChange: "configChange", columnChange: "columnChange" }, ngImport: i0, template: `
9732
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: ColumnsConfigEditorComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
9733
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.17", type: ColumnsConfigEditorComponent, isStandalone: true, selector: "columns-config-editor", inputs: { config: "config" }, outputs: { configChange: "configChange", columnChange: "columnChange" }, ngImport: i0, template: `
9734
9734
  <div class="columns-config-editor">
9735
9735
  <!-- Educational Card - Compact -->
9736
9736
  <mat-card class="educational-card compact">
@@ -11056,7 +11056,7 @@ class ColumnsConfigEditorComponent {
11056
11056
  </div>
11057
11057
  `, 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: i14.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$1.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 });
11058
11058
  }
11059
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: ColumnsConfigEditorComponent, decorators: [{
11059
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: ColumnsConfigEditorComponent, decorators: [{
11060
11060
  type: Component,
11061
11061
  args: [{ selector: 'columns-config-editor', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [
11062
11062
  CommonModule,
@@ -12918,8 +12918,8 @@ class BehaviorConfigEditorComponent {
12918
12918
  .map((item) => item.trim())
12919
12919
  .filter((item) => !!item);
12920
12920
  }
12921
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: BehaviorConfigEditorComponent, deps: [{ token: i1$1.FormBuilder }], target: i0.ɵɵFactoryTarget.Component });
12922
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.4", type: BehaviorConfigEditorComponent, isStandalone: true, selector: "behavior-config-editor", inputs: { config: "config", resourcePath: "resourcePath", forceClientStrategies: "forceClientStrategies" }, outputs: { configChange: "configChange", behaviorChange: "behaviorChange" }, usesOnChanges: true, ngImport: i0, template: `
12921
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: BehaviorConfigEditorComponent, deps: [{ token: i1$1.FormBuilder }], target: i0.ɵɵFactoryTarget.Component });
12922
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.17", type: BehaviorConfigEditorComponent, isStandalone: true, selector: "behavior-config-editor", inputs: { config: "config", resourcePath: "resourcePath", forceClientStrategies: "forceClientStrategies" }, outputs: { configChange: "configChange", behaviorChange: "behaviorChange" }, usesOnChanges: true, ngImport: i0, template: `
12923
12923
  <div class="behavior-config-container">
12924
12924
  <form [formGroup]="behaviorForm">
12925
12925
  @if (forceClientStrategies) { <div class="mode-constraint-note">
@@ -13477,7 +13477,7 @@ class BehaviorConfigEditorComponent {
13477
13477
  </div>
13478
13478
  `, 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.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"] }] });
13479
13479
  }
13480
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: BehaviorConfigEditorComponent, decorators: [{
13480
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: BehaviorConfigEditorComponent, decorators: [{
13481
13481
  type: Component,
13482
13482
  args: [{ selector: 'behavior-config-editor', standalone: true, imports: [
13483
13483
  CommonModule,
@@ -15359,8 +15359,8 @@ class ToolbarActionsEditorComponent {
15359
15359
  this.toolbarForm.get('rowActionsHeaderIcon')?.setValue(res);
15360
15360
  }
15361
15361
  }
15362
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: ToolbarActionsEditorComponent, deps: [{ token: i1$1.FormBuilder }, { token: i1.IconPickerService }], target: i0.ɵɵFactoryTarget.Component });
15363
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.4", type: ToolbarActionsEditorComponent, isStandalone: true, selector: "toolbar-actions-editor", inputs: { config: "config" }, outputs: { configChange: "configChange", toolbarActionsChange: "toolbarActionsChange" }, usesOnChanges: true, ngImport: i0, template: `
15362
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: ToolbarActionsEditorComponent, deps: [{ token: i1$1.FormBuilder }, { token: i1.IconPickerService }], target: i0.ɵɵFactoryTarget.Component });
15363
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.17", type: ToolbarActionsEditorComponent, isStandalone: true, selector: "toolbar-actions-editor", inputs: { config: "config" }, outputs: { configChange: "configChange", toolbarActionsChange: "toolbarActionsChange" }, usesOnChanges: true, ngImport: i0, template: `
15364
15364
  <div class="toolbar-actions-container">
15365
15365
  <ng-template #globalActionFields let-action let-kind="kind">
15366
15366
  @if (getGlobalActionSchema(action); as schema) {
@@ -16855,7 +16855,7 @@ class ToolbarActionsEditorComponent {
16855
16855
  </div>
16856
16856
  `, 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"] }] });
16857
16857
  }
16858
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: ToolbarActionsEditorComponent, decorators: [{
16858
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: ToolbarActionsEditorComponent, decorators: [{
16859
16859
  type: Component,
16860
16860
  args: [{ selector: 'toolbar-actions-editor', standalone: true, imports: [
16861
16861
  CommonModule,
@@ -18686,8 +18686,8 @@ class MessagesLocalizationEditorComponent {
18686
18686
  }
18687
18687
  this.configChange.emit(updatedConfig);
18688
18688
  }
18689
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: MessagesLocalizationEditorComponent, deps: [{ token: i1$1.FormBuilder }], target: i0.ɵɵFactoryTarget.Component });
18690
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.4", type: MessagesLocalizationEditorComponent, isStandalone: true, selector: "messages-localization-editor", inputs: { config: "config" }, outputs: { configChange: "configChange", messagesLocalizationChange: "messagesLocalizationChange" }, ngImport: i0, template: `
18689
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: MessagesLocalizationEditorComponent, deps: [{ token: i1$1.FormBuilder }], target: i0.ɵɵFactoryTarget.Component });
18690
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.17", type: MessagesLocalizationEditorComponent, isStandalone: true, selector: "messages-localization-editor", inputs: { config: "config" }, outputs: { configChange: "configChange", messagesLocalizationChange: "messagesLocalizationChange" }, ngImport: i0, template: `
18691
18691
  <div class="messages-localization-container">
18692
18692
  <form [formGroup]="messagesForm">
18693
18693
 
@@ -19323,7 +19323,7 @@ class MessagesLocalizationEditorComponent {
19323
19323
  </div>
19324
19324
  `, 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 }] });
19325
19325
  }
19326
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: MessagesLocalizationEditorComponent, decorators: [{
19326
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: MessagesLocalizationEditorComponent, decorators: [{
19327
19327
  type: Component,
19328
19328
  args: [{ selector: 'messages-localization-editor', standalone: true, imports: [
19329
19329
  CommonModule,
@@ -20145,10 +20145,10 @@ class PraxisNumberWheelBlurDirective {
20145
20145
  this.cleanup?.();
20146
20146
  this.cleanup = null;
20147
20147
  }
20148
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: PraxisNumberWheelBlurDirective, deps: [{ token: i0.ElementRef }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Directive });
20149
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.1.4", type: PraxisNumberWheelBlurDirective, isStandalone: true, selector: "input[type=number][praxisNumberWheelBlur]", ngImport: i0 });
20148
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: PraxisNumberWheelBlurDirective, deps: [{ token: i0.ElementRef }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Directive });
20149
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.17", type: PraxisNumberWheelBlurDirective, isStandalone: true, selector: "input[type=number][praxisNumberWheelBlur]", ngImport: i0 });
20150
20150
  }
20151
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: PraxisNumberWheelBlurDirective, decorators: [{
20151
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: PraxisNumberWheelBlurDirective, decorators: [{
20152
20152
  type: Directive,
20153
20153
  args: [{
20154
20154
  selector: 'input[type=number][praxisNumberWheelBlur]',
@@ -20257,6 +20257,7 @@ class FilterSettingsComponent {
20257
20257
  try {
20258
20258
  this.storage.clearConfig('filter-config:' + key).pipe(take(1)).subscribe();
20259
20259
  this.storage.clearConfig(`filter-dto:${key}`).pipe(take(1)).subscribe();
20260
+ void this.clearPersistedSchemaStateByConfigKey(key);
20260
20261
  this.reset(); // Reset form to initial/default values
20261
20262
  this.form.markAsPristine();
20262
20263
  this.snackBar.open('Preferências do filtro redefinidas', undefined, {
@@ -20354,6 +20355,62 @@ class FilterSettingsComponent {
20354
20355
  tagsKey() {
20355
20356
  return this.configKey ? `filter-tags:${this.configKey}` : null;
20356
20357
  }
20358
+ schemaMetaScopeKey(configKey) {
20359
+ return `filter-schema-meta:${configKey}`;
20360
+ }
20361
+ schemaMetaIndexKey(configKey) {
20362
+ return `${this.schemaMetaScopeKey(configKey)}:index`;
20363
+ }
20364
+ schemaMetaKeyForSchemaId(configKey, schemaId) {
20365
+ return `${this.schemaMetaScopeKey(configKey)}:schema:${schemaId}`;
20366
+ }
20367
+ filterSchemaIgnoreKey(configKey, serverHash) {
20368
+ return `filter-schema-ignore:${configKey}:${serverHash}`;
20369
+ }
20370
+ filterSchemaSnoozeKey(configKey, serverHash) {
20371
+ return `filter-schema-snooze:${configKey}:${serverHash}`;
20372
+ }
20373
+ filterSchemaNotifiedKey(configKey, serverHash) {
20374
+ return `filter-schema-notified:${configKey}:${serverHash}`;
20375
+ }
20376
+ async clearPersistedSchemaStateByConfigKey(configKey) {
20377
+ const scopeKey = this.schemaMetaScopeKey(configKey);
20378
+ const indexKey = this.schemaMetaIndexKey(configKey);
20379
+ const schemaIds = await firstValueFrom(this.storage.loadConfig(indexKey).pipe(take(1)))
20380
+ .then((raw) => Array.from(new Set((Array.isArray(raw) ? raw : [])
20381
+ .map((item) => String(item || '').trim())
20382
+ .filter((item) => !!item))))
20383
+ .catch(() => []);
20384
+ const hashes = new Set();
20385
+ const legacyMeta = await firstValueFrom(this.storage.loadConfig(scopeKey).pipe(take(1))).catch(() => null);
20386
+ const legacyHash = String(legacyMeta?.serverHash || '').trim();
20387
+ if (legacyHash)
20388
+ hashes.add(legacyHash);
20389
+ for (const schemaId of schemaIds) {
20390
+ const key = this.schemaMetaKeyForSchemaId(configKey, schemaId);
20391
+ const meta = await firstValueFrom(this.storage.loadConfig(key).pipe(take(1))).catch(() => null);
20392
+ const hash = String(meta?.serverHash || '').trim();
20393
+ if (hash)
20394
+ hashes.add(hash);
20395
+ this.storage.clearConfig(key).pipe(take(1)).subscribe();
20396
+ }
20397
+ this.storage.clearConfig(indexKey).pipe(take(1)).subscribe();
20398
+ this.storage.clearConfig(scopeKey).pipe(take(1)).subscribe();
20399
+ hashes.forEach((hash) => {
20400
+ this.storage
20401
+ .clearConfig(this.filterSchemaIgnoreKey(configKey, hash))
20402
+ .pipe(take(1))
20403
+ .subscribe();
20404
+ this.storage
20405
+ .clearConfig(this.filterSchemaSnoozeKey(configKey, hash))
20406
+ .pipe(take(1))
20407
+ .subscribe();
20408
+ this.storage
20409
+ .clearConfig(this.filterSchemaNotifiedKey(configKey, hash))
20410
+ .pipe(take(1))
20411
+ .subscribe();
20412
+ });
20413
+ }
20357
20414
  async loadTags() {
20358
20415
  const key = this.tagsKey();
20359
20416
  if (!key) {
@@ -21830,10 +21887,10 @@ class FilterSettingsComponent {
21830
21887
  });
21831
21888
  // In a real implementation, this would trigger schema reload in PraxisFilter
21832
21889
  }
21833
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: FilterSettingsComponent, deps: [{ token: i1$1.FormBuilder }], target: i0.ɵɵFactoryTarget.Component });
21834
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.4", 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: i14.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 });
21890
+ 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 });
21891
+ 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: i14.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 });
21835
21892
  }
21836
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: FilterSettingsComponent, decorators: [{
21893
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: FilterSettingsComponent, decorators: [{
21837
21894
  type: Component,
21838
21895
  args: [{ selector: 'filter-settings', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [
21839
21896
  CommonModule,
@@ -21937,8 +21994,8 @@ class HeaderAppearanceEditorComponent {
21937
21994
  this.config = next;
21938
21995
  this.configChange.emit(next);
21939
21996
  }
21940
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: HeaderAppearanceEditorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
21941
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.4", type: HeaderAppearanceEditorComponent, isStandalone: true, selector: "header-appearance-editor", inputs: { config: "config" }, outputs: { configChange: "configChange" }, ngImport: i0, template: `
21997
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: HeaderAppearanceEditorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
21998
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.17", type: HeaderAppearanceEditorComponent, isStandalone: true, selector: "header-appearance-editor", inputs: { config: "config" }, outputs: { configChange: "configChange" }, ngImport: i0, template: `
21942
21999
  <div class="header-editor">
21943
22000
  <mat-card class="header-editor-card">
21944
22001
  <mat-card-header>
@@ -22044,7 +22101,7 @@ class HeaderAppearanceEditorComponent {
22044
22101
  </div>
22045
22102
  `, 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 });
22046
22103
  }
22047
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: HeaderAppearanceEditorComponent, decorators: [{
22104
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: HeaderAppearanceEditorComponent, decorators: [{
22048
22105
  type: Component,
22049
22106
  args: [{ selector: 'header-appearance-editor', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [CommonModule, FormsModule, MatFormFieldModule, MatInputModule, MatSelectModule, MatSlideToggleModule, MatCardModule, MatIconModule, MatTooltipModule], template: `
22050
22107
  <div class="header-editor">
@@ -22384,8 +22441,8 @@ class CrudIntegrationEditorComponent {
22384
22441
  grp.patchValue({ openMode: '', formId: undefined, route: undefined }, { emitEvent: false });
22385
22442
  this.updateActionControlsState(grp);
22386
22443
  }
22387
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: CrudIntegrationEditorComponent, deps: [{ token: i1$1.FormBuilder }, { token: ASYNC_CONFIG_STORAGE }], target: i0.ɵɵFactoryTarget.Component });
22388
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.4", type: CrudIntegrationEditorComponent, isStandalone: true, selector: "crud-integration-editor", inputs: { tableId: "tableId", crudContext: "crudContext", componentKeyId: "componentKeyId" }, ngImport: i0, template: `
22444
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: CrudIntegrationEditorComponent, deps: [{ token: i1$1.FormBuilder }, { token: ASYNC_CONFIG_STORAGE }], target: i0.ɵɵFactoryTarget.Component });
22445
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.17", type: CrudIntegrationEditorComponent, isStandalone: true, selector: "crud-integration-editor", inputs: { tableId: "tableId", crudContext: "crudContext", componentKeyId: "componentKeyId" }, ngImport: i0, template: `
22389
22446
  <div class="crud-editor">
22390
22447
  <mat-expansion-panel [expanded]="true">
22391
22448
  <mat-expansion-panel-header>
@@ -22575,7 +22632,7 @@ class CrudIntegrationEditorComponent {
22575
22632
  </div>
22576
22633
  `, 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"] }] });
22577
22634
  }
22578
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: CrudIntegrationEditorComponent, decorators: [{
22635
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: CrudIntegrationEditorComponent, decorators: [{
22579
22636
  type: Component,
22580
22637
  args: [{ selector: 'crud-integration-editor', standalone: true, imports: [
22581
22638
  CommonModule,
@@ -23134,10 +23191,10 @@ class ConfirmDialogAppearanceEditorComponent {
23134
23191
  next.dialogs.confirm.delete = curr;
23135
23192
  this.configChange.emit(next);
23136
23193
  }
23137
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: ConfirmDialogAppearanceEditorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
23138
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.4", 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"] }] });
23194
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: ConfirmDialogAppearanceEditorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
23195
+ 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"] }] });
23139
23196
  }
23140
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: ConfirmDialogAppearanceEditorComponent, decorators: [{
23197
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: ConfirmDialogAppearanceEditorComponent, decorators: [{
23141
23198
  type: Component,
23142
23199
  args: [{ selector: 'confirm-dialog-appearance-editor', standalone: true, imports: [CommonModule, FormsModule, MatFormFieldModule, MatInputModule, MatSelectModule, MatSlideToggleModule, MatButtonModule, MatExpansionModule, MatIconModule, PraxisIconDirective], 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"] }]
23143
23200
  }], propDecorators: { config: [{
@@ -23158,8 +23215,8 @@ class TableConfigToolbarComponent {
23158
23215
  import = new EventEmitter();
23159
23216
  reset = new EventEmitter();
23160
23217
  apply = new EventEmitter();
23161
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: TableConfigToolbarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
23162
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.4", type: TableConfigToolbarComponent, isStandalone: true, selector: "pfx-table-config-toolbar", inputs: { applyDisabled: "applyDisabled", ariaLabel: "ariaLabel", exportLabel: "exportLabel", importLabel: "importLabel", resetLabel: "resetLabel", resetLabelShort: "resetLabelShort", applyLabel: "applyLabel" }, outputs: { export: "export", import: "import", reset: "reset", apply: "apply" }, ngImport: i0, template: `
23218
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: TableConfigToolbarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
23219
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.17", type: TableConfigToolbarComponent, isStandalone: true, selector: "pfx-table-config-toolbar", inputs: { applyDisabled: "applyDisabled", ariaLabel: "ariaLabel", exportLabel: "exportLabel", importLabel: "importLabel", resetLabel: "resetLabel", resetLabelShort: "resetLabelShort", applyLabel: "applyLabel" }, outputs: { export: "export", import: "import", reset: "reset", apply: "apply" }, ngImport: i0, template: `
23163
23220
  <div class="pfx-tct">
23164
23221
  <div class="spacer"></div>
23165
23222
  <div class="actions" role="toolbar" [attr.aria-label]="ariaLabel || 'Ações'">
@@ -23183,7 +23240,7 @@ class TableConfigToolbarComponent {
23183
23240
  </div>
23184
23241
  `, isInline: true, styles: [".pfx-tct{display:flex;align-items:center;gap:8px;width:100%}.actions{display:flex;gap:8px;align-items:center}.spacer{flex:1}.apply{color:var(--md-sys-color-on-primary);background-image:linear-gradient(180deg,var(--md-sys-color-primary),var(--md-sys-color-primary-fixed-dim))}.apply:disabled{background-image:none}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { 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: "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"] }] });
23185
23242
  }
23186
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: TableConfigToolbarComponent, decorators: [{
23243
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: TableConfigToolbarComponent, decorators: [{
23187
23244
  type: Component,
23188
23245
  args: [{ selector: 'pfx-table-config-toolbar', standalone: true, imports: [CommonModule, MatButtonModule, MatIconModule, MatTooltipModule], template: `
23189
23246
  <div class="pfx-tct">
@@ -23424,10 +23481,10 @@ class OperatorsRegistryService {
23424
23481
  { key: 'has property', label: 'Possui propriedade', icon: 'key' },
23425
23482
  // join condition simples pode ser expresso com 'key ==' existente
23426
23483
  ];
23427
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: OperatorsRegistryService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
23428
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: OperatorsRegistryService, providedIn: 'root' });
23484
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: OperatorsRegistryService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
23485
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: OperatorsRegistryService, providedIn: 'root' });
23429
23486
  }
23430
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: OperatorsRegistryService, decorators: [{
23487
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: OperatorsRegistryService, decorators: [{
23431
23488
  type: Injectable,
23432
23489
  args: [{ providedIn: 'root' }]
23433
23490
  }] });
@@ -23600,10 +23657,10 @@ class RuleCompilerService {
23600
23657
  return 'false';
23601
23658
  return `'${s.replace(/'/g, "\\'")}'`;
23602
23659
  }
23603
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: RuleCompilerService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
23604
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: RuleCompilerService, providedIn: 'root' });
23660
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: RuleCompilerService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
23661
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: RuleCompilerService, providedIn: 'root' });
23605
23662
  }
23606
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: RuleCompilerService, decorators: [{
23663
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: RuleCompilerService, decorators: [{
23607
23664
  type: Injectable,
23608
23665
  args: [{ providedIn: 'root' }]
23609
23666
  }] });
@@ -25348,8 +25405,8 @@ class TableRulesEditorComponent {
25348
25405
  groups[idx] = { op: 'AND', conditions: [] };
25349
25406
  return groups[idx];
25350
25407
  }
25351
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: TableRulesEditorComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: OperatorsRegistryService }, { token: RuleCompilerService }, { token: i1.DynamicFormService }, { token: i1.GenericCrudService, optional: true }], target: i0.ɵɵFactoryTarget.Component });
25352
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.4", type: TableRulesEditorComponent, isStandalone: true, selector: "table-rules-editor", inputs: { config: "config", resourcePath: "resourcePath", fields: "fields", i18nRules: "i18nRules", dslFunctionRegistry: "dslFunctionRegistry", debugLogs: "debugLogs", debugLevel: "debugLevel" }, outputs: { configChange: "configChange" }, usesOnChanges: true, ngImport: i0, template: `
25408
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: TableRulesEditorComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: OperatorsRegistryService }, { token: RuleCompilerService }, { token: i1.DynamicFormService }, { token: i1.GenericCrudService, optional: true }], target: i0.ɵɵFactoryTarget.Component });
25409
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.17", type: TableRulesEditorComponent, isStandalone: true, selector: "table-rules-editor", inputs: { config: "config", resourcePath: "resourcePath", fields: "fields", i18nRules: "i18nRules", dslFunctionRegistry: "dslFunctionRegistry", debugLogs: "debugLogs", debugLevel: "debugLevel" }, outputs: { configChange: "configChange" }, usesOnChanges: true, ngImport: i0, template: `
25353
25410
  <div class="rules-editor">
25354
25411
  <mat-accordion multi>
25355
25412
  <!-- Block A: Scope & Actions -->
@@ -25883,7 +25940,7 @@ class TableRulesEditorComponent {
25883
25940
  </div>
25884
25941
  `, 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 });
25885
25942
  }
25886
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: TableRulesEditorComponent, decorators: [{
25943
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: TableRulesEditorComponent, decorators: [{
25887
25944
  type: Component,
25888
25945
  args: [{ selector: 'table-rules-editor', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [
25889
25946
  CommonModule,
@@ -27483,10 +27540,10 @@ class PraxisTableConfigEditor {
27483
27540
  this.isValid$.complete();
27484
27541
  this.isBusy$.complete();
27485
27542
  }
27486
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: PraxisTableConfigEditor, deps: [{ token: i0.ChangeDetectorRef }, { token: i1.TableConfigService }], target: i0.ɵɵFactoryTarget.Component });
27487
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.4", 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"] }] });
27543
+ 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 });
27544
+ 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"] }] });
27488
27545
  }
27489
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: PraxisTableConfigEditor, decorators: [{
27546
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: PraxisTableConfigEditor, decorators: [{
27490
27547
  type: Component,
27491
27548
  args: [{ selector: 'praxis-table-config-editor', standalone: true, imports: [
27492
27549
  CommonModule,
@@ -27546,10 +27603,10 @@ class TableDefaultsProvider {
27546
27603
  // Ensure proper typing: treat global table config as Partial<TableConfig>
27547
27604
  return g ? fillUndefined(base, g) : base;
27548
27605
  }
27549
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: TableDefaultsProvider, deps: [{ token: i1.GlobalConfigService }], target: i0.ɵɵFactoryTarget.Injectable });
27550
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: TableDefaultsProvider, providedIn: 'root' });
27606
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: TableDefaultsProvider, deps: [{ token: i1.GlobalConfigService }], target: i0.ɵɵFactoryTarget.Injectable });
27607
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: TableDefaultsProvider, providedIn: 'root' });
27551
27608
  }
27552
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: TableDefaultsProvider, decorators: [{
27609
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: TableDefaultsProvider, decorators: [{
27553
27610
  type: Injectable,
27554
27611
  args: [{ providedIn: 'root' }]
27555
27612
  }], ctorParameters: () => [{ type: i1.GlobalConfigService }] });
@@ -27578,10 +27635,10 @@ class FilterConfigService {
27578
27635
  save(key, config) {
27579
27636
  this.storage.saveConfig(this.PREFIX + key, config).subscribe();
27580
27637
  }
27581
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: FilterConfigService, deps: [{ token: ASYNC_CONFIG_STORAGE }], target: i0.ɵɵFactoryTarget.Injectable });
27582
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: FilterConfigService, providedIn: 'root' });
27638
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: FilterConfigService, deps: [{ token: ASYNC_CONFIG_STORAGE }], target: i0.ɵɵFactoryTarget.Injectable });
27639
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: FilterConfigService, providedIn: 'root' });
27583
27640
  }
27584
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: FilterConfigService, decorators: [{
27641
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: FilterConfigService, decorators: [{
27585
27642
  type: Injectable,
27586
27643
  args: [{ providedIn: 'root' }]
27587
27644
  }], ctorParameters: () => [{ type: undefined, decorators: [{
@@ -27616,6 +27673,8 @@ const DEFAULT_I18N = {
27616
27673
  retry: 'Tentar novamente',
27617
27674
  errorLoadingFilters: 'Erro ao carregar filtros.',
27618
27675
  settings: 'Configurações',
27676
+ settingsAriaLabel: 'Abrir configurações do filtro',
27677
+ tagActionsAriaLabel: 'Ações do atalho',
27619
27678
  save: 'Salvar',
27620
27679
  cancel: 'Cancelar',
27621
27680
  shortcutsLabel: 'Atalhos',
@@ -27667,6 +27726,28 @@ const FILTER_CONTROL_TYPE_SYNONYMS = new Set([
27667
27726
  ...INLINE_FILTER_ALIAS_TOKENS,
27668
27727
  ]);
27669
27728
  const INLINE_COMPACT_CONTROL_TYPE_TOKENS = new Set(INLINE_FILTER_CONTROL_TYPE_VALUES.map((controlType) => normalizeControlTypeToken(controlType)));
27729
+ function normalizeCorporateLoggerEnvironment$1(candidate) {
27730
+ const value = String(candidate || '')
27731
+ .trim()
27732
+ .toLowerCase();
27733
+ if (!value)
27734
+ return 'prod';
27735
+ if (value === 'dev' || value === 'development' || value === 'local')
27736
+ return 'dev';
27737
+ if (value === 'qa' || value === 'test' || value === 'testing')
27738
+ return 'qa';
27739
+ if (value === 'hml'
27740
+ || value === 'homolog'
27741
+ || value === 'homologacao'
27742
+ || value === 'stage'
27743
+ || value === 'staging') {
27744
+ return 'hml';
27745
+ }
27746
+ return 'prod';
27747
+ }
27748
+ function createPraxisFilterFallbackLogger(environment) {
27749
+ return new LoggerService(createCorporateLoggerConfig(normalizeCorporateLoggerEnvironment$1(environment)), [new ConsoleLoggerSink()]);
27750
+ }
27670
27751
  /**
27671
27752
  * Componente de filtro dinâmico para tabelas.
27672
27753
  *
@@ -27694,6 +27775,7 @@ class PraxisFilter {
27694
27775
  schemaNormalizer;
27695
27776
  componentKeys;
27696
27777
  route;
27778
+ logger;
27697
27779
  resourcePath;
27698
27780
  /**
27699
27781
  * Optional static metadata for offline/showcase usage.
@@ -27815,6 +27897,7 @@ class PraxisFilter {
27815
27897
  i18nLabels = DEFAULT_I18N;
27816
27898
  configKey = null;
27817
27899
  lastSchemaMeta;
27900
+ schemaLoadVersion = 0;
27818
27901
  // Outdated state and persistence helpers
27819
27902
  schemaOutdated = false;
27820
27903
  anchorRef;
@@ -27833,6 +27916,8 @@ class PraxisFilter {
27833
27916
  addItems = [];
27834
27917
  addItemsUpdateQueued = false;
27835
27918
  applySchemaQueued = false;
27919
+ fallbackLogger;
27920
+ fallbackLoggerEnvironment = null;
27836
27921
  // Lifecycle control
27837
27922
  isViewInitialized = false;
27838
27923
  // Debug trackers
@@ -27927,6 +28012,17 @@ class PraxisFilter {
27927
28012
  const key = this.resolveConfigKey();
27928
28013
  return key ? `filter-schema-meta:${key}` : null;
27929
28014
  }
28015
+ filterSchemaMetaIndexKey() {
28016
+ const key = this.filterSchemaMetaKey();
28017
+ return key ? `${key}:index` : null;
28018
+ }
28019
+ filterSchemaMetaKeyForSchemaId(schemaId) {
28020
+ const scopeKey = this.filterSchemaMetaKey();
28021
+ const id = String(schemaId || '').trim();
28022
+ if (!scopeKey || !id)
28023
+ return null;
28024
+ return `${scopeKey}:schema:${id}`;
28025
+ }
27930
28026
  filterSchemaIgnoreKey(serverHash) {
27931
28027
  const key = this.resolveConfigKey();
27932
28028
  return key ? `filter-schema-ignore:${key}:${serverHash}` : null;
@@ -27939,7 +28035,7 @@ class PraxisFilter {
27939
28035
  const key = this.resolveConfigKey();
27940
28036
  return key ? `filter-schema-notified:${key}:${serverHash}` : null;
27941
28037
  }
27942
- constructor(crud, configStorage, destroyRef, filterConfig, settingsPanel, snackBar, dialog, cdr, ngZone, dynamicForm, schemaNormalizer, componentKeys, route) {
28038
+ constructor(crud, configStorage, destroyRef, filterConfig, settingsPanel, snackBar, dialog, cdr, ngZone, dynamicForm, schemaNormalizer, componentKeys, route, logger) {
27943
28039
  this.crud = crud;
27944
28040
  this.configStorage = configStorage;
27945
28041
  this.destroyRef = destroyRef;
@@ -27953,8 +28049,53 @@ class PraxisFilter {
27953
28049
  this.schemaNormalizer = schemaNormalizer;
27954
28050
  this.componentKeys = componentKeys;
27955
28051
  this.route = route;
28052
+ this.logger = logger;
27956
28053
  }
27957
28054
  global = inject(GlobalConfigService);
28055
+ resolveRuntimeEnvironment() {
28056
+ const globalAny = this.global;
28057
+ let globalAppEnvironment;
28058
+ let globalEnvironment;
28059
+ try {
28060
+ globalAppEnvironment = globalAny?.get?.('app.environment');
28061
+ globalEnvironment = globalAny?.get?.('environment');
28062
+ }
28063
+ catch {
28064
+ // ignore config access failures
28065
+ }
28066
+ const candidates = [
28067
+ globalAppEnvironment,
28068
+ globalEnvironment,
28069
+ globalThis?.process?.env?.NODE_ENV,
28070
+ ];
28071
+ for (const candidate of candidates) {
28072
+ if (typeof candidate === 'string' && candidate.trim()) {
28073
+ return candidate.trim().toLowerCase();
28074
+ }
28075
+ }
28076
+ return 'prod';
28077
+ }
28078
+ getLogger() {
28079
+ if (this.logger)
28080
+ return this.logger;
28081
+ const runtimeEnvironment = normalizeCorporateLoggerEnvironment$1(this.resolveRuntimeEnvironment());
28082
+ if (!this.fallbackLogger
28083
+ || this.fallbackLoggerEnvironment !== runtimeEnvironment) {
28084
+ this.fallbackLogger = createPraxisFilterFallbackLogger(runtimeEnvironment);
28085
+ this.fallbackLoggerEnvironment = runtimeEnvironment;
28086
+ }
28087
+ return this.fallbackLogger;
28088
+ }
28089
+ buildFilterLogOptions(data, actionId) {
28090
+ return {
28091
+ context: {
28092
+ lib: 'praxis-table',
28093
+ component: 'PraxisFilter',
28094
+ ...(actionId ? { actionId } : {}),
28095
+ },
28096
+ ...(data !== undefined ? { data } : {}),
28097
+ };
28098
+ }
27958
28099
  isFilterDebugEnabled() {
27959
28100
  try {
27960
28101
  const explicitFlag = typeof window !== 'undefined' ? window.DEBUG_PTABLE : undefined;
@@ -27971,18 +28112,12 @@ class PraxisFilter {
27971
28112
  logFilterDebug(message, payload) {
27972
28113
  if (!this.isFilterDebugEnabled())
27973
28114
  return;
27974
- if (payload === undefined)
27975
- console.debug(message);
27976
- else
27977
- console.debug(message, payload);
28115
+ this.getLogger().debug(message, this.buildFilterLogOptions(payload, 'filter.debug'));
27978
28116
  }
27979
28117
  logFilterWarn(message, payload) {
27980
28118
  if (!this.isFilterDebugEnabled())
27981
28119
  return;
27982
- if (payload === undefined)
27983
- console.warn(message);
27984
- else
27985
- console.warn(message, payload);
28120
+ this.getLogger().warn(message, this.buildFilterLogOptions(payload, 'filter.warn'));
27986
28121
  }
27987
28122
  // Optional injection (adapter provided by host app)
27988
28123
  filterDrawerAdapter = (() => {
@@ -28283,12 +28418,20 @@ class PraxisFilter {
28283
28418
  }
28284
28419
  }
28285
28420
  ngOnChanges(changes) {
28421
+ const schemaIdentityChanged = (changes['resourcePath'] && !changes['resourcePath'].firstChange) ||
28422
+ (changes['filterId'] && !changes['filterId'].firstChange) ||
28423
+ (changes['formId'] && !changes['formId'].firstChange) ||
28424
+ (changes['persistenceKey'] && !changes['persistenceKey'].firstChange) ||
28425
+ (changes['componentInstanceId'] && !changes['componentInstanceId'].firstChange);
28286
28426
  if (changes['resourcePath'] ||
28287
28427
  changes['filterId'] ||
28288
28428
  changes['formId'] ||
28289
28429
  changes['persistenceKey'] ||
28290
28430
  changes['componentInstanceId']) {
28291
28431
  this.resolveConfigKey();
28432
+ if (schemaIdentityChanged) {
28433
+ this.resetSchemaStateForContextChange();
28434
+ }
28292
28435
  }
28293
28436
  if (changes['resourcePath'] && !changes['resourcePath'].firstChange) {
28294
28437
  this.logFilterDebug('[PFILTER] ngOnChanges: resourcePath changed', {
@@ -28615,7 +28758,7 @@ class PraxisFilter {
28615
28758
  this.snackBar.open(message, 'Fechar', { duration: 3000 });
28616
28759
  }
28617
28760
  catch (err) {
28618
- console.error('PFILTER:config:save:error', err);
28761
+ this.getLogger().error('PFILTER:config:save:error', this.buildFilterLogOptions({ error: err }, 'config.save'));
28619
28762
  this.snackBar.open('Erro ao salvar configurações', 'Fechar', {
28620
28763
  duration: 3000,
28621
28764
  });
@@ -28691,7 +28834,7 @@ class PraxisFilter {
28691
28834
  });
28692
28835
  }
28693
28836
  catch (err) {
28694
- console.error('PFILTER:openSettings:error', err);
28837
+ this.getLogger().error('PFILTER:openSettings:error', this.buildFilterLogOptions({ error: err }, 'settings.open'));
28695
28838
  this.snackBar.open('Erro ao abrir configurações', 'Fechar', {
28696
28839
  duration: 3000,
28697
28840
  });
@@ -28853,6 +28996,211 @@ class PraxisFilter {
28853
28996
  const locale = (typeof navigator !== 'undefined' && navigator.language) ? navigator.language : undefined;
28854
28997
  return { path, operation, schemaType, includeInternalSchemas: true, tenant, locale, baseUrl, apiOrigin };
28855
28998
  }
28999
+ toSchemaIdContext(ctx) {
29000
+ return {
29001
+ path: ctx.path,
29002
+ operation: ctx.operation,
29003
+ schemaType: ctx.schemaType,
29004
+ includeInternalSchemas: ctx.includeInternalSchemas,
29005
+ tenant: ctx.tenant,
29006
+ locale: ctx.locale,
29007
+ apiOrigin: ctx.apiOrigin,
29008
+ };
29009
+ }
29010
+ resetSchemaStateForContextChange() {
29011
+ this.schemaLoadVersion += 1;
29012
+ this.setSchemaLoading(false);
29013
+ this.lastSchemaMeta = undefined;
29014
+ this.schemaOutdated = false;
29015
+ this.schemaError = false;
29016
+ this.schemaMetas = undefined;
29017
+ this.advancedConfig = undefined;
29018
+ this.advancedForm = undefined;
29019
+ this.schemaStatusChange.emit({ outdated: false, formId: this.formId });
29020
+ }
29021
+ clearSchemaMetaPersistence(options) {
29022
+ try {
29023
+ const keys = new Set();
29024
+ const legacyScopeKey = this.getSchemaMetaKey();
29025
+ if (legacyScopeKey)
29026
+ keys.add(legacyScopeKey);
29027
+ if (options?.context) {
29028
+ const contextualKey = this.getSchemaMetaKeyForContext(options.context);
29029
+ if (contextualKey)
29030
+ keys.add(contextualKey);
29031
+ }
29032
+ if (options?.includeAllScoped) {
29033
+ const indexKey = this.filterSchemaMetaIndexKey();
29034
+ if (indexKey) {
29035
+ this.configStorage
29036
+ .loadConfig(indexKey)
29037
+ .pipe(take(1))
29038
+ .subscribe({
29039
+ next: (storedIds) => {
29040
+ const ids = Array.isArray(storedIds) ? storedIds : [];
29041
+ ids.forEach((schemaId) => {
29042
+ const key = this.filterSchemaMetaKeyForSchemaId(schemaId);
29043
+ if (key)
29044
+ this.clearConfigStorageKey(key);
29045
+ });
29046
+ this.clearConfigStorageKey(indexKey);
29047
+ },
29048
+ error: () => {
29049
+ this.clearConfigStorageKey(indexKey);
29050
+ },
29051
+ });
29052
+ }
29053
+ }
29054
+ keys.forEach((key) => this.clearConfigStorageKey(key));
29055
+ }
29056
+ catch {
29057
+ // no-op: schema metadata cleanup is best effort
29058
+ }
29059
+ }
29060
+ clearConfigStorageKey(key) {
29061
+ if (!key)
29062
+ return;
29063
+ try {
29064
+ this.configStorage.clearConfig(key).pipe(take(1)).subscribe();
29065
+ }
29066
+ catch {
29067
+ // ignore storage clear failures
29068
+ }
29069
+ }
29070
+ loadStoredSchemaMeta(key) {
29071
+ if (!key)
29072
+ return Promise.resolve(undefined);
29073
+ return firstValueFrom(this.configStorage.loadConfig(key))
29074
+ .then((value) => value ?? undefined)
29075
+ .catch(() => undefined);
29076
+ }
29077
+ rememberSchemaMetaContext(schemaId) {
29078
+ const id = String(schemaId || '').trim();
29079
+ if (!id)
29080
+ return;
29081
+ const indexKey = this.filterSchemaMetaIndexKey();
29082
+ if (!indexKey)
29083
+ return;
29084
+ try {
29085
+ this.configStorage
29086
+ .loadConfig(indexKey)
29087
+ .pipe(take(1))
29088
+ .subscribe((stored) => {
29089
+ const unique = new Set((Array.isArray(stored) ? stored : [])
29090
+ .map((item) => String(item || '').trim())
29091
+ .filter((item) => !!item));
29092
+ unique.add(id);
29093
+ this.configStorage
29094
+ .saveConfig(indexKey, Array.from(unique))
29095
+ .pipe(take(1))
29096
+ .subscribe();
29097
+ });
29098
+ }
29099
+ catch {
29100
+ // ignore index update failures
29101
+ }
29102
+ }
29103
+ getSchemaMetaKeyForContext(context) {
29104
+ try {
29105
+ return this.filterSchemaMetaKeyForSchemaId(buildSchemaId(context));
29106
+ }
29107
+ catch {
29108
+ return this.getSchemaMetaKey();
29109
+ }
29110
+ }
29111
+ isStoredSchemaMetaForContext(storedMeta, schemaId, context) {
29112
+ if (!storedMeta || typeof storedMeta !== 'object')
29113
+ return false;
29114
+ const storedSchemaId = String(storedMeta.schemaId || '').trim();
29115
+ const storedContext = storedMeta.schemaContext;
29116
+ if (!storedSchemaId && !storedContext)
29117
+ return false;
29118
+ if (storedSchemaId && storedSchemaId !== schemaId)
29119
+ return false;
29120
+ if (storedContext && !this.isSameSchemaContext(storedContext, context))
29121
+ return false;
29122
+ return true;
29123
+ }
29124
+ isSameSchemaContext(left, right) {
29125
+ if (!left || !right)
29126
+ return false;
29127
+ return (left.path === right.path &&
29128
+ left.operation === right.operation &&
29129
+ left.schemaType === right.schemaType &&
29130
+ left.includeInternalSchemas === right.includeInternalSchemas &&
29131
+ left.tenant === right.tenant &&
29132
+ left.locale === right.locale &&
29133
+ left.apiOrigin === right.apiOrigin);
29134
+ }
29135
+ resolveLocalSchemaHashForContext(context) {
29136
+ const localHash = String(this.lastSchemaMeta?.serverHash || '').trim();
29137
+ if (!localHash)
29138
+ return undefined;
29139
+ if (!this.isSameSchemaContext(this.lastSchemaMeta?.context, context)) {
29140
+ return undefined;
29141
+ }
29142
+ return localHash;
29143
+ }
29144
+ persistSchemaMeta(schemaId, context, serverHash) {
29145
+ try {
29146
+ const key = this.filterSchemaMetaKeyForSchemaId(schemaId) || this.getSchemaMetaKey();
29147
+ if (!key)
29148
+ return;
29149
+ const nowIso = new Date().toISOString();
29150
+ this.configStorage
29151
+ .loadConfig(key)
29152
+ .pipe(take(1))
29153
+ .subscribe((prev) => {
29154
+ const next = {
29155
+ ...(prev || {}),
29156
+ schemaId,
29157
+ schemaContext: context,
29158
+ lastVerifiedAt: nowIso,
29159
+ };
29160
+ if (serverHash)
29161
+ next.serverHash = serverHash;
29162
+ this.configStorage.saveConfig(key, next).pipe(take(1)).subscribe();
29163
+ });
29164
+ this.rememberSchemaMetaContext(schemaId);
29165
+ }
29166
+ catch {
29167
+ // no-op: schema metadata persistence is best effort
29168
+ }
29169
+ }
29170
+ syncSchemaMeta(ctx, serverHash) {
29171
+ const context = this.toSchemaIdContext(ctx);
29172
+ const schemaId = buildSchemaId(context);
29173
+ this.lastSchemaMeta = { schemaId, serverHash, context };
29174
+ this.metaChanged.emit({ schemaId, serverHash, context });
29175
+ this.persistSchemaMeta(schemaId, context, serverHash);
29176
+ }
29177
+ resolveFallbackSchemaHash() {
29178
+ try {
29179
+ const hash = String(this.crud?.getLastSchemaInfo?.()?.schemaHash || '').trim();
29180
+ if (hash)
29181
+ return hash;
29182
+ }
29183
+ catch {
29184
+ // ignore and try local fallback
29185
+ }
29186
+ const currentContext = this.toSchemaIdContext(this.buildFilteredSchemaContext());
29187
+ return this.resolveLocalSchemaHashForContext(currentContext);
29188
+ }
29189
+ isExplicitlyFilterable(definition) {
29190
+ if (!definition || typeof definition !== 'object')
29191
+ return false;
29192
+ if (definition.filterable === true)
29193
+ return true;
29194
+ const filterControlTypeToken = normalizeControlTypeToken(definition.filterControlType || '');
29195
+ if (filterControlTypeToken)
29196
+ return true;
29197
+ const controlTypeToken = normalizeControlTypeToken(definition.controlType || '');
29198
+ return controlTypeToken.startsWith('filter');
29199
+ }
29200
+ pickSafeGenericFallbackDefs(definitions) {
29201
+ const source = Array.isArray(definitions) ? definitions : [];
29202
+ return source.filter((definition) => this.isExplicitlyFilterable(definition));
29203
+ }
28856
29204
  async loadSchemaViaClient() {
28857
29205
  const ctx = this.buildFilteredSchemaContext();
28858
29206
  try {
@@ -28863,36 +29211,76 @@ class PraxisFilter {
28863
29211
  const adapter = disableCache
28864
29212
  ? new MemoryCacheAdapter()
28865
29213
  : new LocalStorageCacheAdapter({ ttlMs: 30 * 60 * 1000, maxEntries: 200 });
28866
- const client = new SchemaMetadataClient(adapter);
28867
- const entry = await client.getSchema({
28868
- baseUrl: ctx.baseUrl,
28869
- path: ctx.path,
28870
- operation: ctx.operation,
28871
- schemaType: ctx.schemaType,
28872
- includeInternalSchemas: ctx.includeInternalSchemas,
28873
- tenant: ctx.tenant,
28874
- locale: ctx.locale,
28875
- });
28876
- const defs = this.schemaNormalizer.normalizeSchema(entry.schema);
28877
- const metas = mapFieldDefinitionsToMetadata(defs);
28878
- this.logFilterWarn('[PFILTER] loadSchemaViaClient: metas', {
28879
- count: metas.length,
28880
- names: metas.map((m) => m.name),
28881
- });
28882
- const schemaId = buildSchemaId(ctx);
28883
- this.lastSchemaMeta = { schemaId, serverHash: entry.schemaHash, context: ctx };
28884
- // Emit metadata to host
28885
- this.metaChanged.emit({ schemaId, serverHash: entry.schemaHash, context: ctx });
28886
- // Persist minimal meta for future verify-only calls
28887
29214
  try {
28888
- const nowIso = new Date().toISOString();
28889
- const metaKey = this.getSchemaMetaKey();
28890
- if (metaKey) {
28891
- this.configStorage.saveConfig(metaKey, { serverHash: entry.schemaHash, lastVerifiedAt: nowIso }).pipe(take(1)).subscribe();
29215
+ const client = new SchemaMetadataClient(adapter);
29216
+ const entry = await client.getSchema({
29217
+ baseUrl: ctx.baseUrl,
29218
+ path: ctx.path,
29219
+ operation: ctx.operation,
29220
+ schemaType: ctx.schemaType,
29221
+ includeInternalSchemas: ctx.includeInternalSchemas,
29222
+ tenant: ctx.tenant,
29223
+ locale: ctx.locale,
29224
+ });
29225
+ const defs = this.schemaNormalizer.normalizeSchema(entry.schema);
29226
+ const metas = mapFieldDefinitionsToMetadata(defs);
29227
+ this.logFilterWarn('[PFILTER] loadSchemaViaClient: metas', {
29228
+ count: metas.length,
29229
+ names: metas.map((m) => m.name),
29230
+ });
29231
+ this.syncSchemaMeta(ctx, entry.schemaHash);
29232
+ return metas;
29233
+ }
29234
+ catch (schemaClientError) {
29235
+ // Runtime hardening: if /schemas/filtered returns HTML/redirect or invalid JSON,
29236
+ // fallback to CRUD HttpClient path before failing the filter experience.
29237
+ this.logFilterWarn('[PFILTER] loadSchemaViaClient: metadata client failed, trying CRUD fallback', {
29238
+ message: schemaClientError instanceof Error ? schemaClientError.message : String(schemaClientError),
29239
+ path: ctx.path,
29240
+ baseUrl: ctx.baseUrl,
29241
+ });
29242
+ return this.loadSchemaViaCrudFallback(ctx, schemaClientError);
29243
+ }
29244
+ }
29245
+ async loadSchemaViaCrudFallback(ctx, primaryError) {
29246
+ try {
29247
+ const filteredDefs = await firstValueFrom(this.crud.getFilteredSchema({
29248
+ path: ctx.path,
29249
+ operation: ctx.operation,
29250
+ schemaType: ctx.schemaType,
29251
+ includeInternalSchemas: ctx.includeInternalSchemas,
29252
+ }));
29253
+ const metas = mapFieldDefinitionsToMetadata(filteredDefs);
29254
+ this.syncSchemaMeta(ctx, this.resolveFallbackSchemaHash());
29255
+ this.logFilterWarn('[PFILTER] loadSchemaViaCrudFallback: using getFilteredSchema', {
29256
+ count: metas.length,
29257
+ hasSchemaHash: !!this.lastSchemaMeta?.serverHash,
29258
+ });
29259
+ return metas;
29260
+ }
29261
+ catch (filteredError) {
29262
+ try {
29263
+ const genericDefs = await firstValueFrom(this.crud.getSchema());
29264
+ const safeFallbackDefs = this.pickSafeGenericFallbackDefs(genericDefs);
29265
+ if (!safeFallbackDefs.length) {
29266
+ const unsafeFallback = new Error('PFILTER:schema:generic-fallback-unsafe');
29267
+ unsafeFallback.cause = genericDefs;
29268
+ throw unsafeFallback;
29269
+ }
29270
+ const metas = mapFieldDefinitionsToMetadata(safeFallbackDefs);
29271
+ this.syncSchemaMeta(ctx, this.resolveFallbackSchemaHash());
29272
+ this.logFilterWarn('[PFILTER] loadSchemaViaCrudFallback: using getSchema', {
29273
+ count: metas.length,
29274
+ originalCount: Array.isArray(genericDefs) ? genericDefs.length : 0,
29275
+ });
29276
+ return metas;
29277
+ }
29278
+ catch (genericError) {
29279
+ const error = new Error('PFILTER:schema:load:fallback-failed');
29280
+ error.cause = { primaryError, filteredError, genericError };
29281
+ throw error;
28892
29282
  }
28893
29283
  }
28894
- catch { }
28895
- return metas;
28896
29284
  }
28897
29285
  loadSchema() {
28898
29286
  this.logFilterWarn('[PFILTER] loadSchema: start');
@@ -28910,15 +29298,53 @@ class PraxisFilter {
28910
29298
  this.logFilterWarn('[PFILTER] loadSchema: already loading - skip');
28911
29299
  return;
28912
29300
  }
29301
+ // Avoid opening stale advanced config while a new schema context is being loaded.
29302
+ const requestContext = (() => {
29303
+ try {
29304
+ return this.toSchemaIdContext(this.buildFilteredSchemaContext());
29305
+ }
29306
+ catch {
29307
+ return undefined;
29308
+ }
29309
+ })();
29310
+ const requestVersion = ++this.schemaLoadVersion;
29311
+ this.advancedConfig = undefined;
29312
+ this.advancedForm = undefined;
28913
29313
  this.setSchemaLoading(true);
28914
29314
  this.schemaError = false;
28915
29315
  // Use SchemaMetadataClient with ETag/304 + schemaId context
28916
29316
  this.loadSchemaViaClient()
28917
29317
  .then((metas) => {
29318
+ if (requestVersion !== this.schemaLoadVersion)
29319
+ return;
29320
+ if (requestContext &&
29321
+ !this.isSameSchemaContext(requestContext, (() => {
29322
+ try {
29323
+ return this.toSchemaIdContext(this.buildFilteredSchemaContext());
29324
+ }
29325
+ catch {
29326
+ return undefined;
29327
+ }
29328
+ })())) {
29329
+ return;
29330
+ }
28918
29331
  if (this.schemaError)
28919
29332
  return;
28920
29333
  setTimeout(() => {
28921
29334
  this.ngZone.run(() => {
29335
+ if (requestVersion !== this.schemaLoadVersion)
29336
+ return;
29337
+ if (requestContext &&
29338
+ !this.isSameSchemaContext(requestContext, (() => {
29339
+ try {
29340
+ return this.toSchemaIdContext(this.buildFilteredSchemaContext());
29341
+ }
29342
+ catch {
29343
+ return undefined;
29344
+ }
29345
+ })())) {
29346
+ return;
29347
+ }
28922
29348
  this.setSchemaLoading(false);
28923
29349
  this.schemaMetas = metas;
28924
29350
  this.logFilterDebug('[PFILTER] loadSchema: metas received', {
@@ -28930,15 +29356,37 @@ class PraxisFilter {
28930
29356
  });
28931
29357
  })
28932
29358
  .catch((err) => {
28933
- console.error('PFILTER:schema:load:error', err);
29359
+ this.getLogger().error('PFILTER:schema:load:error', this.buildFilterLogOptions({ error: err }, 'schema.load'));
28934
29360
  setTimeout(() => {
28935
29361
  this.ngZone.run(() => {
29362
+ if (requestVersion !== this.schemaLoadVersion)
29363
+ return;
29364
+ if (requestContext &&
29365
+ !this.isSameSchemaContext(requestContext, (() => {
29366
+ try {
29367
+ return this.toSchemaIdContext(this.buildFilteredSchemaContext());
29368
+ }
29369
+ catch {
29370
+ return undefined;
29371
+ }
29372
+ })())) {
29373
+ return;
29374
+ }
28936
29375
  this.setSchemaLoading(false);
28937
29376
  this.schemaError = true;
28938
29377
  });
28939
29378
  });
28940
29379
  });
28941
29380
  }
29381
+ retrySchemaLoad() {
29382
+ if (this.usesProvidedFieldMetadata()) {
29383
+ this.applyProvidedFieldMetadata();
29384
+ return;
29385
+ }
29386
+ this.schemaMetas = undefined;
29387
+ this.schemaError = false;
29388
+ this.loadSchema();
29389
+ }
28942
29390
  applySchemaMetas() {
28943
29391
  if (this.applySchemaQueued)
28944
29392
  return;
@@ -29863,6 +30311,14 @@ class PraxisFilter {
29863
30311
  const plural = count > 1 ? 's' : '';
29864
30312
  return `${this.i18nLabels.advanced}, ${count} filtro${plural} ativo${plural}`;
29865
30313
  }
30314
+ getSettingsAriaLabel() {
30315
+ return this.i18nLabels.settingsAriaLabel || this.i18nLabels.settings || 'Configurações';
30316
+ }
30317
+ getTagActionsAriaLabel(tag) {
30318
+ const base = this.i18nLabels.tagActionsAriaLabel || 'Ações do atalho';
30319
+ const tagLabel = String(tag?.label || '').trim();
30320
+ return tagLabel ? `${base}: ${tagLabel}` : base;
30321
+ }
29866
30322
  // =============================
29867
30323
  // Schema verification (ETag) + persistence helpers
29868
30324
  // =============================
@@ -29966,59 +30422,57 @@ class PraxisFilter {
29966
30422
  try {
29967
30423
  if (this.usesProvidedFieldMetadata())
29968
30424
  return;
29969
- const metaKey = this.getSchemaMetaKey();
29970
- if (!this.resourcePath || !metaKey)
30425
+ if (!this.resourcePath)
30426
+ return;
30427
+ const currentCtx = this.buildFilteredSchemaContext();
30428
+ const currentSchemaContext = this.toSchemaIdContext(currentCtx);
30429
+ const currentSchemaId = buildSchemaId(currentSchemaContext);
30430
+ const scopedMetaKey = this.getSchemaMetaKeyForContext(currentSchemaContext) || this.getSchemaMetaKey();
30431
+ if (!scopedMetaKey)
29971
30432
  return;
29972
30433
  // Build request to /schemas/filtered for filter (path=/.../filter, operation=post, schemaType=request)
29973
- const baseUrl = this.crud.getSchemasFilteredBaseUrl();
29974
- const basePath = (this.crud.schemaUrl() || '').replace(/\/+$/, '').replace(/\/schemas$/, '');
29975
- let path = basePath ? `${basePath}/filter` : `/${(this.resourcePath || '').replace(/^\/+|\/+$/g, '')}/filter`;
29976
- const u = new URL(baseUrl);
29977
- u.searchParams.set('path', path);
29978
- u.searchParams.set('operation', 'post');
29979
- u.searchParams.set('schemaType', 'request');
29980
- u.searchParams.set('includeInternalSchemas', 'true');
30434
+ const u = new URL(currentCtx.baseUrl);
30435
+ u.searchParams.set('path', currentCtx.path);
30436
+ u.searchParams.set('operation', String(currentCtx.operation || 'post'));
30437
+ u.searchParams.set('schemaType', String(currentCtx.schemaType || 'request'));
30438
+ u.searchParams.set('includeInternalSchemas', currentCtx.includeInternalSchemas ? 'true' : 'false');
29981
30439
  // Load previously persisted meta (serverHash)
29982
- const persistedMeta = await (async () => {
29983
- if (!metaKey)
29984
- return undefined;
29985
- try {
29986
- return await firstValueFrom(this.configStorage.loadConfig(metaKey));
29987
- }
29988
- catch {
29989
- return undefined;
29990
- }
29991
- })();
29992
- const previousHash = persistedMeta?.serverHash || this.lastSchemaMeta?.serverHash;
29993
- const hasPersistedMeta = persistedMeta != null;
29994
- const hasLocalMeta = !!this.lastSchemaMeta?.serverHash;
29995
- const shouldPersistMeta = hasPersistedMeta || !hasLocalMeta;
30440
+ const scopedMeta = await this.loadStoredSchemaMeta(scopedMetaKey);
30441
+ const legacyScopeKey = this.getSchemaMetaKey();
30442
+ const legacyMeta = legacyScopeKey && legacyScopeKey !== scopedMetaKey
30443
+ ? await this.loadStoredSchemaMeta(legacyScopeKey)
30444
+ : undefined;
30445
+ const persistedMeta = this.isStoredSchemaMetaForContext(scopedMeta, currentSchemaId, currentSchemaContext)
30446
+ ? scopedMeta
30447
+ : this.isStoredSchemaMetaForContext(legacyMeta, currentSchemaId, currentSchemaContext)
30448
+ ? legacyMeta
30449
+ : undefined;
30450
+ const persistedHash = String(persistedMeta?.serverHash || '').trim() || undefined;
30451
+ const previousHash = persistedHash ||
30452
+ this.resolveLocalSchemaHashForContext(currentSchemaContext);
29996
30453
  // If we have no prior hash and no in-memory schema, skip verification to avoid an extra full GET.
29997
30454
  // The initial loadSchema() will fetch the body and persist the hash.
29998
30455
  if (!previousHash && !this.schemaMetas?.length) {
29999
30456
  return;
30000
30457
  }
30001
- const tenant = (() => { try {
30002
- return this.global.getTenant();
30003
- }
30004
- catch {
30005
- return undefined;
30006
- } })();
30007
- const locale = (() => { try {
30008
- return (typeof navigator !== 'undefined' && navigator.language) ? navigator.language : undefined;
30009
- }
30010
- catch {
30011
- return undefined;
30012
- } })();
30458
+ const tenant = currentCtx.tenant;
30459
+ const locale = currentCtx.locale;
30013
30460
  const res = await fetchWithETag({ url: u.toString(), schemaHash: previousHash, tenant, locale });
30014
30461
  const nowIso = new Date().toISOString();
30015
30462
  const metaToSave = { ...(persistedMeta || {}) };
30463
+ metaToSave.schemaId = currentSchemaId;
30464
+ metaToSave.schemaContext = currentSchemaContext;
30016
30465
  metaToSave.lastVerifiedAt = nowIso;
30466
+ if (!metaToSave.serverHash && previousHash) {
30467
+ metaToSave.serverHash = previousHash;
30468
+ }
30017
30469
  if (res.status === 304) {
30018
30470
  try {
30019
- const key = this.getSchemaMetaKey();
30020
- if (shouldPersistMeta && key)
30021
- this.configStorage.saveConfig(key, metaToSave).pipe(take(1)).subscribe();
30471
+ this.configStorage
30472
+ .saveConfig(scopedMetaKey, metaToSave)
30473
+ .pipe(take(1))
30474
+ .subscribe();
30475
+ this.rememberSchemaMetaContext(currentSchemaId);
30022
30476
  }
30023
30477
  catch { }
30024
30478
  if (this.schemaOutdated)
@@ -30030,9 +30484,11 @@ class PraxisFilter {
30030
30484
  const newHash = res.schemaHash;
30031
30485
  metaToSave.serverHash = newHash;
30032
30486
  try {
30033
- const key = this.getSchemaMetaKey();
30034
- if (shouldPersistMeta && key)
30035
- this.configStorage.saveConfig(key, metaToSave).pipe(take(1)).subscribe();
30487
+ this.configStorage
30488
+ .saveConfig(scopedMetaKey, metaToSave)
30489
+ .pipe(take(1))
30490
+ .subscribe();
30491
+ this.rememberSchemaMetaContext(currentSchemaId);
30036
30492
  }
30037
30493
  catch { }
30038
30494
  // Only mark outdated when there was a previous base (hash or schemaMetas) and we are in edit mode
@@ -30057,10 +30513,11 @@ class PraxisFilter {
30057
30513
  return;
30058
30514
  if (this._resolvedPrefs.notifyIfOutdated === 'none')
30059
30515
  return;
30060
- const metaKey = this.getSchemaMetaKey();
30516
+ const currentSchemaContext = this.toSchemaIdContext(this.buildFilteredSchemaContext());
30517
+ const metaKey = this.getSchemaMetaKeyForContext(currentSchemaContext);
30061
30518
  if (!metaKey)
30062
30519
  return;
30063
- const serverHash = (await firstValueFrom(this.configStorage.loadConfig(metaKey)) || {})?.serverHash;
30520
+ const serverHash = (await this.loadStoredSchemaMeta(metaKey) || {})?.serverHash;
30064
30521
  if (!serverHash || !this.schemaOutdated)
30065
30522
  return;
30066
30523
  if (await this.isOutdatedIgnored(serverHash))
@@ -30130,7 +30587,7 @@ class PraxisFilter {
30130
30587
  this.submit.emit({ ...this.dto });
30131
30588
  }
30132
30589
  catch (err) {
30133
- console.error('PFILTER:applyTag:error', err);
30590
+ this.getLogger().error('PFILTER:applyTag:error', this.buildFilterLogOptions({ error: err }, 'tag.apply'));
30134
30591
  }
30135
30592
  }
30136
30593
  // =============================
@@ -30200,6 +30657,8 @@ class PraxisFilter {
30200
30657
  this.applyProvidedFieldMetadata();
30201
30658
  return !!this.advancedConfig;
30202
30659
  }
30660
+ if (this.schemaError)
30661
+ return false;
30203
30662
  if (!this.schemaLoading)
30204
30663
  this.loadSchema();
30205
30664
  const startedAt = Date.now();
@@ -30209,19 +30668,41 @@ class PraxisFilter {
30209
30668
  }
30210
30669
  await new Promise((resolve) => setTimeout(resolve, 50));
30211
30670
  }
30212
- return !!this.advancedConfig || this.schemaError || !this.schemaLoading;
30671
+ return !!this.advancedConfig;
30672
+ }
30673
+ focusSchemaRetryButton() {
30674
+ setTimeout(() => {
30675
+ try {
30676
+ const host = this.advancedButton?.nativeElement?.closest('.praxis-filter-bar')?.parentElement;
30677
+ const retry = host?.querySelector('.schema-error-retry');
30678
+ retry?.focus?.();
30679
+ }
30680
+ catch {
30681
+ // ignore focus errors
30682
+ }
30683
+ });
30684
+ }
30685
+ showAdvancedUnavailableFeedback() {
30686
+ const hasSchemaError = !!this.schemaError && !this.advancedConfig;
30687
+ if (hasSchemaError) {
30688
+ this.focusSchemaRetryButton();
30689
+ return;
30690
+ }
30691
+ const message = this.i18nLabels.noData || 'Nenhum filtro avançado disponível.';
30692
+ const action = this.i18nLabels.cancel || 'Fechar';
30693
+ this.snackBar.open(message, action, { duration: 3200 });
30213
30694
  }
30214
30695
  async openAdvancedModal() {
30215
30696
  this.captureLastActiveElement();
30216
30697
  const ready = await this.ensureAdvancedConfigReady();
30217
- if (!ready && !this.advancedConfig) {
30218
- this.snackBar.open(this.i18nLabels.errorLoadingFilters || 'Erro ao carregar filtros.', this.i18nLabels.retry || 'Tentar novamente', { duration: 3200 });
30698
+ if (!ready || !this.advancedConfig) {
30699
+ this.showAdvancedUnavailableFeedback();
30219
30700
  return;
30220
30701
  }
30221
30702
  this.advancedOpen = true;
30222
30703
  this.saveConfig();
30223
30704
  try {
30224
- const { FilterFormDialogHostComponent } = await import('./praxisui-table-filter-form-dialog-host.component-CLF05-__.mjs');
30705
+ const { FilterFormDialogHostComponent } = await import('./praxisui-table-filter-form-dialog-host.component-C2rQnHE1.mjs');
30225
30706
  const formId = this.formId || this.filterId || 'filter';
30226
30707
  const ref = this.dialog.open(FilterFormDialogHostComponent, {
30227
30708
  width: '780px',
@@ -30259,8 +30740,8 @@ class PraxisFilter {
30259
30740
  return;
30260
30741
  }
30261
30742
  const ready = await this.ensureAdvancedConfigReady();
30262
- if (!ready && !this.advancedConfig) {
30263
- this.snackBar.open(this.i18nLabels.errorLoadingFilters || 'Erro ao carregar filtros.', this.i18nLabels.retry || 'Tentar novamente', { duration: 3200 });
30743
+ if (!ready || !this.advancedConfig) {
30744
+ this.showAdvancedUnavailableFeedback();
30264
30745
  return;
30265
30746
  }
30266
30747
  this.advancedOpen = true;
@@ -30285,7 +30766,7 @@ class PraxisFilter {
30285
30766
  }
30286
30767
  catch (error) {
30287
30768
  this.closeAdvanced();
30288
- console.error('PFILTER:drawer:open:error', error);
30769
+ this.getLogger().error('PFILTER:drawer:open:error', this.buildFilterLogOptions({ error }, 'drawer.open'));
30289
30770
  }
30290
30771
  }
30291
30772
  toggleAdvanced() {
@@ -30310,10 +30791,12 @@ class PraxisFilter {
30310
30791
  if (!this.usesProvidedFieldMetadata())
30311
30792
  return;
30312
30793
  const source = (this.fieldMetadata || []);
30794
+ this.schemaLoadVersion += 1;
30313
30795
  this.schemaError = false;
30314
30796
  this.setSchemaLoading(false);
30315
30797
  this.schemaMetas = source.map((meta) => ({ ...meta }));
30316
30798
  this.lastSchemaMeta = undefined;
30799
+ this.clearSchemaMetaPersistence();
30317
30800
  this.applySchemaMetas();
30318
30801
  }
30319
30802
  saveConfig() {
@@ -30540,10 +31023,10 @@ class PraxisFilter {
30540
31023
  // no-op
30541
31024
  }
30542
31025
  }
30543
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.4", 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 }], target: i0.ɵɵFactoryTarget.Component });
30544
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.4", 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\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\">\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()\" aria-label=\"tag actions\">\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}.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.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$1.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 }] });
31026
+ 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 });
31027
+ 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$1.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 }] });
30545
31028
  }
30546
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: PraxisFilter, decorators: [{
31029
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: PraxisFilter, decorators: [{
30547
31030
  type: Component,
30548
31031
  args: [{ selector: 'praxis-filter', standalone: true, imports: [
30549
31032
  CommonModule,
@@ -30569,12 +31052,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImpor
30569
31052
  '[style.--pfx-always-min]': 'alwaysMinWidth + "px"',
30570
31053
  '[style.--pfx-always-cols-md]': 'alwaysColsMd',
30571
31054
  '[style.--pfx-always-cols-lg]': 'alwaysColsLg',
30572
- }, template: "<mat-progress-bar *ngIf=\"saving\" mode=\"indeterminate\"></mat-progress-bar>\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\">\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()\" aria-label=\"tag actions\">\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}.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"] }]
31055
+ }, 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"] }]
30573
31056
  }], ctorParameters: () => [{ type: i1.GenericCrudService }, { type: undefined, decorators: [{
30574
31057
  type: Inject,
30575
31058
  args: [ASYNC_CONFIG_STORAGE]
30576
31059
  }] }, { type: i0.DestroyRef }, { type: FilterConfigService }, { type: i3$1.SettingsPanelService }, { type: i2$1.MatSnackBar }, { type: i1$3.MatDialog }, { type: i0.ChangeDetectorRef }, { type: i0.NgZone }, { type: i1.DynamicFormService }, { type: i1.SchemaNormalizerService }, { type: i1.ComponentKeyService }, { type: i6$2.ActivatedRoute, decorators: [{
30577
31060
  type: Optional
31061
+ }] }, { type: i1.LoggerService, decorators: [{
31062
+ type: Optional
30578
31063
  }] }], propDecorators: { resourcePath: [{
30579
31064
  type: Input,
30580
31065
  args: [{ required: true }]
@@ -37312,15 +37797,15 @@ class PraxisTable {
37312
37797
  this.removeViewportChangeListeners = null;
37313
37798
  disposePraxisTableDslRuntimeRegistry(this.dslRuntimeContextKey);
37314
37799
  }
37315
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: PraxisTable, deps: [{ token: i0.ChangeDetectorRef }, { token: i3$1.SettingsPanelService }, { token: i1.GenericCrudService }, { token: TableDefaultsProvider }, { token: FilterConfigService }, { token: DataFormattingService }, { token: i6$3.PraxisDialog }, { token: i2$1.MatSnackBar }, { token: ASYNC_CONFIG_STORAGE }, { token: CONNECTION_STORAGE }, { token: i0.ElementRef }, { token: i1.GlobalConfigService }, { token: i1.ComponentKeyService }, { token: i1.LoadingOrchestrator }, { token: PRAXIS_LOADING_RENDERER, optional: true }, { token: i6$2.ActivatedRoute, optional: true }, { token: i1.LoggerService, optional: true }], target: i0.ɵɵFactoryTarget.Component });
37316
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.4", type: PraxisTable, isStandalone: true, selector: "praxis-table", inputs: { config: "config", resourcePath: "resourcePath", data: "data", tableId: "tableId", componentInstanceId: "componentInstanceId", title: "title", subtitle: "subtitle", icon: "icon", autoDelete: "autoDelete", notifyIfOutdated: "notifyIfOutdated", snoozeMs: "snoozeMs", autoOpenSettingsOnOutdated: "autoOpenSettingsOnOutdated", crudContext: "crudContext", dslFunctionRegistry: "dslFunctionRegistry", editModeEnabled: "editModeEnabled", dense: "dense" }, outputs: { rowClick: "rowClick", rowDoubleClick: "rowDoubleClick", rowAction: "rowAction", toolbarAction: "toolbarAction", bulkAction: "bulkAction", columnReorder: "columnReorder", columnReorderAttempt: "columnReorderAttempt", beforeDelete: "beforeDelete", afterDelete: "afterDelete", deleteError: "deleteError", beforeBulkDelete: "beforeBulkDelete", afterBulkDelete: "afterBulkDelete", bulkDeleteError: "bulkDeleteError", schemaStatusChange: "schemaStatusChange", metadataChange: "metadataChange", loadingStateChange: "loadingStateChange" }, host: { properties: { "class.density-compact": "this.hostDensityCompactClass", "class.density-comfortable": "this.hostDensityComfortableClass", "class.density-spacious": "this.hostDensitySpaciousClass", "class.row-borders": "this.hostRowBordersClass", "class.col-borders": "this.hostColumnBordersClass" } }, providers: [
37800
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: PraxisTable, deps: [{ token: i0.ChangeDetectorRef }, { token: i3$1.SettingsPanelService }, { token: i1.GenericCrudService }, { token: TableDefaultsProvider }, { token: FilterConfigService }, { token: DataFormattingService }, { token: i6$3.PraxisDialog }, { token: i2$1.MatSnackBar }, { token: ASYNC_CONFIG_STORAGE }, { token: CONNECTION_STORAGE }, { token: i0.ElementRef }, { token: i1.GlobalConfigService }, { token: i1.ComponentKeyService }, { token: i1.LoadingOrchestrator }, { token: PRAXIS_LOADING_RENDERER, optional: true }, { token: i6$2.ActivatedRoute, optional: true }, { token: i1.LoggerService, optional: true }], target: i0.ɵɵFactoryTarget.Component });
37801
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.17", type: PraxisTable, isStandalone: true, selector: "praxis-table", inputs: { config: "config", resourcePath: "resourcePath", data: "data", tableId: "tableId", componentInstanceId: "componentInstanceId", title: "title", subtitle: "subtitle", icon: "icon", autoDelete: "autoDelete", notifyIfOutdated: "notifyIfOutdated", snoozeMs: "snoozeMs", autoOpenSettingsOnOutdated: "autoOpenSettingsOnOutdated", crudContext: "crudContext", dslFunctionRegistry: "dslFunctionRegistry", editModeEnabled: "editModeEnabled", dense: "dense" }, outputs: { rowClick: "rowClick", rowDoubleClick: "rowDoubleClick", rowAction: "rowAction", toolbarAction: "toolbarAction", bulkAction: "bulkAction", columnReorder: "columnReorder", columnReorderAttempt: "columnReorderAttempt", beforeDelete: "beforeDelete", afterDelete: "afterDelete", deleteError: "deleteError", beforeBulkDelete: "beforeBulkDelete", afterBulkDelete: "afterBulkDelete", bulkDeleteError: "bulkDeleteError", schemaStatusChange: "schemaStatusChange", metadataChange: "metadataChange", loadingStateChange: "loadingStateChange" }, host: { properties: { "class.density-compact": "this.hostDensityCompactClass", "class.density-comfortable": "this.hostDensityComfortableClass", "class.density-spacious": "this.hostDensitySpaciousClass", "class.row-borders": "this.hostRowBordersClass", "class.col-borders": "this.hostColumnBordersClass" } }, providers: [
37317
37802
  GenericCrudService,
37318
37803
  TableDefaultsProvider,
37319
37804
  FilterConfigService,
37320
37805
  DataFormattingService
37321
- ], 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: "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 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 @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 >\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 <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\">{{ getCellValue(element, column) }}</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 </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 [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)\"\n (dblclick)=\"onRowDoubleClicked(row, i)\"\n ></tr>\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)\"\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 <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 </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}:host.density-compact{--p-header-padding: 8px 12px;--p-actions-btn-size: 32px;--p-actions-icon-size: 18px}:host.density-comfortable{--p-header-padding: 12px 16px;--p-actions-btn-size: 40px;--p-actions-icon-size: 22px}:host.density-spacious{--p-header-padding: 16px 20px;--p-actions-btn-size: 44px;--p-actions-icon-size: 24px}:host.density-compact ::ng-deep .mat-mdc-cell{padding:8px 12px}:host.density-comfortable ::ng-deep .mat-mdc-cell{padding:12px 16px}:host.density-spacious ::ng-deep .mat-mdc-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{--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: 36px;--p-table-drag-handle-color: var(--md-sys-color-on-surface-variant);--p-table-drag-handle-base-opacity: .92;--p-table-drag-handle-idle-bg: var(--md-sys-color-surface-container-low);--p-table-drag-handle-idle-border: var(--md-sys-color-outline-variant);--p-table-drag-handle-hover-bg: var(--md-sys-color-surface-container-high);--p-table-drag-handle-hover-border: var(--md-sys-color-outline);--p-table-drag-handle-active-bg: var(--md-sys-color-surface-container-highest);--p-table-drag-handle-active-border: var(--md-sys-color-primary);--p-table-drag-handle-focus-ring: var(--md-sys-color-primary);--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:1px solid var(--p-table-drag-handle-idle-border);background:var(--p-table-drag-handle-idle-bg);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:999px;cursor:inherit;pointer-events:none;touch-action:none;opacity:var(--p-table-drag-handle-base-opacity, .84);transform:none;transition:opacity var(--p-table-drag-handle-transition-duration, .16s) var(--p-table-motion-easing, cubic-bezier(0, 0, .2, 1)),transform var(--p-table-drag-handle-transition-duration, .16s) var(--p-table-motion-easing, cubic-bezier(0, 0, .2, 1)),background-color var(--p-table-drag-handle-transition-duration, .16s) var(--p-table-motion-easing, cubic-bezier(0, 0, .2, 1)),border-color 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-column-drag-handle:focus-visible{opacity:1;background:var(--p-table-drag-handle-hover-bg);border-color:var(--p-table-drag-handle-hover-border)}:host ::ng-deep .pfx-column-drag-enabled .mat-mdc-header-cell .praxis-column-drag-handle:focus-visible{outline:2px solid var(--p-table-drag-handle-focus-ring);outline-offset:2px}:host ::ng-deep .pfx-column-drag-enabled .mat-mdc-header-cell .praxis-column-drag-handle:active{background:var(--p-table-drag-handle-active-bg);border-color:var(--p-table-drag-handle-active-border);transform:scale(.97);cursor:grabbing}:host ::ng-deep .pfx-column-drag-enabled .mat-mdc-header-cell .praxis-column-drag-handle .mat-icon{font-size:18px;width:18px;height:18px;line-height:18px;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:translate(1px)}: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: 44px}}:host ::ng-deep .mat-mdc-cell{color:var(--p-table-text-color);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}: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: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.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$1.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)]] });
37806
+ ], 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: "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 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 @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 >\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 <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\">{{ getCellValue(element, column) }}</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 </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 [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)\"\n (dblclick)=\"onRowDoubleClicked(row, i)\"\n ></tr>\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)\"\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 <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 </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}:host.density-compact{--p-header-padding: 8px 12px;--p-actions-btn-size: 32px;--p-actions-icon-size: 18px}:host.density-comfortable{--p-header-padding: 12px 16px;--p-actions-btn-size: 40px;--p-actions-icon-size: 22px}:host.density-spacious{--p-header-padding: 16px 20px;--p-actions-btn-size: 44px;--p-actions-icon-size: 24px}:host.density-compact ::ng-deep .mat-mdc-cell{padding:8px 12px}:host.density-comfortable ::ng-deep .mat-mdc-cell{padding:12px 16px}:host.density-spacious ::ng-deep .mat-mdc-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);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}: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: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.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$1.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)]] });
37322
37807
  }
37323
- i0.ɵɵngDeclareClassMetadataAsync({ minVersion: "18.0.0", version: "20.1.4", ngImport: i0, type: PraxisTable, resolveDeferredDeps: () => [import('@praxisui/ai').then(m => m.PraxisAiAssistantComponent)], resolveMetadata: PraxisAiAssistantComponent => ({ decorators: [{
37808
+ 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: [{
37324
37809
  type: Component,
37325
37810
  args: [{ selector: 'praxis-table', imports: [
37326
37811
  CommonModule,
@@ -37349,7 +37834,7 @@ i0.ɵɵngDeclareClassMetadataAsync({ minVersion: "18.0.0", version: "20.1.4", ng
37349
37834
  TableDefaultsProvider,
37350
37835
  FilterConfigService,
37351
37836
  DataFormattingService
37352
- ], 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 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 @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 >\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 <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\">{{ getCellValue(element, column) }}</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 </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 [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)\"\n (dblclick)=\"onRowDoubleClicked(row, i)\"\n ></tr>\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)\"\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 <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 </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}:host.density-compact{--p-header-padding: 8px 12px;--p-actions-btn-size: 32px;--p-actions-icon-size: 18px}:host.density-comfortable{--p-header-padding: 12px 16px;--p-actions-btn-size: 40px;--p-actions-icon-size: 22px}:host.density-spacious{--p-header-padding: 16px 20px;--p-actions-btn-size: 44px;--p-actions-icon-size: 24px}:host.density-compact ::ng-deep .mat-mdc-cell{padding:8px 12px}:host.density-comfortable ::ng-deep .mat-mdc-cell{padding:12px 16px}:host.density-spacious ::ng-deep .mat-mdc-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{--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: 36px;--p-table-drag-handle-color: var(--md-sys-color-on-surface-variant);--p-table-drag-handle-base-opacity: .92;--p-table-drag-handle-idle-bg: var(--md-sys-color-surface-container-low);--p-table-drag-handle-idle-border: var(--md-sys-color-outline-variant);--p-table-drag-handle-hover-bg: var(--md-sys-color-surface-container-high);--p-table-drag-handle-hover-border: var(--md-sys-color-outline);--p-table-drag-handle-active-bg: var(--md-sys-color-surface-container-highest);--p-table-drag-handle-active-border: var(--md-sys-color-primary);--p-table-drag-handle-focus-ring: var(--md-sys-color-primary);--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:1px solid var(--p-table-drag-handle-idle-border);background:var(--p-table-drag-handle-idle-bg);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:999px;cursor:inherit;pointer-events:none;touch-action:none;opacity:var(--p-table-drag-handle-base-opacity, .84);transform:none;transition:opacity var(--p-table-drag-handle-transition-duration, .16s) var(--p-table-motion-easing, cubic-bezier(0, 0, .2, 1)),transform var(--p-table-drag-handle-transition-duration, .16s) var(--p-table-motion-easing, cubic-bezier(0, 0, .2, 1)),background-color var(--p-table-drag-handle-transition-duration, .16s) var(--p-table-motion-easing, cubic-bezier(0, 0, .2, 1)),border-color 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-column-drag-handle:focus-visible{opacity:1;background:var(--p-table-drag-handle-hover-bg);border-color:var(--p-table-drag-handle-hover-border)}:host ::ng-deep .pfx-column-drag-enabled .mat-mdc-header-cell .praxis-column-drag-handle:focus-visible{outline:2px solid var(--p-table-drag-handle-focus-ring);outline-offset:2px}:host ::ng-deep .pfx-column-drag-enabled .mat-mdc-header-cell .praxis-column-drag-handle:active{background:var(--p-table-drag-handle-active-bg);border-color:var(--p-table-drag-handle-active-border);transform:scale(.97);cursor:grabbing}:host ::ng-deep .pfx-column-drag-enabled .mat-mdc-header-cell .praxis-column-drag-handle .mat-icon{font-size:18px;width:18px;height:18px;line-height:18px;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:translate(1px)}: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: 44px}}:host ::ng-deep .mat-mdc-cell{color:var(--p-table-text-color);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}: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: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"] }]
37837
+ ], 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 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 @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 >\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 <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\">{{ getCellValue(element, column) }}</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 </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 [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)\"\n (dblclick)=\"onRowDoubleClicked(row, i)\"\n ></tr>\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)\"\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 <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 </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}:host.density-compact{--p-header-padding: 8px 12px;--p-actions-btn-size: 32px;--p-actions-icon-size: 18px}:host.density-comfortable{--p-header-padding: 12px 16px;--p-actions-btn-size: 40px;--p-actions-icon-size: 22px}:host.density-spacious{--p-header-padding: 16px 20px;--p-actions-btn-size: 44px;--p-actions-icon-size: 24px}:host.density-compact ::ng-deep .mat-mdc-cell{padding:8px 12px}:host.density-comfortable ::ng-deep .mat-mdc-cell{padding:12px 16px}:host.density-spacious ::ng-deep .mat-mdc-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);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}: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: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"] }]
37353
37838
  }], 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: [{
37354
37839
  type: Inject,
37355
37840
  args: [ASYNC_CONFIG_STORAGE]