argent-grid 0.1.0 → 0.3.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 (122) 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 +70 -27
  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/cell-renderers.spec.ts +152 -0
  28. package/e2e/debug-streaming.spec.ts +31 -0
  29. package/e2e/dnd.spec.ts +73 -0
  30. package/e2e/screenshots.spec.ts +52 -0
  31. package/e2e/theming.spec.ts +35 -0
  32. package/e2e/visual.spec.ts +112 -0
  33. package/e2e/visual.spec.ts-snapshots/checkbox-renderer-mixed.png +0 -0
  34. package/e2e/visual.spec.ts-snapshots/debug.png +0 -0
  35. package/e2e/visual.spec.ts-snapshots/grid-column-group-headers.png +0 -0
  36. package/e2e/visual.spec.ts-snapshots/grid-default.png +0 -0
  37. package/e2e/visual.spec.ts-snapshots/grid-empty-state.png +0 -0
  38. package/e2e/visual.spec.ts-snapshots/grid-filter-popup.png +0 -0
  39. package/e2e/visual.spec.ts-snapshots/grid-scroll-borders.png +0 -0
  40. package/e2e/visual.spec.ts-snapshots/grid-sidebar-buttons.png +0 -0
  41. package/e2e/visual.spec.ts-snapshots/grid-text-filter.png +0 -0
  42. package/e2e/visual.spec.ts-snapshots/grid-with-selection.png +0 -0
  43. package/e2e/visual.spec.ts-snapshots/rating-renderer-varied.png +0 -0
  44. package/package.json +21 -7
  45. package/plan.md +56 -28
  46. package/playwright.config.ts +38 -0
  47. package/setup-vitest.ts +10 -13
  48. package/src/lib/argent-grid.module.ts +10 -12
  49. package/src/lib/components/argent-grid.component.css +281 -321
  50. package/src/lib/components/argent-grid.component.html +295 -207
  51. package/src/lib/components/argent-grid.component.spec.ts +120 -160
  52. package/src/lib/components/argent-grid.component.ts +1193 -290
  53. package/src/lib/components/argent-grid.regressions.spec.ts +301 -0
  54. package/src/lib/components/argent-grid.selection.spec.ts +132 -0
  55. package/src/lib/components/set-filter/set-filter.component.spec.ts +191 -0
  56. package/src/lib/components/set-filter/set-filter.component.ts +307 -0
  57. package/src/lib/directives/ag-grid-compatibility.directive.ts +16 -26
  58. package/src/lib/directives/click-outside.directive.ts +19 -0
  59. package/src/lib/rendering/canvas-renderer.spec.ts +513 -0
  60. package/src/lib/rendering/canvas-renderer.ts +456 -452
  61. package/src/lib/rendering/live-data-handler.ts +110 -0
  62. package/src/lib/rendering/live-data-optimizations.ts +133 -0
  63. package/src/lib/rendering/render/blit.spec.ts +16 -27
  64. package/src/lib/rendering/render/blit.ts +48 -36
  65. package/src/lib/rendering/render/cells.spec.ts +132 -0
  66. package/src/lib/rendering/render/cells.ts +167 -28
  67. package/src/lib/rendering/render/column-utils.ts +95 -0
  68. package/src/lib/rendering/render/hit-test.ts +50 -0
  69. package/src/lib/rendering/render/index.ts +88 -76
  70. package/src/lib/rendering/render/lines.ts +53 -47
  71. package/src/lib/rendering/render/primitives.ts +423 -0
  72. package/src/lib/rendering/render/theme.spec.ts +8 -12
  73. package/src/lib/rendering/render/theme.ts +7 -10
  74. package/src/lib/rendering/render/types.ts +3 -2
  75. package/src/lib/rendering/render/walk.spec.ts +35 -38
  76. package/src/lib/rendering/render/walk.ts +94 -64
  77. package/src/lib/rendering/utils/damage-tracker.spec.ts +8 -7
  78. package/src/lib/rendering/utils/damage-tracker.ts +6 -18
  79. package/src/lib/rendering/utils/index.ts +1 -1
  80. package/src/lib/services/grid.service.set-filter.spec.ts +219 -0
  81. package/src/lib/services/grid.service.spec.ts +1241 -201
  82. package/src/lib/services/grid.service.ts +1204 -235
  83. package/src/lib/themes/parts/color-schemes.ts +132 -0
  84. package/src/lib/themes/parts/icon-sets.ts +258 -0
  85. package/src/lib/themes/theme-builder.ts +347 -0
  86. package/src/lib/themes/theme-quartz.ts +72 -0
  87. package/src/lib/themes/types.ts +238 -0
  88. package/src/lib/types/ag-grid-types.ts +573 -14
  89. package/src/public-api.ts +39 -9
  90. package/src/stories/Advanced.stories.ts +249 -0
  91. package/src/stories/ArgentGrid.stories.ts +301 -0
  92. package/src/stories/Benchmark.stories.ts +76 -0
  93. package/src/stories/CellRenderers.stories.ts +395 -0
  94. package/src/stories/Filtering.stories.ts +292 -0
  95. package/src/stories/Grouping.stories.ts +290 -0
  96. package/src/stories/Streaming.stories.ts +57 -0
  97. package/src/stories/Theming.stories.ts +137 -0
  98. package/src/stories/Tooltips.stories.ts +381 -0
  99. package/src/stories/benchmark-wrapper.component.ts +355 -0
  100. package/src/stories/story-utils.ts +88 -0
  101. package/src/stories/streaming-wrapper.component.ts +441 -0
  102. package/tsconfig.json +1 -0
  103. package/tsconfig.storybook.json +10 -0
  104. package/vitest.config.ts +9 -9
  105. package/demo-app/README.md +0 -70
  106. package/demo-app/angular.json +0 -78
  107. package/demo-app/e2e/benchmark.spec.ts +0 -53
  108. package/demo-app/e2e/demo-page.spec.ts +0 -77
  109. package/demo-app/e2e/grid-features.spec.ts +0 -269
  110. package/demo-app/package-lock.json +0 -14023
  111. package/demo-app/package.json +0 -36
  112. package/demo-app/playwright-test-menu.js +0 -19
  113. package/demo-app/playwright.config.ts +0 -23
  114. package/demo-app/src/app/app.component.ts +0 -10
  115. package/demo-app/src/app/app.config.ts +0 -13
  116. package/demo-app/src/app/app.routes.ts +0 -7
  117. package/demo-app/src/app/demo-page/demo-page.component.css +0 -313
  118. package/demo-app/src/app/demo-page/demo-page.component.html +0 -124
  119. package/demo-app/src/app/demo-page/demo-page.component.ts +0 -366
  120. package/demo-app/src/index.html +0 -19
  121. package/demo-app/src/main.ts +0 -6
  122. package/demo-app/tsconfig.json +0 -31
