@egose/shadcn-theme-ng-tw 0.5.3 → 0.6.1

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.
Files changed (61) hide show
  1. package/README.md +131 -12
  2. package/autocomplete/fesm2022/autocomplete.mjs +14 -4
  3. package/autocomplete/types/autocomplete.d.ts +4 -1
  4. package/checkbox/README.md +6 -2
  5. package/checkbox/fesm2022/checkbox.mjs +15 -9
  6. package/checkbox/types/checkbox.d.ts +6 -4
  7. package/combobox/fesm2022/combobox.mjs +22 -6
  8. package/combobox/types/combobox.d.ts +8 -2
  9. package/data-table/README.md +174 -0
  10. package/data-table/fesm2022/data-table.mjs +1485 -0
  11. package/data-table/package.json +25 -0
  12. package/data-table/types/data-table.d.ts +495 -0
  13. package/date-picker/README.md +41 -9
  14. package/date-picker/fesm2022/date-picker.mjs +265 -59
  15. package/date-picker/types/date-picker.d.ts +58 -27
  16. package/dropdown-menu/README.md +2 -0
  17. package/form-autocomplete/README.md +4 -2
  18. package/form-autocomplete/fesm2022/form-autocomplete.mjs +33 -8
  19. package/form-autocomplete/types/form-autocomplete.d.ts +9 -3
  20. package/form-combobox/README.md +4 -2
  21. package/form-combobox/fesm2022/form-combobox.mjs +65 -14
  22. package/form-combobox/types/form-combobox.d.ts +10 -3
  23. package/form-input-otp/README.md +7 -5
  24. package/form-input-otp/fesm2022/form-input-otp.mjs +28 -14
  25. package/form-input-otp/types/form-input-otp.d.ts +9 -3
  26. package/form-searchable-multiselect/README.md +15 -1
  27. package/form-searchable-multiselect/fesm2022/form-searchable-multiselect.mjs +23 -3
  28. package/form-searchable-multiselect/types/form-searchable-multiselect.d.ts +9 -1
  29. package/form-slider/README.md +3 -1
  30. package/form-slider/fesm2022/form-slider.mjs +21 -6
  31. package/form-slider/types/form-slider.d.ts +9 -3
  32. package/form-text-input/fesm2022/form-text-input.mjs +1 -1
  33. package/form-textarea/fesm2022/form-textarea.mjs +1 -1
  34. package/form-toggle/README.md +22 -18
  35. package/form-toggle/fesm2022/form-toggle.mjs +25 -8
  36. package/form-toggle/types/form-toggle.d.ts +6 -2
  37. package/input/README.md +7 -12
  38. package/input/fesm2022/input.mjs +7 -4
  39. package/input/types/input.d.ts +3 -1
  40. package/input-otp/README.md +33 -9
  41. package/input-otp/fesm2022/input-otp.mjs +127 -11
  42. package/input-otp/types/input-otp.d.ts +24 -4
  43. package/layout-simple/fesm2022/layout-simple.mjs +1 -1
  44. package/package.json +6 -1
  45. package/pagination/README.md +21 -12
  46. package/pagination/fesm2022/pagination.mjs +83 -75
  47. package/pagination/types/pagination.d.ts +21 -8
  48. package/phone-input/README.md +16 -0
  49. package/phone-input/fesm2022/phone-input.mjs +42 -4
  50. package/phone-input/types/phone-input.d.ts +5 -2
  51. package/searchable-multiselect/README.md +62 -40
  52. package/searchable-multiselect/fesm2022/searchable-multiselect.mjs +97 -36
  53. package/searchable-multiselect/types/searchable-multiselect.d.ts +23 -6
  54. package/slider/fesm2022/slider.mjs +15 -5
  55. package/slider/types/slider.d.ts +6 -2
  56. package/stepper/README.md +39 -19
  57. package/stepper/fesm2022/stepper.mjs +71 -17
  58. package/stepper/types/stepper.d.ts +12 -1
  59. package/table/README.md +2 -0
  60. package/table/fesm2022/table.mjs +12 -8
  61. package/table/types/table.d.ts +7 -2
