@frame-kit/ui-ng 0.2.3 → 0.2.5
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/fesm2022/frame-kit-ui-ng-ui-data-table.mjs +52 -4
- package/fesm2022/frame-kit-ui-ng-ui-data-table.mjs.map +1 -1
- package/fesm2022/frame-kit-ui-ng-ui-nav-brand.mjs +2 -2
- package/fesm2022/frame-kit-ui-ng-ui-nav-brand.mjs.map +1 -1
- package/package.json +1 -1
- package/types/frame-kit-ui-ng-ui-data-table.d.ts +33 -1
- package/ui/data-table/README.md +59 -18
|
@@ -30,11 +30,11 @@ class NavBrandComponent {
|
|
|
30
30
|
return this.classes();
|
|
31
31
|
}
|
|
32
32
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: NavBrandComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
33
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: NavBrandComponent, isStandalone: true, selector: "fk-nav-brand", inputs: { brandText: { classPropertyName: "brandText", publicName: "brandText", isSignal: true, isRequired: true, transformFunction: null }, href: { classPropertyName: "href", publicName: "href", isSignal: true, isRequired: false, transformFunction: null }, description: { classPropertyName: "description", publicName: "description", isSignal: true, isRequired: false, transformFunction: null }, id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, className: { classPropertyName: "className", publicName: "className", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "this.hostClass" } }, ngImport: i0, template: "<a\n class=\"fk-nav-brand__link\"\n [routerLink]=\"href()\"\n [attr.id]=\"id()\"\n [attr.aria-label]=\"ariaLabel()\"\n>\n <span class=\"fk-nav-brand__logo\">\n <ng-content select=\"[navLogo]\"></ng-content>\n </span>\n <span class=\"fk-nav-brand__body\">\n <span class=\"fk-nav-brand__text\">{{ brandText() }}</span>\n @if (description(); as brandDescription) {\n <span class=\"fk-nav-brand__description\">{{ brandDescription }}</span>\n }\n </span>\n</a>\n", styles: [":host{display:inline-block;max-width:100
|
|
33
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: NavBrandComponent, isStandalone: true, selector: "fk-nav-brand", inputs: { brandText: { classPropertyName: "brandText", publicName: "brandText", isSignal: true, isRequired: true, transformFunction: null }, href: { classPropertyName: "href", publicName: "href", isSignal: true, isRequired: false, transformFunction: null }, description: { classPropertyName: "description", publicName: "description", isSignal: true, isRequired: false, transformFunction: null }, id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, className: { classPropertyName: "className", publicName: "className", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "this.hostClass" } }, ngImport: i0, template: "<a\n class=\"fk-nav-brand__link\"\n [routerLink]=\"href()\"\n [attr.id]=\"id()\"\n [attr.aria-label]=\"ariaLabel()\"\n>\n <span class=\"fk-nav-brand__logo\">\n <ng-content select=\"[navLogo]\"></ng-content>\n </span>\n <span class=\"fk-nav-brand__body\">\n <span class=\"fk-nav-brand__text\">{{ brandText() }}</span>\n @if (description(); as brandDescription) {\n <span class=\"fk-nav-brand__description\">{{ brandDescription }}</span>\n }\n </span>\n</a>\n", styles: [":host{display:inline-block;max-width:100%;min-width:0}.fk-nav-brand__link{display:flex;width:100%;align-items:center;gap:var(--fk-nav-brand-gap, .5rem);text-decoration:none;color:var(--fk-nav-brand-color, inherit);min-width:0}.fk-nav-brand__link:hover{color:var(--fk-nav-brand-color-hover, inherit)}.fk-nav-brand__logo{display:inline-flex;flex:none;align-items:center}.fk-nav-brand__body{display:flex;flex:1 1 auto;flex-direction:column;justify-content:center;align-items:flex-start;min-width:0;gap:var(--fk-nav-brand-description-gap, .125rem)}.fk-nav-brand__text{font-family:var(--fk-nav-brand-font-family, var(--fk-font-family-display, var(--fk-font-family-base, sans-serif)));font-size:var(--fk-nav-brand-font-size, 1.125rem);font-weight:var(--fk-nav-brand-font-weight, 600);line-height:var(--fk-nav-brand-line-height, 1);white-space:nowrap;max-width:100%;overflow:hidden;text-overflow:ellipsis}.fk-nav-brand__description{font-family:var(--fk-nav-brand-description-font-family, var(--fk-font-family-base, sans-serif));font-size:var(--fk-nav-brand-description-font-size, .6875rem);font-weight:var(--fk-nav-brand-description-font-weight, 500);line-height:var(--fk-nav-brand-description-line-height, 1.2);letter-spacing:var(--fk-nav-brand-description-letter-spacing, .02em);color:var(--fk-nav-brand-description-color, var(--fk-color-muted, inherit));white-space:nowrap;max-width:100%;overflow:hidden;text-overflow:ellipsis}\n"], dependencies: [{ kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i1.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
34
34
|
}
|
|
35
35
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: NavBrandComponent, decorators: [{
|
|
36
36
|
type: Component,
|
|
37
|
-
args: [{ selector: 'fk-nav-brand', standalone: true, imports: [RouterModule], changeDetection: ChangeDetectionStrategy.OnPush, template: "<a\n class=\"fk-nav-brand__link\"\n [routerLink]=\"href()\"\n [attr.id]=\"id()\"\n [attr.aria-label]=\"ariaLabel()\"\n>\n <span class=\"fk-nav-brand__logo\">\n <ng-content select=\"[navLogo]\"></ng-content>\n </span>\n <span class=\"fk-nav-brand__body\">\n <span class=\"fk-nav-brand__text\">{{ brandText() }}</span>\n @if (description(); as brandDescription) {\n <span class=\"fk-nav-brand__description\">{{ brandDescription }}</span>\n }\n </span>\n</a>\n", styles: [":host{display:inline-block;max-width:100
|
|
37
|
+
args: [{ selector: 'fk-nav-brand', standalone: true, imports: [RouterModule], changeDetection: ChangeDetectionStrategy.OnPush, template: "<a\n class=\"fk-nav-brand__link\"\n [routerLink]=\"href()\"\n [attr.id]=\"id()\"\n [attr.aria-label]=\"ariaLabel()\"\n>\n <span class=\"fk-nav-brand__logo\">\n <ng-content select=\"[navLogo]\"></ng-content>\n </span>\n <span class=\"fk-nav-brand__body\">\n <span class=\"fk-nav-brand__text\">{{ brandText() }}</span>\n @if (description(); as brandDescription) {\n <span class=\"fk-nav-brand__description\">{{ brandDescription }}</span>\n }\n </span>\n</a>\n", styles: [":host{display:inline-block;max-width:100%;min-width:0}.fk-nav-brand__link{display:flex;width:100%;align-items:center;gap:var(--fk-nav-brand-gap, .5rem);text-decoration:none;color:var(--fk-nav-brand-color, inherit);min-width:0}.fk-nav-brand__link:hover{color:var(--fk-nav-brand-color-hover, inherit)}.fk-nav-brand__logo{display:inline-flex;flex:none;align-items:center}.fk-nav-brand__body{display:flex;flex:1 1 auto;flex-direction:column;justify-content:center;align-items:flex-start;min-width:0;gap:var(--fk-nav-brand-description-gap, .125rem)}.fk-nav-brand__text{font-family:var(--fk-nav-brand-font-family, var(--fk-font-family-display, var(--fk-font-family-base, sans-serif)));font-size:var(--fk-nav-brand-font-size, 1.125rem);font-weight:var(--fk-nav-brand-font-weight, 600);line-height:var(--fk-nav-brand-line-height, 1);white-space:nowrap;max-width:100%;overflow:hidden;text-overflow:ellipsis}.fk-nav-brand__description{font-family:var(--fk-nav-brand-description-font-family, var(--fk-font-family-base, sans-serif));font-size:var(--fk-nav-brand-description-font-size, .6875rem);font-weight:var(--fk-nav-brand-description-font-weight, 500);line-height:var(--fk-nav-brand-description-line-height, 1.2);letter-spacing:var(--fk-nav-brand-description-letter-spacing, .02em);color:var(--fk-nav-brand-description-color, var(--fk-color-muted, inherit));white-space:nowrap;max-width:100%;overflow:hidden;text-overflow:ellipsis}\n"] }]
|
|
38
38
|
}], propDecorators: { brandText: [{ type: i0.Input, args: [{ isSignal: true, alias: "brandText", required: true }] }], href: [{ type: i0.Input, args: [{ isSignal: true, alias: "href", required: false }] }], description: [{ type: i0.Input, args: [{ isSignal: true, alias: "description", required: false }] }], id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], className: [{ type: i0.Input, args: [{ isSignal: true, alias: "className", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], hostClass: [{
|
|
39
39
|
type: HostBinding,
|
|
40
40
|
args: ['class']
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"frame-kit-ui-ng-ui-nav-brand.mjs","sources":["../../../../packages/ui-ng/ui/nav-brand/nav-brand.component.ts","../../../../packages/ui-ng/ui/nav-brand/nav-brand.component.html","../../../../packages/ui-ng/ui/nav-brand/frame-kit-ui-ng-ui-nav-brand.ts"],"sourcesContent":["import {\n ChangeDetectionStrategy,\n Component,\n computed,\n HostBinding,\n input,\n} from '@angular/core';\nimport { RouterModule } from '@angular/router';\n\n@Component({\n selector: 'fk-nav-brand',\n standalone: true,\n imports: [RouterModule],\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './nav-brand.component.html',\n styleUrl: './nav-brand.component.scss',\n})\nexport class NavBrandComponent {\n // ===== REQUIRED =====\n /** Brand or application name rendered as the nav logo text. */\n readonly brandText = input.required<string>();\n\n // ===== OPTIONAL =====\n /** Router path the brand link navigates to when clicked. */\n readonly href = input<string>('/');\n\n /**\n * Secondary line under the brand text — typically the product or edition the\n * brand is qualifying (\"Developer Console\", \"Admin Workspace\"). Omit it and\n * the brand text stays a single line, centered against the logo exactly as\n * before; supply it and the two lines are centered against the logo as one\n * block, left-aligned with each other.\n */\n readonly description = input<string | null>(null);\n\n // ===== BASE PROPS =====\n readonly id = input<string | null>(null);\n readonly className = input<string>('');\n readonly ariaLabel = input<string | null>(null);\n\n // ===== COMPUTED =====\n readonly classes = computed(() => {\n return ['fk-nav-brand', this.className()].filter(Boolean).join(' ');\n });\n\n @HostBinding('class')\n get hostClass() {\n return this.classes();\n }\n}\n","<a\n class=\"fk-nav-brand__link\"\n [routerLink]=\"href()\"\n [attr.id]=\"id()\"\n [attr.aria-label]=\"ariaLabel()\"\n>\n <span class=\"fk-nav-brand__logo\">\n <ng-content select=\"[navLogo]\"></ng-content>\n </span>\n <span class=\"fk-nav-brand__body\">\n <span class=\"fk-nav-brand__text\">{{ brandText() }}</span>\n @if (description(); as brandDescription) {\n <span class=\"fk-nav-brand__description\">{{ brandDescription }}</span>\n }\n </span>\n</a>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;;;MAiBa,iBAAiB,CAAA;;;AAGnB,IAAA,SAAS,GAAG,KAAK,CAAC,QAAQ,+EAAU;;;AAIpC,IAAA,IAAI,GAAG,KAAK,CAAS,GAAG,2EAAC;AAElC;;;;;;AAMG;AACM,IAAA,WAAW,GAAG,KAAK,CAAgB,IAAI,kFAAC;;AAGxC,IAAA,EAAE,GAAG,KAAK,CAAgB,IAAI,yEAAC;AAC/B,IAAA,SAAS,GAAG,KAAK,CAAS,EAAE,gFAAC;AAC7B,IAAA,SAAS,GAAG,KAAK,CAAgB,IAAI,gFAAC;;AAGtC,IAAA,OAAO,GAAG,QAAQ,CAAC,MAAK;AAC/B,QAAA,OAAO,CAAC,cAAc,EAAE,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;AACrE,IAAA,CAAC,8EAAC;AAEF,IAAA,IACI,SAAS,GAAA;AACX,QAAA,OAAO,IAAI,CAAC,OAAO,EAAE;IACvB;uGA/BW,iBAAiB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;2FAAjB,iBAAiB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,cAAA,EAAA,MAAA,EAAA,EAAA,SAAA,EAAA,EAAA,iBAAA,EAAA,WAAA,EAAA,UAAA,EAAA,WAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,IAAA,EAAA,EAAA,iBAAA,EAAA,MAAA,EAAA,UAAA,EAAA,MAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,WAAA,EAAA,EAAA,iBAAA,EAAA,aAAA,EAAA,UAAA,EAAA,aAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,EAAA,EAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,SAAA,EAAA,EAAA,iBAAA,EAAA,WAAA,EAAA,UAAA,EAAA,WAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,SAAA,EAAA,EAAA,iBAAA,EAAA,WAAA,EAAA,UAAA,EAAA,WAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,EAAA,IAAA,EAAA,EAAA,UAAA,EAAA,EAAA,OAAA,EAAA,gBAAA,EAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,ECjB9B,oeAgBA,EAAA,MAAA,EAAA,CAAA,
|
|
1
|
+
{"version":3,"file":"frame-kit-ui-ng-ui-nav-brand.mjs","sources":["../../../../packages/ui-ng/ui/nav-brand/nav-brand.component.ts","../../../../packages/ui-ng/ui/nav-brand/nav-brand.component.html","../../../../packages/ui-ng/ui/nav-brand/frame-kit-ui-ng-ui-nav-brand.ts"],"sourcesContent":["import {\n ChangeDetectionStrategy,\n Component,\n computed,\n HostBinding,\n input,\n} from '@angular/core';\nimport { RouterModule } from '@angular/router';\n\n@Component({\n selector: 'fk-nav-brand',\n standalone: true,\n imports: [RouterModule],\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './nav-brand.component.html',\n styleUrl: './nav-brand.component.scss',\n})\nexport class NavBrandComponent {\n // ===== REQUIRED =====\n /** Brand or application name rendered as the nav logo text. */\n readonly brandText = input.required<string>();\n\n // ===== OPTIONAL =====\n /** Router path the brand link navigates to when clicked. */\n readonly href = input<string>('/');\n\n /**\n * Secondary line under the brand text — typically the product or edition the\n * brand is qualifying (\"Developer Console\", \"Admin Workspace\"). Omit it and\n * the brand text stays a single line, centered against the logo exactly as\n * before; supply it and the two lines are centered against the logo as one\n * block, left-aligned with each other.\n */\n readonly description = input<string | null>(null);\n\n // ===== BASE PROPS =====\n readonly id = input<string | null>(null);\n readonly className = input<string>('');\n readonly ariaLabel = input<string | null>(null);\n\n // ===== COMPUTED =====\n readonly classes = computed(() => {\n return ['fk-nav-brand', this.className()].filter(Boolean).join(' ');\n });\n\n @HostBinding('class')\n get hostClass() {\n return this.classes();\n }\n}\n","<a\n class=\"fk-nav-brand__link\"\n [routerLink]=\"href()\"\n [attr.id]=\"id()\"\n [attr.aria-label]=\"ariaLabel()\"\n>\n <span class=\"fk-nav-brand__logo\">\n <ng-content select=\"[navLogo]\"></ng-content>\n </span>\n <span class=\"fk-nav-brand__body\">\n <span class=\"fk-nav-brand__text\">{{ brandText() }}</span>\n @if (description(); as brandDescription) {\n <span class=\"fk-nav-brand__description\">{{ brandDescription }}</span>\n }\n </span>\n</a>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
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,11 @@ declare class DataTableComponent<T = unknown> {
|
|
|
282
309
|
*/
|
|
283
310
|
private readonly groupCoordinator;
|
|
284
311
|
constructor();
|
|
312
|
+
/**
|
|
313
|
+
* The group heading to emit before a row, or null when the row continues the
|
|
314
|
+
* group above it. The first row always opens its group.
|
|
315
|
+
*/
|
|
316
|
+
groupHeadingFor(row: T, index: number): string | null;
|
|
285
317
|
/** Resolves the display value for a cell given its column definition and row data. */
|
|
286
318
|
getCellValue(column: ColumnDef<T>, row: T): unknown;
|
|
287
319
|
/** Returns the trackBy function from the merged config for use in `*ngFor`. */
|
|
@@ -372,7 +404,7 @@ declare class DataTableComponent<T = unknown> {
|
|
|
372
404
|
/** Returns the current sort direction for the given column id, or null if not sorted. */
|
|
373
405
|
getSortDirection(columnId: string): 'asc' | 'desc' | null;
|
|
374
406
|
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>;
|
|
407
|
+
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
408
|
}
|
|
377
409
|
|
|
378
410
|
/**
|
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,36 @@ 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
|
+
> **Grouping and virtualization are mutually exclusive.** Virtual scrolling
|
|
266
|
+
> positions rows by multiplying an index by `rowHeight`, and a heading is not
|
|
267
|
+
> that tall. Setting `groupBy` turns virtualization off rather than misplacing
|
|
268
|
+
> every row after the first heading.
|
|
269
|
+
|
|
238
270
|
### Virtual scrolling
|
|
239
271
|
|
|
240
272
|
Virtual scrolling activates automatically when row count exceeds `virtualizationThreshold` (default 200). Force it on or off:
|
|
@@ -341,6 +373,15 @@ Pinned columns stick to the left or right edge when scrolling horizontally.
|
|
|
341
373
|
--fk-data-table-row-hover-bg
|
|
342
374
|
--fk-data-table-viewport-height
|
|
343
375
|
|
|
376
|
+
// Group headings
|
|
377
|
+
--fk-data-table-group-heading-bg
|
|
378
|
+
--fk-data-table-group-heading-color
|
|
379
|
+
--fk-data-table-group-heading-font-size
|
|
380
|
+
--fk-data-table-group-heading-font-weight
|
|
381
|
+
--fk-data-table-group-heading-letter-spacing
|
|
382
|
+
--fk-data-table-group-heading-text-transform
|
|
383
|
+
--fk-data-table-group-heading-padding
|
|
384
|
+
|
|
344
385
|
// Empty & Loading
|
|
345
386
|
--fk-data-table-empty-padding
|
|
346
387
|
--fk-data-table-empty-color
|