argent-grid 0.1.0 → 0.2.0

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 (108) hide show
  1. package/.github/workflows/ci.yml +69 -0
  2. package/.github/workflows/pages.yml +6 -12
  3. package/.storybook/main.ts +20 -0
  4. package/.storybook/preview.ts +18 -0
  5. package/.storybook/tsconfig.json +24 -0
  6. package/AGENTS.md +2 -2
  7. package/README.md +51 -34
  8. package/angular.json +66 -0
  9. package/biome.json +66 -0
  10. package/demo-app/e2e/selection-screenshot.spec.ts +20 -0
  11. package/docs/AG-GRID-COMPARISON.md +725 -0
  12. package/docs/CELL-RENDERER-GUIDE.md +241 -0
  13. package/docs/CONTEXT-MENU-GUIDE.md +371 -0
  14. package/docs/LIVE-DATA-OPTIMIZATIONS.md +497 -0
  15. package/docs/PERFORMANCE-OPTIMIZATIONS-PHASE1.md +162 -0
  16. package/docs/PERFORMANCE-REVIEW.md +571 -0
  17. package/docs/RESEARCH-STATUS.md +234 -0
  18. package/docs/STATE-PERSISTENCE-GUIDE.md +370 -0
  19. package/docs/STORYBOOK-REFACTOR.md +215 -0
  20. package/docs/STORYBOOK-STATUS.md +156 -0
  21. package/docs/TEST-COVERAGE-REPORT.md +276 -0
  22. package/docs/THEME-API-GUIDE.md +445 -0
  23. package/docs/THEME-API-PLAN.md +364 -0
  24. package/e2e/advanced.spec.ts +109 -0
  25. package/e2e/argentgrid.spec.ts +65 -0
  26. package/e2e/benchmark.spec.ts +52 -0
  27. package/e2e/screenshots.spec.ts +52 -0
  28. package/e2e/theming.spec.ts +35 -0
  29. package/e2e/visual.spec.ts +91 -0
  30. package/e2e/visual.spec.ts-snapshots/grid-default.png +0 -0
  31. package/e2e/visual.spec.ts-snapshots/grid-empty-state.png +0 -0
  32. package/e2e/visual.spec.ts-snapshots/grid-filter-popup.png +0 -0
  33. package/e2e/visual.spec.ts-snapshots/grid-scroll-borders.png +0 -0
  34. package/e2e/visual.spec.ts-snapshots/grid-sidebar-buttons.png +0 -0
  35. package/e2e/visual.spec.ts-snapshots/grid-text-filter.png +0 -0
  36. package/e2e/visual.spec.ts-snapshots/grid-with-selection.png +0 -0
  37. package/package.json +20 -6
  38. package/plan.md +50 -18
  39. package/playwright.config.ts +38 -0
  40. package/setup-vitest.ts +10 -13
  41. package/src/lib/argent-grid.module.ts +10 -12
  42. package/src/lib/components/argent-grid.component.css +327 -76
  43. package/src/lib/components/argent-grid.component.html +186 -64
  44. package/src/lib/components/argent-grid.component.spec.ts +120 -160
  45. package/src/lib/components/argent-grid.component.ts +642 -189
  46. package/src/lib/components/argent-grid.selection.spec.ts +132 -0
  47. package/src/lib/components/set-filter/set-filter.component.ts +302 -0
  48. package/src/lib/directives/ag-grid-compatibility.directive.ts +16 -26
  49. package/src/lib/directives/click-outside.directive.ts +19 -0
  50. package/src/lib/rendering/canvas-renderer.spec.ts +366 -0
  51. package/src/lib/rendering/canvas-renderer.ts +418 -305
  52. package/src/lib/rendering/live-data-handler.ts +110 -0
  53. package/src/lib/rendering/live-data-optimizations.ts +133 -0
  54. package/src/lib/rendering/render/blit.spec.ts +16 -27
  55. package/src/lib/rendering/render/blit.ts +48 -36
  56. package/src/lib/rendering/render/cells.spec.ts +132 -0
  57. package/src/lib/rendering/render/cells.ts +46 -24
  58. package/src/lib/rendering/render/column-utils.ts +73 -0
  59. package/src/lib/rendering/render/hit-test.ts +55 -0
  60. package/src/lib/rendering/render/index.ts +79 -76
  61. package/src/lib/rendering/render/lines.ts +43 -43
  62. package/src/lib/rendering/render/primitives.ts +161 -0
  63. package/src/lib/rendering/render/theme.spec.ts +8 -12
  64. package/src/lib/rendering/render/theme.ts +7 -10
  65. package/src/lib/rendering/render/types.ts +2 -2
  66. package/src/lib/rendering/render/walk.spec.ts +35 -38
  67. package/src/lib/rendering/render/walk.ts +60 -50
  68. package/src/lib/rendering/utils/damage-tracker.spec.ts +8 -7
  69. package/src/lib/rendering/utils/damage-tracker.ts +6 -18
  70. package/src/lib/rendering/utils/index.ts +1 -1
  71. package/src/lib/services/grid.service.set-filter.spec.ts +219 -0
  72. package/src/lib/services/grid.service.spec.ts +1165 -201
  73. package/src/lib/services/grid.service.ts +819 -187
  74. package/src/lib/themes/parts/color-schemes.ts +132 -0
  75. package/src/lib/themes/parts/icon-sets.ts +258 -0
  76. package/src/lib/themes/theme-builder.ts +347 -0
  77. package/src/lib/themes/theme-quartz.ts +72 -0
  78. package/src/lib/themes/types.ts +238 -0
  79. package/src/lib/types/ag-grid-types.ts +73 -14
  80. package/src/public-api.ts +39 -9
  81. package/src/stories/Advanced.stories.ts +188 -0
  82. package/src/stories/ArgentGrid.stories.ts +277 -0
  83. package/src/stories/Benchmark.stories.ts +74 -0
  84. package/src/stories/CellRenderers.stories.ts +221 -0
  85. package/src/stories/Filtering.stories.ts +252 -0
  86. package/src/stories/Grouping.stories.ts +217 -0
  87. package/src/stories/Theming.stories.ts +124 -0
  88. package/src/stories/benchmark-wrapper.component.ts +315 -0
  89. package/tsconfig.storybook.json +10 -0
  90. package/vitest.config.ts +9 -9
  91. package/demo-app/README.md +0 -70
  92. package/demo-app/angular.json +0 -78
  93. package/demo-app/e2e/benchmark.spec.ts +0 -53
  94. package/demo-app/e2e/demo-page.spec.ts +0 -77
  95. package/demo-app/e2e/grid-features.spec.ts +0 -269
  96. package/demo-app/package-lock.json +0 -14023
  97. package/demo-app/package.json +0 -36
  98. package/demo-app/playwright-test-menu.js +0 -19
  99. package/demo-app/playwright.config.ts +0 -23
  100. package/demo-app/src/app/app.component.ts +0 -10
  101. package/demo-app/src/app/app.config.ts +0 -13
  102. package/demo-app/src/app/app.routes.ts +0 -7
  103. package/demo-app/src/app/demo-page/demo-page.component.css +0 -313
  104. package/demo-app/src/app/demo-page/demo-page.component.html +0 -124
  105. package/demo-app/src/app/demo-page/demo-page.component.ts +0 -366
  106. package/demo-app/src/index.html +0 -19
  107. package/demo-app/src/main.ts +0 -6
  108. package/demo-app/tsconfig.json +0 -31
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * ArgentGrid - AG Grid Compatible Type Definitions
3
3
  * A free, high-performance alternative to AG Grid Enterprise
