cats-data-grid 2.0.82 → 2.0.83

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 (36) hide show
  1. package/README.md +465 -33
  2. package/assets/images/add-more-right-blue.svg +3 -3
  3. package/assets/images/autosize-all.svg +3 -3
  4. package/assets/images/autosize-this.svg +3 -3
  5. package/assets/images/check-white.svg +3 -3
  6. package/assets/images/eye-custom-header.svg +4 -4
  7. package/assets/images/eye-off-custom-header.svg +3 -3
  8. package/assets/images/gripper.svg +8 -8
  9. package/assets/images/minus-blue.svg +3 -3
  10. package/assets/images/pin.svg +4 -4
  11. package/assets/images/sort_down.svg +6 -6
  12. package/assets/images/sort_up.svg +6 -6
  13. package/assets/images/t-arrow-down.svg +4 -4
  14. package/assets/images/t-arrow-up.svg +4 -4
  15. package/assets/images/t-choose-column.svg +3 -3
  16. package/assets/images/t-data-pipeline.svg +13 -13
  17. package/assets/images/t-filter-applied.svg +4 -4
  18. package/assets/images/t-filter.svg +3 -3
  19. package/assets/images/t-gripper.svg +8 -8
  20. package/assets/images/t-group-by-name.svg +3 -3
  21. package/assets/images/t-more-vertical.svg +5 -5
  22. package/assets/images/t-move.svg +15 -15
  23. package/assets/images/t-x.svg +4 -4
  24. package/fesm2022/cats-data-grid.mjs +15 -12
  25. package/fesm2022/cats-data-grid.mjs.map +1 -1
  26. package/package.json +1 -1
  27. package/styles/_index.scss +3 -3
  28. package/styles/base/_fonts.scss +74 -74
  29. package/styles/base/_index.scss +1 -1
  30. package/styles/base/_reset.scss +60 -60
  31. package/styles/component/_form.scss +426 -426
  32. package/styles/component/_index.scss +1 -1
  33. package/styles/sass-utils/_function.scss +14 -14
  34. package/styles/sass-utils/_index.scss +3 -3
  35. package/styles/sass-utils/_mixin.scss +100 -100
  36. package/styles/sass-utils/_variable.scss +128 -128
package/README.md CHANGED
@@ -1,63 +1,495 @@
1
- # CatsDataGrid
1
+ # Cats Data Grid
2
2
 
