@praxisui/table 1.0.0-beta.25 → 1.0.0-beta.28
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.
- package/fesm2022/{praxisui-table-filter-form-dialog-host.component-DI8aWSSJ.mjs → praxisui-table-filter-form-dialog-host.component-Du_IEq0W.mjs} +10 -2
- package/fesm2022/praxisui-table-filter-form-dialog-host.component-Du_IEq0W.mjs.map +1 -0
- package/fesm2022/praxisui-table.mjs +112 -15
- package/fesm2022/praxisui-table.mjs.map +1 -1
- package/index.d.ts +17 -1
- package/package.json +6 -6
- package/fesm2022/praxisui-table-filter-form-dialog-host.component-DI8aWSSJ.mjs.map +0 -1
|
@@ -409,7 +409,7 @@ class PraxisTableToolbar {
|
|
|
409
409
|
</div>
|
|
410
410
|
</div>
|
|
411
411
|
</mat-toolbar>
|
|
412
|
-
`, isInline: true, styles: [":host{display:block}:host(.debug-layout) .praxis-toolbar{outline:2px solid #ff4d4f}:host(.debug-layout) .toolbar-main{outline:1px dashed #3b82f6}:host(.debug-layout) .toolbar-actions{outline:1px dashed #22c55e}.praxis-toolbar{border-radius:12px 12px 0 0;background:transparent;box-shadow:none;padding:8px 12px;min-height:var(--pfx-filter-h, 44px);display:flex;flex-direction:row;align-items:
|
|
412
|
+
`, isInline: true, styles: [":host{display:block}:host(.debug-layout) .praxis-toolbar{outline:2px solid #ff4d4f}:host(.debug-layout) .toolbar-main{outline:1px dashed #3b82f6}:host(.debug-layout) .toolbar-actions{outline:1px dashed #22c55e}.praxis-toolbar{border-radius:12px 12px 0 0;background:transparent;box-shadow:none;padding:8px 12px;min-height:var(--pfx-filter-h, 44px);display:flex;flex-direction:row;align-items:flex-start;gap:8px;flex-wrap:wrap}.toolbar-main{display:flex;align-items:stretch;min-width:0;gap:8px;min-height:var(--pfx-filter-h, 44px);flex:1 0 100%}.toolbar-actions{display:flex;align-items:center;gap:8px;min-height:var(--pfx-filter-h, 44px);flex:0 0 auto}.actions-group{display:flex;align-items:center;gap:8px}.action-btn{height:40px}.pfx-tonal{background:var(--mat-sys-secondary-container, color-mix(in srgb, currentColor 12%, transparent));color:var(--mat-sys-on-secondary-container, currentColor)}.pfx-tonal:hover{background:color-mix(in srgb,var(--mat-sys-secondary-container, currentColor) 90%,black 0%)}.mobile-actions{display:none;align-items:center;gap:8px}.overflow-trigger{height:40px}.spacer{flex:1 1 auto;min-width:8px}.end-actions{display:flex;align-items:center;gap:8px}@media (min-width: 1024px){.toolbar-actions{justify-content:flex-end}.toolbar-actions .spacer{display:none}}@media (max-width: 1023px){.actions-group{display:none}.mobile-actions{display:flex}.toolbar-actions .spacer{flex:1 1 auto}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { 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: "ngmodule", type: MatIconModule }, { kind: "component", type: i4.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }, { kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i5.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.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i5.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }] });
|
|
413
413
|
}
|
|
414
414
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: PraxisTableToolbar, decorators: [{
|
|
415
415
|
type: Component,
|
|
@@ -616,7 +616,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImpor
|
|
|
616
616
|
</div>
|
|
617
617
|
</div>
|
|
618
618
|
</mat-toolbar>
|
|
619
|
-
`, host: { '[class.debug-layout]': 'debugLayout' }, styles: [":host{display:block}:host(.debug-layout) .praxis-toolbar{outline:2px solid #ff4d4f}:host(.debug-layout) .toolbar-main{outline:1px dashed #3b82f6}:host(.debug-layout) .toolbar-actions{outline:1px dashed #22c55e}.praxis-toolbar{border-radius:12px 12px 0 0;background:transparent;box-shadow:none;padding:8px 12px;min-height:var(--pfx-filter-h, 44px);display:flex;flex-direction:row;align-items:
|
|
619
|
+
`, host: { '[class.debug-layout]': 'debugLayout' }, styles: [":host{display:block}:host(.debug-layout) .praxis-toolbar{outline:2px solid #ff4d4f}:host(.debug-layout) .toolbar-main{outline:1px dashed #3b82f6}:host(.debug-layout) .toolbar-actions{outline:1px dashed #22c55e}.praxis-toolbar{border-radius:12px 12px 0 0;background:transparent;box-shadow:none;padding:8px 12px;min-height:var(--pfx-filter-h, 44px);display:flex;flex-direction:row;align-items:flex-start;gap:8px;flex-wrap:wrap}.toolbar-main{display:flex;align-items:stretch;min-width:0;gap:8px;min-height:var(--pfx-filter-h, 44px);flex:1 0 100%}.toolbar-actions{display:flex;align-items:center;gap:8px;min-height:var(--pfx-filter-h, 44px);flex:0 0 auto}.actions-group{display:flex;align-items:center;gap:8px}.action-btn{height:40px}.pfx-tonal{background:var(--mat-sys-secondary-container, color-mix(in srgb, currentColor 12%, transparent));color:var(--mat-sys-on-secondary-container, currentColor)}.pfx-tonal:hover{background:color-mix(in srgb,var(--mat-sys-secondary-container, currentColor) 90%,black 0%)}.mobile-actions{display:none;align-items:center;gap:8px}.overflow-trigger{height:40px}.spacer{flex:1 1 auto;min-width:8px}.end-actions{display:flex;align-items:center;gap:8px}@media (min-width: 1024px){.toolbar-actions{justify-content:flex-end}.toolbar-actions .spacer{display:none}}@media (max-width: 1023px){.actions-group{display:none}.mobile-actions{display:flex}.toolbar-actions .spacer{flex:1 1 auto}}\n"] }]
|
|
620
620
|
}], propDecorators: { config: [{
|
|
621
621
|
type: Input
|
|
622
622
|
}], debugLayout: [{
|
|
@@ -14168,6 +14168,7 @@ class FilterSettingsComponent {
|
|
|
14168
14168
|
overlayVariant: this.fb.nonNullable.control('card'),
|
|
14169
14169
|
overlayBackdrop: this.fb.nonNullable.control(true),
|
|
14170
14170
|
advancedOpenMode: this.fb.nonNullable.control('overlay'),
|
|
14171
|
+
showQuickFallback: this.fb.nonNullable.control(false),
|
|
14171
14172
|
});
|
|
14172
14173
|
this.canSave$ = this.form.valueChanges.pipe(map(() => this.form.dirty && this.form.valid), startWith(false));
|
|
14173
14174
|
// Expose state observables expected by SettingsPanel
|
|
@@ -14209,6 +14210,7 @@ class FilterSettingsComponent {
|
|
|
14209
14210
|
overlayVariant: this.injectedData.settings.overlayVariant ?? 'card',
|
|
14210
14211
|
overlayBackdrop: this.injectedData.settings.overlayBackdrop ?? true,
|
|
14211
14212
|
advancedOpenMode: this.injectedData.settings.advancedOpenMode ?? 'overlay',
|
|
14213
|
+
showQuickFallback: this.injectedData.settings.showQuickFallback ?? false,
|
|
14212
14214
|
});
|
|
14213
14215
|
}
|
|
14214
14216
|
if (this.injectedData.configKey) {
|
|
@@ -14427,6 +14429,7 @@ class FilterSettingsComponent {
|
|
|
14427
14429
|
overlayVariant: value.overlayVariant !== 'card' ? value.overlayVariant : undefined,
|
|
14428
14430
|
overlayBackdrop: value.overlayBackdrop !== true ? value.overlayBackdrop : undefined,
|
|
14429
14431
|
advancedOpenMode: value.advancedOpenMode !== 'overlay' ? value.advancedOpenMode : undefined,
|
|
14432
|
+
showQuickFallback: value.showQuickFallback ? true : undefined,
|
|
14430
14433
|
};
|
|
14431
14434
|
}
|
|
14432
14435
|
reset() {
|
|
@@ -14454,6 +14457,7 @@ class FilterSettingsComponent {
|
|
|
14454
14457
|
overlayVariant: this.initialSettings.overlayVariant ?? 'card',
|
|
14455
14458
|
overlayBackdrop: this.initialSettings.overlayBackdrop ?? true,
|
|
14456
14459
|
advancedOpenMode: this.initialSettings.advancedOpenMode ?? 'overlay',
|
|
14460
|
+
showQuickFallback: this.initialSettings.showQuickFallback ?? false,
|
|
14457
14461
|
});
|
|
14458
14462
|
}
|
|
14459
14463
|
clampDebounce(value) {
|
|
@@ -14473,7 +14477,7 @@ class FilterSettingsComponent {
|
|
|
14473
14477
|
return Math.min(4, Math.max(1, v));
|
|
14474
14478
|
}
|
|
14475
14479
|
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 });
|
|
14476
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.4", type: FilterSettingsComponent, isStandalone: true, selector: "filter-settings", inputs: { metadata: "metadata", settings: "settings", configKey: "configKey" }, outputs: { settingsChange: "settingsChange" }, usesOnChanges: true, ngImport: i0, template: "<form [formGroup]=\"form\">\n <mat-tab-group>\n <mat-tab label=\"Quick Field\">\n <mat-form-field appearance=\"outline\" class=\"full-width\">\n <mat-label>Quick Field</mat-label>\n <mat-select formControlName=\"quickField\">\n <mat-option [value]=\"meta.name\" *ngFor=\"let meta of metadata\">\n {{ meta.label || meta.name }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n </mat-tab>\n <mat-tab label=\"Always Visible\">\n <mat-form-field appearance=\"outline\" class=\"full-width\">\n <mat-label>Always Visible Fields</mat-label>\n <mat-select formControlName=\"alwaysVisibleFields\" multiple>\n <mat-option [value]=\"meta.name\" *ngFor=\"let meta of metadata\">\n {{ meta.label || meta.name }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n <div class=\"options\">\n <p><strong>Order (drag to reorder)</strong></p>\n <div cdkDropList (cdkDropListDropped)=\"dropAlwaysVisible($event)\" class=\"dnd-list\">\n <div class=\"dnd-item\" *ngFor=\"let name of form.controls.alwaysVisibleFields.value; let i = index\" cdkDrag>\n <mat-icon [praxisIcon]=\"'drag_indicator'\"></mat-icon>\n <span>{{ getFieldLabel(name) }}</span>\n </div>\n </div>\n </div>\n </mat-tab>\n <mat-tab label=\"Layout\">\n <div class=\"options\">\n <mat-form-field appearance=\"outline\" class=\"full-width\">\n <mat-label>Min width (px)</mat-label>\n <input matInput type=\"number\" formControlName=\"alwaysMinWidth\" min=\"240\" max=\"480\" />\n </mat-form-field>\n <mat-form-field appearance=\"outline\" class=\"full-width\">\n <mat-label>Columns \u2265600px</mat-label>\n <input matInput type=\"number\" formControlName=\"alwaysColsMd\" min=\"1\" max=\"3\" />\n </mat-form-field>\n <mat-form-field appearance=\"outline\" class=\"full-width\">\n <mat-label>Columns \u2265960px</mat-label>\n <input matInput type=\"number\" formControlName=\"alwaysColsLg\" min=\"1\" max=\"4\" />\n </mat-form-field>\n </div>\n </mat-tab>\n <mat-tab label=\"Booleans\">\n <div class=\"options\">\n <mat-checkbox formControlName=\"placeBooleansInActions\">Place toggles in actions</mat-checkbox>\n <mat-checkbox formControlName=\"showToggleLabels\">Show toggle labels</mat-checkbox>\n </div>\n </mat-tab>\n <mat-tab label=\"Options\">\n <div class=\"options\">\n <mat-form-field appearance=\"outline\" class=\"full-width\">\n <mat-label>Overlay theme</mat-label>\n <mat-select formControlName=\"overlayVariant\">\n <mat-option value=\"card\">Card</mat-option>\n <mat-option value=\"frosted\">Frosted</mat-option>\n </mat-select>\n </mat-form-field>\n <mat-checkbox formControlName=\"overlayBackdrop\">Overlay with backdrop</mat-checkbox>\n <mat-form-field appearance=\"outline\" class=\"full-width\">\n <mat-label>Advanced open mode</mat-label>\n <mat-select formControlName=\"advancedOpenMode\">\n <mat-option value=\"overlay\">Overlay (default)</mat-option>\n <mat-option value=\"modal\">Modal</mat-option>\n <mat-option value=\"drawer\">Drawer (right)</mat-option>\n </mat-select>\n </mat-form-field>\n <mat-form-field appearance=\"outline\" class=\"full-width\">\n <mat-label>Placeholder</mat-label>\n <input matInput formControlName=\"placeholder\" />\n </mat-form-field>\n <mat-checkbox formControlName=\"showAdvanced\"\n >Show Advanced</mat-checkbox\n >\n <mat-checkbox formControlName=\"autoSummary\">Enable auto summary</mat-checkbox>\n <mat-checkbox formControlName=\"confirmTagDelete\">Confirm tag delete</mat-checkbox>\n <div class=\"options\">\n <h4>Tag theme</h4>\n <mat-form-field appearance=\"outline\">\n <mat-label>Tag color</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 </mat-form-field>\n <mat-form-field appearance=\"outline\">\n <mat-label>Tag variant</mat-label>\n <mat-select formControlName=\"tagVariant\">\n <mat-option value=\"filled\">Filled</mat-option>\n <mat-option value=\"outlined\">Outlined</mat-option>\n </mat-select>\n </mat-form-field>\n <mat-form-field appearance=\"outline\">\n <mat-label>Button color</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 </mat-form-field>\n </div>\n <div class=\"options\">\n <h4>Action buttons theme</h4>\n <mat-form-field appearance=\"outline\">\n <mat-label>Buttons color</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>Buttons variant</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 <div class=\"options\">\n <h4>Theme presets</h4>\n <div class=\"preset-row\">\n <button mat-stroked-button *ngFor=\"let p of presets\" (click)=\"applyPreset(p.key)\">{{ p.label }}</button>\n </div>\n </div>\n </div>\n </mat-tab>\n <mat-tab label=\"i18n\">\n <div class=\"options\">\n <mat-form-field appearance=\"outline\" class=\"full-width\">\n <mat-label>Search placeholder</mat-label>\n <input matInput [value]=\"settings?.placeholder || ''\" disabled />\n <mat-hint>Placeholder do quick (integra com i18n no futuro)</mat-hint>\n </mat-form-field>\n <!-- Espa\u00E7o reservado para i18n granular, se necess\u00E1rio -->\n </div>\n </mat-tab>\n <mat-tab label=\"Tags\" *ngIf=\"configKey\">\n <div class=\"options\">\n <div class=\"tags-header\">\n <span><strong>Saved tags</strong></span>\n <span class=\"spacer\"></span>\n <button mat-stroked-button color=\"warn\" (click)=\"clearTags()\">Clear all</button>\n </div>\n <div class=\"new-tag\">\n <mat-form-field appearance=\"outline\" class=\"full-width\">\n <mat-label>New tag label</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, optional)</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()\">Add</button>\n <button mat-stroked-button (click)=\"addTagFromCurrent()\" *ngIf=\"hasCurrentDto()\">Add from current filters</button>\n </div>\n </div>\n <mat-list>\n <mat-list-item *ngFor=\"let t of tags; index as i\">\n <span matListItemTitle>{{ t.label }}</span>\n <span matListItemLine>{{ t.id }}</span>\n <button mat-icon-button (click)=\"removeTag(i)\" matTooltip=\"Delete\">\n <mat-icon [praxisIcon]=\"'delete'\"></mat-icon>\n </button>\n <button mat-icon-button (click)=\"renameTagPrompt(i)\" matTooltip=\"Rename\">\n <mat-icon [praxisIcon]=\"'edit'\"></mat-icon>\n </button>\n </mat-list-item>\n </mat-list>\n <mat-form-field appearance=\"outline\" class=\"full-width\">\n <mat-label>Import/Export JSON</mat-label>\n <textarea matInput rows=\"6\" [(ngModel)]=\"exportJson\" [ngModelOptions]=\"{standalone: true}\"></textarea>\n </mat-form-field>\n <div>\n <button mat-stroked-button color=\"primary\" (click)=\"importTags()\">Import</button>\n <button mat-stroked-button (click)=\"loadTags()\">Reload</button>\n <button mat-stroked-button (click)=\"saveTags()\">Save</button>\n </div>\n </div>\n </mat-tab>\n <mat-tab label=\"Behavior\">\n <div class=\"options\">\n <mat-form-field appearance=\"outline\" class=\"full-width\">\n <mat-label>Mode</mat-label>\n <mat-select formControlName=\"mode\">\n <mat-option value=\"auto\">Auto</mat-option>\n <mat-option value=\"filter\">Filter</mat-option>\n <mat-option value=\"card\">Card</mat-option>\n </mat-select>\n </mat-form-field>\n <mat-checkbox formControlName=\"allowSaveTags\"\n >Allow Save Tags</mat-checkbox\n >\n <mat-checkbox formControlName=\"debugLayout\">Show debug layout</mat-checkbox>\n </div>\n </mat-tab>\n <mat-tab label=\"Advanced\">\n <div class=\"options\">\n <mat-form-field appearance=\"outline\" class=\"full-width\">\n <mat-label>Change Debounce (ms)</mat-label>\n <input\n matInput\n type=\"number\"\n formControlName=\"changeDebounceMs\"\n min=\"100\"\n max=\"1000\"\n />\n <mat-error *ngIf=\"form.controls.changeDebounceMs.invalid\">\n Value must be between 100 and 1000\n </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 Reset filter preferences\n </button>\n </div>\n </div>\n </mat-tab>\n </mat-tab-group>\n</form>\n", styles: [".full-width{width:100%}.options{display:flex;flex-direction:column;gap:1rem;padding:1rem 0}.dnd-list{display:flex;flex-direction:column;gap:6px}.dnd-item{display:flex;align-items:center;gap:8px;padding:6px 8px;border:1px dashed rgba(255,255,255,.15);border-radius:6px;cursor:grab}.dnd-item mat-icon{opacity:.8}.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}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.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$1.MatTab, selector: "mat-tab", inputs: ["disabled", "label", "aria-label", "aria-labelledby", "labelClass", "bodyClass", "id"], exportAs: ["matTab"] }, { kind: "component", type: i4$1.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: i3$1.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i3$1.MatLabel, selector: "mat-label" }, { kind: "directive", type: i3$1.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "directive", type: i3$1.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i5$1.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i5$1.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i6.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: i8$1.MatList, selector: "mat-list", exportAs: ["matList"] }, { kind: "component", type: i8$1.MatListItem, selector: "mat-list-item, a[mat-list-item], button[mat-list-item]", inputs: ["activated"], exportAs: ["matListItem"] }, { kind: "directive", type: i8$1.MatListItemLine, selector: "[matListItemLine]" }, { kind: "directive", type: i8$1.MatListItemTitle, selector: "[matListItemTitle]" }, { 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: i4.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: i17.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: i17.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"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
14480
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.4", type: FilterSettingsComponent, isStandalone: true, selector: "filter-settings", inputs: { metadata: "metadata", settings: "settings", configKey: "configKey" }, outputs: { settingsChange: "settingsChange" }, usesOnChanges: true, ngImport: i0, template: "<form [formGroup]=\"form\">\n <mat-tab-group>\n <mat-tab label=\"Campo R\u00E1pido\">\n <mat-form-field appearance=\"outline\" class=\"full-width\">\n <mat-label>Quick Field</mat-label>\n <mat-select formControlName=\"quickField\">\n <mat-option [value]=\"meta.name\" *ngFor=\"let meta of metadata\">\n {{ meta.label || meta.name }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n </mat-tab>\n <mat-tab label=\"Sempre Vis\u00EDveis\">\n <mat-form-field appearance=\"outline\" class=\"full-width\">\n <mat-label>Always Visible Fields</mat-label>\n <mat-select formControlName=\"alwaysVisibleFields\" multiple>\n <mat-option [value]=\"meta.name\" *ngFor=\"let meta of metadata\">\n {{ meta.label || meta.name }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n <div class=\"options\">\n <p><strong>Ordem (arraste para reordenar)</strong></p>\n <div cdkDropList (cdkDropListDropped)=\"dropAlwaysVisible($event)\" class=\"dnd-list\">\n <div class=\"dnd-item\" *ngFor=\"let name of form.controls.alwaysVisibleFields.value; let i = index\" cdkDrag>\n <mat-icon [praxisIcon]=\"'drag_indicator'\"></mat-icon>\n <span>{{ getFieldLabel(name) }}</span>\n </div>\n </div>\n </div>\n </mat-tab>\n <mat-tab label=\"Layout\">\n <div class=\"options\">\n <mat-form-field appearance=\"outline\" class=\"full-width\">\n <mat-label>Largura m\u00EDnima (px)</mat-label>\n <input matInput type=\"number\" formControlName=\"alwaysMinWidth\" min=\"240\" max=\"480\" />\n </mat-form-field>\n <mat-form-field appearance=\"outline\" class=\"full-width\">\n <mat-label>Colunas \u2265600px</mat-label>\n <input matInput type=\"number\" formControlName=\"alwaysColsMd\" min=\"1\" max=\"3\" />\n </mat-form-field>\n <mat-form-field appearance=\"outline\" class=\"full-width\">\n <mat-label>Colunas \u2265960px</mat-label>\n <input matInput type=\"number\" formControlName=\"alwaysColsLg\" min=\"1\" max=\"4\" />\n </mat-form-field>\n </div>\n </mat-tab>\n <mat-tab label=\"Alternadores\">\n <div class=\"options\">\n <mat-checkbox formControlName=\"placeBooleansInActions\">Colocar alternadores na \u00E1rea de a\u00E7\u00F5es</mat-checkbox>\n <mat-checkbox formControlName=\"showToggleLabels\">Mostrar r\u00F3tulos dos alternadores</mat-checkbox>\n </div>\n </mat-tab>\n <mat-tab label=\"Op\u00E7\u00F5es\">\n <div class=\"options\">\n <mat-form-field appearance=\"outline\" class=\"full-width\">\n <mat-label>Tema do overlay</mat-label>\n <mat-select formControlName=\"overlayVariant\">\n <mat-option value=\"card\">Card</mat-option>\n <mat-option value=\"frosted\">Frosted</mat-option>\n </mat-select>\n </mat-form-field>\n <mat-checkbox formControlName=\"overlayBackdrop\">Overlay com backdrop</mat-checkbox>\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=\"overlay\">Overlay (default)</mat-option>\n <mat-option value=\"modal\">Modal</mat-option>\n <mat-option value=\"drawer\">Drawer (right)</mat-option>\n </mat-select>\n </mat-form-field>\n <mat-checkbox formControlName=\"showQuickFallback\">Mostrar \"Buscar\" quando n\u00E3o houver Quick</mat-checkbox>\n <mat-form-field appearance=\"outline\" class=\"full-width\">\n <mat-label>Placeholder da busca</mat-label>\n <input matInput formControlName=\"placeholder\" placeholder=\"Ex.: Buscar por nome\" />\n </mat-form-field>\n <mat-checkbox formControlName=\"showAdvanced\"\n >Mostrar Avan\u00E7ado</mat-checkbox\n >\n <mat-checkbox formControlName=\"autoSummary\">Ativar resumo autom\u00E1tico</mat-checkbox>\n <mat-checkbox formControlName=\"confirmTagDelete\">Confirmar exclus\u00E3o de atalho</mat-checkbox>\n <div class=\"options\">\n <h4>Tema das tags</h4>\n <mat-form-field appearance=\"outline\">\n <mat-label>Cor da tag</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 </mat-form-field>\n <mat-form-field appearance=\"outline\">\n <mat-label>Variante da tag</mat-label>\n <mat-select formControlName=\"tagVariant\">\n <mat-option value=\"filled\">Filled</mat-option>\n <mat-option value=\"outlined\">Outlined</mat-option>\n </mat-select>\n </mat-form-field>\n <mat-form-field appearance=\"outline\">\n <mat-label>Cor dos bot\u00F5es</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 </mat-form-field>\n </div>\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 <div class=\"options\">\n <h4>Predefini\u00E7\u00F5es de tema</h4>\n <div class=\"preset-row\">\n <button mat-stroked-button *ngFor=\"let p of presets\" (click)=\"applyPreset(p.key)\">{{ p.label }}</button>\n </div>\n </div>\n </div>\n </mat-tab>\n <mat-tab label=\"i18n\">\n <div class=\"options\">\n <mat-form-field appearance=\"outline\" class=\"full-width\">\n <mat-label>Placeholder da busca</mat-label>\n <input matInput [value]=\"settings?.placeholder || ''\" disabled />\n <mat-hint>Placeholder do Campo R\u00E1pido (integra com i18n futuramente)</mat-hint>\n </mat-form-field>\n <!-- Espa\u00E7o reservado para i18n granular, se necess\u00E1rio -->\n </div>\n </mat-tab>\n <mat-tab label=\"Atalhos\" *ngIf=\"configKey\">\n <div class=\"options\">\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 <button mat-stroked-button (click)=\"addTagFromCurrent()\" *ngIf=\"hasCurrentDto()\">Adicionar a partir dos filtros atuais</button>\n </div>\n </div>\n <mat-list>\n <mat-list-item *ngFor=\"let t of tags; index as i\">\n <span matListItemTitle>{{ t.label }}</span>\n <span matListItemLine>{{ t.id }}</span>\n <button mat-icon-button (click)=\"removeTag(i)\" matTooltip=\"Delete\">\n <mat-icon [praxisIcon]=\"'delete'\"></mat-icon>\n </button>\n <button mat-icon-button (click)=\"renameTagPrompt(i)\" matTooltip=\"Rename\">\n <mat-icon [praxisIcon]=\"'edit'\"></mat-icon>\n </button>\n </mat-list-item>\n </mat-list>\n <mat-form-field appearance=\"outline\" class=\"full-width\">\n <mat-label>Importar/Exportar JSON</mat-label>\n <textarea matInput rows=\"6\" [(ngModel)]=\"exportJson\" [ngModelOptions]=\"{standalone: true}\"></textarea>\n </mat-form-field>\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 </mat-tab>\n <mat-tab label=\"Comportamento\">\n <div class=\"options\">\n <mat-form-field appearance=\"outline\" class=\"full-width\">\n <mat-label>Modo</mat-label>\n <mat-select formControlName=\"mode\">\n <mat-option value=\"auto\">Auto</mat-option>\n <mat-option value=\"filter\">Filter</mat-option>\n <mat-option value=\"card\">Card</mat-option>\n </mat-select>\n </mat-form-field>\n <mat-checkbox formControlName=\"allowSaveTags\"\n >Permitir salvar atalhos</mat-checkbox\n >\n <mat-checkbox formControlName=\"debugLayout\">Mostrar depura\u00E7\u00E3o de layout</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\n matInput\n type=\"number\"\n formControlName=\"changeDebounceMs\"\n min=\"100\"\n max=\"1000\"\n />\n <mat-error *ngIf=\"form.controls.changeDebounceMs.invalid\">\n Value must be between 100 and 1000\n </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 </div>\n </div>\n </mat-tab>\n </mat-tab-group>\n</form>\n", styles: [".full-width{width:100%}.options{display:flex;flex-direction:column;gap:1rem;padding:1rem 0}.dnd-list{display:flex;flex-direction:column;gap:6px}.dnd-item{display:flex;align-items:center;gap:8px;padding:6px 8px;border:1px dashed rgba(255,255,255,.15);border-radius:6px;cursor:grab}.dnd-item mat-icon{opacity:.8}.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}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.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$1.MatTab, selector: "mat-tab", inputs: ["disabled", "label", "aria-label", "aria-labelledby", "labelClass", "bodyClass", "id"], exportAs: ["matTab"] }, { kind: "component", type: i4$1.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: i3$1.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i3$1.MatLabel, selector: "mat-label" }, { kind: "directive", type: i3$1.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "directive", type: i3$1.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i5$1.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i5$1.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i6.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: i8$1.MatList, selector: "mat-list", exportAs: ["matList"] }, { kind: "component", type: i8$1.MatListItem, selector: "mat-list-item, a[mat-list-item], button[mat-list-item]", inputs: ["activated"], exportAs: ["matListItem"] }, { kind: "directive", type: i8$1.MatListItemLine, selector: "[matListItemLine]" }, { kind: "directive", type: i8$1.MatListItemTitle, selector: "[matListItemTitle]" }, { 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: i4.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: i17.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: i17.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"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
14477
14481
|
}
|
|
14478
14482
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: FilterSettingsComponent, decorators: [{
|
|
14479
14483
|
type: Component,
|
|
@@ -14491,7 +14495,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImpor
|
|
|
14491
14495
|
MatIconModule,
|
|
14492
14496
|
PraxisIconDirective,
|
|
14493
14497
|
DragDropModule,
|
|
14494
|
-
], template: "<form [formGroup]=\"form\">\n <mat-tab-group>\n <mat-tab label=\"Quick Field\">\n <mat-form-field appearance=\"outline\" class=\"full-width\">\n <mat-label>Quick Field</mat-label>\n <mat-select formControlName=\"quickField\">\n <mat-option [value]=\"meta.name\" *ngFor=\"let meta of metadata\">\n {{ meta.label || meta.name }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n </mat-tab>\n <mat-tab label=\"Always Visible\">\n <mat-form-field appearance=\"outline\" class=\"full-width\">\n <mat-label>Always Visible Fields</mat-label>\n <mat-select formControlName=\"alwaysVisibleFields\" multiple>\n <mat-option [value]=\"meta.name\" *ngFor=\"let meta of metadata\">\n {{ meta.label || meta.name }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n <div class=\"options\">\n <p><strong>Order (drag to reorder)</strong></p>\n <div cdkDropList (cdkDropListDropped)=\"dropAlwaysVisible($event)\" class=\"dnd-list\">\n <div class=\"dnd-item\" *ngFor=\"let name of form.controls.alwaysVisibleFields.value; let i = index\" cdkDrag>\n <mat-icon [praxisIcon]=\"'drag_indicator'\"></mat-icon>\n <span>{{ getFieldLabel(name) }}</span>\n </div>\n </div>\n </div>\n </mat-tab>\n <mat-tab label=\"Layout\">\n <div class=\"options\">\n <mat-form-field appearance=\"outline\" class=\"full-width\">\n <mat-label>Min width (px)</mat-label>\n <input matInput type=\"number\" formControlName=\"alwaysMinWidth\" min=\"240\" max=\"480\" />\n </mat-form-field>\n <mat-form-field appearance=\"outline\" class=\"full-width\">\n <mat-label>Columns \u2265600px</mat-label>\n <input matInput type=\"number\" formControlName=\"alwaysColsMd\" min=\"1\" max=\"3\" />\n </mat-form-field>\n <mat-form-field appearance=\"outline\" class=\"full-width\">\n <mat-label>Columns \u2265960px</mat-label>\n <input matInput type=\"number\" formControlName=\"alwaysColsLg\" min=\"1\" max=\"4\" />\n </mat-form-field>\n </div>\n </mat-tab>\n <mat-tab label=\"Booleans\">\n <div class=\"options\">\n <mat-checkbox formControlName=\"placeBooleansInActions\">Place toggles in actions</mat-checkbox>\n <mat-checkbox formControlName=\"showToggleLabels\">Show toggle labels</mat-checkbox>\n </div>\n </mat-tab>\n <mat-tab label=\"Options\">\n <div class=\"options\">\n <mat-form-field appearance=\"outline\" class=\"full-width\">\n <mat-label>Overlay theme</mat-label>\n <mat-select formControlName=\"overlayVariant\">\n <mat-option value=\"card\">Card</mat-option>\n <mat-option value=\"frosted\">Frosted</mat-option>\n </mat-select>\n </mat-form-field>\n <mat-checkbox formControlName=\"overlayBackdrop\">Overlay with backdrop</mat-checkbox>\n <mat-form-field appearance=\"outline\" class=\"full-width\">\n <mat-label>Advanced open mode</mat-label>\n <mat-select formControlName=\"advancedOpenMode\">\n <mat-option value=\"overlay\">Overlay (default)</mat-option>\n <mat-option value=\"modal\">Modal</mat-option>\n <mat-option value=\"drawer\">Drawer (right)</mat-option>\n </mat-select>\n </mat-form-field>\n <mat-form-field appearance=\"outline\" class=\"full-width\">\n <mat-label>Placeholder</mat-label>\n <input matInput formControlName=\"placeholder\" />\n </mat-form-field>\n <mat-checkbox formControlName=\"showAdvanced\"\n >Show Advanced</mat-checkbox\n >\n <mat-checkbox formControlName=\"autoSummary\">Enable auto summary</mat-checkbox>\n <mat-checkbox formControlName=\"confirmTagDelete\">Confirm tag delete</mat-checkbox>\n <div class=\"options\">\n <h4>Tag theme</h4>\n <mat-form-field appearance=\"outline\">\n <mat-label>Tag color</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 </mat-form-field>\n <mat-form-field appearance=\"outline\">\n <mat-label>Tag variant</mat-label>\n <mat-select formControlName=\"tagVariant\">\n <mat-option value=\"filled\">Filled</mat-option>\n <mat-option value=\"outlined\">Outlined</mat-option>\n </mat-select>\n </mat-form-field>\n <mat-form-field appearance=\"outline\">\n <mat-label>Button color</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 </mat-form-field>\n </div>\n <div class=\"options\">\n <h4>Action buttons theme</h4>\n <mat-form-field appearance=\"outline\">\n <mat-label>Buttons color</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>Buttons variant</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 <div class=\"options\">\n <h4>Theme presets</h4>\n <div class=\"preset-row\">\n <button mat-stroked-button *ngFor=\"let p of presets\" (click)=\"applyPreset(p.key)\">{{ p.label }}</button>\n </div>\n </div>\n </div>\n </mat-tab>\n <mat-tab label=\"i18n\">\n <div class=\"options\">\n <mat-form-field appearance=\"outline\" class=\"full-width\">\n <mat-label>Search placeholder</mat-label>\n <input matInput [value]=\"settings?.placeholder || ''\" disabled />\n <mat-hint>Placeholder do quick (integra com i18n no futuro)</mat-hint>\n </mat-form-field>\n <!-- Espa\u00E7o reservado para i18n granular, se necess\u00E1rio -->\n </div>\n </mat-tab>\n <mat-tab label=\"Tags\" *ngIf=\"configKey\">\n <div class=\"options\">\n <div class=\"tags-header\">\n <span><strong>Saved tags</strong></span>\n <span class=\"spacer\"></span>\n <button mat-stroked-button color=\"warn\" (click)=\"clearTags()\">Clear all</button>\n </div>\n <div class=\"new-tag\">\n <mat-form-field appearance=\"outline\" class=\"full-width\">\n <mat-label>New tag label</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, optional)</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()\">Add</button>\n <button mat-stroked-button (click)=\"addTagFromCurrent()\" *ngIf=\"hasCurrentDto()\">Add from current filters</button>\n </div>\n </div>\n <mat-list>\n <mat-list-item *ngFor=\"let t of tags; index as i\">\n <span matListItemTitle>{{ t.label }}</span>\n <span matListItemLine>{{ t.id }}</span>\n <button mat-icon-button (click)=\"removeTag(i)\" matTooltip=\"Delete\">\n <mat-icon [praxisIcon]=\"'delete'\"></mat-icon>\n </button>\n <button mat-icon-button (click)=\"renameTagPrompt(i)\" matTooltip=\"Rename\">\n <mat-icon [praxisIcon]=\"'edit'\"></mat-icon>\n </button>\n </mat-list-item>\n </mat-list>\n <mat-form-field appearance=\"outline\" class=\"full-width\">\n <mat-label>Import/Export JSON</mat-label>\n <textarea matInput rows=\"6\" [(ngModel)]=\"exportJson\" [ngModelOptions]=\"{standalone: true}\"></textarea>\n </mat-form-field>\n <div>\n <button mat-stroked-button color=\"primary\" (click)=\"importTags()\">Import</button>\n <button mat-stroked-button (click)=\"loadTags()\">Reload</button>\n <button mat-stroked-button (click)=\"saveTags()\">Save</button>\n </div>\n </div>\n </mat-tab>\n <mat-tab label=\"Behavior\">\n <div class=\"options\">\n <mat-form-field appearance=\"outline\" class=\"full-width\">\n <mat-label>Mode</mat-label>\n <mat-select formControlName=\"mode\">\n <mat-option value=\"auto\">Auto</mat-option>\n <mat-option value=\"filter\">Filter</mat-option>\n <mat-option value=\"card\">Card</mat-option>\n </mat-select>\n </mat-form-field>\n <mat-checkbox formControlName=\"allowSaveTags\"\n >Allow Save Tags</mat-checkbox\n >\n <mat-checkbox formControlName=\"debugLayout\">Show debug layout</mat-checkbox>\n </div>\n </mat-tab>\n <mat-tab label=\"Advanced\">\n <div class=\"options\">\n <mat-form-field appearance=\"outline\" class=\"full-width\">\n <mat-label>Change Debounce (ms)</mat-label>\n <input\n matInput\n type=\"number\"\n formControlName=\"changeDebounceMs\"\n min=\"100\"\n max=\"1000\"\n />\n <mat-error *ngIf=\"form.controls.changeDebounceMs.invalid\">\n Value must be between 100 and 1000\n </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 Reset filter preferences\n </button>\n </div>\n </div>\n </mat-tab>\n </mat-tab-group>\n</form>\n", styles: [".full-width{width:100%}.options{display:flex;flex-direction:column;gap:1rem;padding:1rem 0}.dnd-list{display:flex;flex-direction:column;gap:6px}.dnd-item{display:flex;align-items:center;gap:8px;padding:6px 8px;border:1px dashed rgba(255,255,255,.15);border-radius:6px;cursor:grab}.dnd-item mat-icon{opacity:.8}.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}\n"] }]
|
|
14498
|
+
], template: "<form [formGroup]=\"form\">\n <mat-tab-group>\n <mat-tab label=\"Campo R\u00E1pido\">\n <mat-form-field appearance=\"outline\" class=\"full-width\">\n <mat-label>Quick Field</mat-label>\n <mat-select formControlName=\"quickField\">\n <mat-option [value]=\"meta.name\" *ngFor=\"let meta of metadata\">\n {{ meta.label || meta.name }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n </mat-tab>\n <mat-tab label=\"Sempre Vis\u00EDveis\">\n <mat-form-field appearance=\"outline\" class=\"full-width\">\n <mat-label>Always Visible Fields</mat-label>\n <mat-select formControlName=\"alwaysVisibleFields\" multiple>\n <mat-option [value]=\"meta.name\" *ngFor=\"let meta of metadata\">\n {{ meta.label || meta.name }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n <div class=\"options\">\n <p><strong>Ordem (arraste para reordenar)</strong></p>\n <div cdkDropList (cdkDropListDropped)=\"dropAlwaysVisible($event)\" class=\"dnd-list\">\n <div class=\"dnd-item\" *ngFor=\"let name of form.controls.alwaysVisibleFields.value; let i = index\" cdkDrag>\n <mat-icon [praxisIcon]=\"'drag_indicator'\"></mat-icon>\n <span>{{ getFieldLabel(name) }}</span>\n </div>\n </div>\n </div>\n </mat-tab>\n <mat-tab label=\"Layout\">\n <div class=\"options\">\n <mat-form-field appearance=\"outline\" class=\"full-width\">\n <mat-label>Largura m\u00EDnima (px)</mat-label>\n <input matInput type=\"number\" formControlName=\"alwaysMinWidth\" min=\"240\" max=\"480\" />\n </mat-form-field>\n <mat-form-field appearance=\"outline\" class=\"full-width\">\n <mat-label>Colunas \u2265600px</mat-label>\n <input matInput type=\"number\" formControlName=\"alwaysColsMd\" min=\"1\" max=\"3\" />\n </mat-form-field>\n <mat-form-field appearance=\"outline\" class=\"full-width\">\n <mat-label>Colunas \u2265960px</mat-label>\n <input matInput type=\"number\" formControlName=\"alwaysColsLg\" min=\"1\" max=\"4\" />\n </mat-form-field>\n </div>\n </mat-tab>\n <mat-tab label=\"Alternadores\">\n <div class=\"options\">\n <mat-checkbox formControlName=\"placeBooleansInActions\">Colocar alternadores na \u00E1rea de a\u00E7\u00F5es</mat-checkbox>\n <mat-checkbox formControlName=\"showToggleLabels\">Mostrar r\u00F3tulos dos alternadores</mat-checkbox>\n </div>\n </mat-tab>\n <mat-tab label=\"Op\u00E7\u00F5es\">\n <div class=\"options\">\n <mat-form-field appearance=\"outline\" class=\"full-width\">\n <mat-label>Tema do overlay</mat-label>\n <mat-select formControlName=\"overlayVariant\">\n <mat-option value=\"card\">Card</mat-option>\n <mat-option value=\"frosted\">Frosted</mat-option>\n </mat-select>\n </mat-form-field>\n <mat-checkbox formControlName=\"overlayBackdrop\">Overlay com backdrop</mat-checkbox>\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=\"overlay\">Overlay (default)</mat-option>\n <mat-option value=\"modal\">Modal</mat-option>\n <mat-option value=\"drawer\">Drawer (right)</mat-option>\n </mat-select>\n </mat-form-field>\n <mat-checkbox formControlName=\"showQuickFallback\">Mostrar \"Buscar\" quando n\u00E3o houver Quick</mat-checkbox>\n <mat-form-field appearance=\"outline\" class=\"full-width\">\n <mat-label>Placeholder da busca</mat-label>\n <input matInput formControlName=\"placeholder\" placeholder=\"Ex.: Buscar por nome\" />\n </mat-form-field>\n <mat-checkbox formControlName=\"showAdvanced\"\n >Mostrar Avan\u00E7ado</mat-checkbox\n >\n <mat-checkbox formControlName=\"autoSummary\">Ativar resumo autom\u00E1tico</mat-checkbox>\n <mat-checkbox formControlName=\"confirmTagDelete\">Confirmar exclus\u00E3o de atalho</mat-checkbox>\n <div class=\"options\">\n <h4>Tema das tags</h4>\n <mat-form-field appearance=\"outline\">\n <mat-label>Cor da tag</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 </mat-form-field>\n <mat-form-field appearance=\"outline\">\n <mat-label>Variante da tag</mat-label>\n <mat-select formControlName=\"tagVariant\">\n <mat-option value=\"filled\">Filled</mat-option>\n <mat-option value=\"outlined\">Outlined</mat-option>\n </mat-select>\n </mat-form-field>\n <mat-form-field appearance=\"outline\">\n <mat-label>Cor dos bot\u00F5es</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 </mat-form-field>\n </div>\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 <div class=\"options\">\n <h4>Predefini\u00E7\u00F5es de tema</h4>\n <div class=\"preset-row\">\n <button mat-stroked-button *ngFor=\"let p of presets\" (click)=\"applyPreset(p.key)\">{{ p.label }}</button>\n </div>\n </div>\n </div>\n </mat-tab>\n <mat-tab label=\"i18n\">\n <div class=\"options\">\n <mat-form-field appearance=\"outline\" class=\"full-width\">\n <mat-label>Placeholder da busca</mat-label>\n <input matInput [value]=\"settings?.placeholder || ''\" disabled />\n <mat-hint>Placeholder do Campo R\u00E1pido (integra com i18n futuramente)</mat-hint>\n </mat-form-field>\n <!-- Espa\u00E7o reservado para i18n granular, se necess\u00E1rio -->\n </div>\n </mat-tab>\n <mat-tab label=\"Atalhos\" *ngIf=\"configKey\">\n <div class=\"options\">\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 <button mat-stroked-button (click)=\"addTagFromCurrent()\" *ngIf=\"hasCurrentDto()\">Adicionar a partir dos filtros atuais</button>\n </div>\n </div>\n <mat-list>\n <mat-list-item *ngFor=\"let t of tags; index as i\">\n <span matListItemTitle>{{ t.label }}</span>\n <span matListItemLine>{{ t.id }}</span>\n <button mat-icon-button (click)=\"removeTag(i)\" matTooltip=\"Delete\">\n <mat-icon [praxisIcon]=\"'delete'\"></mat-icon>\n </button>\n <button mat-icon-button (click)=\"renameTagPrompt(i)\" matTooltip=\"Rename\">\n <mat-icon [praxisIcon]=\"'edit'\"></mat-icon>\n </button>\n </mat-list-item>\n </mat-list>\n <mat-form-field appearance=\"outline\" class=\"full-width\">\n <mat-label>Importar/Exportar JSON</mat-label>\n <textarea matInput rows=\"6\" [(ngModel)]=\"exportJson\" [ngModelOptions]=\"{standalone: true}\"></textarea>\n </mat-form-field>\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 </mat-tab>\n <mat-tab label=\"Comportamento\">\n <div class=\"options\">\n <mat-form-field appearance=\"outline\" class=\"full-width\">\n <mat-label>Modo</mat-label>\n <mat-select formControlName=\"mode\">\n <mat-option value=\"auto\">Auto</mat-option>\n <mat-option value=\"filter\">Filter</mat-option>\n <mat-option value=\"card\">Card</mat-option>\n </mat-select>\n </mat-form-field>\n <mat-checkbox formControlName=\"allowSaveTags\"\n >Permitir salvar atalhos</mat-checkbox\n >\n <mat-checkbox formControlName=\"debugLayout\">Mostrar depura\u00E7\u00E3o de layout</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\n matInput\n type=\"number\"\n formControlName=\"changeDebounceMs\"\n min=\"100\"\n max=\"1000\"\n />\n <mat-error *ngIf=\"form.controls.changeDebounceMs.invalid\">\n Value must be between 100 and 1000\n </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 </div>\n </div>\n </mat-tab>\n </mat-tab-group>\n</form>\n", styles: [".full-width{width:100%}.options{display:flex;flex-direction:column;gap:1rem;padding:1rem 0}.dnd-list{display:flex;flex-direction:column;gap:6px}.dnd-item{display:flex;align-items:center;gap:8px;padding:6px 8px;border:1px dashed rgba(255,255,255,.15);border-radius:6px;cursor:grab}.dnd-item mat-icon{opacity:.8}.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}\n"] }]
|
|
14495
14499
|
}], ctorParameters: () => [{ type: i1$1.FormBuilder }], propDecorators: { metadata: [{
|
|
14496
14500
|
type: Input
|
|
14497
14501
|
}], settings: [{
|
|
@@ -19595,6 +19599,8 @@ class PraxisFilter {
|
|
|
19595
19599
|
changeDebounceMs = 300;
|
|
19596
19600
|
/** Controla a exibição do botão de configurações dentro do filtro */
|
|
19597
19601
|
showFilterSettings = false;
|
|
19602
|
+
/** Mostrar campo de busca genérico quando não houver Quick configurado */
|
|
19603
|
+
showQuickFallback;
|
|
19598
19604
|
/** Data used to render the summary card when mode resolves to 'card'. */
|
|
19599
19605
|
summary;
|
|
19600
19606
|
/** Custom template to render the summary card; receives the summary as $implicit. */
|
|
@@ -19612,7 +19618,7 @@ class PraxisFilter {
|
|
|
19612
19618
|
/** Mostrar rótulos dos toggles na área de ações */
|
|
19613
19619
|
showToggleLabels = true;
|
|
19614
19620
|
/** Config da grade dos alwaysVisible */
|
|
19615
|
-
alwaysMinWidth =
|
|
19621
|
+
alwaysMinWidth = 240; // px (largura mínima padrão por campo)
|
|
19616
19622
|
alwaysColsMd = 2;
|
|
19617
19623
|
alwaysColsLg = 3;
|
|
19618
19624
|
/** Tag theming */
|
|
@@ -19768,6 +19774,20 @@ class PraxisFilter {
|
|
|
19768
19774
|
return undefined;
|
|
19769
19775
|
}
|
|
19770
19776
|
})();
|
|
19777
|
+
/** Decide se o bloco Quick deve ser exibido (heurística + preferência) */
|
|
19778
|
+
showQuickBar() {
|
|
19779
|
+
if (this.quickField || this.quickFieldMeta)
|
|
19780
|
+
return true;
|
|
19781
|
+
if (this.showQuickFallback === true)
|
|
19782
|
+
return true;
|
|
19783
|
+
const hasAlwaysCfg = Array.isArray(this.alwaysVisibleFields) && this.alwaysVisibleFields.length > 0;
|
|
19784
|
+
if (!this.schemaMetas || this.schemaMetas.length === 0) {
|
|
19785
|
+
return !hasAlwaysCfg;
|
|
19786
|
+
}
|
|
19787
|
+
const hasAlways = (this.alwaysVisibleMetas?.length || 0) > 0;
|
|
19788
|
+
const hasToggles = (this.toggleMetas?.length || 0) > 0;
|
|
19789
|
+
return !(hasAlways || hasToggles);
|
|
19790
|
+
}
|
|
19771
19791
|
loadSavedTagsFromStorage() {
|
|
19772
19792
|
try {
|
|
19773
19793
|
if (!this.configKey)
|
|
@@ -19810,6 +19830,9 @@ class PraxisFilter {
|
|
|
19810
19830
|
if (this.allowSaveTags === undefined && cfg.allowSaveTags !== undefined) {
|
|
19811
19831
|
this.allowSaveTags = cfg.allowSaveTags;
|
|
19812
19832
|
}
|
|
19833
|
+
if (this.showQuickFallback === undefined && cfg.showQuickFallback !== undefined) {
|
|
19834
|
+
this.showQuickFallback = !!cfg.showQuickFallback;
|
|
19835
|
+
}
|
|
19813
19836
|
if (this.changeDebounceMs === 300 && cfg.changeDebounceMs !== undefined) {
|
|
19814
19837
|
this.changeDebounceMs = cfg.changeDebounceMs;
|
|
19815
19838
|
}
|
|
@@ -20471,9 +20494,19 @@ class PraxisFilter {
|
|
|
20471
20494
|
this.alwaysForm.valueChanges
|
|
20472
20495
|
.pipe(debounceTime$1(this.changeDebounceMs), takeUntil$1(this.alwaysFormReset$), takeUntilDestroyed(this.destroyRef))
|
|
20473
20496
|
.subscribe((val) => this.advancedChange$.next(val));
|
|
20474
|
-
|
|
20497
|
+
let advancedMetas = metas
|
|
20475
20498
|
.filter((m) => m.name !== this.quickField && !this.alwaysVisibleFields?.includes(m.name))
|
|
20476
20499
|
.map((m) => ({ ...m, updateOn: 'change' }));
|
|
20500
|
+
// Quando o painel avançado abre em modal/gaveta, habilitar touchUi nos campos de data
|
|
20501
|
+
if (this.advancedOpenMode === 'modal' || this.advancedOpenMode === 'drawer') {
|
|
20502
|
+
advancedMetas = advancedMetas.map((m) => {
|
|
20503
|
+
const ct = m.controlType;
|
|
20504
|
+
if (ct === 'date' || ct === 'dateRange' || ct === 'dateTime' || ct === 'dateTimeRange') {
|
|
20505
|
+
return { ...m, touchUi: true };
|
|
20506
|
+
}
|
|
20507
|
+
return m;
|
|
20508
|
+
});
|
|
20509
|
+
}
|
|
20477
20510
|
if (advancedMetas.length) {
|
|
20478
20511
|
// Única linha com várias colunas: melhora responsividade via wrap no formulário filho
|
|
20479
20512
|
this.advancedConfig = {
|
|
@@ -20612,9 +20645,15 @@ class PraxisFilter {
|
|
|
20612
20645
|
this.autoSummaryData = undefined;
|
|
20613
20646
|
return;
|
|
20614
20647
|
}
|
|
20615
|
-
const maxBadges =
|
|
20616
|
-
const badges = entries.slice(0, maxBadges).map(([k, v]) =>
|
|
20648
|
+
const maxBadges = 5;
|
|
20649
|
+
const badges = entries.slice(0, maxBadges).map(([k, v]) => {
|
|
20650
|
+
const label = this.getFieldLabel(k) || k;
|
|
20651
|
+
return `${label}=${this.formatValueForBadge(k, v)}`;
|
|
20652
|
+
});
|
|
20617
20653
|
const extra = entries.length > maxBadges ? ` +${entries.length - maxBadges}` : '';
|
|
20654
|
+
if (entries.length > maxBadges) {
|
|
20655
|
+
badges.push(`+${entries.length - maxBadges}`);
|
|
20656
|
+
}
|
|
20618
20657
|
this.autoSummaryData = {
|
|
20619
20658
|
count: entries.length,
|
|
20620
20659
|
dto: { ...this.dto },
|
|
@@ -20629,17 +20668,71 @@ class PraxisFilter {
|
|
|
20629
20668
|
badges: this.autoSummaryData?.badges?.map((b) => (() => b)) ?? [],
|
|
20630
20669
|
};
|
|
20631
20670
|
}
|
|
20632
|
-
|
|
20671
|
+
/** Salva o estado atual dos filtros como um atalho (tag) do usuário */
|
|
20672
|
+
saveCurrentAsTag() {
|
|
20673
|
+
try {
|
|
20674
|
+
const dto = { ...(this.advancedForm?.getRawValue?.() || this.dto || {}) };
|
|
20675
|
+
if (!Object.keys(dto).length)
|
|
20676
|
+
return;
|
|
20677
|
+
const label = prompt(this.i18nLabels.saveAsShortcut || 'Salvar como atalho', '') || '';
|
|
20678
|
+
if (!label.trim())
|
|
20679
|
+
return;
|
|
20680
|
+
const tag = { id: Date.now().toString(), label: label.trim(), patch: dto };
|
|
20681
|
+
this.savedTags.push(tag);
|
|
20682
|
+
this.persistTags();
|
|
20683
|
+
this.updateDisplayedTags();
|
|
20684
|
+
}
|
|
20685
|
+
catch { }
|
|
20686
|
+
}
|
|
20687
|
+
formatValueForBadge(fieldName, v) {
|
|
20633
20688
|
if (v === null || v === undefined)
|
|
20634
20689
|
return '';
|
|
20690
|
+
// Array: traduz item a item
|
|
20635
20691
|
if (Array.isArray(v))
|
|
20636
|
-
return v.join(',');
|
|
20692
|
+
return v.map((it) => this.formatValueForBadge(fieldName, it)).join(',');
|
|
20693
|
+
// Try map via options (enum/select) when available
|
|
20694
|
+
const opt = this.getOptionText(fieldName, v);
|
|
20695
|
+
if (opt)
|
|
20696
|
+
return opt;
|
|
20697
|
+
// Boolean in pt-BR
|
|
20698
|
+
if (typeof v === 'boolean')
|
|
20699
|
+
return v ? 'Sim' : 'Não';
|
|
20637
20700
|
if (v instanceof Date)
|
|
20638
20701
|
return v.toISOString().slice(0, 10);
|
|
20639
20702
|
if (typeof v === 'object')
|
|
20640
20703
|
return JSON.stringify(v);
|
|
20641
20704
|
return String(v);
|
|
20642
20705
|
}
|
|
20706
|
+
/**
|
|
20707
|
+
* Resolve a user-friendly label for a filter key using the loaded FieldMetadata.
|
|
20708
|
+
* Falls back to the key itself when metadata is not available.
|
|
20709
|
+
*/
|
|
20710
|
+
getFieldLabel(name) {
|
|
20711
|
+
// Prefer schemaMetas when available
|
|
20712
|
+
const metas = this.schemaMetas || this.advancedConfig?.fieldMetadata || [];
|
|
20713
|
+
try {
|
|
20714
|
+
const found = metas.find((m) => m?.name === name);
|
|
20715
|
+
return found?.label || undefined;
|
|
20716
|
+
}
|
|
20717
|
+
catch {
|
|
20718
|
+
return undefined;
|
|
20719
|
+
}
|
|
20720
|
+
}
|
|
20721
|
+
/** Resolve option display text from FieldMetadata.options, when present */
|
|
20722
|
+
getOptionText(name, value) {
|
|
20723
|
+
const metas = this.schemaMetas || this.advancedConfig?.fieldMetadata || [];
|
|
20724
|
+
try {
|
|
20725
|
+
const found = metas.find((m) => m?.name === name);
|
|
20726
|
+
const opts = found?.options;
|
|
20727
|
+
if (!opts || !opts.length)
|
|
20728
|
+
return undefined;
|
|
20729
|
+
const match = opts.find((o) => (o?.value === value) || (String(o?.value) === String(value)));
|
|
20730
|
+
return match?.text;
|
|
20731
|
+
}
|
|
20732
|
+
catch {
|
|
20733
|
+
return undefined;
|
|
20734
|
+
}
|
|
20735
|
+
}
|
|
20643
20736
|
// Helper A11y: label do botão Avançado com contagem
|
|
20644
20737
|
getAdvancedAriaLabel() {
|
|
20645
20738
|
const count = this.activeFiltersCount || 0;
|
|
@@ -21218,7 +21311,7 @@ class PraxisFilter {
|
|
|
21218
21311
|
}
|
|
21219
21312
|
}
|
|
21220
21313
|
async openAdvancedModal() {
|
|
21221
|
-
const { FilterFormDialogHostComponent } = await import('./praxisui-table-filter-form-dialog-host.component-
|
|
21314
|
+
const { FilterFormDialogHostComponent } = await import('./praxisui-table-filter-form-dialog-host.component-Du_IEq0W.mjs');
|
|
21222
21315
|
const ref = this.dialog.open(FilterFormDialogHostComponent, {
|
|
21223
21316
|
width: '780px',
|
|
21224
21317
|
maxWidth: '96vw',
|
|
@@ -21226,6 +21319,7 @@ class PraxisFilter {
|
|
|
21226
21319
|
formId: this.formId,
|
|
21227
21320
|
resourcePath: this.resourcePath,
|
|
21228
21321
|
config: this.advancedConfig,
|
|
21322
|
+
initialDto: this.advancedForm?.getRawValue?.() || this.dto || {},
|
|
21229
21323
|
schemaLoading: this.schemaLoading,
|
|
21230
21324
|
},
|
|
21231
21325
|
});
|
|
@@ -21323,6 +21417,7 @@ class PraxisFilter {
|
|
|
21323
21417
|
overlayVariant: this.overlayVariant,
|
|
21324
21418
|
overlayBackdrop: this.overlayBackdrop,
|
|
21325
21419
|
advancedOpenMode: this.advancedOpenMode,
|
|
21420
|
+
showQuickFallback: this.showQuickFallback,
|
|
21326
21421
|
};
|
|
21327
21422
|
this.filterConfig.save(this.configKey, config);
|
|
21328
21423
|
}
|
|
@@ -21428,7 +21523,7 @@ class PraxisFilter {
|
|
|
21428
21523
|
}
|
|
21429
21524
|
}
|
|
21430
21525
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: PraxisFilter, deps: [{ token: i1$3.GenericCrudService }, { token: CONFIG_STORAGE }, { token: i0.DestroyRef }, { token: FilterConfigService }, { token: i3$2.SettingsPanelService }, { token: i2$1.MatSnackBar }, { token: i1$2.MatDialog }, { token: i0.ChangeDetectorRef }, { token: i1$3.DynamicFormService }, { token: i1$3.SchemaNormalizerService }], target: i0.ɵɵFactoryTarget.Component });
|
|
21431
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.4", type: PraxisFilter, isStandalone: true, selector: "praxis-filter", inputs: { resourcePath: "resourcePath", formId: "formId", mode: "mode", notifyIfOutdated: "notifyIfOutdated", snoozeMs: "snoozeMs", autoOpenSettingsOnOutdated: "autoOpenSettingsOnOutdated", editModeEnabled: "editModeEnabled", value: "value", quickField: "quickField", alwaysVisibleFields: "alwaysVisibleFields", tags: "tags", allowSaveTags: "allowSaveTags", persistenceKey: "persistenceKey", i18n: "i18n", changeDebounceMs: "changeDebounceMs", showFilterSettings: "showFilterSettings", summary: "summary", summaryTemplate: "summaryTemplate", summaryMap: "summaryMap", autoSummary: "autoSummary", confirmTagDelete: "confirmTagDelete", debugLayout: "debugLayout", placeBooleansInActions: "placeBooleansInActions", showToggleLabels: "showToggleLabels", alwaysMinWidth: "alwaysMinWidth", alwaysColsMd: "alwaysColsMd", alwaysColsLg: "alwaysColsLg", tagColor: "tagColor", tagVariant: "tagVariant", tagButtonColor: "tagButtonColor", actionsButtonColor: "actionsButtonColor", actionsVariant: "actionsVariant", overlayVariant: "overlayVariant", overlayBackdrop: "overlayBackdrop", advancedOpenMode: "advancedOpenMode" }, outputs: { submit: "submit", change: "change", clear: "clear", modeChange: "modeChange", requestSearch: "requestSearch", tagsChange: "tagsChange", metaChanged: "metaChanged", schemaStatusChange: "schemaStatusChange" }, host: { listeners: { "window:resize": "onWindowResize()", "document:keydown": "onGlobalKeydown($event)" }, properties: { "class.debug-layout": "debugLayout", "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: "quickHostRef", first: true, predicate: ["quickHostRef"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<ng-container *ngIf=\"modeState === 'filter'; else summaryCard\">\n <mat-progress-bar *ngIf=\"saving\" mode=\"indeterminate\"></mat-progress-bar>\n\n <form class=\"praxis-filter-bar\" [class.is-open]=\"advancedOpen\" (submit)=\"onSubmit(); $event.preventDefault()\">\n <!-- QUICK FIELD -->\n <div class=\"quick-field\" *ngIf=\"quickFieldMeta; else fallbackQuick\">\n <div class=\"filter-anchor quick-shell\" #anchorRef=\"cdkOverlayOrigin\" cdkOverlayOrigin>\n\n <!-- din\u00E2mico: envolvido por host para garantir layout flex correto -->\n <div *ngIf=\"quickFieldMode === 'dynamic'\" class=\"quick-field-host\" #quickHostRef\n dynamicFieldLoader\n [fields]=\"quickFieldMetaArray\"\n [formGroup]=\"quickForm\"\n (componentsCreated)=\"onQuickComponents($event)\"\n (fieldCreated)=\"onQuickFieldCreated($event)\">\n </div>\n\n <!-- fallback (com meta) \u2014 sem suffix, s\u00F3 o input -->\n <mat-form-field *ngIf=\"quickFieldMode === 'fallback'\"\n appearance=\"outline\"\n floatLabel=\"always\"\n class=\"fallback-quick-field\">\n <mat-label>{{ quickFieldMeta.label || quickField }}</mat-label>\n <input matInput [formControl]=\"quickControl\"\n [type]=\"getQuickInputType()\"\n [attr.inputmode]=\"getQuickInputMode()\"\n [attr.aria-label]=\"quickFieldMeta.label || quickField\"\n (keydown.escape)=\"onQuickClear()\"\n (keypress)=\"onQuickNumericKeypress($event)\"\n (blur)=\"onQuickBlurFormat()\">\n </mat-form-field>\n\n \n </div>\n </div>\n\n\n <!-- QUICK \u201Cfalso\u201D (quando n\u00E3o h\u00E1 meta) -->\n <ng-template #fallbackQuick>\n <div class=\"filter-anchor quick-shell\" #anchorRef=\"cdkOverlayOrigin\" cdkOverlayOrigin>\n <mat-form-field appearance=\"outline\" floatLabel=\"always\" class=\"fallback-quick-field\">\n <mat-label>{{ i18nLabels.searchPlaceholder }}</mat-label>\n <input matInput [formControl]=\"quickControl\"\n [attr.aria-label]=\"i18nLabels.searchPlaceholder\"\n (keydown.escape)=\"onQuickClear()\" />\n </mat-form-field>\n </div>\n </ng-template>\n\n <!-- A\u00C7\u00D5ES INLINE (fixas \u00E0 direita da barra) -->\n <div class=\"inline-actions\" [class.actions-outlined]=\"actionsVariant==='outlined'\">\n <!-- Toggles/booleans simples realocados para a barra de a\u00E7\u00F5es -->\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 <button mat-icon-button [color]=\"actionsButtonColor==='basic'? null : actionsButtonColor\" type=\"button\" *ngIf=\"quickHasValue()\"\n (click)=\"onQuickClear()\" [attr.aria-label]=\"i18nLabels.clear\">\n <mat-icon [praxisIcon]=\"'close'\"></mat-icon>\n </button>\n <button mat-icon-button [color]=\"actionsButtonColor==='basic'? null : actionsButtonColor\" type=\"button\" (click)=\"onSubmit()\" [attr.aria-label]=\"i18nLabels.apply\">\n <mat-icon [praxisIcon]=\"'search'\"></mat-icon>\n </button>\n <button mat-icon-button [color]=\"actionsButtonColor==='basic'? null : actionsButtonColor\" type=\"button\"\n [matBadge]=\"activeFiltersCount\"\n [matBadgeHidden]=\"!activeFiltersCount\"\n matBadgeSize=\"small\"\n matBadgeColor=\"primary\"\n [matBadgeOverlap]=\"false\"\n (click)=\"toggleAdvanced()\"\n [attr.aria-label]=\"getAdvancedAriaLabel()\"\n [attr.aria-expanded]=\"advancedOpen\"\n [attr.aria-controls]=\"advancedPanelId\">\n <mat-icon [praxisIcon]=\"'tune'\"></mat-icon>\n </button>\n <button mat-icon-button [color]=\"actionsButtonColor==='basic'? null : actionsButtonColor\" type=\"button\" (click)=\"openSettings()\" *ngIf=\"showFilterSettings\"\n [matBadge]=\"schemaOutdated ? '!' : ''\"\n [matBadgeHidden]=\"!schemaOutdated\"\n 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 <!-- campos sempre vis\u00EDveis (se houver) -->\n <div class=\"always-fields\" *ngIf=\"alwaysVisibleMetas.length\">\n <ng-container dynamicFieldLoader [fields]=\"alwaysVisibleMetas\" [formGroup]=\"alwaysForm\"\n (componentsCreated)=\"onAlwaysComponents($event)\"></ng-container>\n </div>\n\n <!-- acessibilidade -->\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 <!-- tags -->\n <div class=\"praxis-filter-tags\" *ngIf=\"displayedTags.length\" [class.outlined]=\"tagVariant==='outlined'\">\n <mat-chip-set>\n <mat-chip *ngFor=\"let tag of displayedTags\"\n [color]=\"tagColor === 'basic' ? null : tagColor\"\n (click)=\"applyTag(tag)\" (keydown.enter)=\"applyTag(tag)\"\n tabindex=\"0\" role=\"button\">\n <ng-container *ngIf=\"editingTagId !== tag.id; else editChip\">\n <span class=\"chip-label\">{{ tag.label }}</span>\n <span class=\"chip-actions\" *ngIf=\"isUserTag(tag)\">\n <button mat-icon-button [color]=\"tagButtonColor === 'basic' ? null : tagButtonColor\"\n (click)=\"startEditTag(tag, $event)\" aria-label=\"edit tag\">\n <mat-icon>edit</mat-icon>\n </button>\n <button mat-icon-button [color]=\"tagButtonColor === 'basic' ? null : tagButtonColor\"\n (click)=\"deleteTag(tag)\" aria-label=\"remove tag\">\n <mat-icon>close</mat-icon>\n </button>\n </span>\n </ng-container>\n <ng-template #editChip>\n <input matInput class=\"chip-editor\" [formControl]=\"editingTagLabel\"\n (keydown.enter)=\"commitEditTag(tag, $event)\" (keydown.escape)=\"cancelEditTag($event)\" (click)=\"$event.stopPropagation()\" />\n <button mat-button color=\"primary\" (click)=\"commitEditTag(tag, $event)\">{{ i18nLabels.save }}</button>\n <button mat-button (click)=\"cancelEditTag($event)\">{{ i18nLabels.cancel }}</button>\n </ng-template>\n </mat-chip>\n </mat-chip-set>\n </div>\n\n <!-- OVERLAY -->\n <ng-container *ngIf=\"overlayOrigin\">\n <ng-template cdkConnectedOverlay\n [cdkConnectedOverlayOrigin]=\"overlayOrigin!\"\n [cdkConnectedOverlayOpen]=\"advancedOpen\"\n [cdkConnectedOverlayHasBackdrop]=\"overlayBackdrop\"\n [cdkConnectedOverlayBackdropClass]=\"'praxis-overlay-backdrop'\"\n [cdkConnectedOverlayPositions]=\"overlayPositions\"\n [cdkConnectedOverlayFlexibleDimensions]=\"true\"\n [cdkConnectedOverlayPush]=\"true\"\n [cdkConnectedOverlayOffsetY]=\"8\"\n [cdkConnectedOverlayLockPosition]=\"true\"\n [cdkConnectedOverlayWidth]=\"overlayWidth\"\n [cdkConnectedOverlayPanelClass]=\"['praxis-filter-overlay', isMobile ? 'mobile' : '', overlayVariant === 'frosted' ? 'frosted' : '']\"\n (overlayOutsideClick)=\"onOverlayOutsideClick($event)\"\n (backdropClick)=\"onOverlayDetach()\"\n (detach)=\"onOverlayDetach()\">\n <div class=\"praxis-filter-advanced\" (keydown.escape)=\"toggleAdvanced()\" role=\"dialog\" aria-modal=\"true\" [attr.id]=\"advancedPanelId\">\n <div class=\"advanced-body\">\n <mat-progress-bar *ngIf=\"schemaLoading\" mode=\"indeterminate\"></mat-progress-bar>\n <p *ngIf=\"schemaError\" class=\"schema-error\">\n {{ i18nLabels.errorLoadingFilters }}\n <button mat-button type=\"button\" (click)=\"loadSchema()\">{{ i18nLabels.retry }}</button>\n </p>\n <praxis-filter-form *ngIf=\"!schemaLoading && !schemaError && advancedConfig\"\n [formId]=\"formId\" [resourcePath]=\"resourcePath\" [mode]=\"'edit'\" [config]=\"advancedConfig\"\n (formReady)=\"onAdvancedReady($event)\" (valueChange)=\"onAdvancedChange($event)\"\n (validityChange)=\"onAdvancedValidityChange($event)\" (submit)=\"onAdvancedSubmit($event)\">\n </praxis-filter-form>\n <p *ngIf=\"!schemaLoading && !schemaError && !advancedConfig\">{{ i18nLabels.noData }}</p>\n </div>\n <div class=\"advanced-actions\" *ngIf=\"!schemaLoading && !schemaError && advancedConfig\">\n <button mat-raised-button color=\"primary\" type=\"button\"\n (click)=\"onAdvancedSubmit({ formData: (advancedForm?.getRawValue?.() || {}) })\"\n [disabled]=\"!advancedValid\">\n {{ i18nLabels.apply }}\n </button>\n <button mat-button type=\"button\" (click)=\"onClear()\">{{ i18nLabels.clear }}</button>\n </div>\n </div>\n </ng-template>\n </ng-container>\n</ng-container>\n\n<!-- resumo -->\n<ng-template #summaryCard>\n <div class=\"praxis-filter-card\" (keydown.escape)=\"onClear()\">\n <div class=\"summary-header\">\n <img *ngIf=\"currentSummaryMap?.avatar?.(currentSummary)\" [src]=\"currentSummaryMap?.avatar?.(currentSummary)\"\n class=\"summary-avatar\" alt=\"\" />\n <div class=\"summary-text\">\n <div class=\"summary-title\">{{ currentSummaryMap?.title?.(currentSummary) || '' }}</div>\n <div class=\"summary-subtitle\" *ngIf=\"currentSummaryMap?.subtitle\">{{ currentSummaryMap?.subtitle?.(currentSummary) }}</div>\n </div>\n </div>\n <div class=\"summary-badges\" *ngIf=\"currentSummaryMap?.badges?.length\">\n <span *ngFor=\"let b of currentSummaryMap!.badges\">{{ b(currentSummary) }}</span>\n </div>\n <div class=\"card-actions\">\n <button mat-button type=\"button\" (click)=\"switchToFilter()\">{{ i18nLabels.edit }}</button>\n <button mat-button type=\"button\" (click)=\"onClear()\">{{ i18nLabels.clear }}</button>\n </div>\n </div>\n</ng-template>\n", styles: ["@charset \"UTF-8\";:root{--pfx-filter-h: 40px;--pfx-filter-align-offset: 2px;--pfx-gap-x: 16px;--pfx-gap-y: 12px;--pfx-quick-pad-top: 5px;--pfx-quick-pad-left: 12px;--pfx-advanced-pad-x: 24px;--pfx-field-min: 280px;--pfx-quick-bg: var(--surface-2, #232a32);--pfx-quick-border: var(--pfx-surface-border, rgba(255,255,255,.08));--pfx-quick-radius: 12px}.praxis-filter-bar{display:grid;width:100%;grid-template-columns:1fr auto;grid-template-areas:\"quick actions\" \"always always\";column-gap:0;row-gap:8px;align-items:center}:host.debug-layout{background-image:repeating-linear-gradient(to right,rgba(147,197,253,.08) 0,rgba(147,197,253,.08) 1px,transparent 1px,transparent var(--pfx-gap-x)),repeating-linear-gradient(to bottom,rgba(163,230,53,.08) 0,rgba(163,230,53,.08) 1px,transparent 1px,transparent 8px)}:host.debug-layout .praxis-filter-bar{outline:1px dashed #f59e0b}:host.debug-layout .quick-shell{outline:1px dashed #3b82f6}:host.debug-layout .always-fields{outline:1px dashed #22c55e}:host.debug-layout .praxis-filter-overlay .praxis-filter-advanced{outline:2px solid #a855f7}.quick-field{grid-area:quick;min-width:280px;align-self:center}.inline-actions{grid-area:actions;justify-self:end}.always-fields{grid-area:always}.quick-shell{min-height:var(--pfx-filter-h);padding:0 0 0 var(--pfx-quick-pad-left);display:flex;align-items:center;flex-wrap:nowrap;gap:6px;overflow:hidden;background:var(--pfx-quick-bg);border:1px solid var(--pfx-quick-border);border-right:none;border-radius:var(--pfx-quick-radius) 0 0 var(--pfx-quick-radius)}.quick-shell>*{flex:1 1 auto;min-width:0}.quick-field-host{display:contents}:host ::ng-deep .quick-shell .mat-mdc-form-field{width:100%!important;flex:1 1 auto}:host ::ng-deep .quick-shell .mat-mdc-form-field{margin:0!important}:host ::ng-deep .quick-shell pdx-text-input,:host ::ng-deep .quick-shell pdx-select,:host ::ng-deep .quick-shell pdx-date-input,:host ::ng-deep .quick-shell pdx-auto-complete{flex:1 1 auto;min-width:0;display:block}.inline-actions{flex:0 0 auto;display:flex;gap:4px;align-self:start;white-space:nowrap;height:var(--pfx-filter-h);align-items:center;background:var(--pfx-quick-bg);border:1px solid var(--pfx-quick-border);border-left:none;border-radius:0 var(--pfx-quick-radius) var(--pfx-quick-radius) 0;padding-right:4px;margin-left:-1px}.inline-actions.actions-outlined button.mat-mdc-icon-button{border:1px solid var(--pfx-quick-border);border-radius:50%}.inline-actions .mat-mdc-icon-button{width:36px;height:36px}.inline-actions mat-icon{width:20px;height:20px;font-size:20px}.fallback-quick-field{height:var(--pfx-filter-h);display:flex;align-items:center}:host ::ng-deep .fallback-quick-field .mat-mdc-text-field-wrapper.mdc-text-field--outlined{height:var(--pfx-filter-h);align-items:center;padding-top:var(--pfx-quick-pad-top)}:host ::ng-deep .quick-shell .mat-mdc-text-field-wrapper.mdc-text-field--outlined{min-height:var(--pfx-filter-h);align-items:center;padding-top:var(--pfx-quick-pad-top)}:host ::ng-deep .quick-shell .mat-mdc-form-field-infix{min-height:var(--pfx-filter-h);padding-top:8px}:host ::ng-deep .quick-shell .mat-mdc-select-trigger{height:var(--pfx-filter-h);align-items:center}:host ::ng-deep .quick-shell .mat-mdc-form-field-subscript-wrapper{display:none}:host ::ng-deep .quick-shell .mdc-line-ripple{display:none!important}.always-fields{display:grid;grid-template-columns:repeat(auto-fit,minmax(var(--pfx-always-min, 300px),1fr));gap:8px}:host ::ng-deep .always-fields .mat-mdc-text-field-wrapper.mdc-text-field--outlined{min-height:var(--pfx-filter-h);align-items:center}:host ::ng-deep .always-fields .mat-mdc-form-field-infix{min-height:var(--pfx-filter-h)}:host ::ng-deep .always-fields .mat-mdc-select-trigger{height:var(--pfx-filter-h);align-items:center}:host ::ng-deep .always-fields .mat-mdc-form-field{width:100%}.praxis-filter-tags{display:flex;flex-wrap:wrap;gap:6px}.praxis-filter-tags mat-chip{border-radius:16px;padding:0 6px}.praxis-filter-tags .chip-actions{display:inline-flex;align-items:center;gap:2px;margin-left:4px}.chip-editor{width:140px;margin-right:8px}.praxis-filter-tags.outlined mat-chip{background:transparent!important;border:1px solid var(--pfx-quick-border)}.praxis-filter-advanced{display:flex;flex-direction:column;min-width:400px;max-width:90vw;min-height:260px;max-height:80vh;margin-top:25px;margin-right:15px;margin-left:25px;background:var(--md-sys-color-surface-container, #2a3038)!important;background-color:var(--md-sys-color-surface-container, #2a3038)!important;background:color-mix(in srgb,var(--md-sys-color-surface-container, #2a3038),transparent 6%)!important;color:var(--md-sys-color-on-surface, #e6eaf2);border:1px solid var(--border-color);border-radius:12px;box-shadow:0 8px 24px #00000052,0 2px 8px #0000002e}.praxis-filter-overlay.mobile .praxis-filter-advanced{height:100vh;max-height:100vh}:host ::ng-deep .praxis-overlay-backdrop{background:#0006;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px)}.advanced-body{padding:var(--pfx-gap-y) 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:var(--md-sys-color-surface-container, #2a3038)!important;background-color:var(--md-sys-color-surface-container, #2a3038)!important;background:color-mix(in srgb,var(--md-sys-color-surface-container, #2a3038),transparent 0%)!important;border-top:1px solid var(--border-color);box-shadow:0 -1px #0000002e}.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(--md-sys-color-on-surface-variant);--mdc-outlined-text-field-input-text-color: var(--md-sys-color-on-surface);--mdc-outlined-text-field-container-color: var(--md-sys-color-surface-container, #2a3038);--mdc-outlined-text-field-container-color: color-mix(in srgb, var(--md-sys-color-surface-container, #2a3038), transparent 90%)}: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(--md-sys-color-on-surface)}@media (min-width: 600px){.always-fields{grid-template-columns:repeat(var(--pfx-always-cols-md, 2),minmax(0,1fr))}:host ::ng-deep .praxis-filter-advanced .praxis-filter-form .filter-row{grid-template-columns:repeat(2,minmax(0,1fr))}}@media (min-width: 960px){.always-fields{grid-template-columns:repeat(var(--pfx-always-cols-lg, 3),minmax(0,1fr))}}.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}.praxis-filter-card{display:flex;flex-direction:column;gap:6px;padding:8px 12px;border-radius:12px;border:1px solid var(--pfx-quick-border);background:var(--pfx-quick-bg);color:var(--md-sys-color-on-surface, #2B2A28)}.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:color-mix(in oklab,var(--md-sys-color-primary, #3FBCA5),transparent 88%);border:1px solid color-mix(in oklab,var(--md-sys-color-primary, #3FBCA5),transparent 70%);color:var(--md-sys-color-on-surface, #2B2A28);font-size:12px}.praxis-filter-card .card-actions{display:flex;gap:8px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.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: i3$1.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i3$1.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i6.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: i11.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: i11.MatChipSet, selector: "mat-chip-set", inputs: ["disabled", "role", "tabIndex"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i4.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }, { kind: "ngmodule", type: MatBadgeModule }, { kind: "directive", type: i15.MatBadge, selector: "[matBadge]", inputs: ["matBadgeColor", "matBadgeOverlap", "matBadgeDisabled", "matBadgePosition", "matBadge", "matBadgeDescription", "matBadgeSize", "matBadgeHidden"] }, { kind: "ngmodule", type: MatProgressBarModule }, { kind: "component", type: i14$1.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: "directive", type: DynamicFieldLoaderDirective, selector: "[dynamicFieldLoader]", inputs: ["fields", "formGroup", "enableExternalControlBinding", "itemTemplate", "readonlyMode", "disabledMode", "presentationMode", "visible", "canvasMode"], outputs: ["componentsCreated", "fieldCreated", "fieldDestroyed", "canvasMouseEnter", "canvasMouseLeave", "canvasClick"] }, { kind: "component", type: PraxisFilterForm, selector: "praxis-filter-form", inputs: ["config", "formId", "resourcePath", "mode"], outputs: ["formReady", "valueChange", "submit", "validityChange"] }, { kind: "ngmodule", type: OverlayModule }, { kind: "directive", type: i19.CdkConnectedOverlay, selector: "[cdk-connected-overlay], [connected-overlay], [cdkConnectedOverlay]", inputs: ["cdkConnectedOverlayOrigin", "cdkConnectedOverlayPositions", "cdkConnectedOverlayPositionStrategy", "cdkConnectedOverlayOffsetX", "cdkConnectedOverlayOffsetY", "cdkConnectedOverlayWidth", "cdkConnectedOverlayHeight", "cdkConnectedOverlayMinWidth", "cdkConnectedOverlayMinHeight", "cdkConnectedOverlayBackdropClass", "cdkConnectedOverlayPanelClass", "cdkConnectedOverlayViewportMargin", "cdkConnectedOverlayScrollStrategy", "cdkConnectedOverlayOpen", "cdkConnectedOverlayDisableClose", "cdkConnectedOverlayTransformOriginOn", "cdkConnectedOverlayHasBackdrop", "cdkConnectedOverlayLockPosition", "cdkConnectedOverlayFlexibleDimensions", "cdkConnectedOverlayGrowAfterOpen", "cdkConnectedOverlayPush", "cdkConnectedOverlayDisposeOnNavigation"], outputs: ["backdropClick", "positionChange", "attach", "detach", "overlayKeydown", "overlayOutsideClick"], exportAs: ["cdkConnectedOverlay"] }, { kind: "directive", type: i19.CdkOverlayOrigin, selector: "[cdk-overlay-origin], [overlay-origin], [cdkOverlayOrigin]", exportAs: ["cdkOverlayOrigin"] }, { kind: "ngmodule", type: MatDialogModule }] });
|
|
21526
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.4", type: PraxisFilter, isStandalone: true, selector: "praxis-filter", inputs: { resourcePath: "resourcePath", formId: "formId", mode: "mode", notifyIfOutdated: "notifyIfOutdated", snoozeMs: "snoozeMs", autoOpenSettingsOnOutdated: "autoOpenSettingsOnOutdated", editModeEnabled: "editModeEnabled", value: "value", quickField: "quickField", alwaysVisibleFields: "alwaysVisibleFields", tags: "tags", allowSaveTags: "allowSaveTags", persistenceKey: "persistenceKey", i18n: "i18n", changeDebounceMs: "changeDebounceMs", showFilterSettings: "showFilterSettings", showQuickFallback: "showQuickFallback", summary: "summary", summaryTemplate: "summaryTemplate", summaryMap: "summaryMap", autoSummary: "autoSummary", confirmTagDelete: "confirmTagDelete", debugLayout: "debugLayout", placeBooleansInActions: "placeBooleansInActions", showToggleLabels: "showToggleLabels", alwaysMinWidth: "alwaysMinWidth", alwaysColsMd: "alwaysColsMd", alwaysColsLg: "alwaysColsLg", tagColor: "tagColor", tagVariant: "tagVariant", tagButtonColor: "tagButtonColor", actionsButtonColor: "actionsButtonColor", actionsVariant: "actionsVariant", overlayVariant: "overlayVariant", overlayBackdrop: "overlayBackdrop", advancedOpenMode: "advancedOpenMode" }, outputs: { submit: "submit", change: "change", clear: "clear", modeChange: "modeChange", requestSearch: "requestSearch", tagsChange: "tagsChange", metaChanged: "metaChanged", schemaStatusChange: "schemaStatusChange" }, host: { listeners: { "window:resize": "onWindowResize()", "document:keydown": "onGlobalKeydown($event)" }, properties: { "class.debug-layout": "debugLayout", "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: "quickHostRef", first: true, predicate: ["quickHostRef"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<ng-container *ngIf=\"modeState === 'filter'; else summaryCard\">\n <mat-progress-bar *ngIf=\"saving\" mode=\"indeterminate\"></mat-progress-bar>\n\n <form class=\"praxis-filter-bar\" [class.is-open]=\"advancedOpen\" (submit)=\"onSubmit(); $event.preventDefault()\">\n <!-- QUICK FIELD (oculto quando n\u00E3o h\u00E1 Quick e existem campos sempre vis\u00EDveis, salvo override) -->\n <ng-container *ngIf=\"showQuickBar(); else noQuick\">\n <div class=\"quick-field\" *ngIf=\"quickFieldMeta; else fallbackQuick\">\n <div class=\"filter-anchor quick-shell\" #anchorRef=\"cdkOverlayOrigin\" cdkOverlayOrigin>\n\n <!-- din\u00E2mico: envolvido por host para garantir layout flex correto -->\n <div *ngIf=\"quickFieldMode === 'dynamic'\" class=\"quick-field-host\" #quickHostRef\n dynamicFieldLoader\n [fields]=\"quickFieldMetaArray\"\n [formGroup]=\"quickForm\"\n (componentsCreated)=\"onQuickComponents($event)\"\n (fieldCreated)=\"onQuickFieldCreated($event)\">\n </div>\n\n <!-- fallback (com meta) \u2014 sem suffix, s\u00F3 o input -->\n <mat-form-field *ngIf=\"quickFieldMode === 'fallback'\"\n appearance=\"outline\"\n floatLabel=\"always\"\n class=\"fallback-quick-field\">\n <mat-label>{{ quickFieldMeta.label || quickField }}</mat-label>\n <input matInput [formControl]=\"quickControl\"\n [type]=\"getQuickInputType()\"\n [attr.inputmode]=\"getQuickInputMode()\"\n [attr.aria-label]=\"quickFieldMeta.label || quickField\"\n (keydown.escape)=\"onQuickClear()\"\n (keypress)=\"onQuickNumericKeypress($event)\"\n (blur)=\"onQuickBlurFormat()\">\n </mat-form-field>\n\n \n </div>\n </div>\n\n\n <!-- QUICK \u201Cfalso\u201D (quando n\u00E3o h\u00E1 meta) -->\n <ng-template #fallbackQuick>\n <div class=\"filter-anchor quick-shell\" #anchorRef=\"cdkOverlayOrigin\" cdkOverlayOrigin>\n <mat-form-field appearance=\"outline\" floatLabel=\"always\" class=\"fallback-quick-field\">\n <mat-label>{{ i18nLabels.searchPlaceholder }}</mat-label>\n <input matInput [formControl]=\"quickControl\"\n [attr.aria-label]=\"i18nLabels.searchPlaceholder\"\n (keydown.escape)=\"onQuickClear()\" />\n </mat-form-field>\n </div>\n </ng-template>\n </ng-container>\n\n <ng-template #noQuick></ng-template>\n\n <!-- A\u00C7\u00D5ES INLINE (fixas \u00E0 direita da barra) -->\n <div class=\"inline-actions\" [class.actions-outlined]=\"actionsVariant==='outlined'\">\n <!-- Anchor de overlay quando n\u00E3o h\u00E1 Quick -->\n <div *ngIf=\"!showQuickBar()\" class=\"actions-anchor\" #anchorRef=\"cdkOverlayOrigin\" cdkOverlayOrigin></div>\n <!-- Toggles/booleans simples realocados para a barra de a\u00E7\u00F5es -->\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 <button mat-icon-button [color]=\"actionsButtonColor==='basic'? null : actionsButtonColor\" type=\"button\" *ngIf=\"quickHasValue()\"\n (click)=\"onQuickClear()\" [attr.aria-label]=\"i18nLabels.clear\">\n <mat-icon [praxisIcon]=\"'close'\"></mat-icon>\n </button>\n <button mat-icon-button [color]=\"actionsButtonColor==='basic'? null : actionsButtonColor\" type=\"button\" (click)=\"onSubmit()\" [attr.aria-label]=\"i18nLabels.apply\">\n <mat-icon [praxisIcon]=\"'search'\"></mat-icon>\n </button>\n <button mat-icon-button [color]=\"actionsButtonColor==='basic'? null : actionsButtonColor\" type=\"button\"\n [matBadge]=\"activeFiltersCount\"\n [matBadgeHidden]=\"!activeFiltersCount\"\n matBadgeSize=\"small\"\n matBadgeColor=\"primary\"\n [matBadgeOverlap]=\"false\"\n (click)=\"toggleAdvanced()\"\n [attr.aria-label]=\"getAdvancedAriaLabel()\"\n [attr.aria-expanded]=\"advancedOpen\"\n [attr.aria-controls]=\"advancedPanelId\">\n <mat-icon [praxisIcon]=\"'tune'\"></mat-icon>\n </button>\n <button mat-icon-button [color]=\"actionsButtonColor==='basic'? null : actionsButtonColor\" type=\"button\" (click)=\"openSettings()\" *ngIf=\"showFilterSettings\"\n [matBadge]=\"schemaOutdated ? '!' : ''\"\n [matBadgeHidden]=\"!schemaOutdated\"\n 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 <!-- campos sempre vis\u00EDveis (se houver) -->\n <div class=\"always-fields\" *ngIf=\"alwaysVisibleMetas.length\">\n <ng-container dynamicFieldLoader [fields]=\"alwaysVisibleMetas\" [formGroup]=\"alwaysForm\"\n (componentsCreated)=\"onAlwaysComponents($event)\"></ng-container>\n </div>\n\n <!-- acessibilidade -->\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 <!-- tags -->\n <div class=\"praxis-filter-tags\" *ngIf=\"displayedTags.length\" [class.outlined]=\"tagVariant==='outlined'\">\n <mat-chip-set>\n <mat-chip *ngFor=\"let tag of displayedTags\"\n [color]=\"tagColor === 'basic' ? null : tagColor\"\n (click)=\"applyTag(tag)\" (keydown.enter)=\"applyTag(tag)\"\n tabindex=\"0\" role=\"button\">\n <ng-container *ngIf=\"editingTagId !== tag.id; else editChip\">\n <span class=\"chip-label\">{{ tag.label }}</span>\n <span class=\"chip-actions\" *ngIf=\"isUserTag(tag)\">\n <button mat-icon-button [color]=\"tagButtonColor === 'basic' ? null : tagButtonColor\"\n (click)=\"startEditTag(tag, $event)\" aria-label=\"edit tag\">\n <mat-icon>edit</mat-icon>\n </button>\n <button mat-icon-button [color]=\"tagButtonColor === 'basic' ? null : tagButtonColor\"\n (click)=\"deleteTag(tag)\" aria-label=\"remove tag\">\n <mat-icon>close</mat-icon>\n </button>\n </span>\n </ng-container>\n <ng-template #editChip>\n <input matInput class=\"chip-editor\" [formControl]=\"editingTagLabel\"\n (keydown.enter)=\"commitEditTag(tag, $event)\" (keydown.escape)=\"cancelEditTag($event)\" (click)=\"$event.stopPropagation()\" />\n <button mat-button color=\"primary\" (click)=\"commitEditTag(tag, $event)\">{{ i18nLabels.save }}</button>\n <button mat-button (click)=\"cancelEditTag($event)\">{{ i18nLabels.cancel }}</button>\n </ng-template>\n </mat-chip>\n </mat-chip-set>\n </div>\n\n <!-- OVERLAY -->\n <ng-container *ngIf=\"overlayOrigin\">\n <ng-template cdkConnectedOverlay\n [cdkConnectedOverlayOrigin]=\"overlayOrigin!\"\n [cdkConnectedOverlayOpen]=\"advancedOpen\"\n [cdkConnectedOverlayHasBackdrop]=\"overlayBackdrop\"\n [cdkConnectedOverlayBackdropClass]=\"'praxis-overlay-backdrop'\"\n [cdkConnectedOverlayPositions]=\"overlayPositions\"\n [cdkConnectedOverlayFlexibleDimensions]=\"true\"\n [cdkConnectedOverlayPush]=\"true\"\n [cdkConnectedOverlayOffsetY]=\"8\"\n [cdkConnectedOverlayLockPosition]=\"true\"\n [cdkConnectedOverlayWidth]=\"overlayWidth\"\n [cdkConnectedOverlayPanelClass]=\"['praxis-filter-overlay', isMobile ? 'mobile' : '', overlayVariant === 'frosted' ? 'frosted' : '']\"\n (overlayOutsideClick)=\"onOverlayOutsideClick($event)\"\n (backdropClick)=\"onOverlayDetach()\"\n (detach)=\"onOverlayDetach()\">\n <div class=\"praxis-filter-advanced\" (keydown.escape)=\"toggleAdvanced()\" (keydown.enter)=\"onAdvancedSubmit({ formData: (advancedForm?.getRawValue?.() || {}) })\" role=\"dialog\" aria-modal=\"true\" [attr.id]=\"advancedPanelId\">\n <div class=\"advanced-body\">\n <mat-progress-bar *ngIf=\"schemaLoading\" mode=\"indeterminate\"></mat-progress-bar>\n <p *ngIf=\"schemaError\" class=\"schema-error\">\n {{ i18nLabels.errorLoadingFilters }}\n <button mat-button type=\"button\" (click)=\"loadSchema()\">{{ i18nLabels.retry }}</button>\n </p>\n <praxis-filter-form *ngIf=\"!schemaLoading && !schemaError && advancedConfig\"\n [formId]=\"formId\" [resourcePath]=\"resourcePath\" [mode]=\"'edit'\" [config]=\"advancedConfig\"\n (formReady)=\"onAdvancedReady($event)\" (valueChange)=\"onAdvancedChange($event)\"\n (validityChange)=\"onAdvancedValidityChange($event)\" (submit)=\"onAdvancedSubmit($event)\">\n </praxis-filter-form>\n <p *ngIf=\"!schemaLoading && !schemaError && !advancedConfig\">{{ i18nLabels.noData }}</p>\n </div>\n <div class=\"advanced-actions\" *ngIf=\"!schemaLoading && !schemaError && advancedConfig\">\n <button mat-button type=\"button\" *ngIf=\"allowSaveTags && activeFiltersCount\" (click)=\"saveCurrentAsTag()\">\n {{ i18nLabels.saveAsShortcut }}\n </button>\n <button mat-raised-button color=\"primary\" type=\"button\"\n (click)=\"onAdvancedSubmit({ formData: (advancedForm?.getRawValue?.() || {}) })\"\n [disabled]=\"!advancedValid\">\n {{ i18nLabels.apply }}\n </button>\n <button mat-button type=\"button\" (click)=\"onClear()\">{{ i18nLabels.clear }}</button>\n </div>\n </div>\n </ng-template>\n </ng-container>\n</ng-container>\n\n<!-- resumo -->\n<ng-template #summaryCard>\n <div class=\"praxis-filter-card\" (keydown.escape)=\"onClear()\">\n <div class=\"summary-header\">\n <img *ngIf=\"currentSummaryMap?.avatar?.(currentSummary)\" [src]=\"currentSummaryMap?.avatar?.(currentSummary)\"\n class=\"summary-avatar\" alt=\"\" />\n <div class=\"summary-text\">\n <div class=\"summary-title\">{{ currentSummaryMap?.title?.(currentSummary) || '' }}</div>\n <div class=\"summary-subtitle\" *ngIf=\"currentSummaryMap?.subtitle\">{{ currentSummaryMap?.subtitle?.(currentSummary) }}</div>\n </div>\n </div>\n <div class=\"summary-badges\" *ngIf=\"currentSummaryMap?.badges?.length\">\n <span *ngFor=\"let b of currentSummaryMap!.badges\">{{ b(currentSummary) }}</span>\n </div>\n <div class=\"card-actions\">\n <button mat-button type=\"button\" (click)=\"switchToFilter()\">{{ i18nLabels.edit }}</button>\n <button mat-button type=\"button\" (click)=\"onClear()\">{{ i18nLabels.clear }}</button>\n </div>\n </div>\n</ng-template>\n", styles: ["@charset \"UTF-8\";:root{--pfx-filter-h: 40px;--pfx-filter-align-offset: 2px;--pfx-gap-x: 16px;--pfx-gap-y: 12px;--pfx-quick-pad-top: 5px;--pfx-quick-pad-left: 12px;--pfx-advanced-pad-x: 24px;--pfx-field-min: 280px;--pfx-quick-bg: var(--surface-2, #232a32);--pfx-quick-border: var(--pfx-surface-border, rgba(255,255,255,.08));--pfx-quick-radius: 12px}.praxis-filter-bar{display:grid;width:100%;grid-template-columns:1fr auto;grid-template-areas:\"quick actions\" \"always always\";column-gap:0;row-gap:8px;align-items:center}:host.debug-layout{background-image:repeating-linear-gradient(to right,rgba(147,197,253,.08) 0,rgba(147,197,253,.08) 1px,transparent 1px,transparent var(--pfx-gap-x)),repeating-linear-gradient(to bottom,rgba(163,230,53,.08) 0,rgba(163,230,53,.08) 1px,transparent 1px,transparent 8px)}:host.debug-layout .praxis-filter-bar{outline:1px dashed #f59e0b}:host.debug-layout .quick-shell{outline:1px dashed #3b82f6}:host.debug-layout .always-fields{outline:1px dashed #22c55e}:host.debug-layout .praxis-filter-overlay .praxis-filter-advanced{outline:2px solid #a855f7}.quick-field{grid-area:quick;min-width:280px;align-self:center}.inline-actions{grid-area:actions;justify-self:end}.always-fields{grid-area:always}.inline-actions .actions-anchor{width:0;height:0;overflow:hidden}.quick-shell{min-height:var(--pfx-filter-h);padding:0 0 0 var(--pfx-quick-pad-left);display:flex;align-items:center;flex-wrap:nowrap;gap:6px;overflow:hidden;background:var(--pfx-quick-bg);border:1px solid var(--pfx-quick-border);border-right:none;border-radius:var(--pfx-quick-radius) 0 0 var(--pfx-quick-radius)}.quick-shell>*{flex:1 1 auto;min-width:0}.quick-field-host{display:contents}:host ::ng-deep .quick-shell .mat-mdc-form-field{width:100%!important;flex:1 1 auto}:host ::ng-deep .quick-shell .mat-mdc-form-field{margin:0!important}:host ::ng-deep .quick-shell pdx-text-input,:host ::ng-deep .quick-shell pdx-select,:host ::ng-deep .quick-shell pdx-date-input,:host ::ng-deep .quick-shell pdx-auto-complete{flex:1 1 auto;min-width:0;display:block}.inline-actions{flex:0 0 auto;display:flex;gap:4px;align-self:start;white-space:nowrap;height:var(--pfx-filter-h);align-items:center;background:var(--pfx-quick-bg);border:1px solid var(--pfx-quick-border);border-left:none;border-radius:0 var(--pfx-quick-radius) var(--pfx-quick-radius) 0;padding-right:4px;margin-left:-1px}.inline-actions.actions-outlined button.mat-mdc-icon-button{border:1px solid var(--pfx-quick-border);border-radius:50%}.inline-actions .mat-mdc-icon-button{width:36px;height:36px}.inline-actions mat-icon{width:20px;height:20px;font-size:20px}.fallback-quick-field{height:var(--pfx-filter-h);display:flex;align-items:center}:host ::ng-deep .fallback-quick-field .mat-mdc-text-field-wrapper.mdc-text-field--outlined{height:var(--pfx-filter-h);align-items:center;padding-top:var(--pfx-quick-pad-top)}:host ::ng-deep .quick-shell .mat-mdc-text-field-wrapper.mdc-text-field--outlined{min-height:var(--pfx-filter-h);align-items:center;padding-top:var(--pfx-quick-pad-top)}:host ::ng-deep .quick-shell .mat-mdc-form-field-infix{min-height:var(--pfx-filter-h);padding-top:8px}:host ::ng-deep .quick-shell .mat-mdc-select-trigger{height:var(--pfx-filter-h);align-items:center}:host ::ng-deep .quick-shell .mat-mdc-form-field-subscript-wrapper{display:none}:host ::ng-deep .quick-shell .mdc-line-ripple{display:none!important}.always-fields{display:grid;grid-template-columns:repeat(auto-fit,minmax(var(--pfx-always-min, 300px),1fr));gap:8px}:host ::ng-deep .always-fields .mat-mdc-text-field-wrapper.mdc-text-field--outlined{min-height:var(--pfx-filter-h);align-items:center}:host ::ng-deep .always-fields .mat-mdc-form-field-infix{min-height:var(--pfx-filter-h)}:host ::ng-deep .always-fields .mat-mdc-select-trigger{height:var(--pfx-filter-h);align-items:center}:host ::ng-deep .always-fields .mat-mdc-form-field{width:100%}.praxis-filter-tags{display:flex;flex-wrap:wrap;gap:6px}.praxis-filter-tags mat-chip{border-radius:16px;padding:0 6px}.praxis-filter-tags .chip-actions{display:inline-flex;align-items:center;gap:2px;margin-left:4px}.chip-editor{width:140px;margin-right:8px}.praxis-filter-tags.outlined mat-chip{background:transparent!important;border:1px solid var(--pfx-quick-border)}.praxis-filter-advanced{display:flex;flex-direction:column;min-width:400px;max-width:90vw;min-height:260px;max-height:80vh;margin-top:25px;margin-right:15px;margin-left:25px;background:var(--md-sys-color-surface-container, #2a3038)!important;background-color:var(--md-sys-color-surface-container, #2a3038)!important;background:color-mix(in srgb,var(--md-sys-color-surface-container, #2a3038),transparent 6%)!important;color:var(--md-sys-color-on-surface, #e6eaf2);border:1px solid var(--border-color);border-radius:12px;box-shadow:0 8px 24px #00000052,0 2px 8px #0000002e}.praxis-filter-overlay.mobile .praxis-filter-advanced{height:100vh;max-height:100vh}:host ::ng-deep .praxis-overlay-backdrop{background:#0006;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px)}.advanced-body{padding:var(--pfx-gap-y) 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:var(--md-sys-color-surface-container, #2a3038)!important;background-color:var(--md-sys-color-surface-container, #2a3038)!important;background:color-mix(in srgb,var(--md-sys-color-surface-container, #2a3038),transparent 0%)!important;border-top:1px solid var(--border-color);box-shadow:0 -1px #0000002e}.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(--md-sys-color-on-surface-variant);--mdc-outlined-text-field-input-text-color: var(--md-sys-color-on-surface);--mdc-outlined-text-field-container-color: var(--md-sys-color-surface-container, #2a3038);--mdc-outlined-text-field-container-color: color-mix(in srgb, var(--md-sys-color-surface-container, #2a3038), transparent 90%)}: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(--md-sys-color-on-surface)}@media (min-width: 600px){.always-fields{grid-template-columns:repeat(var(--pfx-always-cols-md, 2),minmax(0,1fr))}:host ::ng-deep .praxis-filter-advanced .praxis-filter-form .filter-row{grid-template-columns:repeat(2,minmax(0,1fr))}}@media (min-width: 960px){.always-fields{grid-template-columns:repeat(var(--pfx-always-cols-lg, 3),minmax(0,1fr))}}.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: 240px}.praxis-filter-card{display:flex;flex-direction:column;gap:6px;padding:8px 12px;border-radius:12px;border:1px solid var(--pfx-quick-border);background:var(--pfx-quick-bg);color:var(--md-sys-color-on-surface, #2B2A28)}.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:color-mix(in oklab,var(--md-sys-color-primary, #3FBCA5),transparent 88%);border:1px solid color-mix(in oklab,var(--md-sys-color-primary, #3FBCA5),transparent 70%);color:var(--md-sys-color-on-surface, #2B2A28);font-size:12px}.praxis-filter-card .card-actions{display:flex;gap:8px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.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: i3$1.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i3$1.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i6.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: i11.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: i11.MatChipSet, selector: "mat-chip-set", inputs: ["disabled", "role", "tabIndex"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i4.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }, { kind: "ngmodule", type: MatBadgeModule }, { kind: "directive", type: i15.MatBadge, selector: "[matBadge]", inputs: ["matBadgeColor", "matBadgeOverlap", "matBadgeDisabled", "matBadgePosition", "matBadge", "matBadgeDescription", "matBadgeSize", "matBadgeHidden"] }, { kind: "ngmodule", type: MatProgressBarModule }, { kind: "component", type: i14$1.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: "directive", type: DynamicFieldLoaderDirective, selector: "[dynamicFieldLoader]", inputs: ["fields", "formGroup", "enableExternalControlBinding", "itemTemplate", "readonlyMode", "disabledMode", "presentationMode", "visible", "canvasMode"], outputs: ["componentsCreated", "fieldCreated", "fieldDestroyed", "canvasMouseEnter", "canvasMouseLeave", "canvasClick"] }, { kind: "component", type: PraxisFilterForm, selector: "praxis-filter-form", inputs: ["config", "formId", "resourcePath", "mode"], outputs: ["formReady", "valueChange", "submit", "validityChange"] }, { kind: "ngmodule", type: OverlayModule }, { kind: "directive", type: i19.CdkConnectedOverlay, selector: "[cdk-connected-overlay], [connected-overlay], [cdkConnectedOverlay]", inputs: ["cdkConnectedOverlayOrigin", "cdkConnectedOverlayPositions", "cdkConnectedOverlayPositionStrategy", "cdkConnectedOverlayOffsetX", "cdkConnectedOverlayOffsetY", "cdkConnectedOverlayWidth", "cdkConnectedOverlayHeight", "cdkConnectedOverlayMinWidth", "cdkConnectedOverlayMinHeight", "cdkConnectedOverlayBackdropClass", "cdkConnectedOverlayPanelClass", "cdkConnectedOverlayViewportMargin", "cdkConnectedOverlayScrollStrategy", "cdkConnectedOverlayOpen", "cdkConnectedOverlayDisableClose", "cdkConnectedOverlayTransformOriginOn", "cdkConnectedOverlayHasBackdrop", "cdkConnectedOverlayLockPosition", "cdkConnectedOverlayFlexibleDimensions", "cdkConnectedOverlayGrowAfterOpen", "cdkConnectedOverlayPush", "cdkConnectedOverlayDisposeOnNavigation"], outputs: ["backdropClick", "positionChange", "attach", "detach", "overlayKeydown", "overlayOutsideClick"], exportAs: ["cdkConnectedOverlay"] }, { kind: "directive", type: i19.CdkOverlayOrigin, selector: "[cdk-overlay-origin], [overlay-origin], [cdkOverlayOrigin]", exportAs: ["cdkOverlayOrigin"] }, { kind: "ngmodule", type: MatDialogModule }] });
|
|
21432
21527
|
}
|
|
21433
21528
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: PraxisFilter, decorators: [{
|
|
21434
21529
|
type: Component,
|
|
@@ -21454,7 +21549,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImpor
|
|
|
21454
21549
|
'[style.--pfx-always-min]': 'alwaysMinWidth + "px"',
|
|
21455
21550
|
'[style.--pfx-always-cols-md]': 'alwaysColsMd',
|
|
21456
21551
|
'[style.--pfx-always-cols-lg]': 'alwaysColsLg',
|
|
21457
|
-
}, template: "<ng-container *ngIf=\"modeState === 'filter'; else summaryCard\">\n <mat-progress-bar *ngIf=\"saving\" mode=\"indeterminate\"></mat-progress-bar>\n\n <form class=\"praxis-filter-bar\" [class.is-open]=\"advancedOpen\" (submit)=\"onSubmit(); $event.preventDefault()\">\n <!-- QUICK FIELD -->\n <div class=\"quick-field\" *ngIf=\"quickFieldMeta; else fallbackQuick\">\n <div class=\"filter-anchor quick-shell\" #anchorRef=\"cdkOverlayOrigin\" cdkOverlayOrigin>\n\n <!-- din\u00E2mico: envolvido por host para garantir layout flex correto -->\n <div *ngIf=\"quickFieldMode === 'dynamic'\" class=\"quick-field-host\" #quickHostRef\n dynamicFieldLoader\n [fields]=\"quickFieldMetaArray\"\n [formGroup]=\"quickForm\"\n (componentsCreated)=\"onQuickComponents($event)\"\n (fieldCreated)=\"onQuickFieldCreated($event)\">\n </div>\n\n <!-- fallback (com meta) \u2014 sem suffix, s\u00F3 o input -->\n <mat-form-field *ngIf=\"quickFieldMode === 'fallback'\"\n appearance=\"outline\"\n floatLabel=\"always\"\n class=\"fallback-quick-field\">\n <mat-label>{{ quickFieldMeta.label || quickField }}</mat-label>\n <input matInput [formControl]=\"quickControl\"\n [type]=\"getQuickInputType()\"\n [attr.inputmode]=\"getQuickInputMode()\"\n [attr.aria-label]=\"quickFieldMeta.label || quickField\"\n (keydown.escape)=\"onQuickClear()\"\n (keypress)=\"onQuickNumericKeypress($event)\"\n (blur)=\"onQuickBlurFormat()\">\n </mat-form-field>\n\n \n </div>\n </div>\n\n\n <!-- QUICK \u201Cfalso\u201D (quando n\u00E3o h\u00E1 meta) -->\n <ng-template #fallbackQuick>\n <div class=\"filter-anchor quick-shell\" #anchorRef=\"cdkOverlayOrigin\" cdkOverlayOrigin>\n <mat-form-field appearance=\"outline\" floatLabel=\"always\" class=\"fallback-quick-field\">\n <mat-label>{{ i18nLabels.searchPlaceholder }}</mat-label>\n <input matInput [formControl]=\"quickControl\"\n [attr.aria-label]=\"i18nLabels.searchPlaceholder\"\n (keydown.escape)=\"onQuickClear()\" />\n </mat-form-field>\n </div>\n </ng-template>\n\n <!-- A\u00C7\u00D5ES INLINE (fixas \u00E0 direita da barra) -->\n <div class=\"inline-actions\" [class.actions-outlined]=\"actionsVariant==='outlined'\">\n <!-- Toggles/booleans simples realocados para a barra de a\u00E7\u00F5es -->\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 <button mat-icon-button [color]=\"actionsButtonColor==='basic'? null : actionsButtonColor\" type=\"button\" *ngIf=\"quickHasValue()\"\n (click)=\"onQuickClear()\" [attr.aria-label]=\"i18nLabels.clear\">\n <mat-icon [praxisIcon]=\"'close'\"></mat-icon>\n </button>\n <button mat-icon-button [color]=\"actionsButtonColor==='basic'? null : actionsButtonColor\" type=\"button\" (click)=\"onSubmit()\" [attr.aria-label]=\"i18nLabels.apply\">\n <mat-icon [praxisIcon]=\"'search'\"></mat-icon>\n </button>\n <button mat-icon-button [color]=\"actionsButtonColor==='basic'? null : actionsButtonColor\" type=\"button\"\n [matBadge]=\"activeFiltersCount\"\n [matBadgeHidden]=\"!activeFiltersCount\"\n matBadgeSize=\"small\"\n matBadgeColor=\"primary\"\n [matBadgeOverlap]=\"false\"\n (click)=\"toggleAdvanced()\"\n [attr.aria-label]=\"getAdvancedAriaLabel()\"\n [attr.aria-expanded]=\"advancedOpen\"\n [attr.aria-controls]=\"advancedPanelId\">\n <mat-icon [praxisIcon]=\"'tune'\"></mat-icon>\n </button>\n <button mat-icon-button [color]=\"actionsButtonColor==='basic'? null : actionsButtonColor\" type=\"button\" (click)=\"openSettings()\" *ngIf=\"showFilterSettings\"\n [matBadge]=\"schemaOutdated ? '!' : ''\"\n [matBadgeHidden]=\"!schemaOutdated\"\n 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 <!-- campos sempre vis\u00EDveis (se houver) -->\n <div class=\"always-fields\" *ngIf=\"alwaysVisibleMetas.length\">\n <ng-container dynamicFieldLoader [fields]=\"alwaysVisibleMetas\" [formGroup]=\"alwaysForm\"\n (componentsCreated)=\"onAlwaysComponents($event)\"></ng-container>\n </div>\n\n <!-- acessibilidade -->\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 <!-- tags -->\n <div class=\"praxis-filter-tags\" *ngIf=\"displayedTags.length\" [class.outlined]=\"tagVariant==='outlined'\">\n <mat-chip-set>\n <mat-chip *ngFor=\"let tag of displayedTags\"\n [color]=\"tagColor === 'basic' ? null : tagColor\"\n (click)=\"applyTag(tag)\" (keydown.enter)=\"applyTag(tag)\"\n tabindex=\"0\" role=\"button\">\n <ng-container *ngIf=\"editingTagId !== tag.id; else editChip\">\n <span class=\"chip-label\">{{ tag.label }}</span>\n <span class=\"chip-actions\" *ngIf=\"isUserTag(tag)\">\n <button mat-icon-button [color]=\"tagButtonColor === 'basic' ? null : tagButtonColor\"\n (click)=\"startEditTag(tag, $event)\" aria-label=\"edit tag\">\n <mat-icon>edit</mat-icon>\n </button>\n <button mat-icon-button [color]=\"tagButtonColor === 'basic' ? null : tagButtonColor\"\n (click)=\"deleteTag(tag)\" aria-label=\"remove tag\">\n <mat-icon>close</mat-icon>\n </button>\n </span>\n </ng-container>\n <ng-template #editChip>\n <input matInput class=\"chip-editor\" [formControl]=\"editingTagLabel\"\n (keydown.enter)=\"commitEditTag(tag, $event)\" (keydown.escape)=\"cancelEditTag($event)\" (click)=\"$event.stopPropagation()\" />\n <button mat-button color=\"primary\" (click)=\"commitEditTag(tag, $event)\">{{ i18nLabels.save }}</button>\n <button mat-button (click)=\"cancelEditTag($event)\">{{ i18nLabels.cancel }}</button>\n </ng-template>\n </mat-chip>\n </mat-chip-set>\n </div>\n\n <!-- OVERLAY -->\n <ng-container *ngIf=\"overlayOrigin\">\n <ng-template cdkConnectedOverlay\n [cdkConnectedOverlayOrigin]=\"overlayOrigin!\"\n [cdkConnectedOverlayOpen]=\"advancedOpen\"\n [cdkConnectedOverlayHasBackdrop]=\"overlayBackdrop\"\n [cdkConnectedOverlayBackdropClass]=\"'praxis-overlay-backdrop'\"\n [cdkConnectedOverlayPositions]=\"overlayPositions\"\n [cdkConnectedOverlayFlexibleDimensions]=\"true\"\n [cdkConnectedOverlayPush]=\"true\"\n [cdkConnectedOverlayOffsetY]=\"8\"\n [cdkConnectedOverlayLockPosition]=\"true\"\n [cdkConnectedOverlayWidth]=\"overlayWidth\"\n [cdkConnectedOverlayPanelClass]=\"['praxis-filter-overlay', isMobile ? 'mobile' : '', overlayVariant === 'frosted' ? 'frosted' : '']\"\n (overlayOutsideClick)=\"onOverlayOutsideClick($event)\"\n (backdropClick)=\"onOverlayDetach()\"\n (detach)=\"onOverlayDetach()\">\n <div class=\"praxis-filter-advanced\" (keydown.escape)=\"toggleAdvanced()\" role=\"dialog\" aria-modal=\"true\" [attr.id]=\"advancedPanelId\">\n <div class=\"advanced-body\">\n <mat-progress-bar *ngIf=\"schemaLoading\" mode=\"indeterminate\"></mat-progress-bar>\n <p *ngIf=\"schemaError\" class=\"schema-error\">\n {{ i18nLabels.errorLoadingFilters }}\n <button mat-button type=\"button\" (click)=\"loadSchema()\">{{ i18nLabels.retry }}</button>\n </p>\n <praxis-filter-form *ngIf=\"!schemaLoading && !schemaError && advancedConfig\"\n [formId]=\"formId\" [resourcePath]=\"resourcePath\" [mode]=\"'edit'\" [config]=\"advancedConfig\"\n (formReady)=\"onAdvancedReady($event)\" (valueChange)=\"onAdvancedChange($event)\"\n (validityChange)=\"onAdvancedValidityChange($event)\" (submit)=\"onAdvancedSubmit($event)\">\n </praxis-filter-form>\n <p *ngIf=\"!schemaLoading && !schemaError && !advancedConfig\">{{ i18nLabels.noData }}</p>\n </div>\n <div class=\"advanced-actions\" *ngIf=\"!schemaLoading && !schemaError && advancedConfig\">\n <button mat-raised-button color=\"primary\" type=\"button\"\n (click)=\"onAdvancedSubmit({ formData: (advancedForm?.getRawValue?.() || {}) })\"\n [disabled]=\"!advancedValid\">\n {{ i18nLabels.apply }}\n </button>\n <button mat-button type=\"button\" (click)=\"onClear()\">{{ i18nLabels.clear }}</button>\n </div>\n </div>\n </ng-template>\n </ng-container>\n</ng-container>\n\n<!-- resumo -->\n<ng-template #summaryCard>\n <div class=\"praxis-filter-card\" (keydown.escape)=\"onClear()\">\n <div class=\"summary-header\">\n <img *ngIf=\"currentSummaryMap?.avatar?.(currentSummary)\" [src]=\"currentSummaryMap?.avatar?.(currentSummary)\"\n class=\"summary-avatar\" alt=\"\" />\n <div class=\"summary-text\">\n <div class=\"summary-title\">{{ currentSummaryMap?.title?.(currentSummary) || '' }}</div>\n <div class=\"summary-subtitle\" *ngIf=\"currentSummaryMap?.subtitle\">{{ currentSummaryMap?.subtitle?.(currentSummary) }}</div>\n </div>\n </div>\n <div class=\"summary-badges\" *ngIf=\"currentSummaryMap?.badges?.length\">\n <span *ngFor=\"let b of currentSummaryMap!.badges\">{{ b(currentSummary) }}</span>\n </div>\n <div class=\"card-actions\">\n <button mat-button type=\"button\" (click)=\"switchToFilter()\">{{ i18nLabels.edit }}</button>\n <button mat-button type=\"button\" (click)=\"onClear()\">{{ i18nLabels.clear }}</button>\n </div>\n </div>\n</ng-template>\n", styles: ["@charset \"UTF-8\";:root{--pfx-filter-h: 40px;--pfx-filter-align-offset: 2px;--pfx-gap-x: 16px;--pfx-gap-y: 12px;--pfx-quick-pad-top: 5px;--pfx-quick-pad-left: 12px;--pfx-advanced-pad-x: 24px;--pfx-field-min: 280px;--pfx-quick-bg: var(--surface-2, #232a32);--pfx-quick-border: var(--pfx-surface-border, rgba(255,255,255,.08));--pfx-quick-radius: 12px}.praxis-filter-bar{display:grid;width:100%;grid-template-columns:1fr auto;grid-template-areas:\"quick actions\" \"always always\";column-gap:0;row-gap:8px;align-items:center}:host.debug-layout{background-image:repeating-linear-gradient(to right,rgba(147,197,253,.08) 0,rgba(147,197,253,.08) 1px,transparent 1px,transparent var(--pfx-gap-x)),repeating-linear-gradient(to bottom,rgba(163,230,53,.08) 0,rgba(163,230,53,.08) 1px,transparent 1px,transparent 8px)}:host.debug-layout .praxis-filter-bar{outline:1px dashed #f59e0b}:host.debug-layout .quick-shell{outline:1px dashed #3b82f6}:host.debug-layout .always-fields{outline:1px dashed #22c55e}:host.debug-layout .praxis-filter-overlay .praxis-filter-advanced{outline:2px solid #a855f7}.quick-field{grid-area:quick;min-width:280px;align-self:center}.inline-actions{grid-area:actions;justify-self:end}.always-fields{grid-area:always}.quick-shell{min-height:var(--pfx-filter-h);padding:0 0 0 var(--pfx-quick-pad-left);display:flex;align-items:center;flex-wrap:nowrap;gap:6px;overflow:hidden;background:var(--pfx-quick-bg);border:1px solid var(--pfx-quick-border);border-right:none;border-radius:var(--pfx-quick-radius) 0 0 var(--pfx-quick-radius)}.quick-shell>*{flex:1 1 auto;min-width:0}.quick-field-host{display:contents}:host ::ng-deep .quick-shell .mat-mdc-form-field{width:100%!important;flex:1 1 auto}:host ::ng-deep .quick-shell .mat-mdc-form-field{margin:0!important}:host ::ng-deep .quick-shell pdx-text-input,:host ::ng-deep .quick-shell pdx-select,:host ::ng-deep .quick-shell pdx-date-input,:host ::ng-deep .quick-shell pdx-auto-complete{flex:1 1 auto;min-width:0;display:block}.inline-actions{flex:0 0 auto;display:flex;gap:4px;align-self:start;white-space:nowrap;height:var(--pfx-filter-h);align-items:center;background:var(--pfx-quick-bg);border:1px solid var(--pfx-quick-border);border-left:none;border-radius:0 var(--pfx-quick-radius) var(--pfx-quick-radius) 0;padding-right:4px;margin-left:-1px}.inline-actions.actions-outlined button.mat-mdc-icon-button{border:1px solid var(--pfx-quick-border);border-radius:50%}.inline-actions .mat-mdc-icon-button{width:36px;height:36px}.inline-actions mat-icon{width:20px;height:20px;font-size:20px}.fallback-quick-field{height:var(--pfx-filter-h);display:flex;align-items:center}:host ::ng-deep .fallback-quick-field .mat-mdc-text-field-wrapper.mdc-text-field--outlined{height:var(--pfx-filter-h);align-items:center;padding-top:var(--pfx-quick-pad-top)}:host ::ng-deep .quick-shell .mat-mdc-text-field-wrapper.mdc-text-field--outlined{min-height:var(--pfx-filter-h);align-items:center;padding-top:var(--pfx-quick-pad-top)}:host ::ng-deep .quick-shell .mat-mdc-form-field-infix{min-height:var(--pfx-filter-h);padding-top:8px}:host ::ng-deep .quick-shell .mat-mdc-select-trigger{height:var(--pfx-filter-h);align-items:center}:host ::ng-deep .quick-shell .mat-mdc-form-field-subscript-wrapper{display:none}:host ::ng-deep .quick-shell .mdc-line-ripple{display:none!important}.always-fields{display:grid;grid-template-columns:repeat(auto-fit,minmax(var(--pfx-always-min, 300px),1fr));gap:8px}:host ::ng-deep .always-fields .mat-mdc-text-field-wrapper.mdc-text-field--outlined{min-height:var(--pfx-filter-h);align-items:center}:host ::ng-deep .always-fields .mat-mdc-form-field-infix{min-height:var(--pfx-filter-h)}:host ::ng-deep .always-fields .mat-mdc-select-trigger{height:var(--pfx-filter-h);align-items:center}:host ::ng-deep .always-fields .mat-mdc-form-field{width:100%}.praxis-filter-tags{display:flex;flex-wrap:wrap;gap:6px}.praxis-filter-tags mat-chip{border-radius:16px;padding:0 6px}.praxis-filter-tags .chip-actions{display:inline-flex;align-items:center;gap:2px;margin-left:4px}.chip-editor{width:140px;margin-right:8px}.praxis-filter-tags.outlined mat-chip{background:transparent!important;border:1px solid var(--pfx-quick-border)}.praxis-filter-advanced{display:flex;flex-direction:column;min-width:400px;max-width:90vw;min-height:260px;max-height:80vh;margin-top:25px;margin-right:15px;margin-left:25px;background:var(--md-sys-color-surface-container, #2a3038)!important;background-color:var(--md-sys-color-surface-container, #2a3038)!important;background:color-mix(in srgb,var(--md-sys-color-surface-container, #2a3038),transparent 6%)!important;color:var(--md-sys-color-on-surface, #e6eaf2);border:1px solid var(--border-color);border-radius:12px;box-shadow:0 8px 24px #00000052,0 2px 8px #0000002e}.praxis-filter-overlay.mobile .praxis-filter-advanced{height:100vh;max-height:100vh}:host ::ng-deep .praxis-overlay-backdrop{background:#0006;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px)}.advanced-body{padding:var(--pfx-gap-y) 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:var(--md-sys-color-surface-container, #2a3038)!important;background-color:var(--md-sys-color-surface-container, #2a3038)!important;background:color-mix(in srgb,var(--md-sys-color-surface-container, #2a3038),transparent 0%)!important;border-top:1px solid var(--border-color);box-shadow:0 -1px #0000002e}.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(--md-sys-color-on-surface-variant);--mdc-outlined-text-field-input-text-color: var(--md-sys-color-on-surface);--mdc-outlined-text-field-container-color: var(--md-sys-color-surface-container, #2a3038);--mdc-outlined-text-field-container-color: color-mix(in srgb, var(--md-sys-color-surface-container, #2a3038), transparent 90%)}: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(--md-sys-color-on-surface)}@media (min-width: 600px){.always-fields{grid-template-columns:repeat(var(--pfx-always-cols-md, 2),minmax(0,1fr))}:host ::ng-deep .praxis-filter-advanced .praxis-filter-form .filter-row{grid-template-columns:repeat(2,minmax(0,1fr))}}@media (min-width: 960px){.always-fields{grid-template-columns:repeat(var(--pfx-always-cols-lg, 3),minmax(0,1fr))}}.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}.praxis-filter-card{display:flex;flex-direction:column;gap:6px;padding:8px 12px;border-radius:12px;border:1px solid var(--pfx-quick-border);background:var(--pfx-quick-bg);color:var(--md-sys-color-on-surface, #2B2A28)}.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:color-mix(in oklab,var(--md-sys-color-primary, #3FBCA5),transparent 88%);border:1px solid color-mix(in oklab,var(--md-sys-color-primary, #3FBCA5),transparent 70%);color:var(--md-sys-color-on-surface, #2B2A28);font-size:12px}.praxis-filter-card .card-actions{display:flex;gap:8px}\n"] }]
|
|
21552
|
+
}, template: "<ng-container *ngIf=\"modeState === 'filter'; else summaryCard\">\n <mat-progress-bar *ngIf=\"saving\" mode=\"indeterminate\"></mat-progress-bar>\n\n <form class=\"praxis-filter-bar\" [class.is-open]=\"advancedOpen\" (submit)=\"onSubmit(); $event.preventDefault()\">\n <!-- QUICK FIELD (oculto quando n\u00E3o h\u00E1 Quick e existem campos sempre vis\u00EDveis, salvo override) -->\n <ng-container *ngIf=\"showQuickBar(); else noQuick\">\n <div class=\"quick-field\" *ngIf=\"quickFieldMeta; else fallbackQuick\">\n <div class=\"filter-anchor quick-shell\" #anchorRef=\"cdkOverlayOrigin\" cdkOverlayOrigin>\n\n <!-- din\u00E2mico: envolvido por host para garantir layout flex correto -->\n <div *ngIf=\"quickFieldMode === 'dynamic'\" class=\"quick-field-host\" #quickHostRef\n dynamicFieldLoader\n [fields]=\"quickFieldMetaArray\"\n [formGroup]=\"quickForm\"\n (componentsCreated)=\"onQuickComponents($event)\"\n (fieldCreated)=\"onQuickFieldCreated($event)\">\n </div>\n\n <!-- fallback (com meta) \u2014 sem suffix, s\u00F3 o input -->\n <mat-form-field *ngIf=\"quickFieldMode === 'fallback'\"\n appearance=\"outline\"\n floatLabel=\"always\"\n class=\"fallback-quick-field\">\n <mat-label>{{ quickFieldMeta.label || quickField }}</mat-label>\n <input matInput [formControl]=\"quickControl\"\n [type]=\"getQuickInputType()\"\n [attr.inputmode]=\"getQuickInputMode()\"\n [attr.aria-label]=\"quickFieldMeta.label || quickField\"\n (keydown.escape)=\"onQuickClear()\"\n (keypress)=\"onQuickNumericKeypress($event)\"\n (blur)=\"onQuickBlurFormat()\">\n </mat-form-field>\n\n \n </div>\n </div>\n\n\n <!-- QUICK \u201Cfalso\u201D (quando n\u00E3o h\u00E1 meta) -->\n <ng-template #fallbackQuick>\n <div class=\"filter-anchor quick-shell\" #anchorRef=\"cdkOverlayOrigin\" cdkOverlayOrigin>\n <mat-form-field appearance=\"outline\" floatLabel=\"always\" class=\"fallback-quick-field\">\n <mat-label>{{ i18nLabels.searchPlaceholder }}</mat-label>\n <input matInput [formControl]=\"quickControl\"\n [attr.aria-label]=\"i18nLabels.searchPlaceholder\"\n (keydown.escape)=\"onQuickClear()\" />\n </mat-form-field>\n </div>\n </ng-template>\n </ng-container>\n\n <ng-template #noQuick></ng-template>\n\n <!-- A\u00C7\u00D5ES INLINE (fixas \u00E0 direita da barra) -->\n <div class=\"inline-actions\" [class.actions-outlined]=\"actionsVariant==='outlined'\">\n <!-- Anchor de overlay quando n\u00E3o h\u00E1 Quick -->\n <div *ngIf=\"!showQuickBar()\" class=\"actions-anchor\" #anchorRef=\"cdkOverlayOrigin\" cdkOverlayOrigin></div>\n <!-- Toggles/booleans simples realocados para a barra de a\u00E7\u00F5es -->\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 <button mat-icon-button [color]=\"actionsButtonColor==='basic'? null : actionsButtonColor\" type=\"button\" *ngIf=\"quickHasValue()\"\n (click)=\"onQuickClear()\" [attr.aria-label]=\"i18nLabels.clear\">\n <mat-icon [praxisIcon]=\"'close'\"></mat-icon>\n </button>\n <button mat-icon-button [color]=\"actionsButtonColor==='basic'? null : actionsButtonColor\" type=\"button\" (click)=\"onSubmit()\" [attr.aria-label]=\"i18nLabels.apply\">\n <mat-icon [praxisIcon]=\"'search'\"></mat-icon>\n </button>\n <button mat-icon-button [color]=\"actionsButtonColor==='basic'? null : actionsButtonColor\" type=\"button\"\n [matBadge]=\"activeFiltersCount\"\n [matBadgeHidden]=\"!activeFiltersCount\"\n matBadgeSize=\"small\"\n matBadgeColor=\"primary\"\n [matBadgeOverlap]=\"false\"\n (click)=\"toggleAdvanced()\"\n [attr.aria-label]=\"getAdvancedAriaLabel()\"\n [attr.aria-expanded]=\"advancedOpen\"\n [attr.aria-controls]=\"advancedPanelId\">\n <mat-icon [praxisIcon]=\"'tune'\"></mat-icon>\n </button>\n <button mat-icon-button [color]=\"actionsButtonColor==='basic'? null : actionsButtonColor\" type=\"button\" (click)=\"openSettings()\" *ngIf=\"showFilterSettings\"\n [matBadge]=\"schemaOutdated ? '!' : ''\"\n [matBadgeHidden]=\"!schemaOutdated\"\n 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 <!-- campos sempre vis\u00EDveis (se houver) -->\n <div class=\"always-fields\" *ngIf=\"alwaysVisibleMetas.length\">\n <ng-container dynamicFieldLoader [fields]=\"alwaysVisibleMetas\" [formGroup]=\"alwaysForm\"\n (componentsCreated)=\"onAlwaysComponents($event)\"></ng-container>\n </div>\n\n <!-- acessibilidade -->\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 <!-- tags -->\n <div class=\"praxis-filter-tags\" *ngIf=\"displayedTags.length\" [class.outlined]=\"tagVariant==='outlined'\">\n <mat-chip-set>\n <mat-chip *ngFor=\"let tag of displayedTags\"\n [color]=\"tagColor === 'basic' ? null : tagColor\"\n (click)=\"applyTag(tag)\" (keydown.enter)=\"applyTag(tag)\"\n tabindex=\"0\" role=\"button\">\n <ng-container *ngIf=\"editingTagId !== tag.id; else editChip\">\n <span class=\"chip-label\">{{ tag.label }}</span>\n <span class=\"chip-actions\" *ngIf=\"isUserTag(tag)\">\n <button mat-icon-button [color]=\"tagButtonColor === 'basic' ? null : tagButtonColor\"\n (click)=\"startEditTag(tag, $event)\" aria-label=\"edit tag\">\n <mat-icon>edit</mat-icon>\n </button>\n <button mat-icon-button [color]=\"tagButtonColor === 'basic' ? null : tagButtonColor\"\n (click)=\"deleteTag(tag)\" aria-label=\"remove tag\">\n <mat-icon>close</mat-icon>\n </button>\n </span>\n </ng-container>\n <ng-template #editChip>\n <input matInput class=\"chip-editor\" [formControl]=\"editingTagLabel\"\n (keydown.enter)=\"commitEditTag(tag, $event)\" (keydown.escape)=\"cancelEditTag($event)\" (click)=\"$event.stopPropagation()\" />\n <button mat-button color=\"primary\" (click)=\"commitEditTag(tag, $event)\">{{ i18nLabels.save }}</button>\n <button mat-button (click)=\"cancelEditTag($event)\">{{ i18nLabels.cancel }}</button>\n </ng-template>\n </mat-chip>\n </mat-chip-set>\n </div>\n\n <!-- OVERLAY -->\n <ng-container *ngIf=\"overlayOrigin\">\n <ng-template cdkConnectedOverlay\n [cdkConnectedOverlayOrigin]=\"overlayOrigin!\"\n [cdkConnectedOverlayOpen]=\"advancedOpen\"\n [cdkConnectedOverlayHasBackdrop]=\"overlayBackdrop\"\n [cdkConnectedOverlayBackdropClass]=\"'praxis-overlay-backdrop'\"\n [cdkConnectedOverlayPositions]=\"overlayPositions\"\n [cdkConnectedOverlayFlexibleDimensions]=\"true\"\n [cdkConnectedOverlayPush]=\"true\"\n [cdkConnectedOverlayOffsetY]=\"8\"\n [cdkConnectedOverlayLockPosition]=\"true\"\n [cdkConnectedOverlayWidth]=\"overlayWidth\"\n [cdkConnectedOverlayPanelClass]=\"['praxis-filter-overlay', isMobile ? 'mobile' : '', overlayVariant === 'frosted' ? 'frosted' : '']\"\n (overlayOutsideClick)=\"onOverlayOutsideClick($event)\"\n (backdropClick)=\"onOverlayDetach()\"\n (detach)=\"onOverlayDetach()\">\n <div class=\"praxis-filter-advanced\" (keydown.escape)=\"toggleAdvanced()\" (keydown.enter)=\"onAdvancedSubmit({ formData: (advancedForm?.getRawValue?.() || {}) })\" role=\"dialog\" aria-modal=\"true\" [attr.id]=\"advancedPanelId\">\n <div class=\"advanced-body\">\n <mat-progress-bar *ngIf=\"schemaLoading\" mode=\"indeterminate\"></mat-progress-bar>\n <p *ngIf=\"schemaError\" class=\"schema-error\">\n {{ i18nLabels.errorLoadingFilters }}\n <button mat-button type=\"button\" (click)=\"loadSchema()\">{{ i18nLabels.retry }}</button>\n </p>\n <praxis-filter-form *ngIf=\"!schemaLoading && !schemaError && advancedConfig\"\n [formId]=\"formId\" [resourcePath]=\"resourcePath\" [mode]=\"'edit'\" [config]=\"advancedConfig\"\n (formReady)=\"onAdvancedReady($event)\" (valueChange)=\"onAdvancedChange($event)\"\n (validityChange)=\"onAdvancedValidityChange($event)\" (submit)=\"onAdvancedSubmit($event)\">\n </praxis-filter-form>\n <p *ngIf=\"!schemaLoading && !schemaError && !advancedConfig\">{{ i18nLabels.noData }}</p>\n </div>\n <div class=\"advanced-actions\" *ngIf=\"!schemaLoading && !schemaError && advancedConfig\">\n <button mat-button type=\"button\" *ngIf=\"allowSaveTags && activeFiltersCount\" (click)=\"saveCurrentAsTag()\">\n {{ i18nLabels.saveAsShortcut }}\n </button>\n <button mat-raised-button color=\"primary\" type=\"button\"\n (click)=\"onAdvancedSubmit({ formData: (advancedForm?.getRawValue?.() || {}) })\"\n [disabled]=\"!advancedValid\">\n {{ i18nLabels.apply }}\n </button>\n <button mat-button type=\"button\" (click)=\"onClear()\">{{ i18nLabels.clear }}</button>\n </div>\n </div>\n </ng-template>\n </ng-container>\n</ng-container>\n\n<!-- resumo -->\n<ng-template #summaryCard>\n <div class=\"praxis-filter-card\" (keydown.escape)=\"onClear()\">\n <div class=\"summary-header\">\n <img *ngIf=\"currentSummaryMap?.avatar?.(currentSummary)\" [src]=\"currentSummaryMap?.avatar?.(currentSummary)\"\n class=\"summary-avatar\" alt=\"\" />\n <div class=\"summary-text\">\n <div class=\"summary-title\">{{ currentSummaryMap?.title?.(currentSummary) || '' }}</div>\n <div class=\"summary-subtitle\" *ngIf=\"currentSummaryMap?.subtitle\">{{ currentSummaryMap?.subtitle?.(currentSummary) }}</div>\n </div>\n </div>\n <div class=\"summary-badges\" *ngIf=\"currentSummaryMap?.badges?.length\">\n <span *ngFor=\"let b of currentSummaryMap!.badges\">{{ b(currentSummary) }}</span>\n </div>\n <div class=\"card-actions\">\n <button mat-button type=\"button\" (click)=\"switchToFilter()\">{{ i18nLabels.edit }}</button>\n <button mat-button type=\"button\" (click)=\"onClear()\">{{ i18nLabels.clear }}</button>\n </div>\n </div>\n</ng-template>\n", styles: ["@charset \"UTF-8\";:root{--pfx-filter-h: 40px;--pfx-filter-align-offset: 2px;--pfx-gap-x: 16px;--pfx-gap-y: 12px;--pfx-quick-pad-top: 5px;--pfx-quick-pad-left: 12px;--pfx-advanced-pad-x: 24px;--pfx-field-min: 280px;--pfx-quick-bg: var(--surface-2, #232a32);--pfx-quick-border: var(--pfx-surface-border, rgba(255,255,255,.08));--pfx-quick-radius: 12px}.praxis-filter-bar{display:grid;width:100%;grid-template-columns:1fr auto;grid-template-areas:\"quick actions\" \"always always\";column-gap:0;row-gap:8px;align-items:center}:host.debug-layout{background-image:repeating-linear-gradient(to right,rgba(147,197,253,.08) 0,rgba(147,197,253,.08) 1px,transparent 1px,transparent var(--pfx-gap-x)),repeating-linear-gradient(to bottom,rgba(163,230,53,.08) 0,rgba(163,230,53,.08) 1px,transparent 1px,transparent 8px)}:host.debug-layout .praxis-filter-bar{outline:1px dashed #f59e0b}:host.debug-layout .quick-shell{outline:1px dashed #3b82f6}:host.debug-layout .always-fields{outline:1px dashed #22c55e}:host.debug-layout .praxis-filter-overlay .praxis-filter-advanced{outline:2px solid #a855f7}.quick-field{grid-area:quick;min-width:280px;align-self:center}.inline-actions{grid-area:actions;justify-self:end}.always-fields{grid-area:always}.inline-actions .actions-anchor{width:0;height:0;overflow:hidden}.quick-shell{min-height:var(--pfx-filter-h);padding:0 0 0 var(--pfx-quick-pad-left);display:flex;align-items:center;flex-wrap:nowrap;gap:6px;overflow:hidden;background:var(--pfx-quick-bg);border:1px solid var(--pfx-quick-border);border-right:none;border-radius:var(--pfx-quick-radius) 0 0 var(--pfx-quick-radius)}.quick-shell>*{flex:1 1 auto;min-width:0}.quick-field-host{display:contents}:host ::ng-deep .quick-shell .mat-mdc-form-field{width:100%!important;flex:1 1 auto}:host ::ng-deep .quick-shell .mat-mdc-form-field{margin:0!important}:host ::ng-deep .quick-shell pdx-text-input,:host ::ng-deep .quick-shell pdx-select,:host ::ng-deep .quick-shell pdx-date-input,:host ::ng-deep .quick-shell pdx-auto-complete{flex:1 1 auto;min-width:0;display:block}.inline-actions{flex:0 0 auto;display:flex;gap:4px;align-self:start;white-space:nowrap;height:var(--pfx-filter-h);align-items:center;background:var(--pfx-quick-bg);border:1px solid var(--pfx-quick-border);border-left:none;border-radius:0 var(--pfx-quick-radius) var(--pfx-quick-radius) 0;padding-right:4px;margin-left:-1px}.inline-actions.actions-outlined button.mat-mdc-icon-button{border:1px solid var(--pfx-quick-border);border-radius:50%}.inline-actions .mat-mdc-icon-button{width:36px;height:36px}.inline-actions mat-icon{width:20px;height:20px;font-size:20px}.fallback-quick-field{height:var(--pfx-filter-h);display:flex;align-items:center}:host ::ng-deep .fallback-quick-field .mat-mdc-text-field-wrapper.mdc-text-field--outlined{height:var(--pfx-filter-h);align-items:center;padding-top:var(--pfx-quick-pad-top)}:host ::ng-deep .quick-shell .mat-mdc-text-field-wrapper.mdc-text-field--outlined{min-height:var(--pfx-filter-h);align-items:center;padding-top:var(--pfx-quick-pad-top)}:host ::ng-deep .quick-shell .mat-mdc-form-field-infix{min-height:var(--pfx-filter-h);padding-top:8px}:host ::ng-deep .quick-shell .mat-mdc-select-trigger{height:var(--pfx-filter-h);align-items:center}:host ::ng-deep .quick-shell .mat-mdc-form-field-subscript-wrapper{display:none}:host ::ng-deep .quick-shell .mdc-line-ripple{display:none!important}.always-fields{display:grid;grid-template-columns:repeat(auto-fit,minmax(var(--pfx-always-min, 300px),1fr));gap:8px}:host ::ng-deep .always-fields .mat-mdc-text-field-wrapper.mdc-text-field--outlined{min-height:var(--pfx-filter-h);align-items:center}:host ::ng-deep .always-fields .mat-mdc-form-field-infix{min-height:var(--pfx-filter-h)}:host ::ng-deep .always-fields .mat-mdc-select-trigger{height:var(--pfx-filter-h);align-items:center}:host ::ng-deep .always-fields .mat-mdc-form-field{width:100%}.praxis-filter-tags{display:flex;flex-wrap:wrap;gap:6px}.praxis-filter-tags mat-chip{border-radius:16px;padding:0 6px}.praxis-filter-tags .chip-actions{display:inline-flex;align-items:center;gap:2px;margin-left:4px}.chip-editor{width:140px;margin-right:8px}.praxis-filter-tags.outlined mat-chip{background:transparent!important;border:1px solid var(--pfx-quick-border)}.praxis-filter-advanced{display:flex;flex-direction:column;min-width:400px;max-width:90vw;min-height:260px;max-height:80vh;margin-top:25px;margin-right:15px;margin-left:25px;background:var(--md-sys-color-surface-container, #2a3038)!important;background-color:var(--md-sys-color-surface-container, #2a3038)!important;background:color-mix(in srgb,var(--md-sys-color-surface-container, #2a3038),transparent 6%)!important;color:var(--md-sys-color-on-surface, #e6eaf2);border:1px solid var(--border-color);border-radius:12px;box-shadow:0 8px 24px #00000052,0 2px 8px #0000002e}.praxis-filter-overlay.mobile .praxis-filter-advanced{height:100vh;max-height:100vh}:host ::ng-deep .praxis-overlay-backdrop{background:#0006;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px)}.advanced-body{padding:var(--pfx-gap-y) 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:var(--md-sys-color-surface-container, #2a3038)!important;background-color:var(--md-sys-color-surface-container, #2a3038)!important;background:color-mix(in srgb,var(--md-sys-color-surface-container, #2a3038),transparent 0%)!important;border-top:1px solid var(--border-color);box-shadow:0 -1px #0000002e}.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(--md-sys-color-on-surface-variant);--mdc-outlined-text-field-input-text-color: var(--md-sys-color-on-surface);--mdc-outlined-text-field-container-color: var(--md-sys-color-surface-container, #2a3038);--mdc-outlined-text-field-container-color: color-mix(in srgb, var(--md-sys-color-surface-container, #2a3038), transparent 90%)}: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(--md-sys-color-on-surface)}@media (min-width: 600px){.always-fields{grid-template-columns:repeat(var(--pfx-always-cols-md, 2),minmax(0,1fr))}:host ::ng-deep .praxis-filter-advanced .praxis-filter-form .filter-row{grid-template-columns:repeat(2,minmax(0,1fr))}}@media (min-width: 960px){.always-fields{grid-template-columns:repeat(var(--pfx-always-cols-lg, 3),minmax(0,1fr))}}.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: 240px}.praxis-filter-card{display:flex;flex-direction:column;gap:6px;padding:8px 12px;border-radius:12px;border:1px solid var(--pfx-quick-border);background:var(--pfx-quick-bg);color:var(--md-sys-color-on-surface, #2B2A28)}.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:color-mix(in oklab,var(--md-sys-color-primary, #3FBCA5),transparent 88%);border:1px solid color-mix(in oklab,var(--md-sys-color-primary, #3FBCA5),transparent 70%);color:var(--md-sys-color-on-surface, #2B2A28);font-size:12px}.praxis-filter-card .card-actions{display:flex;gap:8px}\n"] }]
|
|
21458
21553
|
}], ctorParameters: () => [{ type: i1$3.GenericCrudService }, { type: undefined, decorators: [{
|
|
21459
21554
|
type: Inject,
|
|
21460
21555
|
args: [CONFIG_STORAGE]
|
|
@@ -21492,6 +21587,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImpor
|
|
|
21492
21587
|
type: Input
|
|
21493
21588
|
}], showFilterSettings: [{
|
|
21494
21589
|
type: Input
|
|
21590
|
+
}], showQuickFallback: [{
|
|
21591
|
+
type: Input
|
|
21495
21592
|
}], summary: [{
|
|
21496
21593
|
type: Input
|
|
21497
21594
|
}], summaryTemplate: [{
|
|
@@ -24159,7 +24256,7 @@ class PraxisTable {
|
|
|
24159
24256
|
this.dataSubject.complete();
|
|
24160
24257
|
}
|
|
24161
24258
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: PraxisTable, deps: [{ token: i1$3.GenericCrudService }, { token: i0.ChangeDetectorRef }, { token: i3$2.SettingsPanelService }, { token: DataFormattingService }, { token: CONFIG_STORAGE }, { token: CONNECTION_STORAGE }, { token: TableDefaultsProvider }, { token: i2$1.MatSnackBar }, { token: FilterConfigService }, { token: i7$2.PraxisDialog }, { token: i0.ElementRef }, { token: i1$3.GlobalConfigService }], target: i0.ɵɵFactoryTarget.Component });
|
|
24162
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.4", type: PraxisTable, isStandalone: true, selector: "praxis-table", inputs: { config: "config", resourcePath: "resourcePath", filterCriteria: "filterCriteria", notifyIfOutdated: "notifyIfOutdated", snoozeMs: "snoozeMs", autoOpenSettingsOnOutdated: "autoOpenSettingsOnOutdated", showToolbar: "showToolbar", toolbarV2: "toolbarV2", autoDelete: "autoDelete", editModeEnabled: "editModeEnabled", dense: "dense", tableId: "tableId", debugLayout: "debugLayout", horizontalScroll: "horizontalScroll", crudContext: "crudContext", idField: "idField" }, outputs: { rowClick: "rowClick", rowAction: "rowAction", toolbarAction: "toolbarAction", bulkAction: "bulkAction", rowDoubleClick: "rowDoubleClick", schemaStatusChange: "schemaStatusChange", metadataChange: "metadataChange", beforeDelete: "beforeDelete", afterDelete: "afterDelete", deleteError: "deleteError", beforeBulkDelete: "beforeBulkDelete", afterBulkDelete: "afterBulkDelete", bulkDeleteError: "bulkDeleteError" }, host: { properties: { "class.debug-layout": "debugLayout", "class.density-compact": "config?.appearance?.density === 'compact'", "class.density-comfortable": "config?.appearance?.density === 'comfortable'", "class.density-spacious": "config?.appearance?.density === 'spacious'", "class.row-borders": "config?.appearance?.borders?.showRowBorders !== false", "class.col-borders": "!!config?.appearance?.borders?.showColumnBorders" } }, queries: [{ propertyName: "projectedFilter", first: true, predicate: PraxisFilter, descendants: true }], viewQueries: [{ propertyName: "paginator", first: true, predicate: MatPaginator, descendants: true }, { propertyName: "sort", first: true, predicate: MatSort, descendants: true }, { propertyName: "actionsHeaderCell", first: true, predicate: ["actionsHeaderCell"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<praxis-empty-state-card\n *ngIf=\"!resourcePath\"\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<!-- Error State with Quick Connect CTA -->\n<div class=\"ptable-error\" *ngIf=\"resourcePath && (schemaError || dataError)\" style=\"display:flex; align-items:center; gap:12px; padding:12px; border:1px solid var(--md-sys-color-error, #b00020); border-radius:8px; margin: 8px 0;\">\n <mat-icon color=\"warn\" aria-hidden=\"true\">error</mat-icon>\n <div style=\"flex:1\">\n <div style=\"font-weight:600\">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 <button mat-stroked-button (click)=\"retryData()\" *ngIf=\"!schemaError\">Tentar novamente</button>\n <button mat-stroked-button (click)=\"reloadSchema()\" *ngIf=\"schemaError\">Recarregar colunas</button>\n </div>\n\n<!-- Inline banner for schema change (only in edit mode) -->\n<div *ngIf=\"shouldShowOutdatedInline()\" 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 <ng-container *ngIf=\"resourcePath && !schemaError && !dataError && toolbarV2; else legacyHeader\">\n <div class=\"praxis-table-header\" [class.debug-layout]=\"debugLayout\" [class.edit-mode]=\"editModeEnabled\" *ngIf=\"showToolbar || editModeEnabled\">\n <praxis-table-toolbar\n *ngIf=\"showToolbar\"\n [config]=\"config\"\n [debugLayout]=\"debugLayout\"\n (toolbarAction)=\"onToolbarAction($event)\"\n (reset)=\"onResetPreferences()\"\n >\n <praxis-filter\n *ngIf=\"\n resourcePath &&\n config.behavior?.filtering?.advancedFilters?.enabled &&\n !projectedFilter\n \"\n advancedFilter\n [resourcePath]=\"resourcePath\"\n [formId]=\"tableId + '-filter'\"\n [editModeEnabled]=\"editModeEnabled\"\n [quickField]=\"\n config.behavior?.filtering?.advancedFilters?.settings?.quickField\n \"\n [alwaysVisibleFields]=\"\n config.behavior?.filtering?.advancedFilters?.settings\n ?.alwaysVisibleFields\n \"\n [allowSaveTags]=\"\n config.behavior?.filtering?.advancedFilters?.settings\n ?.allowSaveTags\n \"\n [changeDebounceMs]=\"\n config.behavior?.filtering?.advancedFilters?.settings\n ?.changeDebounceMs ?? 300\n \"\n [i18n]=\"getFilterI18n()\"\n [mode]=\"\n config.behavior?.filtering?.advancedFilters?.settings?.mode ??\n 'auto'\n \"\n [debugLayout]=\"debugLayout\"\n [showFilterSettings]=\"!editModeEnabled\"\n (submit)=\"onAdvancedFilterSubmit($event)\"\n (clear)=\"onAdvancedFilterClear()\"\n ></praxis-filter>\n <ng-content select=\"[advancedFilter]\" />\n <ng-content select=\"[toolbar]\" />\n <button end-actions mat-icon-button color=\"primary\" data-role=\"table-settings\" *ngIf=\"editModeEnabled\"\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 </praxis-table-toolbar>\n <!-- Render a minimal settings button when toolbar is hidden but edit mode is enabled -->\n <div class=\"ptable-header-actions\" *ngIf=\"!showToolbar && editModeEnabled\">\n <button mat-icon-button color=\"primary\" (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 <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 </div>\n \n </div>\n</ng-container>\n<ng-template #legacyHeader>\n <ng-container *ngIf=\"resourcePath && !schemaError && !dataError\">\n <praxis-table-toolbar\n *ngIf=\"showToolbar\"\n [config]=\"config\"\n [debugLayout]=\"debugLayout\"\n (toolbarAction)=\"onToolbarAction($event)\"\n (reset)=\"onResetPreferences()\"\n >\n <praxis-filter\n *ngIf=\"\n resourcePath &&\n config.behavior?.filtering?.advancedFilters?.enabled &&\n !projectedFilter\n \"\n advancedFilter\n [resourcePath]=\"resourcePath\"\n [formId]=\"tableId + '-filter'\"\n [editModeEnabled]=\"editModeEnabled\"\n [quickField]=\"\n config.behavior?.filtering?.advancedFilters?.settings?.quickField\n \"\n [alwaysVisibleFields]=\"\n config.behavior?.filtering?.advancedFilters?.settings\n ?.alwaysVisibleFields\n \"\n [allowSaveTags]=\"\n config.behavior?.filtering?.advancedFilters?.settings?.allowSaveTags\n \"\n [changeDebounceMs]=\"\n config.behavior?.filtering?.advancedFilters?.settings\n ?.changeDebounceMs ?? 300\n \"\n [i18n]=\"getFilterI18n()\"\n [mode]=\"\n config.behavior?.filtering?.advancedFilters?.settings?.mode ??\n 'auto'\n \"\n [debugLayout]=\"debugLayout\"\n [showFilterSettings]=\"!editModeEnabled\"\n (submit)=\"onAdvancedFilterSubmit($event)\"\n (clear)=\"onAdvancedFilterClear()\"\n ></praxis-filter>\n <ng-content select=\"[advancedFilter]\" />\n <ng-content select=\"[toolbar]\" />\n <button end-actions mat-icon-button color=\"primary\" *ngIf=\"editModeEnabled\"\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 </praxis-table-toolbar>\n <!-- Legacy header: settings button when toolbar hidden -->\n <div class=\"ptable-header-actions\" *ngIf=\"!showToolbar && editModeEnabled\">\n <button mat-icon-button color=\"primary\" data-role=\"table-settings\" (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 </ng-container>\n \n</ng-template>\n<div class=\"px-scroll-viewport\"\n [class.scroll-auto]=\"horizontalScroll === 'auto'\"\n [class.scroll-wrap]=\"horizontalScroll === 'wrap'\"\n [class.scroll-none]=\"horizontalScroll === 'none'\">\n\n<table\n *ngIf=\"resourcePath && !schemaError && !dataError\"\n mat-table\n [dataSource]=\"dataSource\"\n matSort\n (matSortChange)=\"onSortChange($event)\"\n [matSortDisabled]=\"!getSortingEnabled()\"\n class=\"mat-elevation-z8\"\n>\n <ng-container\n *ngIf=\"config.behavior?.selection?.enabled\"\n matColumnDef=\"_select\"\n >\n <th mat-header-cell *matHeaderCellDef>\n <mat-checkbox\n (change)=\"masterToggle()\"\n [checked]=\"isAllSelected()\"\n [indeterminate]=\"selection.hasValue() && !isAllSelected()\"\n ></mat-checkbox>\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 <ng-container\n *ngFor=\"let column of visibleColumns\"\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 [disabled]=\"!getSortingEnabled() || column.sortable === false\"\n [style.text-align]=\"column.align\"\n [style.width]=\"column.width\"\n [attr.style]=\"column.headerStyle\"\n >\n {{ column.header }}\n </th>\n <td\n mat-cell\n *matCellDef=\"let element\"\n [style.text-align]=\"column.align\"\n [style.width]=\"column.width\"\n [attr.style]=\"column.style\"\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 <mat-icon *ngIf=\"getBadgeIcon(element, column) as bi\" 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 <mat-icon *ngIf=\"getButtonIcon(element, column) as bi\">{{ 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 <mat-icon *ngIf=\"getButtonIcon(element, column) as bi\">{{ 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 <mat-icon *ngIf=\"getButtonIcon(element, column) as bi\">{{ 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 <mat-icon *ngIf=\"getChipIcon(element, column) as ci\" 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.%]=\"getProgressValue(element, column)\" [style.background]=\"getProgressColor(element, column) || null\"></div>\n <div class=\"pfx-progress-label\" *ngIf=\"getProgressShowLabel(element, column)\">{{ getProgressValue(element, column) }}%</div>\n </div>\n </ng-container>\n\n <!-- Avatar renderer -->\n <ng-container *ngSwitchCase=\"'avatar'\">\n <ng-container *ngIf=\"getAvatarSrc(element, column) as asrc; else initials\">\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 </ng-container>\n <ng-template #initials>\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 </ng-template>\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.id, element, $event)\" [disabled]=\"!it.__visible\" >\n <mat-icon *ngIf=\"it.icon\">{{ it.icon }}</mat-icon>\n <span>{{ it.label }}</span>\n </button>\n </mat-menu>\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))\"><mat-icon *ngIf=\"getBadgeIcon(element, asItemColumn(column, it)) as bi\" 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)\"><mat-icon *ngIf=\"getButtonIcon(element, asItemColumn(column, it)) as bi\">{{ 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)\"><mat-icon *ngIf=\"getButtonIcon(element, asItemColumn(column, it)) as bi\">{{ 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)\"><mat-icon *ngIf=\"getButtonIcon(element, asItemColumn(column, it)) as bi\">{{ 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))\"><mat-icon *ngIf=\"getChipIcon(element, asItemColumn(column, it)) as ci\" 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.%]=\"getProgressValue(element, asItemColumn(column, it))\" [style.background]=\"getProgressColor(element, asItemColumn(column, it)) || null\"></div><div class=\"pfx-progress-label\" *ngIf=\"getProgressShowLabel(element, asItemColumn(column, it))\">{{ getProgressValue(element, asItemColumn(column, it)) }}%</div></div>\n </ng-container>\n <ng-container *ngSwitchCase=\"'avatar'\">\n <ng-container *ngIf=\"getAvatarSrc(element, asItemColumn(column, it)) as asrc; else initials_comp\">\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 </ng-container>\n <ng-template #initials_comp>\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 </ng-template>\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.id, element, $event)\" [disabled]=\"!mi.__visible\"><mat-icon *ngIf=\"mi.icon\">{{ mi.icon }}</mat-icon><span>{{ mi.label }}</span></button>\n </mat-menu>\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 <ng-container *ngIf=\"config.actions?.row?.enabled\" 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]=\"config.actions?.row?.width\" 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 <mat-icon *ngIf=\"getActionsHeaderIcon() as hi\" [praxisIcon]=\"hi\"></mat-icon>\n <span class=\"label\" *ngIf=\"getActionsHeaderLabel() as hl\">{{ 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]=\"config.actions?.row?.width\"\n >\n <div class=\"praxis-actions-cell__content\">\n <!-- A\u00E7\u00F5es inline -->\n <!-- Inline actions: icons mode -->\n <ng-container *ngIf=\"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 </ng-container>\n\n <!-- Inline actions: buttons mode (show label + icon) -->\n <ng-container *ngIf=\"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 </ng-container>\n\n <!-- Menu de overflow -->\n <button\n mat-icon-button\n class=\"praxis-icon-btn praxis-more-btn\"\n *ngIf=\"hasOverflowRowActions(row)\"\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 <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 <tr mat-header-row *matHeaderRowDef=\"displayedColumns\"></tr>\n <ng-container *ngIf=\"!isVirtualized()\">\n <tr\n mat-row\n *matRowDef=\"let row; let i = index; columns: displayedColumns\"\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 </ng-container>\n</table>\n\n<!-- Virtual rows path (header preserved above) -->\n<ng-container *ngIf=\"resourcePath && !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]=\"getVirtMinHeightStyle()\"\n >\n <table class=\"mat-mdc-table mat-elevation-z8\" [style.width]=\"horizontalScroll === 'auto' ? 'max-content' : '100%'\">\n <tbody>\n <tr class=\"mat-mdc-row\"\n *cdkVirtualFor=\"let row of dataSource.data; let i = index; trackBy: trackByRow\"\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 <td class=\"mat-mdc-cell\" *ngIf=\"config.behavior?.selection?.enabled\">\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 <td class=\"mat-mdc-cell\"\n *ngFor=\"let column of visibleColumns\"\n [style.text-align]=\"column.align\"\n [style.width]=\"column.width\"\n [attr.style]=\"column.style\"\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 <mat-icon *ngIf=\"getBadgeIcon(row, column) as bi\" 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 <!-- Actions column -->\n <td class=\"mat-mdc-cell praxis-actions-cell\" *ngIf=\"config.actions?.row?.enabled\" [class.dense]=\"dense\" [style.width]=\"config.actions?.row?.width\">\n <div class=\"praxis-actions-cell__content\">\n <ng-container *ngIf=\"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 </ng-container>\n <ng-container *ngIf=\"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 </ng-container>\n <button mat-icon-button class=\"praxis-icon-btn praxis-more-btn\"\n *ngIf=\"hasOverflowRowActions(row)\"\n [matMenuTriggerFor]=\"rowMoreMenuV\"\n [color]=\"getRowMenuButtonColor() || null\"\n aria-label=\"Mais a\u00E7\u00F5es\">\n <mat-icon [praxisIcon]=\"getRowMenuIcon()\"></mat-icon>\n </button>\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 </tr>\n </tbody>\n </table>\n </cdk-virtual-scroll-viewport>\n</ng-container>\n\n</div>\n<!-- Paginadores (top/bottom) -->\n<mat-paginator\n *ngIf=\"resourcePath && !schemaError && !dataError && getPaginationEnabled() && (config.behavior?.pagination?.position === 'top' || config.behavior?.pagination?.position === 'both')\"\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<mat-paginator\n *ngIf=\"resourcePath && !schemaError && !dataError && getPaginationEnabled() && (config.behavior?.pagination?.position === 'bottom' || config.behavior?.pagination?.position === 'both' || !config.behavior?.pagination?.position)\"\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", styles: ["@charset \"UTF-8\";table{width:100%}.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, rgba(255, 255, 255, .06))}.praxis-icon-btn:focus-visible{outline:2px solid var(--primary, #48a1ff);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:#ff6b6b}.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.debug-layout,:host.debug-layout .praxis-table-header{outline:2px dashed #ff4d4f;border-radius:8px}:host.debug-layout ::ng-deep .praxis-filter-bar{outline:1px dashed #f59e0b}:host.debug-layout ::ng-deep .quick-shell{outline:1px dashed #3b82f6}:host.debug-layout ::ng-deep .always-fields{outline:1px dashed #22c55e}:host.debug-layout ::ng-deep .praxis-filter-overlay .praxis-filter-advanced{outline:2px solid #a855f7}:host.debug-layout ::ng-deep .mat-mdc-table{outline:1px dashed #94a3b8}.praxis-table-header>praxis-table-toolbar{flex:1 0 100%}:host{--p-table-header-bg: var(--md-sys-color-surface-container-highest, #1d1d1f);--p-table-header-fg: var(--md-sys-color-on-surface, #e8f3f1);--p-table-border-color: var(--md-sys-color-outline-variant, rgba(255, 255, 255, .12));--p-table-row-even-bg: var(--md-sys-color-surface-container, rgba(255, 255, 255, .04));--p-table-row-hover-bg: color-mix(in srgb, var(--md-sys-color-primary, #3f51b5) 10%, transparent);--p-table-row-selected-bg: var(--md-sys-color-primary-container, rgba(63,81,181,.14));--p-table-badge-soft-primary-bg: color-mix(in srgb, var(--mat-sys-primary, var(--md-sys-color-primary)) 16%, transparent);--p-table-badge-soft-primary-fg: var(--mat-sys-primary, var(--md-sys-color-primary));--p-table-badge-soft-accent-bg: color-mix(in srgb, var(--mat-sys-secondary, var(--md-sys-color-secondary, #ff4081)) 14%, transparent);--p-table-badge-soft-accent-fg: var(--mat-sys-secondary, var(--md-sys-color-secondary, #ff4081));--p-table-badge-soft-warn-bg: color-mix(in srgb, var(--mat-sys-error, var(--md-sys-color-error, #f44336)) 14%, transparent);--p-table-badge-soft-warn-fg: var(--mat-sys-error, var(--md-sys-color-error, #f44336));--p-table-state-success-bg: color-mix(in srgb, var(--mat-sys-tertiary, var(--md-sys-color-tertiary, #388E3C)) 16%, transparent);--p-table-state-success-fg: var(--md-sys-color-on-surface, #c8e6c9);--p-table-state-warning-bg: color-mix(in srgb, var(--md-sys-color-secondary, #FFA000) 18%, transparent);--p-table-state-warning-fg: var(--md-sys-color-on-surface, #ffe0b2);--p-table-state-danger-bg: color-mix(in srgb, var(--md-sys-color-error, #e53935) 18%, transparent);--p-table-state-danger-fg: var(--md-sys-color-on-surface, #ffcdd2);--p-table-state-highlight-bg: color-mix(in srgb, var(--md-sys-color-primary, #2196f3) 16%, transparent);--p-table-state-highlight-fg: var(--md-sys-color-on-surface, #bbdefb)}:host ::ng-deep .mat-mdc-table{background:var(--md-sys-color-surface-container-highest, #1d1d1f);border-radius:12px;width:100%}:host [data-role=table-settings].mat-mdc-icon-button{--mdc-icon-button-icon-color: var(--mat-sys-primary, var(--md-sys-color-primary, #3f51b5));color:var(--mat-sys-primary, var(--md-sys-color-primary, #3f51b5))}.pfx-link{color:var(--mat-sys-primary, #3f51b5);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(--mat-sys-outline-variant);color:var(--mat-sys-on-surface)}.pfx-chip--filled-primary{background:var(--mat-sys-primary);color:var(--mat-sys-on-primary)}.pfx-chip--filled-accent{background:var(--mat-sys-secondary, #ff4081);color:#fff}.pfx-chip--filled-warn{background:var(--mat-sys-error, #f44336);color:#fff}.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(--mat-sys-surface-container-highest, rgba(255, 255, 255, .08));border-radius:4px;overflow:hidden;display:inline-block;vertical-align:middle}.pfx-progress-bar{height:100%;background:var(--mat-sys-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(--mat-sys-surface-container, #2a2a2e);color:var(--mat-sys-on-surface, #eee);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;scrollbar-gutter:stable}.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}.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 .mat-mdc-cell{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: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.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-info-banner{display:flex;gap:12px;align-items:center;padding:8px 12px;margin:8px 0;border-radius:8px;border:1px solid var(--mat-sys-primary, var(--md-sys-color-primary, #1a73e8));background:color-mix(in srgb,var(--mat-sys-primary, var(--md-sys-color-primary, #1a73e8)) 10%,transparent)}.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, #2a2a2a);border:1px solid var(--md-sys-color-outline-variant, rgba(0, 0, 0, .08))}.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(--mat-sys-primary, #3f51b5);color:var(--mat-sys-on-primary, #fff)}.pfx-badge--filled-accent{background:var(--mat-sys-secondary, #ff4081);color:var(--mat-sys-on-secondary, #fff)}.pfx-badge--filled-warn{background:var(--mat-sys-error, #f44336);color:var(--mat-sys-on-error, #fff)}.pfx-badge--outlined{background:transparent;border-color:var(--mat-sys-outline-variant, rgba(255, 255, 255, .24));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.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: i1.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i1.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "directive", type: i1.NgSwitchDefault, selector: "[ngSwitchDefault]" }, { kind: "ngmodule", type: MatTableModule }, { kind: "component", type: i8.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i8.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i8.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i8.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i8.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i8.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i8.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i8.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i8.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i8.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { 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: MatPaginatorModule }, { kind: "component", type: i11$1.MatPaginator, selector: "mat-paginator", inputs: ["color", "pageIndex", "length", "pageSize", "pageSizeOptions", "hidePageSize", "showFirstLastButtons", "selectConfig", "disabled"], outputs: ["page"], exportAs: ["matPaginator"] }, { kind: "ngmodule", type: MatSortModule }, { kind: "directive", type: i12.MatSort, selector: "[matSort]", inputs: ["matSortActive", "matSortStart", "matSortDirection", "matSortDisableClear", "matSortDisabled"], outputs: ["matSortChange"], exportAs: ["matSort"] }, { kind: "component", type: i12.MatSortHeader, selector: "[mat-sort-header]", inputs: ["mat-sort-header", "arrowPosition", "start", "disabled", "sortActionDescription", "disableClear"], exportAs: ["matSortHeader"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i4.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i5.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.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i5.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: 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: MatSnackBarModule }, { 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: MatBadgeModule }, { kind: "directive", type: i15.MatBadge, selector: "[matBadge]", inputs: ["matBadgeColor", "matBadgeOverlap", "matBadgeDisabled", "matBadgePosition", "matBadge", "matBadgeDescription", "matBadgeSize", "matBadgeHidden"] }, { kind: "ngmodule", type: ScrollingModule }, { kind: "directive", type: i19.ɵɵCdkFixedSizeVirtualScroll, selector: "cdk-virtual-scroll-viewport[itemSize]", inputs: ["itemSize", "minBufferPx", "maxBufferPx"] }, { kind: "directive", type: i19.ɵɵCdkVirtualForOf, selector: "[cdkVirtualFor][cdkVirtualForOf]", inputs: ["cdkVirtualForOf", "cdkVirtualForTrackBy", "cdkVirtualForTemplate", "cdkVirtualForTemplateCacheSize"] }, { kind: "component", type: i19.ɵɵCdkVirtualScrollViewport, selector: "cdk-virtual-scroll-viewport", inputs: ["orientation", "appendOnly"], outputs: ["scrolledIndexChange"] }, { kind: "component", type: PraxisTableToolbar, selector: "praxis-table-toolbar", inputs: ["config", "debugLayout"], outputs: ["toolbarAction", "reset"] }, { kind: "component", type: PraxisFilter, selector: "praxis-filter", inputs: ["resourcePath", "formId", "mode", "notifyIfOutdated", "snoozeMs", "autoOpenSettingsOnOutdated", "editModeEnabled", "value", "quickField", "alwaysVisibleFields", "tags", "allowSaveTags", "persistenceKey", "i18n", "changeDebounceMs", "showFilterSettings", "summary", "summaryTemplate", "summaryMap", "autoSummary", "confirmTagDelete", "debugLayout", "placeBooleansInActions", "showToggleLabels", "alwaysMinWidth", "alwaysColsMd", "alwaysColsLg", "tagColor", "tagVariant", "tagButtonColor", "actionsButtonColor", "actionsVariant", "overlayVariant", "overlayBackdrop", "advancedOpenMode"], outputs: ["submit", "change", "clear", "modeChange", "requestSearch", "tagsChange", "metaChanged", "schemaStatusChange"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }, { kind: "component", type: EmptyStateCardComponent, selector: "praxis-empty-state-card", inputs: ["icon", "title", "description", "primaryAction", "secondaryActions", "inline"] }] });
|
|
24259
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.4", type: PraxisTable, isStandalone: true, selector: "praxis-table", inputs: { config: "config", resourcePath: "resourcePath", filterCriteria: "filterCriteria", notifyIfOutdated: "notifyIfOutdated", snoozeMs: "snoozeMs", autoOpenSettingsOnOutdated: "autoOpenSettingsOnOutdated", showToolbar: "showToolbar", toolbarV2: "toolbarV2", autoDelete: "autoDelete", editModeEnabled: "editModeEnabled", dense: "dense", tableId: "tableId", debugLayout: "debugLayout", horizontalScroll: "horizontalScroll", crudContext: "crudContext", idField: "idField" }, outputs: { rowClick: "rowClick", rowAction: "rowAction", toolbarAction: "toolbarAction", bulkAction: "bulkAction", rowDoubleClick: "rowDoubleClick", schemaStatusChange: "schemaStatusChange", metadataChange: "metadataChange", beforeDelete: "beforeDelete", afterDelete: "afterDelete", deleteError: "deleteError", beforeBulkDelete: "beforeBulkDelete", afterBulkDelete: "afterBulkDelete", bulkDeleteError: "bulkDeleteError" }, host: { properties: { "class.debug-layout": "debugLayout", "class.density-compact": "config?.appearance?.density === 'compact'", "class.density-comfortable": "config?.appearance?.density === 'comfortable'", "class.density-spacious": "config?.appearance?.density === 'spacious'", "class.row-borders": "config?.appearance?.borders?.showRowBorders !== false", "class.col-borders": "!!config?.appearance?.borders?.showColumnBorders" } }, queries: [{ propertyName: "projectedFilter", first: true, predicate: PraxisFilter, descendants: true }], viewQueries: [{ propertyName: "paginator", first: true, predicate: MatPaginator, descendants: true }, { propertyName: "sort", first: true, predicate: MatSort, descendants: true }, { propertyName: "actionsHeaderCell", first: true, predicate: ["actionsHeaderCell"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<praxis-empty-state-card\n *ngIf=\"!resourcePath\"\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<!-- Error State with Quick Connect CTA -->\n<div class=\"ptable-error\" *ngIf=\"resourcePath && (schemaError || dataError)\" style=\"display:flex; align-items:center; gap:12px; padding:12px; border:1px solid var(--md-sys-color-error, #b00020); border-radius:8px; margin: 8px 0;\">\n <mat-icon color=\"warn\" aria-hidden=\"true\">error</mat-icon>\n <div style=\"flex:1\">\n <div style=\"font-weight:600\">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 <button mat-stroked-button (click)=\"retryData()\" *ngIf=\"!schemaError\">Tentar novamente</button>\n <button mat-stroked-button (click)=\"reloadSchema()\" *ngIf=\"schemaError\">Recarregar colunas</button>\n </div>\n\n<!-- Inline banner for schema change (only in edit mode) -->\n<div *ngIf=\"shouldShowOutdatedInline()\" 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 <ng-container *ngIf=\"resourcePath && !schemaError && !dataError && toolbarV2; else legacyHeader\">\n <div class=\"praxis-table-header\" [class.debug-layout]=\"debugLayout\" [class.edit-mode]=\"editModeEnabled\" *ngIf=\"showToolbar || editModeEnabled\">\n <praxis-table-toolbar\n *ngIf=\"showToolbar\"\n [config]=\"config\"\n [debugLayout]=\"debugLayout\"\n (toolbarAction)=\"onToolbarAction($event)\"\n (reset)=\"onResetPreferences()\"\n >\n <praxis-filter\n *ngIf=\"\n resourcePath &&\n config.behavior?.filtering?.advancedFilters?.enabled &&\n !projectedFilter\n \"\n advancedFilter\n [resourcePath]=\"resourcePath\"\n [formId]=\"tableId + '-filter'\"\n [editModeEnabled]=\"editModeEnabled\"\n [quickField]=\"\n config.behavior?.filtering?.advancedFilters?.settings?.quickField\n \"\n [alwaysVisibleFields]=\"\n config.behavior?.filtering?.advancedFilters?.settings\n ?.alwaysVisibleFields\n \"\n [allowSaveTags]=\"\n config.behavior?.filtering?.advancedFilters?.settings\n ?.allowSaveTags\n \"\n [changeDebounceMs]=\"\n config.behavior?.filtering?.advancedFilters?.settings\n ?.changeDebounceMs ?? 300\n \"\n [i18n]=\"getFilterI18n()\"\n [mode]=\"\n config.behavior?.filtering?.advancedFilters?.settings?.mode ??\n 'auto'\n \"\n [debugLayout]=\"debugLayout\"\n [showFilterSettings]=\"editModeEnabled\"\n (submit)=\"onAdvancedFilterSubmit($event)\"\n (clear)=\"onAdvancedFilterClear()\"\n ></praxis-filter>\n <ng-content select=\"[advancedFilter]\" />\n <ng-content select=\"[toolbar]\" />\n <button end-actions mat-icon-button color=\"primary\" data-role=\"table-settings\" *ngIf=\"editModeEnabled\"\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 </praxis-table-toolbar>\n <!-- Render a minimal settings button when toolbar is hidden but edit mode is enabled -->\n <div class=\"ptable-header-actions\" *ngIf=\"!showToolbar && editModeEnabled\">\n <button mat-icon-button color=\"primary\" (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 <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 </div>\n \n </div>\n</ng-container>\n<ng-template #legacyHeader>\n <ng-container *ngIf=\"resourcePath && !schemaError && !dataError\">\n <praxis-table-toolbar\n *ngIf=\"showToolbar\"\n [config]=\"config\"\n [debugLayout]=\"debugLayout\"\n (toolbarAction)=\"onToolbarAction($event)\"\n (reset)=\"onResetPreferences()\"\n >\n <praxis-filter\n *ngIf=\"\n resourcePath &&\n config.behavior?.filtering?.advancedFilters?.enabled &&\n !projectedFilter\n \"\n advancedFilter\n [resourcePath]=\"resourcePath\"\n [formId]=\"tableId + '-filter'\"\n [editModeEnabled]=\"editModeEnabled\"\n [quickField]=\"\n config.behavior?.filtering?.advancedFilters?.settings?.quickField\n \"\n [alwaysVisibleFields]=\"\n config.behavior?.filtering?.advancedFilters?.settings\n ?.alwaysVisibleFields\n \"\n [allowSaveTags]=\"\n config.behavior?.filtering?.advancedFilters?.settings?.allowSaveTags\n \"\n [changeDebounceMs]=\"\n config.behavior?.filtering?.advancedFilters?.settings\n ?.changeDebounceMs ?? 300\n \"\n [i18n]=\"getFilterI18n()\"\n [mode]=\"\n config.behavior?.filtering?.advancedFilters?.settings?.mode ??\n 'auto'\n \"\n [debugLayout]=\"debugLayout\"\n [showFilterSettings]=\"editModeEnabled\"\n (submit)=\"onAdvancedFilterSubmit($event)\"\n (clear)=\"onAdvancedFilterClear()\"\n ></praxis-filter>\n <ng-content select=\"[advancedFilter]\" />\n <ng-content select=\"[toolbar]\" />\n <button end-actions mat-icon-button color=\"primary\" *ngIf=\"editModeEnabled\"\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 </praxis-table-toolbar>\n <!-- Legacy header: settings button when toolbar hidden -->\n <div class=\"ptable-header-actions\" *ngIf=\"!showToolbar && editModeEnabled\">\n <button mat-icon-button color=\"primary\" data-role=\"table-settings\" (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 </ng-container>\n \n</ng-template>\n<div class=\"px-scroll-viewport\"\n [class.scroll-auto]=\"horizontalScroll === 'auto'\"\n [class.scroll-wrap]=\"horizontalScroll === 'wrap'\"\n [class.scroll-none]=\"horizontalScroll === 'none'\">\n\n<table\n *ngIf=\"resourcePath && !schemaError && !dataError\"\n mat-table\n [dataSource]=\"dataSource\"\n matSort\n (matSortChange)=\"onSortChange($event)\"\n [matSortDisabled]=\"!getSortingEnabled()\"\n class=\"mat-elevation-z8\"\n>\n <ng-container\n *ngIf=\"config.behavior?.selection?.enabled\"\n matColumnDef=\"_select\"\n >\n <th mat-header-cell *matHeaderCellDef>\n <mat-checkbox\n (change)=\"masterToggle()\"\n [checked]=\"isAllSelected()\"\n [indeterminate]=\"selection.hasValue() && !isAllSelected()\"\n ></mat-checkbox>\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 <ng-container\n *ngFor=\"let column of visibleColumns\"\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 [disabled]=\"!getSortingEnabled() || column.sortable === false\"\n [style.text-align]=\"column.align\"\n [style.width]=\"column.width\"\n [attr.style]=\"column.headerStyle\"\n >\n {{ column.header }}\n </th>\n <td\n mat-cell\n *matCellDef=\"let element\"\n [style.text-align]=\"column.align\"\n [style.width]=\"column.width\"\n [attr.style]=\"column.style\"\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 <mat-icon *ngIf=\"getBadgeIcon(element, column) as bi\" 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 <mat-icon *ngIf=\"getButtonIcon(element, column) as bi\">{{ 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 <mat-icon *ngIf=\"getButtonIcon(element, column) as bi\">{{ 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 <mat-icon *ngIf=\"getButtonIcon(element, column) as bi\">{{ 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 <mat-icon *ngIf=\"getChipIcon(element, column) as ci\" 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.%]=\"getProgressValue(element, column)\" [style.background]=\"getProgressColor(element, column) || null\"></div>\n <div class=\"pfx-progress-label\" *ngIf=\"getProgressShowLabel(element, column)\">{{ getProgressValue(element, column) }}%</div>\n </div>\n </ng-container>\n\n <!-- Avatar renderer -->\n <ng-container *ngSwitchCase=\"'avatar'\">\n <ng-container *ngIf=\"getAvatarSrc(element, column) as asrc; else initials\">\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 </ng-container>\n <ng-template #initials>\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 </ng-template>\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.id, element, $event)\" [disabled]=\"!it.__visible\" >\n <mat-icon *ngIf=\"it.icon\">{{ it.icon }}</mat-icon>\n <span>{{ it.label }}</span>\n </button>\n </mat-menu>\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))\"><mat-icon *ngIf=\"getBadgeIcon(element, asItemColumn(column, it)) as bi\" 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)\"><mat-icon *ngIf=\"getButtonIcon(element, asItemColumn(column, it)) as bi\">{{ 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)\"><mat-icon *ngIf=\"getButtonIcon(element, asItemColumn(column, it)) as bi\">{{ 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)\"><mat-icon *ngIf=\"getButtonIcon(element, asItemColumn(column, it)) as bi\">{{ 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))\"><mat-icon *ngIf=\"getChipIcon(element, asItemColumn(column, it)) as ci\" 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.%]=\"getProgressValue(element, asItemColumn(column, it))\" [style.background]=\"getProgressColor(element, asItemColumn(column, it)) || null\"></div><div class=\"pfx-progress-label\" *ngIf=\"getProgressShowLabel(element, asItemColumn(column, it))\">{{ getProgressValue(element, asItemColumn(column, it)) }}%</div></div>\n </ng-container>\n <ng-container *ngSwitchCase=\"'avatar'\">\n <ng-container *ngIf=\"getAvatarSrc(element, asItemColumn(column, it)) as asrc; else initials_comp\">\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 </ng-container>\n <ng-template #initials_comp>\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 </ng-template>\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.id, element, $event)\" [disabled]=\"!mi.__visible\"><mat-icon *ngIf=\"mi.icon\">{{ mi.icon }}</mat-icon><span>{{ mi.label }}</span></button>\n </mat-menu>\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 <ng-container *ngIf=\"config.actions?.row?.enabled\" 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]=\"config.actions?.row?.width\" 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 <mat-icon *ngIf=\"getActionsHeaderIcon() as hi\" [praxisIcon]=\"hi\"></mat-icon>\n <span class=\"label\" *ngIf=\"getActionsHeaderLabel() as hl\">{{ 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]=\"config.actions?.row?.width\"\n >\n <div class=\"praxis-actions-cell__content\">\n <!-- A\u00E7\u00F5es inline -->\n <!-- Inline actions: icons mode -->\n <ng-container *ngIf=\"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 </ng-container>\n\n <!-- Inline actions: buttons mode (show label + icon) -->\n <ng-container *ngIf=\"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 </ng-container>\n\n <!-- Menu de overflow -->\n <button\n mat-icon-button\n class=\"praxis-icon-btn praxis-more-btn\"\n *ngIf=\"hasOverflowRowActions(row)\"\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 <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 <tr mat-header-row *matHeaderRowDef=\"displayedColumns\"></tr>\n <ng-container *ngIf=\"!isVirtualized()\">\n <tr\n mat-row\n *matRowDef=\"let row; let i = index; columns: displayedColumns\"\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 </ng-container>\n</table>\n\n<!-- Virtual rows path (header preserved above) -->\n<ng-container *ngIf=\"resourcePath && !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]=\"getVirtMinHeightStyle()\"\n >\n <table class=\"mat-mdc-table mat-elevation-z8\" [style.width]=\"horizontalScroll === 'auto' ? 'max-content' : '100%'\">\n <tbody>\n <tr class=\"mat-mdc-row\"\n *cdkVirtualFor=\"let row of dataSource.data; let i = index; trackBy: trackByRow\"\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 <td class=\"mat-mdc-cell\" *ngIf=\"config.behavior?.selection?.enabled\">\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 <td class=\"mat-mdc-cell\"\n *ngFor=\"let column of visibleColumns\"\n [style.text-align]=\"column.align\"\n [style.width]=\"column.width\"\n [attr.style]=\"column.style\"\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 <mat-icon *ngIf=\"getBadgeIcon(row, column) as bi\" 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 <!-- Actions column -->\n <td class=\"mat-mdc-cell praxis-actions-cell\" *ngIf=\"config.actions?.row?.enabled\" [class.dense]=\"dense\" [style.width]=\"config.actions?.row?.width\">\n <div class=\"praxis-actions-cell__content\">\n <ng-container *ngIf=\"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 </ng-container>\n <ng-container *ngIf=\"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 </ng-container>\n <button mat-icon-button class=\"praxis-icon-btn praxis-more-btn\"\n *ngIf=\"hasOverflowRowActions(row)\"\n [matMenuTriggerFor]=\"rowMoreMenuV\"\n [color]=\"getRowMenuButtonColor() || null\"\n aria-label=\"Mais a\u00E7\u00F5es\">\n <mat-icon [praxisIcon]=\"getRowMenuIcon()\"></mat-icon>\n </button>\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 </tr>\n </tbody>\n </table>\n </cdk-virtual-scroll-viewport>\n</ng-container>\n\n</div>\n<!-- Paginadores (top/bottom) -->\n<mat-paginator\n *ngIf=\"resourcePath && !schemaError && !dataError && getPaginationEnabled() && (config.behavior?.pagination?.position === 'top' || config.behavior?.pagination?.position === 'both')\"\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<mat-paginator\n *ngIf=\"resourcePath && !schemaError && !dataError && getPaginationEnabled() && (config.behavior?.pagination?.position === 'bottom' || config.behavior?.pagination?.position === 'both' || !config.behavior?.pagination?.position)\"\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", styles: ["@charset \"UTF-8\";table{width:100%}.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, rgba(255, 255, 255, .06))}.praxis-icon-btn:focus-visible{outline:2px solid var(--primary, #48a1ff);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:#ff6b6b}.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.debug-layout,:host.debug-layout .praxis-table-header{outline:2px dashed #ff4d4f;border-radius:8px}:host.debug-layout ::ng-deep .praxis-filter-bar{outline:1px dashed #f59e0b}:host.debug-layout ::ng-deep .quick-shell{outline:1px dashed #3b82f6}:host.debug-layout ::ng-deep .always-fields{outline:1px dashed #22c55e}:host.debug-layout ::ng-deep .praxis-filter-overlay .praxis-filter-advanced{outline:2px solid #a855f7}:host.debug-layout ::ng-deep .mat-mdc-table{outline:1px dashed #94a3b8}.praxis-table-header>praxis-table-toolbar{flex:1 0 100%}:host{--p-table-header-bg: var(--md-sys-color-surface-container-highest, #1d1d1f);--p-table-header-fg: var(--md-sys-color-on-surface, #e8f3f1);--p-table-border-color: var(--md-sys-color-outline-variant, rgba(255, 255, 255, .12));--p-table-row-even-bg: var(--md-sys-color-surface-container, rgba(255, 255, 255, .04));--p-table-row-hover-bg: color-mix(in srgb, var(--md-sys-color-primary, #3f51b5) 10%, transparent);--p-table-row-selected-bg: var(--md-sys-color-primary-container, rgba(63,81,181,.14));--p-table-badge-soft-primary-bg: color-mix(in srgb, var(--mat-sys-primary, var(--md-sys-color-primary)) 16%, transparent);--p-table-badge-soft-primary-fg: var(--mat-sys-primary, var(--md-sys-color-primary));--p-table-badge-soft-accent-bg: color-mix(in srgb, var(--mat-sys-secondary, var(--md-sys-color-secondary, #ff4081)) 14%, transparent);--p-table-badge-soft-accent-fg: var(--mat-sys-secondary, var(--md-sys-color-secondary, #ff4081));--p-table-badge-soft-warn-bg: color-mix(in srgb, var(--mat-sys-error, var(--md-sys-color-error, #f44336)) 14%, transparent);--p-table-badge-soft-warn-fg: var(--mat-sys-error, var(--md-sys-color-error, #f44336));--p-table-state-success-bg: color-mix(in srgb, var(--mat-sys-tertiary, var(--md-sys-color-tertiary, #388E3C)) 16%, transparent);--p-table-state-success-fg: var(--md-sys-color-on-surface, #c8e6c9);--p-table-state-warning-bg: color-mix(in srgb, var(--md-sys-color-secondary, #FFA000) 18%, transparent);--p-table-state-warning-fg: var(--md-sys-color-on-surface, #ffe0b2);--p-table-state-danger-bg: color-mix(in srgb, var(--md-sys-color-error, #e53935) 18%, transparent);--p-table-state-danger-fg: var(--md-sys-color-on-surface, #ffcdd2);--p-table-state-highlight-bg: color-mix(in srgb, var(--md-sys-color-primary, #2196f3) 16%, transparent);--p-table-state-highlight-fg: var(--md-sys-color-on-surface, #bbdefb)}:host ::ng-deep .mat-mdc-table{background:var(--md-sys-color-surface-container-highest, #1d1d1f);border-radius:12px;width:100%}:host [data-role=table-settings].mat-mdc-icon-button{--mdc-icon-button-icon-color: var(--mat-sys-primary, var(--md-sys-color-primary, #3f51b5));color:var(--mat-sys-primary, var(--md-sys-color-primary, #3f51b5))}.pfx-link{color:var(--mat-sys-primary, #3f51b5);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(--mat-sys-outline-variant);color:var(--mat-sys-on-surface)}.pfx-chip--filled-primary{background:var(--mat-sys-primary);color:var(--mat-sys-on-primary)}.pfx-chip--filled-accent{background:var(--mat-sys-secondary, #ff4081);color:#fff}.pfx-chip--filled-warn{background:var(--mat-sys-error, #f44336);color:#fff}.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(--mat-sys-surface-container-highest, rgba(255, 255, 255, .08));border-radius:4px;overflow:hidden;display:inline-block;vertical-align:middle}.pfx-progress-bar{height:100%;background:var(--mat-sys-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(--mat-sys-surface-container, #2a2a2e);color:var(--mat-sys-on-surface, #eee);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;scrollbar-gutter:stable}.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}.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 .mat-mdc-cell{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: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.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-info-banner{display:flex;gap:12px;align-items:center;padding:8px 12px;margin:8px 0;border-radius:8px;border:1px solid var(--mat-sys-primary, var(--md-sys-color-primary, #1a73e8));background:color-mix(in srgb,var(--mat-sys-primary, var(--md-sys-color-primary, #1a73e8)) 10%,transparent)}.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, #2a2a2a);border:1px solid var(--md-sys-color-outline-variant, rgba(0, 0, 0, .08))}.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(--mat-sys-primary, #3f51b5);color:var(--mat-sys-on-primary, #fff)}.pfx-badge--filled-accent{background:var(--mat-sys-secondary, #ff4081);color:var(--mat-sys-on-secondary, #fff)}.pfx-badge--filled-warn{background:var(--mat-sys-error, #f44336);color:var(--mat-sys-on-error, #fff)}.pfx-badge--outlined{background:transparent;border-color:var(--mat-sys-outline-variant, rgba(255, 255, 255, .24));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.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: i1.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i1.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "directive", type: i1.NgSwitchDefault, selector: "[ngSwitchDefault]" }, { kind: "ngmodule", type: MatTableModule }, { kind: "component", type: i8.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i8.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i8.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i8.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i8.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i8.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i8.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i8.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i8.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i8.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { 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: MatPaginatorModule }, { kind: "component", type: i11$1.MatPaginator, selector: "mat-paginator", inputs: ["color", "pageIndex", "length", "pageSize", "pageSizeOptions", "hidePageSize", "showFirstLastButtons", "selectConfig", "disabled"], outputs: ["page"], exportAs: ["matPaginator"] }, { kind: "ngmodule", type: MatSortModule }, { kind: "directive", type: i12.MatSort, selector: "[matSort]", inputs: ["matSortActive", "matSortStart", "matSortDirection", "matSortDisableClear", "matSortDisabled"], outputs: ["matSortChange"], exportAs: ["matSort"] }, { kind: "component", type: i12.MatSortHeader, selector: "[mat-sort-header]", inputs: ["mat-sort-header", "arrowPosition", "start", "disabled", "sortActionDescription", "disableClear"], exportAs: ["matSortHeader"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i4.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i5.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.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i5.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: 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: MatSnackBarModule }, { 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: MatBadgeModule }, { kind: "directive", type: i15.MatBadge, selector: "[matBadge]", inputs: ["matBadgeColor", "matBadgeOverlap", "matBadgeDisabled", "matBadgePosition", "matBadge", "matBadgeDescription", "matBadgeSize", "matBadgeHidden"] }, { kind: "ngmodule", type: ScrollingModule }, { kind: "directive", type: i19.ɵɵCdkFixedSizeVirtualScroll, selector: "cdk-virtual-scroll-viewport[itemSize]", inputs: ["itemSize", "minBufferPx", "maxBufferPx"] }, { kind: "directive", type: i19.ɵɵCdkVirtualForOf, selector: "[cdkVirtualFor][cdkVirtualForOf]", inputs: ["cdkVirtualForOf", "cdkVirtualForTrackBy", "cdkVirtualForTemplate", "cdkVirtualForTemplateCacheSize"] }, { kind: "component", type: i19.ɵɵCdkVirtualScrollViewport, selector: "cdk-virtual-scroll-viewport", inputs: ["orientation", "appendOnly"], outputs: ["scrolledIndexChange"] }, { kind: "component", type: PraxisTableToolbar, selector: "praxis-table-toolbar", inputs: ["config", "debugLayout"], outputs: ["toolbarAction", "reset"] }, { kind: "component", type: PraxisFilter, selector: "praxis-filter", inputs: ["resourcePath", "formId", "mode", "notifyIfOutdated", "snoozeMs", "autoOpenSettingsOnOutdated", "editModeEnabled", "value", "quickField", "alwaysVisibleFields", "tags", "allowSaveTags", "persistenceKey", "i18n", "changeDebounceMs", "showFilterSettings", "showQuickFallback", "summary", "summaryTemplate", "summaryMap", "autoSummary", "confirmTagDelete", "debugLayout", "placeBooleansInActions", "showToggleLabels", "alwaysMinWidth", "alwaysColsMd", "alwaysColsLg", "tagColor", "tagVariant", "tagButtonColor", "actionsButtonColor", "actionsVariant", "overlayVariant", "overlayBackdrop", "advancedOpenMode"], outputs: ["submit", "change", "clear", "modeChange", "requestSearch", "tagsChange", "metaChanged", "schemaStatusChange"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }, { kind: "component", type: EmptyStateCardComponent, selector: "praxis-empty-state-card", inputs: ["icon", "title", "description", "primaryAction", "secondaryActions", "inline"] }] });
|
|
24163
24260
|
}
|
|
24164
24261
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: PraxisTable, decorators: [{
|
|
24165
24262
|
type: Component,
|
|
@@ -24190,7 +24287,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImpor
|
|
|
24190
24287
|
// Quick borders toggles (rows/columns)
|
|
24191
24288
|
"[class.row-borders]": "config?.appearance?.borders?.showRowBorders !== false",
|
|
24192
24289
|
"[class.col-borders]": "!!config?.appearance?.borders?.showColumnBorders",
|
|
24193
|
-
}, template: "<praxis-empty-state-card\n *ngIf=\"!resourcePath\"\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<!-- Error State with Quick Connect CTA -->\n<div class=\"ptable-error\" *ngIf=\"resourcePath && (schemaError || dataError)\" style=\"display:flex; align-items:center; gap:12px; padding:12px; border:1px solid var(--md-sys-color-error, #b00020); border-radius:8px; margin: 8px 0;\">\n <mat-icon color=\"warn\" aria-hidden=\"true\">error</mat-icon>\n <div style=\"flex:1\">\n <div style=\"font-weight:600\">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 <button mat-stroked-button (click)=\"retryData()\" *ngIf=\"!schemaError\">Tentar novamente</button>\n <button mat-stroked-button (click)=\"reloadSchema()\" *ngIf=\"schemaError\">Recarregar colunas</button>\n </div>\n\n<!-- Inline banner for schema change (only in edit mode) -->\n<div *ngIf=\"shouldShowOutdatedInline()\" 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 <ng-container *ngIf=\"resourcePath && !schemaError && !dataError && toolbarV2; else legacyHeader\">\n <div class=\"praxis-table-header\" [class.debug-layout]=\"debugLayout\" [class.edit-mode]=\"editModeEnabled\" *ngIf=\"showToolbar || editModeEnabled\">\n <praxis-table-toolbar\n *ngIf=\"showToolbar\"\n [config]=\"config\"\n [debugLayout]=\"debugLayout\"\n (toolbarAction)=\"onToolbarAction($event)\"\n (reset)=\"onResetPreferences()\"\n >\n <praxis-filter\n *ngIf=\"\n resourcePath &&\n config.behavior?.filtering?.advancedFilters?.enabled &&\n !projectedFilter\n \"\n advancedFilter\n [resourcePath]=\"resourcePath\"\n [formId]=\"tableId + '-filter'\"\n [editModeEnabled]=\"editModeEnabled\"\n [quickField]=\"\n config.behavior?.filtering?.advancedFilters?.settings?.quickField\n \"\n [alwaysVisibleFields]=\"\n config.behavior?.filtering?.advancedFilters?.settings\n ?.alwaysVisibleFields\n \"\n [allowSaveTags]=\"\n config.behavior?.filtering?.advancedFilters?.settings\n ?.allowSaveTags\n \"\n [changeDebounceMs]=\"\n config.behavior?.filtering?.advancedFilters?.settings\n ?.changeDebounceMs ?? 300\n \"\n [i18n]=\"getFilterI18n()\"\n [mode]=\"\n config.behavior?.filtering?.advancedFilters?.settings?.mode ??\n 'auto'\n \"\n [debugLayout]=\"debugLayout\"\n [showFilterSettings]=\"!editModeEnabled\"\n (submit)=\"onAdvancedFilterSubmit($event)\"\n (clear)=\"onAdvancedFilterClear()\"\n ></praxis-filter>\n <ng-content select=\"[advancedFilter]\" />\n <ng-content select=\"[toolbar]\" />\n <button end-actions mat-icon-button color=\"primary\" data-role=\"table-settings\" *ngIf=\"editModeEnabled\"\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 </praxis-table-toolbar>\n <!-- Render a minimal settings button when toolbar is hidden but edit mode is enabled -->\n <div class=\"ptable-header-actions\" *ngIf=\"!showToolbar && editModeEnabled\">\n <button mat-icon-button color=\"primary\" (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 <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 </div>\n \n </div>\n</ng-container>\n<ng-template #legacyHeader>\n <ng-container *ngIf=\"resourcePath && !schemaError && !dataError\">\n <praxis-table-toolbar\n *ngIf=\"showToolbar\"\n [config]=\"config\"\n [debugLayout]=\"debugLayout\"\n (toolbarAction)=\"onToolbarAction($event)\"\n (reset)=\"onResetPreferences()\"\n >\n <praxis-filter\n *ngIf=\"\n resourcePath &&\n config.behavior?.filtering?.advancedFilters?.enabled &&\n !projectedFilter\n \"\n advancedFilter\n [resourcePath]=\"resourcePath\"\n [formId]=\"tableId + '-filter'\"\n [editModeEnabled]=\"editModeEnabled\"\n [quickField]=\"\n config.behavior?.filtering?.advancedFilters?.settings?.quickField\n \"\n [alwaysVisibleFields]=\"\n config.behavior?.filtering?.advancedFilters?.settings\n ?.alwaysVisibleFields\n \"\n [allowSaveTags]=\"\n config.behavior?.filtering?.advancedFilters?.settings?.allowSaveTags\n \"\n [changeDebounceMs]=\"\n config.behavior?.filtering?.advancedFilters?.settings\n ?.changeDebounceMs ?? 300\n \"\n [i18n]=\"getFilterI18n()\"\n [mode]=\"\n config.behavior?.filtering?.advancedFilters?.settings?.mode ??\n 'auto'\n \"\n [debugLayout]=\"debugLayout\"\n [showFilterSettings]=\"!editModeEnabled\"\n (submit)=\"onAdvancedFilterSubmit($event)\"\n (clear)=\"onAdvancedFilterClear()\"\n ></praxis-filter>\n <ng-content select=\"[advancedFilter]\" />\n <ng-content select=\"[toolbar]\" />\n <button end-actions mat-icon-button color=\"primary\" *ngIf=\"editModeEnabled\"\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 </praxis-table-toolbar>\n <!-- Legacy header: settings button when toolbar hidden -->\n <div class=\"ptable-header-actions\" *ngIf=\"!showToolbar && editModeEnabled\">\n <button mat-icon-button color=\"primary\" data-role=\"table-settings\" (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 </ng-container>\n \n</ng-template>\n<div class=\"px-scroll-viewport\"\n [class.scroll-auto]=\"horizontalScroll === 'auto'\"\n [class.scroll-wrap]=\"horizontalScroll === 'wrap'\"\n [class.scroll-none]=\"horizontalScroll === 'none'\">\n\n<table\n *ngIf=\"resourcePath && !schemaError && !dataError\"\n mat-table\n [dataSource]=\"dataSource\"\n matSort\n (matSortChange)=\"onSortChange($event)\"\n [matSortDisabled]=\"!getSortingEnabled()\"\n class=\"mat-elevation-z8\"\n>\n <ng-container\n *ngIf=\"config.behavior?.selection?.enabled\"\n matColumnDef=\"_select\"\n >\n <th mat-header-cell *matHeaderCellDef>\n <mat-checkbox\n (change)=\"masterToggle()\"\n [checked]=\"isAllSelected()\"\n [indeterminate]=\"selection.hasValue() && !isAllSelected()\"\n ></mat-checkbox>\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 <ng-container\n *ngFor=\"let column of visibleColumns\"\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 [disabled]=\"!getSortingEnabled() || column.sortable === false\"\n [style.text-align]=\"column.align\"\n [style.width]=\"column.width\"\n [attr.style]=\"column.headerStyle\"\n >\n {{ column.header }}\n </th>\n <td\n mat-cell\n *matCellDef=\"let element\"\n [style.text-align]=\"column.align\"\n [style.width]=\"column.width\"\n [attr.style]=\"column.style\"\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 <mat-icon *ngIf=\"getBadgeIcon(element, column) as bi\" 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 <mat-icon *ngIf=\"getButtonIcon(element, column) as bi\">{{ 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 <mat-icon *ngIf=\"getButtonIcon(element, column) as bi\">{{ 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 <mat-icon *ngIf=\"getButtonIcon(element, column) as bi\">{{ 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 <mat-icon *ngIf=\"getChipIcon(element, column) as ci\" 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.%]=\"getProgressValue(element, column)\" [style.background]=\"getProgressColor(element, column) || null\"></div>\n <div class=\"pfx-progress-label\" *ngIf=\"getProgressShowLabel(element, column)\">{{ getProgressValue(element, column) }}%</div>\n </div>\n </ng-container>\n\n <!-- Avatar renderer -->\n <ng-container *ngSwitchCase=\"'avatar'\">\n <ng-container *ngIf=\"getAvatarSrc(element, column) as asrc; else initials\">\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 </ng-container>\n <ng-template #initials>\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 </ng-template>\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.id, element, $event)\" [disabled]=\"!it.__visible\" >\n <mat-icon *ngIf=\"it.icon\">{{ it.icon }}</mat-icon>\n <span>{{ it.label }}</span>\n </button>\n </mat-menu>\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))\"><mat-icon *ngIf=\"getBadgeIcon(element, asItemColumn(column, it)) as bi\" 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)\"><mat-icon *ngIf=\"getButtonIcon(element, asItemColumn(column, it)) as bi\">{{ 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)\"><mat-icon *ngIf=\"getButtonIcon(element, asItemColumn(column, it)) as bi\">{{ 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)\"><mat-icon *ngIf=\"getButtonIcon(element, asItemColumn(column, it)) as bi\">{{ 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))\"><mat-icon *ngIf=\"getChipIcon(element, asItemColumn(column, it)) as ci\" 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.%]=\"getProgressValue(element, asItemColumn(column, it))\" [style.background]=\"getProgressColor(element, asItemColumn(column, it)) || null\"></div><div class=\"pfx-progress-label\" *ngIf=\"getProgressShowLabel(element, asItemColumn(column, it))\">{{ getProgressValue(element, asItemColumn(column, it)) }}%</div></div>\n </ng-container>\n <ng-container *ngSwitchCase=\"'avatar'\">\n <ng-container *ngIf=\"getAvatarSrc(element, asItemColumn(column, it)) as asrc; else initials_comp\">\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 </ng-container>\n <ng-template #initials_comp>\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 </ng-template>\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.id, element, $event)\" [disabled]=\"!mi.__visible\"><mat-icon *ngIf=\"mi.icon\">{{ mi.icon }}</mat-icon><span>{{ mi.label }}</span></button>\n </mat-menu>\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 <ng-container *ngIf=\"config.actions?.row?.enabled\" 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]=\"config.actions?.row?.width\" 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 <mat-icon *ngIf=\"getActionsHeaderIcon() as hi\" [praxisIcon]=\"hi\"></mat-icon>\n <span class=\"label\" *ngIf=\"getActionsHeaderLabel() as hl\">{{ 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]=\"config.actions?.row?.width\"\n >\n <div class=\"praxis-actions-cell__content\">\n <!-- A\u00E7\u00F5es inline -->\n <!-- Inline actions: icons mode -->\n <ng-container *ngIf=\"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 </ng-container>\n\n <!-- Inline actions: buttons mode (show label + icon) -->\n <ng-container *ngIf=\"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 </ng-container>\n\n <!-- Menu de overflow -->\n <button\n mat-icon-button\n class=\"praxis-icon-btn praxis-more-btn\"\n *ngIf=\"hasOverflowRowActions(row)\"\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 <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 <tr mat-header-row *matHeaderRowDef=\"displayedColumns\"></tr>\n <ng-container *ngIf=\"!isVirtualized()\">\n <tr\n mat-row\n *matRowDef=\"let row; let i = index; columns: displayedColumns\"\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 </ng-container>\n</table>\n\n<!-- Virtual rows path (header preserved above) -->\n<ng-container *ngIf=\"resourcePath && !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]=\"getVirtMinHeightStyle()\"\n >\n <table class=\"mat-mdc-table mat-elevation-z8\" [style.width]=\"horizontalScroll === 'auto' ? 'max-content' : '100%'\">\n <tbody>\n <tr class=\"mat-mdc-row\"\n *cdkVirtualFor=\"let row of dataSource.data; let i = index; trackBy: trackByRow\"\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 <td class=\"mat-mdc-cell\" *ngIf=\"config.behavior?.selection?.enabled\">\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 <td class=\"mat-mdc-cell\"\n *ngFor=\"let column of visibleColumns\"\n [style.text-align]=\"column.align\"\n [style.width]=\"column.width\"\n [attr.style]=\"column.style\"\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 <mat-icon *ngIf=\"getBadgeIcon(row, column) as bi\" 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 <!-- Actions column -->\n <td class=\"mat-mdc-cell praxis-actions-cell\" *ngIf=\"config.actions?.row?.enabled\" [class.dense]=\"dense\" [style.width]=\"config.actions?.row?.width\">\n <div class=\"praxis-actions-cell__content\">\n <ng-container *ngIf=\"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 </ng-container>\n <ng-container *ngIf=\"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 </ng-container>\n <button mat-icon-button class=\"praxis-icon-btn praxis-more-btn\"\n *ngIf=\"hasOverflowRowActions(row)\"\n [matMenuTriggerFor]=\"rowMoreMenuV\"\n [color]=\"getRowMenuButtonColor() || null\"\n aria-label=\"Mais a\u00E7\u00F5es\">\n <mat-icon [praxisIcon]=\"getRowMenuIcon()\"></mat-icon>\n </button>\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 </tr>\n </tbody>\n </table>\n </cdk-virtual-scroll-viewport>\n</ng-container>\n\n</div>\n<!-- Paginadores (top/bottom) -->\n<mat-paginator\n *ngIf=\"resourcePath && !schemaError && !dataError && getPaginationEnabled() && (config.behavior?.pagination?.position === 'top' || config.behavior?.pagination?.position === 'both')\"\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<mat-paginator\n *ngIf=\"resourcePath && !schemaError && !dataError && getPaginationEnabled() && (config.behavior?.pagination?.position === 'bottom' || config.behavior?.pagination?.position === 'both' || !config.behavior?.pagination?.position)\"\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", styles: ["@charset \"UTF-8\";table{width:100%}.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, rgba(255, 255, 255, .06))}.praxis-icon-btn:focus-visible{outline:2px solid var(--primary, #48a1ff);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:#ff6b6b}.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.debug-layout,:host.debug-layout .praxis-table-header{outline:2px dashed #ff4d4f;border-radius:8px}:host.debug-layout ::ng-deep .praxis-filter-bar{outline:1px dashed #f59e0b}:host.debug-layout ::ng-deep .quick-shell{outline:1px dashed #3b82f6}:host.debug-layout ::ng-deep .always-fields{outline:1px dashed #22c55e}:host.debug-layout ::ng-deep .praxis-filter-overlay .praxis-filter-advanced{outline:2px solid #a855f7}:host.debug-layout ::ng-deep .mat-mdc-table{outline:1px dashed #94a3b8}.praxis-table-header>praxis-table-toolbar{flex:1 0 100%}:host{--p-table-header-bg: var(--md-sys-color-surface-container-highest, #1d1d1f);--p-table-header-fg: var(--md-sys-color-on-surface, #e8f3f1);--p-table-border-color: var(--md-sys-color-outline-variant, rgba(255, 255, 255, .12));--p-table-row-even-bg: var(--md-sys-color-surface-container, rgba(255, 255, 255, .04));--p-table-row-hover-bg: color-mix(in srgb, var(--md-sys-color-primary, #3f51b5) 10%, transparent);--p-table-row-selected-bg: var(--md-sys-color-primary-container, rgba(63,81,181,.14));--p-table-badge-soft-primary-bg: color-mix(in srgb, var(--mat-sys-primary, var(--md-sys-color-primary)) 16%, transparent);--p-table-badge-soft-primary-fg: var(--mat-sys-primary, var(--md-sys-color-primary));--p-table-badge-soft-accent-bg: color-mix(in srgb, var(--mat-sys-secondary, var(--md-sys-color-secondary, #ff4081)) 14%, transparent);--p-table-badge-soft-accent-fg: var(--mat-sys-secondary, var(--md-sys-color-secondary, #ff4081));--p-table-badge-soft-warn-bg: color-mix(in srgb, var(--mat-sys-error, var(--md-sys-color-error, #f44336)) 14%, transparent);--p-table-badge-soft-warn-fg: var(--mat-sys-error, var(--md-sys-color-error, #f44336));--p-table-state-success-bg: color-mix(in srgb, var(--mat-sys-tertiary, var(--md-sys-color-tertiary, #388E3C)) 16%, transparent);--p-table-state-success-fg: var(--md-sys-color-on-surface, #c8e6c9);--p-table-state-warning-bg: color-mix(in srgb, var(--md-sys-color-secondary, #FFA000) 18%, transparent);--p-table-state-warning-fg: var(--md-sys-color-on-surface, #ffe0b2);--p-table-state-danger-bg: color-mix(in srgb, var(--md-sys-color-error, #e53935) 18%, transparent);--p-table-state-danger-fg: var(--md-sys-color-on-surface, #ffcdd2);--p-table-state-highlight-bg: color-mix(in srgb, var(--md-sys-color-primary, #2196f3) 16%, transparent);--p-table-state-highlight-fg: var(--md-sys-color-on-surface, #bbdefb)}:host ::ng-deep .mat-mdc-table{background:var(--md-sys-color-surface-container-highest, #1d1d1f);border-radius:12px;width:100%}:host [data-role=table-settings].mat-mdc-icon-button{--mdc-icon-button-icon-color: var(--mat-sys-primary, var(--md-sys-color-primary, #3f51b5));color:var(--mat-sys-primary, var(--md-sys-color-primary, #3f51b5))}.pfx-link{color:var(--mat-sys-primary, #3f51b5);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(--mat-sys-outline-variant);color:var(--mat-sys-on-surface)}.pfx-chip--filled-primary{background:var(--mat-sys-primary);color:var(--mat-sys-on-primary)}.pfx-chip--filled-accent{background:var(--mat-sys-secondary, #ff4081);color:#fff}.pfx-chip--filled-warn{background:var(--mat-sys-error, #f44336);color:#fff}.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(--mat-sys-surface-container-highest, rgba(255, 255, 255, .08));border-radius:4px;overflow:hidden;display:inline-block;vertical-align:middle}.pfx-progress-bar{height:100%;background:var(--mat-sys-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(--mat-sys-surface-container, #2a2a2e);color:var(--mat-sys-on-surface, #eee);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;scrollbar-gutter:stable}.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}.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 .mat-mdc-cell{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: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.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-info-banner{display:flex;gap:12px;align-items:center;padding:8px 12px;margin:8px 0;border-radius:8px;border:1px solid var(--mat-sys-primary, var(--md-sys-color-primary, #1a73e8));background:color-mix(in srgb,var(--mat-sys-primary, var(--md-sys-color-primary, #1a73e8)) 10%,transparent)}.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, #2a2a2a);border:1px solid var(--md-sys-color-outline-variant, rgba(0, 0, 0, .08))}.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(--mat-sys-primary, #3f51b5);color:var(--mat-sys-on-primary, #fff)}.pfx-badge--filled-accent{background:var(--mat-sys-secondary, #ff4081);color:var(--mat-sys-on-secondary, #fff)}.pfx-badge--filled-warn{background:var(--mat-sys-error, #f44336);color:var(--mat-sys-on-error, #fff)}.pfx-badge--outlined{background:transparent;border-color:var(--mat-sys-outline-variant, rgba(255, 255, 255, .24));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"] }]
|
|
24290
|
+
}, template: "<praxis-empty-state-card\n *ngIf=\"!resourcePath\"\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<!-- Error State with Quick Connect CTA -->\n<div class=\"ptable-error\" *ngIf=\"resourcePath && (schemaError || dataError)\" style=\"display:flex; align-items:center; gap:12px; padding:12px; border:1px solid var(--md-sys-color-error, #b00020); border-radius:8px; margin: 8px 0;\">\n <mat-icon color=\"warn\" aria-hidden=\"true\">error</mat-icon>\n <div style=\"flex:1\">\n <div style=\"font-weight:600\">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 <button mat-stroked-button (click)=\"retryData()\" *ngIf=\"!schemaError\">Tentar novamente</button>\n <button mat-stroked-button (click)=\"reloadSchema()\" *ngIf=\"schemaError\">Recarregar colunas</button>\n </div>\n\n<!-- Inline banner for schema change (only in edit mode) -->\n<div *ngIf=\"shouldShowOutdatedInline()\" 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 <ng-container *ngIf=\"resourcePath && !schemaError && !dataError && toolbarV2; else legacyHeader\">\n <div class=\"praxis-table-header\" [class.debug-layout]=\"debugLayout\" [class.edit-mode]=\"editModeEnabled\" *ngIf=\"showToolbar || editModeEnabled\">\n <praxis-table-toolbar\n *ngIf=\"showToolbar\"\n [config]=\"config\"\n [debugLayout]=\"debugLayout\"\n (toolbarAction)=\"onToolbarAction($event)\"\n (reset)=\"onResetPreferences()\"\n >\n <praxis-filter\n *ngIf=\"\n resourcePath &&\n config.behavior?.filtering?.advancedFilters?.enabled &&\n !projectedFilter\n \"\n advancedFilter\n [resourcePath]=\"resourcePath\"\n [formId]=\"tableId + '-filter'\"\n [editModeEnabled]=\"editModeEnabled\"\n [quickField]=\"\n config.behavior?.filtering?.advancedFilters?.settings?.quickField\n \"\n [alwaysVisibleFields]=\"\n config.behavior?.filtering?.advancedFilters?.settings\n ?.alwaysVisibleFields\n \"\n [allowSaveTags]=\"\n config.behavior?.filtering?.advancedFilters?.settings\n ?.allowSaveTags\n \"\n [changeDebounceMs]=\"\n config.behavior?.filtering?.advancedFilters?.settings\n ?.changeDebounceMs ?? 300\n \"\n [i18n]=\"getFilterI18n()\"\n [mode]=\"\n config.behavior?.filtering?.advancedFilters?.settings?.mode ??\n 'auto'\n \"\n [debugLayout]=\"debugLayout\"\n [showFilterSettings]=\"editModeEnabled\"\n (submit)=\"onAdvancedFilterSubmit($event)\"\n (clear)=\"onAdvancedFilterClear()\"\n ></praxis-filter>\n <ng-content select=\"[advancedFilter]\" />\n <ng-content select=\"[toolbar]\" />\n <button end-actions mat-icon-button color=\"primary\" data-role=\"table-settings\" *ngIf=\"editModeEnabled\"\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 </praxis-table-toolbar>\n <!-- Render a minimal settings button when toolbar is hidden but edit mode is enabled -->\n <div class=\"ptable-header-actions\" *ngIf=\"!showToolbar && editModeEnabled\">\n <button mat-icon-button color=\"primary\" (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 <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 </div>\n \n </div>\n</ng-container>\n<ng-template #legacyHeader>\n <ng-container *ngIf=\"resourcePath && !schemaError && !dataError\">\n <praxis-table-toolbar\n *ngIf=\"showToolbar\"\n [config]=\"config\"\n [debugLayout]=\"debugLayout\"\n (toolbarAction)=\"onToolbarAction($event)\"\n (reset)=\"onResetPreferences()\"\n >\n <praxis-filter\n *ngIf=\"\n resourcePath &&\n config.behavior?.filtering?.advancedFilters?.enabled &&\n !projectedFilter\n \"\n advancedFilter\n [resourcePath]=\"resourcePath\"\n [formId]=\"tableId + '-filter'\"\n [editModeEnabled]=\"editModeEnabled\"\n [quickField]=\"\n config.behavior?.filtering?.advancedFilters?.settings?.quickField\n \"\n [alwaysVisibleFields]=\"\n config.behavior?.filtering?.advancedFilters?.settings\n ?.alwaysVisibleFields\n \"\n [allowSaveTags]=\"\n config.behavior?.filtering?.advancedFilters?.settings?.allowSaveTags\n \"\n [changeDebounceMs]=\"\n config.behavior?.filtering?.advancedFilters?.settings\n ?.changeDebounceMs ?? 300\n \"\n [i18n]=\"getFilterI18n()\"\n [mode]=\"\n config.behavior?.filtering?.advancedFilters?.settings?.mode ??\n 'auto'\n \"\n [debugLayout]=\"debugLayout\"\n [showFilterSettings]=\"editModeEnabled\"\n (submit)=\"onAdvancedFilterSubmit($event)\"\n (clear)=\"onAdvancedFilterClear()\"\n ></praxis-filter>\n <ng-content select=\"[advancedFilter]\" />\n <ng-content select=\"[toolbar]\" />\n <button end-actions mat-icon-button color=\"primary\" *ngIf=\"editModeEnabled\"\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 </praxis-table-toolbar>\n <!-- Legacy header: settings button when toolbar hidden -->\n <div class=\"ptable-header-actions\" *ngIf=\"!showToolbar && editModeEnabled\">\n <button mat-icon-button color=\"primary\" data-role=\"table-settings\" (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 </ng-container>\n \n</ng-template>\n<div class=\"px-scroll-viewport\"\n [class.scroll-auto]=\"horizontalScroll === 'auto'\"\n [class.scroll-wrap]=\"horizontalScroll === 'wrap'\"\n [class.scroll-none]=\"horizontalScroll === 'none'\">\n\n<table\n *ngIf=\"resourcePath && !schemaError && !dataError\"\n mat-table\n [dataSource]=\"dataSource\"\n matSort\n (matSortChange)=\"onSortChange($event)\"\n [matSortDisabled]=\"!getSortingEnabled()\"\n class=\"mat-elevation-z8\"\n>\n <ng-container\n *ngIf=\"config.behavior?.selection?.enabled\"\n matColumnDef=\"_select\"\n >\n <th mat-header-cell *matHeaderCellDef>\n <mat-checkbox\n (change)=\"masterToggle()\"\n [checked]=\"isAllSelected()\"\n [indeterminate]=\"selection.hasValue() && !isAllSelected()\"\n ></mat-checkbox>\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 <ng-container\n *ngFor=\"let column of visibleColumns\"\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 [disabled]=\"!getSortingEnabled() || column.sortable === false\"\n [style.text-align]=\"column.align\"\n [style.width]=\"column.width\"\n [attr.style]=\"column.headerStyle\"\n >\n {{ column.header }}\n </th>\n <td\n mat-cell\n *matCellDef=\"let element\"\n [style.text-align]=\"column.align\"\n [style.width]=\"column.width\"\n [attr.style]=\"column.style\"\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 <mat-icon *ngIf=\"getBadgeIcon(element, column) as bi\" 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 <mat-icon *ngIf=\"getButtonIcon(element, column) as bi\">{{ 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 <mat-icon *ngIf=\"getButtonIcon(element, column) as bi\">{{ 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 <mat-icon *ngIf=\"getButtonIcon(element, column) as bi\">{{ 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 <mat-icon *ngIf=\"getChipIcon(element, column) as ci\" 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.%]=\"getProgressValue(element, column)\" [style.background]=\"getProgressColor(element, column) || null\"></div>\n <div class=\"pfx-progress-label\" *ngIf=\"getProgressShowLabel(element, column)\">{{ getProgressValue(element, column) }}%</div>\n </div>\n </ng-container>\n\n <!-- Avatar renderer -->\n <ng-container *ngSwitchCase=\"'avatar'\">\n <ng-container *ngIf=\"getAvatarSrc(element, column) as asrc; else initials\">\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 </ng-container>\n <ng-template #initials>\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 </ng-template>\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.id, element, $event)\" [disabled]=\"!it.__visible\" >\n <mat-icon *ngIf=\"it.icon\">{{ it.icon }}</mat-icon>\n <span>{{ it.label }}</span>\n </button>\n </mat-menu>\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))\"><mat-icon *ngIf=\"getBadgeIcon(element, asItemColumn(column, it)) as bi\" 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)\"><mat-icon *ngIf=\"getButtonIcon(element, asItemColumn(column, it)) as bi\">{{ 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)\"><mat-icon *ngIf=\"getButtonIcon(element, asItemColumn(column, it)) as bi\">{{ 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)\"><mat-icon *ngIf=\"getButtonIcon(element, asItemColumn(column, it)) as bi\">{{ 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))\"><mat-icon *ngIf=\"getChipIcon(element, asItemColumn(column, it)) as ci\" 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.%]=\"getProgressValue(element, asItemColumn(column, it))\" [style.background]=\"getProgressColor(element, asItemColumn(column, it)) || null\"></div><div class=\"pfx-progress-label\" *ngIf=\"getProgressShowLabel(element, asItemColumn(column, it))\">{{ getProgressValue(element, asItemColumn(column, it)) }}%</div></div>\n </ng-container>\n <ng-container *ngSwitchCase=\"'avatar'\">\n <ng-container *ngIf=\"getAvatarSrc(element, asItemColumn(column, it)) as asrc; else initials_comp\">\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 </ng-container>\n <ng-template #initials_comp>\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 </ng-template>\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.id, element, $event)\" [disabled]=\"!mi.__visible\"><mat-icon *ngIf=\"mi.icon\">{{ mi.icon }}</mat-icon><span>{{ mi.label }}</span></button>\n </mat-menu>\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 <ng-container *ngIf=\"config.actions?.row?.enabled\" 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]=\"config.actions?.row?.width\" 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 <mat-icon *ngIf=\"getActionsHeaderIcon() as hi\" [praxisIcon]=\"hi\"></mat-icon>\n <span class=\"label\" *ngIf=\"getActionsHeaderLabel() as hl\">{{ 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]=\"config.actions?.row?.width\"\n >\n <div class=\"praxis-actions-cell__content\">\n <!-- A\u00E7\u00F5es inline -->\n <!-- Inline actions: icons mode -->\n <ng-container *ngIf=\"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 </ng-container>\n\n <!-- Inline actions: buttons mode (show label + icon) -->\n <ng-container *ngIf=\"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 </ng-container>\n\n <!-- Menu de overflow -->\n <button\n mat-icon-button\n class=\"praxis-icon-btn praxis-more-btn\"\n *ngIf=\"hasOverflowRowActions(row)\"\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 <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 <tr mat-header-row *matHeaderRowDef=\"displayedColumns\"></tr>\n <ng-container *ngIf=\"!isVirtualized()\">\n <tr\n mat-row\n *matRowDef=\"let row; let i = index; columns: displayedColumns\"\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 </ng-container>\n</table>\n\n<!-- Virtual rows path (header preserved above) -->\n<ng-container *ngIf=\"resourcePath && !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]=\"getVirtMinHeightStyle()\"\n >\n <table class=\"mat-mdc-table mat-elevation-z8\" [style.width]=\"horizontalScroll === 'auto' ? 'max-content' : '100%'\">\n <tbody>\n <tr class=\"mat-mdc-row\"\n *cdkVirtualFor=\"let row of dataSource.data; let i = index; trackBy: trackByRow\"\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 <td class=\"mat-mdc-cell\" *ngIf=\"config.behavior?.selection?.enabled\">\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 <td class=\"mat-mdc-cell\"\n *ngFor=\"let column of visibleColumns\"\n [style.text-align]=\"column.align\"\n [style.width]=\"column.width\"\n [attr.style]=\"column.style\"\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 <mat-icon *ngIf=\"getBadgeIcon(row, column) as bi\" 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 <!-- Actions column -->\n <td class=\"mat-mdc-cell praxis-actions-cell\" *ngIf=\"config.actions?.row?.enabled\" [class.dense]=\"dense\" [style.width]=\"config.actions?.row?.width\">\n <div class=\"praxis-actions-cell__content\">\n <ng-container *ngIf=\"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 </ng-container>\n <ng-container *ngIf=\"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 </ng-container>\n <button mat-icon-button class=\"praxis-icon-btn praxis-more-btn\"\n *ngIf=\"hasOverflowRowActions(row)\"\n [matMenuTriggerFor]=\"rowMoreMenuV\"\n [color]=\"getRowMenuButtonColor() || null\"\n aria-label=\"Mais a\u00E7\u00F5es\">\n <mat-icon [praxisIcon]=\"getRowMenuIcon()\"></mat-icon>\n </button>\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 </tr>\n </tbody>\n </table>\n </cdk-virtual-scroll-viewport>\n</ng-container>\n\n</div>\n<!-- Paginadores (top/bottom) -->\n<mat-paginator\n *ngIf=\"resourcePath && !schemaError && !dataError && getPaginationEnabled() && (config.behavior?.pagination?.position === 'top' || config.behavior?.pagination?.position === 'both')\"\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<mat-paginator\n *ngIf=\"resourcePath && !schemaError && !dataError && getPaginationEnabled() && (config.behavior?.pagination?.position === 'bottom' || config.behavior?.pagination?.position === 'both' || !config.behavior?.pagination?.position)\"\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", styles: ["@charset \"UTF-8\";table{width:100%}.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, rgba(255, 255, 255, .06))}.praxis-icon-btn:focus-visible{outline:2px solid var(--primary, #48a1ff);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:#ff6b6b}.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.debug-layout,:host.debug-layout .praxis-table-header{outline:2px dashed #ff4d4f;border-radius:8px}:host.debug-layout ::ng-deep .praxis-filter-bar{outline:1px dashed #f59e0b}:host.debug-layout ::ng-deep .quick-shell{outline:1px dashed #3b82f6}:host.debug-layout ::ng-deep .always-fields{outline:1px dashed #22c55e}:host.debug-layout ::ng-deep .praxis-filter-overlay .praxis-filter-advanced{outline:2px solid #a855f7}:host.debug-layout ::ng-deep .mat-mdc-table{outline:1px dashed #94a3b8}.praxis-table-header>praxis-table-toolbar{flex:1 0 100%}:host{--p-table-header-bg: var(--md-sys-color-surface-container-highest, #1d1d1f);--p-table-header-fg: var(--md-sys-color-on-surface, #e8f3f1);--p-table-border-color: var(--md-sys-color-outline-variant, rgba(255, 255, 255, .12));--p-table-row-even-bg: var(--md-sys-color-surface-container, rgba(255, 255, 255, .04));--p-table-row-hover-bg: color-mix(in srgb, var(--md-sys-color-primary, #3f51b5) 10%, transparent);--p-table-row-selected-bg: var(--md-sys-color-primary-container, rgba(63,81,181,.14));--p-table-badge-soft-primary-bg: color-mix(in srgb, var(--mat-sys-primary, var(--md-sys-color-primary)) 16%, transparent);--p-table-badge-soft-primary-fg: var(--mat-sys-primary, var(--md-sys-color-primary));--p-table-badge-soft-accent-bg: color-mix(in srgb, var(--mat-sys-secondary, var(--md-sys-color-secondary, #ff4081)) 14%, transparent);--p-table-badge-soft-accent-fg: var(--mat-sys-secondary, var(--md-sys-color-secondary, #ff4081));--p-table-badge-soft-warn-bg: color-mix(in srgb, var(--mat-sys-error, var(--md-sys-color-error, #f44336)) 14%, transparent);--p-table-badge-soft-warn-fg: var(--mat-sys-error, var(--md-sys-color-error, #f44336));--p-table-state-success-bg: color-mix(in srgb, var(--mat-sys-tertiary, var(--md-sys-color-tertiary, #388E3C)) 16%, transparent);--p-table-state-success-fg: var(--md-sys-color-on-surface, #c8e6c9);--p-table-state-warning-bg: color-mix(in srgb, var(--md-sys-color-secondary, #FFA000) 18%, transparent);--p-table-state-warning-fg: var(--md-sys-color-on-surface, #ffe0b2);--p-table-state-danger-bg: color-mix(in srgb, var(--md-sys-color-error, #e53935) 18%, transparent);--p-table-state-danger-fg: var(--md-sys-color-on-surface, #ffcdd2);--p-table-state-highlight-bg: color-mix(in srgb, var(--md-sys-color-primary, #2196f3) 16%, transparent);--p-table-state-highlight-fg: var(--md-sys-color-on-surface, #bbdefb)}:host ::ng-deep .mat-mdc-table{background:var(--md-sys-color-surface-container-highest, #1d1d1f);border-radius:12px;width:100%}:host [data-role=table-settings].mat-mdc-icon-button{--mdc-icon-button-icon-color: var(--mat-sys-primary, var(--md-sys-color-primary, #3f51b5));color:var(--mat-sys-primary, var(--md-sys-color-primary, #3f51b5))}.pfx-link{color:var(--mat-sys-primary, #3f51b5);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(--mat-sys-outline-variant);color:var(--mat-sys-on-surface)}.pfx-chip--filled-primary{background:var(--mat-sys-primary);color:var(--mat-sys-on-primary)}.pfx-chip--filled-accent{background:var(--mat-sys-secondary, #ff4081);color:#fff}.pfx-chip--filled-warn{background:var(--mat-sys-error, #f44336);color:#fff}.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(--mat-sys-surface-container-highest, rgba(255, 255, 255, .08));border-radius:4px;overflow:hidden;display:inline-block;vertical-align:middle}.pfx-progress-bar{height:100%;background:var(--mat-sys-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(--mat-sys-surface-container, #2a2a2e);color:var(--mat-sys-on-surface, #eee);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;scrollbar-gutter:stable}.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}.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 .mat-mdc-cell{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: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.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-info-banner{display:flex;gap:12px;align-items:center;padding:8px 12px;margin:8px 0;border-radius:8px;border:1px solid var(--mat-sys-primary, var(--md-sys-color-primary, #1a73e8));background:color-mix(in srgb,var(--mat-sys-primary, var(--md-sys-color-primary, #1a73e8)) 10%,transparent)}.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, #2a2a2a);border:1px solid var(--md-sys-color-outline-variant, rgba(0, 0, 0, .08))}.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(--mat-sys-primary, #3f51b5);color:var(--mat-sys-on-primary, #fff)}.pfx-badge--filled-accent{background:var(--mat-sys-secondary, #ff4081);color:var(--mat-sys-on-secondary, #fff)}.pfx-badge--filled-warn{background:var(--mat-sys-error, #f44336);color:var(--mat-sys-on-error, #fff)}.pfx-badge--outlined{background:transparent;border-color:var(--mat-sys-outline-variant, rgba(255, 255, 255, .24));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"] }]
|
|
24194
24291
|
}], ctorParameters: () => [{ type: i1$3.GenericCrudService }, { type: i0.ChangeDetectorRef }, { type: i3$2.SettingsPanelService }, { type: DataFormattingService }, { type: undefined, decorators: [{
|
|
24195
24292
|
type: Inject,
|
|
24196
24293
|
args: [CONFIG_STORAGE]
|