@elasticias/ui 1.0.0 → 1.0.2
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.
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
2
|
import { Pipe, input, Component, output, booleanAttribute, Input, Directive, signal, computed, inject, EventEmitter, Injector, forwardRef, Output, ContentChild, HostBinding, ChangeDetectionStrategy, ElementRef, LOCALE_ID, ViewContainerRef, DestroyRef, ChangeDetectorRef, effect, HostListener, ViewChild, model, viewChild, contentChild, ViewEncapsulation, TemplateRef, ContentChildren, ViewChildren, untracked, PLATFORM_ID } from '@angular/core';
|
|
3
|
-
import { NumberUtils, UuidUtils } from '@elasticias/utils';
|
|
3
|
+
import { NumberUtils, UuidUtils, StorageUtils } from '@elasticias/utils';
|
|
4
4
|
import * as i1 from 'primeng/button';
|
|
5
5
|
import { ButtonModule } from 'primeng/button';
|
|
6
6
|
import * as i1$3 from '@angular/common';
|
|
@@ -8674,6 +8674,18 @@ class EfDataCardComponent {
|
|
|
8674
8674
|
showEditAction = input(true, { ...(ngDevMode ? { debugName: "showEditAction" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
8675
8675
|
showDuplicateAction = input(true, { ...(ngDevMode ? { debugName: "showDuplicateAction" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
8676
8676
|
showDeleteAction = input(true, { ...(ngDevMode ? { debugName: "showDeleteAction" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
8677
|
+
/* ── Table tools (density / column picker) ──────────────────── */
|
|
8678
|
+
/** Render the Density control in the head row. */
|
|
8679
|
+
showDensityControl = input(false, { ...(ngDevMode ? { debugName: "showDensityControl" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
8680
|
+
/** Render the Columns picker in the head row. */
|
|
8681
|
+
showColumnPicker = input(false, { ...(ngDevMode ? { debugName: "showColumnPicker" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
8682
|
+
/**
|
|
8683
|
+
* Stable key used to remember density and hidden columns for this
|
|
8684
|
+
* table. Preferences are a per-viewer convenience, so they live in
|
|
8685
|
+
* localStorage and are read defensively -- a private window or
|
|
8686
|
+
* cleared site data simply falls back to the defaults.
|
|
8687
|
+
*/
|
|
8688
|
+
tableKey = input('', ...(ngDevMode ? [{ debugName: "tableKey" }] : /* istanbul ignore next */ []));
|
|
8677
8689
|
/* ── Outputs ────────────────────────────────────────────────── */
|
|
8678
8690
|
pageChange = output();
|
|
8679
8691
|
pageSizeChange = output();
|
|
@@ -8687,6 +8699,7 @@ class EfDataCardComponent {
|
|
|
8687
8699
|
bodyTemplateMap = signal(new Map(), ...(ngDevMode ? [{ debugName: "bodyTemplateMap" }] : /* istanbul ignore next */ []));
|
|
8688
8700
|
headerTemplateMap = signal(new Map(), ...(ngDevMode ? [{ debugName: "headerTemplateMap" }] : /* istanbul ignore next */ []));
|
|
8689
8701
|
ngAfterContentInit() {
|
|
8702
|
+
this.loadPreferences();
|
|
8690
8703
|
this.bodyTemplateMap.set(toMap(this.bodyTemplates));
|
|
8691
8704
|
this.headerTemplateMap.set(toMap(this.headerTemplates));
|
|
8692
8705
|
this.bodyTemplates.changes.subscribe(() => this.bodyTemplateMap.set(toMap(this.bodyTemplates)));
|
|
@@ -8697,7 +8710,10 @@ class EfDataCardComponent {
|
|
|
8697
8710
|
* + the auto `'actions'` column when `[hasActionsColumn]` is on
|
|
8698
8711
|
* and the consumer hasn't declared one already. */
|
|
8699
8712
|
effectiveColumns = computed(() => {
|
|
8700
|
-
const
|
|
8713
|
+
const hidden = this.hiddenColumnIds();
|
|
8714
|
+
const declared = this.columns()
|
|
8715
|
+
.filter(col => !hidden.includes(col.id))
|
|
8716
|
+
.map(col => ({
|
|
8701
8717
|
...col,
|
|
8702
8718
|
type: col.type ?? 'text',
|
|
8703
8719
|
align: col.align ??
|
|
@@ -8825,6 +8841,94 @@ class EfDataCardComponent {
|
|
|
8825
8841
|
const max = col.maxFractionDigits ?? 2;
|
|
8826
8842
|
return `1.${min}-${max}`;
|
|
8827
8843
|
}
|
|
8844
|
+
/* ── Table tools state ──────────────────────────────────────── */
|
|
8845
|
+
/** Which tools panel is open, if any. */
|
|
8846
|
+
openTool = signal(null, ...(ngDevMode ? [{ debugName: "openTool" }] : /* istanbul ignore next */ []));
|
|
8847
|
+
/** Row density. Applied as a class on `.tbl-wrap`. */
|
|
8848
|
+
density = signal('default', ...(ngDevMode ? [{ debugName: "density" }] : /* istanbul ignore next */ []));
|
|
8849
|
+
/** Column ids the viewer has hidden. */
|
|
8850
|
+
hiddenColumnIds = signal([], ...(ngDevMode ? [{ debugName: "hiddenColumnIds" }] : /* istanbul ignore next */ []));
|
|
8851
|
+
densityOptions = [
|
|
8852
|
+
{ value: 'compact', labelKey: 'common_density_compact', icon: 'pi-align-justify' },
|
|
8853
|
+
{ value: 'default', labelKey: 'common_density_default', icon: 'pi-bars' },
|
|
8854
|
+
{ value: 'comfortable', labelKey: 'common_density_comfortable', icon: 'pi-list' },
|
|
8855
|
+
];
|
|
8856
|
+
/** Columns the viewer may hide -- structural ones stay put, since
|
|
8857
|
+
* hiding the selection checkbox or the row-actions cell would strand
|
|
8858
|
+
* the bulk bar and the per-row menu with no way back. */
|
|
8859
|
+
hideableColumns = computed(() =>
|
|
8860
|
+
// Derived from the DECLARED columns, not `effectiveColumns` --
|
|
8861
|
+
// that one already drops hidden columns, so a hidden column would
|
|
8862
|
+
// vanish from its own picker and could never be restored.
|
|
8863
|
+
this.columns().filter(c => c.id !== 'select' && c.id !== 'actions' && c.hideable !== false), ...(ngDevMode ? [{ debugName: "hideableColumns" }] : /* istanbul ignore next */ []));
|
|
8864
|
+
toggleTool(tool) {
|
|
8865
|
+
this.openTool.update(cur => (cur === tool ? null : tool));
|
|
8866
|
+
}
|
|
8867
|
+
setDensity(value) {
|
|
8868
|
+
this.density.set(value);
|
|
8869
|
+
this.openTool.set(null);
|
|
8870
|
+
this.savePreferences();
|
|
8871
|
+
}
|
|
8872
|
+
isColumnHidden(id) {
|
|
8873
|
+
return this.hiddenColumnIds().includes(id);
|
|
8874
|
+
}
|
|
8875
|
+
toggleColumn(id) {
|
|
8876
|
+
this.hiddenColumnIds.update(ids => ids.includes(id) ? ids.filter(x => x !== id) : [...ids, id]);
|
|
8877
|
+
this.savePreferences();
|
|
8878
|
+
}
|
|
8879
|
+
resetColumns() {
|
|
8880
|
+
this.hiddenColumnIds.set([]);
|
|
8881
|
+
this.savePreferences();
|
|
8882
|
+
}
|
|
8883
|
+
/** Close an open panel on an outside click or Escape. */
|
|
8884
|
+
onDocumentClick(event) {
|
|
8885
|
+
if (!this.openTool())
|
|
8886
|
+
return;
|
|
8887
|
+
const target = event.target;
|
|
8888
|
+
if (target?.closest('.tbl-tools'))
|
|
8889
|
+
return;
|
|
8890
|
+
this.openTool.set(null);
|
|
8891
|
+
}
|
|
8892
|
+
onEscape() {
|
|
8893
|
+
this.openTool.set(null);
|
|
8894
|
+
}
|
|
8895
|
+
storageKey() {
|
|
8896
|
+
const key = this.tableKey();
|
|
8897
|
+
return key ? `TABLE_PREFS_${key}` : null;
|
|
8898
|
+
}
|
|
8899
|
+
loadPreferences() {
|
|
8900
|
+
const key = this.storageKey();
|
|
8901
|
+
if (!key)
|
|
8902
|
+
return;
|
|
8903
|
+
try {
|
|
8904
|
+
const saved = StorageUtils.getLocal(key);
|
|
8905
|
+
if (!saved)
|
|
8906
|
+
return;
|
|
8907
|
+
if (saved.density)
|
|
8908
|
+
this.density.set(saved.density);
|
|
8909
|
+
if (Array.isArray(saved.hiddenColumnIds))
|
|
8910
|
+
this.hiddenColumnIds.set(saved.hiddenColumnIds);
|
|
8911
|
+
}
|
|
8912
|
+
catch {
|
|
8913
|
+
// Storage can throw outright (blocked site data, previews) --
|
|
8914
|
+
// the defaults are a perfectly good table.
|
|
8915
|
+
}
|
|
8916
|
+
}
|
|
8917
|
+
savePreferences() {
|
|
8918
|
+
const key = this.storageKey();
|
|
8919
|
+
if (!key)
|
|
8920
|
+
return;
|
|
8921
|
+
try {
|
|
8922
|
+
StorageUtils.setLocal(key, {
|
|
8923
|
+
density: this.density(),
|
|
8924
|
+
hiddenColumnIds: this.hiddenColumnIds(),
|
|
8925
|
+
});
|
|
8926
|
+
}
|
|
8927
|
+
catch {
|
|
8928
|
+
// Preferences are a convenience; losing them must never break
|
|
8929
|
+
// the table.
|
|
8930
|
+
}
|
|
8931
|
+
}
|
|
8828
8932
|
/** Tracks how many `ef-row-actions` are currently open inside this
|
|
8829
8933
|
* card. When > 0, `.tbl-wrap` lifts its `overflow: hidden` so the
|
|
8830
8934
|
* popup can escape its rounded edges. */
|
|
@@ -8857,7 +8961,7 @@ class EfDataCardComponent {
|
|
|
8857
8961
|
};
|
|
8858
8962
|
trackByColumn = (_, col) => col.id;
|
|
8859
8963
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: EfDataCardComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
8860
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.11", type: EfDataCardComponent, isStandalone: true, selector: "ef-data-card", inputs: { columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: false, transformFunction: null }, rows: { classPropertyName: "rows", publicName: "rows", isSignal: true, isRequired: false, transformFunction: null }, trackByField: { classPropertyName: "trackByField", publicName: "trackByField", isSignal: true, isRequired: false, transformFunction: null }, pageNumber: { classPropertyName: "pageNumber", publicName: "pageNumber", isSignal: true, isRequired: false, transformFunction: null }, pageSize: { classPropertyName: "pageSize", publicName: "pageSize", isSignal: true, isRequired: false, transformFunction: null }, totalCount: { classPropertyName: "totalCount", publicName: "totalCount", isSignal: true, isRequired: false, transformFunction: null }, pageSizeOptions: { classPropertyName: "pageSizeOptions", publicName: "pageSizeOptions", isSignal: true, isRequired: false, transformFunction: null }, hidePager: { classPropertyName: "hidePager", publicName: "hidePager", isSignal: true, isRequired: false, transformFunction: null }, sort: { classPropertyName: "sort", publicName: "sort", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, errorMsg: { classPropertyName: "errorMsg", publicName: "errorMsg", isSignal: true, isRequired: false, transformFunction: null }, loadingKey: { classPropertyName: "loadingKey", publicName: "loadingKey", isSignal: true, isRequired: false, transformFunction: null }, rowDoubleClickable: { classPropertyName: "rowDoubleClickable", publicName: "rowDoubleClickable", isSignal: true, isRequired: false, transformFunction: null }, hasActionsColumn: { classPropertyName: "hasActionsColumn", publicName: "hasActionsColumn", isSignal: true, isRequired: false, transformFunction: null }, rowActionsContext: { classPropertyName: "rowActionsContext", publicName: "rowActionsContext", isSignal: true, isRequired: false, transformFunction: null }, showViewAction: { classPropertyName: "showViewAction", publicName: "showViewAction", isSignal: true, isRequired: false, transformFunction: null }, showEditAction: { classPropertyName: "showEditAction", publicName: "showEditAction", isSignal: true, isRequired: false, transformFunction: null }, showDuplicateAction: { classPropertyName: "showDuplicateAction", publicName: "showDuplicateAction", isSignal: true, isRequired: false, transformFunction: null }, showDeleteAction: { classPropertyName: "showDeleteAction", publicName: "showDeleteAction", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { pageChange: "pageChange", pageSizeChange: "pageSizeChange", sortChange: "sortChange", rowDoubleClick: "rowDoubleClick", rowAction: "rowAction" }, host: { listeners: { "ef-row-actions-toggle": "onRowActionsToggle($event)" } }, queries: [{ propertyName: "bodyTemplates", predicate: EfColumnTemplateDirective }, { propertyName: "headerTemplates", predicate: EfColumnHeaderTemplateDirective }], ngImport: i0, template: "<div class=\"tbl-wrap\" [class.has-open-menu]=\"openMenuCount() > 0\">\n <!-- \u2500\u2500 HEAD ROW \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <div class=\"tbl-head\">\n <div class=\"count small\">\n @if (loading()) {\n <span>{{ loadingKey() | translate }}</span>\n } @else if (errorMsg()) {\n <span style=\"color: var(--st-cancelled-fg); font-weight: 600;\">\u26A0 {{ errorMsg() }}</span>\n } @else {\n <ng-content select=\"[tbl-head-info]\"></ng-content>\n }\n </div>\n <div style=\"display: flex; gap: 6px; align-items: center;\">\n <ng-content select=\"[tbl-head-actions]\"></ng-content>\n </div>\n </div>\n\n <!-- \u2500\u2500 TABLE \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <table class=\"tbl\">\n <thead>\n <tr>\n @for (col of effectiveColumns(); track trackByColumn($index, col)) {\n <th\n [class]=\"headerAlignClass(col)\"\n [class.is-sortable]=\"col.sortable\"\n [style.width]=\"col.width || null\"\n [attr.data-col]=\"col.id\"\n (click)=\"onHeaderClick(col)\"\n [style.cursor]=\"col.sortable ? 'pointer' : null\"\n >\n @if (headerTemplate(col.id); as headerTpl) {\n <ng-container *ngTemplateOutlet=\"headerTpl; context: { $implicit: col, col: col }\"></ng-container>\n } @else if (col.headerKey) {\n <span>{{ col.headerKey | translate }}</span>\n } @else if (col.header) {\n <span>{{ col.header }}</span>\n }\n @if (col.sortable && sortIndicator(col)) {\n <span aria-hidden=\"true\" style=\"margin-inline-start: 4px; opacity: 0.7;\">{{ sortIndicator(col) }}</span>\n }\n </th>\n }\n </tr>\n </thead>\n\n <tbody>\n @for (row of rows(); track trackByRow($index, row)) {\n <tr\n [class.is-row-clickable]=\"rowDoubleClickable()\"\n (dblclick)=\"onRowDoubleClick(row, $event)\"\n >\n @for (col of effectiveColumns(); track trackByColumn($index, col); let colIdx = $index) {\n <td [class]=\"cellAlignClass(col)\" [attr.data-col]=\"col.id\">\n @if (bodyTemplate(col.id); as bodyTpl) {\n <ng-container\n *ngTemplateOutlet=\"bodyTpl; context: { $implicit: row, col: col, index: $index }\"\n ></ng-container>\n } @else if (col.id === 'actions' && hasActionsColumn()) {\n <!-- Auto row-actions cell: View / Edit / Duplicate / Delete,\n gated by [show*Action] flags + ScreenContext perms. -->\n <ef-row-actions\n [items]=\"defaultRowActions(row)\"\n [context]=\"rowActionsContext()\"\n />\n } @else {\n @switch (col.type) {\n @case ('number') {\n {{ $any(cellValue(row, col)) | number:numberFormat(col):col.locale }}\n }\n @case ('money') {\n {{ $any(cellValue(row, col)) | currency:(col.currencyCode || 'EUR'):(col.currencyDisplay || 'symbol'):numberFormat(col):col.locale }}\n }\n @case ('date') {\n {{ $any(cellValue(row, col)) | date:(col.dateFormat || 'dd/MM/yyyy'):undefined:col.locale }}\n }\n @case ('datetime') {\n {{ $any(cellValue(row, col)) | date:(col.dateFormat || 'dd/MM/yyyy HH:mm'):undefined:col.locale }}\n }\n @case ('boolean') {\n @if (cellValue(row, col)) {\n <span class=\"bool yes\"><span class=\"dot\"></span> \u2713</span>\n } @else {\n <span class=\"bool no\"><span class=\"dot\"></span> \u2014</span>\n }\n }\n @case ('mono') {\n <span class=\"ref\">{{ cellValue(row, col) }}</span>\n }\n @case ('chip') {\n <span [class]=\"'chip ' + (col.chipPrefix || 'chip-') + cellValue(row, col)\">\n \u25CF {{ cellValue(row, col) }}\n </span>\n }\n @case ('status') {\n <ef-status-chip\n [referenceKey]=\"col.referenceKey || ''\"\n [code]=\"$any(cellValue(row, col))\"\n />\n }\n @case ('reference') {\n {{ resolveReference(cellValue(row, col), col) }}\n }\n @default {\n {{ cellValue(row, col) }}\n }\n }\n }\n </td>\n }\n </tr>\n } @empty {\n <tr>\n <td [attr.colspan]=\"effectiveColumns().length\">\n <ng-content select=\"[empty-state]\"></ng-content>\n </td>\n </tr>\n }\n </tbody>\n </table>\n\n <!-- \u2500\u2500 PAGER \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n @if (!hidePager()) {\n <ef-pager\n [pageNumber]=\"pageNumber()\"\n [pageSize]=\"pageSize()\"\n [totalCount]=\"totalCount()\"\n [pageSizeOptions]=\"pageSizeOptions()\"\n (pageChange)=\"pageChange.emit($event)\"\n (pageSizeChange)=\"pageSizeChange.emit($event)\"\n />\n }\n</div>\n", styles: ["@charset \"UTF-8\";.tbl thead th.is-sortable{cursor:pointer;-webkit-user-select:none;user-select:none;transition:color var(--t-fast, .14s) var(--ease-out, ease-out)}.tbl thead th.is-sortable:hover{color:var(--text)}.tbl tbody tr.is-row-clickable{cursor:pointer}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$3.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "component", type: EfPagerComponent, selector: "ef-pager", inputs: ["pageNumber", "pageSize", "totalCount", "pageSizeOptions", "linesPerPageLabelKey", "ofLabelKey", "prevLabelKey", "nextLabelKey", "hideSize"], outputs: ["pageChange", "pageSizeChange"] }, { kind: "component", type: EfStatusChipComponent, selector: "ef-status-chip", inputs: ["referenceKey", "code", "color", "label", "labelKey", "hideDot", "showCode"] }, { kind: "component", type: EfRowActionsComponent, selector: "ef-row-actions", inputs: ["items", "context", "triggerIcon", "triggerAriaKey", "disabled", "menuLeft"], outputs: ["opened", "closed"] }, { kind: "pipe", type: i1$3.DecimalPipe, name: "number" }, { kind: "pipe", type: i1$3.CurrencyPipe, name: "currency" }, { kind: "pipe", type: i1$3.DatePipe, name: "date" }, { kind: "pipe", type: i1$1.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
8964
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.11", type: EfDataCardComponent, isStandalone: true, selector: "ef-data-card", inputs: { columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: false, transformFunction: null }, rows: { classPropertyName: "rows", publicName: "rows", isSignal: true, isRequired: false, transformFunction: null }, trackByField: { classPropertyName: "trackByField", publicName: "trackByField", isSignal: true, isRequired: false, transformFunction: null }, pageNumber: { classPropertyName: "pageNumber", publicName: "pageNumber", isSignal: true, isRequired: false, transformFunction: null }, pageSize: { classPropertyName: "pageSize", publicName: "pageSize", isSignal: true, isRequired: false, transformFunction: null }, totalCount: { classPropertyName: "totalCount", publicName: "totalCount", isSignal: true, isRequired: false, transformFunction: null }, pageSizeOptions: { classPropertyName: "pageSizeOptions", publicName: "pageSizeOptions", isSignal: true, isRequired: false, transformFunction: null }, hidePager: { classPropertyName: "hidePager", publicName: "hidePager", isSignal: true, isRequired: false, transformFunction: null }, sort: { classPropertyName: "sort", publicName: "sort", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, errorMsg: { classPropertyName: "errorMsg", publicName: "errorMsg", isSignal: true, isRequired: false, transformFunction: null }, loadingKey: { classPropertyName: "loadingKey", publicName: "loadingKey", isSignal: true, isRequired: false, transformFunction: null }, rowDoubleClickable: { classPropertyName: "rowDoubleClickable", publicName: "rowDoubleClickable", isSignal: true, isRequired: false, transformFunction: null }, hasActionsColumn: { classPropertyName: "hasActionsColumn", publicName: "hasActionsColumn", isSignal: true, isRequired: false, transformFunction: null }, rowActionsContext: { classPropertyName: "rowActionsContext", publicName: "rowActionsContext", isSignal: true, isRequired: false, transformFunction: null }, showViewAction: { classPropertyName: "showViewAction", publicName: "showViewAction", isSignal: true, isRequired: false, transformFunction: null }, showEditAction: { classPropertyName: "showEditAction", publicName: "showEditAction", isSignal: true, isRequired: false, transformFunction: null }, showDuplicateAction: { classPropertyName: "showDuplicateAction", publicName: "showDuplicateAction", isSignal: true, isRequired: false, transformFunction: null }, showDeleteAction: { classPropertyName: "showDeleteAction", publicName: "showDeleteAction", isSignal: true, isRequired: false, transformFunction: null }, showDensityControl: { classPropertyName: "showDensityControl", publicName: "showDensityControl", isSignal: true, isRequired: false, transformFunction: null }, showColumnPicker: { classPropertyName: "showColumnPicker", publicName: "showColumnPicker", isSignal: true, isRequired: false, transformFunction: null }, tableKey: { classPropertyName: "tableKey", publicName: "tableKey", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { pageChange: "pageChange", pageSizeChange: "pageSizeChange", sortChange: "sortChange", rowDoubleClick: "rowDoubleClick", rowAction: "rowAction" }, host: { listeners: { "document:click": "onDocumentClick($event)", "document:keydown.escape": "onEscape()", "ef-row-actions-toggle": "onRowActionsToggle($event)" } }, queries: [{ propertyName: "bodyTemplates", predicate: EfColumnTemplateDirective }, { propertyName: "headerTemplates", predicate: EfColumnHeaderTemplateDirective }], ngImport: i0, template: "<div class=\"tbl-wrap\" [class.has-open-menu]=\"openMenuCount() > 0 || openTool() !== null\" [attr.data-density]=\"density()\">\n <!-- \u2500\u2500 HEAD ROW \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <div class=\"tbl-head\">\n <div class=\"count small\">\n @if (loading()) {\n <span>{{ loadingKey() | translate }}</span>\n } @else if (errorMsg()) {\n <span style=\"color: var(--st-cancelled-fg); font-weight: 600;\">\u26A0 {{ errorMsg() }}</span>\n } @else {\n <ng-content select=\"[tbl-head-info]\"></ng-content>\n }\n </div>\n <div class=\"tbl-tools\">\n <ng-content select=\"[tbl-head-actions]\"></ng-content>\n\n @if (showDensityControl()) {\n <div class=\"tbl-tool\">\n <button\n class=\"btn btn-ghost btn-sm\"\n type=\"button\"\n [class.open]=\"openTool() === 'density'\"\n [attr.aria-expanded]=\"openTool() === 'density'\"\n aria-haspopup=\"menu\"\n (click)=\"toggleTool('density')\"\n >\n <i class=\"pi pi-bars\" aria-hidden=\"true\"></i>\n {{ 'common_density' | translate }}\n </button>\n @if (openTool() === 'density') {\n <div class=\"tbl-tool__menu\" role=\"menu\">\n @for (opt of densityOptions; track opt.value) {\n <button\n type=\"button\"\n role=\"menuitemradio\"\n [attr.aria-checked]=\"density() === opt.value\"\n [class.is-active]=\"density() === opt.value\"\n (click)=\"setDensity(opt.value)\"\n >\n <i class=\"pi\" [ngClass]=\"opt.icon\" aria-hidden=\"true\"></i>\n <span class=\"tbl-tool__label\">{{ opt.labelKey | translate }}</span>\n @if (density() === opt.value) {\n <i class=\"pi pi-check tbl-tool__check\" aria-hidden=\"true\"></i>\n }\n </button>\n }\n </div>\n }\n </div>\n }\n\n @if (showColumnPicker()) {\n <div class=\"tbl-tool\">\n <button\n class=\"btn btn-ghost btn-sm\"\n type=\"button\"\n [class.open]=\"openTool() === 'columns'\"\n [attr.aria-expanded]=\"openTool() === 'columns'\"\n aria-haspopup=\"menu\"\n (click)=\"toggleTool('columns')\"\n >\n <i class=\"pi pi-th-large\" aria-hidden=\"true\"></i>\n {{ 'common_columns' | translate }}\n </button>\n @if (openTool() === 'columns') {\n <div class=\"tbl-tool__menu tbl-tool__menu--wide\" role=\"menu\">\n @for (col of hideableColumns(); track col.id) {\n <button\n type=\"button\"\n role=\"menuitemcheckbox\"\n [attr.aria-checked]=\"!isColumnHidden(col.id)\"\n [class.is-active]=\"!isColumnHidden(col.id)\"\n (click)=\"toggleColumn(col.id)\"\n >\n <i class=\"pi\" [class.pi-check]=\"!isColumnHidden(col.id)\" aria-hidden=\"true\"></i>\n <span class=\"tbl-tool__label\">{{\n col.headerKey ? (col.headerKey | translate) : (col.header || col.id)\n }}</span>\n </button>\n }\n <div class=\"tbl-tool__sep\"></div>\n <button type=\"button\" role=\"menuitem\" (click)=\"resetColumns()\">\n <i class=\"pi pi-refresh\" aria-hidden=\"true\"></i>\n <span class=\"tbl-tool__label\">{{ 'common_columns_reset' | translate }}</span>\n </button>\n </div>\n }\n </div>\n }\n </div>\n </div>\n\n <!-- \u2500\u2500 TABLE \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <table class=\"tbl\">\n <thead>\n <tr>\n @for (col of effectiveColumns(); track trackByColumn($index, col)) {\n <th\n [class]=\"headerAlignClass(col)\"\n [class.is-sortable]=\"col.sortable\"\n [style.width]=\"col.width || null\"\n [attr.data-col]=\"col.id\"\n (click)=\"onHeaderClick(col)\"\n [style.cursor]=\"col.sortable ? 'pointer' : null\"\n >\n @if (headerTemplate(col.id); as headerTpl) {\n <ng-container *ngTemplateOutlet=\"headerTpl; context: { $implicit: col, col: col }\"></ng-container>\n } @else if (col.headerKey) {\n <span>{{ col.headerKey | translate }}</span>\n } @else if (col.header) {\n <span>{{ col.header }}</span>\n }\n @if (col.sortable && sortIndicator(col)) {\n <span aria-hidden=\"true\" style=\"margin-inline-start: 4px; opacity: 0.7;\">{{ sortIndicator(col) }}</span>\n }\n </th>\n }\n </tr>\n </thead>\n\n <tbody>\n @for (row of rows(); track trackByRow($index, row)) {\n <tr\n [class.is-row-clickable]=\"rowDoubleClickable()\"\n (dblclick)=\"onRowDoubleClick(row, $event)\"\n >\n @for (col of effectiveColumns(); track trackByColumn($index, col); let colIdx = $index) {\n <td [class]=\"cellAlignClass(col)\" [attr.data-col]=\"col.id\">\n @if (bodyTemplate(col.id); as bodyTpl) {\n <ng-container\n *ngTemplateOutlet=\"bodyTpl; context: { $implicit: row, col: col, index: $index }\"\n ></ng-container>\n } @else if (col.id === 'actions' && hasActionsColumn()) {\n <!-- Auto row-actions cell: View / Edit / Duplicate / Delete,\n gated by [show*Action] flags + ScreenContext perms. -->\n <ef-row-actions\n [items]=\"defaultRowActions(row)\"\n [context]=\"rowActionsContext()\"\n />\n } @else {\n @switch (col.type) {\n @case ('number') {\n {{ $any(cellValue(row, col)) | number:numberFormat(col):col.locale }}\n }\n @case ('money') {\n {{ $any(cellValue(row, col)) | currency:(col.currencyCode || 'EUR'):(col.currencyDisplay || 'symbol'):numberFormat(col):col.locale }}\n }\n @case ('date') {\n {{ $any(cellValue(row, col)) | date:(col.dateFormat || 'dd/MM/yyyy'):undefined:col.locale }}\n }\n @case ('datetime') {\n {{ $any(cellValue(row, col)) | date:(col.dateFormat || 'dd/MM/yyyy HH:mm'):undefined:col.locale }}\n }\n @case ('boolean') {\n @if (cellValue(row, col)) {\n <span class=\"bool yes\"><span class=\"dot\"></span> \u2713</span>\n } @else {\n <span class=\"bool no\"><span class=\"dot\"></span> \u2014</span>\n }\n }\n @case ('mono') {\n <span class=\"ref\">{{ cellValue(row, col) }}</span>\n }\n @case ('chip') {\n <span [class]=\"'chip ' + (col.chipPrefix || 'chip-') + cellValue(row, col)\">\n \u25CF {{ cellValue(row, col) }}\n </span>\n }\n @case ('status') {\n <ef-status-chip\n [referenceKey]=\"col.referenceKey || ''\"\n [code]=\"$any(cellValue(row, col))\"\n />\n }\n @case ('reference') {\n {{ resolveReference(cellValue(row, col), col) }}\n }\n @default {\n {{ cellValue(row, col) }}\n }\n }\n }\n </td>\n }\n </tr>\n } @empty {\n <tr>\n <td [attr.colspan]=\"effectiveColumns().length\">\n <ng-content select=\"[empty-state]\"></ng-content>\n </td>\n </tr>\n }\n </tbody>\n </table>\n\n <!-- \u2500\u2500 PAGER \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n @if (!hidePager()) {\n <ef-pager\n [pageNumber]=\"pageNumber()\"\n [pageSize]=\"pageSize()\"\n [totalCount]=\"totalCount()\"\n [pageSizeOptions]=\"pageSizeOptions()\"\n (pageChange)=\"pageChange.emit($event)\"\n (pageSizeChange)=\"pageSizeChange.emit($event)\"\n />\n }\n</div>\n", styles: ["@charset \"UTF-8\";.tbl thead th.is-sortable{cursor:pointer;-webkit-user-select:none;user-select:none;transition:color var(--t-fast, .14s) var(--ease-out, ease-out)}.tbl thead th.is-sortable:hover{color:var(--text)}.tbl tbody tr.is-row-clickable{cursor:pointer}.tbl-tools{display:flex;gap:6px;align-items:center}.tbl-tool{position:relative}.tbl-tool>.btn.open{color:var(--text);background:var(--paper)}.tbl-tool__menu{position:absolute;top:calc(100% + 8px);inset-inline-end:0;z-index:40;min-width:212px;max-height:340px;overflow-y:auto;padding:6px;display:grid;gap:1px;background:var(--paper-alt);border:1px solid var(--rule);border-radius:var(--r-xl);box-shadow:var(--shadow-3);animation:row-actions-menu-in var(--t-base) var(--ease-spring)}.tbl-tool__menu--wide{min-width:248px}.tbl-tool__menu button{appearance:none;background:transparent;border:0;width:100%;text-align:start;font:inherit;font-size:13.5px;font-weight:600;color:var(--text);display:flex;align-items:center;gap:12px;padding:9px 12px;border-radius:var(--r-md);cursor:pointer;transition:background-color var(--t-fast) var(--ease-out)}.tbl-tool__menu button:hover,.tbl-tool__menu button:focus-visible{background:var(--paper);outline:0}.tbl-tool__menu button>.pi{width:16px;flex:none;font-size:14px;color:var(--muted)}.tbl-tool__menu button.is-active>.pi{color:var(--module, var(--text))}.tbl-tool__label{flex:1 1 auto;min-width:0}.tbl-tool__check{color:var(--module, var(--text))}.tbl-tool__sep{margin:5px 2px;border-top:1px solid var(--rule)}.tbl-wrap[data-density=compact] .tbl tbody td{padding-top:4px;padding-bottom:4px}.tbl-wrap[data-density=comfortable] .tbl tbody td{padding-top:16px;padding-bottom:16px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$3.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$3.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "component", type: EfPagerComponent, selector: "ef-pager", inputs: ["pageNumber", "pageSize", "totalCount", "pageSizeOptions", "linesPerPageLabelKey", "ofLabelKey", "prevLabelKey", "nextLabelKey", "hideSize"], outputs: ["pageChange", "pageSizeChange"] }, { kind: "component", type: EfStatusChipComponent, selector: "ef-status-chip", inputs: ["referenceKey", "code", "color", "label", "labelKey", "hideDot", "showCode"] }, { kind: "component", type: EfRowActionsComponent, selector: "ef-row-actions", inputs: ["items", "context", "triggerIcon", "triggerAriaKey", "disabled", "menuLeft"], outputs: ["opened", "closed"] }, { kind: "pipe", type: i1$3.DecimalPipe, name: "number" }, { kind: "pipe", type: i1$3.CurrencyPipe, name: "currency" }, { kind: "pipe", type: i1$3.DatePipe, name: "date" }, { kind: "pipe", type: i1$1.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
8861
8965
|
}
|
|
8862
8966
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: EfDataCardComponent, decorators: [{
|
|
8863
8967
|
type: Component,
|
|
@@ -8867,13 +8971,19 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImpo
|
|
|
8867
8971
|
EfPagerComponent,
|
|
8868
8972
|
EfStatusChipComponent,
|
|
8869
8973
|
EfRowActionsComponent,
|
|
8870
|
-
], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"tbl-wrap\" [class.has-open-menu]=\"openMenuCount() > 0\">\n <!-- \u2500\u2500 HEAD ROW \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <div class=\"tbl-head\">\n <div class=\"count small\">\n @if (loading()) {\n <span>{{ loadingKey() | translate }}</span>\n } @else if (errorMsg()) {\n <span style=\"color: var(--st-cancelled-fg); font-weight: 600;\">\u26A0 {{ errorMsg() }}</span>\n } @else {\n <ng-content select=\"[tbl-head-info]\"></ng-content>\n }\n </div>\n <div style=\"display: flex; gap: 6px; align-items: center;\">\n <ng-content select=\"[tbl-head-actions]\"></ng-content>\n </div>\n </div>\n\n <!-- \u2500\u2500 TABLE \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <table class=\"tbl\">\n <thead>\n <tr>\n @for (col of effectiveColumns(); track trackByColumn($index, col)) {\n <th\n [class]=\"headerAlignClass(col)\"\n [class.is-sortable]=\"col.sortable\"\n [style.width]=\"col.width || null\"\n [attr.data-col]=\"col.id\"\n (click)=\"onHeaderClick(col)\"\n [style.cursor]=\"col.sortable ? 'pointer' : null\"\n >\n @if (headerTemplate(col.id); as headerTpl) {\n <ng-container *ngTemplateOutlet=\"headerTpl; context: { $implicit: col, col: col }\"></ng-container>\n } @else if (col.headerKey) {\n <span>{{ col.headerKey | translate }}</span>\n } @else if (col.header) {\n <span>{{ col.header }}</span>\n }\n @if (col.sortable && sortIndicator(col)) {\n <span aria-hidden=\"true\" style=\"margin-inline-start: 4px; opacity: 0.7;\">{{ sortIndicator(col) }}</span>\n }\n </th>\n }\n </tr>\n </thead>\n\n <tbody>\n @for (row of rows(); track trackByRow($index, row)) {\n <tr\n [class.is-row-clickable]=\"rowDoubleClickable()\"\n (dblclick)=\"onRowDoubleClick(row, $event)\"\n >\n @for (col of effectiveColumns(); track trackByColumn($index, col); let colIdx = $index) {\n <td [class]=\"cellAlignClass(col)\" [attr.data-col]=\"col.id\">\n @if (bodyTemplate(col.id); as bodyTpl) {\n <ng-container\n *ngTemplateOutlet=\"bodyTpl; context: { $implicit: row, col: col, index: $index }\"\n ></ng-container>\n } @else if (col.id === 'actions' && hasActionsColumn()) {\n <!-- Auto row-actions cell: View / Edit / Duplicate / Delete,\n gated by [show*Action] flags + ScreenContext perms. -->\n <ef-row-actions\n [items]=\"defaultRowActions(row)\"\n [context]=\"rowActionsContext()\"\n />\n } @else {\n @switch (col.type) {\n @case ('number') {\n {{ $any(cellValue(row, col)) | number:numberFormat(col):col.locale }}\n }\n @case ('money') {\n {{ $any(cellValue(row, col)) | currency:(col.currencyCode || 'EUR'):(col.currencyDisplay || 'symbol'):numberFormat(col):col.locale }}\n }\n @case ('date') {\n {{ $any(cellValue(row, col)) | date:(col.dateFormat || 'dd/MM/yyyy'):undefined:col.locale }}\n }\n @case ('datetime') {\n {{ $any(cellValue(row, col)) | date:(col.dateFormat || 'dd/MM/yyyy HH:mm'):undefined:col.locale }}\n }\n @case ('boolean') {\n @if (cellValue(row, col)) {\n <span class=\"bool yes\"><span class=\"dot\"></span> \u2713</span>\n } @else {\n <span class=\"bool no\"><span class=\"dot\"></span> \u2014</span>\n }\n }\n @case ('mono') {\n <span class=\"ref\">{{ cellValue(row, col) }}</span>\n }\n @case ('chip') {\n <span [class]=\"'chip ' + (col.chipPrefix || 'chip-') + cellValue(row, col)\">\n \u25CF {{ cellValue(row, col) }}\n </span>\n }\n @case ('status') {\n <ef-status-chip\n [referenceKey]=\"col.referenceKey || ''\"\n [code]=\"$any(cellValue(row, col))\"\n />\n }\n @case ('reference') {\n {{ resolveReference(cellValue(row, col), col) }}\n }\n @default {\n {{ cellValue(row, col) }}\n }\n }\n }\n </td>\n }\n </tr>\n } @empty {\n <tr>\n <td [attr.colspan]=\"effectiveColumns().length\">\n <ng-content select=\"[empty-state]\"></ng-content>\n </td>\n </tr>\n }\n </tbody>\n </table>\n\n <!-- \u2500\u2500 PAGER \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n @if (!hidePager()) {\n <ef-pager\n [pageNumber]=\"pageNumber()\"\n [pageSize]=\"pageSize()\"\n [totalCount]=\"totalCount()\"\n [pageSizeOptions]=\"pageSizeOptions()\"\n (pageChange)=\"pageChange.emit($event)\"\n (pageSizeChange)=\"pageSizeChange.emit($event)\"\n />\n }\n</div>\n", styles: ["@charset \"UTF-8\";.tbl thead th.is-sortable{cursor:pointer;-webkit-user-select:none;user-select:none;transition:color var(--t-fast, .14s) var(--ease-out, ease-out)}.tbl thead th.is-sortable:hover{color:var(--text)}.tbl tbody tr.is-row-clickable{cursor:pointer}\n"] }]
|
|
8871
|
-
}], propDecorators: { columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: false }] }], rows: [{ type: i0.Input, args: [{ isSignal: true, alias: "rows", required: false }] }], trackByField: [{ type: i0.Input, args: [{ isSignal: true, alias: "trackByField", required: false }] }], pageNumber: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageNumber", required: false }] }], pageSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageSize", required: false }] }], totalCount: [{ type: i0.Input, args: [{ isSignal: true, alias: "totalCount", required: false }] }], pageSizeOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageSizeOptions", required: false }] }], hidePager: [{ type: i0.Input, args: [{ isSignal: true, alias: "hidePager", required: false }] }], sort: [{ type: i0.Input, args: [{ isSignal: true, alias: "sort", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], errorMsg: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorMsg", required: false }] }], loadingKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "loadingKey", required: false }] }], rowDoubleClickable: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowDoubleClickable", required: false }] }], hasActionsColumn: [{ type: i0.Input, args: [{ isSignal: true, alias: "hasActionsColumn", required: false }] }], rowActionsContext: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowActionsContext", required: false }] }], showViewAction: [{ type: i0.Input, args: [{ isSignal: true, alias: "showViewAction", required: false }] }], showEditAction: [{ type: i0.Input, args: [{ isSignal: true, alias: "showEditAction", required: false }] }], showDuplicateAction: [{ type: i0.Input, args: [{ isSignal: true, alias: "showDuplicateAction", required: false }] }], showDeleteAction: [{ type: i0.Input, args: [{ isSignal: true, alias: "showDeleteAction", required: false }] }], pageChange: [{ type: i0.Output, args: ["pageChange"] }], pageSizeChange: [{ type: i0.Output, args: ["pageSizeChange"] }], sortChange: [{ type: i0.Output, args: ["sortChange"] }], rowDoubleClick: [{ type: i0.Output, args: ["rowDoubleClick"] }], rowAction: [{ type: i0.Output, args: ["rowAction"] }], bodyTemplates: [{
|
|
8974
|
+
], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"tbl-wrap\" [class.has-open-menu]=\"openMenuCount() > 0 || openTool() !== null\" [attr.data-density]=\"density()\">\n <!-- \u2500\u2500 HEAD ROW \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <div class=\"tbl-head\">\n <div class=\"count small\">\n @if (loading()) {\n <span>{{ loadingKey() | translate }}</span>\n } @else if (errorMsg()) {\n <span style=\"color: var(--st-cancelled-fg); font-weight: 600;\">\u26A0 {{ errorMsg() }}</span>\n } @else {\n <ng-content select=\"[tbl-head-info]\"></ng-content>\n }\n </div>\n <div class=\"tbl-tools\">\n <ng-content select=\"[tbl-head-actions]\"></ng-content>\n\n @if (showDensityControl()) {\n <div class=\"tbl-tool\">\n <button\n class=\"btn btn-ghost btn-sm\"\n type=\"button\"\n [class.open]=\"openTool() === 'density'\"\n [attr.aria-expanded]=\"openTool() === 'density'\"\n aria-haspopup=\"menu\"\n (click)=\"toggleTool('density')\"\n >\n <i class=\"pi pi-bars\" aria-hidden=\"true\"></i>\n {{ 'common_density' | translate }}\n </button>\n @if (openTool() === 'density') {\n <div class=\"tbl-tool__menu\" role=\"menu\">\n @for (opt of densityOptions; track opt.value) {\n <button\n type=\"button\"\n role=\"menuitemradio\"\n [attr.aria-checked]=\"density() === opt.value\"\n [class.is-active]=\"density() === opt.value\"\n (click)=\"setDensity(opt.value)\"\n >\n <i class=\"pi\" [ngClass]=\"opt.icon\" aria-hidden=\"true\"></i>\n <span class=\"tbl-tool__label\">{{ opt.labelKey | translate }}</span>\n @if (density() === opt.value) {\n <i class=\"pi pi-check tbl-tool__check\" aria-hidden=\"true\"></i>\n }\n </button>\n }\n </div>\n }\n </div>\n }\n\n @if (showColumnPicker()) {\n <div class=\"tbl-tool\">\n <button\n class=\"btn btn-ghost btn-sm\"\n type=\"button\"\n [class.open]=\"openTool() === 'columns'\"\n [attr.aria-expanded]=\"openTool() === 'columns'\"\n aria-haspopup=\"menu\"\n (click)=\"toggleTool('columns')\"\n >\n <i class=\"pi pi-th-large\" aria-hidden=\"true\"></i>\n {{ 'common_columns' | translate }}\n </button>\n @if (openTool() === 'columns') {\n <div class=\"tbl-tool__menu tbl-tool__menu--wide\" role=\"menu\">\n @for (col of hideableColumns(); track col.id) {\n <button\n type=\"button\"\n role=\"menuitemcheckbox\"\n [attr.aria-checked]=\"!isColumnHidden(col.id)\"\n [class.is-active]=\"!isColumnHidden(col.id)\"\n (click)=\"toggleColumn(col.id)\"\n >\n <i class=\"pi\" [class.pi-check]=\"!isColumnHidden(col.id)\" aria-hidden=\"true\"></i>\n <span class=\"tbl-tool__label\">{{\n col.headerKey ? (col.headerKey | translate) : (col.header || col.id)\n }}</span>\n </button>\n }\n <div class=\"tbl-tool__sep\"></div>\n <button type=\"button\" role=\"menuitem\" (click)=\"resetColumns()\">\n <i class=\"pi pi-refresh\" aria-hidden=\"true\"></i>\n <span class=\"tbl-tool__label\">{{ 'common_columns_reset' | translate }}</span>\n </button>\n </div>\n }\n </div>\n }\n </div>\n </div>\n\n <!-- \u2500\u2500 TABLE \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <table class=\"tbl\">\n <thead>\n <tr>\n @for (col of effectiveColumns(); track trackByColumn($index, col)) {\n <th\n [class]=\"headerAlignClass(col)\"\n [class.is-sortable]=\"col.sortable\"\n [style.width]=\"col.width || null\"\n [attr.data-col]=\"col.id\"\n (click)=\"onHeaderClick(col)\"\n [style.cursor]=\"col.sortable ? 'pointer' : null\"\n >\n @if (headerTemplate(col.id); as headerTpl) {\n <ng-container *ngTemplateOutlet=\"headerTpl; context: { $implicit: col, col: col }\"></ng-container>\n } @else if (col.headerKey) {\n <span>{{ col.headerKey | translate }}</span>\n } @else if (col.header) {\n <span>{{ col.header }}</span>\n }\n @if (col.sortable && sortIndicator(col)) {\n <span aria-hidden=\"true\" style=\"margin-inline-start: 4px; opacity: 0.7;\">{{ sortIndicator(col) }}</span>\n }\n </th>\n }\n </tr>\n </thead>\n\n <tbody>\n @for (row of rows(); track trackByRow($index, row)) {\n <tr\n [class.is-row-clickable]=\"rowDoubleClickable()\"\n (dblclick)=\"onRowDoubleClick(row, $event)\"\n >\n @for (col of effectiveColumns(); track trackByColumn($index, col); let colIdx = $index) {\n <td [class]=\"cellAlignClass(col)\" [attr.data-col]=\"col.id\">\n @if (bodyTemplate(col.id); as bodyTpl) {\n <ng-container\n *ngTemplateOutlet=\"bodyTpl; context: { $implicit: row, col: col, index: $index }\"\n ></ng-container>\n } @else if (col.id === 'actions' && hasActionsColumn()) {\n <!-- Auto row-actions cell: View / Edit / Duplicate / Delete,\n gated by [show*Action] flags + ScreenContext perms. -->\n <ef-row-actions\n [items]=\"defaultRowActions(row)\"\n [context]=\"rowActionsContext()\"\n />\n } @else {\n @switch (col.type) {\n @case ('number') {\n {{ $any(cellValue(row, col)) | number:numberFormat(col):col.locale }}\n }\n @case ('money') {\n {{ $any(cellValue(row, col)) | currency:(col.currencyCode || 'EUR'):(col.currencyDisplay || 'symbol'):numberFormat(col):col.locale }}\n }\n @case ('date') {\n {{ $any(cellValue(row, col)) | date:(col.dateFormat || 'dd/MM/yyyy'):undefined:col.locale }}\n }\n @case ('datetime') {\n {{ $any(cellValue(row, col)) | date:(col.dateFormat || 'dd/MM/yyyy HH:mm'):undefined:col.locale }}\n }\n @case ('boolean') {\n @if (cellValue(row, col)) {\n <span class=\"bool yes\"><span class=\"dot\"></span> \u2713</span>\n } @else {\n <span class=\"bool no\"><span class=\"dot\"></span> \u2014</span>\n }\n }\n @case ('mono') {\n <span class=\"ref\">{{ cellValue(row, col) }}</span>\n }\n @case ('chip') {\n <span [class]=\"'chip ' + (col.chipPrefix || 'chip-') + cellValue(row, col)\">\n \u25CF {{ cellValue(row, col) }}\n </span>\n }\n @case ('status') {\n <ef-status-chip\n [referenceKey]=\"col.referenceKey || ''\"\n [code]=\"$any(cellValue(row, col))\"\n />\n }\n @case ('reference') {\n {{ resolveReference(cellValue(row, col), col) }}\n }\n @default {\n {{ cellValue(row, col) }}\n }\n }\n }\n </td>\n }\n </tr>\n } @empty {\n <tr>\n <td [attr.colspan]=\"effectiveColumns().length\">\n <ng-content select=\"[empty-state]\"></ng-content>\n </td>\n </tr>\n }\n </tbody>\n </table>\n\n <!-- \u2500\u2500 PAGER \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n @if (!hidePager()) {\n <ef-pager\n [pageNumber]=\"pageNumber()\"\n [pageSize]=\"pageSize()\"\n [totalCount]=\"totalCount()\"\n [pageSizeOptions]=\"pageSizeOptions()\"\n (pageChange)=\"pageChange.emit($event)\"\n (pageSizeChange)=\"pageSizeChange.emit($event)\"\n />\n }\n</div>\n", styles: ["@charset \"UTF-8\";.tbl thead th.is-sortable{cursor:pointer;-webkit-user-select:none;user-select:none;transition:color var(--t-fast, .14s) var(--ease-out, ease-out)}.tbl thead th.is-sortable:hover{color:var(--text)}.tbl tbody tr.is-row-clickable{cursor:pointer}.tbl-tools{display:flex;gap:6px;align-items:center}.tbl-tool{position:relative}.tbl-tool>.btn.open{color:var(--text);background:var(--paper)}.tbl-tool__menu{position:absolute;top:calc(100% + 8px);inset-inline-end:0;z-index:40;min-width:212px;max-height:340px;overflow-y:auto;padding:6px;display:grid;gap:1px;background:var(--paper-alt);border:1px solid var(--rule);border-radius:var(--r-xl);box-shadow:var(--shadow-3);animation:row-actions-menu-in var(--t-base) var(--ease-spring)}.tbl-tool__menu--wide{min-width:248px}.tbl-tool__menu button{appearance:none;background:transparent;border:0;width:100%;text-align:start;font:inherit;font-size:13.5px;font-weight:600;color:var(--text);display:flex;align-items:center;gap:12px;padding:9px 12px;border-radius:var(--r-md);cursor:pointer;transition:background-color var(--t-fast) var(--ease-out)}.tbl-tool__menu button:hover,.tbl-tool__menu button:focus-visible{background:var(--paper);outline:0}.tbl-tool__menu button>.pi{width:16px;flex:none;font-size:14px;color:var(--muted)}.tbl-tool__menu button.is-active>.pi{color:var(--module, var(--text))}.tbl-tool__label{flex:1 1 auto;min-width:0}.tbl-tool__check{color:var(--module, var(--text))}.tbl-tool__sep{margin:5px 2px;border-top:1px solid var(--rule)}.tbl-wrap[data-density=compact] .tbl tbody td{padding-top:4px;padding-bottom:4px}.tbl-wrap[data-density=comfortable] .tbl tbody td{padding-top:16px;padding-bottom:16px}\n"] }]
|
|
8975
|
+
}], propDecorators: { columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: false }] }], rows: [{ type: i0.Input, args: [{ isSignal: true, alias: "rows", required: false }] }], trackByField: [{ type: i0.Input, args: [{ isSignal: true, alias: "trackByField", required: false }] }], pageNumber: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageNumber", required: false }] }], pageSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageSize", required: false }] }], totalCount: [{ type: i0.Input, args: [{ isSignal: true, alias: "totalCount", required: false }] }], pageSizeOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageSizeOptions", required: false }] }], hidePager: [{ type: i0.Input, args: [{ isSignal: true, alias: "hidePager", required: false }] }], sort: [{ type: i0.Input, args: [{ isSignal: true, alias: "sort", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], errorMsg: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorMsg", required: false }] }], loadingKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "loadingKey", required: false }] }], rowDoubleClickable: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowDoubleClickable", required: false }] }], hasActionsColumn: [{ type: i0.Input, args: [{ isSignal: true, alias: "hasActionsColumn", required: false }] }], rowActionsContext: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowActionsContext", required: false }] }], showViewAction: [{ type: i0.Input, args: [{ isSignal: true, alias: "showViewAction", required: false }] }], showEditAction: [{ type: i0.Input, args: [{ isSignal: true, alias: "showEditAction", required: false }] }], showDuplicateAction: [{ type: i0.Input, args: [{ isSignal: true, alias: "showDuplicateAction", required: false }] }], showDeleteAction: [{ type: i0.Input, args: [{ isSignal: true, alias: "showDeleteAction", required: false }] }], showDensityControl: [{ type: i0.Input, args: [{ isSignal: true, alias: "showDensityControl", required: false }] }], showColumnPicker: [{ type: i0.Input, args: [{ isSignal: true, alias: "showColumnPicker", required: false }] }], tableKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "tableKey", required: false }] }], pageChange: [{ type: i0.Output, args: ["pageChange"] }], pageSizeChange: [{ type: i0.Output, args: ["pageSizeChange"] }], sortChange: [{ type: i0.Output, args: ["sortChange"] }], rowDoubleClick: [{ type: i0.Output, args: ["rowDoubleClick"] }], rowAction: [{ type: i0.Output, args: ["rowAction"] }], bodyTemplates: [{
|
|
8872
8976
|
type: ContentChildren,
|
|
8873
8977
|
args: [EfColumnTemplateDirective]
|
|
8874
8978
|
}], headerTemplates: [{
|
|
8875
8979
|
type: ContentChildren,
|
|
8876
8980
|
args: [EfColumnHeaderTemplateDirective]
|
|
8981
|
+
}], onDocumentClick: [{
|
|
8982
|
+
type: HostListener,
|
|
8983
|
+
args: ['document:click', ['$event']]
|
|
8984
|
+
}], onEscape: [{
|
|
8985
|
+
type: HostListener,
|
|
8986
|
+
args: ['document:keydown.escape']
|
|
8877
8987
|
}], onRowActionsToggle: [{
|
|
8878
8988
|
type: HostListener,
|
|
8879
8989
|
args: ['ef-row-actions-toggle', ['$event']]
|