4
- *
4
+ *
5
5
  * This file provides 1:1 TypeScript definitions compatible with AG Grid API
6
6
  * to ensure users can switch to ArgentGrid by simply changing their import.
7
7
  */
@@ -147,7 +147,9 @@ export interface GridOptions<TData = any> {
147
147
  // === CALLBACKS ===
148
148
  processCellForClipboard?: (params: ProcessCellForClipboardParams<TData>) => any;
149
149
  processCellFromClipboard?: (params: ProcessCellFromClipboardParams<TData>) => any;
150
- getContextMenuItems?: (params: GetContextMenuItemsParams<TData>) => (DefaultMenuItem | MenuItemDef)[];
150
+ getContextMenuItems?: (
151
+ params: GetContextMenuItemsParams<TData>
152
+ ) => (DefaultMenuItem | MenuItemDef)[];
151
153
  getMainMenuItems?: (params: GetMainMenuItemsParams<TData>) => (DefaultMenuItem | MenuItemDef)[];
152
154
  }
153
155
 
@@ -174,7 +176,9 @@ export interface ColDef<TData = any, TValue = any> {
174
176
  suppressKeyboardEvent?: (params: SuppressKeyboardEventParams<TData>) => boolean;
175
177
  suppressPaste?: boolean | ((params: SuppressPasteParams<TData>) => boolean);
176
178
  suppressFillHandle?: boolean;
177
- contextMenuItems?: (DefaultMenuItem | MenuItemDef)[] | ((params: any) => (DefaultMenuItem | MenuItemDef)[]);
179
+ contextMenuItems?:
180
+ | (DefaultMenuItem | MenuItemDef)[]
181
+ | ((params: any) => (DefaultMenuItem | MenuItemDef)[]);
178
182
  context?: any;
179
183
 
180
184
  // === SELECTION ===
@@ -255,7 +259,9 @@ export interface ColDef<TData = any, TValue = any> {
255
259
  enablePivot?: boolean;
256
260
 
257
261
  // === RENDERING AND STYLING ===
258
- cellStyle?: { [key: string]: any } | ((params: CellStyleParams<TData, TValue>) => { [key: string]: any });
262
+ cellStyle?:
263
+ | { [key: string]: any }
264
+ | ((params: CellStyleParams<TData, TValue>) => { [key: string]: any });
259
265
  cellClass?: string | string[] | ((params: CellClassParams<TData, TValue>) => string | string[]);
260
266
  cellClassRules?: { [key: string]: (params: CellClassParams<TData, TValue>) => boolean };
261
267
  cellRenderer?: any;
@@ -349,6 +355,7 @@ export interface GridApi<TData = any> {
349
355
  setRowData(rowData: TData[]): void;
350
356
  applyTransaction(transaction: RowDataTransaction<TData>): RowDataTransactionResult | null;
351
357
  getDisplayedRowCount(): number;
358
+ getRowY(index: number): number;
352
359
  getAggregations(): { [field: string]: any };
353
360
  getRowNode(id: string): IRowNode<TData> | null;
354
361
 
@@ -386,6 +393,15 @@ export interface GridApi<TData = any> {
386
393
  // === CLIPBOARD API ===
387
394
  copyToClipboard(): void;
388
395
  cutToClipboard(): void;
396
+
397
+ // === STATE PERSISTENCE API ===
398
+ getState(): GridState;
399
+ setState(state: GridState): void;
400
+ saveState(key?: string): void;
401
+ restoreState(key?: string): boolean;
402
+ clearState(key?: string): void;
403
+ hasState(key?: string): boolean;
404
+ getUniqueValues(field: string): any[];
389
405
  pasteFromClipboard(): void;
390
406
 
391
407
  // === GRID STATE API ===
@@ -447,6 +463,9 @@ export interface Column {
447
463
  sort?: SortDirection;
448
464
  sortIndex?: number;
449
465
  aggFunc?: string | null;
466
+ checkboxSelection?: boolean;
467
+ headerCheckboxSelection?: boolean;
468
+ filter?: any;
450
469
  }
451
470
 
452
471
  export interface IRowNode<TData = any> {
@@ -471,6 +490,7 @@ export interface IRowNode<TData = any> {
471
490
  lastChild: boolean;
472
491
  rowIndex: number | null;
473
492
  displayedRowIndex: number;
493
+ setSelected(selected: boolean, clearSelection?: boolean): void;
474
494
  }
475
495
 
476
496
  export interface GroupRowNode<TData = any> {
@@ -573,7 +593,7 @@ export interface CellRange {
573
593
  startRow: number;
574
594
  endRow: number;
575
595
  startColumn: string; // colId
576
- endColumn: string; // colId
596
+ endColumn: string; // colId
577
597
  columns: Column[];
578
598
  }
579
599
 
@@ -650,9 +670,7 @@ export interface RowSelectionOptions {
650
670
  enableSelectionWithoutKeys?: boolean;
651
671
  }
652
672
 
653
- export interface CellSelectionOptions {
654
- // Cell selection configuration
655
- }
673
+ export type CellSelectionOptions = {};
656
674
 
657
675
  export interface SelectionColumnDef {
658
676
  headerCheckbox?: boolean;
@@ -869,7 +887,34 @@ export type DomLayoutType = 'normal' | 'autoHeight' | 'print';
869
887
  export type SortDirection = 'asc' | 'desc' | null;
870
888
  export type RowGroupingDisplayType = 'singleColumn' | 'multipleColumns' | 'groupRows' | 'custom';
871
889
  export type ColumnMenuTab = 'filterMenu' | 'mainMenu' | 'columnsMenu' | 'chartMenu';
872
- export type DefaultMenuItem = 'pinMenu' | 'valueMenu' | 'columnMenu' | 'expandable' | 'separator' | 'copy' | 'copyWithHeaders' | 'copyWithGroupHeaders' | 'cut' | 'paste' | 'export' | 'chartRange' | 'pivot' | 'resetColumns' | 'deselectAll' | 'selectAll' | 'selectAllOtherColumns' | 'autoSizeAll' | 'autoSizeThisColumn' | 'resetColumns' | 'expandAll' | 'collapseAll' | 'rowGroupingGroup' | 'rowGroupingUnGroup' | 'pivotMenu' | 'aggFuncMenu' | 'sideBar';
890
+ export type DefaultMenuItem =
891
+ | 'pinMenu'
892
+ | 'valueMenu'
893
+ | 'columnMenu'
894
+ | 'expandable'
895
+ | 'separator'
896
+ | 'copy'
897
+ | 'copyWithHeaders'
898
+ | 'copyWithGroupHeaders'
899
+ | 'cut'
900
+ | 'paste'
901
+ | 'export'
902
+ | 'chartRange'
903
+ | 'pivot'
904
+ | 'resetColumns'
905
+ | 'deselectAll'
906
+ | 'selectAll'
907
+ | 'selectAllOtherColumns'
908
+ | 'autoSizeAll'
909
+ | 'autoSizeThisColumn'
910
+ | 'resetColumns'
911
+ | 'expandAll'
912
+ | 'collapseAll'
913
+ | 'rowGroupingGroup'
914
+ | 'rowGroupingUnGroup'
915
+ | 'pivotMenu'
916
+ | 'aggFuncMenu'
917
+ | 'sideBar';
873
918
 
874
919
  export interface MenuItemDef {
875
920
  name: string;
@@ -885,14 +930,28 @@ export interface MenuItemDef {
885
930
  // FUNCTION TYPE DEFINITIONS
886
931
  // ============================================================================
887
932
 
888
- export type ValueGetterFunc<TData = any, TValue = any> = (params: ValueGetterParams<TData>) => TValue;
889
- export type ValueFormatterFunc<TData = any, TValue = any> = (params: ValueFormatterParams<TData, TValue>) => string;
890
- export type ValueSetterFunc<TData = any, TValue = any> = (params: ValueSetterParams<TData, TValue>) => boolean;
891
- export type ValueParserFunc<TData = any, TValue = any> = (params: ValueParserParams<TData, TValue>) => TValue;
933
+ export type ValueGetterFunc<TData = any, TValue = any> = (
934
+ params: ValueGetterParams<TData>
935
+ ) => TValue;
936
+ export type ValueFormatterFunc<TData = any, TValue = any> = (
937
+ params: ValueFormatterParams<TData, TValue>
938
+ ) => string;
939
+ export type ValueSetterFunc<TData = any, TValue = any> = (
940
+ params: ValueSetterParams<TData, TValue>
941
+ ) => boolean;
942
+ export type ValueParserFunc<TData = any, TValue = any> = (
943
+ params: ValueParserParams<TData, TValue>
944
+ ) => TValue;
892
945
  export type KeyCreatorFunc<TValue = any> = (params: KeyCreatorParams<TValue>) => string;
893
946
  export type EqualsFunc<TValue = any> = (params: EqualsParams<TValue>) => boolean;
894
947
  export type HeaderValueGetterFunc<TData = any> = (params: HeaderValueGetterParams<TData>) => string;
895
- export type SortComparatorFn<TValue = any> = (valueA: TValue, valueB: TValue, nodeA: IRowNode, nodeB: IRowNode, isDescending: boolean) => number;
948
+ export type SortComparatorFn<TValue = any> = (
949
+ valueA: TValue,
950
+ valueB: TValue,
951
+ nodeA: IRowNode,
952
+ nodeB: IRowNode,
953
+ isDescending: boolean
954
+ ) => number;
896
955
  export type GetRowIdFunc<TData = any> = (params: GetRowIdParams<TData>) => string;
897
956
  export type IAggFunc<TData = any> = (params: IAggFuncParams<TData>) => any;
898
957
 
package/src/public-api.ts CHANGED
@@ -3,20 +3,50 @@
3
3
  * A free, high-performance alternative to AG Grid Enterprise
4
4
  */
5
5
 
6
- // Core types - AG Grid compatible
7
- export * from './lib/types/ag-grid-types';
6
+ // Modules
7
+ export { ArgentGridModule } from './lib/argent-grid.module';
8
8
 
9
9
  // Main grid component
10
10
  export { ArgentGridComponent } from './lib/components/argent-grid.component';
11
-
12
- // Canvas renderer
13
- export { CanvasRenderer } from './lib/rendering/canvas-renderer';
11
+ // Components
12
+ export { SetFilterComponent } from './lib/components/set-filter/set-filter.component';
14
13
 
15
14
  // Directives
16
15
  export { AgGridCompatibilityDirective } from './lib/directives/ag-grid-compatibility.directive';
17
-
16
+ export { ClickOutsideDirective } from './lib/directives/click-outside.directive';
17
+ // Canvas renderer
18
+ export { CanvasRenderer } from './lib/rendering/canvas-renderer';
19
+ // Live Data Optimizations
20
+ export { LiveDataOptimizations } from './lib/rendering/live-data-optimizations';
18
21
  // Services
19
22
  export { GridService } from './lib/services/grid.service';
20
-
21
- // Modules
22
- export { ArgentGridModule } from './lib/argent-grid.module';
23
+ export {
24
+ COLOR_SCHEMES,
25
+ colorSchemeAuto,
26
+ colorSchemeDark,
27
+ colorSchemeLight,
28
+ getColorScheme,
29
+ } from './lib/themes/parts/color-schemes';
30
+ export {
31
+ getIconSet,
32
+ getIconSvg,
33
+ ICON_SETS,
34
+ iconSetMaterial,
35
+ iconSetMinimal,
36
+ iconSetQuartz,
37
+ } from './lib/themes/parts/icon-sets';
38
+ export {
39
+ applyTheme,
40
+ applyThemeCSSVariables,
41
+ convertThemeToGridTheme,
42
+ createTheme,
43
+ extendTheme,
44
+ getThemeCSSVariables,
45
+ mergeThemes,
46
+ removeTheme,
47
+ } from './lib/themes/theme-builder';
48
+ export { themeQuartz } from './lib/themes/theme-quartz';
49
+ // Theme System - New Theming API (AG Grid v32.2+ compatible)
50
+ export * from './lib/themes/types';
51
+ // Core types - AG Grid compatible
52
+ export * from './lib/types/ag-grid-types';
@@ -0,0 +1,188 @@
1
+ import { BrowserModule } from '@angular/platform-browser';
2
+ import type { Meta, StoryObj } from '@storybook/angular';
3
+ import { moduleMetadata } from '@storybook/angular';
4
+ import { ArgentGridComponent, ArgentGridModule, themeQuartz } from '../public-api';
5
+
6
+ interface Employee {
7
+ id: number;
8
+ name: string;
9
+ department: string;
10
+ role: string;
11
+ salary: number;
12
+ location: string;
13
+ performance: number;
14
+ }
15
+
16
+ const meta: Meta<ArgentGridComponent<Employee>> = {
17
+ title: 'Features/Advanced',
18
+ component: ArgentGridComponent,
19
+ decorators: [
20
+ moduleMetadata({
21
+ imports: [ArgentGridModule, BrowserModule],
22
+ }),
23
+ ],
24
+ parameters: {
25
+ layout: 'fullscreen',
26
+ },
27
+ };
28
+
29
+ export default meta;
30
+ type Story = StoryObj<ArgentGridComponent<Employee>>;
31
+
32
+ function generateStaticData(count: number): Employee[] {
33
+ const departments = ['Engineering', 'Sales', 'Marketing', 'HR', 'Finance'];
34
+ const roles = ['Engineer', 'Manager', 'Director', 'VP', 'Intern'];
35
+ const locations = ['New York', 'San Francisco', 'London', 'Singapore', 'Remote'];
36
+
37
+ return Array.from({ length: count }, (_, i) => ({
38
+ id: i + 1,
39
+ name: `Employee ${i + 1}`,
40
+ department: departments[i % departments.length],
41
+ role: roles[i % roles.length],
42
+ salary: 50000 + i * 1000,
43
+ location: locations[i % locations.length],
44
+ performance: 80,
45
+ }));
46
+ }
47
+
48
+ export const SideBar: Story = {
49
+ args: {
50
+ columnDefs: [
51
+ { field: 'id', headerName: 'ID', width: 80, filter: true },
52
+ { field: 'name', headerName: 'Name', width: 200, filter: true },
53
+ { field: 'department', headerName: 'Department', width: 180, filter: 'set' },
54
+ { field: 'role', headerName: 'Role', width: 250, filter: true },
55
+ { field: 'salary', headerName: 'Salary', width: 120, filter: 'number' },
56
+ { field: 'location', headerName: 'Location', width: 150, filter: 'set' },
57
+ { field: 'performance', headerName: 'Performance', width: 120, filter: 'number' },
58
+ ],
59
+ rowData: generateStaticData(50),
60
+ height: '500px',
61
+ width: '100%',
62
+ theme: themeQuartz,
63
+ gridOptions: {
64
+ sideBar: {
65
+ toolPanels: [
66
+ {
67
+ id: 'columns',
68
+ labelDefault: 'Columns',
69
+ labelKey: 'columns',
70
+ iconKey: 'columns',
71
+ toolPanel: 'agColumnsToolPanel',
72
+ },
73
+ {
74
+ id: 'filters',
75
+ labelDefault: 'Filters',
76
+ labelKey: 'filters',
77
+ iconKey: 'filter',
78
+ toolPanel: 'agFiltersToolPanel',
79
+ },
80
+ ],
81
+ },
82
+ },
83
+ },
84
+ parameters: {
85
+ docs: {
86
+ description: {
87
+ story:
88
+ 'Side bar with Columns and Filters panels. Click the sidebar toggle button in the grid toolbar to show/hide.',
89
+ },
90
+ },
91
+ },
92
+ };
93
+
94
+ export const SideBarDefault: Story = {
95
+ args: {
96
+ columnDefs: [
97
+ { field: 'id', headerName: 'ID', width: 80, filter: true },
98
+ { field: 'name', headerName: 'Name', width: 200, filter: true },
99
+ { field: 'department', headerName: 'Department', width: 180, filter: 'set' },
100
+ { field: 'role', headerName: 'Role', width: 250, filter: true },
101
+ { field: 'salary', headerName: 'Salary', width: 120, filter: 'number' },
102
+ ],
103
+ rowData: generateStaticData(50),
104
+ height: '500px',
105
+ width: '100%',
106
+ theme: themeQuartz,
107
+ gridOptions: {
108
+ sideBar: true,
109
+ },
110
+ },
111
+ parameters: {
112
+ docs: {
113
+ description: {
114
+ story: 'Side bar with default configuration (Columns and Filters tool panels).',
115
+ },
116
+ },
117
+ },
118
+ };
119
+
120
+ export const RangeSelection: Story = {
121
+ args: {
122
+ columnDefs: [
123
+ { field: 'id', headerName: 'ID', width: 80 },
124
+ { field: 'name', headerName: 'Name', width: 200 },
125
+ { field: 'department', headerName: 'Department', width: 180 },
126
+ { field: 'role', headerName: 'Role', width: 250 },
127
+ { field: 'salary', headerName: 'Salary', width: 120 },
128
+ { field: 'location', headerName: 'Location', width: 150 },
129
+ ],
130
+ rowData: generateStaticData(50),
131
+ height: '400px',
132
+ width: '100%',
133
+ theme: themeQuartz,
134
+ gridOptions: {
135
+ enableRangeSelection: true,
136
+ },
137
+ },
138
+ parameters: {
139
+ docs: {
140
+ description: {
141
+ story:
142
+ 'Enable range selection to select multiple cells by clicking and dragging. Use Ctrl+C to copy selected range.',
143
+ },
144
+ },
145
+ },
146
+ };
147
+
148
+ export const FullFeatures: Story = {
149
+ args: {
150
+ columnDefs: [
151
+ { field: 'id', headerName: 'ID', width: 80, filter: true, sortable: true },
152
+ { field: 'name', headerName: 'Name', width: 200, filter: true, sortable: true },
153
+ {
154
+ field: 'department',
155
+ headerName: 'Department',
156
+ width: 180,
157
+ filter: 'set',
158
+ sortable: true,
159
+ rowGroup: true,
160
+ },
161
+ { field: 'role', headerName: 'Role', width: 250, filter: true },
162
+ { field: 'salary', headerName: 'Salary', width: 120, filter: 'number', sortable: true },
163
+ { field: 'location', headerName: 'Location', width: 150, filter: 'set' },
164
+ ],
165
+ rowData: generateStaticData(100),
166
+ height: '500px',
167
+ width: '100%',
168
+ theme: themeQuartz,
169
+ gridOptions: {
170
+ floatingFilter: true,
171
+ enableRangeSelection: true,
172
+ sideBar: true,
173
+ autoGroupColumnDef: {
174
+ headerName: 'Organization',
175
+ width: 250,
176
+ pinned: 'left',
177
+ },
178
+ },
179
+ },
180
+ parameters: {
181
+ docs: {
182
+ description: {
183
+ story:
184
+ 'Full-featured grid with sorting, filtering, floating filters, range selection, side bar, and row grouping.',
185
+ },
186
+ },
187
+ },
188
+ };
@@ -0,0 +1,277 @@
1
+ import type { Meta, StoryObj } from '@storybook/angular';
2
+ import { moduleMetadata } from '@storybook/angular';
3
+ import { ArgentGridComponent, ArgentGridModule, themeQuartz } from '../public-api';
4
+
5
+ interface Employee {
6
+ id: number;
7
+ name: string;
8
+ department: string;
9
+ role: string;
10
+ salary: number;
11
+ location: string;
12
+ startDate: string;
13
+ performance: number;
14
+ }
15
+
16
+ const meta: Meta<ArgentGridComponent<Employee>> = {
17
+ title: 'Components/ArgentGrid',
18
+ component: ArgentGridComponent,
19
+ decorators: [
20
+ moduleMetadata({
21
+ imports: [ArgentGridModule],
22
+ }),
23
+ ],
24
+ parameters: {
25
+ layout: 'fullscreen',
26
+ },
27
+ argTypes: {
28
+ height: { control: 'text' },
29
+ width: { control: 'text' },
30
+ rowHeight: { control: 'number' },
31
+ },
32
+ };
33
+
34
+ export default meta;
35
+ type Story = StoryObj<ArgentGridComponent<Employee>>;
36
+
37
+ function generateStaticData(count: number): Employee[] {
38
+ const departments = ['Engineering', 'Sales', 'Marketing', 'HR', 'Finance'];
39
+ const roles = ['Engineer', 'Manager', 'Director', 'VP', 'Intern'];
40
+ const locations = ['New York', 'San Francisco', 'London', 'Singapore', 'Remote'];
41
+
42
+ return Array.from({ length: count }, (_, i) => ({
43
+ id: i + 1,
44
+ name: `Employee ${i + 1}`,
45
+ department: departments[i % departments.length],
46
+ role: roles[i % roles.length],
47
+ salary: 50000 + i * 1000,
48
+ location: locations[i % locations.length],
49
+ startDate: '2020-01-01',
50
+ performance: 80,
51
+ }));
52
+ }
53
+
54
+ export const Default: Story = {
55
+ args: {
56
+ columnDefs: [
57
+ { field: 'id', headerName: 'ID', width: 80 },
58
+ { field: 'name', headerName: 'Name', width: 200 },
59
+ { field: 'department', headerName: 'Department', width: 180 },
60
+ { field: 'role', headerName: 'Role', width: 250 },
61
+ { field: 'salary', headerName: 'Salary', width: 120 },
62
+ { field: 'location', headerName: 'Location', width: 150 },
63
+ { field: 'startDate', headerName: 'Start Date', width: 130 },
64
+ { field: 'performance', headerName: 'Performance', width: 120 },
65
+ ],
66
+ rowData: generateStaticData(100),
67
+ height: '500px',
68
+ width: '100%',
69
+ theme: themeQuartz,
70
+ },
71
+ parameters: {
72
+ docs: {
73
+ description: {
74
+ story: '**Basic grid** with 100 rows. Default theme (Quartz). No special features enabled.',
75
+ },
76
+ },
77
+ },
78
+ };
79
+
80
+ export const LargeDataset: Story = {
81
+ args: {
82
+ columnDefs: [
83
+ { field: 'id', headerName: 'ID', width: 80 },
84
+ { field: 'name', headerName: 'Name', width: 200 },
85
+ { field: 'department', headerName: 'Department', width: 180 },
86
+ { field: 'role', headerName: 'Role', width: 250 },
87
+ { field: 'salary', headerName: 'Salary', width: 120 },
88
+ ],
89
+ rowData: generateStaticData(100000),
90
+ height: '500px',
91
+ width: '100%',
92
+ theme: themeQuartz,
93
+ },
94
+ parameters: {
95
+ docs: {
96
+ description: {
97
+ story:
98
+ '**Performance demo with 100K rows**. Scroll smoothly at 60fps thanks to canvas rendering and virtual scrolling. Try scrolling to the bottom!',
99
+ },
100
+ },
101
+ },
102
+ };
103
+
104
+ export const WithSorting: Story = {
105
+ args: {
106
+ columnDefs: [
107
+ {
108
+ field: 'id',
109
+ headerName: 'ID ↕️',
110
+ width: 80,
111
+ sortable: true,
112
+ headerComponentParams: { sortIcon: '↕️' },
113
+ },
114
+ {
115
+ field: 'name',
116
+ headerName: 'Name ↕️',
117
+ width: 200,
118
+ sortable: true,
119
+ headerComponentParams: { sortIcon: '↕️' },
120
+ },
121
+ {
122
+ field: 'department',
123
+ headerName: 'Department ↕️',
124
+ width: 180,
125
+ sortable: true,
126
+ headerComponentParams: { sortIcon: '↕️' },
127
+ },
128
+ {
129
+ field: 'salary',
130
+ headerName: 'Salary ↕️',
131
+ width: 120,
132
+ sortable: true,
133
+ headerComponentParams: { sortIcon: '↕️' },
134
+ },
135
+ ],
136
+ rowData: generateStaticData(50),
137
+ height: '400px',
138
+ width: '100%',
139
+ theme: themeQuartz,
140
+ },
141
+ parameters: {
142
+ docs: {
143
+ description: {
144
+ story:
145
+ '**Sortable columns** with ↕️ indicators. **Click column headers** to sort ascending/descending. Look for the **▲/▼ arrows** that appear when sorted.',
146
+ },
147
+ },
148
+ },
149
+ };
150
+
151
+ export const WithSelection: Story = {
152
+ args: {
153
+ columnDefs: [
154
+ {
155
+ field: 'id',
156
+ headerName: 'ID ☑️',
157
+ width: 80,
158
+ checkboxSelection: true,
159
+ headerComponentParams: { selectionIcon: '☑️' },
160
+ },
161
+ { field: 'name', headerName: 'Name', width: 200 },
162
+ { field: 'department', headerName: 'Department', width: 180 },
163
+ { field: 'role', headerName: 'Role', width: 250 },
164
+ ],
165
+ rowData: generateStaticData(50),
166
+ rowSelection: 'multiple',
167
+ height: '400px',
168
+ width: '100%',
169
+ theme: themeQuartz,
170
+ },
171
+ parameters: {
172
+ docs: {
173
+ description: {
174
+ story:
175
+ '**Row selection with checkboxes**. The first column shows **☑️ checkboxes** in every row. **Click checkboxes** to select/deselect rows. **Header checkbox** selects/deselects all visible rows.',
176
+ },
177
+ },
178
+ },
179
+ };
180
+
181
+ export const WithFiltering: Story = {
182
+ args: {
183
+ columnDefs: [
184
+ {
185
+ field: 'id',
186
+ headerName: 'ID 🔢',
187
+ width: 80,
188
+ filter: 'number',
189
+ floatingFilter: true,
190
+ headerComponentParams: { filterIcon: '🔢' },
191
+ },
192
+ {
193
+ field: 'name',
194
+ headerName: 'Name 🔤',
195
+ width: 200,
196
+ filter: 'text',
197
+ floatingFilter: true,
198
+ headerComponentParams: { filterIcon: '🔤' },
199
+ },
200
+ {
201
+ field: 'department',
202
+ headerName: 'Department ☑️',
203
+ width: 180,
204
+ filter: 'set',
205
+ floatingFilter: true,
206
+ headerComponentParams: { filterIcon: '☑️' },
207
+ },
208
+ {
209
+ field: 'role',
210
+ headerName: 'Role 🔤',
211
+ width: 250,
212
+ filter: 'text',
213
+ floatingFilter: true,
214
+ headerComponentParams: { filterIcon: '🔤' },
215
+ },
216
+ ],
217
+ rowData: generateStaticData(50),
218
+ height: '500px',
219
+ width: '100%',
220
+ theme: themeQuartz,
221
+ },
222
+ parameters: {
223
+ docs: {
224
+ description: {
225
+ story:
226
+ '**Filtering with visible filter inputs**. Each filterable column shows an icon (🔢 Number, 🔤 Text, ☑️ Set). **Filter inputs are visible in the header row** - type to filter. Department uses a set filter (dropdown with checkboxes).',
227
+ },
228
+ },
229
+ },
230
+ };
231
+
232
+ export const Empty: Story = {
233
+ args: {
234
+ columnDefs: [
235
+ { field: 'id', headerName: 'ID', width: 80 },
236
+ { field: 'name', headerName: 'Name', width: 200 },
237
+ ],
238
+ rowData: [],
239
+ height: '300px',
240
+ width: '100%',
241
+ theme: themeQuartz,
242
+ },
243
+ parameters: {
244
+ docs: {
245
+ description: {
246
+ story: '**Empty grid** with no rows. Shows overlay message "No rows to show".',
247
+ },
248
+ },
249
+ },
250
+ };
251
+
252
+ export const WithCustomTheme: Story = {
253
+ args: {
254
+ columnDefs: [
255
+ { field: 'id', headerName: 'ID', width: 80 },
256
+ { field: 'name', headerName: 'Name', width: 200 },
257
+ { field: 'department', headerName: 'Department', width: 180 },
258
+ { field: 'salary', headerName: 'Salary', width: 120 },
259
+ ],
260
+ rowData: generateStaticData(50),
261
+ height: '400px',
262
+ width: '100%',
263
+ theme: themeQuartz.withParams({
264
+ accentColor: '#ff5722', // Orange accent
265
+ rowHeight: 48,
266
+ fontSize: 14,
267
+ }),
268
+ },
269
+ parameters: {
270
+ docs: {
271
+ description: {
272
+ story:
273
+ '**Custom theme** with orange accent color, larger row height (48px), and larger font (14px). See Theming stories for more theme options.',
274
+ },
275
+ },
276
+ },
277
+ };