argent-grid 0.2.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.
- package/AGENTS.md +70 -27
- package/e2e/advanced.spec.ts +1 -1
- package/e2e/benchmark.spec.ts +7 -7
- package/e2e/cell-renderers.spec.ts +152 -0
- package/e2e/debug-streaming.spec.ts +31 -0
- package/e2e/dnd.spec.ts +73 -0
- package/e2e/screenshots.spec.ts +1 -1
- package/e2e/visual.spec.ts +30 -9
- package/e2e/visual.spec.ts-snapshots/checkbox-renderer-mixed.png +0 -0
- package/e2e/visual.spec.ts-snapshots/debug.png +0 -0
- package/e2e/visual.spec.ts-snapshots/grid-column-group-headers.png +0 -0
- package/e2e/visual.spec.ts-snapshots/grid-default.png +0 -0
- package/e2e/visual.spec.ts-snapshots/grid-empty-state.png +0 -0
- package/e2e/visual.spec.ts-snapshots/grid-filter-popup.png +0 -0
- package/e2e/visual.spec.ts-snapshots/grid-scroll-borders.png +0 -0
- package/e2e/visual.spec.ts-snapshots/grid-sidebar-buttons.png +0 -0
- package/e2e/visual.spec.ts-snapshots/grid-text-filter.png +0 -0
- package/e2e/visual.spec.ts-snapshots/grid-with-selection.png +0 -0
- package/e2e/visual.spec.ts-snapshots/rating-renderer-varied.png +0 -0
- package/package.json +5 -5
- package/plan.md +30 -34
- package/src/lib/components/argent-grid.component.css +258 -549
- package/src/lib/components/argent-grid.component.html +272 -306
- package/src/lib/components/argent-grid.component.ts +585 -135
- package/src/lib/components/argent-grid.regressions.spec.ts +301 -0
- package/src/lib/components/argent-grid.selection.spec.ts +2 -2
- package/src/lib/components/set-filter/set-filter.component.spec.ts +191 -0
- package/src/lib/components/set-filter/set-filter.component.ts +7 -2
- package/src/lib/rendering/canvas-renderer.spec.ts +148 -1
- package/src/lib/rendering/canvas-renderer.ts +177 -286
- package/src/lib/rendering/render/cells.ts +122 -5
- package/src/lib/rendering/render/column-utils.ts +27 -5
- package/src/lib/rendering/render/hit-test.ts +6 -11
- package/src/lib/rendering/render/index.ts +15 -6
- package/src/lib/rendering/render/lines.ts +12 -6
- package/src/lib/rendering/render/primitives.ts +269 -7
- package/src/lib/rendering/render/types.ts +2 -1
- package/src/lib/rendering/render/walk.ts +39 -19
- package/src/lib/services/grid.service.spec.ts +76 -0
- package/src/lib/services/grid.service.ts +451 -114
- package/src/lib/themes/theme-quartz.ts +2 -2
- package/src/lib/types/ag-grid-types.ts +500 -0
- package/src/stories/Advanced.stories.ts +78 -17
- package/src/stories/ArgentGrid.stories.ts +50 -26
- package/src/stories/Benchmark.stories.ts +17 -15
- package/src/stories/CellRenderers.stories.ts +205 -31
- package/src/stories/Filtering.stories.ts +56 -16
- package/src/stories/Grouping.stories.ts +86 -13
- package/src/stories/Streaming.stories.ts +57 -0
- package/src/stories/Theming.stories.ts +23 -10
- package/src/stories/Tooltips.stories.ts +381 -0
- package/src/stories/benchmark-wrapper.component.ts +69 -29
- package/src/stories/story-utils.ts +88 -0
- package/src/stories/streaming-wrapper.component.ts +441 -0
- package/tsconfig.json +1 -0
|
@@ -2,6 +2,7 @@ import { BrowserModule } from '@angular/platform-browser';
|
|
|
2
2
|
import type { Meta, StoryObj } from '@storybook/angular';
|
|
3
3
|
import { moduleMetadata } from '@storybook/angular';
|
|
4
4
|
import { ArgentGridComponent, ArgentGridModule, themeQuartz } from '../public-api';
|
|
5
|
+
import { STORY_LOCATIONS } from './story-utils';
|
|
5
6
|
|
|
6
7
|
interface Employee {
|
|
7
8
|
id: number;
|
|
@@ -34,7 +35,7 @@ type Story = StoryObj<ArgentGridComponent<Employee>>;
|
|
|
34
35
|
function generateStaticData(count: number): Employee[] {
|
|
35
36
|
const departments = ['Engineering', 'Sales', 'Marketing', 'HR', 'Finance'];
|
|
36
37
|
const roles = ['Engineer', 'Manager', 'Director', 'VP', 'Intern'];
|
|
37
|
-
const locations =
|
|
38
|
+
const locations = STORY_LOCATIONS;
|
|
38
39
|
const statuses = ['Active', 'On Leave', 'Remote', 'Travel'];
|
|
39
40
|
|
|
40
41
|
return Array.from({ length: count }, (_, i) => ({
|
|
@@ -45,8 +46,9 @@ function generateStaticData(count: number): Employee[] {
|
|
|
45
46
|
salary: 50000 + i * 1000,
|
|
46
47
|
salaryTrend: [10, 20, 30, 40, 50, 60, 70, 80, 90, 100].map((v) => (v + i * 5) % 100),
|
|
47
48
|
location: locations[i % locations.length],
|
|
48
|
-
|
|
49
|
-
|
|
49
|
+
// Use deterministic "semi-random" patterns based on index for stable E2E screenshots
|
|
50
|
+
performance: 60 + ((i * 7) % 40),
|
|
51
|
+
status: statuses[(i * 3) % statuses.length],
|
|
50
52
|
}));
|
|
51
53
|
}
|
|
52
54
|
|
|
@@ -72,7 +74,7 @@ export const SparklineArea: Story = {
|
|
|
72
74
|
},
|
|
73
75
|
],
|
|
74
76
|
rowData: generateStaticData(50),
|
|
75
|
-
height: '
|
|
77
|
+
height: 'calc(100vh - 60px)',
|
|
76
78
|
width: '100%',
|
|
77
79
|
theme: themeQuartz,
|
|
78
80
|
},
|
|
@@ -106,7 +108,7 @@ export const SparklineLine: Story = {
|
|
|
106
108
|
},
|
|
107
109
|
],
|
|
108
110
|
rowData: generateStaticData(50),
|
|
109
|
-
height: '
|
|
111
|
+
height: 'calc(100vh - 60px)',
|
|
110
112
|
width: '100%',
|
|
111
113
|
theme: themeQuartz,
|
|
112
114
|
},
|
|
@@ -119,7 +121,41 @@ export const SparklineLine: Story = {
|
|
|
119
121
|
},
|
|
120
122
|
};
|
|
121
123
|
|
|
122
|
-
export const
|
|
124
|
+
export const SparklineBar: Story = {
|
|
125
|
+
args: {
|
|
126
|
+
columnDefs: [
|
|
127
|
+
{ field: 'id', headerName: 'ID', width: 80 },
|
|
128
|
+
{ field: 'name', headerName: 'Name', width: 200 },
|
|
129
|
+
{ field: 'department', headerName: 'Department', width: 180 },
|
|
130
|
+
{
|
|
131
|
+
field: 'salaryTrend',
|
|
132
|
+
headerName: 'Salary Trend',
|
|
133
|
+
width: 200,
|
|
134
|
+
cellRenderer: 'sparkline',
|
|
135
|
+
sparklineOptions: {
|
|
136
|
+
type: 'bar',
|
|
137
|
+
bar: {
|
|
138
|
+
fill: '#6366f1',
|
|
139
|
+
strokeWidth: 0,
|
|
140
|
+
},
|
|
141
|
+
},
|
|
142
|
+
},
|
|
143
|
+
],
|
|
144
|
+
rowData: generateStaticData(50),
|
|
145
|
+
height: 'calc(100vh - 60px)',
|
|
146
|
+
width: '100%',
|
|
147
|
+
theme: themeQuartz,
|
|
148
|
+
},
|
|
149
|
+
parameters: {
|
|
150
|
+
docs: {
|
|
151
|
+
description: {
|
|
152
|
+
story: 'Bar sparkline showing salary trend data as a series of vertical bars.',
|
|
153
|
+
},
|
|
154
|
+
},
|
|
155
|
+
},
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
export const ProgressBar: Story = {
|
|
123
159
|
args: {
|
|
124
160
|
columnDefs: [
|
|
125
161
|
{ field: 'id', headerName: 'ID', width: 80 },
|
|
@@ -128,28 +164,25 @@ export const CustomCellRenderer: Story = {
|
|
|
128
164
|
{
|
|
129
165
|
field: 'performance',
|
|
130
166
|
headerName: 'Performance',
|
|
131
|
-
width:
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
<div style="width: ${value}%; height: 100%; background: ${color}; border-radius: 4px;"></div>
|
|
138
|
-
</div>
|
|
139
|
-
<span style="color: ${color}; font-weight: 600; min-width: 40px;">${value}%</span>
|
|
140
|
-
</div>`;
|
|
167
|
+
width: 180,
|
|
168
|
+
progressOptions: {
|
|
169
|
+
min: 0,
|
|
170
|
+
max: 100,
|
|
171
|
+
fill: (value: number) => (value >= 80 ? '#22c55e' : value >= 60 ? '#eab308' : '#ef4444'),
|
|
172
|
+
showLabel: true,
|
|
141
173
|
},
|
|
142
174
|
},
|
|
143
175
|
],
|
|
144
176
|
rowData: generateStaticData(50),
|
|
145
|
-
height: '
|
|
177
|
+
height: 'calc(100vh - 60px)',
|
|
146
178
|
width: '100%',
|
|
147
179
|
theme: themeQuartz,
|
|
148
180
|
},
|
|
149
181
|
parameters: {
|
|
150
182
|
docs: {
|
|
151
183
|
description: {
|
|
152
|
-
story:
|
|
184
|
+
story:
|
|
185
|
+
'Built-in progress bar cell renderer with traffic-light color coding (green ≥ 80, yellow ≥ 60, red < 60).',
|
|
153
186
|
},
|
|
154
187
|
},
|
|
155
188
|
},
|
|
@@ -165,29 +198,86 @@ export const StatusBadge: Story = {
|
|
|
165
198
|
field: 'status',
|
|
166
199
|
headerName: 'Status',
|
|
167
200
|
width: 120,
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
}
|
|
176
|
-
const { bg, text } = colors[status] || { bg: '#f3f4f6', text: '#6b7280' };
|
|
177
|
-
return `<span style="padding: 4px 12px; background: ${bg}; color: ${text}; border-radius: 9999px; font-size: 12px; font-weight: 500;">${status}</span>`;
|
|
201
|
+
badgeOptions: {
|
|
202
|
+
colorMap: {
|
|
203
|
+
Active: { fill: '#dcfce7', text: '#16a34a' },
|
|
204
|
+
'On Leave': { fill: '#fef3c7', text: '#d97706' },
|
|
205
|
+
Remote: { fill: '#dbeafe', text: '#2563eb' },
|
|
206
|
+
Travel: { fill: '#f3e8ff', text: '#9333ea' },
|
|
207
|
+
},
|
|
208
|
+
defaultColors: { fill: '#f3f4f6', text: '#6b7280' },
|
|
178
209
|
},
|
|
179
210
|
},
|
|
180
211
|
{ field: 'salary', headerName: 'Salary', width: 120 },
|
|
181
212
|
],
|
|
182
213
|
rowData: generateStaticData(50),
|
|
183
|
-
height: '
|
|
214
|
+
height: 'calc(100vh - 60px)',
|
|
184
215
|
width: '100%',
|
|
185
216
|
theme: themeQuartz,
|
|
186
217
|
},
|
|
187
218
|
parameters: {
|
|
188
219
|
docs: {
|
|
189
220
|
description: {
|
|
190
|
-
story:
|
|
221
|
+
story:
|
|
222
|
+
'Built-in badge cell renderer with per-value color mapping (green = Active, yellow = On Leave, blue = Remote, purple = Travel).',
|
|
223
|
+
},
|
|
224
|
+
},
|
|
225
|
+
},
|
|
226
|
+
};
|
|
227
|
+
|
|
228
|
+
export const ButtonCell: Story = {
|
|
229
|
+
args: {
|
|
230
|
+
columnDefs: [
|
|
231
|
+
{ field: 'id', headerName: 'ID', width: 80 },
|
|
232
|
+
{ field: 'name', headerName: 'Name', width: 200 },
|
|
233
|
+
{ field: 'department', headerName: 'Department', width: 180 },
|
|
234
|
+
{
|
|
235
|
+
field: 'status',
|
|
236
|
+
headerName: 'Action',
|
|
237
|
+
width: 140,
|
|
238
|
+
buttonOptions: {
|
|
239
|
+
label: 'View Details',
|
|
240
|
+
variant: 'primary',
|
|
241
|
+
onClick: (params: any) => {
|
|
242
|
+
alert(`Clicked row ${params.node.rowIndex}: ${params.data.name}`);
|
|
243
|
+
},
|
|
244
|
+
},
|
|
245
|
+
},
|
|
246
|
+
{
|
|
247
|
+
field: 'status',
|
|
248
|
+
headerName: 'Delete',
|
|
249
|
+
width: 120,
|
|
250
|
+
buttonOptions: {
|
|
251
|
+
label: 'Remove',
|
|
252
|
+
variant: 'danger',
|
|
253
|
+
onClick: (params: any) => {
|
|
254
|
+
alert(`Delete ${params.data.name}?`);
|
|
255
|
+
},
|
|
256
|
+
},
|
|
257
|
+
},
|
|
258
|
+
{
|
|
259
|
+
field: 'status',
|
|
260
|
+
headerName: 'Export',
|
|
261
|
+
width: 120,
|
|
262
|
+
buttonOptions: {
|
|
263
|
+
label: 'Export',
|
|
264
|
+
variant: 'secondary',
|
|
265
|
+
onClick: (params: any) => {
|
|
266
|
+
alert(`Export ${params.data.name}`);
|
|
267
|
+
},
|
|
268
|
+
},
|
|
269
|
+
},
|
|
270
|
+
],
|
|
271
|
+
rowData: generateStaticData(50),
|
|
272
|
+
height: 'calc(100vh - 60px)',
|
|
273
|
+
width: '100%',
|
|
274
|
+
theme: themeQuartz,
|
|
275
|
+
},
|
|
276
|
+
parameters: {
|
|
277
|
+
docs: {
|
|
278
|
+
description: {
|
|
279
|
+
story:
|
|
280
|
+
'Built-in button cell renderer with `primary`, `danger`, and `secondary` variants. `onClick` receives AG Grid-compatible params: `{ value, data, node, api, colDef, event }`.',
|
|
191
281
|
},
|
|
192
282
|
},
|
|
193
283
|
},
|
|
@@ -207,7 +297,7 @@ export const CurrencyFormatter: Story = {
|
|
|
207
297
|
},
|
|
208
298
|
],
|
|
209
299
|
rowData: generateStaticData(50),
|
|
210
|
-
height: '
|
|
300
|
+
height: 'calc(100vh - 60px)',
|
|
211
301
|
width: '100%',
|
|
212
302
|
theme: themeQuartz,
|
|
213
303
|
},
|
|
@@ -219,3 +309,87 @@ export const CurrencyFormatter: Story = {
|
|
|
219
309
|
},
|
|
220
310
|
},
|
|
221
311
|
};
|
|
312
|
+
|
|
313
|
+
export const CheckboxRenderer: Story = {
|
|
314
|
+
args: {
|
|
315
|
+
columnDefs: [
|
|
316
|
+
{ field: 'id', headerName: 'ID', width: 80 },
|
|
317
|
+
{ field: 'name', headerName: 'Name', width: 200 },
|
|
318
|
+
{
|
|
319
|
+
field: 'performance',
|
|
320
|
+
headerName: 'High Perf?',
|
|
321
|
+
width: 120,
|
|
322
|
+
cellRenderer: 'checkbox',
|
|
323
|
+
// Example: boolean logic for checkbox
|
|
324
|
+
valueGetter: (params: any) => params.data.performance >= 80,
|
|
325
|
+
},
|
|
326
|
+
{
|
|
327
|
+
field: 'status',
|
|
328
|
+
headerName: 'Remote?',
|
|
329
|
+
width: 120,
|
|
330
|
+
cellRenderer: 'checkbox',
|
|
331
|
+
valueGetter: (params: any) => params.data.status === 'Remote',
|
|
332
|
+
},
|
|
333
|
+
],
|
|
334
|
+
rowData: generateStaticData(50),
|
|
335
|
+
height: 'calc(100vh - 60px)',
|
|
336
|
+
width: '100%',
|
|
337
|
+
theme: themeQuartz,
|
|
338
|
+
},
|
|
339
|
+
parameters: {
|
|
340
|
+
docs: {
|
|
341
|
+
description: {
|
|
342
|
+
story:
|
|
343
|
+
'Dedicated **checkbox cell renderer**. Renders a boolean value as a centered checkbox. ' +
|
|
344
|
+
'Can be used with `valueGetter` to derive boolean state from complex data.',
|
|
345
|
+
},
|
|
346
|
+
},
|
|
347
|
+
},
|
|
348
|
+
};
|
|
349
|
+
|
|
350
|
+
export const RatingRenderer: Story = {
|
|
351
|
+
args: {
|
|
352
|
+
columnDefs: [
|
|
353
|
+
{ field: 'id', headerName: 'ID', width: 80 },
|
|
354
|
+
{ field: 'name', headerName: 'Name', width: 200 },
|
|
355
|
+
{
|
|
356
|
+
field: 'performance',
|
|
357
|
+
headerName: 'Performance',
|
|
358
|
+
width: 150,
|
|
359
|
+
cellRenderer: 'rating',
|
|
360
|
+
// Scale 60-100 to 0-5 stars
|
|
361
|
+
valueGetter: (params: any) => (params.data.performance - 60) / 8,
|
|
362
|
+
ratingOptions: {
|
|
363
|
+
color: '#ffb400',
|
|
364
|
+
size: 16,
|
|
365
|
+
},
|
|
366
|
+
},
|
|
367
|
+
{
|
|
368
|
+
field: 'performance',
|
|
369
|
+
headerName: 'Stars (Small)',
|
|
370
|
+
width: 120,
|
|
371
|
+
cellRenderer: 'rating',
|
|
372
|
+
valueGetter: (params: any) => (params.data.performance - 60) / 8,
|
|
373
|
+
ratingOptions: {
|
|
374
|
+
color: '#3b82f6',
|
|
375
|
+
size: 10,
|
|
376
|
+
max: 5,
|
|
377
|
+
},
|
|
378
|
+
},
|
|
379
|
+
],
|
|
380
|
+
rowData: generateStaticData(50),
|
|
381
|
+
height: 'calc(100vh - 60px)',
|
|
382
|
+
width: '100%',
|
|
383
|
+
theme: themeQuartz,
|
|
384
|
+
},
|
|
385
|
+
parameters: {
|
|
386
|
+
docs: {
|
|
387
|
+
description: {
|
|
388
|
+
story:
|
|
389
|
+
'**Rating cell renderer** using SVG-style star shapes on Canvas. ' +
|
|
390
|
+
'Supports custom colors, sizes, and max star count. ' +
|
|
391
|
+
'Great for visualising scores or feedback.',
|
|
392
|
+
},
|
|
393
|
+
},
|
|
394
|
+
},
|
|
395
|
+
};
|
|
@@ -2,6 +2,14 @@ import { BrowserModule } from '@angular/platform-browser';
|
|
|
2
2
|
import type { Meta, StoryObj } from '@storybook/angular';
|
|
3
3
|
import { moduleMetadata } from '@storybook/angular';
|
|
4
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';
|
|
5
13
|
|
|
6
14
|
interface Employee {
|
|
7
15
|
id: number;
|
|
@@ -30,9 +38,9 @@ export default meta;
|
|
|
30
38
|
type Story = StoryObj<ArgentGridComponent<Employee>>;
|
|
31
39
|
|
|
32
40
|
function generateStaticData(count: number): Employee[] {
|
|
33
|
-
const departments =
|
|
34
|
-
const roles =
|
|
35
|
-
const locations =
|
|
41
|
+
const departments = STORY_DEPARTMENTS;
|
|
42
|
+
const roles = STORY_ROLES;
|
|
43
|
+
const locations = STORY_LOCATIONS;
|
|
36
44
|
|
|
37
45
|
return Array.from({ length: count }, (_, i) => ({
|
|
38
46
|
id: i + 1,
|
|
@@ -64,6 +72,7 @@ export const TextFilter: Story = {
|
|
|
64
72
|
filter: 'text',
|
|
65
73
|
floatingFilter: true,
|
|
66
74
|
headerComponentParams: { filterIcon: '🔤' },
|
|
75
|
+
valueFormatter: departmentValueFormatter,
|
|
67
76
|
},
|
|
68
77
|
{
|
|
69
78
|
field: 'role',
|
|
@@ -72,12 +81,18 @@ export const TextFilter: Story = {
|
|
|
72
81
|
filter: 'text',
|
|
73
82
|
floatingFilter: true,
|
|
74
83
|
headerComponentParams: { filterIcon: '🔤' },
|
|
84
|
+
valueFormatter: roleValueFormatter,
|
|
75
85
|
},
|
|
76
86
|
{ field: 'salary', headerName: 'Salary', width: 120 },
|
|
77
|
-
{
|
|
87
|
+
{
|
|
88
|
+
field: 'location',
|
|
89
|
+
headerName: 'Location',
|
|
90
|
+
width: 150,
|
|
91
|
+
valueFormatter: locationValueFormatter,
|
|
92
|
+
},
|
|
78
93
|
],
|
|
79
94
|
rowData: generateStaticData(50),
|
|
80
|
-
height: '
|
|
95
|
+
height: 'calc(100vh - 60px)',
|
|
81
96
|
width: '100%',
|
|
82
97
|
theme: themeQuartz,
|
|
83
98
|
},
|
|
@@ -96,14 +111,19 @@ export const NumberFilter: Story = {
|
|
|
96
111
|
columnDefs: [
|
|
97
112
|
{
|
|
98
113
|
field: 'id',
|
|
99
|
-
headerName: 'ID
|
|
114
|
+
headerName: 'ID',
|
|
100
115
|
width: 80,
|
|
101
116
|
filter: 'number',
|
|
102
117
|
floatingFilter: true,
|
|
103
118
|
headerComponentParams: { filterIcon: '🔢' },
|
|
104
119
|
},
|
|
105
120
|
{ field: 'name', headerName: 'Name', width: 200 },
|
|
106
|
-
{
|
|
121
|
+
{
|
|
122
|
+
field: 'department',
|
|
123
|
+
headerName: 'Department',
|
|
124
|
+
width: 180,
|
|
125
|
+
valueFormatter: departmentValueFormatter,
|
|
126
|
+
},
|
|
107
127
|
{
|
|
108
128
|
field: 'salary',
|
|
109
129
|
headerName: 'Salary 🔢',
|
|
@@ -112,10 +132,15 @@ export const NumberFilter: Story = {
|
|
|
112
132
|
floatingFilter: true,
|
|
113
133
|
headerComponentParams: { filterIcon: '🔢' },
|
|
114
134
|
},
|
|
115
|
-
{
|
|
135
|
+
{
|
|
136
|
+
field: 'location',
|
|
137
|
+
headerName: 'Location',
|
|
138
|
+
width: 150,
|
|
139
|
+
valueFormatter: locationValueFormatter,
|
|
140
|
+
},
|
|
116
141
|
],
|
|
117
142
|
rowData: generateStaticData(50),
|
|
118
|
-
height: '
|
|
143
|
+
height: 'calc(100vh - 60px)',
|
|
119
144
|
width: '100%',
|
|
120
145
|
theme: themeQuartz,
|
|
121
146
|
},
|
|
@@ -141,8 +166,9 @@ export const SetFilter: Story = {
|
|
|
141
166
|
filter: 'set',
|
|
142
167
|
floatingFilter: true,
|
|
143
168
|
headerComponentParams: { filterIcon: '☑️' },
|
|
169
|
+
valueFormatter: departmentValueFormatter,
|
|
144
170
|
},
|
|
145
|
-
{ field: 'role', headerName: 'Role', width: 250 },
|
|
171
|
+
{ field: 'role', headerName: 'Role', width: 250, valueFormatter: roleValueFormatter },
|
|
146
172
|
{ field: 'salary', headerName: 'Salary', width: 120 },
|
|
147
173
|
{
|
|
148
174
|
field: 'location',
|
|
@@ -151,10 +177,11 @@ export const SetFilter: Story = {
|
|
|
151
177
|
filter: 'set',
|
|
152
178
|
floatingFilter: true,
|
|
153
179
|
headerComponentParams: { filterIcon: '☑️' },
|
|
180
|
+
valueFormatter: locationValueFormatter,
|
|
154
181
|
},
|
|
155
182
|
],
|
|
156
183
|
rowData: generateStaticData(50),
|
|
157
|
-
height: '
|
|
184
|
+
height: 'calc(100vh - 60px)',
|
|
158
185
|
width: '100%',
|
|
159
186
|
theme: themeQuartz,
|
|
160
187
|
},
|
|
@@ -173,12 +200,24 @@ export const HiddenFloatingFilters: Story = {
|
|
|
173
200
|
columnDefs: [
|
|
174
201
|
{ field: 'id', headerName: 'ID', width: 80 },
|
|
175
202
|
{ field: 'name', headerName: 'Name', width: 200, filter: 'text' },
|
|
176
|
-
{
|
|
177
|
-
|
|
203
|
+
{
|
|
204
|
+
field: 'department',
|
|
205
|
+
headerName: 'Department',
|
|
206
|
+
width: 180,
|
|
207
|
+
filter: 'text',
|
|
208
|
+
valueFormatter: departmentValueFormatter,
|
|
209
|
+
},
|
|
210
|
+
{
|
|
211
|
+
field: 'role',
|
|
212
|
+
headerName: 'Role',
|
|
213
|
+
width: 250,
|
|
214
|
+
filter: 'text',
|
|
215
|
+
valueFormatter: roleValueFormatter,
|
|
216
|
+
},
|
|
178
217
|
{ field: 'salary', headerName: 'Salary', width: 120, filter: 'number' },
|
|
179
218
|
],
|
|
180
219
|
rowData: generateStaticData(50),
|
|
181
|
-
height: '
|
|
220
|
+
height: 'calc(100vh - 60px)',
|
|
182
221
|
width: '100%',
|
|
183
222
|
theme: themeQuartz,
|
|
184
223
|
},
|
|
@@ -197,7 +236,7 @@ export const AllFilterTypes: Story = {
|
|
|
197
236
|
columnDefs: [
|
|
198
237
|
{
|
|
199
238
|
field: 'id',
|
|
200
|
-
headerName: 'ID
|
|
239
|
+
headerName: 'ID',
|
|
201
240
|
width: 80,
|
|
202
241
|
filter: 'number',
|
|
203
242
|
floatingFilter: true,
|
|
@@ -218,6 +257,7 @@ export const AllFilterTypes: Story = {
|
|
|
218
257
|
filter: 'set',
|
|
219
258
|
floatingFilter: true,
|
|
220
259
|
headerComponentParams: { filterIcon: '☑️' },
|
|
260
|
+
valueFormatter: departmentValueFormatter,
|
|
221
261
|
},
|
|
222
262
|
{
|
|
223
263
|
field: 'startDate',
|
|
@@ -237,7 +277,7 @@ export const AllFilterTypes: Story = {
|
|
|
237
277
|
},
|
|
238
278
|
],
|
|
239
279
|
rowData: generateStaticData(50),
|
|
240
|
-
height: '
|
|
280
|
+
height: 'calc(100vh - 60px)',
|
|
241
281
|
width: '100%',
|
|
242
282
|
theme: themeQuartz,
|
|
243
283
|
},
|
|
@@ -2,6 +2,14 @@ import { BrowserModule } from '@angular/platform-browser';
|
|
|
2
2
|
import type { Meta, StoryObj } from '@storybook/angular';
|
|
3
3
|
import { moduleMetadata } from '@storybook/angular';
|
|
4
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';
|
|
5
13
|
|
|
6
14
|
interface Employee {
|
|
7
15
|
id: number;
|
|
@@ -29,9 +37,9 @@ export default meta;
|
|
|
29
37
|
type Story = StoryObj<ArgentGridComponent<Employee>>;
|
|
30
38
|
|
|
31
39
|
function generateStaticData(count: number): Employee[] {
|
|
32
|
-
const departments =
|
|
33
|
-
const roles =
|
|
34
|
-
const locations =
|
|
40
|
+
const departments = STORY_DEPARTMENTS;
|
|
41
|
+
const roles = STORY_ROLES;
|
|
42
|
+
const locations = STORY_LOCATIONS;
|
|
35
43
|
|
|
36
44
|
return Array.from({ length: count }, (_, i) => ({
|
|
37
45
|
id: i + 1,
|
|
@@ -54,13 +62,19 @@ export const RowGrouping: Story = {
|
|
|
54
62
|
width: 180,
|
|
55
63
|
rowGroup: true,
|
|
56
64
|
headerComponentParams: { groupIcon: '📁' },
|
|
65
|
+
valueFormatter: departmentValueFormatter,
|
|
57
66
|
},
|
|
58
|
-
{ field: 'role', headerName: 'Role', width: 250 },
|
|
67
|
+
{ field: 'role', headerName: 'Role', width: 250, valueFormatter: roleValueFormatter },
|
|
59
68
|
{ field: 'salary', headerName: 'Salary', width: 120 },
|
|
60
|
-
{
|
|
69
|
+
{
|
|
70
|
+
field: 'location',
|
|
71
|
+
headerName: 'Location',
|
|
72
|
+
width: 150,
|
|
73
|
+
valueFormatter: locationValueFormatter,
|
|
74
|
+
},
|
|
61
75
|
],
|
|
62
76
|
rowData: generateStaticData(100),
|
|
63
|
-
height: '
|
|
77
|
+
height: 'calc(100vh - 60px)',
|
|
64
78
|
width: '100%',
|
|
65
79
|
theme: themeQuartz,
|
|
66
80
|
gridOptions: {
|
|
@@ -93,6 +107,7 @@ export const MultiLevelGrouping: Story = {
|
|
|
93
107
|
width: 150,
|
|
94
108
|
rowGroup: true,
|
|
95
109
|
headerComponentParams: { groupIcon: '📁' },
|
|
110
|
+
valueFormatter: departmentValueFormatter,
|
|
96
111
|
},
|
|
97
112
|
{
|
|
98
113
|
field: 'location',
|
|
@@ -100,12 +115,13 @@ export const MultiLevelGrouping: Story = {
|
|
|
100
115
|
width: 150,
|
|
101
116
|
rowGroup: true,
|
|
102
117
|
headerComponentParams: { groupIcon: '📁' },
|
|
118
|
+
valueFormatter: locationValueFormatter,
|
|
103
119
|
},
|
|
104
|
-
{ field: 'role', headerName: 'Role', width: 250 },
|
|
120
|
+
{ field: 'role', headerName: 'Role', width: 250, valueFormatter: roleValueFormatter },
|
|
105
121
|
{ field: 'salary', headerName: 'Salary', width: 120 },
|
|
106
122
|
],
|
|
107
123
|
rowData: generateStaticData(100),
|
|
108
|
-
height: '
|
|
124
|
+
height: 'calc(100vh - 60px)',
|
|
109
125
|
width: '100%',
|
|
110
126
|
theme: themeQuartz,
|
|
111
127
|
gridOptions: {
|
|
@@ -138,18 +154,24 @@ export const GroupingWithAggregation: Story = {
|
|
|
138
154
|
width: 180,
|
|
139
155
|
rowGroup: true,
|
|
140
156
|
headerComponentParams: { groupIcon: '📁' },
|
|
157
|
+
valueFormatter: departmentValueFormatter,
|
|
141
158
|
},
|
|
142
|
-
{ field: 'role', headerName: 'Role', width: 250 },
|
|
159
|
+
{ field: 'role', headerName: 'Role', width: 250, valueFormatter: roleValueFormatter },
|
|
143
160
|
{
|
|
144
161
|
field: 'salary',
|
|
145
162
|
headerName: 'Salary 💰',
|
|
146
163
|
width: 120,
|
|
147
164
|
aggFunc: 'sum', // Show sum in group rows
|
|
148
165
|
},
|
|
149
|
-
{
|
|
166
|
+
{
|
|
167
|
+
field: 'location',
|
|
168
|
+
headerName: 'Location',
|
|
169
|
+
width: 150,
|
|
170
|
+
valueFormatter: locationValueFormatter,
|
|
171
|
+
},
|
|
150
172
|
],
|
|
151
173
|
rowData: generateStaticData(100),
|
|
152
|
-
height: '
|
|
174
|
+
height: 'calc(100vh - 60px)',
|
|
153
175
|
width: '100%',
|
|
154
176
|
theme: themeQuartz,
|
|
155
177
|
gridOptions: {
|
|
@@ -182,6 +204,7 @@ export const DragAndDropGrouping: Story = {
|
|
|
182
204
|
width: 180,
|
|
183
205
|
rowGroup: false, // Not pre-grouped - user can drag
|
|
184
206
|
headerComponentParams: { draggable: true },
|
|
207
|
+
valueFormatter: departmentValueFormatter,
|
|
185
208
|
},
|
|
186
209
|
{
|
|
187
210
|
field: 'location',
|
|
@@ -189,12 +212,13 @@ export const DragAndDropGrouping: Story = {
|
|
|
189
212
|
width: 150,
|
|
190
213
|
rowGroup: false,
|
|
191
214
|
headerComponentParams: { draggable: true },
|
|
215
|
+
valueFormatter: locationValueFormatter,
|
|
192
216
|
},
|
|
193
|
-
{ field: 'role', headerName: 'Role', width: 250 },
|
|
217
|
+
{ field: 'role', headerName: 'Role', width: 250, valueFormatter: roleValueFormatter },
|
|
194
218
|
{ field: 'salary', headerName: 'Salary', width: 120 },
|
|
195
219
|
],
|
|
196
220
|
rowData: generateStaticData(100),
|
|
197
|
-
height: '
|
|
221
|
+
height: 'calc(100vh - 60px)',
|
|
198
222
|
width: '100%',
|
|
199
223
|
theme: themeQuartz,
|
|
200
224
|
gridOptions: {
|
|
@@ -215,3 +239,52 @@ export const DragAndDropGrouping: Story = {
|
|
|
215
239
|
},
|
|
216
240
|
},
|
|
217
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
|
+
};
|