3
- This project was generated using [Angular CLI](https://github.com/angular/angular-cli) version 20.3.15.
3
+ Cats Data Grid is an Angular library for showing tabular and hierarchical data.
4
+ It provides two standalone components:
4
5
 
5
- ## Code scaffolding
6
+ - `CatsDataGridComponent` for normal flat tables.
7
+ - `CommonTreeTableComponent` for tree or parent-child tables.
6
8
 
7
- Angular CLI includes powerful code scaffolding tools. To generate a new component, run:
9
+ The library supports sorting, filtering, pagination, row selection, column
10
+ settings, column pinning, grouping, editable cells, skeleton loading, and custom
11
+ cell renderers.
12
+
13
+ ## Requirements
14
+
15
+ - Angular `>=18 <22`
16
+ - `@angular/core`
17
+ - `@angular/common`
18
+
19
+ ## Install
8
20
 
9
21
  ```bash
10
- ng generate component component-name
22
+ npm install cats-data-grid
11
23
  ```
12
24
 
13
- For a complete list of available schematics (such as `components`, `directives`, or `pipes`), run:
25
+ If you are using this library from the local workspace, build it first:
14
26
 
15
27
  ```bash
16
- ng generate --help
28
+ ng build cats-data-grid
17
29
  ```
18
30
 
19
- ## Building
31
+ ## Configure Assets And Styles
20
32
 
21
- To build the library, run:
33
+ Add the library assets and styles to your application's `angular.json`.
22
34
 
23
- ```bash
24
- ng build cats-data-grid
35
+ For an installed npm package:
36
+
37
+ ```json
38
+ {
39
+ "assets": [
40
+ {
41
+ "glob": "**/*",
42
+ "input": "node_modules/cats-data-grid/assets"
43
+ }
44
+ ],
45
+ "styles": ["node_modules/cats-data-grid/styles/_index.scss"]
46
+ }
25
47
  ```
26
48
 
27
- This command will compile your project, and the build artifacts will be placed in the `dist/` directory.
49
+ ## Import In Angular
28
50
 
29
- ### Publishing the Library
51
+ The components are standalone, so import them in the component where you use
52
+ them.
30
53
 
31
- Once the project is built, you can publish your library by following these steps:
54
+ ```ts
55
+ import { Component } from "@angular/core";
56
+ import { CatsDataGridComponent, CommonRendererComponent } from "cats-data-grid";
32
57
 
33
- 1. Navigate to the `dist` directory:
34
- ```bash
35
- cd dist/cats-data-grid
36
- ```
58
+ @Component({
59
+ selector: "app-users",
60
+ standalone: true,
61
+ imports: [CatsDataGridComponent],
62
+ templateUrl: "./users.component.html",
63
+ })
64
+ export class UsersComponent {
65
+ // Component code shown below.
66
+ }
67
+ ```
37
68
 
38
- 2. Run the `npm publish` command to publish your library to the npm registry:
39
- ```bash
40
- npm publish
41
- ```
69
+ ## Basic Data Grid
42
70
 
43
- ## Running unit tests
71
+ ### Template
44
72
 
45
- To execute unit tests with the [Karma](https://karma-runner.github.io) test runner, use the following command:
73
+ ```html
74
+ <cats-data-grid [rowData]="rowData" [colDefs]="colDefs" [totalRecords]="totalRecords" [paginationRequired]="true" [sortingRequired]="true" [filterRequired]="true" [checkBoxSelection]="true" [checkboxSelectionType]="'multiple'" [settingsRequired]="true" [threeDotsMenuRequired]="true" [pageSizeList]="[10, 20, 50]" [pageNumber]="pageNumber" [pageSize]="pageSize" [rowId]="'id'" (onPaginationChange)="onPaginationChange($event)" (onCheckboxSelection)="onCheckboxSelection($event)" (onRowClicked)="onRowClicked($event)" (onCellClicked)="onCellClicked($event)" (onCellEdit)="onCellEdit($event)" (onColConfigChange)="onColConfigChange($event)"></cats-data-grid>
75
+ ```
46
76
 
47
- ```bash
48
- ng test
77
+ ### Component
78
+
79
+ ```ts
80
+ import { Component } from "@angular/core";
81
+ import { CatsDataGridComponent, CommonRendererComponent } from "cats-data-grid";
82
+
83
+ @Component({
84
+ selector: "app-users",
85
+ standalone: true,
86
+ imports: [CatsDataGridComponent],
87
+ templateUrl: "./users.component.html",
88
+ })
89
+ export class UsersComponent {
90
+ pageNumber = 0;
91
+ pageSize = 20;
92
+ totalRecords = 3;
93
+
94
+ colDefs = [
95
+ {
96
+ headerName: "ID",
97
+ fieldName: "id",
98
+ width: 100,
99
+ filterType: "number",
100
+ headerLocked: true,
101
+ },
102
+ {
103
+ headerName: "Name",
104
+ fieldName: "name",
105
+ width: 200,
106
+ filterType: "text",
107
+ editable: true,
108
+ },
109
+ {
110
+ headerName: "Status",
111
+ fieldName: "status",
112
+ width: 160,
113
+ filterType: "set",
114
+ cellRenderer: CommonRendererComponent,
115
+ cellRendererParams: {
116
+ type: "tag",
117
+ },
118
+ },
119
+ {
120
+ headerName: "Action",
121
+ fieldName: "action",
122
+ width: 90,
123
+ filterable: false,
124
+ columnAction: false,
125
+ isAction: true,
126
+ cellRenderer: CommonRendererComponent,
127
+ cellRendererParams: {
128
+ type: "action-menu",
129
+ actions: [
130
+ { label: "View", value: "view", image: "images/eye.svg" },
131
+ { label: "Edit", value: "edit", image: "images/edit.svg" },
132
+ ],
133
+ onAction: (event: any) => this.onAction(event),
134
+ },
135
+ },
136
+ ];
137
+
138
+ rowData = [
139
+ { id: 1, name: "Aarav", status: ["Active"] },
140
+ { id: 2, name: "Diya", status: ["Pending"] },
141
+ { id: 3, name: "Kabir", status: ["Inactive"] },
142
+ ];
143
+
144
+ onPaginationChange(event: { page: number; pageSize: number }): void {
145
+ this.pageNumber = event.page;
146
+ this.pageSize = event.pageSize;
147
+ // Call your API here when using server-side pagination.
148
+ }
149
+
150
+ onCheckboxSelection(selectedRows: any[]): void {
151
+ console.log("Selected rows", selectedRows);
152
+ }
153
+
154
+ onRowClicked(event: any): void {
155
+ console.log("Row clicked", event.row);
156
+ }
157
+
158
+ onCellClicked(event: any): void {
159
+ console.log("Cell clicked", event.row, event.col);
160
+ }
161
+
162
+ onCellEdit(event: any): void {
163
+ console.log("Cell edited", event);
164
+ }
165
+
166
+ onColConfigChange(activeFields: string[]): void {
167
+ console.log("Visible columns", activeFields);
168
+ }
169
+
170
+ onAction(event: any): void {
171
+ console.log("Action clicked", event);
172
+ }
173
+ }
49
174
  ```
50
175
 
51
- ## Running end-to-end tests
176
+ ## Column Definition
52
177
 
53
- For end-to-end (e2e) testing, run:
178
+ Use `colDefs` to configure table columns.
54
179
 
55
- ```bash
56
- ng e2e
180
+ | Property | Type | Description |
181
+ | -------------------- | --------------------------------------- | ---------------------------------------------------------------------- |
182
+ | `headerName` | `string` | Column title shown in the header. |
183
+ | `fieldName` | `string` | Field to read from row data. Dot paths like `user.name` are supported. |
184
+ | `width` | `number` | Column width in pixels. |
185
+ | `minWidth` | `number` | Minimum column width in pixels. |
186
+ | `maxWidth` | `number` | Maximum column width in pixels. |
187
+ | `filterType` | `'text' \| 'number' \| 'date' \| 'set'` | Type of filter to show. |
188
+ | `sortable` | `boolean` | Enables or disables sorting for this column. |
189
+ | `filterable` | `boolean` | Enables or disables filtering for this column. |
190
+ | `active` | `boolean` | Shows or hides the column initially. |
191
+ | `headerLocked` | `boolean` | Keeps the column visible in column settings. |
192
+ | `editable` | `boolean` | Allows cell editing on double click. |
193
+ | `category` | `string` | Groups columns inside the column settings panel. |
194
+ | `disableGrouping` | `boolean` | Prevents this column from being used in grouping. |
195
+ | `cellRenderer` | `any` | Angular component or function used to render the cell. |
196
+ | `cellRendererParams` | `object` | Extra configuration passed to the renderer. |
197
+ | `isAction` | `boolean` | Marks the column as a sticky action column. |
198
+ | `columnAction` | `boolean` | Shows or hides the column menu for this column. |
199
+
200
+ ## Data Grid Inputs
201
+
202
+ | Input | Type | Default | Description |
203
+ | -------------------------- | ---------------- | ------------------- | -------------------------------------------------------------- |
204
+ | `rowData` | `any[]` | `[]` | Rows displayed in the grid. Required. |
205
+ | `colDefs` | `any[]` | `[]` | Column definitions. Required. |
206
+ | `tableOptions` | `any` | - | Extra options, such as custom row classes or no-data template. |
207
+ | `totalRecords` | `number` | `0` | Total record count for pagination. |
208
+ | `sortingRequired` | `boolean` | `true` | Enables sorting. |
209
+ | `filterRequired` | `boolean` | `true` | Enables filtering. |
210
+ | `paginationRequired` | `boolean` | `true` | Shows pagination. |
211
+ | `checkBoxSelection` | `boolean` | `false` | Shows row checkboxes. |
212
+ | `checkboxSelectionType` | `string` | `'multiple'` | Use `'single'` or `'multiple'`. |
213
+ | `settingsRequired` | `boolean` | `true` | Enables column settings. |
214
+ | `settingsClicked` | `boolean` | `false` | Opens or closes the settings panel from parent component. |
215
+ | `threeDotsMenuRequired` | `boolean` | `true` | Shows the column action menu. |
216
+ | `groupByRequired` | `boolean` | `false` | Enables grouping UI. |
217
+ | `groupByField` | `string` | `''` | Applies an initial group field. |
218
+ | `dynamicGroupingFiltering` | `boolean` | `false` | Emits grouping/filter events for server-side handling. |
219
+ | `appliedFilters` | `ColumnFilter[]` | `[]` | Pre-applied filters. |
220
+ | `pageSizeList` | `number[]` | `[20, 50, 75, 100]` | Page size options. |
221
+ | `pageNumber` | `number` | - | Current page number. |
222
+ | `pageSize` | `number` | - | Current page size. |
223
+ | `resetPage` | `boolean` | `true` | Resets page when total records change. |
224
+ | `rowId` | `string` | `null` | Unique row id field. |
225
+ | `rowGripFieldName` | `string` | - | Field used for row drag grip. |
226
+ | `bigRows` | `boolean` | `false` | Uses larger row height. |
227
+ | `height` | `number` | `400` | Grid height in pixels. |
228
+ | `isRowsEditable` | `boolean` | `false` | Enables row edit behavior. |
229
+ | `showSkeleton` | `boolean` | `false` | Shows skeleton loading rows. |
230
+ | `skeletonRowsLength` | `number` | `8` | Number of skeleton rows. |
231
+ | `skeletonColsLength` | `number` | `8` | Number of skeleton columns. |
232
+
233
+ ## Data Grid Events
234
+
235
+ | Event | Payload | Description |
236
+ | --------------------- | ---------------------------- | ------------------------------------------- |
237
+ | `onPaginationChange` | `{ page, pageSize }` | Emits when page or page size changes. |
238
+ | `onCheckboxSelection` | `any[]` | Emits selected rows. |
239
+ | `onRowClicked` | `{ row }` | Emits when a row is clicked. |
240
+ | `onCellClicked` | `{ row, col }` | Emits when a cell is clicked. |
241
+ | `onCellEdit` | `{ row, col, changedValue }` | Emits after editable cell value changes. |
242
+ | `onColConfigChange` | `string[]` | Emits visible column field names. |
243
+ | `appliedFiltersEvent` | `ColumnFilter[]` | Emits applied filters. |
244
+ | `activeGroupsEvent` | `string[]` | Emits active group fields. |
245
+ | `onScrollEmitter` | `void` | Emits when the table reaches bottom scroll. |
246
+ | `filter` | `any` | Emits filtered data/filter changes. |
247
+ | `onHideSettings` | `boolean` | Emits when settings panel is hidden. |
248
+
249
+ ## Built-In Cell Renderers
250
+
251
+ Import `CommonRendererComponent` and use it in `cellRenderer`.
252
+
253
+ ### Tag
254
+
255
+ ```ts
256
+ {
257
+ headerName: 'Status',
258
+ fieldName: 'status',
259
+ filterType: 'set',
260
+ cellRenderer: CommonRendererComponent,
261
+ cellRendererParams: {
262
+ type: 'tag',
263
+ tagKey: 'name',
264
+ class: 'active',
265
+ },
266
+ }
267
+ ```
268
+
269
+ ### Link
270
+
271
+ ```ts
272
+ {
273
+ headerName: 'Customer',
274
+ fieldName: 'customer.name',
275
+ cellRenderer: CommonRendererComponent,
276
+ cellRendererParams: {
277
+ type: 'link',
278
+ onLinkClick: (event: any) => this.onCustomerClick(event),
279
+ },
280
+ }
281
+ ```
282
+
283
+ ### Switch
284
+
285
+ ```ts
286
+ {
287
+ headerName: 'Enabled',
288
+ fieldName: 'enabled',
289
+ cellRenderer: CommonRendererComponent,
290
+ cellRendererParams: {
291
+ type: 'switch',
292
+ onToggle: (event: any) => this.onStatusToggle(event),
293
+ },
294
+ }
295
+ ```
296
+
297
+ ### Action Menu
298
+
299
+ ```ts
300
+ {
301
+ headerName: 'Action',
302
+ fieldName: 'action',
303
+ filterable: false,
304
+ columnAction: false,
305
+ isAction: true,
306
+ cellRenderer: CommonRendererComponent,
307
+ cellRendererParams: {
308
+ type: 'action-menu',
309
+ actions: [
310
+ { label: 'View', value: 'view', image: 'images/eye.svg' },
311
+ { label: 'Delete', value: 'delete', image: 'images/trash.svg' },
312
+ ],
313
+ onAction: (event: any) => this.onAction(event),
314
+ },
315
+ }
316
+ ```
317
+
318
+ ## Tree Table
319
+
320
+ Use `cats-tree-table` when your data has children or nested rows.
321
+
322
+ ### Import
323
+
324
+ ```ts
325
+ import { Component } from "@angular/core";
326
+ import { CatsTreeExpandEvent, CatsTreeSelectionChangeEvent, CatsTreeTableColumn, CommonTreeTableComponent } from "cats-data-grid";
327
+
328
+ @Component({
329
+ selector: "app-tree-demo",
330
+ standalone: true,
331
+ imports: [CommonTreeTableComponent],
332
+ templateUrl: "./tree-demo.component.html",
333
+ })
334
+ export class TreeDemoComponent {
335
+ // Component code shown below.
336
+ }
337
+ ```
338
+
339
+ ### Template
340
+
341
+ ```html
342
+ <cats-tree-table [data]="treeData" [columns]="columns" childrenField="children" labelField="name" [showCheckbox]="true" [sortingRequired]="true" [filterRequired]="true" [paginationRequired]="true" [totalRecords]="treeData.length" [pageSizeList]="[10, 20, 50]" [expandAllNodes]="false" [isExpandable]="isExpandable" [rowOptionsResolver]="rowOptionsResolver" [nodeIconResolver]="nodeIconResolver" [linkResolver]="linkResolver" (nodeToggle)="onNodeToggle($event)" (selectionChange)="onSelectionChange($event)" (linkClick)="onLinkClick($event)" (linkDoubleClick)="onLinkDoubleClick($event)"></cats-tree-table>
343
+ ```
344
+
345
+ ### Component
346
+
347
+ ```ts
348
+ columns: CatsTreeTableColumn[] = [
349
+ { fieldName: 'name', header: 'Name', width: 260, filterType: 'text' },
350
+ { fieldName: 'type', header: 'Type', width: 140, filterType: 'set' },
351
+ { fieldName: 'owner', header: 'Owner', width: 180, filterType: 'text' },
352
+ ];
353
+
354
+ treeData = [
355
+ {
356
+ id: 1,
357
+ name: 'Network',
358
+ type: 'group',
359
+ owner: 'Admin',
360
+ children: [
361
+ { id: 11, name: 'Router Template', type: 'template', owner: 'NOC' },
362
+ { id: 12, name: 'Switch Template', type: 'template', owner: 'NOC' },
363
+ ],
364
+ },
365
+ ];
366
+
367
+ isExpandable = (node: any): boolean => {
368
+ return Array.isArray(node.children) && node.children.length > 0;
369
+ };
370
+
371
+ rowOptionsResolver = (node: any) => {
372
+ if (node.type === 'template') {
373
+ return { showCheckbox: false, showLink: true, showNodeIcon: true };
374
+ }
375
+
376
+ return { showCheckbox: true, showNodeIcon: true };
377
+ };
378
+
379
+ nodeIconResolver = (node: any, level: number, path: any[], expanded: boolean) => {
380
+ if (node.type === 'group') {
381
+ return expanded ? 'folder-minus.svg' : 'folder-plus.svg';
382
+ }
383
+
384
+ return 'file-text.svg';
385
+ };
386
+
387
+ linkResolver = (node: any): string | null => {
388
+ return node.type === 'template' ? `/templates/${node.id}` : null;
389
+ };
390
+
391
+ onNodeToggle(event: CatsTreeExpandEvent<any>): void {
392
+ console.log('Node toggled', event);
393
+ }
394
+
395
+ onSelectionChange(event: CatsTreeSelectionChangeEvent<any>): void {
396
+ console.log('Selection changed', event.selectedNodes);
397
+ }
398
+
399
+ onLinkClick(event: any): void {
400
+ console.log('Link clicked', event);
401
+ }
402
+
403
+ onLinkDoubleClick(event: any): void {
404
+ console.log('Link double clicked', event);
405
+ }
57
406
  ```
58
407
 
59
- Angular CLI does not come with an end-to-end testing framework by default. You can choose one that suits your needs.
408
+ ## Tree Table Inputs
409
+
410
+ | Input | Type | Default | Description |
411
+ | -------------------------- | ----------------------- | ----------------------------------------- | ------------------------------------------------------------------ |
412
+ | `data` | `any[]` | `[]` | Root nodes for the tree. |
413
+ | `columns` | `CatsTreeTableColumn[]` | `[{ fieldName: 'name', header: 'Name' }]` | Tree table columns. |
414
+ | `idField` | `string` | `'id'` | Unique id field. |
415
+ | `labelField` | `string` | `'name'` | Field displayed as the tree label. |
416
+ | `childrenField` | `string` | `'array'` | Field containing child nodes. |
417
+ | `treeColumnField` | `string` | - | Column used as the tree column. |
418
+ | `indentPx` | `number` | `24` | Indentation per tree level. |
419
+ | `showHeader` | `boolean` | `true` | Shows the header row. |
420
+ | `showCheckbox` | `boolean` | `false` | Shows node checkboxes. |
421
+ | `showNodeIcon` | `boolean` | `true` | Shows node icons. |
422
+ | `expandAllNodes` | `boolean` | `false` | Expands all nodes. |
423
+ | `expandAllControlRequired` | `boolean` | `true` | Shows expand-all control. |
424
+ | `isExpandable` | `function` | checks children | Controls whether a node can expand. |
425
+ | `rowOptionsResolver` | `function` | `{}` | Controls checkbox, toggle, icon, link, and disabled state per row. |
426
+ | `nodeIconResolver` | `function` | `null` | Returns an icon path or file name for each node. |
427
+ | `linkResolver` | `function` | `null` | Returns the URL used for link rows. |
428
+ | `iconBasePath` | `string` | `'images'` | Base folder for icon file names. |
429
+ | `sortingRequired` | `boolean` | `true` | Enables sorting. |
430
+ | `filterRequired` | `boolean` | `false` | Enables filtering. |
431
+ | `paginationRequired` | `boolean` | `true` | Shows pagination. |
432
+ | `settingsRequired` | `boolean` | `true` | Enables column settings. |
433
+ | `threeDotsMenuRequired` | `boolean` | `true` | Shows column action menu. |
434
+ | `pageSizeList` | `number[]` | `[20, 50, 75, 100]` | Page size options. |
435
+ | `totalRecords` | `number` | `0` | Total records for pagination. |
436
+ | `showSkeleton` | `boolean` | `false` | Shows loading skeleton. |
437
+
438
+ ## Tree Table Events
439
+
440
+ | Event | Payload | Description |
441
+ | -------------------- | ----------------------------------------------- | --------------------------------------- |
442
+ | `nodeToggle` | `{ node, level, path, expanded }` | Emits when a node expands or collapses. |
443
+ | `selectionChange` | `{ node, level, path, checked, selectedNodes }` | Emits when tree selection changes. |
444
+ | `linkClick` | `{ node, level, path, url, col }` | Emits on link click. |
445
+ | `linkDoubleClick` | `{ node, level, path, url, col }` | Emits on link double click. |
446
+ | `onPaginationChange` | `{ page, pageSize }` | Emits when page changes. |
447
+ | `onColConfigChange` | `string[]` | Emits visible column field names. |
448
+ | `onHideSettings` | `boolean` | Emits when settings panel is hidden. |
449
+
450
+ ## Custom No Data Template
451
+
452
+ Pass a template from the parent component through `tableOptions`.
453
+
454
+ ```html
455
+ <cats-data-grid [rowData]="[]" [colDefs]="colDefs" [tableOptions]="tableOptions"></cats-data-grid>
456
+
457
+ <ng-template #noDataTemplate>
458
+ <div class="no-data">No records found</div>
459
+ </ng-template>
460
+ ```
461
+
462
+ ```ts
463
+ import { AfterViewInit, ViewChild } from "@angular/core";
464
+
465
+ export class UsersComponent implements AfterViewInit {
466
+ @ViewChild("noDataTemplate") noDataTemplate!: any;
467
+
468
+ tableOptions: any = {};
469
+
470
+ ngAfterViewInit(): void {
471
+ this.tableOptions.noDataTemplate = this.noDataTemplate;
472
+ }
473
+ }
474
+ ```
475
+
476
+ ## Common Usage Tips
477
+
478
+ - Use `rowId` for stable row selection and row drag behavior.
479
+ - Use dot notation in `fieldName` for nested object values.
480
+ - Use `filterType: 'set'` for columns with repeated predefined values.
481
+ - Use `dynamicGroupingFiltering` when grouping/filtering should be handled by an API.
482
+ - Use `showSkeleton` while data is loading.
483
+ - Use `active: false` to hide a column initially.
484
+ - Use `headerLocked: true` for columns that must always remain visible.
485
+
486
+ ## Build And Test
487
+
488
+ ```bash
489
+ ng build cats-data-grid
490
+ ng test cats-data-grid
491
+ ```
60
492
 
61
- ## Additional Resources
493
+ ## License
62
494
 
63
- For more information on using the Angular CLI, including detailed command references, visit the [Angular CLI Overview and Command Reference](https://angular.dev/tools/cli) page.
495
+ MIT
@@ -1,3 +1,3 @@
1
- <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
2
- <path d="M6 12L10 8L6 4" stroke="#2680EA" stroke-linecap="round" stroke-linejoin="round"/>
3
- </svg>
1
+ <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path d="M6 12L10 8L6 4" stroke="#2680EA" stroke-linecap="round" stroke-linejoin="round"/>
3
+ </svg>
@@ -1,3 +1,3 @@
1
- <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
2
- <path d="M14 6.66675H8.66667M14 4.00008H8.66667M14 9.33341H8.66667M14 12.0001H8.66667M4 13.3334L4 2.66675M4 13.3334L2 11.3334M4 13.3334L6 11.3334M4 2.66675L2 4.66675M4 2.66675L6 4.66675" stroke="#040D17" stroke-linecap="round" stroke-linejoin="round"/>
3
- </svg>
1
+ <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path d="M14 6.66675H8.66667M14 4.00008H8.66667M14 9.33341H8.66667M14 12.0001H8.66667M4 13.3334L4 2.66675M4 13.3334L2 11.3334M4 13.3334L6 11.3334M4 2.66675L2 4.66675M4 2.66675L6 4.66675" stroke="#040D17" stroke-linecap="round" stroke-linejoin="round"/>
3
+ </svg>
@@ -1,3 +1,3 @@
1
- <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
2
- <path d="M8 12L8 4M8 12L6 10.6667M8 12L10 10.6667M8 4L6 5.33333M8 4L10 5.33333M14 2H2M14 14H2" stroke="#040D17" stroke-linecap="round" stroke-linejoin="round"/>
3
- </svg>
1
+ <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path d="M8 12L8 4M8 12L6 10.6667M8 12L10 10.6667M8 4L6 5.33333M8 4L10 5.33333M14 2H2M14 14H2" stroke="#040D17" stroke-linecap="round" stroke-linejoin="round"/>
3
+ </svg>
@@ -1,3 +1,3 @@
1
- <svg width="8" height="6" viewBox="0 0 8 6" fill="none" xmlns="http://www.w3.org/2000/svg">
2
- <path d="M6.625 0.625L2.5 4.75L0.625 2.875" stroke="#EAF3FD" stroke-width="1.24995" stroke-linecap="round" stroke-linejoin="round"/>
3
- </svg>
1
+ <svg width="8" height="6" viewBox="0 0 8 6" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path d="M6.625 0.625L2.5 4.75L0.625 2.875" stroke="#EAF3FD" stroke-width="1.24995" stroke-linecap="round" stroke-linejoin="round"/>
3
+ </svg>
@@ -1,4 +1,4 @@
1
- <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
2
- <path d="M0.666016 8.00008C0.666016 8.00008 3.33268 2.66675 7.99935 2.66675C12.666 2.66675 15.3327 8.00008 15.3327 8.00008C15.3327 8.00008 12.666 13.3334 7.99935 13.3334C3.33268 13.3334 0.666016 8.00008 0.666016 8.00008Z" stroke="#040D17" stroke-linecap="round" stroke-linejoin="round"/>
3
- <path d="M8 10C9.10457 10 10 9.10457 10 8C10 6.89543 9.10457 6 8 6C6.89543 6 6 6.89543 6 8C6 9.10457 6.89543 10 8 10Z" stroke="#040D17" stroke-linecap="round" stroke-linejoin="round"/>
4
- </svg>
1
+ <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path d="M0.666016 8.00008C0.666016 8.00008 3.33268 2.66675 7.99935 2.66675C12.666 2.66675 15.3327 8.00008 15.3327 8.00008C15.3327 8.00008 12.666 13.3334 7.99935 13.3334C3.33268 13.3334 0.666016 8.00008 0.666016 8.00008Z" stroke="#040D17" stroke-linecap="round" stroke-linejoin="round"/>
3
+ <path d="M8 10C9.10457 10 10 9.10457 10 8C10 6.89543 9.10457 6 8 6C6.89543 6 6 6.89543 6 8C6 9.10457 6.89543 10 8 10Z" stroke="#040D17" stroke-linecap="round" stroke-linejoin="round"/>
4
+ </svg>
@@ -1,3 +1,3 @@
1
- <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
2
- <path d="M7.16196 3.39488C7.4329 3.35482 7.7124 3.33333 8.00028 3.33333C11.4036 3.33333 13.6369 6.33656 14.3871 7.52455C14.4779 7.66833 14.5233 7.74023 14.5488 7.85112C14.5678 7.93439 14.5678 8.06578 14.5487 8.14905C14.5233 8.25993 14.4776 8.3323 14.3861 8.47705C14.1862 8.79343 13.8814 9.23807 13.4777 9.7203M4.48288 4.47669C3.0415 5.45447 2.06297 6.81292 1.61407 7.52352C1.52286 7.66791 1.47725 7.74011 1.45183 7.85099C1.43273 7.93426 1.43272 8.06563 1.45181 8.14891C1.47722 8.25979 1.52262 8.33168 1.61342 8.47545C2.36369 9.66344 4.59694 12.6667 8.00028 12.6667C9.37255 12.6667 10.5546 12.1784 11.5259 11.5177M2.00028 2L14.0003 14M6.58606 6.58579C6.22413 6.94772 6.00028 7.44772 6.00028 8C6.00028 9.10457 6.89571 10 8.00028 10C8.55256 10 9.05256 9.77614 9.41449 9.41421" stroke="#434A51" stroke-linecap="round" stroke-linejoin="round"/>
3
- </svg>
1
+ <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path d="M7.16196 3.39488C7.4329 3.35482 7.7124 3.33333 8.00028 3.33333C11.4036 3.33333 13.6369 6.33656 14.3871 7.52455C14.4779 7.66833 14.5233 7.74023 14.5488 7.85112C14.5678 7.93439 14.5678 8.06578 14.5487 8.14905C14.5233 8.25993 14.4776 8.3323 14.3861 8.47705C14.1862 8.79343 13.8814 9.23807 13.4777 9.7203M4.48288 4.47669C3.0415 5.45447 2.06297 6.81292 1.61407 7.52352C1.52286 7.66791 1.47725 7.74011 1.45183 7.85099C1.43273 7.93426 1.43272 8.06563 1.45181 8.14891C1.47722 8.25979 1.52262 8.33168 1.61342 8.47545C2.36369 9.66344 4.59694 12.6667 8.00028 12.6667C9.37255 12.6667 10.5546 12.1784 11.5259 11.5177M2.00028 2L14.0003 14M6.58606 6.58579C6.22413 6.94772 6.00028 7.44772 6.00028 8C6.00028 9.10457 6.89571 10 8.00028 10C8.55256 10 9.05256 9.77614 9.41449 9.41421" stroke="#434A51" stroke-linecap="round" stroke-linejoin="round"/>
3
+ </svg>
@@ -1,8 +1,8 @@
1
- <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
2
- <path d="M8.99984 5.16671C8.99984 4.79852 8.70136 4.50004 8.33317 4.50004C7.96498 4.50004 7.6665 4.79852 7.6665 5.16671C7.6665 5.5349 7.96498 5.83337 8.33317 5.83337C8.70136 5.83337 8.99984 5.5349 8.99984 5.16671Z" fill="#434A51" stroke="#434A51" stroke-linecap="round" stroke-linejoin="round"/>
3
- <path d="M4.33333 5.16671C4.33333 4.79852 4.03486 4.50004 3.66667 4.50004C3.29848 4.50004 3 4.79852 3 5.16671C3 5.5349 3.29848 5.83337 3.66667 5.83337C4.03486 5.83337 4.33333 5.5349 4.33333 5.16671Z" fill="#434A51" stroke="#434A51" stroke-linecap="round" stroke-linejoin="round"/>
4
- <path d="M13.6666 5.16671C13.6666 4.79852 13.3681 4.50004 12.9999 4.50004C12.6317 4.50004 12.3333 4.79852 12.3333 5.16671C12.3333 5.5349 12.6317 5.83337 12.9999 5.83337C13.3681 5.83337 13.6666 5.5349 13.6666 5.16671Z" fill="#434A51" stroke="#434A51" stroke-linecap="round" stroke-linejoin="round"/>
5
- <path d="M8.99984 10.8333C8.99984 10.4651 8.70136 10.1667 8.33317 10.1667C7.96498 10.1667 7.6665 10.4651 7.6665 10.8333C7.6665 11.2015 7.96498 11.5 8.33317 11.5C8.70136 11.5 8.99984 11.2015 8.99984 10.8333Z" fill="#434A51" stroke="#434A51" stroke-linecap="round" stroke-linejoin="round"/>
6
- <path d="M4.33333 10.8333C4.33333 10.4651 4.03486 10.1667 3.66667 10.1667C3.29848 10.1667 3 10.4651 3 10.8333C3 11.2015 3.29848 11.5 3.66667 11.5C4.03486 11.5 4.33333 11.2015 4.33333 10.8333Z" fill="#434A51" stroke="#434A51" stroke-linecap="round" stroke-linejoin="round"/>
7
- <path d="M13.6666 10.8333C13.6666 10.4651 13.3681 10.1667 12.9999 10.1667C12.6317 10.1667 12.3333 10.4651 12.3333 10.8333C12.3333 11.2015 12.6317 11.5 12.9999 11.5C13.3681 11.5 13.6666 11.2015 13.6666 10.8333Z" fill="#434A51" stroke="#434A51" stroke-linecap="round" stroke-linejoin="round"/>
8
- </svg>
1
+ <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path d="M8.99984 5.16671C8.99984 4.79852 8.70136 4.50004 8.33317 4.50004C7.96498 4.50004 7.6665 4.79852 7.6665 5.16671C7.6665 5.5349 7.96498 5.83337 8.33317 5.83337C8.70136 5.83337 8.99984 5.5349 8.99984 5.16671Z" fill="#434A51" stroke="#434A51" stroke-linecap="round" stroke-linejoin="round"/>
3
+ <path d="M4.33333 5.16671C4.33333 4.79852 4.03486 4.50004 3.66667 4.50004C3.29848 4.50004 3 4.79852 3 5.16671C3 5.5349 3.29848 5.83337 3.66667 5.83337C4.03486 5.83337 4.33333 5.5349 4.33333 5.16671Z" fill="#434A51" stroke="#434A51" stroke-linecap="round" stroke-linejoin="round"/>
4
+ <path d="M13.6666 5.16671C13.6666 4.79852 13.3681 4.50004 12.9999 4.50004C12.6317 4.50004 12.3333 4.79852 12.3333 5.16671C12.3333 5.5349 12.6317 5.83337 12.9999 5.83337C13.3681 5.83337 13.6666 5.5349 13.6666 5.16671Z" fill="#434A51" stroke="#434A51" stroke-linecap="round" stroke-linejoin="round"/>
5
+ <path d="M8.99984 10.8333C8.99984 10.4651 8.70136 10.1667 8.33317 10.1667C7.96498 10.1667 7.6665 10.4651 7.6665 10.8333C7.6665 11.2015 7.96498 11.5 8.33317 11.5C8.70136 11.5 8.99984 11.2015 8.99984 10.8333Z" fill="#434A51" stroke="#434A51" stroke-linecap="round" stroke-linejoin="round"/>
6
+ <path d="M4.33333 10.8333C4.33333 10.4651 4.03486 10.1667 3.66667 10.1667C3.29848 10.1667 3 10.4651 3 10.8333C3 11.2015 3.29848 11.5 3.66667 11.5C4.03486 11.5 4.33333 11.2015 4.33333 10.8333Z" fill="#434A51" stroke="#434A51" stroke-linecap="round" stroke-linejoin="round"/>
7
+ <path d="M13.6666 10.8333C13.6666 10.4651 13.3681 10.1667 12.9999 10.1667C12.6317 10.1667 12.3333 10.4651 12.3333 10.8333C12.3333 11.2015 12.6317 11.5 12.9999 11.5C13.3681 11.5 13.6666 11.2015 13.6666 10.8333Z" fill="#434A51" stroke="#434A51" stroke-linecap="round" stroke-linejoin="round"/>
8
+ </svg>
@@ -1,3 +1,3 @@
1
- <svg width="7" height="1" viewBox="0 0 7 1" fill="none" xmlns="http://www.w3.org/2000/svg">
2
- <path d="M0.5 0.5H6.5" stroke="#2680EA" stroke-linecap="round" stroke-linejoin="round"/>
3
- </svg>
1
+ <svg width="7" height="1" viewBox="0 0 7 1" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path d="M0.5 0.5H6.5" stroke="#2680EA" stroke-linecap="round" stroke-linejoin="round"/>
3
+ </svg>