@@ -0,0 +1,290 @@
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
+ import {
6
+ departmentValueFormatter,
7
+ locationValueFormatter,
8
+ roleValueFormatter,
9
+ STORY_DEPARTMENTS,
10
+ STORY_LOCATIONS,
11
+ STORY_ROLES,
12
+ } from './story-utils';
13
+
14
+ interface Employee {
15
+ id: number;
16
+ name: string;
17
+ department: string;
18
+ role: string;
19
+ salary: number;
20
+ location: string;
21
+ }
22
+
23
+ const meta: Meta<ArgentGridComponent<Employee>> = {
24
+ title: 'Features/Grouping',
25
+ component: ArgentGridComponent,
26
+ decorators: [
27
+ moduleMetadata({
28
+ imports: [ArgentGridModule, BrowserModule],
29
+ }),
30
+ ],
31
+ parameters: {
32
+ layout: 'fullscreen',
33
+ },
34
+ };
35
+
36
+ export default meta;
37
+ type Story = StoryObj<ArgentGridComponent<Employee>>;
38
+
39
+ function generateStaticData(count: number): Employee[] {
40
+ const departments = STORY_DEPARTMENTS;
41
+ const roles = STORY_ROLES;
42
+ const locations = STORY_LOCATIONS;
43
+
44
+ return Array.from({ length: count }, (_, i) => ({
45
+ id: i + 1,
46
+ name: `Employee ${i + 1}`,
47
+ department: departments[i % departments.length],
48
+ role: roles[i % roles.length],
49
+ salary: 50000 + i * 1000,
50
+ location: locations[i % locations.length],
51
+ }));
52
+ }
53
+
54
+ export const RowGrouping: Story = {
55
+ args: {
56
+ columnDefs: [
57
+ { field: 'id', headerName: 'ID', width: 80 },
58
+ { field: 'name', headerName: 'Name', width: 200 },
59
+ {
60
+ field: 'department',
61
+ headerName: 'Department 📁',
62
+ width: 180,
63
+ rowGroup: true,
64
+ headerComponentParams: { groupIcon: '📁' },
65
+ valueFormatter: departmentValueFormatter,
66
+ },
67
+ { field: 'role', headerName: 'Role', width: 250, valueFormatter: roleValueFormatter },
68
+ { field: 'salary', headerName: 'Salary', width: 120 },
69
+ {
70
+ field: 'location',
71
+ headerName: 'Location',
72
+ width: 150,
73
+ valueFormatter: locationValueFormatter,
74
+ },
75
+ ],
76
+ rowData: generateStaticData(100),
77
+ height: 'calc(100vh - 60px)',
78
+ width: '100%',
79
+ theme: themeQuartz,
80
+ gridOptions: {
81
+ autoGroupColumnDef: {
82
+ headerName: 'Organization 📁',
83
+ width: 250,
84
+ pinned: 'left',
85
+ },
86
+ groupDefaultExpanded: 1, // Expand first level by default
87
+ },
88
+ },
89
+ parameters: {
90
+ docs: {
91
+ description: {
92
+ story:
93
+ '**Row grouping by Department** column. Grouped columns show a 📁 icon. Click the **▶ expand/collapse arrows** in the group rows to show/hide items. **Drag column headers** to the left panel to group by multiple columns.',
94
+ },
95
+ },
96
+ },
97
+ };
98
+
99
+ export const MultiLevelGrouping: Story = {
100
+ args: {
101
+ columnDefs: [
102
+ { field: 'id', headerName: 'ID', width: 80 },
103
+ { field: 'name', headerName: 'Name', width: 200 },
104
+ {
105
+ field: 'department',
106
+ headerName: 'Department 📁',
107
+ width: 150,
108
+ rowGroup: true,
109
+ headerComponentParams: { groupIcon: '📁' },
110
+ valueFormatter: departmentValueFormatter,
111
+ },
112
+ {
113
+ field: 'location',
114
+ headerName: 'Location 📁',
115
+ width: 150,
116
+ rowGroup: true,
117
+ headerComponentParams: { groupIcon: '📁' },
118
+ valueFormatter: locationValueFormatter,
119
+ },
120
+ { field: 'role', headerName: 'Role', width: 250, valueFormatter: roleValueFormatter },
121
+ { field: 'salary', headerName: 'Salary', width: 120 },
122
+ ],
123
+ rowData: generateStaticData(100),
124
+ height: 'calc(100vh - 60px)',
125
+ width: '100%',
126
+ theme: themeQuartz,
127
+ gridOptions: {
128
+ autoGroupColumnDef: {
129
+ headerName: 'Organization 📁📁',
130
+ width: 300,
131
+ pinned: 'left',
132
+ },
133
+ groupDefaultExpanded: 2, // Expand first 2 levels by default
134
+ },
135
+ },
136
+ parameters: {
137
+ docs: {
138
+ description: {
139
+ story:
140
+ '**Multi-level grouping** by Department AND Location. Each grouped column shows a 📁 icon. Groups are **expanded by default** to show the hierarchy. Click **▶ arrows** to collapse/expand. Notice the nested structure: Department → Location → Employees.',
141
+ },
142
+ },
143
+ },
144
+ };
145
+
146
+ export const GroupingWithAggregation: Story = {
147
+ args: {
148
+ columnDefs: [
149
+ { field: 'id', headerName: 'ID', width: 80 },
150
+ { field: 'name', headerName: 'Name', width: 200 },
151
+ {
152
+ field: 'department',
153
+ headerName: 'Department 📁',
154
+ width: 180,
155
+ rowGroup: true,
156
+ headerComponentParams: { groupIcon: '📁' },
157
+ valueFormatter: departmentValueFormatter,
158
+ },
159
+ { field: 'role', headerName: 'Role', width: 250, valueFormatter: roleValueFormatter },
160
+ {
161
+ field: 'salary',
162
+ headerName: 'Salary 💰',
163
+ width: 120,
164
+ aggFunc: 'sum', // Show sum in group rows
165
+ },
166
+ {
167
+ field: 'location',
168
+ headerName: 'Location',
169
+ width: 150,
170
+ valueFormatter: locationValueFormatter,
171
+ },
172
+ ],
173
+ rowData: generateStaticData(100),
174
+ height: 'calc(100vh - 60px)',
175
+ width: '100%',
176
+ theme: themeQuartz,
177
+ gridOptions: {
178
+ autoGroupColumnDef: {
179
+ headerName: 'Organization 📁',
180
+ width: 250,
181
+ pinned: 'left',
182
+ },
183
+ groupDefaultExpanded: 1,
184
+ },
185
+ },
186
+ parameters: {
187
+ docs: {
188
+ description: {
189
+ story:
190
+ '**Grouping with aggregation**. Salary column shows **sum (💰)** for each department group. Look at the group rows to see aggregated values. Supported aggregations: sum, avg, min, max, count.',
191
+ },
192
+ },
193
+ },
194
+ };
195
+
196
+ export const DragAndDropGrouping: Story = {
197
+ args: {
198
+ columnDefs: [
199
+ { field: 'id', headerName: 'ID', width: 80 },
200
+ { field: 'name', headerName: 'Name', width: 200 },
201
+ {
202
+ field: 'department',
203
+ headerName: 'Department 📁 (drag me!)',
204
+ width: 180,
205
+ rowGroup: false, // Not pre-grouped - user can drag
206
+ headerComponentParams: { draggable: true },
207
+ valueFormatter: departmentValueFormatter,
208
+ },
209
+ {
210
+ field: 'location',
211
+ headerName: 'Location 📁 (drag me!)',
212
+ width: 150,
213
+ rowGroup: false,
214
+ headerComponentParams: { draggable: true },
215
+ valueFormatter: locationValueFormatter,
216
+ },
217
+ { field: 'role', headerName: 'Role', width: 250, valueFormatter: roleValueFormatter },
218
+ { field: 'salary', headerName: 'Salary', width: 120 },
219
+ ],
220
+ rowData: generateStaticData(100),
221
+ height: 'calc(100vh - 60px)',
222
+ width: '100%',
223
+ theme: themeQuartz,
224
+ gridOptions: {
225
+ rowGroupPanelShow: 'always', // Always show group panel
226
+ autoGroupColumnDef: {
227
+ headerName: 'Groups 📁',
228
+ width: 250,
229
+ pinned: 'left',
230
+ },
231
+ },
232
+ },
233
+ parameters: {
234
+ docs: {
235
+ description: {
236
+ story:
237
+ '**Drag-and-drop grouping**. See the **"Drag me!"** labels? **Drag column headers** (Department, Location) to the **"Groups" panel on the left** to create groups dynamically. Drop columns back to ungroup. Multiple columns can be grouped at once.',
238
+ },
239
+ },
240
+ },
241
+ };
242
+
243
+ export const ColumnGroups: Story = {
244
+ args: {
245
+ columnDefs: [
246
+ {
247
+ headerName: 'Group A',
248
+ children: [
249
+ { field: 'id', headerName: 'ID', width: 80 },
250
+ { field: 'name', headerName: 'Name', width: 200 },
251
+ ],
252
+ },
253
+ {
254
+ headerName: 'Group B',
255
+ children: [
256
+ {
257
+ field: 'department',
258
+ headerName: 'Department',
259
+ width: 180,
260
+ valueFormatter: departmentValueFormatter,
261
+ },
262
+ {
263
+ headerName: 'Deep Group',
264
+ children: [
265
+ { field: 'role', headerName: 'Role', width: 250, valueFormatter: roleValueFormatter },
266
+ { field: 'salary', headerName: 'Salary', width: 120 },
267
+ ],
268
+ },
269
+ ],
270
+ },
271
+ {
272
+ field: 'location',
273
+ headerName: 'Location',
274
+ width: 150,
275
+ valueFormatter: locationValueFormatter,
276
+ },
277
+ ],
278
+ rowData: generateStaticData(50),
279
+ height: 'calc(100vh - 60px)',
280
+ width: '100%',
281
+ theme: themeQuartz,
282
+ },
283
+ parameters: {
284
+ docs: {
285
+ description: {
286
+ story: '**Nested column groups**. Demonstrates multiple levels of header grouping.',
287
+ },
288
+ },
289
+ },
290
+ };
@@ -0,0 +1,57 @@
1
+ import type { Meta, StoryObj } from '@storybook/angular';
2
+ import { moduleMetadata } from '@storybook/angular';
3
+ import { StreamingWrapperComponent } from './streaming-wrapper.component';
4
+
5
+ const meta: Meta<StreamingWrapperComponent> = {
6
+ title: 'Features/Streaming',
7
+ component: StreamingWrapperComponent,
8
+ decorators: [
9
+ moduleMetadata({
10
+ imports: [StreamingWrapperComponent],
11
+ }),
12
+ ],
13
+ parameters: {
14
+ layout: 'fullscreen',
15
+ },
16
+ };
17
+
18
+ export default meta;
19
+ type Story = StoryObj<StreamingWrapperComponent>;
20
+
21
+ export const LiveStockFeed: Story = {
22
+ args: {
23
+ updateFrequency: 100,
24
+ batchSize: 5,
25
+ },
26
+ render: (args) => ({
27
+ props: args,
28
+ template: `<app-streaming-wrapper [updateFrequency]="updateFrequency" [batchSize]="batchSize" />`,
29
+ }),
30
+ parameters: {
31
+ docs: {
32
+ description: {
33
+ story:
34
+ 'Simulates a live stock market feed. Updates are buffered and applied via applyTransaction at most twice per second (500ms throttle) for efficient rendering. Demonstrates high-performance row updates with the canvas engine.',
35
+ },
36
+ },
37
+ },
38
+ };
39
+
40
+ export const HighFrequencyStream: Story = {
41
+ args: {
42
+ updateFrequency: 50,
43
+ batchSize: 10,
44
+ },
45
+ render: (args) => ({
46
+ props: args,
47
+ template: `<app-streaming-wrapper [updateFrequency]="updateFrequency" [batchSize]="batchSize" />`,
48
+ }),
49
+ parameters: {
50
+ docs: {
51
+ description: {
52
+ story:
53
+ 'Stresses the grid with 20 updates per second (10 rows each), totaling 200 row updates per second. All updates are buffered and applied in batched transactions every 500ms. Shows the efficiency of the transaction API and canvas renderer.',
54
+ },
55
+ },
56
+ },
57
+ };
@@ -0,0 +1,137 @@
1
+ import { BrowserModule } from '@angular/platform-browser';
2
+ import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
3
+ import type { Meta, StoryObj } from '@storybook/angular';
4
+ import { moduleMetadata } from '@storybook/angular';
5
+ import { ArgentGridComponent, ArgentGridModule, colorSchemeDark, themeQuartz } from '../public-api';
6
+ import {
7
+ departmentValueFormatter,
8
+ locationValueFormatter,
9
+ roleValueFormatter,
10
+ STORY_DEPARTMENTS,
11
+ STORY_LOCATIONS,
12
+ STORY_ROLES,
13
+ } from './story-utils';
14
+
15
+ interface Employee {
16
+ id: number;
17
+ name: string;
18
+ department: string;
19
+ role: string;
20
+ salary: number;
21
+ location: string;
22
+ }
23
+
24
+ const meta: Meta<ArgentGridComponent<Employee>> = {
25
+ title: 'Features/Theming',
26
+ component: ArgentGridComponent,
27
+ decorators: [
28
+ moduleMetadata({
29
+ imports: [ArgentGridModule, BrowserModule, BrowserAnimationsModule],
30
+ }),
31
+ ],
32
+ parameters: {
33
+ layout: 'fullscreen',
34
+ },
35
+ };
36
+
37
+ export default meta;
38
+ type Story = StoryObj<ArgentGridComponent<Employee>>;
39
+
40
+ function generateStaticData(count: number): Employee[] {
41
+ const departments = STORY_DEPARTMENTS;
42
+ const roles = STORY_ROLES;
43
+ const locations = STORY_LOCATIONS;
44
+
45
+ return Array.from({ length: count }, (_, i) => ({
46
+ id: i + 1,
47
+ name: `Employee ${i + 1}`,
48
+ department: departments[i % departments.length],
49
+ role: roles[i % roles.length],
50
+ salary: 50000 + i * 1000,
51
+ location: locations[i % locations.length],
52
+ }));
53
+ }
54
+
55
+ const columnDefs = [
56
+ { field: 'id', headerName: 'ID', width: 80 },
57
+ { field: 'name', headerName: 'Name', width: 200 },
58
+ {
59
+ field: 'department',
60
+ headerName: 'Department',
61
+ width: 180,
62
+ valueFormatter: departmentValueFormatter,
63
+ },
64
+ { field: 'role', headerName: 'Role', width: 250, valueFormatter: roleValueFormatter },
65
+ { field: 'salary', headerName: 'Salary', width: 120 },
66
+ { field: 'location', headerName: 'Location', width: 150, valueFormatter: locationValueFormatter },
67
+ ];
68
+
69
+ export const LightMode: Story = {
70
+ args: {
71
+ columnDefs,
72
+ rowData: generateStaticData(50),
73
+ height: 'calc(100vh - 60px)',
74
+ width: '100%',
75
+ theme: themeQuartz,
76
+ },
77
+ parameters: {
78
+ docs: {
79
+ description: {
80
+ story: 'Default light theme using Quartz theme.',
81
+ },
82
+ },
83
+ },
84
+ };
85
+
86
+ export const DarkMode: Story = {
87
+ args: {
88
+ columnDefs,
89
+ rowData: generateStaticData(50),
90
+ height: 'calc(100vh - 60px)',
91
+ width: '100%',
92
+ theme: themeQuartz.withPart(colorSchemeDark),
93
+ },
94
+ parameters: {
95
+ docs: {
96
+ description: {
97
+ story: 'Dark mode using Quartz theme with dark color scheme.',
98
+ },
99
+ },
100
+ },
101
+ };
102
+
103
+ export const CompactMode: Story = {
104
+ args: {
105
+ columnDefs,
106
+ rowData: generateStaticData(50),
107
+ height: 'calc(100vh - 60px)',
108
+ width: '100%',
109
+ theme: themeQuartz.withParams({ rowHeight: 32, fontSize: 12, spacing: 4 }),
110
+ },
111
+ parameters: {
112
+ docs: {
113
+ description: {
114
+ story: 'Compact mode with smaller row height and font size.',
115
+ },
116
+ },
117
+ },
118
+ };
119
+
120
+ export const CompactDarkMode: Story = {
121
+ args: {
122
+ columnDefs,
123
+ rowData: generateStaticData(50),
124
+ height: 'calc(100vh - 60px)',
125
+ width: '100%',
126
+ theme: themeQuartz
127
+ .withParams({ rowHeight: 32, fontSize: 12, spacing: 4 })
128
+ .withPart(colorSchemeDark),
129
+ },
130
+ parameters: {
131
+ docs: {
132
+ description: {
133
+ story: 'Combined compact and dark mode for dense data display.',
134
+ },
135
+ },
136
+ },
137
+ };