@frame-kit/ui-ng 0.2.4 → 0.2.6
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/package.json
CHANGED
|
@@ -40,6 +40,19 @@ interface TableConfig<T = unknown> {
|
|
|
40
40
|
emptyMessage: string;
|
|
41
41
|
trackBy: (index: number, row: T) => unknown;
|
|
42
42
|
rowStyleFn: ((row: T, index: number) => Record<string, string> | null) | null;
|
|
43
|
+
/**
|
|
44
|
+
* Groups consecutive rows under a heading. Returns the group key for a row,
|
|
45
|
+
* or `null` to leave it ungrouped; a heading is emitted wherever the key
|
|
46
|
+
* changes from the previous row.
|
|
47
|
+
*
|
|
48
|
+
* Grouping reads the rows in the order they are already sorted — it does not
|
|
49
|
+
* reorder them. Sort by the same field you group on, or the same group will
|
|
50
|
+
* open more than once.
|
|
51
|
+
*
|
|
52
|
+
* Mutually exclusive with virtualization, which assumes every row is
|
|
53
|
+
* `rowHeight` tall; a heading is not. Setting this turns virtualization off.
|
|
54
|
+
*/
|
|
55
|
+
groupBy: ((row: T) => string | null) | null;
|
|
43
56
|
virtualization: boolean | 'auto';
|
|
44
57
|
virtualizationThreshold: number;
|
|
45
58
|
rowHeight: number;
|
|
@@ -245,6 +258,15 @@ declare class DataTableComponent<T = unknown> {
|
|
|
245
258
|
readonly expandableRow: _angular_core.InputSignal<((row: T) => boolean) | null>;
|
|
246
259
|
/** Accessible label for each row's expansion chevron. */
|
|
247
260
|
readonly expansionLabel: _angular_core.InputSignal<string>;
|
|
261
|
+
/**
|
|
262
|
+
* Template rendered inside a group heading. Receives the group key and the
|
|
263
|
+
* first row of the group, so a heading can show more than the key it was
|
|
264
|
+
* grouped by. Omit it and the key is rendered as text.
|
|
265
|
+
*/
|
|
266
|
+
readonly groupHeadingRenderer: _angular_core.InputSignal<TemplateRef<{
|
|
267
|
+
$implicit: string;
|
|
268
|
+
row: T;
|
|
269
|
+
}> | null>;
|
|
248
270
|
/** Fires when the user clicks a sortable column header, emitting the new sort state. */
|
|
249
271
|
readonly sortChange: _angular_core.OutputEmitterRef<SortState>;
|
|
250
272
|
/** Fires when a filter changes, emitting the updated filter state. */
|
|
@@ -269,6 +291,11 @@ declare class DataTableComponent<T = unknown> {
|
|
|
269
291
|
readonly useVirtualization: _angular_core.Signal<boolean>;
|
|
270
292
|
readonly virtualRows: _angular_core.Signal<T[]>;
|
|
271
293
|
readonly virtualStartIndex: _angular_core.Signal<number>;
|
|
294
|
+
/**
|
|
295
|
+
* How many cells a heading has to span — the visible columns plus whichever
|
|
296
|
+
* of the selection and expansion cells the table is currently rendering.
|
|
297
|
+
*/
|
|
298
|
+
readonly groupHeadingSpan: _angular_core.Signal<number>;
|
|
272
299
|
readonly isEmpty: _angular_core.Signal<boolean>;
|
|
273
300
|
readonly classes: _angular_core.Signal<string>;
|
|
274
301
|
get hostClass(): string;
|
|
@@ -282,6 +309,8 @@ declare class DataTableComponent<T = unknown> {
|
|
|
282
309
|
*/
|
|
283
310
|
private readonly groupCoordinator;
|
|
284
311
|
constructor();
|
|
312
|
+
/** The group heading to open before this row, if it starts a new group. */
|
|
313
|
+
groupHeadingFor(row: T, index: number): string | null;
|
|
285
314
|
/** Resolves the display value for a cell given its column definition and row data. */
|
|
286
315
|
getCellValue(column: ColumnDef<T>, row: T): unknown;
|
|
287
316
|
/** Returns the trackBy function from the merged config for use in `*ngFor`. */
|
|
@@ -372,7 +401,7 @@ declare class DataTableComponent<T = unknown> {
|
|
|
372
401
|
/** Returns the current sort direction for the given column id, or null if not sorted. */
|
|
373
402
|
getSortDirection(columnId: string): 'asc' | 'desc' | null;
|
|
374
403
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<DataTableComponent<any>, never>;
|
|
375
|
-
static ɵcmp: _angular_core.ɵɵComponentDeclaration<DataTableComponent<any>, "fk-data-table", never, { "className": { "alias": "className"; "required": false; "isSignal": true; }; "id": { "alias": "id"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "ariaLabel"; "required": false; "isSignal": true; }; "columns": { "alias": "columns"; "required": false; "isSignal": true; }; "rows": { "alias": "rows"; "required": false; "isSignal": true; }; "config": { "alias": "config"; "required": false; "isSignal": true; }; "loading": { "alias": "loading"; "required": false; "isSignal": true; }; "sortState": { "alias": "sortState"; "required": false; "isSignal": true; }; "filterState": { "alias": "filterState"; "required": false; "isSignal": true; }; "pageState": { "alias": "pageState"; "required": false; "isSignal": true; }; "rowSelection": { "alias": "rowSelection"; "required": false; "isSignal": true; }; "selectedKeys": { "alias": "selectedKeys"; "required": false; "isSignal": true; }; "getRowId": { "alias": "getRowId"; "required": false; "isSignal": true; }; "selectionDisabled": { "alias": "selectionDisabled"; "required": false; "isSignal": true; }; "selectionColumnPosition": { "alias": "selectionColumnPosition"; "required": false; "isSignal": true; }; "selectionLabel": { "alias": "selectionLabel"; "required": false; "isSignal": true; }; "rowDetailTemplate": { "alias": "rowDetailTemplate"; "required": false; "isSignal": true; }; "expansionColumnPosition": { "alias": "expansionColumnPosition"; "required": false; "isSignal": true; }; "expandedKeys": { "alias": "expandedKeys"; "required": false; "isSignal": true; }; "expandableRow": { "alias": "expandableRow"; "required": false; "isSignal": true; }; "expansionLabel": { "alias": "expansionLabel"; "required": false; "isSignal": true; }; }, { "sortChange": "sortChange"; "filterChange": "filterChange"; "pageChange": "pageChange"; "rowClick": "rowClick"; "selectionChange": "selectionChange"; "expansionChange": "expansionChange"; "columnResize": "columnResize"; }, never, never, true, never>;
|
|
404
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<DataTableComponent<any>, "fk-data-table", never, { "className": { "alias": "className"; "required": false; "isSignal": true; }; "id": { "alias": "id"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "ariaLabel"; "required": false; "isSignal": true; }; "columns": { "alias": "columns"; "required": false; "isSignal": true; }; "rows": { "alias": "rows"; "required": false; "isSignal": true; }; "config": { "alias": "config"; "required": false; "isSignal": true; }; "loading": { "alias": "loading"; "required": false; "isSignal": true; }; "sortState": { "alias": "sortState"; "required": false; "isSignal": true; }; "filterState": { "alias": "filterState"; "required": false; "isSignal": true; }; "pageState": { "alias": "pageState"; "required": false; "isSignal": true; }; "rowSelection": { "alias": "rowSelection"; "required": false; "isSignal": true; }; "selectedKeys": { "alias": "selectedKeys"; "required": false; "isSignal": true; }; "getRowId": { "alias": "getRowId"; "required": false; "isSignal": true; }; "selectionDisabled": { "alias": "selectionDisabled"; "required": false; "isSignal": true; }; "selectionColumnPosition": { "alias": "selectionColumnPosition"; "required": false; "isSignal": true; }; "selectionLabel": { "alias": "selectionLabel"; "required": false; "isSignal": true; }; "rowDetailTemplate": { "alias": "rowDetailTemplate"; "required": false; "isSignal": true; }; "expansionColumnPosition": { "alias": "expansionColumnPosition"; "required": false; "isSignal": true; }; "expandedKeys": { "alias": "expandedKeys"; "required": false; "isSignal": true; }; "expandableRow": { "alias": "expandableRow"; "required": false; "isSignal": true; }; "expansionLabel": { "alias": "expansionLabel"; "required": false; "isSignal": true; }; "groupHeadingRenderer": { "alias": "groupHeadingRenderer"; "required": false; "isSignal": true; }; }, { "sortChange": "sortChange"; "filterChange": "filterChange"; "pageChange": "pageChange"; "rowClick": "rowClick"; "selectionChange": "selectionChange"; "expansionChange": "expansionChange"; "columnResize": "columnResize"; }, never, never, true, never>;
|
|
376
405
|
}
|
|
377
406
|
|
|
378
407
|
/**
|
|
@@ -446,6 +475,14 @@ declare class DataTableStackComponent<T = unknown> {
|
|
|
446
475
|
readonly config: _angular_core.InputSignal<TableConfig<T> | null>;
|
|
447
476
|
/** TrackBy function used by the `@for` loop over rows. */
|
|
448
477
|
readonly trackByFn: _angular_core.InputSignal<(index: number, row: T) => unknown>;
|
|
478
|
+
/**
|
|
479
|
+
* Template rendered inside a group heading. Mirrors the semantic-table path
|
|
480
|
+
* so a grouped table looks grouped at every viewport.
|
|
481
|
+
*/
|
|
482
|
+
readonly groupHeadingRenderer: _angular_core.InputSignal<TemplateRef<{
|
|
483
|
+
$implicit: string;
|
|
484
|
+
row: T;
|
|
485
|
+
}> | null>;
|
|
449
486
|
/** Mirrors the host table's `rowSelection` input to show checkboxes on each card. */
|
|
450
487
|
readonly rowSelection: _angular_core.InputSignal<boolean>;
|
|
451
488
|
/** Currently selected row keys forwarded from the host table engine. */
|
|
@@ -456,6 +493,8 @@ declare class DataTableStackComponent<T = unknown> {
|
|
|
456
493
|
readonly selectionDisabled: _angular_core.InputSignal<SelectionDisabled<T>>;
|
|
457
494
|
/** Accessible label for each card's selection checkbox. */
|
|
458
495
|
readonly selectionLabel: _angular_core.InputSignal<string>;
|
|
496
|
+
/** The group heading to open before this card, if it starts a new group. */
|
|
497
|
+
groupHeadingFor(row: T, index: number): string | null;
|
|
459
498
|
/** Fires when the user clicks a card row, emitting the row context. */
|
|
460
499
|
readonly rowClick: _angular_core.OutputEmitterRef<TableRowContext<T>>;
|
|
461
500
|
/** Fires when the user toggles a card's selection checkbox, bubbling up to the host. */
|
|
@@ -475,7 +514,7 @@ declare class DataTableStackComponent<T = unknown> {
|
|
|
475
514
|
isRowSelectionDisabled(row: T): boolean;
|
|
476
515
|
private getSelectionKey;
|
|
477
516
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<DataTableStackComponent<any>, never>;
|
|
478
|
-
static ɵcmp: _angular_core.ɵɵComponentDeclaration<DataTableStackComponent<any>, "fk-data-table-stack", never, { "rows": { "alias": "rows"; "required": false; "isSignal": true; }; "columns": { "alias": "columns"; "required": false; "isSignal": true; }; "config": { "alias": "config"; "required": false; "isSignal": true; }; "trackByFn": { "alias": "trackByFn"; "required": false; "isSignal": true; }; "rowSelection": { "alias": "rowSelection"; "required": false; "isSignal": true; }; "selectedKeys": { "alias": "selectedKeys"; "required": false; "isSignal": true; }; "getRowId": { "alias": "getRowId"; "required": false; "isSignal": true; }; "selectionDisabled": { "alias": "selectionDisabled"; "required": false; "isSignal": true; }; "selectionLabel": { "alias": "selectionLabel"; "required": false; "isSignal": true; }; }, { "rowClick": "rowClick"; "toggleRow": "toggleRow"; }, never, never, true, never>;
|
|
517
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<DataTableStackComponent<any>, "fk-data-table-stack", never, { "rows": { "alias": "rows"; "required": false; "isSignal": true; }; "columns": { "alias": "columns"; "required": false; "isSignal": true; }; "config": { "alias": "config"; "required": false; "isSignal": true; }; "trackByFn": { "alias": "trackByFn"; "required": false; "isSignal": true; }; "groupHeadingRenderer": { "alias": "groupHeadingRenderer"; "required": false; "isSignal": true; }; "rowSelection": { "alias": "rowSelection"; "required": false; "isSignal": true; }; "selectedKeys": { "alias": "selectedKeys"; "required": false; "isSignal": true; }; "getRowId": { "alias": "getRowId"; "required": false; "isSignal": true; }; "selectionDisabled": { "alias": "selectionDisabled"; "required": false; "isSignal": true; }; "selectionLabel": { "alias": "selectionLabel"; "required": false; "isSignal": true; }; }, { "rowClick": "rowClick"; "toggleRow": "toggleRow"; }, never, never, true, never>;
|
|
479
518
|
}
|
|
480
519
|
|
|
481
520
|
export { ColumnResizeDirective, DEFAULT_TABLE_CONFIG, DataTableComponent, DataTableGroupComponent, DataTableGroupCoordinator, DataTableStackComponent, ResponsiveStrategyService, TableEngineService, VirtualizationEngineService };
|
package/ui/data-table/README.md
CHANGED
|
@@ -8,24 +8,25 @@ A token-driven, responsive data table component for Angular with sorting, virtua
|
|
|
8
8
|
|
|
9
9
|
### Inputs
|
|
10
10
|
|
|
11
|
-
| Input | Type
|
|
12
|
-
| ------------------------- |
|
|
13
|
-
| `columns` | `ColumnDef<T>[]`
|
|
14
|
-
| `rows` | `T[]`
|
|
15
|
-
| `config` | `Partial<TableConfig<T>>`
|
|
16
|
-
| `loading` | `boolean`
|
|
17
|
-
| `sortState` | `SortState \| null`
|
|
18
|
-
| `filterState` | `FilterState \| null`
|
|
19
|
-
| `pageState` | `PageState \| null`
|
|
20
|
-
| `rowSelection` | `boolean`
|
|
21
|
-
| `selectedKeys` | `Set<unknown> \| null`
|
|
22
|
-
| `getRowId` | `(row: T) => unknown` \| `null`
|
|
23
|
-
| `selectionDisabled` | `boolean \| ((row: T) => boolean)`
|
|
24
|
-
| `selectionColumnPosition` | `'start' \| 'end'`
|
|
25
|
-
| `selectionLabel` | `string`
|
|
26
|
-
| `
|
|
27
|
-
| `
|
|
28
|
-
| `
|
|
11
|
+
| Input | Type | Default | Description |
|
|
12
|
+
| ------------------------- | ---------------------------------------------------- | -------------- | ---------------------------------------------------------------------------------------------------- |
|
|
13
|
+
| `columns` | `ColumnDef<T>[]` | `[]` | Column definitions describing headers, accessors, and behavior |
|
|
14
|
+
| `rows` | `T[]` | `[]` | Data rows to render |
|
|
15
|
+
| `config` | `Partial<TableConfig<T>>` | `{}` | Table configuration merged with defaults |
|
|
16
|
+
| `loading` | `boolean` | `false` | Shows a loading overlay |
|
|
17
|
+
| `sortState` | `SortState \| null` | `null` | Controlled sort state; `null` uses internal state |
|
|
18
|
+
| `filterState` | `FilterState \| null` | `null` | Controlled filter state; `null` uses internal state |
|
|
19
|
+
| `pageState` | `PageState \| null` | `null` | Controlled page state; `null` uses internal state |
|
|
20
|
+
| `rowSelection` | `boolean` | `false` | Render a leading (or trailing) checkbox column with multi-row selection |
|
|
21
|
+
| `selectedKeys` | `Set<unknown> \| null` | `null` | Controlled selection set; `null` uses internal state. Table never mutates the input — emits new Sets |
|
|
22
|
+
| `getRowId` | `(row: T) => unknown` \| `null` | `null` | Required when `rowSelection` is `true`. Returns each row's stable identity key |
|
|
23
|
+
| `selectionDisabled` | `boolean \| ((row: T) => boolean)` | `false` | Per-row opt-out. Disabled rows can't be selected and are skipped by the header "select all" |
|
|
24
|
+
| `selectionColumnPosition` | `'start' \| 'end'` | `'start'` | Render the checkbox column at the leading or trailing edge |
|
|
25
|
+
| `selectionLabel` | `string` | `'Select row'` | `aria-label` applied to each row checkbox |
|
|
26
|
+
| `groupHeadingRenderer` | `TemplateRef<{ $implicit: string; row: T }> \| null` | `null` | Template for a group heading; omit to render the group key as text |
|
|
27
|
+
| `className` | `string` | `''` | Additional CSS classes for the host |
|
|
28
|
+
| `id` | `string \| null` | `null` | Optional ID for the host element |
|
|
29
|
+
| `ariaLabel` | `string \| null` | `null` | ARIA label for the table |
|
|
29
30
|
|
|
30
31
|
### Outputs
|
|
31
32
|
|
|
@@ -74,6 +75,7 @@ A token-driven, responsive data table component for Angular with sorting, virtua
|
|
|
74
75
|
| `rowExpansion` | `boolean` | `false` | Enable row expansion |
|
|
75
76
|
| `emptyMessage` | `string` | `'No data available'` | Message shown when no rows exist |
|
|
76
77
|
| `trackBy` | `(index: number, row: T) => unknown` | `(index) => index` | Track-by function for row rendering |
|
|
78
|
+
| `groupBy` | `((row: T) => string \| null) \| null` | `null` | Group consecutive rows under a heading (see below) |
|
|
77
79
|
| `virtualization` | `boolean \| 'auto'` | `'auto'` | Virtual scrolling mode |
|
|
78
80
|
| `virtualizationThreshold` | `number` | `200` | Row count threshold for auto-activating virtualization |
|
|
79
81
|
| `rowHeight` | `number` | `48` | Fixed row height in px (required for virtual scrolling) |
|
|
@@ -235,6 +237,39 @@ isLocked = (row: Order) => row.status === 'Closed';
|
|
|
235
237
|
<fk-data-table [columns]="columns" [rows]="[]" [config]="{ emptyMessage: 'No records found' }" />
|
|
236
238
|
```
|
|
237
239
|
|
|
240
|
+
### Row grouping
|
|
241
|
+
|
|
242
|
+
Rows sharing a group key render under a heading spanning the full table:
|
|
243
|
+
|
|
244
|
+
```html
|
|
245
|
+
<fk-data-table [columns]="columns" [rows]="events" [config]="{ groupBy: byDay }" />
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
```ts
|
|
249
|
+
byDay = (row: Event) => this.formatDay(row.created_at);
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
Return `null` from `groupBy` to leave a row ungrouped.
|
|
253
|
+
|
|
254
|
+
Grouping reads the rows in the order it is handed them — it does not reorder.
|
|
255
|
+
Sort by the same field you group on, or a group will open more than once.
|
|
256
|
+
|
|
257
|
+
For a heading richer than the key, pass a template:
|
|
258
|
+
|
|
259
|
+
```html
|
|
260
|
+
<fk-data-table [columns]="columns" [rows]="events" [config]="{ groupBy: byDay }" [groupHeadingRenderer]="dayHeading" />
|
|
261
|
+
|
|
262
|
+
<ng-template #dayHeading let-key let-row="row"> {{ key }} <span class="muted">{{ row.created_at | date }}</span> </ng-template>
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
Headings render on both the semantic-table and stack (small-viewport) paths, so
|
|
266
|
+
a grouped table stays grouped at every width.
|
|
267
|
+
|
|
268
|
+
> **Grouping and virtualization are mutually exclusive.** Virtual scrolling
|
|
269
|
+
> positions rows by multiplying an index by `rowHeight`, and a heading is not
|
|
270
|
+
> that tall. Setting `groupBy` turns virtualization off rather than misplacing
|
|
271
|
+
> every row after the first heading.
|
|
272
|
+
|
|
238
273
|
### Virtual scrolling
|
|
239
274
|
|
|
240
275
|
Virtual scrolling activates automatically when row count exceeds `virtualizationThreshold` (default 200). Force it on or off:
|
|
@@ -341,6 +376,15 @@ Pinned columns stick to the left or right edge when scrolling horizontally.
|
|
|
341
376
|
--fk-data-table-row-hover-bg
|
|
342
377
|
--fk-data-table-viewport-height
|
|
343
378
|
|
|
379
|
+
// Group headings
|
|
380
|
+
--fk-data-table-group-heading-bg
|
|
381
|
+
--fk-data-table-group-heading-color
|
|
382
|
+
--fk-data-table-group-heading-font-size
|
|
383
|
+
--fk-data-table-group-heading-font-weight
|
|
384
|
+
--fk-data-table-group-heading-letter-spacing
|
|
385
|
+
--fk-data-table-group-heading-text-transform
|
|
386
|
+
--fk-data-table-group-heading-padding
|
|
387
|
+
|
|
344
388
|
// Empty & Loading
|
|
345
389
|
--fk-data-table-empty-padding
|
|
346
390
|
--fk-data-table-empty-color
|