@life-cockpit/angular-ui-kit 2.3.0 → 2.4.0
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,5 +1,5 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { inject, PLATFORM_ID, signal, computed, Injectable, input, effect, ChangeDetectionStrategy, Component, model, contentChildren, untracked, output, ViewChild, ViewEncapsulation, HostListener, forwardRef, InjectionToken, ElementRef, viewChild, ChangeDetectorRef, EventEmitter, Output, Input, ViewChildren, HostBinding, ViewContainerRef, Renderer2, Directive, TemplateRef, ContentChildren, ContentChild, DestroyRef, afterNextRender, SecurityContext, NgZone, ApplicationRef, EnvironmentInjector, createComponent } from '@angular/core';
|
|
2
|
+
import { inject, PLATFORM_ID, signal, computed, Injectable, input, effect, ChangeDetectionStrategy, Component, model, contentChildren, untracked, output, ViewChild, ViewEncapsulation, HostListener, forwardRef, InjectionToken, ElementRef, viewChild, ChangeDetectorRef, EventEmitter, Output, Input, ViewChildren, HostBinding, ViewContainerRef, Renderer2, Directive, TemplateRef, ContentChildren, ContentChild, linkedSignal, DestroyRef, afterNextRender, SecurityContext, NgZone, ApplicationRef, EnvironmentInjector, createComponent } from '@angular/core';
|
|
3
3
|
import { isPlatformBrowser, NgClass, CommonModule, NgTemplateOutlet, NgStyle, SlicePipe } from '@angular/common';
|
|
4
4
|
import * as i1$4 from '@angular/platform-browser';
|
|
5
5
|
import { DomSanitizer } from '@angular/platform-browser';
|
|
@@ -7121,6 +7121,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.10", ngImpo
|
|
|
7121
7121
|
* - Per-cell class/style callbacks for conditional styling
|
|
7122
7122
|
* - Custom cell templates via content projection
|
|
7123
7123
|
* - Composed cells (e.g. avatar + badge + actions)
|
|
7124
|
+
* - Hierarchical "tree" rows (grouped / expandable) via `idKey` + `parentKey`
|
|
7124
7125
|
* - Responsive horizontal scrolling
|
|
7125
7126
|
* - Empty state text for no data
|
|
7126
7127
|
* - Accessible with proper table semantics
|
|
@@ -7190,6 +7191,31 @@ class TableComponent {
|
|
|
7190
7191
|
actionsWidth = input(undefined, ...(ngDevMode ? [{ debugName: "actionsWidth" }] : /* istanbul ignore next */ []));
|
|
7191
7192
|
/** Horizontal alignment of the action buttons (and header label) within the cell */
|
|
7192
7193
|
actionsAlign = input('start', ...(ngDevMode ? [{ debugName: "actionsAlign" }] : /* istanbul ignore next */ []));
|
|
7194
|
+
// -- Tree / grouped rows --
|
|
7195
|
+
/**
|
|
7196
|
+
* Row field holding the unique id. Required (together with {@link parentKey})
|
|
7197
|
+
* to enable hierarchical "tree mode". Absent ⇒ today's flat table.
|
|
7198
|
+
*/
|
|
7199
|
+
idKey = input(undefined, ...(ngDevMode ? [{ debugName: "idKey" }] : /* istanbul ignore next */ []));
|
|
7200
|
+
/**
|
|
7201
|
+
* Row field referencing the parent row's id. Presence of both `idKey` and
|
|
7202
|
+
* `parentKey` enables tree mode. Rows with an absent/empty or unknown parent
|
|
7203
|
+
* id are treated as roots.
|
|
7204
|
+
*/
|
|
7205
|
+
parentKey = input(undefined, ...(ngDevMode ? [{ debugName: "parentKey" }] : /* istanbul ignore next */ []));
|
|
7206
|
+
/** Column key the chevron + indentation attach to. Default: first column. */
|
|
7207
|
+
treeColumn = input(undefined, ...(ngDevMode ? [{ debugName: "treeColumn" }] : /* istanbul ignore next */ []));
|
|
7208
|
+
/** Initial expand state for all parent rows when uncontrolled. Default: true. */
|
|
7209
|
+
defaultExpanded = input(true, ...(ngDevMode ? [{ debugName: "defaultExpanded" }] : /* istanbul ignore next */ []));
|
|
7210
|
+
/**
|
|
7211
|
+
* Controlled set of expanded parent ids. When provided, the table renders
|
|
7212
|
+
* exactly these as expanded; combine with {@link expandedIdsChange} for
|
|
7213
|
+
* `[(expandedIds)]`. When omitted, expansion is uncontrolled and seeded by
|
|
7214
|
+
* {@link defaultExpanded}.
|
|
7215
|
+
*/
|
|
7216
|
+
expandedIds = input(undefined, ...(ngDevMode ? [{ debugName: "expandedIds" }] : /* istanbul ignore next */ []));
|
|
7217
|
+
/** Indentation per depth level, in px. Default: 20. */
|
|
7218
|
+
indentSize = input(20, ...(ngDevMode ? [{ debugName: "indentSize" }] : /* istanbul ignore next */ []));
|
|
7193
7219
|
/** Emitted when a sortable column header is clicked */
|
|
7194
7220
|
sort = output();
|
|
7195
7221
|
/** Emitted when a row is clicked */
|
|
@@ -7200,14 +7226,24 @@ class TableComponent {
|
|
|
7200
7226
|
selectionChange = output();
|
|
7201
7227
|
/** Emitted when a row action button is clicked */
|
|
7202
7228
|
actionClick = output();
|
|
7229
|
+
/** Emitted when a parent row is expanded/collapsed (tree mode). */
|
|
7230
|
+
rowToggle = output();
|
|
7231
|
+
/** Emitted with the full list of expanded parent ids; enables `[(expandedIds)]`. */
|
|
7232
|
+
expandedIdsChange = output();
|
|
7203
7233
|
// -- Internal state --
|
|
7204
7234
|
currentSort = signal(null, ...(ngDevMode ? [{ debugName: "currentSort" }] : /* istanbul ignore next */ []));
|
|
7205
7235
|
currentPage = signal(0, ...(ngDevMode ? [{ debugName: "currentPage" }] : /* istanbul ignore next */ []));
|
|
7206
|
-
|
|
7236
|
+
/**
|
|
7237
|
+
* Effective page size. Seeded from the `pageSize` input (resetting if it
|
|
7238
|
+
* changes) and overridable by the user via the page-size dropdown.
|
|
7239
|
+
*/
|
|
7240
|
+
internalPageSize = linkedSignal(() => this.pageSize(), ...(ngDevMode ? [{ debugName: "internalPageSize" }] : /* istanbul ignore next */ []));
|
|
7207
7241
|
selectedRows = signal(new Set(), ...(ngDevMode ? [{ debugName: "selectedRows" }] : /* istanbul ignore next */ []));
|
|
7208
7242
|
columnFilters = signal({}, ...(ngDevMode ? [{ debugName: "columnFilters" }] : /* istanbul ignore next */ []));
|
|
7209
7243
|
editingCell = signal(null, ...(ngDevMode ? [{ debugName: "editingCell" }] : /* istanbul ignore next */ []));
|
|
7210
7244
|
editValue = signal('', ...(ngDevMode ? [{ debugName: "editValue" }] : /* istanbul ignore next */ []));
|
|
7245
|
+
/** User expand/collapse overrides keyed by row id (uncontrolled mode). */
|
|
7246
|
+
expandOverrides = signal(new Map(), ...(ngDevMode ? [{ debugName: "expandOverrides" }] : /* istanbul ignore next */ []));
|
|
7211
7247
|
/**
|
|
7212
7248
|
* Filtered data (applies column filters)
|
|
7213
7249
|
*/
|
|
@@ -7223,15 +7259,9 @@ class TableComponent {
|
|
|
7223
7259
|
}
|
|
7224
7260
|
return items;
|
|
7225
7261
|
}, ...(ngDevMode ? [{ debugName: "filteredData" }] : /* istanbul ignore next */ []));
|
|
7226
|
-
/**
|
|
7227
|
-
|
|
7228
|
-
|
|
7229
|
-
sortedData = computed(() => {
|
|
7230
|
-
const items = [...this.filteredData()];
|
|
7231
|
-
const sortState = this.currentSort();
|
|
7232
|
-
if (!sortState)
|
|
7233
|
-
return items;
|
|
7234
|
-
return items.sort((a, b) => {
|
|
7262
|
+
/** Comparator for the active sort, shared by flat sorting and tree sibling sorting. */
|
|
7263
|
+
rowComparator(sortState) {
|
|
7264
|
+
return (a, b) => {
|
|
7235
7265
|
const aVal = a[sortState.column];
|
|
7236
7266
|
const bVal = b[sortState.column];
|
|
7237
7267
|
let cmp = 0;
|
|
@@ -7246,10 +7276,20 @@ class TableComponent {
|
|
|
7246
7276
|
else
|
|
7247
7277
|
cmp = String(aVal).localeCompare(String(bVal));
|
|
7248
7278
|
return sortState.direction === 'asc' ? cmp : -cmp;
|
|
7249
|
-
}
|
|
7279
|
+
};
|
|
7280
|
+
}
|
|
7281
|
+
/**
|
|
7282
|
+
* Sorted data
|
|
7283
|
+
*/
|
|
7284
|
+
sortedData = computed(() => {
|
|
7285
|
+
const items = [...this.filteredData()];
|
|
7286
|
+
const sortState = this.currentSort();
|
|
7287
|
+
if (!sortState)
|
|
7288
|
+
return items;
|
|
7289
|
+
return items.sort(this.rowComparator(sortState));
|
|
7250
7290
|
}, ...(ngDevMode ? [{ debugName: "sortedData" }] : /* istanbul ignore next */ []));
|
|
7251
7291
|
/**
|
|
7252
|
-
* Paginated data (or all if pagination disabled)
|
|
7292
|
+
* Paginated data (or all if pagination disabled). Flat mode only.
|
|
7253
7293
|
*/
|
|
7254
7294
|
displayData = computed(() => {
|
|
7255
7295
|
const items = this.sortedData();
|
|
@@ -7259,21 +7299,178 @@ class TableComponent {
|
|
|
7259
7299
|
const start = this.currentPage() * ps;
|
|
7260
7300
|
return items.slice(start, start + ps);
|
|
7261
7301
|
}, ...(ngDevMode ? [{ debugName: "displayData" }] : /* istanbul ignore next */ []));
|
|
7302
|
+
// -- Tree / grouped rows -----------------------------------------------------
|
|
7303
|
+
/** Whether hierarchical tree mode is active. */
|
|
7304
|
+
treeMode = computed(() => !!this.idKey() && !!this.parentKey(), ...(ngDevMode ? [{ debugName: "treeMode" }] : /* istanbul ignore next */ []));
|
|
7305
|
+
/** Column the chevron + indentation attach to (defaults to the first column). */
|
|
7306
|
+
effectiveTreeColumn = computed(() => this.treeColumn() || this.columns()[0]?.key, ...(ngDevMode ? [{ debugName: "effectiveTreeColumn" }] : /* istanbul ignore next */ []));
|
|
7307
|
+
/** Stable map of row object → its index in `data()` (row identity for tree mode). */
|
|
7308
|
+
dataIndexMap = computed(() => {
|
|
7309
|
+
const map = new Map();
|
|
7310
|
+
this.data().forEach((row, i) => map.set(row, i));
|
|
7311
|
+
return map;
|
|
7312
|
+
}, ...(ngDevMode ? [{ debugName: "dataIndexMap" }] : /* istanbul ignore next */ []));
|
|
7313
|
+
/** Parent → ordered children index built from `idKey`/`parentKey`. */
|
|
7314
|
+
treeBuild = computed(() => {
|
|
7315
|
+
const idKey = this.idKey();
|
|
7316
|
+
const parentKey = this.parentKey();
|
|
7317
|
+
const byId = new Map();
|
|
7318
|
+
const childrenOf = new Map();
|
|
7319
|
+
const roots = [];
|
|
7320
|
+
if (!idKey || !parentKey)
|
|
7321
|
+
return { byId, childrenOf, roots };
|
|
7322
|
+
const rows = this.data();
|
|
7323
|
+
for (const row of rows) {
|
|
7324
|
+
const id = String(row[idKey] ?? '');
|
|
7325
|
+
if (id)
|
|
7326
|
+
byId.set(id, row);
|
|
7327
|
+
}
|
|
7328
|
+
for (const row of rows) {
|
|
7329
|
+
const parentRaw = row[parentKey];
|
|
7330
|
+
const parentId = parentRaw == null ? '' : String(parentRaw);
|
|
7331
|
+
if (parentId && byId.has(parentId)) {
|
|
7332
|
+
const siblings = childrenOf.get(parentId) ?? [];
|
|
7333
|
+
siblings.push(row);
|
|
7334
|
+
childrenOf.set(parentId, siblings);
|
|
7335
|
+
}
|
|
7336
|
+
else {
|
|
7337
|
+
// No parent, empty parent, or orphaned (unknown parent) ⇒ root.
|
|
7338
|
+
roots.push(row);
|
|
7339
|
+
}
|
|
7340
|
+
}
|
|
7341
|
+
return { byId, childrenOf, roots };
|
|
7342
|
+
}, ...(ngDevMode ? [{ debugName: "treeBuild" }] : /* istanbul ignore next */ []));
|
|
7343
|
+
/**
|
|
7344
|
+
* Tree restricted to rows that match the active filters together with their
|
|
7345
|
+
* ancestor chain (so the path to a match stays visible).
|
|
7346
|
+
*/
|
|
7347
|
+
treeFiltered = computed(() => {
|
|
7348
|
+
const { byId, childrenOf, roots } = this.treeBuild();
|
|
7349
|
+
const parentKey = this.parentKey();
|
|
7350
|
+
const filters = this.columnFilters();
|
|
7351
|
+
const active = this.filterable() && parentKey && Object.values(filters).some((v) => v.trim());
|
|
7352
|
+
if (!active)
|
|
7353
|
+
return { childrenOf, roots };
|
|
7354
|
+
const matches = (row) => Object.entries(filters).every(([key, value]) => !value.trim() ||
|
|
7355
|
+
String(row[key] ?? '').toLowerCase().includes(value.toLowerCase()));
|
|
7356
|
+
// Visible = every matching row plus all of its ancestors.
|
|
7357
|
+
const visible = new Set();
|
|
7358
|
+
for (const row of this.data()) {
|
|
7359
|
+
if (!matches(row))
|
|
7360
|
+
continue;
|
|
7361
|
+
let current = row;
|
|
7362
|
+
while (current && !visible.has(current)) {
|
|
7363
|
+
visible.add(current);
|
|
7364
|
+
const parentRaw = current[parentKey];
|
|
7365
|
+
const parentId = parentRaw == null ? '' : String(parentRaw);
|
|
7366
|
+
current = parentId ? byId.get(parentId) : undefined;
|
|
7367
|
+
}
|
|
7368
|
+
}
|
|
7369
|
+
const visibleChildrenOf = new Map();
|
|
7370
|
+
const visibleRoots = [];
|
|
7371
|
+
for (const row of this.data()) {
|
|
7372
|
+
if (!visible.has(row))
|
|
7373
|
+
continue;
|
|
7374
|
+
const parentRaw = row[parentKey];
|
|
7375
|
+
const parentId = parentRaw == null ? '' : String(parentRaw);
|
|
7376
|
+
const parent = parentId ? byId.get(parentId) : undefined;
|
|
7377
|
+
if (parent && visible.has(parent)) {
|
|
7378
|
+
const siblings = visibleChildrenOf.get(parentId) ?? [];
|
|
7379
|
+
siblings.push(row);
|
|
7380
|
+
visibleChildrenOf.set(parentId, siblings);
|
|
7381
|
+
}
|
|
7382
|
+
else {
|
|
7383
|
+
visibleRoots.push(row);
|
|
7384
|
+
}
|
|
7385
|
+
}
|
|
7386
|
+
return { childrenOf: visibleChildrenOf, roots: visibleRoots };
|
|
7387
|
+
}, ...(ngDevMode ? [{ debugName: "treeFiltered" }] : /* istanbul ignore next */ []));
|
|
7388
|
+
/** Tree with each sibling group sorted by the active sort (structure kept intact). */
|
|
7389
|
+
treeSorted = computed(() => {
|
|
7390
|
+
const { childrenOf, roots } = this.treeFiltered();
|
|
7391
|
+
const sortState = this.currentSort();
|
|
7392
|
+
if (!sortState)
|
|
7393
|
+
return { childrenOf, roots };
|
|
7394
|
+
const cmp = this.rowComparator(sortState);
|
|
7395
|
+
const sortedChildrenOf = new Map();
|
|
7396
|
+
for (const [parentId, siblings] of childrenOf) {
|
|
7397
|
+
sortedChildrenOf.set(parentId, [...siblings].sort(cmp));
|
|
7398
|
+
}
|
|
7399
|
+
return { childrenOf: sortedChildrenOf, roots: [...roots].sort(cmp) };
|
|
7400
|
+
}, ...(ngDevMode ? [{ debugName: "treeSorted" }] : /* istanbul ignore next */ []));
|
|
7401
|
+
/** Root rows after filter/sort — the unit of pagination in tree mode. */
|
|
7402
|
+
treeRoots = computed(() => this.treeSorted().roots, ...(ngDevMode ? [{ debugName: "treeRoots" }] : /* istanbul ignore next */ []));
|
|
7403
|
+
/**
|
|
7404
|
+
* Render-ready rows. In flat mode this wraps the existing paginated data; in
|
|
7405
|
+
* tree mode it paginates roots and flattens each visible (expanded) subtree.
|
|
7406
|
+
*/
|
|
7407
|
+
displayRows = computed(() => {
|
|
7408
|
+
if (!this.treeMode()) {
|
|
7409
|
+
return this.displayData().map((row, i) => ({
|
|
7410
|
+
row,
|
|
7411
|
+
absIndex: this.getAbsoluteIndex(i),
|
|
7412
|
+
id: null,
|
|
7413
|
+
depth: 0,
|
|
7414
|
+
level: 0,
|
|
7415
|
+
hasChildren: false,
|
|
7416
|
+
expanded: false,
|
|
7417
|
+
posInSet: 0,
|
|
7418
|
+
setSize: 0,
|
|
7419
|
+
}));
|
|
7420
|
+
}
|
|
7421
|
+
const idKey = this.idKey();
|
|
7422
|
+
const { childrenOf } = this.treeSorted();
|
|
7423
|
+
let roots = this.treeRoots();
|
|
7424
|
+
if (this.paginate()) {
|
|
7425
|
+
const ps = this.internalPageSize();
|
|
7426
|
+
const start = this.currentPage() * ps;
|
|
7427
|
+
roots = roots.slice(start, start + ps);
|
|
7428
|
+
}
|
|
7429
|
+
const dataIndex = this.dataIndexMap();
|
|
7430
|
+
const out = [];
|
|
7431
|
+
const walk = (group, depth) => {
|
|
7432
|
+
group.forEach((row, idx) => {
|
|
7433
|
+
const id = String(row[idKey] ?? '');
|
|
7434
|
+
const children = childrenOf.get(id) ?? [];
|
|
7435
|
+
const hasChildren = children.length > 0;
|
|
7436
|
+
const expanded = hasChildren && this.isExpanded(id);
|
|
7437
|
+
out.push({
|
|
7438
|
+
row,
|
|
7439
|
+
absIndex: dataIndex.get(row) ?? -1,
|
|
7440
|
+
id,
|
|
7441
|
+
depth,
|
|
7442
|
+
level: depth + 1,
|
|
7443
|
+
hasChildren,
|
|
7444
|
+
expanded,
|
|
7445
|
+
posInSet: idx + 1,
|
|
7446
|
+
setSize: group.length,
|
|
7447
|
+
});
|
|
7448
|
+
if (expanded)
|
|
7449
|
+
walk(children, depth + 1);
|
|
7450
|
+
});
|
|
7451
|
+
};
|
|
7452
|
+
walk(roots, 0);
|
|
7453
|
+
return out;
|
|
7454
|
+
}, ...(ngDevMode ? [{ debugName: "displayRows" }] : /* istanbul ignore next */ []));
|
|
7262
7455
|
/** Total pages */
|
|
7263
7456
|
totalPages = computed(() => {
|
|
7264
7457
|
if (!this.paginate())
|
|
7265
7458
|
return 1;
|
|
7266
|
-
|
|
7459
|
+
const total = this.treeMode() ? this.treeRoots().length : this.filteredData().length;
|
|
7460
|
+
return Math.max(1, Math.ceil(total / this.internalPageSize()));
|
|
7267
7461
|
}, ...(ngDevMode ? [{ debugName: "totalPages" }] : /* istanbul ignore next */ []));
|
|
7268
|
-
/**
|
|
7269
|
-
|
|
7462
|
+
/**
|
|
7463
|
+
* Pagination row count. Tree mode counts root rows (the paginated unit); flat
|
|
7464
|
+
* mode counts filtered rows.
|
|
7465
|
+
*/
|
|
7466
|
+
totalRows = computed(() => this.treeMode() ? this.treeRoots().length : this.filteredData().length, ...(ngDevMode ? [{ debugName: "totalRows" }] : /* istanbul ignore next */ []));
|
|
7270
7467
|
/** Whether all visible rows are selected */
|
|
7271
7468
|
allSelected = computed(() => {
|
|
7272
|
-
const
|
|
7273
|
-
if (
|
|
7469
|
+
const rows = this.displayRows();
|
|
7470
|
+
if (rows.length === 0)
|
|
7274
7471
|
return false;
|
|
7275
7472
|
const selected = this.selectedRows();
|
|
7276
|
-
return
|
|
7473
|
+
return rows.every((r) => selected.has(r.absIndex));
|
|
7277
7474
|
}, ...(ngDevMode ? [{ debugName: "allSelected" }] : /* istanbul ignore next */ []));
|
|
7278
7475
|
pageSizeSelectOptions = computed(() => this.pageSizeOptions().map((opt) => ({
|
|
7279
7476
|
value: opt,
|
|
@@ -7338,13 +7535,13 @@ class TableComponent {
|
|
|
7338
7535
|
getCellValue(row, columnKey) {
|
|
7339
7536
|
return row[columnKey];
|
|
7340
7537
|
}
|
|
7341
|
-
getFormattedCellValue(row, column,
|
|
7538
|
+
getFormattedCellValue(row, column, rowIndex) {
|
|
7342
7539
|
const value = this.getCellValue(row, column.key);
|
|
7343
7540
|
if (!column.formatter)
|
|
7344
7541
|
return value;
|
|
7345
|
-
return column.formatter(value, row, column,
|
|
7542
|
+
return column.formatter(value, row, column, rowIndex);
|
|
7346
7543
|
}
|
|
7347
|
-
getCellClasses(row, column,
|
|
7544
|
+
getCellClasses(row, column, rowIndex) {
|
|
7348
7545
|
const classes = [];
|
|
7349
7546
|
if (column.cssClass)
|
|
7350
7547
|
classes.push(column.cssClass);
|
|
@@ -7352,20 +7549,33 @@ class TableComponent {
|
|
|
7352
7549
|
classes.push(column.cellClass);
|
|
7353
7550
|
}
|
|
7354
7551
|
else if (typeof column.cellClass === 'function') {
|
|
7355
|
-
const resolved = column.cellClass(this.getCellValue(row, column.key), row, column,
|
|
7552
|
+
const resolved = column.cellClass(this.getCellValue(row, column.key), row, column, rowIndex);
|
|
7356
7553
|
if (resolved)
|
|
7357
7554
|
classes.push(resolved);
|
|
7358
7555
|
}
|
|
7359
7556
|
return classes.join(' ').trim();
|
|
7360
7557
|
}
|
|
7361
|
-
getCellStyles(row, column,
|
|
7558
|
+
getCellStyles(row, column, rowIndex) {
|
|
7362
7559
|
if (!column.cellStyle)
|
|
7363
7560
|
return null;
|
|
7364
7561
|
if (typeof column.cellStyle === 'function') {
|
|
7365
|
-
return column.cellStyle(this.getCellValue(row, column.key), row, column,
|
|
7562
|
+
return column.cellStyle(this.getCellValue(row, column.key), row, column, rowIndex);
|
|
7366
7563
|
}
|
|
7367
7564
|
return column.cellStyle;
|
|
7368
7565
|
}
|
|
7566
|
+
/** Whether the given column is the disclosure/indent column in tree mode. */
|
|
7567
|
+
isTreeColumn(columnKey) {
|
|
7568
|
+
return this.treeMode() && columnKey === this.effectiveTreeColumn();
|
|
7569
|
+
}
|
|
7570
|
+
/** Indent levels to render before a row's chevron (one guide per ancestor depth). */
|
|
7571
|
+
indentLevels(depth) {
|
|
7572
|
+
return Array.from({ length: depth }, (_, i) => i);
|
|
7573
|
+
}
|
|
7574
|
+
/** Accessible name for a row's disclosure button (the tree column's value). */
|
|
7575
|
+
treeCellLabel(row) {
|
|
7576
|
+
const col = this.effectiveTreeColumn();
|
|
7577
|
+
return col ? String(row[col] ?? '') : '';
|
|
7578
|
+
}
|
|
7369
7579
|
getCellTemplate(columnKey) {
|
|
7370
7580
|
return this.cellTemplates?.find((template) => template.columnKey() === columnKey);
|
|
7371
7581
|
}
|
|
@@ -7378,21 +7588,62 @@ class TableComponent {
|
|
|
7378
7588
|
// -- Row Actions --
|
|
7379
7589
|
/** Whether the trailing actions column should be rendered */
|
|
7380
7590
|
hasActions = computed(() => this.actions().length > 0, ...(ngDevMode ? [{ debugName: "hasActions" }] : /* istanbul ignore next */ []));
|
|
7381
|
-
isActionHidden(action, row,
|
|
7382
|
-
return action.hidden ? action.hidden(row,
|
|
7591
|
+
isActionHidden(action, row, rowIndex) {
|
|
7592
|
+
return action.hidden ? action.hidden(row, rowIndex) : false;
|
|
7383
7593
|
}
|
|
7384
|
-
isActionDisabled(action, row,
|
|
7385
|
-
return action.disabled ? action.disabled(row,
|
|
7594
|
+
isActionDisabled(action, row, rowIndex) {
|
|
7595
|
+
return action.disabled ? action.disabled(row, rowIndex) : false;
|
|
7386
7596
|
}
|
|
7387
7597
|
/**
|
|
7388
7598
|
* Handles an action button click. The DOM click is stopped from propagating
|
|
7389
7599
|
* (see template `$event.stopPropagation()`), so the row's `rowClick` never fires.
|
|
7390
7600
|
*/
|
|
7391
|
-
onActionClick(action, row,
|
|
7601
|
+
onActionClick(action, row, rowIndex) {
|
|
7392
7602
|
this.actionClick.emit({
|
|
7393
7603
|
action: action.key,
|
|
7394
7604
|
row,
|
|
7395
|
-
rowIndex
|
|
7605
|
+
rowIndex,
|
|
7606
|
+
});
|
|
7607
|
+
}
|
|
7608
|
+
// -- Tree expand / collapse --------------------------------------------------
|
|
7609
|
+
/** Whether the parent row with the given id is currently expanded. */
|
|
7610
|
+
isExpanded(id) {
|
|
7611
|
+
const controlled = this.expandedIds();
|
|
7612
|
+
if (controlled !== undefined)
|
|
7613
|
+
return controlled.includes(id);
|
|
7614
|
+
const override = this.expandOverrides().get(id);
|
|
7615
|
+
if (override !== undefined)
|
|
7616
|
+
return override;
|
|
7617
|
+
return this.defaultExpanded();
|
|
7618
|
+
}
|
|
7619
|
+
/** Chevron click: toggle expand state without triggering the row click. */
|
|
7620
|
+
onChevronClick(displayRow, event) {
|
|
7621
|
+
event.stopPropagation();
|
|
7622
|
+
if (displayRow.id)
|
|
7623
|
+
this.toggleRow(displayRow.id, displayRow.row);
|
|
7624
|
+
}
|
|
7625
|
+
toggleRow(id, row) {
|
|
7626
|
+
const expanded = !this.isExpanded(id);
|
|
7627
|
+
this.expandOverrides.update((map) => {
|
|
7628
|
+
const next = new Map(map);
|
|
7629
|
+
next.set(id, expanded);
|
|
7630
|
+
return next;
|
|
7631
|
+
});
|
|
7632
|
+
this.rowToggle.emit({ id, expanded, row });
|
|
7633
|
+
this.expandedIdsChange.emit(this.nextExpandedIds(id, expanded));
|
|
7634
|
+
}
|
|
7635
|
+
/** The full list of expanded parent ids after applying a single toggle. */
|
|
7636
|
+
nextExpandedIds(changedId, changedExpanded) {
|
|
7637
|
+
const controlled = this.expandedIds();
|
|
7638
|
+
const overrides = this.expandOverrides();
|
|
7639
|
+
const parentIds = Array.from(this.treeBuild().childrenOf.keys());
|
|
7640
|
+
return parentIds.filter((pid) => {
|
|
7641
|
+
if (pid === changedId)
|
|
7642
|
+
return changedExpanded;
|
|
7643
|
+
if (controlled !== undefined)
|
|
7644
|
+
return controlled.includes(pid);
|
|
7645
|
+
const override = overrides.get(pid);
|
|
7646
|
+
return override !== undefined ? override : this.defaultExpanded();
|
|
7396
7647
|
});
|
|
7397
7648
|
}
|
|
7398
7649
|
// -- Pagination --
|
|
@@ -7426,30 +7677,28 @@ class TableComponent {
|
|
|
7426
7677
|
// -- Selection --
|
|
7427
7678
|
toggleSelectAll() {
|
|
7428
7679
|
const selected = new Set(this.selectedRows());
|
|
7429
|
-
const
|
|
7680
|
+
const rows = this.displayRows();
|
|
7430
7681
|
const allSelected = this.allSelected();
|
|
7431
|
-
|
|
7432
|
-
const absIdx = this.getAbsoluteIndex(i);
|
|
7682
|
+
rows.forEach((r) => {
|
|
7433
7683
|
if (allSelected)
|
|
7434
|
-
selected.delete(
|
|
7684
|
+
selected.delete(r.absIndex);
|
|
7435
7685
|
else
|
|
7436
|
-
selected.add(
|
|
7686
|
+
selected.add(r.absIndex);
|
|
7437
7687
|
});
|
|
7438
7688
|
this.selectedRows.set(selected);
|
|
7439
7689
|
this.emitSelectionChange();
|
|
7440
7690
|
}
|
|
7441
|
-
toggleRowSelect(
|
|
7442
|
-
const absIdx = this.getAbsoluteIndex(relativeIndex);
|
|
7691
|
+
toggleRowSelect(absIndex) {
|
|
7443
7692
|
const selected = new Set(this.selectedRows());
|
|
7444
|
-
if (selected.has(
|
|
7445
|
-
selected.delete(
|
|
7693
|
+
if (selected.has(absIndex))
|
|
7694
|
+
selected.delete(absIndex);
|
|
7446
7695
|
else
|
|
7447
|
-
selected.add(
|
|
7696
|
+
selected.add(absIndex);
|
|
7448
7697
|
this.selectedRows.set(selected);
|
|
7449
7698
|
this.emitSelectionChange();
|
|
7450
7699
|
}
|
|
7451
|
-
isRowSelected(
|
|
7452
|
-
return this.selectedRows().has(
|
|
7700
|
+
isRowSelected(absIndex) {
|
|
7701
|
+
return this.selectedRows().has(absIndex);
|
|
7453
7702
|
}
|
|
7454
7703
|
getAbsoluteIndex(relativeIndex) {
|
|
7455
7704
|
if (!this.paginate())
|
|
@@ -7471,37 +7720,36 @@ class TableComponent {
|
|
|
7471
7720
|
return this.columnFilters()[columnKey] || '';
|
|
7472
7721
|
}
|
|
7473
7722
|
// -- Inline Editing --
|
|
7474
|
-
startEdit(
|
|
7723
|
+
startEdit(absIndex, column, currentValue) {
|
|
7475
7724
|
if (!this.editable())
|
|
7476
7725
|
return;
|
|
7477
7726
|
const col = this.columns().find(c => c.key === column);
|
|
7478
7727
|
if (col && col.editable === false)
|
|
7479
7728
|
return;
|
|
7480
|
-
this.editingCell.set({ rowIndex, column });
|
|
7729
|
+
this.editingCell.set({ rowIndex: absIndex, column });
|
|
7481
7730
|
this.editValue.set(String(currentValue ?? ''));
|
|
7482
7731
|
}
|
|
7483
|
-
isEditing(
|
|
7732
|
+
isEditing(absIndex, column) {
|
|
7484
7733
|
const cell = this.editingCell();
|
|
7485
|
-
return cell !== null && cell.rowIndex ===
|
|
7734
|
+
return cell !== null && cell.rowIndex === absIndex && cell.column === column;
|
|
7486
7735
|
}
|
|
7487
|
-
commitEdit(
|
|
7488
|
-
const
|
|
7489
|
-
const row = this.data()[absIdx];
|
|
7736
|
+
commitEdit(absIndex, column) {
|
|
7737
|
+
const row = this.data()[absIndex];
|
|
7490
7738
|
if (!row)
|
|
7491
7739
|
return;
|
|
7492
7740
|
const oldValue = row[column];
|
|
7493
7741
|
const newValue = this.editValue();
|
|
7494
7742
|
this.editingCell.set(null);
|
|
7495
7743
|
if (String(oldValue ?? '') !== newValue) {
|
|
7496
|
-
this.cellEdit.emit({ row, column, oldValue, newValue, rowIndex:
|
|
7744
|
+
this.cellEdit.emit({ row, column, oldValue, newValue, rowIndex: absIndex });
|
|
7497
7745
|
}
|
|
7498
7746
|
}
|
|
7499
7747
|
cancelEdit() {
|
|
7500
7748
|
this.editingCell.set(null);
|
|
7501
7749
|
}
|
|
7502
|
-
onEditKeydown(event,
|
|
7750
|
+
onEditKeydown(event, absIndex, column) {
|
|
7503
7751
|
if (event.key === 'Enter') {
|
|
7504
|
-
this.commitEdit(
|
|
7752
|
+
this.commitEdit(absIndex, column);
|
|
7505
7753
|
}
|
|
7506
7754
|
else if (event.key === 'Escape') {
|
|
7507
7755
|
this.cancelEdit();
|
|
@@ -7511,15 +7759,15 @@ class TableComponent {
|
|
|
7511
7759
|
return event.target.value;
|
|
7512
7760
|
}
|
|
7513
7761
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.10", ngImport: i0, type: TableComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
7514
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.10", type: TableComponent, isStandalone: true, selector: "lc-table", inputs: { columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: false, transformFunction: null }, data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, hoverable: { classPropertyName: "hoverable", publicName: "hoverable", isSignal: true, isRequired: false, transformFunction: null }, responsive: { classPropertyName: "responsive", publicName: "responsive", isSignal: true, isRequired: false, transformFunction: null }, emptyText: { classPropertyName: "emptyText", publicName: "emptyText", isSignal: true, isRequired: false, transformFunction: null }, paginate: { classPropertyName: "paginate", publicName: "paginate", isSignal: true, isRequired: false, transformFunction: null }, pageSize: { classPropertyName: "pageSize", publicName: "pageSize", isSignal: true, isRequired: false, transformFunction: null }, pageSizeOptions: { classPropertyName: "pageSizeOptions", publicName: "pageSizeOptions", isSignal: true, isRequired: false, transformFunction: null }, selectable: { classPropertyName: "selectable", publicName: "selectable", isSignal: true, isRequired: false, transformFunction: null }, filterable: { classPropertyName: "filterable", publicName: "filterable", isSignal: true, isRequired: false, transformFunction: null }, editable: { classPropertyName: "editable", publicName: "editable", isSignal: true, isRequired: false, transformFunction: null }, actions: { classPropertyName: "actions", publicName: "actions", isSignal: true, isRequired: false, transformFunction: null }, actionsLabel: { classPropertyName: "actionsLabel", publicName: "actionsLabel", isSignal: true, isRequired: false, transformFunction: null }, actionsWidth: { classPropertyName: "actionsWidth", publicName: "actionsWidth", isSignal: true, isRequired: false, transformFunction: null }, actionsAlign: { classPropertyName: "actionsAlign", publicName: "actionsAlign", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { sort: "sort", rowClick: "rowClick", cellEdit: "cellEdit", selectionChange: "selectionChange", actionClick: "actionClick" }, queries: [{ propertyName: "cellTemplates", predicate: TableCellDirective }], ngImport: i0, template: "<div [class]=\"wrapperClasses()\">\n <table [class]=\"tableClasses()\" role=\"table\">\n <thead>\n <!-- Filter row -->\n @if (filterable()) {\n <tr class=\"lc-table__filter-row\">\n @if (selectable()) {\n <th class=\"lc-table__select-cell\"></th>\n }\n @for (column of columns(); track column.key) {\n <th>\n @if (column.filterable !== false) {\n <lc-input\n class=\"lc-table__filter-input\"\n size=\"xs\"\n [placeholder]=\"'Filter ' + column.label\"\n [ariaLabel]=\"'Filter by ' + column.label\"\n [ngModel]=\"getFilterValue(column.key)\"\n (ngModelChange)=\"onFilterChange(column.key, $event)\"\n />\n }\n </th>\n }\n @if (hasActions()) {\n <th class=\"lc-table__actions-cell\"></th>\n }\n </tr>\n }\n <!-- Header row -->\n <tr>\n @if (selectable()) {\n <th class=\"lc-table__select-cell\" scope=\"col\">\n <input\n type=\"checkbox\"\n class=\"lc-table__checkbox\"\n [checked]=\"allSelected()\"\n (change)=\"toggleSelectAll()\"\n aria-label=\"Select all rows\"\n />\n </th>\n }\n @for (column of columns(); track column.key) {\n <th\n scope=\"col\"\n [class]=\"getHeaderClasses(column) + (column.cssClass ? ' ' + column.cssClass : '')\"\n [attr.aria-sort]=\"getAriaSort(column.key)\"\n [style.width]=\"column.width\"\n [title]=\"column.tooltip || ''\"\n (click)=\"handleSort(column.key)\">\n {{ column.label }}\n @if (column.sortable && getSortState(column.key)) {\n <span class=\"sort-indicator\" [attr.aria-label]=\"getSortState(column.key) === 'asc' ? 'sorted ascending' : 'sorted descending'\">\n @if (getSortState(column.key) === 'asc') {\n \u2191\n } @else {\n \u2193\n }\n </span>\n }\n </th>\n }\n @if (hasActions()) {\n <th\n scope=\"col\"\n class=\"lc-table__actions-cell\"\n [class]=\"'lc-table__actions-cell--' + actionsAlign()\"\n [style.width]=\"actionsWidth()\"\n >\n {{ actionsLabel() }}\n </th>\n }\n </tr>\n </thead>\n <tbody>\n @if (displayData().length === 0) {\n <tr>\n <td [attr.colspan]=\"columns().length + (selectable() ? 1 : 0) + (hasActions() ? 1 : 0)\" class=\"lc-table__empty\">\n {{ emptyText() }}\n </td>\n </tr>\n } @else {\n @for (row of displayData(); track $index; let i = $index) {\n <tr\n [class.lc-table__row--selected]=\"selectable() && isRowSelected(i)\"\n (click)=\"onRowClick(row)\"\n >\n @if (selectable()) {\n <td class=\"lc-table__select-cell\">\n <input\n type=\"checkbox\"\n class=\"lc-table__checkbox\"\n [checked]=\"isRowSelected($index)\"\n (change)=\"toggleRowSelect($index)\"\n (click)=\"$event.stopPropagation()\"\n [attr.aria-label]=\"'Select row ' + ($index + 1)\"\n />\n </td>\n }\n @for (column of columns(); track column.key) {\n <td\n [class]=\"getCellClasses(row, column, i)\"\n [ngStyle]=\"getCellStyles(row, column, i)\"\n (dblclick)=\"editable() ? startEdit($index, column.key, getCellValue(row, column.key)) : null\"\n >\n @if (isEditing($index, column.key)) {\n <input\n type=\"text\"\n class=\"lc-table__edit-input\"\n [value]=\"editValue()\"\n (input)=\"editValue.set(getInputValue($event))\"\n (blur)=\"commitEdit($index, column.key)\"\n (keydown)=\"onEditKeydown($event, $index, column.key)\"\n autofocus\n />\n } @else if (hasCustomTemplate(column.key)) {\n <ng-container *ngTemplateOutlet=\"getCellTemplate(column.key)!.template; context: { $implicit: row }\"></ng-container>\n } @else {\n {{ getFormattedCellValue(row, column, i) }}\n }\n </td>\n }\n @if (hasActions()) {\n <td\n class=\"lc-table__actions-cell\"\n [class]=\"'lc-table__actions-cell--' + actionsAlign()\"\n (click)=\"$event.stopPropagation()\"\n >\n <div class=\"lc-table__actions\">\n @for (action of actions(); track action.key) {\n @if (!isActionHidden(action, row, i)) {\n <lc-button\n [variant]=\"action.variant ?? 'ghost'\"\n size=\"xs\"\n [iconOnly]=\"!action.label\"\n [disabled]=\"isActionDisabled(action, row, i)\"\n [ariaLabel]=\"action.tooltip ?? action.label ?? action.key\"\n (clicked)=\"onActionClick(action, row, i)\"\n >\n @if (action.icon) {\n <lc-icon [name]=\"action.icon\" size=\"sm\" [decorative]=\"true\" />\n }\n @if (action.label) {\n {{ action.label }}\n }\n </lc-button>\n }\n }\n </div>\n </td>\n }\n </tr>\n }\n }\n </tbody>\n </table>\n</div>\n\n<!-- Pagination -->\n@if (paginate()) {\n <div class=\"lc-table-pagination\">\n <div class=\"lc-table-pagination__info\">\n {{ paginationStart }}\u2013{{ paginationEnd }} of {{ totalRows() }}\n </div>\n <div class=\"lc-table-pagination__controls\">\n <lc-select\n class=\"lc-table-pagination__size\"\n [size]=\"size() === 'sm' ? 'sm' : size() === 'lg' ? 'lg' : 'md'\"\n [options]=\"pageSizeSelectOptions()\"\n [ngModel]=\"internalPageSize()\"\n [ariaLabel]=\"'Rows per page'\"\n (ngModelChange)=\"onPageSizeModelChange($event)\"\n />\n <button\n type=\"button\"\n class=\"lc-table-pagination__btn\"\n [disabled]=\"currentPage() === 0\"\n (click)=\"goToPage(currentPage() - 1)\"\n aria-label=\"Previous page\"\n >\u2039</button>\n <span class=\"lc-table-pagination__page\">\n {{ currentPage() + 1 }} / {{ totalPages() }}\n </span>\n <button\n type=\"button\"\n class=\"lc-table-pagination__btn\"\n [disabled]=\"currentPage() >= totalPages() - 1\"\n (click)=\"goToPage(currentPage() + 1)\"\n aria-label=\"Next page\"\n >\u203A</button>\n </div>\n </div>\n}\n", styles: [".lc-table-wrapper{width:100%}.lc-table-wrapper--responsive{overflow-x:auto;-webkit-overflow-scrolling:touch}@media(max-width:768px){.lc-table-wrapper--responsive::-webkit-scrollbar{height:8px}.lc-table-wrapper--responsive::-webkit-scrollbar-thumb{background-color:var(--color-border);border-radius:var(--border-radius-sm)}}.lc-table{width:100%;border-collapse:collapse;border-spacing:0;background-color:var(--color-surface);color:var(--color-text-primary);font-family:var(--typography-font-family)}.lc-table thead{background-color:var(--color-surface-2);border-bottom:2px solid var(--color-border-strong)}.lc-table thead tr th{padding:var(--lc-density-padding-sm, var(--spacing-3)) var(--lc-density-padding-md, var(--spacing-4));text-align:left;font-weight:var(--typography-font-weight-semibold);font-size:var(--typography-font-size-sm);text-transform:uppercase;letter-spacing:.04em;color:var(--color-text-secondary);white-space:nowrap;-webkit-user-select:none;user-select:none}.lc-table thead tr th.sortable{cursor:pointer;position:relative;padding-right:var(--spacing-8);transition:background-color .2s ease}.lc-table thead tr th.sortable:hover{background-color:var(--color-surface-hover);color:var(--color-text-primary)}.lc-table thead tr th.sortable .sort-indicator{position:absolute;right:var(--spacing-3);top:50%;transform:translateY(-50%);font-size:var(--typography-font-size-xs);color:var(--color-primary)}.lc-table thead tr th.sorted-asc,.lc-table thead tr th.sorted-desc{background-color:var(--color-surface-hover);color:var(--color-text-primary)}.lc-table tbody tr{border-bottom:1px solid var(--color-divider)}.lc-table tbody tr:last-child{border-bottom:none}.lc-table tbody tr td{padding:var(--lc-density-padding-sm, var(--spacing-3)) var(--lc-density-padding-md, var(--spacing-4));font-size:var(--typography-font-size-sm);color:var(--color-text-primary)}.lc-table__empty{text-align:center;padding:var(--spacing-8) var(--spacing-4)!important;color:var(--color-text-secondary);font-style:italic}.lc-table--striped tbody tr:nth-child(2n){background-color:var(--color-surface-2)}.lc-table--bordered{border:1px solid var(--color-border)}.lc-table--bordered thead tr th,.lc-table--bordered tbody tr td{border-right:1px solid var(--color-divider)}.lc-table--bordered thead tr th:last-child,.lc-table--bordered tbody tr td:last-child{border-right:none}.lc-table--bordered tbody tr{border-bottom:1px solid var(--color-border)}.lc-table--hoverable tbody tr{transition:background-color .15s ease;cursor:pointer}.lc-table--hoverable tbody tr:hover{background-color:var(--color-surface-hover)}.lc-table--sm thead tr th,.lc-table--sm tbody tr td{padding:var(--lc-density-padding-xs, var(--spacing-2)) var(--lc-density-padding-sm, var(--spacing-3));font-size:var(--typography-font-size-xs)}.lc-table--lg thead tr th,.lc-table--lg tbody tr td{padding:var(--lc-density-padding-md, var(--spacing-4)) var(--spacing-5);font-size:var(--typography-font-size-base)}.lc-table__filter-row th{padding:var(--spacing-2) var(--spacing-4)!important;background-color:var(--color-background)!important;border-bottom:1px solid var(--color-divider)!important}.lc-table__filter-input{width:100%;display:block}.lc-table__filter-input .input-field{font-size:var(--typography-font-size-xs)}.lc-table__select-cell{width:40px;text-align:center!important;padding:var(--spacing-2)!important}.lc-table__checkbox{width:16px;height:16px;cursor:pointer;accent-color:var(--color-primary)}.lc-table__row--selected{background-color:var(--color-surface-selected)!important}.lc-table__actions-cell{white-space:nowrap}.lc-table th.lc-table__actions-cell--start,.lc-table td.lc-table__actions-cell--start{text-align:left}.lc-table th.lc-table__actions-cell--center,.lc-table td.lc-table__actions-cell--center{text-align:center}.lc-table th.lc-table__actions-cell--end,.lc-table td.lc-table__actions-cell--end{text-align:right}.lc-table__actions{display:flex;align-items:center;gap:var(--spacing-2);justify-content:flex-start}.lc-table__actions-cell--center .lc-table__actions{justify-content:center}.lc-table__actions-cell--end .lc-table__actions{justify-content:flex-end}.lc-table__edit-input{width:100%;padding:var(--spacing-1) var(--spacing-2);border:2px solid var(--color-primary);border-radius:var(--border-radius-sm);font-size:inherit;background-color:var(--color-surface-2);color:var(--color-text-primary);outline:none}.lc-table-pagination{display:flex;align-items:center;justify-content:space-between;padding:var(--spacing-3) var(--spacing-1);font-size:var(--typography-font-size-sm);color:var(--color-text-secondary)}.lc-table-pagination__info{white-space:nowrap}.lc-table-pagination__controls{display:flex;align-items:center;gap:var(--spacing-2)}.lc-table-pagination__size{display:block;min-width:110px}.lc-table-pagination__btn{appearance:none;border:1px solid var(--color-border);background-color:var(--color-surface);color:var(--color-text-primary);width:28px;height:28px;display:flex;align-items:center;justify-content:center;border-radius:var(--border-radius-sm);font-size:var(--typography-font-size-base);cursor:pointer;transition:background-color .15s ease}.lc-table-pagination__btn:hover:not(:disabled){background-color:var(--color-surface-hover)}.lc-table-pagination__btn:disabled{opacity:.4;cursor:not-allowed}.lc-table-pagination__page{white-space:nowrap;min-width:60px;text-align:center}@media(max-width:640px){.lc-table-wrapper--stack .lc-table thead{display:none}.lc-table-wrapper--stack .lc-table tbody tr{display:block;margin-bottom:var(--spacing-4);border:1px solid var(--color-border);border-radius:var(--border-radius-md)}.lc-table-wrapper--stack .lc-table tbody tr td{display:block;text-align:right;padding:var(--spacing-2) var(--spacing-4);border-bottom:1px solid var(--color-divider)}.lc-table-wrapper--stack .lc-table tbody tr td:last-child{border-bottom:none}.lc-table-wrapper--stack .lc-table tbody tr td:before{content:attr(data-label);float:left;font-weight:var(--typography-font-weight-semibold);color:var(--color-text-secondary)}}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: SelectComponent, selector: "lc-select", inputs: ["variant", "size", "disabled", "error", "required", "loading", "searchable", "multiple", "placeholder", "helperText", "errorMessage", "ariaLabel", "options"], outputs: ["selectionChange", "opened", "closed"] }, { kind: "component", type: InputComponent, selector: "lc-input", inputs: ["label", "placeholder", "type", "size", "disabled", "readonly", "required", "error", "helperText", "iconBefore", "iconAfter", "maxLength", "showCharCount", "ariaLabel"], outputs: ["valueChange", "focused", "blurred", "enterPressed"] }, { kind: "component", type: ButtonComponent, selector: "lc-button", inputs: ["variant", "size", "disabled", "loading", "iconOnly", "fullWidth", "ariaLabel", "type"], outputs: ["clicked", "focused", "blurred"] }, { kind: "component", type: IconComponent, selector: "lc-icon", inputs: ["name", "variant", "size", "color", "ariaLabel", "decorative"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
7762
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.10", type: TableComponent, isStandalone: true, selector: "lc-table", inputs: { columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: false, transformFunction: null }, data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, hoverable: { classPropertyName: "hoverable", publicName: "hoverable", isSignal: true, isRequired: false, transformFunction: null }, responsive: { classPropertyName: "responsive", publicName: "responsive", isSignal: true, isRequired: false, transformFunction: null }, emptyText: { classPropertyName: "emptyText", publicName: "emptyText", isSignal: true, isRequired: false, transformFunction: null }, paginate: { classPropertyName: "paginate", publicName: "paginate", isSignal: true, isRequired: false, transformFunction: null }, pageSize: { classPropertyName: "pageSize", publicName: "pageSize", isSignal: true, isRequired: false, transformFunction: null }, pageSizeOptions: { classPropertyName: "pageSizeOptions", publicName: "pageSizeOptions", isSignal: true, isRequired: false, transformFunction: null }, selectable: { classPropertyName: "selectable", publicName: "selectable", isSignal: true, isRequired: false, transformFunction: null }, filterable: { classPropertyName: "filterable", publicName: "filterable", isSignal: true, isRequired: false, transformFunction: null }, editable: { classPropertyName: "editable", publicName: "editable", isSignal: true, isRequired: false, transformFunction: null }, actions: { classPropertyName: "actions", publicName: "actions", isSignal: true, isRequired: false, transformFunction: null }, actionsLabel: { classPropertyName: "actionsLabel", publicName: "actionsLabel", isSignal: true, isRequired: false, transformFunction: null }, actionsWidth: { classPropertyName: "actionsWidth", publicName: "actionsWidth", isSignal: true, isRequired: false, transformFunction: null }, actionsAlign: { classPropertyName: "actionsAlign", publicName: "actionsAlign", isSignal: true, isRequired: false, transformFunction: null }, idKey: { classPropertyName: "idKey", publicName: "idKey", isSignal: true, isRequired: false, transformFunction: null }, parentKey: { classPropertyName: "parentKey", publicName: "parentKey", isSignal: true, isRequired: false, transformFunction: null }, treeColumn: { classPropertyName: "treeColumn", publicName: "treeColumn", isSignal: true, isRequired: false, transformFunction: null }, defaultExpanded: { classPropertyName: "defaultExpanded", publicName: "defaultExpanded", isSignal: true, isRequired: false, transformFunction: null }, expandedIds: { classPropertyName: "expandedIds", publicName: "expandedIds", isSignal: true, isRequired: false, transformFunction: null }, indentSize: { classPropertyName: "indentSize", publicName: "indentSize", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { sort: "sort", rowClick: "rowClick", cellEdit: "cellEdit", selectionChange: "selectionChange", actionClick: "actionClick", rowToggle: "rowToggle", expandedIdsChange: "expandedIdsChange" }, queries: [{ propertyName: "cellTemplates", predicate: TableCellDirective }], ngImport: i0, template: "<div [class]=\"wrapperClasses()\">\n <table [class]=\"tableClasses()\" [attr.role]=\"treeMode() ? 'treegrid' : 'table'\">\n <thead>\n <!-- Filter row -->\n @if (filterable()) {\n <tr class=\"lc-table__filter-row\">\n @if (selectable()) {\n <th class=\"lc-table__select-cell\"></th>\n }\n @for (column of columns(); track column.key) {\n <th>\n @if (column.filterable !== false) {\n <lc-input\n class=\"lc-table__filter-input\"\n size=\"xs\"\n [placeholder]=\"'Filter ' + column.label\"\n [ariaLabel]=\"'Filter by ' + column.label\"\n [ngModel]=\"getFilterValue(column.key)\"\n (ngModelChange)=\"onFilterChange(column.key, $event)\"\n />\n }\n </th>\n }\n @if (hasActions()) {\n <th class=\"lc-table__actions-cell\"></th>\n }\n </tr>\n }\n <!-- Header row -->\n <tr>\n @if (selectable()) {\n <th class=\"lc-table__select-cell\" scope=\"col\">\n <input\n type=\"checkbox\"\n class=\"lc-table__checkbox\"\n [checked]=\"allSelected()\"\n (change)=\"toggleSelectAll()\"\n aria-label=\"Select all rows\"\n />\n </th>\n }\n @for (column of columns(); track column.key) {\n <th\n scope=\"col\"\n [class]=\"getHeaderClasses(column) + (column.cssClass ? ' ' + column.cssClass : '')\"\n [attr.aria-sort]=\"getAriaSort(column.key)\"\n [style.width]=\"column.width\"\n [title]=\"column.tooltip || ''\"\n (click)=\"handleSort(column.key)\">\n {{ column.label }}\n @if (column.sortable && getSortState(column.key)) {\n <span class=\"sort-indicator\" [attr.aria-label]=\"getSortState(column.key) === 'asc' ? 'sorted ascending' : 'sorted descending'\">\n @if (getSortState(column.key) === 'asc') {\n \u2191\n } @else {\n \u2193\n }\n </span>\n }\n </th>\n }\n @if (hasActions()) {\n <th\n scope=\"col\"\n class=\"lc-table__actions-cell\"\n [class]=\"'lc-table__actions-cell--' + actionsAlign()\"\n [style.width]=\"actionsWidth()\"\n >\n {{ actionsLabel() }}\n </th>\n }\n </tr>\n </thead>\n <tbody>\n @if (displayRows().length === 0) {\n <tr>\n <td [attr.colspan]=\"columns().length + (selectable() ? 1 : 0) + (hasActions() ? 1 : 0)\" class=\"lc-table__empty\">\n {{ emptyText() }}\n </td>\n </tr>\n } @else {\n @for (dr of displayRows(); track dr.absIndex) {\n <tr\n [class.lc-table__row--selected]=\"selectable() && isRowSelected(dr.absIndex)\"\n [class.lc-table__row--group]=\"dr.hasChildren\"\n [attr.role]=\"treeMode() ? 'row' : null\"\n [attr.aria-level]=\"treeMode() ? dr.level : null\"\n [attr.aria-expanded]=\"treeMode() && dr.hasChildren ? dr.expanded : null\"\n [attr.aria-posinset]=\"treeMode() ? dr.posInSet : null\"\n [attr.aria-setsize]=\"treeMode() ? dr.setSize : null\"\n (click)=\"onRowClick(dr.row)\"\n >\n @if (selectable()) {\n <td class=\"lc-table__select-cell\" [attr.role]=\"treeMode() ? 'gridcell' : null\">\n <input\n type=\"checkbox\"\n class=\"lc-table__checkbox\"\n [checked]=\"isRowSelected(dr.absIndex)\"\n (change)=\"toggleRowSelect(dr.absIndex)\"\n (click)=\"$event.stopPropagation()\"\n [attr.aria-label]=\"'Select row ' + (dr.absIndex + 1)\"\n />\n </td>\n }\n @for (column of columns(); track column.key) {\n <td\n [class]=\"getCellClasses(dr.row, column, dr.absIndex)\"\n [ngStyle]=\"getCellStyles(dr.row, column, dr.absIndex)\"\n [attr.role]=\"treeMode() ? 'gridcell' : null\"\n (dblclick)=\"editable() ? startEdit(dr.absIndex, column.key, getCellValue(dr.row, column.key)) : null\"\n >\n @if (isTreeColumn(column.key)) {\n <span class=\"lc-table__tree-cell\">\n @for (lvl of indentLevels(dr.depth); track lvl) {\n <span class=\"lc-table__tree-indent\" [style.width.px]=\"indentSize()\"></span>\n }\n <span class=\"lc-table__tree-chevron\" [style.width.px]=\"indentSize()\">\n @if (dr.hasChildren) {\n <button\n type=\"button\"\n class=\"lc-table__chevron-btn\"\n [class.lc-table__chevron-btn--expanded]=\"dr.expanded\"\n [attr.aria-label]=\"(dr.expanded ? 'Einklappen: ' : 'Aufklappen: ') + treeCellLabel(dr.row)\"\n [attr.aria-expanded]=\"dr.expanded\"\n (click)=\"onChevronClick(dr, $event)\"\n >\n <lc-icon name=\"chevron-right\" size=\"xs\" [decorative]=\"true\" />\n </button>\n }\n </span>\n <span class=\"lc-table__tree-content\">\n <ng-container\n *ngTemplateOutlet=\"cellContent; context: { row: dr.row, column: column, absIndex: dr.absIndex }\"\n ></ng-container>\n </span>\n </span>\n } @else {\n <ng-container\n *ngTemplateOutlet=\"cellContent; context: { row: dr.row, column: column, absIndex: dr.absIndex }\"\n ></ng-container>\n }\n </td>\n }\n @if (hasActions()) {\n <td\n class=\"lc-table__actions-cell\"\n [class]=\"'lc-table__actions-cell--' + actionsAlign()\"\n [attr.role]=\"treeMode() ? 'gridcell' : null\"\n (click)=\"$event.stopPropagation()\"\n >\n <div class=\"lc-table__actions\">\n @for (action of actions(); track action.key) {\n @if (!isActionHidden(action, dr.row, dr.absIndex)) {\n <lc-button\n [variant]=\"action.variant ?? 'ghost'\"\n size=\"xs\"\n [iconOnly]=\"!action.label\"\n [disabled]=\"isActionDisabled(action, dr.row, dr.absIndex)\"\n [ariaLabel]=\"action.tooltip ?? action.label ?? action.key\"\n (clicked)=\"onActionClick(action, dr.row, dr.absIndex)\"\n >\n @if (action.icon) {\n <lc-icon [name]=\"action.icon\" size=\"sm\" [decorative]=\"true\" />\n }\n @if (action.label) {\n {{ action.label }}\n }\n </lc-button>\n }\n }\n </div>\n </td>\n }\n </tr>\n }\n }\n </tbody>\n </table>\n</div>\n\n<!-- Shared cell content (edit input / custom template / formatted value) -->\n<ng-template #cellContent let-row=\"row\" let-column=\"column\" let-absIndex=\"absIndex\">\n @if (isEditing(absIndex, column.key)) {\n <input\n type=\"text\"\n class=\"lc-table__edit-input\"\n [value]=\"editValue()\"\n (input)=\"editValue.set(getInputValue($event))\"\n (blur)=\"commitEdit(absIndex, column.key)\"\n (keydown)=\"onEditKeydown($event, absIndex, column.key)\"\n autofocus\n />\n } @else if (hasCustomTemplate(column.key)) {\n <ng-container *ngTemplateOutlet=\"getCellTemplate(column.key)!.template; context: { $implicit: row }\"></ng-container>\n } @else {\n {{ getFormattedCellValue(row, column, absIndex) }}\n }\n</ng-template>\n\n<!-- Pagination -->\n@if (paginate()) {\n <div class=\"lc-table-pagination\">\n <div class=\"lc-table-pagination__info\">\n {{ paginationStart }}\u2013{{ paginationEnd }} of {{ totalRows() }}\n </div>\n <div class=\"lc-table-pagination__controls\">\n <lc-select\n class=\"lc-table-pagination__size\"\n [size]=\"size() === 'sm' ? 'sm' : size() === 'lg' ? 'lg' : 'md'\"\n [options]=\"pageSizeSelectOptions()\"\n [ngModel]=\"internalPageSize()\"\n [ariaLabel]=\"'Rows per page'\"\n (ngModelChange)=\"onPageSizeModelChange($event)\"\n />\n <button\n type=\"button\"\n class=\"lc-table-pagination__btn\"\n [disabled]=\"currentPage() === 0\"\n (click)=\"goToPage(currentPage() - 1)\"\n aria-label=\"Previous page\"\n >\u2039</button>\n <span class=\"lc-table-pagination__page\">\n {{ currentPage() + 1 }} / {{ totalPages() }}\n </span>\n <button\n type=\"button\"\n class=\"lc-table-pagination__btn\"\n [disabled]=\"currentPage() >= totalPages() - 1\"\n (click)=\"goToPage(currentPage() + 1)\"\n aria-label=\"Next page\"\n >\u203A</button>\n </div>\n </div>\n}\n", styles: [".lc-table-wrapper{width:100%}.lc-table-wrapper--responsive{overflow-x:auto;-webkit-overflow-scrolling:touch}@media(max-width:768px){.lc-table-wrapper--responsive::-webkit-scrollbar{height:8px}.lc-table-wrapper--responsive::-webkit-scrollbar-thumb{background-color:var(--color-border);border-radius:var(--border-radius-sm)}}.lc-table{width:100%;border-collapse:collapse;border-spacing:0;background-color:var(--color-surface);color:var(--color-text-primary);font-family:var(--typography-font-family)}.lc-table thead{background-color:var(--color-surface-2);border-bottom:2px solid var(--color-border-strong)}.lc-table thead tr th{padding:var(--lc-density-padding-sm, var(--spacing-3)) var(--lc-density-padding-md, var(--spacing-4));text-align:left;font-weight:var(--typography-font-weight-semibold);font-size:var(--typography-font-size-sm);text-transform:uppercase;letter-spacing:.04em;color:var(--color-text-secondary);white-space:nowrap;-webkit-user-select:none;user-select:none}.lc-table thead tr th.sortable{cursor:pointer;position:relative;padding-right:var(--spacing-8);transition:background-color .2s ease}.lc-table thead tr th.sortable:hover{background-color:var(--color-surface-hover);color:var(--color-text-primary)}.lc-table thead tr th.sortable .sort-indicator{position:absolute;right:var(--spacing-3);top:50%;transform:translateY(-50%);font-size:var(--typography-font-size-xs);color:var(--color-primary)}.lc-table thead tr th.sorted-asc,.lc-table thead tr th.sorted-desc{background-color:var(--color-surface-hover);color:var(--color-text-primary)}.lc-table tbody tr{border-bottom:1px solid var(--color-divider)}.lc-table tbody tr:last-child{border-bottom:none}.lc-table tbody tr td{padding:var(--lc-density-padding-sm, var(--spacing-3)) var(--lc-density-padding-md, var(--spacing-4));font-size:var(--typography-font-size-sm);color:var(--color-text-primary)}.lc-table__empty{text-align:center;padding:var(--spacing-8) var(--spacing-4)!important;color:var(--color-text-secondary);font-style:italic}.lc-table--striped tbody tr:nth-child(2n){background-color:var(--color-surface-2)}.lc-table--bordered{border:1px solid var(--color-border)}.lc-table--bordered thead tr th,.lc-table--bordered tbody tr td{border-right:1px solid var(--color-divider)}.lc-table--bordered thead tr th:last-child,.lc-table--bordered tbody tr td:last-child{border-right:none}.lc-table--bordered tbody tr{border-bottom:1px solid var(--color-border)}.lc-table--hoverable tbody tr{transition:background-color .15s ease;cursor:pointer}.lc-table--hoverable tbody tr:hover{background-color:var(--color-surface-hover)}.lc-table--sm thead tr th,.lc-table--sm tbody tr td{padding:var(--lc-density-padding-xs, var(--spacing-2)) var(--lc-density-padding-sm, var(--spacing-3));font-size:var(--typography-font-size-xs)}.lc-table--lg thead tr th,.lc-table--lg tbody tr td{padding:var(--lc-density-padding-md, var(--spacing-4)) var(--spacing-5);font-size:var(--typography-font-size-base)}.lc-table__filter-row th{padding:var(--spacing-2) var(--spacing-4)!important;background-color:var(--color-background)!important;border-bottom:1px solid var(--color-divider)!important}.lc-table__filter-input{width:100%;display:block}.lc-table__filter-input .input-field{font-size:var(--typography-font-size-xs)}.lc-table__select-cell{width:40px;text-align:center!important;padding:var(--spacing-2)!important}.lc-table__checkbox{width:16px;height:16px;cursor:pointer;accent-color:var(--color-primary)}.lc-table__row--selected{background-color:var(--color-surface-selected)!important}.lc-table__actions-cell{white-space:nowrap}.lc-table th.lc-table__actions-cell--start,.lc-table td.lc-table__actions-cell--start{text-align:left}.lc-table th.lc-table__actions-cell--center,.lc-table td.lc-table__actions-cell--center{text-align:center}.lc-table th.lc-table__actions-cell--end,.lc-table td.lc-table__actions-cell--end{text-align:right}.lc-table__actions{display:flex;align-items:center;gap:var(--spacing-2);justify-content:flex-start}.lc-table__actions-cell--center .lc-table__actions{justify-content:center}.lc-table__actions-cell--end .lc-table__actions{justify-content:flex-end}.lc-table__tree-cell{display:flex;align-items:center;min-width:0}.lc-table__tree-indent{flex:0 0 auto;align-self:stretch;position:relative}.lc-table__tree-indent:before{content:\"\";position:absolute;left:50%;top:0;bottom:0;width:1px;background-color:var(--color-border)}.lc-table__tree-chevron{flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center}.lc-table__chevron-btn{display:inline-flex;align-items:center;justify-content:center;width:20px;height:20px;padding:0;border:none;background:transparent;color:var(--color-text-secondary);cursor:pointer;border-radius:var(--border-radius-sm);transition:transform .2s ease,background-color .15s ease,color .15s ease}.lc-table__chevron-btn:hover{background-color:var(--color-surface-hover);color:var(--color-text-primary)}.lc-table__chevron-btn:focus-visible{outline:2px solid var(--color-primary);outline-offset:1px}.lc-table__chevron-btn--expanded{transform:rotate(90deg)}.lc-table__tree-content{flex:1 1 auto;min-width:0}.lc-table__row--group .lc-table__tree-content{font-weight:var(--typography-font-weight-semibold)}.lc-table__edit-input{width:100%;padding:var(--spacing-1) var(--spacing-2);border:2px solid var(--color-primary);border-radius:var(--border-radius-sm);font-size:inherit;background-color:var(--color-surface-2);color:var(--color-text-primary);outline:none}.lc-table-pagination{display:flex;align-items:center;justify-content:space-between;padding:var(--spacing-3) var(--spacing-1);font-size:var(--typography-font-size-sm);color:var(--color-text-secondary)}.lc-table-pagination__info{white-space:nowrap}.lc-table-pagination__controls{display:flex;align-items:center;gap:var(--spacing-2)}.lc-table-pagination__size{display:block;min-width:110px}.lc-table-pagination__btn{appearance:none;border:1px solid var(--color-border);background-color:var(--color-surface);color:var(--color-text-primary);width:28px;height:28px;display:flex;align-items:center;justify-content:center;border-radius:var(--border-radius-sm);font-size:var(--typography-font-size-base);cursor:pointer;transition:background-color .15s ease}.lc-table-pagination__btn:hover:not(:disabled){background-color:var(--color-surface-hover)}.lc-table-pagination__btn:disabled{opacity:.4;cursor:not-allowed}.lc-table-pagination__page{white-space:nowrap;min-width:60px;text-align:center}@media(max-width:640px){.lc-table-wrapper--stack .lc-table thead{display:none}.lc-table-wrapper--stack .lc-table tbody tr{display:block;margin-bottom:var(--spacing-4);border:1px solid var(--color-border);border-radius:var(--border-radius-md)}.lc-table-wrapper--stack .lc-table tbody tr td{display:block;text-align:right;padding:var(--spacing-2) var(--spacing-4);border-bottom:1px solid var(--color-divider)}.lc-table-wrapper--stack .lc-table tbody tr td:last-child{border-bottom:none}.lc-table-wrapper--stack .lc-table tbody tr td:before{content:attr(data-label);float:left;font-weight:var(--typography-font-weight-semibold);color:var(--color-text-secondary)}}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: SelectComponent, selector: "lc-select", inputs: ["variant", "size", "disabled", "error", "required", "loading", "searchable", "multiple", "placeholder", "helperText", "errorMessage", "ariaLabel", "options"], outputs: ["selectionChange", "opened", "closed"] }, { kind: "component", type: InputComponent, selector: "lc-input", inputs: ["label", "placeholder", "type", "size", "disabled", "readonly", "required", "error", "helperText", "iconBefore", "iconAfter", "maxLength", "showCharCount", "ariaLabel"], outputs: ["valueChange", "focused", "blurred", "enterPressed"] }, { kind: "component", type: ButtonComponent, selector: "lc-button", inputs: ["variant", "size", "disabled", "loading", "iconOnly", "fullWidth", "ariaLabel", "type"], outputs: ["clicked", "focused", "blurred"] }, { kind: "component", type: IconComponent, selector: "lc-icon", inputs: ["name", "variant", "size", "color", "ariaLabel", "decorative"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
7515
7763
|
}
|
|
7516
7764
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.10", ngImport: i0, type: TableComponent, decorators: [{
|
|
7517
7765
|
type: Component,
|
|
7518
|
-
args: [{ selector: 'lc-table', standalone: true, imports: [NgTemplateOutlet, NgStyle, FormsModule, SelectComponent, InputComponent, ButtonComponent, IconComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div [class]=\"wrapperClasses()\">\n <table [class]=\"tableClasses()\" role=\"table\">\n <thead>\n <!-- Filter row -->\n @if (filterable()) {\n <tr class=\"lc-table__filter-row\">\n @if (selectable()) {\n <th class=\"lc-table__select-cell\"></th>\n }\n @for (column of columns(); track column.key) {\n <th>\n @if (column.filterable !== false) {\n <lc-input\n class=\"lc-table__filter-input\"\n size=\"xs\"\n [placeholder]=\"'Filter ' + column.label\"\n [ariaLabel]=\"'Filter by ' + column.label\"\n [ngModel]=\"getFilterValue(column.key)\"\n (ngModelChange)=\"onFilterChange(column.key, $event)\"\n />\n }\n </th>\n }\n @if (hasActions()) {\n <th class=\"lc-table__actions-cell\"></th>\n }\n </tr>\n }\n <!-- Header row -->\n <tr>\n @if (selectable()) {\n <th class=\"lc-table__select-cell\" scope=\"col\">\n <input\n type=\"checkbox\"\n class=\"lc-table__checkbox\"\n [checked]=\"allSelected()\"\n (change)=\"toggleSelectAll()\"\n aria-label=\"Select all rows\"\n />\n </th>\n }\n @for (column of columns(); track column.key) {\n <th\n scope=\"col\"\n [class]=\"getHeaderClasses(column) + (column.cssClass ? ' ' + column.cssClass : '')\"\n [attr.aria-sort]=\"getAriaSort(column.key)\"\n [style.width]=\"column.width\"\n [title]=\"column.tooltip || ''\"\n (click)=\"handleSort(column.key)\">\n {{ column.label }}\n @if (column.sortable && getSortState(column.key)) {\n <span class=\"sort-indicator\" [attr.aria-label]=\"getSortState(column.key) === 'asc' ? 'sorted ascending' : 'sorted descending'\">\n @if (getSortState(column.key) === 'asc') {\n \u2191\n } @else {\n \u2193\n }\n </span>\n }\n </th>\n }\n @if (hasActions()) {\n <th\n scope=\"col\"\n class=\"lc-table__actions-cell\"\n [class]=\"'lc-table__actions-cell--' + actionsAlign()\"\n [style.width]=\"actionsWidth()\"\n >\n {{ actionsLabel() }}\n </th>\n }\n </tr>\n </thead>\n <tbody>\n @if (displayData().length === 0) {\n <tr>\n <td [attr.colspan]=\"columns().length + (selectable() ? 1 : 0) + (hasActions() ? 1 : 0)\" class=\"lc-table__empty\">\n {{ emptyText() }}\n </td>\n </tr>\n } @else {\n @for (row of displayData(); track $index; let i = $index) {\n <tr\n [class.lc-table__row--selected]=\"selectable() && isRowSelected(i)\"\n (click)=\"onRowClick(row)\"\n >\n @if (selectable()) {\n <td class=\"lc-table__select-cell\">\n <input\n type=\"checkbox\"\n class=\"lc-table__checkbox\"\n [checked]=\"isRowSelected($index)\"\n (change)=\"toggleRowSelect($index)\"\n (click)=\"$event.stopPropagation()\"\n [attr.aria-label]=\"'Select row ' + ($index + 1)\"\n />\n </td>\n }\n @for (column of columns(); track column.key) {\n <td\n [class]=\"getCellClasses(row, column, i)\"\n [ngStyle]=\"getCellStyles(row, column, i)\"\n (dblclick)=\"editable() ? startEdit($index, column.key, getCellValue(row, column.key)) : null\"\n >\n @if (isEditing($index, column.key)) {\n <input\n type=\"text\"\n class=\"lc-table__edit-input\"\n [value]=\"editValue()\"\n (input)=\"editValue.set(getInputValue($event))\"\n (blur)=\"commitEdit($index, column.key)\"\n (keydown)=\"onEditKeydown($event, $index, column.key)\"\n autofocus\n />\n } @else if (hasCustomTemplate(column.key)) {\n <ng-container *ngTemplateOutlet=\"getCellTemplate(column.key)!.template; context: { $implicit: row }\"></ng-container>\n } @else {\n {{ getFormattedCellValue(row, column, i) }}\n }\n </td>\n }\n @if (hasActions()) {\n <td\n class=\"lc-table__actions-cell\"\n [class]=\"'lc-table__actions-cell--' + actionsAlign()\"\n (click)=\"$event.stopPropagation()\"\n >\n <div class=\"lc-table__actions\">\n @for (action of actions(); track action.key) {\n @if (!isActionHidden(action, row, i)) {\n <lc-button\n [variant]=\"action.variant ?? 'ghost'\"\n size=\"xs\"\n [iconOnly]=\"!action.label\"\n [disabled]=\"isActionDisabled(action, row, i)\"\n [ariaLabel]=\"action.tooltip ?? action.label ?? action.key\"\n (clicked)=\"onActionClick(action, row, i)\"\n >\n @if (action.icon) {\n <lc-icon [name]=\"action.icon\" size=\"sm\" [decorative]=\"true\" />\n }\n @if (action.label) {\n {{ action.label }}\n }\n </lc-button>\n }\n }\n </div>\n </td>\n }\n </tr>\n }\n }\n </tbody>\n </table>\n</div>\n\n<!-- Pagination -->\n@if (paginate()) {\n <div class=\"lc-table-pagination\">\n <div class=\"lc-table-pagination__info\">\n {{ paginationStart }}\u2013{{ paginationEnd }} of {{ totalRows() }}\n </div>\n <div class=\"lc-table-pagination__controls\">\n <lc-select\n class=\"lc-table-pagination__size\"\n [size]=\"size() === 'sm' ? 'sm' : size() === 'lg' ? 'lg' : 'md'\"\n [options]=\"pageSizeSelectOptions()\"\n [ngModel]=\"internalPageSize()\"\n [ariaLabel]=\"'Rows per page'\"\n (ngModelChange)=\"onPageSizeModelChange($event)\"\n />\n <button\n type=\"button\"\n class=\"lc-table-pagination__btn\"\n [disabled]=\"currentPage() === 0\"\n (click)=\"goToPage(currentPage() - 1)\"\n aria-label=\"Previous page\"\n >\u2039</button>\n <span class=\"lc-table-pagination__page\">\n {{ currentPage() + 1 }} / {{ totalPages() }}\n </span>\n <button\n type=\"button\"\n class=\"lc-table-pagination__btn\"\n [disabled]=\"currentPage() >= totalPages() - 1\"\n (click)=\"goToPage(currentPage() + 1)\"\n aria-label=\"Next page\"\n >\u203A</button>\n </div>\n </div>\n}\n", styles: [".lc-table-wrapper{width:100%}.lc-table-wrapper--responsive{overflow-x:auto;-webkit-overflow-scrolling:touch}@media(max-width:768px){.lc-table-wrapper--responsive::-webkit-scrollbar{height:8px}.lc-table-wrapper--responsive::-webkit-scrollbar-thumb{background-color:var(--color-border);border-radius:var(--border-radius-sm)}}.lc-table{width:100%;border-collapse:collapse;border-spacing:0;background-color:var(--color-surface);color:var(--color-text-primary);font-family:var(--typography-font-family)}.lc-table thead{background-color:var(--color-surface-2);border-bottom:2px solid var(--color-border-strong)}.lc-table thead tr th{padding:var(--lc-density-padding-sm, var(--spacing-3)) var(--lc-density-padding-md, var(--spacing-4));text-align:left;font-weight:var(--typography-font-weight-semibold);font-size:var(--typography-font-size-sm);text-transform:uppercase;letter-spacing:.04em;color:var(--color-text-secondary);white-space:nowrap;-webkit-user-select:none;user-select:none}.lc-table thead tr th.sortable{cursor:pointer;position:relative;padding-right:var(--spacing-8);transition:background-color .2s ease}.lc-table thead tr th.sortable:hover{background-color:var(--color-surface-hover);color:var(--color-text-primary)}.lc-table thead tr th.sortable .sort-indicator{position:absolute;right:var(--spacing-3);top:50%;transform:translateY(-50%);font-size:var(--typography-font-size-xs);color:var(--color-primary)}.lc-table thead tr th.sorted-asc,.lc-table thead tr th.sorted-desc{background-color:var(--color-surface-hover);color:var(--color-text-primary)}.lc-table tbody tr{border-bottom:1px solid var(--color-divider)}.lc-table tbody tr:last-child{border-bottom:none}.lc-table tbody tr td{padding:var(--lc-density-padding-sm, var(--spacing-3)) var(--lc-density-padding-md, var(--spacing-4));font-size:var(--typography-font-size-sm);color:var(--color-text-primary)}.lc-table__empty{text-align:center;padding:var(--spacing-8) var(--spacing-4)!important;color:var(--color-text-secondary);font-style:italic}.lc-table--striped tbody tr:nth-child(2n){background-color:var(--color-surface-2)}.lc-table--bordered{border:1px solid var(--color-border)}.lc-table--bordered thead tr th,.lc-table--bordered tbody tr td{border-right:1px solid var(--color-divider)}.lc-table--bordered thead tr th:last-child,.lc-table--bordered tbody tr td:last-child{border-right:none}.lc-table--bordered tbody tr{border-bottom:1px solid var(--color-border)}.lc-table--hoverable tbody tr{transition:background-color .15s ease;cursor:pointer}.lc-table--hoverable tbody tr:hover{background-color:var(--color-surface-hover)}.lc-table--sm thead tr th,.lc-table--sm tbody tr td{padding:var(--lc-density-padding-xs, var(--spacing-2)) var(--lc-density-padding-sm, var(--spacing-3));font-size:var(--typography-font-size-xs)}.lc-table--lg thead tr th,.lc-table--lg tbody tr td{padding:var(--lc-density-padding-md, var(--spacing-4)) var(--spacing-5);font-size:var(--typography-font-size-base)}.lc-table__filter-row th{padding:var(--spacing-2) var(--spacing-4)!important;background-color:var(--color-background)!important;border-bottom:1px solid var(--color-divider)!important}.lc-table__filter-input{width:100%;display:block}.lc-table__filter-input .input-field{font-size:var(--typography-font-size-xs)}.lc-table__select-cell{width:40px;text-align:center!important;padding:var(--spacing-2)!important}.lc-table__checkbox{width:16px;height:16px;cursor:pointer;accent-color:var(--color-primary)}.lc-table__row--selected{background-color:var(--color-surface-selected)!important}.lc-table__actions-cell{white-space:nowrap}.lc-table th.lc-table__actions-cell--start,.lc-table td.lc-table__actions-cell--start{text-align:left}.lc-table th.lc-table__actions-cell--center,.lc-table td.lc-table__actions-cell--center{text-align:center}.lc-table th.lc-table__actions-cell--end,.lc-table td.lc-table__actions-cell--end{text-align:right}.lc-table__actions{display:flex;align-items:center;gap:var(--spacing-2);justify-content:flex-start}.lc-table__actions-cell--center .lc-table__actions{justify-content:center}.lc-table__actions-cell--end .lc-table__actions{justify-content:flex-end}.lc-table__edit-input{width:100%;padding:var(--spacing-1) var(--spacing-2);border:2px solid var(--color-primary);border-radius:var(--border-radius-sm);font-size:inherit;background-color:var(--color-surface-2);color:var(--color-text-primary);outline:none}.lc-table-pagination{display:flex;align-items:center;justify-content:space-between;padding:var(--spacing-3) var(--spacing-1);font-size:var(--typography-font-size-sm);color:var(--color-text-secondary)}.lc-table-pagination__info{white-space:nowrap}.lc-table-pagination__controls{display:flex;align-items:center;gap:var(--spacing-2)}.lc-table-pagination__size{display:block;min-width:110px}.lc-table-pagination__btn{appearance:none;border:1px solid var(--color-border);background-color:var(--color-surface);color:var(--color-text-primary);width:28px;height:28px;display:flex;align-items:center;justify-content:center;border-radius:var(--border-radius-sm);font-size:var(--typography-font-size-base);cursor:pointer;transition:background-color .15s ease}.lc-table-pagination__btn:hover:not(:disabled){background-color:var(--color-surface-hover)}.lc-table-pagination__btn:disabled{opacity:.4;cursor:not-allowed}.lc-table-pagination__page{white-space:nowrap;min-width:60px;text-align:center}@media(max-width:640px){.lc-table-wrapper--stack .lc-table thead{display:none}.lc-table-wrapper--stack .lc-table tbody tr{display:block;margin-bottom:var(--spacing-4);border:1px solid var(--color-border);border-radius:var(--border-radius-md)}.lc-table-wrapper--stack .lc-table tbody tr td{display:block;text-align:right;padding:var(--spacing-2) var(--spacing-4);border-bottom:1px solid var(--color-divider)}.lc-table-wrapper--stack .lc-table tbody tr td:last-child{border-bottom:none}.lc-table-wrapper--stack .lc-table tbody tr td:before{content:attr(data-label);float:left;font-weight:var(--typography-font-weight-semibold);color:var(--color-text-secondary)}}\n"] }]
|
|
7766
|
+
args: [{ selector: 'lc-table', standalone: true, imports: [NgTemplateOutlet, NgStyle, FormsModule, SelectComponent, InputComponent, ButtonComponent, IconComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div [class]=\"wrapperClasses()\">\n <table [class]=\"tableClasses()\" [attr.role]=\"treeMode() ? 'treegrid' : 'table'\">\n <thead>\n <!-- Filter row -->\n @if (filterable()) {\n <tr class=\"lc-table__filter-row\">\n @if (selectable()) {\n <th class=\"lc-table__select-cell\"></th>\n }\n @for (column of columns(); track column.key) {\n <th>\n @if (column.filterable !== false) {\n <lc-input\n class=\"lc-table__filter-input\"\n size=\"xs\"\n [placeholder]=\"'Filter ' + column.label\"\n [ariaLabel]=\"'Filter by ' + column.label\"\n [ngModel]=\"getFilterValue(column.key)\"\n (ngModelChange)=\"onFilterChange(column.key, $event)\"\n />\n }\n </th>\n }\n @if (hasActions()) {\n <th class=\"lc-table__actions-cell\"></th>\n }\n </tr>\n }\n <!-- Header row -->\n <tr>\n @if (selectable()) {\n <th class=\"lc-table__select-cell\" scope=\"col\">\n <input\n type=\"checkbox\"\n class=\"lc-table__checkbox\"\n [checked]=\"allSelected()\"\n (change)=\"toggleSelectAll()\"\n aria-label=\"Select all rows\"\n />\n </th>\n }\n @for (column of columns(); track column.key) {\n <th\n scope=\"col\"\n [class]=\"getHeaderClasses(column) + (column.cssClass ? ' ' + column.cssClass : '')\"\n [attr.aria-sort]=\"getAriaSort(column.key)\"\n [style.width]=\"column.width\"\n [title]=\"column.tooltip || ''\"\n (click)=\"handleSort(column.key)\">\n {{ column.label }}\n @if (column.sortable && getSortState(column.key)) {\n <span class=\"sort-indicator\" [attr.aria-label]=\"getSortState(column.key) === 'asc' ? 'sorted ascending' : 'sorted descending'\">\n @if (getSortState(column.key) === 'asc') {\n \u2191\n } @else {\n \u2193\n }\n </span>\n }\n </th>\n }\n @if (hasActions()) {\n <th\n scope=\"col\"\n class=\"lc-table__actions-cell\"\n [class]=\"'lc-table__actions-cell--' + actionsAlign()\"\n [style.width]=\"actionsWidth()\"\n >\n {{ actionsLabel() }}\n </th>\n }\n </tr>\n </thead>\n <tbody>\n @if (displayRows().length === 0) {\n <tr>\n <td [attr.colspan]=\"columns().length + (selectable() ? 1 : 0) + (hasActions() ? 1 : 0)\" class=\"lc-table__empty\">\n {{ emptyText() }}\n </td>\n </tr>\n } @else {\n @for (dr of displayRows(); track dr.absIndex) {\n <tr\n [class.lc-table__row--selected]=\"selectable() && isRowSelected(dr.absIndex)\"\n [class.lc-table__row--group]=\"dr.hasChildren\"\n [attr.role]=\"treeMode() ? 'row' : null\"\n [attr.aria-level]=\"treeMode() ? dr.level : null\"\n [attr.aria-expanded]=\"treeMode() && dr.hasChildren ? dr.expanded : null\"\n [attr.aria-posinset]=\"treeMode() ? dr.posInSet : null\"\n [attr.aria-setsize]=\"treeMode() ? dr.setSize : null\"\n (click)=\"onRowClick(dr.row)\"\n >\n @if (selectable()) {\n <td class=\"lc-table__select-cell\" [attr.role]=\"treeMode() ? 'gridcell' : null\">\n <input\n type=\"checkbox\"\n class=\"lc-table__checkbox\"\n [checked]=\"isRowSelected(dr.absIndex)\"\n (change)=\"toggleRowSelect(dr.absIndex)\"\n (click)=\"$event.stopPropagation()\"\n [attr.aria-label]=\"'Select row ' + (dr.absIndex + 1)\"\n />\n </td>\n }\n @for (column of columns(); track column.key) {\n <td\n [class]=\"getCellClasses(dr.row, column, dr.absIndex)\"\n [ngStyle]=\"getCellStyles(dr.row, column, dr.absIndex)\"\n [attr.role]=\"treeMode() ? 'gridcell' : null\"\n (dblclick)=\"editable() ? startEdit(dr.absIndex, column.key, getCellValue(dr.row, column.key)) : null\"\n >\n @if (isTreeColumn(column.key)) {\n <span class=\"lc-table__tree-cell\">\n @for (lvl of indentLevels(dr.depth); track lvl) {\n <span class=\"lc-table__tree-indent\" [style.width.px]=\"indentSize()\"></span>\n }\n <span class=\"lc-table__tree-chevron\" [style.width.px]=\"indentSize()\">\n @if (dr.hasChildren) {\n <button\n type=\"button\"\n class=\"lc-table__chevron-btn\"\n [class.lc-table__chevron-btn--expanded]=\"dr.expanded\"\n [attr.aria-label]=\"(dr.expanded ? 'Einklappen: ' : 'Aufklappen: ') + treeCellLabel(dr.row)\"\n [attr.aria-expanded]=\"dr.expanded\"\n (click)=\"onChevronClick(dr, $event)\"\n >\n <lc-icon name=\"chevron-right\" size=\"xs\" [decorative]=\"true\" />\n </button>\n }\n </span>\n <span class=\"lc-table__tree-content\">\n <ng-container\n *ngTemplateOutlet=\"cellContent; context: { row: dr.row, column: column, absIndex: dr.absIndex }\"\n ></ng-container>\n </span>\n </span>\n } @else {\n <ng-container\n *ngTemplateOutlet=\"cellContent; context: { row: dr.row, column: column, absIndex: dr.absIndex }\"\n ></ng-container>\n }\n </td>\n }\n @if (hasActions()) {\n <td\n class=\"lc-table__actions-cell\"\n [class]=\"'lc-table__actions-cell--' + actionsAlign()\"\n [attr.role]=\"treeMode() ? 'gridcell' : null\"\n (click)=\"$event.stopPropagation()\"\n >\n <div class=\"lc-table__actions\">\n @for (action of actions(); track action.key) {\n @if (!isActionHidden(action, dr.row, dr.absIndex)) {\n <lc-button\n [variant]=\"action.variant ?? 'ghost'\"\n size=\"xs\"\n [iconOnly]=\"!action.label\"\n [disabled]=\"isActionDisabled(action, dr.row, dr.absIndex)\"\n [ariaLabel]=\"action.tooltip ?? action.label ?? action.key\"\n (clicked)=\"onActionClick(action, dr.row, dr.absIndex)\"\n >\n @if (action.icon) {\n <lc-icon [name]=\"action.icon\" size=\"sm\" [decorative]=\"true\" />\n }\n @if (action.label) {\n {{ action.label }}\n }\n </lc-button>\n }\n }\n </div>\n </td>\n }\n </tr>\n }\n }\n </tbody>\n </table>\n</div>\n\n<!-- Shared cell content (edit input / custom template / formatted value) -->\n<ng-template #cellContent let-row=\"row\" let-column=\"column\" let-absIndex=\"absIndex\">\n @if (isEditing(absIndex, column.key)) {\n <input\n type=\"text\"\n class=\"lc-table__edit-input\"\n [value]=\"editValue()\"\n (input)=\"editValue.set(getInputValue($event))\"\n (blur)=\"commitEdit(absIndex, column.key)\"\n (keydown)=\"onEditKeydown($event, absIndex, column.key)\"\n autofocus\n />\n } @else if (hasCustomTemplate(column.key)) {\n <ng-container *ngTemplateOutlet=\"getCellTemplate(column.key)!.template; context: { $implicit: row }\"></ng-container>\n } @else {\n {{ getFormattedCellValue(row, column, absIndex) }}\n }\n</ng-template>\n\n<!-- Pagination -->\n@if (paginate()) {\n <div class=\"lc-table-pagination\">\n <div class=\"lc-table-pagination__info\">\n {{ paginationStart }}\u2013{{ paginationEnd }} of {{ totalRows() }}\n </div>\n <div class=\"lc-table-pagination__controls\">\n <lc-select\n class=\"lc-table-pagination__size\"\n [size]=\"size() === 'sm' ? 'sm' : size() === 'lg' ? 'lg' : 'md'\"\n [options]=\"pageSizeSelectOptions()\"\n [ngModel]=\"internalPageSize()\"\n [ariaLabel]=\"'Rows per page'\"\n (ngModelChange)=\"onPageSizeModelChange($event)\"\n />\n <button\n type=\"button\"\n class=\"lc-table-pagination__btn\"\n [disabled]=\"currentPage() === 0\"\n (click)=\"goToPage(currentPage() - 1)\"\n aria-label=\"Previous page\"\n >\u2039</button>\n <span class=\"lc-table-pagination__page\">\n {{ currentPage() + 1 }} / {{ totalPages() }}\n </span>\n <button\n type=\"button\"\n class=\"lc-table-pagination__btn\"\n [disabled]=\"currentPage() >= totalPages() - 1\"\n (click)=\"goToPage(currentPage() + 1)\"\n aria-label=\"Next page\"\n >\u203A</button>\n </div>\n </div>\n}\n", styles: [".lc-table-wrapper{width:100%}.lc-table-wrapper--responsive{overflow-x:auto;-webkit-overflow-scrolling:touch}@media(max-width:768px){.lc-table-wrapper--responsive::-webkit-scrollbar{height:8px}.lc-table-wrapper--responsive::-webkit-scrollbar-thumb{background-color:var(--color-border);border-radius:var(--border-radius-sm)}}.lc-table{width:100%;border-collapse:collapse;border-spacing:0;background-color:var(--color-surface);color:var(--color-text-primary);font-family:var(--typography-font-family)}.lc-table thead{background-color:var(--color-surface-2);border-bottom:2px solid var(--color-border-strong)}.lc-table thead tr th{padding:var(--lc-density-padding-sm, var(--spacing-3)) var(--lc-density-padding-md, var(--spacing-4));text-align:left;font-weight:var(--typography-font-weight-semibold);font-size:var(--typography-font-size-sm);text-transform:uppercase;letter-spacing:.04em;color:var(--color-text-secondary);white-space:nowrap;-webkit-user-select:none;user-select:none}.lc-table thead tr th.sortable{cursor:pointer;position:relative;padding-right:var(--spacing-8);transition:background-color .2s ease}.lc-table thead tr th.sortable:hover{background-color:var(--color-surface-hover);color:var(--color-text-primary)}.lc-table thead tr th.sortable .sort-indicator{position:absolute;right:var(--spacing-3);top:50%;transform:translateY(-50%);font-size:var(--typography-font-size-xs);color:var(--color-primary)}.lc-table thead tr th.sorted-asc,.lc-table thead tr th.sorted-desc{background-color:var(--color-surface-hover);color:var(--color-text-primary)}.lc-table tbody tr{border-bottom:1px solid var(--color-divider)}.lc-table tbody tr:last-child{border-bottom:none}.lc-table tbody tr td{padding:var(--lc-density-padding-sm, var(--spacing-3)) var(--lc-density-padding-md, var(--spacing-4));font-size:var(--typography-font-size-sm);color:var(--color-text-primary)}.lc-table__empty{text-align:center;padding:var(--spacing-8) var(--spacing-4)!important;color:var(--color-text-secondary);font-style:italic}.lc-table--striped tbody tr:nth-child(2n){background-color:var(--color-surface-2)}.lc-table--bordered{border:1px solid var(--color-border)}.lc-table--bordered thead tr th,.lc-table--bordered tbody tr td{border-right:1px solid var(--color-divider)}.lc-table--bordered thead tr th:last-child,.lc-table--bordered tbody tr td:last-child{border-right:none}.lc-table--bordered tbody tr{border-bottom:1px solid var(--color-border)}.lc-table--hoverable tbody tr{transition:background-color .15s ease;cursor:pointer}.lc-table--hoverable tbody tr:hover{background-color:var(--color-surface-hover)}.lc-table--sm thead tr th,.lc-table--sm tbody tr td{padding:var(--lc-density-padding-xs, var(--spacing-2)) var(--lc-density-padding-sm, var(--spacing-3));font-size:var(--typography-font-size-xs)}.lc-table--lg thead tr th,.lc-table--lg tbody tr td{padding:var(--lc-density-padding-md, var(--spacing-4)) var(--spacing-5);font-size:var(--typography-font-size-base)}.lc-table__filter-row th{padding:var(--spacing-2) var(--spacing-4)!important;background-color:var(--color-background)!important;border-bottom:1px solid var(--color-divider)!important}.lc-table__filter-input{width:100%;display:block}.lc-table__filter-input .input-field{font-size:var(--typography-font-size-xs)}.lc-table__select-cell{width:40px;text-align:center!important;padding:var(--spacing-2)!important}.lc-table__checkbox{width:16px;height:16px;cursor:pointer;accent-color:var(--color-primary)}.lc-table__row--selected{background-color:var(--color-surface-selected)!important}.lc-table__actions-cell{white-space:nowrap}.lc-table th.lc-table__actions-cell--start,.lc-table td.lc-table__actions-cell--start{text-align:left}.lc-table th.lc-table__actions-cell--center,.lc-table td.lc-table__actions-cell--center{text-align:center}.lc-table th.lc-table__actions-cell--end,.lc-table td.lc-table__actions-cell--end{text-align:right}.lc-table__actions{display:flex;align-items:center;gap:var(--spacing-2);justify-content:flex-start}.lc-table__actions-cell--center .lc-table__actions{justify-content:center}.lc-table__actions-cell--end .lc-table__actions{justify-content:flex-end}.lc-table__tree-cell{display:flex;align-items:center;min-width:0}.lc-table__tree-indent{flex:0 0 auto;align-self:stretch;position:relative}.lc-table__tree-indent:before{content:\"\";position:absolute;left:50%;top:0;bottom:0;width:1px;background-color:var(--color-border)}.lc-table__tree-chevron{flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center}.lc-table__chevron-btn{display:inline-flex;align-items:center;justify-content:center;width:20px;height:20px;padding:0;border:none;background:transparent;color:var(--color-text-secondary);cursor:pointer;border-radius:var(--border-radius-sm);transition:transform .2s ease,background-color .15s ease,color .15s ease}.lc-table__chevron-btn:hover{background-color:var(--color-surface-hover);color:var(--color-text-primary)}.lc-table__chevron-btn:focus-visible{outline:2px solid var(--color-primary);outline-offset:1px}.lc-table__chevron-btn--expanded{transform:rotate(90deg)}.lc-table__tree-content{flex:1 1 auto;min-width:0}.lc-table__row--group .lc-table__tree-content{font-weight:var(--typography-font-weight-semibold)}.lc-table__edit-input{width:100%;padding:var(--spacing-1) var(--spacing-2);border:2px solid var(--color-primary);border-radius:var(--border-radius-sm);font-size:inherit;background-color:var(--color-surface-2);color:var(--color-text-primary);outline:none}.lc-table-pagination{display:flex;align-items:center;justify-content:space-between;padding:var(--spacing-3) var(--spacing-1);font-size:var(--typography-font-size-sm);color:var(--color-text-secondary)}.lc-table-pagination__info{white-space:nowrap}.lc-table-pagination__controls{display:flex;align-items:center;gap:var(--spacing-2)}.lc-table-pagination__size{display:block;min-width:110px}.lc-table-pagination__btn{appearance:none;border:1px solid var(--color-border);background-color:var(--color-surface);color:var(--color-text-primary);width:28px;height:28px;display:flex;align-items:center;justify-content:center;border-radius:var(--border-radius-sm);font-size:var(--typography-font-size-base);cursor:pointer;transition:background-color .15s ease}.lc-table-pagination__btn:hover:not(:disabled){background-color:var(--color-surface-hover)}.lc-table-pagination__btn:disabled{opacity:.4;cursor:not-allowed}.lc-table-pagination__page{white-space:nowrap;min-width:60px;text-align:center}@media(max-width:640px){.lc-table-wrapper--stack .lc-table thead{display:none}.lc-table-wrapper--stack .lc-table tbody tr{display:block;margin-bottom:var(--spacing-4);border:1px solid var(--color-border);border-radius:var(--border-radius-md)}.lc-table-wrapper--stack .lc-table tbody tr td{display:block;text-align:right;padding:var(--spacing-2) var(--spacing-4);border-bottom:1px solid var(--color-divider)}.lc-table-wrapper--stack .lc-table tbody tr td:last-child{border-bottom:none}.lc-table-wrapper--stack .lc-table tbody tr td:before{content:attr(data-label);float:left;font-weight:var(--typography-font-weight-semibold);color:var(--color-text-secondary)}}\n"] }]
|
|
7519
7767
|
}], propDecorators: { cellTemplates: [{
|
|
7520
7768
|
type: ContentChildren,
|
|
7521
7769
|
args: [TableCellDirective]
|
|
7522
|
-
}], columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: false }] }], data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], hoverable: [{ type: i0.Input, args: [{ isSignal: true, alias: "hoverable", required: false }] }], responsive: [{ type: i0.Input, args: [{ isSignal: true, alias: "responsive", required: false }] }], emptyText: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyText", required: false }] }], paginate: [{ type: i0.Input, args: [{ isSignal: true, alias: "paginate", required: false }] }], pageSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageSize", required: false }] }], pageSizeOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageSizeOptions", required: false }] }], selectable: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectable", required: false }] }], filterable: [{ type: i0.Input, args: [{ isSignal: true, alias: "filterable", required: false }] }], editable: [{ type: i0.Input, args: [{ isSignal: true, alias: "editable", required: false }] }], actions: [{ type: i0.Input, args: [{ isSignal: true, alias: "actions", required: false }] }], actionsLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "actionsLabel", required: false }] }], actionsWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "actionsWidth", required: false }] }], actionsAlign: [{ type: i0.Input, args: [{ isSignal: true, alias: "actionsAlign", required: false }] }], sort: [{ type: i0.Output, args: ["sort"] }], rowClick: [{ type: i0.Output, args: ["rowClick"] }], cellEdit: [{ type: i0.Output, args: ["cellEdit"] }], selectionChange: [{ type: i0.Output, args: ["selectionChange"] }], actionClick: [{ type: i0.Output, args: ["actionClick"] }] } });
|
|
7770
|
+
}], columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: false }] }], data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], hoverable: [{ type: i0.Input, args: [{ isSignal: true, alias: "hoverable", required: false }] }], responsive: [{ type: i0.Input, args: [{ isSignal: true, alias: "responsive", required: false }] }], emptyText: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyText", required: false }] }], paginate: [{ type: i0.Input, args: [{ isSignal: true, alias: "paginate", required: false }] }], pageSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageSize", required: false }] }], pageSizeOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageSizeOptions", required: false }] }], selectable: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectable", required: false }] }], filterable: [{ type: i0.Input, args: [{ isSignal: true, alias: "filterable", required: false }] }], editable: [{ type: i0.Input, args: [{ isSignal: true, alias: "editable", required: false }] }], actions: [{ type: i0.Input, args: [{ isSignal: true, alias: "actions", required: false }] }], actionsLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "actionsLabel", required: false }] }], actionsWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "actionsWidth", required: false }] }], actionsAlign: [{ type: i0.Input, args: [{ isSignal: true, alias: "actionsAlign", required: false }] }], idKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "idKey", required: false }] }], parentKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "parentKey", required: false }] }], treeColumn: [{ type: i0.Input, args: [{ isSignal: true, alias: "treeColumn", required: false }] }], defaultExpanded: [{ type: i0.Input, args: [{ isSignal: true, alias: "defaultExpanded", required: false }] }], expandedIds: [{ type: i0.Input, args: [{ isSignal: true, alias: "expandedIds", required: false }] }], indentSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "indentSize", required: false }] }], sort: [{ type: i0.Output, args: ["sort"] }], rowClick: [{ type: i0.Output, args: ["rowClick"] }], cellEdit: [{ type: i0.Output, args: ["cellEdit"] }], selectionChange: [{ type: i0.Output, args: ["selectionChange"] }], actionClick: [{ type: i0.Output, args: ["actionClick"] }], rowToggle: [{ type: i0.Output, args: ["rowToggle"] }], expandedIdsChange: [{ type: i0.Output, args: ["expandedIdsChange"] }] } });
|
|
7523
7771
|
|
|
7524
7772
|
/**
|
|
7525
7773
|
* Field group component for displaying label-value pairs.
|