@@ -0,0 +1,174 @@
1
+ # Data Table (`@egose/shadcn-theme-ng/data-table`)
2
+
3
+ A generic, TanStack-powered data table with sorting, filtering, pagination, row selection, column visibility, and an optional card-grid layout — equivalent to combining [shadcn/ui Table](https://ui.shadcn.com/docs/components/table) with the [Spartan data-table guide](https://www.spartan.ng/components/data-table). The caller passes `columns` (and optionally `gridColumns`); the table owns its state internally and notifies via outputs.
4
+
5
+ > **Ships as:** `@egose/shadcn-theme-ng/data-table` and `@egose/shadcn-theme-ng-tw/data-table` (the `tw:`-prefixed Tailwind variant). See the [package README](../../README.md) for install steps, peer dependencies, Tailwind setup, and testing/release guidance. Do not publish this project directory independently.
6
+
7
+ ## Installation
8
+
9
+ ```bash
10
+ # Plain Tailwind (no prefix)
11
+ npm install @egose/shadcn-theme-ng @tanstack/angular-table
12
+
13
+ # Or the tw:-prefixed variant
14
+ npm install @egose/shadcn-theme-ng-tw @tanstack/angular-table
15
+ ```
16
+
17
+ `@tanstack/angular-table` (`>=9.1.2 <10.0.0`) is a peer dependency — install it alongside the theme package. See the [package README](../../README.md) for the full peer-dependency table.
18
+
19
+ ## Imports
20
+
21
+ All public symbols are re-exported from `projects/data-table/src/public-api.ts`:
22
+
23
+ ```ts
24
+ import {
25
+ EgDataTable,
26
+ EgDataTableColumnHeader,
27
+ EgDataTableImports,
28
+ EgDataTableModule,
29
+ EgDataTablePagination,
30
+ EgDataTableViewOptions,
31
+ EgSortableColumn,
32
+ EgTableHeadSelection,
33
+ EgTableRowSelection,
34
+ defaultEgDataTableFeatures,
35
+ type EgDataTableFeatures,
36
+ type EgDataTableLayout,
37
+ type EgPaginatedResponse,
38
+ } from '@egose/shadcn-theme-ng/data-table';
39
+ // tw variant: swap to '@egose/shadcn-theme-ng-tw/data-table'
40
+ ```
41
+
42
+ ## Client mode
43
+
44
+ ```ts
45
+ import { Component, signal } from '@angular/core';
46
+ import { createColumnHelper } from '@tanstack/angular-table';
47
+ import { EgDataTable, type EgDataTableFeatures } from '@egose/shadcn-theme-ng/data-table';
48
+
49
+ interface Payment {
50
+ id: string;
51
+ amount: number;
52
+ status: string;
53
+ email: string;
54
+ }
55
+
56
+ const helper = createColumnHelper<EgDataTableFeatures, Payment>();
57
+ const columns = helper.columns([
58
+ helper.accessor('status', { header: 'Status' }),
59
+ helper.accessor('email', { header: 'Email' }),
60
+ helper.accessor('amount', { header: 'Amount' }),
61
+ ]);
62
+
63
+ @Component({
64
+ selector: 'app-payments',
65
+ imports: [EgDataTable],
66
+ template: `<eg-data-table [columns]="columns" [data]="payments()" />`,
67
+ })
68
+ export class PaymentsComponent {
69
+ protected readonly payments = signal<Payment[]>([
70
+ { id: '1', amount: 100, status: 'pending', email: 'm@example.com' },
71
+ ]);
72
+ }
73
+ ```
74
+
75
+ ## Server mode
76
+
77
+ Pass `data` as a page slice with `manualPagination` set. The slice renders as-is — sorting and filtering are not applied client-side. Page, sort and filter interactions emit `pageChange` / `pageSizeChange` / `sortingChange` / `filterChange` (`columnFiltersChange`) so the caller can fetch the next slice:
78
+
79
+ ```ts
80
+ @Component({
81
+ selector: 'app-server-payments',
82
+ imports: [EgDataTable],
83
+ template: `
84
+ <eg-data-table
85
+ [columns]="columns"
86
+ [data]="page()"
87
+ [manualPagination]="true"
88
+ [isLoading]="loading()"
89
+ (pageChange)="load($event)"
90
+ />
91
+ `,
92
+ })
93
+ export class ServerPaymentsComponent {
94
+ protected readonly page = signal<EgPaginatedResponse<Payment> | null>(null);
95
+ protected readonly loading = signal(true);
96
+
97
+ load(pageIndex: number) {
98
+ // fetch `/api/payments?page=${pageIndex}` then `page.set(response)`
99
+ }
100
+ }
101
+ ```
102
+
103
+ ## Selection, sorting, grid layout
104
+
105
+ ```ts
106
+ <eg-data-table
107
+ [columns]="columns"
108
+ [gridColumns]="gridColumns"
109
+ [data]="payments()"
110
+ [enableSelection]="true"
111
+ [getRowId]="paymentId"
112
+ [(layout)]="layout"
113
+ (selectionChange)="onSelect($event)"
114
+ />
115
+ ```
116
+
117
+ - `enableSelection` auto-prepends a checkbox column; `selectionChange` emits the selected rows.
118
+ - Define `readonly paymentId = (payment: Payment): string => payment.id` on the host. `getRowId` is a pure callback returning a unique, stable string per entity; keep the callback reference stable.
119
+ - `[(layout)]` toggles `'table' | 'grid'` (grid requires `gridColumns`). Column `meta: { hideInTable: true }` hides a column in table layout; `meta: { thumbnail: true }` renders it as the card banner.
120
+ - Sortable plain-string headers get an inline sort button; richer headers should use `EgDataTableColumnHeader` via `flexRenderComponent` (no type arguments needed — its `column` input accepts any TanStack column through the `EgSortableColumn` structural type):
121
+
122
+ ```ts
123
+ import { flexRenderComponent } from '@tanstack/angular-table';
124
+ import { EgDataTableColumnHeader } from '@egose/shadcn-theme-ng/data-table';
125
+
126
+ helper.accessor('email', {
127
+ header: ({ column }) => flexRenderComponent(EgDataTableColumnHeader, { inputs: { column, title: 'Email' } }),
128
+ });
129
+ ```
130
+
131
+ ### Selection identity and scope
132
+
133
+ - **Stable IDs:** supply `getRowId` whenever rows can be refreshed, reordered, or fetched from a server. Selection follows IDs still present in the supplied rows, and refreshes emit the current objects, not stale snapshots. Removed IDs are discarded and are not selected if they later return. Changing the callback clears selection.
134
+ - **Server pages:** selection is scoped to the loaded slice, not an accumulated cross-page bulk-action set. Replacing a page keeps only selected IDs also in the new slice. Refreshing the same slice preserves selection when IDs match. Passing `null` or an empty slice clears it; keep the current slice and set `isLoading` if selection should survive loading a refresh.
135
+ - **Client filtering/paging:** `filterRows` defines the available selection scope; removing a row there discards its selection. Built-in column filters and client pagination only hide rows: hidden selections remain in `selectionChange`. Header selection toggles only the displayed page; table and grid share selection. The footer selection count describes the filtered subset.
136
+ - **Without `getRowId`:** existing positional `initialRowSelection` keys (`'0'`, `'1'`, etc.) remain supported for the initial rows. Replacing the source array (including a same-record refresh) or changing the `filterRows` result array clears selection rather than transferring an index to a different entity. Built-in sorting/filtering/paging with the same source array preserves it. This intentionally tightens the former unsafe positional behavior.
137
+ - **Updates and outputs:** update row arrays/objects immutably; in-place mutations are not tracked. `initialRowSelection` seeds only IDs present on initialization; later seed changes are ignored. `selectionChange` fires once on initialization, then when the selected objects or their source order change, including removal and refreshed object references. Unchanged selections do not re-emit for sorting, layout, or other unrelated state changes. IDs must be unique and must not be reused for different entities.
138
+
139
+ ## API reference
140
+
141
+ | Symbol | Kind |
142
+ | ---------------------------------------------------- | ---------------------------------------------------------------------------------------------------------- |
143
+ | `EgDataTable` | Component (`eg-data-table`), generic over `TData extends RowData` |
144
+ | `EgDataTableColumnHeader` | Sortable/hideable header component for `flexRenderComponent` usage (non-generic; takes `EgSortableColumn`) |
145
+ | `EgSortableColumn` | Minimal structural column surface the header needs (any TanStack `Column` satisfies it) |
146
+ | `EgDataTablePagination` | Standalone pager (`[tanStackTable]` DI) with page navigation + rows-per-page selector |
147
+ | `EgDataTablePagination` | Standalone pager reading the table from `[tanStackTable]` DI |
148
+ | `EgDataTableViewOptions` | Column-visibility dropdown reading the table from `[tanStackTable]` DI |
149
+ | `EgTableHeadSelection` / `EgTableRowSelection` | Selection checkboxes (auto-used when `enableSelection`) |
150
+ | `defaultEgDataTableFeatures` / `EgDataTableFeatures` | Default TanStack feature registry + type |
151
+ | `EgPaginatedResponse` | Server page-slice interface |
152
+ | `EgDataTableLayout` | `'table' \| 'grid'` |
153
+ | `EgDataTableImports` / `EgDataTableModule` | Standalone imports array / NgModule |
154
+
155
+ Key `EgDataTable` inputs: `columns` (required), `gridColumns`, `data` (array, or page slice with `manualPagination`), `manualPagination`, `size` (`sm` / `default` / `lg` density for toolbar, table, and pagination; type scale untouched), `filterRows` (caller pre-filter for client rows, before built-in filtering/sorting/pagination; ignored in server mode), `features`, `isLoading`, `emptyMessage`, `enableSelection`, `hideFooter`, `layout` (model), `showLayoutToggle`, `showToolbar`, `filterColumnId`, `filterPlaceholder`, `showColumnToggle`, `defaultPageSize`, `showPageSize`, `pageSizes`, plus `initialSorting` / `initialColumnFilters` / `initialColumnVisibility` / `initialRowSelection` to seed state once at creation (later changes are ignored — subscribe to the corresponding `*Change` outputs instead).
156
+
157
+ Outputs: `selectionChange` (also fires once on init, mirroring React's mount effect), `pageChange`, `pageSizeChange`, `rowClick`, `sortingChange`, `columnFiltersChange`, `filterChange` (toolbar input string), `columnVisibilityChange`.
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.
160
+
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
+
163
+ `rowClick` fires for table-row and grid-card clicks with the row's data. Clicks from nested interactive elements (buttons, links, inputs, checkboxes, selects) are ignored so selection checkboxes and row-action buttons keep working without also firing `rowClick`.
164
+
165
+ The footer pager includes a rows-per-page selector (`pageSizes`, default `[10, 20, 30, 40, 50]`; the table's current size is appended when absent). In client mode the table re-paginates immediately; in server mode the change surfaces via `pageSizeChange` so the caller can refetch with the new limit. Set `showPageSize` to `false` to hide it. `navMode` switches the navigation buttons between `icons` (default), `text` (`First`/`Previous`/`Next`/`Last`), and `both`. `EgDataTablePagination` exposes the same `showStatus` / `showPageSize` / `pageSizes` / `navMode` inputs for custom compositions.
166
+
167
+ ## Related subpaths
168
+
169
+ - `@egose/shadcn-theme-ng/table` — the underlying styling directives.
170
+ - `@egose/shadcn-theme-ng/checkbox` — selection cells.
171
+ - `@egose/shadcn-theme-ng/card` — grid-layout cards.
172
+ - `@egose/shadcn-theme-ng/toggle-group` — layout switch.
173
+ - `@egose/shadcn-theme-ng/spinner` — loading indicator.
174
+ - `@egose/shadcn-theme-ng/pagination` — standalone paging controls for custom compositions.