@egose/shadcn-theme-ng 0.6.0 → 0.6.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +119 -1
- package/autocomplete/fesm2022/autocomplete.mjs +14 -4
- package/autocomplete/types/autocomplete.d.ts +4 -1
- package/checkbox/README.md +6 -2
- package/checkbox/fesm2022/checkbox.mjs +11 -7
- package/checkbox/types/checkbox.d.ts +6 -4
- package/combobox/fesm2022/combobox.mjs +13 -7
- package/combobox/types/combobox.d.ts +8 -2
- package/data-table/README.md +11 -1
- package/data-table/fesm2022/data-table.mjs +64 -18
- package/data-table/types/data-table.d.ts +25 -6
- package/date-picker/README.md +41 -9
- package/date-picker/fesm2022/date-picker.mjs +265 -59
- package/date-picker/types/date-picker.d.ts +58 -27
- package/form-autocomplete/README.md +4 -2
- package/form-autocomplete/fesm2022/form-autocomplete.mjs +19 -6
- package/form-autocomplete/types/form-autocomplete.d.ts +9 -3
- package/form-combobox/README.md +4 -2
- package/form-combobox/fesm2022/form-combobox.mjs +23 -6
- package/form-combobox/types/form-combobox.d.ts +10 -3
- package/form-input-otp/README.md +7 -5
- package/form-input-otp/fesm2022/form-input-otp.mjs +20 -8
- package/form-input-otp/types/form-input-otp.d.ts +9 -3
- package/form-searchable-multiselect/README.md +15 -1
- package/form-searchable-multiselect/fesm2022/form-searchable-multiselect.mjs +15 -3
- package/form-searchable-multiselect/types/form-searchable-multiselect.d.ts +9 -1
- package/form-slider/README.md +3 -1
- package/form-slider/fesm2022/form-slider.mjs +19 -6
- package/form-slider/types/form-slider.d.ts +9 -3
- package/form-toggle/README.md +22 -18
- package/form-toggle/fesm2022/form-toggle.mjs +22 -9
- package/form-toggle/types/form-toggle.d.ts +6 -2
- package/input-otp/README.md +33 -9
- package/input-otp/fesm2022/input-otp.mjs +127 -11
- package/input-otp/types/input-otp.d.ts +24 -4
- package/package.json +1 -1
- package/pagination/README.md +21 -12
- package/pagination/fesm2022/pagination.mjs +73 -65
- package/pagination/types/pagination.d.ts +21 -8
- package/phone-input/README.md +16 -0
- package/phone-input/fesm2022/phone-input.mjs +41 -3
- package/phone-input/types/phone-input.d.ts +5 -2
- package/searchable-multiselect/README.md +62 -40
- package/searchable-multiselect/fesm2022/searchable-multiselect.mjs +59 -32
- package/searchable-multiselect/types/searchable-multiselect.d.ts +23 -6
- package/slider/fesm2022/slider.mjs +9 -5
- package/slider/types/slider.d.ts +6 -2
- package/stepper/README.md +39 -19
- package/stepper/fesm2022/stepper.mjs +64 -12
- package/stepper/types/stepper.d.ts +12 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { input, computed, ChangeDetectionStrategy, Component, model, output, signal, linkedSignal, effect, NgModule } from '@angular/core';
|
|
2
|
+
import { input, computed, ChangeDetectionStrategy, Component, model, output, signal, linkedSignal, effect, untracked, NgModule } from '@angular/core';
|
|
3
3
|
import { NgTemplateOutlet } from '@angular/common';
|
|
4
4
|
import { HlmButton } from '@egose/shadcn-theme-ng/button';
|
|
5
5
|
import { HlmCard, HlmCardContent } from '@egose/shadcn-theme-ng/card';
|
|
@@ -154,7 +154,7 @@ class EgDataTableViewOptions {
|
|
|
154
154
|
.filter((column) => typeof column.accessorFn !== 'undefined' && column.getCanHide()), /* @ts-ignore */
|
|
155
155
|
...(ngDevMode ? [{ debugName: "_hidableColumns" }] : /* istanbul ignore next */ []));
|
|
156
156
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: EgDataTableViewOptions, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
157
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.3", type: EgDataTableViewOptions, isStandalone: true, selector: "eg-data-table-view-options", inputs: { size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null } }, providers: [provideIcons({ lucideSettings2 })], ngImport: i0, template: "\n <button\n hlmButton\n variant=\"secondary\"\n appearance=\"outline\"\n size=\"sm\"\n [class]=\"_buttonClass()\"\n type=\"button\"\n [hlmDropdownMenuTrigger]=\"_menu\"\n >\n <ng-icon hlm name=\"lucideSettings2\" />\n View\n </button>\n <ng-template #_menu>\n <div hlmDropdownMenu class=\"w-[150px]\">\n <div hlmDropdownMenuLabel>Toggle columns</div>\n <div hlmDropdownMenuSeparator></div>\n @for (column of _hidableColumns(); track column.id) {\n <button\n hlmDropdownMenuCheckbox\n class=\"capitalize\"\n [checked]=\"column.getIsVisible()\"\n (triggered)=\"column.toggleVisibility()\"\n >\n <hlm-dropdown-menu-checkbox-indicator />\n {{ column.id }}\n </button>\n }\n </div>\n </ng-template>\n ", isInline: true, dependencies: [{ kind: "component", type: HlmButton, selector: "button[hlmButton], a[hlmButton]", inputs: ["variant", "size", "appearance", "loading", "icon", "iconPosition", "class", "spinnerUserClass", "disabled", "type"] }, { kind: "directive", type: i1$1.HlmDropdownMenu, selector: "[hlmDropdownMenu],hlm-dropdown-menu", inputs: ["sideOffset"] }, { kind: "directive", type: i1$1.HlmDropdownMenuCheckbox, selector: "[hlmDropdownMenuCheckbox],[hlmDropdownMenuCheckboxItem]", inputs: ["inset"] }, { kind: "component", type: i1$1.HlmDropdownMenuCheckboxIndicator, selector: "hlm-dropdown-menu-checkbox-indicator" }, { kind: "directive", type: i1$1.HlmDropdownMenuLabel, selector: "[hlmDropdownMenuLabel],hlm-dropdown-menu-label", inputs: ["inset"] }, { kind: "directive", type: i1$1.HlmDropdownMenuSeparator, selector: "[hlmDropdownMenuSeparator],hlm-dropdown-menu-separator" }, { kind: "directive", type: i1$1.HlmDropdownMenuTrigger, selector: "[hlmDropdownMenuTrigger]", inputs: ["align", "side"] }, { kind: "component", type: NgIcon, selector: "ng-icon", inputs: ["name", "svg", "size", "strokeWidth", "color"] }, { kind: "directive", type: HlmIcon, selector: "ng-icon[hlm]", inputs: ["size"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
157
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.3", type: EgDataTableViewOptions, isStandalone: true, selector: "eg-data-table-view-options", inputs: { size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null } }, providers: [provideIcons({ lucideSettings2 })], ngImport: i0, template: "\n <button\n hlmButton\n variant=\"secondary\"\n appearance=\"outline\"\n size=\"sm\"\n [class]=\"_buttonClass()\"\n type=\"button\"\n [hlmDropdownMenuTrigger]=\"_menu\"\n >\n <ng-icon hlm size=\"sm\" name=\"lucideSettings2\" />\n View\n </button>\n <ng-template #_menu>\n <div hlmDropdownMenu class=\"w-[150px]\">\n <div hlmDropdownMenuLabel>Toggle columns</div>\n <div hlmDropdownMenuSeparator></div>\n @for (column of _hidableColumns(); track column.id) {\n <button\n hlmDropdownMenuCheckbox\n class=\"capitalize\"\n [checked]=\"column.getIsVisible()\"\n (triggered)=\"column.toggleVisibility()\"\n >\n <hlm-dropdown-menu-checkbox-indicator />\n {{ column.id }}\n </button>\n }\n </div>\n </ng-template>\n ", isInline: true, dependencies: [{ kind: "component", type: HlmButton, selector: "button[hlmButton], a[hlmButton]", inputs: ["variant", "size", "appearance", "loading", "icon", "iconPosition", "class", "spinnerUserClass", "disabled", "type"] }, { kind: "directive", type: i1$1.HlmDropdownMenu, selector: "[hlmDropdownMenu],hlm-dropdown-menu", inputs: ["sideOffset"] }, { kind: "directive", type: i1$1.HlmDropdownMenuCheckbox, selector: "[hlmDropdownMenuCheckbox],[hlmDropdownMenuCheckboxItem]", inputs: ["inset"] }, { kind: "component", type: i1$1.HlmDropdownMenuCheckboxIndicator, selector: "hlm-dropdown-menu-checkbox-indicator" }, { kind: "directive", type: i1$1.HlmDropdownMenuLabel, selector: "[hlmDropdownMenuLabel],hlm-dropdown-menu-label", inputs: ["inset"] }, { kind: "directive", type: i1$1.HlmDropdownMenuSeparator, selector: "[hlmDropdownMenuSeparator],hlm-dropdown-menu-separator" }, { kind: "directive", type: i1$1.HlmDropdownMenuTrigger, selector: "[hlmDropdownMenuTrigger]", inputs: ["align", "side"] }, { kind: "component", type: NgIcon, selector: "ng-icon", inputs: ["name", "svg", "size", "strokeWidth", "color"] }, { kind: "directive", type: HlmIcon, selector: "ng-icon[hlm]", inputs: ["size"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
158
158
|
}
|
|
159
159
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: EgDataTableViewOptions, decorators: [{
|
|
160
160
|
type: Component,
|
|
@@ -162,7 +162,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImpor
|
|
|
162
162
|
selector: 'eg-data-table-view-options',
|
|
163
163
|
imports: [HlmButton, HlmDropdownMenuImports, NgIcon, HlmIcon],
|
|
164
164
|
providers: [provideIcons({ lucideSettings2 })],
|
|
165
|
-
template: "\n <button\n hlmButton\n variant=\"secondary\"\n appearance=\"outline\"\n size=\"sm\"\n [class]=\"_buttonClass()\"\n type=\"button\"\n [hlmDropdownMenuTrigger]=\"_menu\"\n >\n <ng-icon hlm name=\"lucideSettings2\" />\n View\n </button>\n <ng-template #_menu>\n <div hlmDropdownMenu class=\"w-[150px]\">\n <div hlmDropdownMenuLabel>Toggle columns</div>\n <div hlmDropdownMenuSeparator></div>\n @for (column of _hidableColumns(); track column.id) {\n <button\n hlmDropdownMenuCheckbox\n class=\"capitalize\"\n [checked]=\"column.getIsVisible()\"\n (triggered)=\"column.toggleVisibility()\"\n >\n <hlm-dropdown-menu-checkbox-indicator />\n {{ column.id }}\n </button>\n }\n </div>\n </ng-template>\n ",
|
|
165
|
+
template: "\n <button\n hlmButton\n variant=\"secondary\"\n appearance=\"outline\"\n size=\"sm\"\n [class]=\"_buttonClass()\"\n type=\"button\"\n [hlmDropdownMenuTrigger]=\"_menu\"\n >\n <ng-icon hlm size=\"sm\" name=\"lucideSettings2\" />\n View\n </button>\n <ng-template #_menu>\n <div hlmDropdownMenu class=\"w-[150px]\">\n <div hlmDropdownMenuLabel>Toggle columns</div>\n <div hlmDropdownMenuSeparator></div>\n @for (column of _hidableColumns(); track column.id) {\n <button\n hlmDropdownMenuCheckbox\n class=\"capitalize\"\n [checked]=\"column.getIsVisible()\"\n (triggered)=\"column.toggleVisibility()\"\n >\n <hlm-dropdown-menu-checkbox-indicator />\n {{ column.id }}\n </button>\n }\n </div>\n </ng-template>\n ",
|
|
166
166
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
167
167
|
}]
|
|
168
168
|
}], propDecorators: { size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }] } });
|
|
@@ -254,6 +254,16 @@ class EgDataTable {
|
|
|
254
254
|
/** Client rows, or a server page slice when `manualPagination` is set (`null` while loading). */
|
|
255
255
|
data = input([], /* @ts-ignore */
|
|
256
256
|
...(ngDevMode ? [{ debugName: "data" }] : /* istanbul ignore next */ []));
|
|
257
|
+
/**
|
|
258
|
+
* Pure stable identity callback, e.g. `(record) => record.id`. Return a unique
|
|
259
|
+
* string per entity, independent of position, and keep the callback reference stable.
|
|
260
|
+
* Selection survives refreshes only for IDs still in the supplied rows (after
|
|
261
|
+
* `filterRows`); server selection is limited to the loaded slice. Without this
|
|
262
|
+
* callback, IDs are positional and replacing the rows clears selection.
|
|
263
|
+
* Changing the callback clears selection. Update data immutably.
|
|
264
|
+
*/
|
|
265
|
+
getRowId = input(/* @ts-ignore */
|
|
266
|
+
...(ngDevMode ? [undefined, { debugName: "getRowId" }] : /* istanbul ignore next */ []));
|
|
257
267
|
/** When true, `data` is a server page slice and the table uses TanStack `manualPagination`. Sorting and filtering are then display-only: the slice is shown as-is while `sortingChange` / `filterChange` (`columnFiltersChange`) notify the caller to refetch. */
|
|
258
268
|
manualPagination = input(false, /* @ts-ignore */
|
|
259
269
|
...(ngDevMode ? [{ debugName: "manualPagination" }] : /* istanbul ignore next */ []));
|
|
@@ -286,7 +296,7 @@ class EgDataTable {
|
|
|
286
296
|
...(ngDevMode ? [{ debugName: "filterColumnId" }] : /* istanbul ignore next */ []));
|
|
287
297
|
filterPlaceholder = input('Filter...', /* @ts-ignore */
|
|
288
298
|
...(ngDevMode ? [{ debugName: "filterPlaceholder" }] : /* istanbul ignore next */ []));
|
|
289
|
-
/** Show the column-visibility dropdown inside the toolbar. Off by default; opt in per table. */
|
|
299
|
+
/** Show the column-visibility dropdown inside the toolbar (requires `showToolbar`). Off by default; opt in per table. Also enables hiding — the `Hide` item in `EgDataTableColumnHeader` only renders when this is true, so hidden columns always have a way back. Per-column `enableHiding: false` further disables individual columns. */
|
|
290
300
|
showColumnToggle = input(false, /* @ts-ignore */
|
|
291
301
|
...(ngDevMode ? [{ debugName: "showColumnToggle" }] : /* istanbul ignore next */ []));
|
|
292
302
|
/** Custom right-side toolbar content (e.g. action buttons) as a template. Renders the toolbar row even when `showToolbar` is false; built-ins stay on the left. */
|
|
@@ -307,7 +317,7 @@ class EgDataTable {
|
|
|
307
317
|
/** Seeds the column-visibility state once at creation. Later changes are ignored. */
|
|
308
318
|
initialColumnVisibility = input({}, /* @ts-ignore */
|
|
309
319
|
...(ngDevMode ? [{ debugName: "initialColumnVisibility" }] : /* istanbul ignore next */ []));
|
|
310
|
-
/** Seeds
|
|
320
|
+
/** Seeds selection once for current rows: keys come from `getRowId`, or positional indices without it. Missing IDs are discarded. Later changes are ignored. */
|
|
311
321
|
initialRowSelection = input({}, /* @ts-ignore */
|
|
312
322
|
...(ngDevMode ? [{ debugName: "initialRowSelection" }] : /* istanbul ignore next */ []));
|
|
313
323
|
/** Show the rows-per-page selector in the footer pager. */
|
|
@@ -320,7 +330,7 @@ class EgDataTable {
|
|
|
320
330
|
navMode = input('icons', /* @ts-ignore */
|
|
321
331
|
...(ngDevMode ? [{ debugName: "navMode" }] : /* istanbul ignore next */ []));
|
|
322
332
|
userClass = input('', { ...(ngDevMode ? { debugName: "userClass" } : /* istanbul ignore next */ {}), alias: 'class' });
|
|
323
|
-
/** Emits
|
|
333
|
+
/** Emits on init and when selected row identities/order or object references change. Includes rows hidden by built-in filters/client pagination, but never rows absent from `data`/`filterRows`. */
|
|
324
334
|
selectionChange = output();
|
|
325
335
|
/** Emits the target page index on pager navigation (primary hook for server fetching). */
|
|
326
336
|
pageChange = output();
|
|
@@ -343,8 +353,6 @@ class EgDataTable {
|
|
|
343
353
|
...(ngDevMode ? [{ debugName: "_columnFilters" }] : /* istanbul ignore next */ []));
|
|
344
354
|
_columnVisibility = signal({}, /* @ts-ignore */
|
|
345
355
|
...(ngDevMode ? [{ debugName: "_columnVisibility" }] : /* istanbul ignore next */ []));
|
|
346
|
-
_rowSelection = signal({}, /* @ts-ignore */
|
|
347
|
-
...(ngDevMode ? [{ debugName: "_rowSelection" }] : /* istanbul ignore next */ []));
|
|
348
356
|
_clientPageIndex = signal(0, /* @ts-ignore */
|
|
349
357
|
...(ngDevMode ? [{ debugName: "_clientPageIndex" }] : /* istanbul ignore next */ []));
|
|
350
358
|
// Linked so the bound `defaultPageSize` applies once inputs are set, while
|
|
@@ -376,6 +384,32 @@ class EgDataTable {
|
|
|
376
384
|
return filter ? filter(rows) : rows;
|
|
377
385
|
}, /* @ts-ignore */
|
|
378
386
|
...(ngDevMode ? [{ debugName: "_items" }] : /* istanbul ignore next */ []));
|
|
387
|
+
// TanStack uses data-reference changes to reset pagination. State/layout
|
|
388
|
+
// updates must not look like a new data set (including selecting page rows).
|
|
389
|
+
_tableItems = computed(() => {
|
|
390
|
+
// A different identity function must also rebuild TanStack's cached rows.
|
|
391
|
+
this.getRowId();
|
|
392
|
+
return [...this._items()];
|
|
393
|
+
}, /* @ts-ignore */
|
|
394
|
+
...(ngDevMode ? [{ debugName: "_tableItems" }] : /* istanbul ignore next */ []));
|
|
395
|
+
// Reconcile synchronously with the data source, before either TanStack or the
|
|
396
|
+
// output can observe old positional keys against new records. An effect-based
|
|
397
|
+
// reset would permit a transient wrong-entity selection.
|
|
398
|
+
_rowSelection = linkedSignal({ ...(ngDevMode ? { debugName: "_rowSelection" } : /* istanbul ignore next */ {}), source: () => ({ items: this._items(), getRowId: this.getRowId() }),
|
|
399
|
+
computation: (source, previous) => {
|
|
400
|
+
if (!previous || source.getRowId !== previous.source.getRowId)
|
|
401
|
+
return {};
|
|
402
|
+
if (!source.getRowId && source.items !== previous.source.items)
|
|
403
|
+
return {};
|
|
404
|
+
return this._keepCurrentSelection(previous.value);
|
|
405
|
+
} });
|
|
406
|
+
_keepCurrentSelection(selection) {
|
|
407
|
+
const getRowId = this.getRowId();
|
|
408
|
+
return Object.fromEntries(this._items()
|
|
409
|
+
.map((row, index) => (getRowId ? getRowId(row) : String(index)))
|
|
410
|
+
.filter((id) => Object.hasOwn(selection, id) && selection[id])
|
|
411
|
+
.map((id) => [id, true]));
|
|
412
|
+
}
|
|
379
413
|
_serverPageCount = computed(() => {
|
|
380
414
|
const paginated = this._page();
|
|
381
415
|
if (!paginated || paginated.limit <= 0)
|
|
@@ -422,7 +456,12 @@ class EgDataTable {
|
|
|
422
456
|
return {
|
|
423
457
|
features: this.features(),
|
|
424
458
|
columns: this._finalColumns(),
|
|
425
|
-
data:
|
|
459
|
+
data: this._tableItems(),
|
|
460
|
+
getRowId: this.getRowId(),
|
|
461
|
+
// Hiding is only allowed when the View menu can bring columns back.
|
|
462
|
+
// This drives `column.getCanHide()` for both `EgDataTableColumnHeader`
|
|
463
|
+
// (Hide item) and `EgDataTableViewOptions` (toggle list).
|
|
464
|
+
enableHiding: this.showColumnToggle(),
|
|
426
465
|
manualPagination: server,
|
|
427
466
|
manualSorting: server,
|
|
428
467
|
manualFiltering: server,
|
|
@@ -472,10 +511,11 @@ class EgDataTable {
|
|
|
472
511
|
},
|
|
473
512
|
};
|
|
474
513
|
});
|
|
514
|
+
_selectedRows = computed(() => this._table.getSelectedRowModel().rows.map((row) => row.original), { ...(ngDevMode ? { debugName: "_selectedRows" } : /* istanbul ignore next */ {}), equal: (a, b) => a.length === b.length && a.every((row, index) => row === b[index]) });
|
|
475
515
|
_emitSelection = effect(() => {
|
|
476
|
-
this.
|
|
477
|
-
|
|
478
|
-
this.selectionChange.emit(selected);
|
|
516
|
+
const selected = this._selectedRows();
|
|
517
|
+
// Consumer handlers may read signals; those reads must not retrigger us.
|
|
518
|
+
untracked(() => this.selectionChange.emit(selected));
|
|
479
519
|
}, /* @ts-ignore */
|
|
480
520
|
...(ngDevMode ? [{ debugName: "_emitSelection" }] : /* istanbul ignore next */ []));
|
|
481
521
|
/**
|
|
@@ -488,7 +528,7 @@ class EgDataTable {
|
|
|
488
528
|
this._sorting.set([...this.initialSorting()]);
|
|
489
529
|
this._columnFilters.set([...this.initialColumnFilters()]);
|
|
490
530
|
this._columnVisibility.set({ ...this.initialColumnVisibility() });
|
|
491
|
-
this._rowSelection.set(
|
|
531
|
+
this._rowSelection.set(this._keepCurrentSelection(this.initialRowSelection()));
|
|
492
532
|
}
|
|
493
533
|
_hasGrid = computed(() => this.gridColumns() !== undefined, /* @ts-ignore */
|
|
494
534
|
...(ngDevMode ? [{ debugName: "_hasGrid" }] : /* istanbul ignore next */ []));
|
|
@@ -568,7 +608,7 @@ class EgDataTable {
|
|
|
568
608
|
return cell.column.id.replace(/_/g, ' ');
|
|
569
609
|
}
|
|
570
610
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: EgDataTable, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
571
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.3", type: EgDataTable, isStandalone: true, selector: "eg-data-table", inputs: { columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: true, transformFunction: null }, gridColumns: { classPropertyName: "gridColumns", publicName: "gridColumns", isSignal: true, isRequired: false, transformFunction: null }, data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, manualPagination: { classPropertyName: "manualPagination", publicName: "manualPagination", isSignal: true, isRequired: false, transformFunction: null }, features: { classPropertyName: "features", publicName: "features", isSignal: true, isRequired: false, transformFunction: null }, isLoading: { classPropertyName: "isLoading", publicName: "isLoading", isSignal: true, isRequired: false, transformFunction: null }, emptyMessage: { classPropertyName: "emptyMessage", publicName: "emptyMessage", isSignal: true, isRequired: false, transformFunction: null }, enableSelection: { classPropertyName: "enableSelection", publicName: "enableSelection", isSignal: true, isRequired: false, transformFunction: null }, hideFooter: { classPropertyName: "hideFooter", publicName: "hideFooter", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, layout: { classPropertyName: "layout", publicName: "layout", isSignal: true, isRequired: false, transformFunction: null }, showLayoutToggle: { classPropertyName: "showLayoutToggle", publicName: "showLayoutToggle", isSignal: true, isRequired: false, transformFunction: null }, showToolbar: { classPropertyName: "showToolbar", publicName: "showToolbar", isSignal: true, isRequired: false, transformFunction: null }, filterColumnId: { classPropertyName: "filterColumnId", publicName: "filterColumnId", isSignal: true, isRequired: false, transformFunction: null }, filterPlaceholder: { classPropertyName: "filterPlaceholder", publicName: "filterPlaceholder", isSignal: true, isRequired: false, transformFunction: null }, showColumnToggle: { classPropertyName: "showColumnToggle", publicName: "showColumnToggle", isSignal: true, isRequired: false, transformFunction: null }, toolbarActions: { classPropertyName: "toolbarActions", publicName: "toolbarActions", isSignal: true, isRequired: false, transformFunction: null }, defaultPageSize: { classPropertyName: "defaultPageSize", publicName: "defaultPageSize", isSignal: true, isRequired: false, transformFunction: null }, filterRows: { classPropertyName: "filterRows", publicName: "filterRows", isSignal: true, isRequired: false, transformFunction: null }, initialSorting: { classPropertyName: "initialSorting", publicName: "initialSorting", isSignal: true, isRequired: false, transformFunction: null }, initialColumnFilters: { classPropertyName: "initialColumnFilters", publicName: "initialColumnFilters", isSignal: true, isRequired: false, transformFunction: null }, initialColumnVisibility: { classPropertyName: "initialColumnVisibility", publicName: "initialColumnVisibility", isSignal: true, isRequired: false, transformFunction: null }, initialRowSelection: { classPropertyName: "initialRowSelection", publicName: "initialRowSelection", isSignal: true, isRequired: false, transformFunction: null }, showPageSize: { classPropertyName: "showPageSize", publicName: "showPageSize", isSignal: true, isRequired: false, transformFunction: null }, pageSizes: { classPropertyName: "pageSizes", publicName: "pageSizes", isSignal: true, isRequired: false, transformFunction: null }, navMode: { classPropertyName: "navMode", publicName: "navMode", isSignal: true, isRequired: false, transformFunction: null }, userClass: { classPropertyName: "userClass", publicName: "class", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { layout: "layoutChange", selectionChange: "selectionChange", pageChange: "pageChange", pageSizeChange: "pageSizeChange", rowClick: "rowClick", sortingChange: "sortingChange", columnFiltersChange: "columnFiltersChange", filterChange: "filterChange", columnVisibilityChange: "columnVisibilityChange" }, providers: [
|
|
611
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.3", type: EgDataTable, isStandalone: true, selector: "eg-data-table", inputs: { columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: true, transformFunction: null }, gridColumns: { classPropertyName: "gridColumns", publicName: "gridColumns", isSignal: true, isRequired: false, transformFunction: null }, data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, getRowId: { classPropertyName: "getRowId", publicName: "getRowId", isSignal: true, isRequired: false, transformFunction: null }, manualPagination: { classPropertyName: "manualPagination", publicName: "manualPagination", isSignal: true, isRequired: false, transformFunction: null }, features: { classPropertyName: "features", publicName: "features", isSignal: true, isRequired: false, transformFunction: null }, isLoading: { classPropertyName: "isLoading", publicName: "isLoading", isSignal: true, isRequired: false, transformFunction: null }, emptyMessage: { classPropertyName: "emptyMessage", publicName: "emptyMessage", isSignal: true, isRequired: false, transformFunction: null }, enableSelection: { classPropertyName: "enableSelection", publicName: "enableSelection", isSignal: true, isRequired: false, transformFunction: null }, hideFooter: { classPropertyName: "hideFooter", publicName: "hideFooter", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, layout: { classPropertyName: "layout", publicName: "layout", isSignal: true, isRequired: false, transformFunction: null }, showLayoutToggle: { classPropertyName: "showLayoutToggle", publicName: "showLayoutToggle", isSignal: true, isRequired: false, transformFunction: null }, showToolbar: { classPropertyName: "showToolbar", publicName: "showToolbar", isSignal: true, isRequired: false, transformFunction: null }, filterColumnId: { classPropertyName: "filterColumnId", publicName: "filterColumnId", isSignal: true, isRequired: false, transformFunction: null }, filterPlaceholder: { classPropertyName: "filterPlaceholder", publicName: "filterPlaceholder", isSignal: true, isRequired: false, transformFunction: null }, showColumnToggle: { classPropertyName: "showColumnToggle", publicName: "showColumnToggle", isSignal: true, isRequired: false, transformFunction: null }, toolbarActions: { classPropertyName: "toolbarActions", publicName: "toolbarActions", isSignal: true, isRequired: false, transformFunction: null }, defaultPageSize: { classPropertyName: "defaultPageSize", publicName: "defaultPageSize", isSignal: true, isRequired: false, transformFunction: null }, filterRows: { classPropertyName: "filterRows", publicName: "filterRows", isSignal: true, isRequired: false, transformFunction: null }, initialSorting: { classPropertyName: "initialSorting", publicName: "initialSorting", isSignal: true, isRequired: false, transformFunction: null }, initialColumnFilters: { classPropertyName: "initialColumnFilters", publicName: "initialColumnFilters", isSignal: true, isRequired: false, transformFunction: null }, initialColumnVisibility: { classPropertyName: "initialColumnVisibility", publicName: "initialColumnVisibility", isSignal: true, isRequired: false, transformFunction: null }, initialRowSelection: { classPropertyName: "initialRowSelection", publicName: "initialRowSelection", isSignal: true, isRequired: false, transformFunction: null }, showPageSize: { classPropertyName: "showPageSize", publicName: "showPageSize", isSignal: true, isRequired: false, transformFunction: null }, pageSizes: { classPropertyName: "pageSizes", publicName: "pageSizes", isSignal: true, isRequired: false, transformFunction: null }, navMode: { classPropertyName: "navMode", publicName: "navMode", isSignal: true, isRequired: false, transformFunction: null }, userClass: { classPropertyName: "userClass", publicName: "class", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { layout: "layoutChange", selectionChange: "selectionChange", pageChange: "pageChange", pageSizeChange: "pageSizeChange", rowClick: "rowClick", sortingChange: "sortingChange", columnFiltersChange: "columnFiltersChange", filterChange: "filterChange", columnVisibilityChange: "columnVisibilityChange" }, providers: [
|
|
572
612
|
provideIcons({ lucideArrowDown, lucideArrowUp, lucideChevronsUpDown, lucideLayoutGrid, lucideLayoutList }),
|
|
573
613
|
], ngImport: i0, template: "\n <div [class]=\"_containerClass()\">\n @if (_showLayoutToggle()) {\n <div class=\"flex items-center justify-between\">\n <div hlmToggleGroup type=\"single\" [value]=\"_effectiveLayout()\" (valueChange)=\"_onLayoutToggle($event)\">\n <button hlmToggleGroupItem value=\"table\" aria-label=\"Table view\">\n <ng-icon hlm name=\"lucideLayoutList\" />\n </button>\n <button hlmToggleGroupItem value=\"grid\" aria-label=\"Grid view\">\n <ng-icon hlm name=\"lucideLayoutGrid\" />\n </button>\n </div>\n <div></div>\n </div>\n }\n\n @if (showToolbar() || toolbarActions()) {\n <div class=\"flex flex-wrap items-center justify-between gap-2 py-1\" [tanStackTable]=\"_table\">\n @if (showToolbar()) {\n <div class=\"flex flex-wrap items-center gap-2\">\n <input\n hlmInput\n class=\"w-full min-w-0 md:w-80\"\n [size]=\"size()\"\n [placeholder]=\"filterPlaceholder()\"\n (input)=\"_onFilterInput($event)\"\n />\n @if (showColumnToggle()) {\n <eg-data-table-view-options [size]=\"size()\" />\n }\n </div>\n }\n @if (toolbarActions()) {\n <div class=\"flex flex-wrap items-center gap-2\">\n <ng-container *ngTemplateOutlet=\"toolbarActions()\" />\n </div>\n }\n </div>\n }\n\n @if (_effectiveLayout() === 'grid') {\n <ng-container *ngTemplateOutlet=\"_gridView\" />\n } @else {\n <ng-container *ngTemplateOutlet=\"_tableView\" />\n }\n\n <ng-template #_tableView>\n <div class=\"overflow-hidden rounded-md border\">\n <div hlmTableContainer>\n <table hlmTable>\n <thead hlmTHead>\n @for (headerGroup of _table.getHeaderGroups(); track headerGroup.id) {\n <tr hlmTr>\n @for (header of headerGroup.headers; track header.id) {\n <th hlmTh [size]=\"size()\" [attr.colSpan]=\"header.colSpan\">\n @if (!header.isPlaceholder) {\n <div class=\"flex items-center gap-1\">\n <ng-container\n *flexRender=\"header.column.columnDef.header; props: header.getContext(); let headerText\"\n >\n <div [innerHTML]=\"headerText\"></div>\n </ng-container>\n @if (_showHeaderSortButton(header)) {\n <button\n hlmButton\n variant=\"ghost\"\n size=\"sm\"\n [class]=\"_sortButtonClass()\"\n type=\"button\"\n [attr.aria-label]=\"'Sort by ' + header.column.id\"\n (click)=\"_toggleHeaderSorting(header)\"\n >\n @switch (header.column.getIsSorted()) {\n @case ('asc') {\n <ng-icon hlm size=\"sm\" name=\"lucideArrowUp\" />\n }\n @case ('desc') {\n <ng-icon hlm size=\"sm\" name=\"lucideArrowDown\" />\n }\n @default {\n <ng-icon hlm size=\"sm\" name=\"lucideChevronsUpDown\" />\n }\n }\n </button>\n }\n </div>\n }\n </th>\n }\n </tr>\n }\n </thead>\n <tbody hlmTBody>\n @if (isLoading()) {\n <tr hlmTr>\n <td hlmTd [attr.colspan]=\"_visibleColumnCount()\" class=\"h-24 text-center\">\n <hlm-spinner class=\"inline-flex\" />\n </td>\n </tr>\n } @else if (_table.getRowModel().rows.length === 0) {\n <tr hlmTr>\n <td hlmTd [attr.colspan]=\"_visibleColumnCount()\" class=\"h-24 text-center\">\n {{ emptyMessage() }}\n </td>\n </tr>\n } @else {\n @for (row of _table.getRowModel().rows; track row.id) {\n <tr\n hlmTr\n [attr.data-state]=\"row.getIsSelected() ? 'selected' : null\"\n (click)=\"_onRowClick($event, row)\"\n >\n @for (cell of row.getVisibleCells(); track cell.id) {\n <td hlmTd [size]=\"size()\">\n <ng-container\n *flexRender=\"cell.column.columnDef.cell; props: cell.getContext(); let cellText\"\n >\n <div [innerHTML]=\"cellText\"></div>\n </ng-container>\n </td>\n }\n </tr>\n }\n }\n </tbody>\n </table>\n </div>\n </div>\n </ng-template>\n\n <ng-template #_gridView>\n @if (isLoading()) {\n <div\n class=\"flex h-64 items-center justify-center rounded-lg border border-dashed\"\n role=\"status\"\n >\n <hlm-spinner />\n </div>\n } @else if (_table.getRowModel().rows.length === 0) {\n <div\n class=\"text-muted-foreground flex h-64 items-center justify-center rounded-lg border border-dashed\"\n >\n {{ emptyMessage() }}\n </div>\n } @else {\n <div class=\"grid grid-cols-1 gap-4 md:grid-cols-2 xl:grid-cols-3 2xl:grid-cols-4\">\n @for (row of _table.getRowModel().rows; track row.id) {\n <div\n hlmCard\n class=\"group relative transition-all hover:shadow-md data-[state=selected]:border-primary data-[state=selected]:ring-1 data-[state=selected]:ring-primary/20\"\n [attr.data-state]=\"row.getIsSelected() ? 'selected' : null\"\n (click)=\"_onRowClick($event, row)\"\n >\n @if (_thumbnailCell(row); as thumbnail) {\n <div class=\"border-b bg-muted/30\">\n <ng-container\n *flexRender=\"thumbnail.column.columnDef.cell; props: thumbnail.getContext(); let thumbHtml\"\n >\n <div [innerHTML]=\"thumbHtml\"></div>\n </ng-container>\n </div>\n }\n @if (_selectionCell(row); as selection) {\n <div class=\"absolute top-4 right-4\">\n <ng-container\n *flexRender=\"selection.column.columnDef.cell; props: selection.getContext(); let selectHtml\"\n >\n <div [innerHTML]=\"selectHtml\"></div>\n </ng-container>\n </div>\n }\n <div hlmCardContent class=\"space-y-3\">\n @for (cell of _contentCells(row); track cell.id) {\n <div class=\"flex flex-col\">\n <dt\n class=\"text-[10px] font-bold tracking-wider uppercase text-muted-foreground/80\"\n >\n {{ _cellLabel(cell) }}\n </dt>\n <dd class=\"mt-0.5 text-sm leading-none font-medium\">\n <ng-container *flexRender=\"cell.column.columnDef.cell; props: cell.getContext(); let valueHtml\">\n <div [innerHTML]=\"valueHtml\"></div>\n </ng-container>\n </dd>\n </div>\n }\n </div>\n </div>\n }\n </div>\n }\n </ng-template>\n\n @if (!hideFooter()) {\n <div\n class=\"flex flex-col gap-2 px-2 py-4 sm:flex-row sm:items-center sm:justify-between\"\n [tanStackTable]=\"_table\"\n >\n <div class=\"text-muted-foreground flex-1 text-sm\">{{ _statusText() }}</div>\n <eg-data-table-pagination\n [showStatus]=\"false\"\n [showPageSize]=\"showPageSize()\"\n [pageSizes]=\"pageSizes()\"\n [navMode]=\"navMode()\"\n [size]=\"size()\"\n />\n </div>\n }\n </div>\n ", isInline: true, dependencies: [{ kind: "directive", type: i1$2.FlexRenderDirective, selector: "ng-template[flexRender]", inputs: ["flexRender", "flexRenderProps", "flexRenderInjector"] }, { kind: "directive", type: TanStackTable, selector: "[tanStackTable]", inputs: ["tanStackTable"], exportAs: ["table"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i2.HlmTableContainer, selector: "div[hlmTableContainer]" }, { kind: "directive", type: i2.HlmTable, selector: "table[hlmTable]" }, { kind: "directive", type: i2.HlmTBody, selector: "tbody[hlmTBody],tbody[hlmTableBody]" }, { kind: "directive", type: i2.HlmTd, selector: "td[hlmTd],td[hlmTableCell]", inputs: ["size"] }, { kind: "directive", type: i2.HlmTh, selector: "th[hlmTh],th[hlmTableHead]", inputs: ["size"] }, { kind: "directive", type: i2.HlmTHead, selector: "thead[hlmTHead],thead[hlmTableHeader]" }, { kind: "directive", type: i2.HlmTr, selector: "tr[hlmTr],tr[hlmTableRow]" }, { kind: "component", type: HlmButton, selector: "button[hlmButton], a[hlmButton]", inputs: ["variant", "size", "appearance", "loading", "icon", "iconPosition", "class", "spinnerUserClass", "disabled", "type"] }, { kind: "directive", type: HlmCard, selector: "[hlmCard],hlm-card", inputs: ["size"] }, { kind: "directive", type: HlmCardContent, selector: "[hlmCardContent]" }, { kind: "directive", type: HlmIcon, selector: "ng-icon[hlm]", inputs: ["size"] }, { kind: "directive", type: HlmInput, selector: "[hlmInput]", inputs: ["ariaDescribedby", "size"] }, { kind: "component", type: HlmSpinner, selector: "hlm-spinner", inputs: ["size", "show", "class", "spinnerClass"] }, { kind: "directive", type: HlmToggleGroup, selector: "[hlmToggleGroup],hlm-toggle-group", inputs: ["variant", "size", "spacing", "orientation"] }, { kind: "directive", type: HlmToggleGroupItem, selector: "button[hlmToggleGroupItem]", inputs: ["variant", "size"] }, { kind: "component", type: NgIcon, selector: "ng-icon", inputs: ["name", "svg", "size", "strokeWidth", "color"] }, { kind: "component", type: EgDataTablePagination, selector: "eg-data-table-pagination", inputs: ["showStatus", "showPageSize", "pageSizes", "navMode", "size"] }, { kind: "component", type: EgDataTableViewOptions, selector: "eg-data-table-view-options", inputs: ["size"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
574
614
|
}
|
|
@@ -599,14 +639,17 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImpor
|
|
|
599
639
|
template: "\n <div [class]=\"_containerClass()\">\n @if (_showLayoutToggle()) {\n <div class=\"flex items-center justify-between\">\n <div hlmToggleGroup type=\"single\" [value]=\"_effectiveLayout()\" (valueChange)=\"_onLayoutToggle($event)\">\n <button hlmToggleGroupItem value=\"table\" aria-label=\"Table view\">\n <ng-icon hlm name=\"lucideLayoutList\" />\n </button>\n <button hlmToggleGroupItem value=\"grid\" aria-label=\"Grid view\">\n <ng-icon hlm name=\"lucideLayoutGrid\" />\n </button>\n </div>\n <div></div>\n </div>\n }\n\n @if (showToolbar() || toolbarActions()) {\n <div class=\"flex flex-wrap items-center justify-between gap-2 py-1\" [tanStackTable]=\"_table\">\n @if (showToolbar()) {\n <div class=\"flex flex-wrap items-center gap-2\">\n <input\n hlmInput\n class=\"w-full min-w-0 md:w-80\"\n [size]=\"size()\"\n [placeholder]=\"filterPlaceholder()\"\n (input)=\"_onFilterInput($event)\"\n />\n @if (showColumnToggle()) {\n <eg-data-table-view-options [size]=\"size()\" />\n }\n </div>\n }\n @if (toolbarActions()) {\n <div class=\"flex flex-wrap items-center gap-2\">\n <ng-container *ngTemplateOutlet=\"toolbarActions()\" />\n </div>\n }\n </div>\n }\n\n @if (_effectiveLayout() === 'grid') {\n <ng-container *ngTemplateOutlet=\"_gridView\" />\n } @else {\n <ng-container *ngTemplateOutlet=\"_tableView\" />\n }\n\n <ng-template #_tableView>\n <div class=\"overflow-hidden rounded-md border\">\n <div hlmTableContainer>\n <table hlmTable>\n <thead hlmTHead>\n @for (headerGroup of _table.getHeaderGroups(); track headerGroup.id) {\n <tr hlmTr>\n @for (header of headerGroup.headers; track header.id) {\n <th hlmTh [size]=\"size()\" [attr.colSpan]=\"header.colSpan\">\n @if (!header.isPlaceholder) {\n <div class=\"flex items-center gap-1\">\n <ng-container\n *flexRender=\"header.column.columnDef.header; props: header.getContext(); let headerText\"\n >\n <div [innerHTML]=\"headerText\"></div>\n </ng-container>\n @if (_showHeaderSortButton(header)) {\n <button\n hlmButton\n variant=\"ghost\"\n size=\"sm\"\n [class]=\"_sortButtonClass()\"\n type=\"button\"\n [attr.aria-label]=\"'Sort by ' + header.column.id\"\n (click)=\"_toggleHeaderSorting(header)\"\n >\n @switch (header.column.getIsSorted()) {\n @case ('asc') {\n <ng-icon hlm size=\"sm\" name=\"lucideArrowUp\" />\n }\n @case ('desc') {\n <ng-icon hlm size=\"sm\" name=\"lucideArrowDown\" />\n }\n @default {\n <ng-icon hlm size=\"sm\" name=\"lucideChevronsUpDown\" />\n }\n }\n </button>\n }\n </div>\n }\n </th>\n }\n </tr>\n }\n </thead>\n <tbody hlmTBody>\n @if (isLoading()) {\n <tr hlmTr>\n <td hlmTd [attr.colspan]=\"_visibleColumnCount()\" class=\"h-24 text-center\">\n <hlm-spinner class=\"inline-flex\" />\n </td>\n </tr>\n } @else if (_table.getRowModel().rows.length === 0) {\n <tr hlmTr>\n <td hlmTd [attr.colspan]=\"_visibleColumnCount()\" class=\"h-24 text-center\">\n {{ emptyMessage() }}\n </td>\n </tr>\n } @else {\n @for (row of _table.getRowModel().rows; track row.id) {\n <tr\n hlmTr\n [attr.data-state]=\"row.getIsSelected() ? 'selected' : null\"\n (click)=\"_onRowClick($event, row)\"\n >\n @for (cell of row.getVisibleCells(); track cell.id) {\n <td hlmTd [size]=\"size()\">\n <ng-container\n *flexRender=\"cell.column.columnDef.cell; props: cell.getContext(); let cellText\"\n >\n <div [innerHTML]=\"cellText\"></div>\n </ng-container>\n </td>\n }\n </tr>\n }\n }\n </tbody>\n </table>\n </div>\n </div>\n </ng-template>\n\n <ng-template #_gridView>\n @if (isLoading()) {\n <div\n class=\"flex h-64 items-center justify-center rounded-lg border border-dashed\"\n role=\"status\"\n >\n <hlm-spinner />\n </div>\n } @else if (_table.getRowModel().rows.length === 0) {\n <div\n class=\"text-muted-foreground flex h-64 items-center justify-center rounded-lg border border-dashed\"\n >\n {{ emptyMessage() }}\n </div>\n } @else {\n <div class=\"grid grid-cols-1 gap-4 md:grid-cols-2 xl:grid-cols-3 2xl:grid-cols-4\">\n @for (row of _table.getRowModel().rows; track row.id) {\n <div\n hlmCard\n class=\"group relative transition-all hover:shadow-md data-[state=selected]:border-primary data-[state=selected]:ring-1 data-[state=selected]:ring-primary/20\"\n [attr.data-state]=\"row.getIsSelected() ? 'selected' : null\"\n (click)=\"_onRowClick($event, row)\"\n >\n @if (_thumbnailCell(row); as thumbnail) {\n <div class=\"border-b bg-muted/30\">\n <ng-container\n *flexRender=\"thumbnail.column.columnDef.cell; props: thumbnail.getContext(); let thumbHtml\"\n >\n <div [innerHTML]=\"thumbHtml\"></div>\n </ng-container>\n </div>\n }\n @if (_selectionCell(row); as selection) {\n <div class=\"absolute top-4 right-4\">\n <ng-container\n *flexRender=\"selection.column.columnDef.cell; props: selection.getContext(); let selectHtml\"\n >\n <div [innerHTML]=\"selectHtml\"></div>\n </ng-container>\n </div>\n }\n <div hlmCardContent class=\"space-y-3\">\n @for (cell of _contentCells(row); track cell.id) {\n <div class=\"flex flex-col\">\n <dt\n class=\"text-[10px] font-bold tracking-wider uppercase text-muted-foreground/80\"\n >\n {{ _cellLabel(cell) }}\n </dt>\n <dd class=\"mt-0.5 text-sm leading-none font-medium\">\n <ng-container *flexRender=\"cell.column.columnDef.cell; props: cell.getContext(); let valueHtml\">\n <div [innerHTML]=\"valueHtml\"></div>\n </ng-container>\n </dd>\n </div>\n }\n </div>\n </div>\n }\n </div>\n }\n </ng-template>\n\n @if (!hideFooter()) {\n <div\n class=\"flex flex-col gap-2 px-2 py-4 sm:flex-row sm:items-center sm:justify-between\"\n [tanStackTable]=\"_table\"\n >\n <div class=\"text-muted-foreground flex-1 text-sm\">{{ _statusText() }}</div>\n <eg-data-table-pagination\n [showStatus]=\"false\"\n [showPageSize]=\"showPageSize()\"\n [pageSizes]=\"pageSizes()\"\n [navMode]=\"navMode()\"\n [size]=\"size()\"\n />\n </div>\n }\n </div>\n ",
|
|
600
640
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
601
641
|
}]
|
|
602
|
-
}], propDecorators: { columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: true }] }], gridColumns: [{ type: i0.Input, args: [{ isSignal: true, alias: "gridColumns", required: false }] }], data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], manualPagination: [{ type: i0.Input, args: [{ isSignal: true, alias: "manualPagination", required: false }] }], features: [{ type: i0.Input, args: [{ isSignal: true, alias: "features", required: false }] }], isLoading: [{ type: i0.Input, args: [{ isSignal: true, alias: "isLoading", required: false }] }], emptyMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyMessage", required: false }] }], enableSelection: [{ type: i0.Input, args: [{ isSignal: true, alias: "enableSelection", required: false }] }], hideFooter: [{ type: i0.Input, args: [{ isSignal: true, alias: "hideFooter", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], layout: [{ type: i0.Input, args: [{ isSignal: true, alias: "layout", required: false }] }, { type: i0.Output, args: ["layoutChange"] }], showLayoutToggle: [{ type: i0.Input, args: [{ isSignal: true, alias: "showLayoutToggle", required: false }] }], showToolbar: [{ type: i0.Input, args: [{ isSignal: true, alias: "showToolbar", required: false }] }], filterColumnId: [{ type: i0.Input, args: [{ isSignal: true, alias: "filterColumnId", required: false }] }], filterPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "filterPlaceholder", required: false }] }], showColumnToggle: [{ type: i0.Input, args: [{ isSignal: true, alias: "showColumnToggle", required: false }] }], toolbarActions: [{ type: i0.Input, args: [{ isSignal: true, alias: "toolbarActions", required: false }] }], defaultPageSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "defaultPageSize", required: false }] }], filterRows: [{ type: i0.Input, args: [{ isSignal: true, alias: "filterRows", required: false }] }], initialSorting: [{ type: i0.Input, args: [{ isSignal: true, alias: "initialSorting", required: false }] }], initialColumnFilters: [{ type: i0.Input, args: [{ isSignal: true, alias: "initialColumnFilters", required: false }] }], initialColumnVisibility: [{ type: i0.Input, args: [{ isSignal: true, alias: "initialColumnVisibility", required: false }] }], initialRowSelection: [{ type: i0.Input, args: [{ isSignal: true, alias: "initialRowSelection", required: false }] }], showPageSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "showPageSize", required: false }] }], pageSizes: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageSizes", required: false }] }], navMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "navMode", required: false }] }], userClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }], selectionChange: [{ type: i0.Output, args: ["selectionChange"] }], pageChange: [{ type: i0.Output, args: ["pageChange"] }], pageSizeChange: [{ type: i0.Output, args: ["pageSizeChange"] }], rowClick: [{ type: i0.Output, args: ["rowClick"] }], sortingChange: [{ type: i0.Output, args: ["sortingChange"] }], columnFiltersChange: [{ type: i0.Output, args: ["columnFiltersChange"] }], filterChange: [{ type: i0.Output, args: ["filterChange"] }], columnVisibilityChange: [{ type: i0.Output, args: ["columnVisibilityChange"] }] } });
|
|
642
|
+
}], propDecorators: { columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: true }] }], gridColumns: [{ type: i0.Input, args: [{ isSignal: true, alias: "gridColumns", required: false }] }], data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], getRowId: [{ type: i0.Input, args: [{ isSignal: true, alias: "getRowId", required: false }] }], manualPagination: [{ type: i0.Input, args: [{ isSignal: true, alias: "manualPagination", required: false }] }], features: [{ type: i0.Input, args: [{ isSignal: true, alias: "features", required: false }] }], isLoading: [{ type: i0.Input, args: [{ isSignal: true, alias: "isLoading", required: false }] }], emptyMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyMessage", required: false }] }], enableSelection: [{ type: i0.Input, args: [{ isSignal: true, alias: "enableSelection", required: false }] }], hideFooter: [{ type: i0.Input, args: [{ isSignal: true, alias: "hideFooter", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], layout: [{ type: i0.Input, args: [{ isSignal: true, alias: "layout", required: false }] }, { type: i0.Output, args: ["layoutChange"] }], showLayoutToggle: [{ type: i0.Input, args: [{ isSignal: true, alias: "showLayoutToggle", required: false }] }], showToolbar: [{ type: i0.Input, args: [{ isSignal: true, alias: "showToolbar", required: false }] }], filterColumnId: [{ type: i0.Input, args: [{ isSignal: true, alias: "filterColumnId", required: false }] }], filterPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "filterPlaceholder", required: false }] }], showColumnToggle: [{ type: i0.Input, args: [{ isSignal: true, alias: "showColumnToggle", required: false }] }], toolbarActions: [{ type: i0.Input, args: [{ isSignal: true, alias: "toolbarActions", required: false }] }], defaultPageSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "defaultPageSize", required: false }] }], filterRows: [{ type: i0.Input, args: [{ isSignal: true, alias: "filterRows", required: false }] }], initialSorting: [{ type: i0.Input, args: [{ isSignal: true, alias: "initialSorting", required: false }] }], initialColumnFilters: [{ type: i0.Input, args: [{ isSignal: true, alias: "initialColumnFilters", required: false }] }], initialColumnVisibility: [{ type: i0.Input, args: [{ isSignal: true, alias: "initialColumnVisibility", required: false }] }], initialRowSelection: [{ type: i0.Input, args: [{ isSignal: true, alias: "initialRowSelection", required: false }] }], showPageSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "showPageSize", required: false }] }], pageSizes: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageSizes", required: false }] }], navMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "navMode", required: false }] }], userClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }], selectionChange: [{ type: i0.Output, args: ["selectionChange"] }], pageChange: [{ type: i0.Output, args: ["pageChange"] }], pageSizeChange: [{ type: i0.Output, args: ["pageSizeChange"] }], rowClick: [{ type: i0.Output, args: ["rowClick"] }], sortingChange: [{ type: i0.Output, args: ["sortingChange"] }], columnFiltersChange: [{ type: i0.Output, args: ["columnFiltersChange"] }], filterChange: [{ type: i0.Output, args: ["filterChange"] }], columnVisibilityChange: [{ type: i0.Output, args: ["columnVisibilityChange"] }] } });
|
|
603
643
|
|
|
604
644
|
/**
|
|
605
645
|
* Sortable + hideable column header.
|
|
606
646
|
*
|
|
607
647
|
* Render via `flexRenderComponent(EgDataTableColumnHeader, { inputs: { column, title } })`
|
|
608
648
|
* so the extra `title` input flows alongside the flex-render `column` context.
|
|
609
|
-
* Non-sortable columns render a plain label.
|
|
649
|
+
* Non-sortable columns render a plain label. The `Hide` menu item only renders
|
|
650
|
+
* when `column.getCanHide()` is true — `EgDataTable` ties table-level
|
|
651
|
+
* `enableHiding` to its `showColumnToggle` input so there is always a way back
|
|
652
|
+
* via the View menu, and per-column `enableHiding: false` further disables it.
|
|
610
653
|
*/
|
|
611
654
|
class EgDataTableColumnHeader {
|
|
612
655
|
column = input.required(/* @ts-ignore */
|
|
@@ -618,11 +661,14 @@ class EgDataTableColumnHeader {
|
|
|
618
661
|
...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
|
|
619
662
|
_sorted = computed(() => this.column().getIsSorted(), /* @ts-ignore */
|
|
620
663
|
...(ngDevMode ? [{ debugName: "_sorted" }] : /* istanbul ignore next */ []));
|
|
664
|
+
/** Hideable only when TanStack allows it (table + column `enableHiding`). Absent `getCanHide` (legacy mocks) means hideable. */
|
|
665
|
+
_canHide = computed(() => this.column().getCanHide?.() ?? true, /* @ts-ignore */
|
|
666
|
+
...(ngDevMode ? [{ debugName: "_canHide" }] : /* istanbul ignore next */ []));
|
|
621
667
|
/** Height per density. Merged by `hlmButton`. */
|
|
622
668
|
_buttonClass = computed(() => hlm("-ml-3", this.size() === 'sm' ? "h-7" : this.size() === 'lg' ? "h-9" : "h-8"), /* @ts-ignore */
|
|
623
669
|
...(ngDevMode ? [{ debugName: "_buttonClass" }] : /* istanbul ignore next */ []));
|
|
624
670
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: EgDataTableColumnHeader, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
625
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.3", type: EgDataTableColumnHeader, isStandalone: true, selector: "eg-data-table-column-header", inputs: { column: { classPropertyName: "column", publicName: "column", isSignal: true, isRequired: true, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: true, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null } }, providers: [provideIcons({ lucideArrowDown, lucideArrowUp, lucideChevronsUpDown, lucideEyeOff })], ngImport: i0, template: "\n @if (column().getCanSort()) {\n <div class=\"flex items-center gap-2\">\n <button\n hlmButton\n variant=\"ghost\"\n size=\"sm\"\n [class]=\"_buttonClass()\"\n type=\"button\"\n [hlmDropdownMenuTrigger]=\"_menu\"\n >\n <span>{{ title() }}</span>\n @switch (_sorted()) {\n @case ('desc') {\n <ng-icon hlm size=\"sm\" name=\"lucideArrowDown\" />\n }\n @case ('asc') {\n <ng-icon hlm size=\"sm\" name=\"lucideArrowUp\" />\n }\n @default {\n <ng-icon hlm size=\"sm\" name=\"lucideChevronsUpDown\" />\n }\n }\n </button>\n <ng-template #_menu>\n <div hlmDropdownMenu>\n <button hlmDropdownMenuItem type=\"button\" (click)=\"column().toggleSorting(false)\">\n <ng-icon hlm size=\"sm\" name=\"lucideArrowUp\" />\n Asc\n </button>\n <button hlmDropdownMenuItem type=\"button\" (click)=\"column().toggleSorting(true)\">\n <ng-icon hlm size=\"sm\" name=\"lucideArrowDown\" />\n Desc\n </button>\n <div hlmDropdownMenuSeparator></div>\n
|
|
671
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.3", type: EgDataTableColumnHeader, isStandalone: true, selector: "eg-data-table-column-header", inputs: { column: { classPropertyName: "column", publicName: "column", isSignal: true, isRequired: true, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: true, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null } }, providers: [provideIcons({ lucideArrowDown, lucideArrowUp, lucideChevronsUpDown, lucideEyeOff })], ngImport: i0, template: "\n @if (column().getCanSort()) {\n <div class=\"flex items-center gap-2\">\n <button\n hlmButton\n variant=\"ghost\"\n size=\"sm\"\n [class]=\"_buttonClass()\"\n type=\"button\"\n [hlmDropdownMenuTrigger]=\"_menu\"\n >\n <span>{{ title() }}</span>\n @switch (_sorted()) {\n @case ('desc') {\n <ng-icon hlm size=\"sm\" name=\"lucideArrowDown\" />\n }\n @case ('asc') {\n <ng-icon hlm size=\"sm\" name=\"lucideArrowUp\" />\n }\n @default {\n <ng-icon hlm size=\"sm\" name=\"lucideChevronsUpDown\" />\n }\n }\n </button>\n <ng-template #_menu>\n <div hlmDropdownMenu>\n <button hlmDropdownMenuItem type=\"button\" (click)=\"column().toggleSorting(false)\">\n <ng-icon hlm size=\"sm\" name=\"lucideArrowUp\" />\n Asc\n </button>\n <button hlmDropdownMenuItem type=\"button\" (click)=\"column().toggleSorting(true)\">\n <ng-icon hlm size=\"sm\" name=\"lucideArrowDown\" />\n Desc\n </button>\n @if (_canHide()) {\n <div hlmDropdownMenuSeparator></div>\n <button hlmDropdownMenuItem type=\"button\" (click)=\"column().toggleVisibility(false)\">\n <ng-icon hlm size=\"sm\" name=\"lucideEyeOff\" />\n Hide\n </button>\n }\n </div>\n </ng-template>\n </div>\n } @else {\n <div>{{ title() }}</div>\n }\n ", isInline: true, dependencies: [{ kind: "component", type: HlmButton, selector: "button[hlmButton], a[hlmButton]", inputs: ["variant", "size", "appearance", "loading", "icon", "iconPosition", "class", "spinnerUserClass", "disabled", "type"] }, { kind: "directive", type: i1$1.HlmDropdownMenu, selector: "[hlmDropdownMenu],hlm-dropdown-menu", inputs: ["sideOffset"] }, { kind: "directive", type: i1$1.HlmDropdownMenuItem, selector: "[hlmDropdownMenuItem],hlm-dropdown-menu-item", inputs: ["disabled", "variant", "inset"] }, { kind: "directive", type: i1$1.HlmDropdownMenuSeparator, selector: "[hlmDropdownMenuSeparator],hlm-dropdown-menu-separator" }, { kind: "directive", type: i1$1.HlmDropdownMenuTrigger, selector: "[hlmDropdownMenuTrigger]", inputs: ["align", "side"] }, { kind: "component", type: NgIcon, selector: "ng-icon", inputs: ["name", "svg", "size", "strokeWidth", "color"] }, { kind: "directive", type: HlmIcon, selector: "ng-icon[hlm]", inputs: ["size"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
626
672
|
}
|
|
627
673
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: EgDataTableColumnHeader, decorators: [{
|
|
628
674
|
type: Component,
|
|
@@ -630,7 +676,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImpor
|
|
|
630
676
|
selector: 'eg-data-table-column-header',
|
|
631
677
|
imports: [HlmButton, HlmDropdownMenuImports, NgIcon, HlmIcon],
|
|
632
678
|
providers: [provideIcons({ lucideArrowDown, lucideArrowUp, lucideChevronsUpDown, lucideEyeOff })],
|
|
633
|
-
template: "\n @if (column().getCanSort()) {\n <div class=\"flex items-center gap-2\">\n <button\n hlmButton\n variant=\"ghost\"\n size=\"sm\"\n [class]=\"_buttonClass()\"\n type=\"button\"\n [hlmDropdownMenuTrigger]=\"_menu\"\n >\n <span>{{ title() }}</span>\n @switch (_sorted()) {\n @case ('desc') {\n <ng-icon hlm size=\"sm\" name=\"lucideArrowDown\" />\n }\n @case ('asc') {\n <ng-icon hlm size=\"sm\" name=\"lucideArrowUp\" />\n }\n @default {\n <ng-icon hlm size=\"sm\" name=\"lucideChevronsUpDown\" />\n }\n }\n </button>\n <ng-template #_menu>\n <div hlmDropdownMenu>\n <button hlmDropdownMenuItem type=\"button\" (click)=\"column().toggleSorting(false)\">\n <ng-icon hlm size=\"sm\" name=\"lucideArrowUp\" />\n Asc\n </button>\n <button hlmDropdownMenuItem type=\"button\" (click)=\"column().toggleSorting(true)\">\n <ng-icon hlm size=\"sm\" name=\"lucideArrowDown\" />\n Desc\n </button>\n <div hlmDropdownMenuSeparator></div>\n
|
|
679
|
+
template: "\n @if (column().getCanSort()) {\n <div class=\"flex items-center gap-2\">\n <button\n hlmButton\n variant=\"ghost\"\n size=\"sm\"\n [class]=\"_buttonClass()\"\n type=\"button\"\n [hlmDropdownMenuTrigger]=\"_menu\"\n >\n <span>{{ title() }}</span>\n @switch (_sorted()) {\n @case ('desc') {\n <ng-icon hlm size=\"sm\" name=\"lucideArrowDown\" />\n }\n @case ('asc') {\n <ng-icon hlm size=\"sm\" name=\"lucideArrowUp\" />\n }\n @default {\n <ng-icon hlm size=\"sm\" name=\"lucideChevronsUpDown\" />\n }\n }\n </button>\n <ng-template #_menu>\n <div hlmDropdownMenu>\n <button hlmDropdownMenuItem type=\"button\" (click)=\"column().toggleSorting(false)\">\n <ng-icon hlm size=\"sm\" name=\"lucideArrowUp\" />\n Asc\n </button>\n <button hlmDropdownMenuItem type=\"button\" (click)=\"column().toggleSorting(true)\">\n <ng-icon hlm size=\"sm\" name=\"lucideArrowDown\" />\n Desc\n </button>\n @if (_canHide()) {\n <div hlmDropdownMenuSeparator></div>\n <button hlmDropdownMenuItem type=\"button\" (click)=\"column().toggleVisibility(false)\">\n <ng-icon hlm size=\"sm\" name=\"lucideEyeOff\" />\n Hide\n </button>\n }\n </div>\n </ng-template>\n </div>\n } @else {\n <div>{{ title() }}</div>\n }\n ",
|
|
634
680
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
635
681
|
}]
|
|
636
682
|
}], propDecorators: { column: [{ type: i0.Input, args: [{ isSignal: true, alias: "column", required: true }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: true }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }] } });
|
|
@@ -188,6 +188,15 @@ declare class EgDataTable<TData extends RowData> implements OnInit {
|
|
|
188
188
|
}, TData>[] | undefined>;
|
|
189
189
|
/** Client rows, or a server page slice when `manualPagination` is set (`null` while loading). */
|
|
190
190
|
readonly data: _angular_core.InputSignal<EgPaginatedResponse<TData> | readonly TData[] | null>;
|
|
191
|
+
/**
|
|
192
|
+
* Pure stable identity callback, e.g. `(record) => record.id`. Return a unique
|
|
193
|
+
* string per entity, independent of position, and keep the callback reference stable.
|
|
194
|
+
* Selection survives refreshes only for IDs still in the supplied rows (after
|
|
195
|
+
* `filterRows`); server selection is limited to the loaded slice. Without this
|
|
196
|
+
* callback, IDs are positional and replacing the rows clears selection.
|
|
197
|
+
* Changing the callback clears selection. Update data immutably.
|
|
198
|
+
*/
|
|
199
|
+
readonly getRowId: _angular_core.InputSignal<((row: TData) => string) | undefined>;
|
|
191
200
|
/** When true, `data` is a server page slice and the table uses TanStack `manualPagination`. Sorting and filtering are then display-only: the slice is shown as-is while `sortingChange` / `filterChange` (`columnFiltersChange`) notify the caller to refetch. */
|
|
192
201
|
readonly manualPagination: _angular_core.InputSignal<boolean>;
|
|
193
202
|
/** TanStack feature registry. Defaults to filtering + visibility + pagination + selection + sorting. */
|
|
@@ -228,7 +237,7 @@ declare class EgDataTable<TData extends RowData> implements OnInit {
|
|
|
228
237
|
/** Column id the toolbar filter input writes to (e.g. `'email'`). Empty means client-side filtering is skipped and keystrokes only emit `filterChange` (server-side pattern). */
|
|
229
238
|
readonly filterColumnId: _angular_core.InputSignal<string>;
|
|
230
239
|
readonly filterPlaceholder: _angular_core.InputSignal<string>;
|
|
231
|
-
/** Show the column-visibility dropdown inside the toolbar. Off by default; opt in per table. */
|
|
240
|
+
/** Show the column-visibility dropdown inside the toolbar (requires `showToolbar`). Off by default; opt in per table. Also enables hiding — the `Hide` item in `EgDataTableColumnHeader` only renders when this is true, so hidden columns always have a way back. Per-column `enableHiding: false` further disables individual columns. */
|
|
232
241
|
readonly showColumnToggle: _angular_core.InputSignal<boolean>;
|
|
233
242
|
/** Custom right-side toolbar content (e.g. action buttons) as a template. Renders the toolbar row even when `showToolbar` is false; built-ins stay on the left. */
|
|
234
243
|
readonly toolbarActions: _angular_core.InputSignal<TemplateRef<unknown> | undefined>;
|
|
@@ -242,7 +251,7 @@ declare class EgDataTable<TData extends RowData> implements OnInit {
|
|
|
242
251
|
readonly initialColumnFilters: _angular_core.InputSignal<ColumnFiltersState>;
|
|
243
252
|
/** Seeds the column-visibility state once at creation. Later changes are ignored. */
|
|
244
253
|
readonly initialColumnVisibility: _angular_core.InputSignal<ColumnVisibilityState>;
|
|
245
|
-
/** Seeds
|
|
254
|
+
/** Seeds selection once for current rows: keys come from `getRowId`, or positional indices without it. Missing IDs are discarded. Later changes are ignored. */
|
|
246
255
|
readonly initialRowSelection: _angular_core.InputSignal<RowSelectionState>;
|
|
247
256
|
/** Show the rows-per-page selector in the footer pager. */
|
|
248
257
|
readonly showPageSize: _angular_core.InputSignal<boolean>;
|
|
@@ -251,7 +260,7 @@ declare class EgDataTable<TData extends RowData> implements OnInit {
|
|
|
251
260
|
/** Footer navigation-button content: icons only, text labels only, or both. */
|
|
252
261
|
readonly navMode: _angular_core.InputSignal<EgPaginationNavMode>;
|
|
253
262
|
readonly userClass: _angular_core.InputSignal<string>;
|
|
254
|
-
/** Emits
|
|
263
|
+
/** Emits on init and when selected row identities/order or object references change. Includes rows hidden by built-in filters/client pagination, but never rows absent from `data`/`filterRows`. */
|
|
255
264
|
readonly selectionChange: _angular_core.OutputEmitterRef<readonly TData[]>;
|
|
256
265
|
/** Emits the target page index on pager navigation (primary hook for server fetching). */
|
|
257
266
|
readonly pageChange: _angular_core.OutputEmitterRef<number>;
|
|
@@ -269,13 +278,15 @@ declare class EgDataTable<TData extends RowData> implements OnInit {
|
|
|
269
278
|
private readonly _sorting;
|
|
270
279
|
private readonly _columnFilters;
|
|
271
280
|
private readonly _columnVisibility;
|
|
272
|
-
private readonly _rowSelection;
|
|
273
281
|
private readonly _clientPageIndex;
|
|
274
282
|
private readonly _clientPageSize;
|
|
275
283
|
private readonly _isServer;
|
|
276
284
|
/** The server page slice when in server mode; `null` for client data, misuse shapes, or `null` while loading. */
|
|
277
285
|
private readonly _page;
|
|
278
286
|
private readonly _items;
|
|
287
|
+
private readonly _tableItems;
|
|
288
|
+
private readonly _rowSelection;
|
|
289
|
+
private _keepCurrentSelection;
|
|
279
290
|
private readonly _serverPageCount;
|
|
280
291
|
private readonly _serverPageIndex;
|
|
281
292
|
private readonly _paginationState;
|
|
@@ -323,6 +334,7 @@ declare class EgDataTable<TData extends RowData> implements OnInit {
|
|
|
323
334
|
readonly thumbnail?: boolean;
|
|
324
335
|
};
|
|
325
336
|
}, TData>;
|
|
337
|
+
private readonly _selectedRows;
|
|
326
338
|
private readonly _emitSelection;
|
|
327
339
|
/**
|
|
328
340
|
* Seeds internal state from the `initial*` inputs. Runs in `ngOnInit` (after
|
|
@@ -352,7 +364,7 @@ declare class EgDataTable<TData extends RowData> implements OnInit {
|
|
|
352
364
|
protected _contentCells(row: Row<EgDataTableFeatures, TData>): Cell<EgDataTableFeatures, TData, CellData>[];
|
|
353
365
|
protected _cellLabel(cell: Cell<EgDataTableFeatures, TData, CellData>): string;
|
|
354
366
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<EgDataTable<any>, never>;
|
|
355
|
-
static ɵcmp: _angular_core.ɵɵComponentDeclaration<EgDataTable<any>, "eg-data-table", never, { "columns": { "alias": "columns"; "required": true; "isSignal": true; }; "gridColumns": { "alias": "gridColumns"; "required": false; "isSignal": true; }; "data": { "alias": "data"; "required": false; "isSignal": true; }; "manualPagination": { "alias": "manualPagination"; "required": false; "isSignal": true; }; "features": { "alias": "features"; "required": false; "isSignal": true; }; "isLoading": { "alias": "isLoading"; "required": false; "isSignal": true; }; "emptyMessage": { "alias": "emptyMessage"; "required": false; "isSignal": true; }; "enableSelection": { "alias": "enableSelection"; "required": false; "isSignal": true; }; "hideFooter": { "alias": "hideFooter"; "required": false; "isSignal": true; }; "size": { "alias": "size"; "required": false; "isSignal": true; }; "layout": { "alias": "layout"; "required": false; "isSignal": true; }; "showLayoutToggle": { "alias": "showLayoutToggle"; "required": false; "isSignal": true; }; "showToolbar": { "alias": "showToolbar"; "required": false; "isSignal": true; }; "filterColumnId": { "alias": "filterColumnId"; "required": false; "isSignal": true; }; "filterPlaceholder": { "alias": "filterPlaceholder"; "required": false; "isSignal": true; }; "showColumnToggle": { "alias": "showColumnToggle"; "required": false; "isSignal": true; }; "toolbarActions": { "alias": "toolbarActions"; "required": false; "isSignal": true; }; "defaultPageSize": { "alias": "defaultPageSize"; "required": false; "isSignal": true; }; "filterRows": { "alias": "filterRows"; "required": false; "isSignal": true; }; "initialSorting": { "alias": "initialSorting"; "required": false; "isSignal": true; }; "initialColumnFilters": { "alias": "initialColumnFilters"; "required": false; "isSignal": true; }; "initialColumnVisibility": { "alias": "initialColumnVisibility"; "required": false; "isSignal": true; }; "initialRowSelection": { "alias": "initialRowSelection"; "required": false; "isSignal": true; }; "showPageSize": { "alias": "showPageSize"; "required": false; "isSignal": true; }; "pageSizes": { "alias": "pageSizes"; "required": false; "isSignal": true; }; "navMode": { "alias": "navMode"; "required": false; "isSignal": true; }; "userClass": { "alias": "class"; "required": false; "isSignal": true; }; }, { "layout": "layoutChange"; "selectionChange": "selectionChange"; "pageChange": "pageChange"; "pageSizeChange": "pageSizeChange"; "rowClick": "rowClick"; "sortingChange": "sortingChange"; "columnFiltersChange": "columnFiltersChange"; "filterChange": "filterChange"; "columnVisibilityChange": "columnVisibilityChange"; }, never, never, true, never>;
|
|
367
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<EgDataTable<any>, "eg-data-table", never, { "columns": { "alias": "columns"; "required": true; "isSignal": true; }; "gridColumns": { "alias": "gridColumns"; "required": false; "isSignal": true; }; "data": { "alias": "data"; "required": false; "isSignal": true; }; "getRowId": { "alias": "getRowId"; "required": false; "isSignal": true; }; "manualPagination": { "alias": "manualPagination"; "required": false; "isSignal": true; }; "features": { "alias": "features"; "required": false; "isSignal": true; }; "isLoading": { "alias": "isLoading"; "required": false; "isSignal": true; }; "emptyMessage": { "alias": "emptyMessage"; "required": false; "isSignal": true; }; "enableSelection": { "alias": "enableSelection"; "required": false; "isSignal": true; }; "hideFooter": { "alias": "hideFooter"; "required": false; "isSignal": true; }; "size": { "alias": "size"; "required": false; "isSignal": true; }; "layout": { "alias": "layout"; "required": false; "isSignal": true; }; "showLayoutToggle": { "alias": "showLayoutToggle"; "required": false; "isSignal": true; }; "showToolbar": { "alias": "showToolbar"; "required": false; "isSignal": true; }; "filterColumnId": { "alias": "filterColumnId"; "required": false; "isSignal": true; }; "filterPlaceholder": { "alias": "filterPlaceholder"; "required": false; "isSignal": true; }; "showColumnToggle": { "alias": "showColumnToggle"; "required": false; "isSignal": true; }; "toolbarActions": { "alias": "toolbarActions"; "required": false; "isSignal": true; }; "defaultPageSize": { "alias": "defaultPageSize"; "required": false; "isSignal": true; }; "filterRows": { "alias": "filterRows"; "required": false; "isSignal": true; }; "initialSorting": { "alias": "initialSorting"; "required": false; "isSignal": true; }; "initialColumnFilters": { "alias": "initialColumnFilters"; "required": false; "isSignal": true; }; "initialColumnVisibility": { "alias": "initialColumnVisibility"; "required": false; "isSignal": true; }; "initialRowSelection": { "alias": "initialRowSelection"; "required": false; "isSignal": true; }; "showPageSize": { "alias": "showPageSize"; "required": false; "isSignal": true; }; "pageSizes": { "alias": "pageSizes"; "required": false; "isSignal": true; }; "navMode": { "alias": "navMode"; "required": false; "isSignal": true; }; "userClass": { "alias": "class"; "required": false; "isSignal": true; }; }, { "layout": "layoutChange"; "selectionChange": "selectionChange"; "pageChange": "pageChange"; "pageSizeChange": "pageSizeChange"; "rowClick": "rowClick"; "sortingChange": "sortingChange"; "columnFiltersChange": "columnFiltersChange"; "filterChange": "filterChange"; "columnVisibilityChange": "columnVisibilityChange"; }, never, never, true, never>;
|
|
356
368
|
}
|
|
357
369
|
|
|
358
370
|
/**
|
|
@@ -369,13 +381,18 @@ interface EgSortableColumn {
|
|
|
369
381
|
getIsSorted(): false | SortDirection;
|
|
370
382
|
toggleSorting(desc?: boolean): void;
|
|
371
383
|
toggleVisibility(value?: boolean): void;
|
|
384
|
+
/** Whether the column can be hidden (`columnDef.enableHiding` and table `enableHiding`). Optional for back-compat mocks — absent means hideable. */
|
|
385
|
+
getCanHide?(): boolean;
|
|
372
386
|
}
|
|
373
387
|
/**
|
|
374
388
|
* Sortable + hideable column header.
|
|
375
389
|
*
|
|
376
390
|
* Render via `flexRenderComponent(EgDataTableColumnHeader, { inputs: { column, title } })`
|
|
377
391
|
* so the extra `title` input flows alongside the flex-render `column` context.
|
|
378
|
-
* Non-sortable columns render a plain label.
|
|
392
|
+
* Non-sortable columns render a plain label. The `Hide` menu item only renders
|
|
393
|
+
* when `column.getCanHide()` is true — `EgDataTable` ties table-level
|
|
394
|
+
* `enableHiding` to its `showColumnToggle` input so there is always a way back
|
|
395
|
+
* via the View menu, and per-column `enableHiding: false` further disables it.
|
|
379
396
|
*/
|
|
380
397
|
declare class EgDataTableColumnHeader {
|
|
381
398
|
readonly column: _angular_core.InputSignal<EgSortableColumn>;
|
|
@@ -383,6 +400,8 @@ declare class EgDataTableColumnHeader {
|
|
|
383
400
|
/** Density of the trigger button. */
|
|
384
401
|
readonly size: _angular_core.InputSignal<HlmTableSize>;
|
|
385
402
|
protected readonly _sorted: _angular_core.Signal<false | SortDirection>;
|
|
403
|
+
/** Hideable only when TanStack allows it (table + column `enableHiding`). Absent `getCanHide` (legacy mocks) means hideable. */
|
|
404
|
+
protected readonly _canHide: _angular_core.Signal<boolean>;
|
|
386
405
|
/** Height per density. Merged by `hlmButton`. */
|
|
387
406
|
protected readonly _buttonClass: _angular_core.Signal<string>;
|
|
388
407
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<EgDataTableColumnHeader, never>;
|
package/date-picker/README.md
CHANGED
|
@@ -135,6 +135,38 @@ Real selectors (from source):
|
|
|
135
135
|
|
|
136
136
|
## API reference
|
|
137
137
|
|
|
138
|
+
### User commits, invalid drafts, and programmatic writes
|
|
139
|
+
|
|
140
|
+
The single, range and multi text inputs commit on **blur or Enter**. Both parsed and transformed values
|
|
141
|
+
must have a finite `getTime` through the configured Spartan date adapter and satisfy inclusive whole-day
|
|
142
|
+
`min`/`max` bounds (`startOfDay(min)` through `endOfDay(max)`). Provide matching parsing, formatting and
|
|
143
|
+
pure transformation callbacks when using a custom adapter/date type. A transformed range must be ordered;
|
|
144
|
+
custom transforms may sort endpoints. The default range parser still treats one date as a same-day range,
|
|
145
|
+
but an explicitly unparseable second endpoint is rejected.
|
|
146
|
+
|
|
147
|
+
For multi selection, `maxSelection` caps the raw and transformed array counts. `minSelection` is the
|
|
148
|
+
calendar's **deselection floor**: reductions below it are rejected, while growth from empty is allowed.
|
|
149
|
+
Supply unique dates. When the calendar proposes resetting a full selection to one new date, that reset
|
|
150
|
+
must also satisfy the floor. Rejected calendar commits restore the previous selection without user emissions.
|
|
151
|
+
|
|
152
|
+
On rejection the committed value stays unchanged, no `dateChange`/CVA `onChange` fires, and the input
|
|
153
|
+
preserves editable text across blur, Enter and refocus. `inputInvalid()` exposes local rejection state;
|
|
154
|
+
the native input receives `aria-invalid="true"` and invalid styling, combined with `forceInvalid`.
|
|
155
|
+
The interaction touches the form control but does not install an Angular validator or overwrite its
|
|
156
|
+
errors: form validators continue to see the last committed value. If unresolved drafts should block
|
|
157
|
+
submission, include `inputInvalid()` in that decision. Use `ariaDescribedby` to associate explanatory text.
|
|
158
|
+
|
|
159
|
+
A successful text/calendar commit, explicit clear, or external value write clears the local rejection.
|
|
160
|
+
Empty text and the clear button bypass transforms and the selection floor, emitting `null` (single/range)
|
|
161
|
+
or `[]` (multi); whitespace is passed to the parser. Enter keeps edit formatting for a subsequent blur;
|
|
162
|
+
blur restores display formatting. Disabled/readonly text inputs do not commit or clear.
|
|
163
|
+
|
|
164
|
+
`updateDate(value)` returns a boolean indicating whether a user commit was accepted. Programmatic CVA
|
|
165
|
+
`writeValue` applies configured transforms without enforcing user constraints or emitting; it replaces
|
|
166
|
+
rejected drafts, including repeated same-value/null writes. `[date]` remains a direct, untransformed
|
|
167
|
+
standalone input. `reset()` is an explicit programmatic clear and emits. Month/year retains its existing
|
|
168
|
+
brain-input lifecycle; this constraint/draft contract applies to single, range and multi pickers.
|
|
169
|
+
|
|
138
170
|
### `HlmDatePicker` — `hlm-date-picker`
|
|
139
171
|
|
|
140
172
|
Single-date picker. Generic `<T>` (usually `Date`). Implements `BrnDatePickerBase<T>` + `ControlValueAccessor`, hosts `BrnFieldControl`.
|
|
@@ -230,15 +262,15 @@ Outputs/methods mirror `HlmDatePicker` (`dateChange: T | null`, `updateDate`, `o
|
|
|
230
262
|
|
|
231
263
|
`HlmDatePickerInput<T>`, `HlmDateMultiInput<T>`, `HlmDateRangeInput<T>`, `HlmMonthYearInput<T>` extend `BrnDateInput` (inheriting `placeholder`, `inputId`, disabled/invalid wiring, clear-button and calendar-button behavior) and add:
|
|
232
264
|
|
|
233
|
-
| Input | Type | Default | Notes
|
|
234
|
-
| -------------------------------------- | ------------------------------------------------------------------------------- | --------------------------------- |
|
|
235
|
-
| `parseDate` | `(value: string) => T \| null` (or `T[] \| null` / `[T,T] \| null` per variant) | from matching `provideHlm*Config` | Return `null` for invalid text;
|
|
236
|
-
| `formatInputDate` / `formatInputDates` | `(date) => string` | from config | Edit format shown while focused.
|
|
237
|
-
| `ariaLabel` / `ariaDescribedby` | `string` | — | Accessible labelling for the inner `<input>`.
|
|
238
|
-
| `name` | `string \| undefined` | — | Native `name` forwarded to the inner `<input>`.
|
|
239
|
-
| `readonly` | `boolean` | `false` | Native `readonly` forwarded to the inner `<input>`.
|
|
240
|
-
| `class` | `ClassValue` | `''` | Extra classes on the host group container.
|
|
241
|
-
| `inputClass` | `ClassValue` | `''` | Extra classes on the inner `<input>` (e.g. text size).
|
|
265
|
+
| Input | Type | Default | Notes |
|
|
266
|
+
| -------------------------------------- | ------------------------------------------------------------------------------- | --------------------------------- | -------------------------------------------------------------------------------------------------- |
|
|
267
|
+
| `parseDate` | `(value: string) => T \| null` (or `T[] \| null` / `[T,T] \| null` per variant) | from matching `provideHlm*Config` | Return `null` for invalid text; single/range/multi preserve the committed value and rejected text. |
|
|
268
|
+
| `formatInputDate` / `formatInputDates` | `(date) => string` | from config | Edit format shown while focused. |
|
|
269
|
+
| `ariaLabel` / `ariaDescribedby` | `string` | — | Accessible labelling for the inner `<input>`. |
|
|
270
|
+
| `name` | `string \| undefined` | — | Native `name` forwarded to the inner `<input>`. |
|
|
271
|
+
| `readonly` | `boolean` | `false` | Native `readonly` forwarded to the inner `<input>`. |
|
|
272
|
+
| `class` | `ClassValue` | `''` | Extra classes on the host group container. |
|
|
273
|
+
| `inputClass` | `ClassValue` | `''` | Extra classes on the inner `<input>` (e.g. text size). |
|
|
242
274
|
|
|
243
275
|
### `HlmDatePickerTrigger` — `hlm-date-picker-trigger`
|
|
244
276
|
|