@egose/shadcn-theme-ng 0.6.1 → 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.
@@ -156,7 +156,7 @@ Key `EgDataTable` inputs: `columns` (required), `gridColumns`, `data` (array, or
156
156
 
157
157
  Outputs: `selectionChange` (also fires once on init, mirroring React's mount effect), `pageChange`, `pageSizeChange`, `rowClick`, `sortingChange`, `columnFiltersChange`, `filterChange` (toolbar input string), `columnVisibilityChange`.
158
158
 
159
- The toolbar (`showToolbar`) always renders the filter input: with `filterColumnId` it filters that column client-side (and `filterChange` mirrors the string); without it, keystrokes only emit `filterChange` so the caller can filter server-side. The column-visibility dropdown is opt-in via `showColumnToggle` (default `false`). `toolbarActions` takes an `ng-template` rendered on the right side of the toolbar row (built-ins stay left) — it renders the row even when `showToolbar` is false.
159
+ The toolbar (`showToolbar`) always renders the filter input: with `filterColumnId` it filters that column client-side (and `filterChange` mirrors the string); without it, keystrokes only emit `filterChange` so the caller can filter server-side. The column-visibility dropdown is opt-in via `showColumnToggle` (default `false`, requires `showToolbar`). `showColumnToggle` also enables hiding: the `Hide` item in `EgDataTableColumnHeader` only renders when it is true (TanStack `column.getCanHide()`), so a hidden column always has a way back via View; per-column `enableHiding: false` disables individual columns even then. `toolbarActions` takes an `ng-template` rendered on the right side of the toolbar row (built-ins stay left) — it renders the row even when `showToolbar` is false.
160
160
 
161
161
  `size` scales spatial density one step down/up (`sm`: `h-8` headers, `p-1` cells, `h-7` buttons; `lg`: `h-12` headers, `p-3` cells, `h-9` buttons; filter input, page-size trigger, and pager meta texts follow). `EgDataTableColumnHeader` (consumer-instantiated via `flexRenderComponent`) takes the same `size` — for reactive updates put every input in `bindings` (`inputBinding('size', ...)`, plus `column`/`title`, since `bindings` cannot mix with `inputs`).
162
162
 
@@ -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 }] }] } });
@@ -296,7 +296,7 @@ class EgDataTable {
296
296
  ...(ngDevMode ? [{ debugName: "filterColumnId" }] : /* istanbul ignore next */ []));
297
297
  filterPlaceholder = input('Filter...', /* @ts-ignore */
298
298
  ...(ngDevMode ? [{ debugName: "filterPlaceholder" }] : /* istanbul ignore next */ []));
299
- /** 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. */
300
300
  showColumnToggle = input(false, /* @ts-ignore */
301
301
  ...(ngDevMode ? [{ debugName: "showColumnToggle" }] : /* istanbul ignore next */ []));
302
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. */
@@ -458,6 +458,10 @@ class EgDataTable {
458
458
  columns: this._finalColumns(),
459
459
  data: this._tableItems(),
460
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(),
461
465
  manualPagination: server,
462
466
  manualSorting: server,
463
467
  manualFiltering: server,
@@ -642,7 +646,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImpor
642
646
  *
643
647
  * Render via `flexRenderComponent(EgDataTableColumnHeader, { inputs: { column, title } })`
644
648
  * so the extra `title` input flows alongside the flex-render `column` context.
645
- * 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.
646
653
  */
647
654
  class EgDataTableColumnHeader {
648
655
  column = input.required(/* @ts-ignore */
@@ -654,11 +661,14 @@ class EgDataTableColumnHeader {
654
661
  ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
655
662
  _sorted = computed(() => this.column().getIsSorted(), /* @ts-ignore */
656
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 */ []));
657
667
  /** Height per density. Merged by `hlmButton`. */
658
668
  _buttonClass = computed(() => hlm("-ml-3", this.size() === 'sm' ? "h-7" : this.size() === 'lg' ? "h-9" : "h-8"), /* @ts-ignore */
659
669
  ...(ngDevMode ? [{ debugName: "_buttonClass" }] : /* istanbul ignore next */ []));
660
670
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: EgDataTableColumnHeader, deps: [], target: i0.ɵɵFactoryTarget.Component });
661
- 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 <button hlmDropdownMenuItem type=\"button\" (click)=\"column().toggleVisibility(false)\">\n <ng-icon hlm size=\"sm\" name=\"lucideEyeOff\" />\n Hide\n </button>\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 });
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 });
662
672
  }
663
673
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: EgDataTableColumnHeader, decorators: [{
664
674
  type: Component,
@@ -666,7 +676,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImpor
666
676
  selector: 'eg-data-table-column-header',
667
677
  imports: [HlmButton, HlmDropdownMenuImports, NgIcon, HlmIcon],
668
678
  providers: [provideIcons({ lucideArrowDown, lucideArrowUp, lucideChevronsUpDown, lucideEyeOff })],
669
- 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 <button hlmDropdownMenuItem type=\"button\" (click)=\"column().toggleVisibility(false)\">\n <ng-icon hlm size=\"sm\" name=\"lucideEyeOff\" />\n Hide\n </button>\n </div>\n </ng-template>\n </div>\n } @else {\n <div>{{ title() }}</div>\n }\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 ",
670
680
  changeDetection: ChangeDetectionStrategy.OnPush,
671
681
  }]
672
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 }] }] } });
@@ -237,7 +237,7 @@ declare class EgDataTable<TData extends RowData> implements OnInit {
237
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). */
238
238
  readonly filterColumnId: _angular_core.InputSignal<string>;
239
239
  readonly filterPlaceholder: _angular_core.InputSignal<string>;
240
- /** 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. */
241
241
  readonly showColumnToggle: _angular_core.InputSignal<boolean>;
242
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. */
243
243
  readonly toolbarActions: _angular_core.InputSignal<TemplateRef<unknown> | undefined>;
@@ -381,13 +381,18 @@ interface EgSortableColumn {
381
381
  getIsSorted(): false | SortDirection;
382
382
  toggleSorting(desc?: boolean): void;
383
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;
384
386
  }
385
387
  /**
386
388
  * Sortable + hideable column header.
387
389
  *
388
390
  * Render via `flexRenderComponent(EgDataTableColumnHeader, { inputs: { column, title } })`
389
391
  * so the extra `title` input flows alongside the flex-render `column` context.
390
- * 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.
391
396
  */
392
397
  declare class EgDataTableColumnHeader {
393
398
  readonly column: _angular_core.InputSignal<EgSortableColumn>;
@@ -395,6 +400,8 @@ declare class EgDataTableColumnHeader {
395
400
  /** Density of the trigger button. */
396
401
  readonly size: _angular_core.InputSignal<HlmTableSize>;
397
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>;
398
405
  /** Height per density. Merged by `hlmButton`. */
399
406
  protected readonly _buttonClass: _angular_core.Signal<string>;
400
407
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<EgDataTableColumnHeader, never>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@egose/shadcn-theme-ng",
3
- "version": "0.6.1",
3
+ "version": "0.6.2",
4
4
  "description": "Angular shadcn UI theme",
5
5
  "author": "Junmin Ahn",
6
6
  "bundles": [