@papernote/ui 1.10.19 → 1.10.21
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/dist/components/Alert.d.ts +1 -1
- package/dist/components/Alert.d.ts.map +1 -1
- package/dist/components/Badge.d.ts +1 -1
- package/dist/components/Badge.d.ts.map +1 -1
- package/dist/components/PivotTable.d.ts +47 -0
- package/dist/components/PivotTable.d.ts.map +1 -0
- package/dist/components/StatusBadge.d.ts +1 -1
- package/dist/components/StatusBadge.d.ts.map +1 -1
- package/dist/components/Text.d.ts +2 -1
- package/dist/components/Text.d.ts.map +1 -1
- package/dist/components/index.d.ts +2 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/index.d.ts +53 -6
- package/dist/index.esm.js +271 -37
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +271 -36
- package/dist/index.js.map +1 -1
- package/dist/styles.css +15 -0
- package/package.json +1 -1
- package/src/components/Alert.stories.tsx +20 -7
- package/src/components/Alert.tsx +7 -1
- package/src/components/Badge.stories.tsx +18 -7
- package/src/components/Badge.tsx +3 -1
- package/src/components/PivotTable.stories.tsx +188 -0
- package/src/components/PivotTable.tsx +422 -0
- package/src/components/StatusBadge.tsx +7 -2
- package/src/components/Text.stories.tsx +30 -6
- package/src/components/Text.tsx +5 -3
- package/src/components/index.ts +4 -0
package/dist/styles.css
CHANGED
|
@@ -3782,6 +3782,11 @@ input:checked + .slider:before{
|
|
|
3782
3782
|
background-color: rgb(217 119 6 / var(--tw-bg-opacity, 1));
|
|
3783
3783
|
}
|
|
3784
3784
|
|
|
3785
|
+
.bg-warning-700{
|
|
3786
|
+
--tw-bg-opacity: 1;
|
|
3787
|
+
background-color: rgb(180 83 9 / var(--tw-bg-opacity, 1));
|
|
3788
|
+
}
|
|
3789
|
+
|
|
3785
3790
|
.bg-white{
|
|
3786
3791
|
--tw-bg-opacity: 1;
|
|
3787
3792
|
background-color: rgb(255 255 255 / var(--tw-bg-opacity, 1));
|
|
@@ -4418,6 +4423,11 @@ input:checked + .slider:before{
|
|
|
4418
4423
|
font-style: italic;
|
|
4419
4424
|
}
|
|
4420
4425
|
|
|
4426
|
+
.tabular-nums{
|
|
4427
|
+
--tw-numeric-spacing: tabular-nums;
|
|
4428
|
+
font-variant-numeric: var(--tw-ordinal) var(--tw-slashed-zero) var(--tw-numeric-figure) var(--tw-numeric-spacing) var(--tw-numeric-fraction);
|
|
4429
|
+
}
|
|
4430
|
+
|
|
4421
4431
|
.leading-5{
|
|
4422
4432
|
line-height: 1.25rem;
|
|
4423
4433
|
}
|
|
@@ -5687,6 +5697,11 @@ input:checked + .slider:before{
|
|
|
5687
5697
|
background-color: rgb(180 83 9 / var(--tw-bg-opacity, 1));
|
|
5688
5698
|
}
|
|
5689
5699
|
|
|
5700
|
+
.hover\:bg-warning-800:hover{
|
|
5701
|
+
--tw-bg-opacity: 1;
|
|
5702
|
+
background-color: rgb(146 64 14 / var(--tw-bg-opacity, 1));
|
|
5703
|
+
}
|
|
5704
|
+
|
|
5690
5705
|
.hover\:bg-white:hover{
|
|
5691
5706
|
--tw-bg-opacity: 1;
|
|
5692
5707
|
background-color: rgb(255 255 255 / var(--tw-bg-opacity, 1));
|
package/package.json
CHANGED
|
@@ -13,7 +13,7 @@ const meta = {
|
|
|
13
13
|
Alert banner for displaying important messages with contextual styling and actions.
|
|
14
14
|
|
|
15
15
|
## Features
|
|
16
|
-
- **Variants**: info, success, warning, error with semantic colors
|
|
16
|
+
- **Variants**: info, success, warning, caution, error with semantic colors
|
|
17
17
|
- **Icons**: Automatic variant-specific icons
|
|
18
18
|
- **Title & Message**: Optional title with message content
|
|
19
19
|
- **Dismissible**: Optional close button
|
|
@@ -45,10 +45,10 @@ import { Alert } from 'notebook-ui';
|
|
|
45
45
|
argTypes: {
|
|
46
46
|
variant: {
|
|
47
47
|
control: 'select',
|
|
48
|
-
options: ['info', 'success', 'warning', 'error'],
|
|
48
|
+
options: ['info', 'success', 'warning', 'caution', 'error'],
|
|
49
49
|
description: 'Alert variant with semantic colors and icons',
|
|
50
50
|
table: {
|
|
51
|
-
type: { summary: 'info | success | warning | error' },
|
|
51
|
+
type: { summary: 'info | success | warning | caution | error' },
|
|
52
52
|
defaultValue: { summary: 'info' },
|
|
53
53
|
},
|
|
54
54
|
},
|
|
@@ -114,6 +114,18 @@ export const Warning: Story = {
|
|
|
114
114
|
},
|
|
115
115
|
};
|
|
116
116
|
|
|
117
|
+
/**
|
|
118
|
+
* Caution variant for informational states that need context but aren't alarming.
|
|
119
|
+
* Use for demo/sandbox modes, wash sale notices, or exploratory features.
|
|
120
|
+
*/
|
|
121
|
+
export const Caution: Story = {
|
|
122
|
+
args: {
|
|
123
|
+
variant: 'caution',
|
|
124
|
+
title: 'Demo Mode',
|
|
125
|
+
children: 'You are in demo mode. Changes will not be saved to the database.',
|
|
126
|
+
},
|
|
127
|
+
};
|
|
128
|
+
|
|
117
129
|
export const Error: Story = {
|
|
118
130
|
args: {
|
|
119
131
|
variant: 'error',
|
|
@@ -170,10 +182,11 @@ export const LongMessage: Story = {
|
|
|
170
182
|
export const AllVariants: Story = {
|
|
171
183
|
render: () => (
|
|
172
184
|
<div style={{ display: 'flex', flexDirection: 'column', gap: '1rem' }}>
|
|
173
|
-
<Alert variant="info" title="Information"
|
|
174
|
-
<Alert variant="success" title="Success"
|
|
175
|
-
<Alert variant="warning" title="Warning"
|
|
176
|
-
<Alert variant="
|
|
185
|
+
<Alert variant="info" title="Information">This is an informational message.</Alert>
|
|
186
|
+
<Alert variant="success" title="Success">Operation completed successfully.</Alert>
|
|
187
|
+
<Alert variant="warning" title="Warning">Please review before proceeding.</Alert>
|
|
188
|
+
<Alert variant="caution" title="Demo Mode">You are exploring in sandbox mode.</Alert>
|
|
189
|
+
<Alert variant="error" title="Error">Something went wrong.</Alert>
|
|
177
190
|
</div>
|
|
178
191
|
),
|
|
179
192
|
};
|
package/src/components/Alert.tsx
CHANGED
|
@@ -8,7 +8,7 @@ export interface AlertAction {
|
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
export interface AlertProps {
|
|
11
|
-
variant?: 'success' | 'error' | 'warning' | 'info';
|
|
11
|
+
variant?: 'success' | 'error' | 'warning' | 'caution' | 'info';
|
|
12
12
|
title?: string;
|
|
13
13
|
children: React.ReactNode;
|
|
14
14
|
onClose?: () => void;
|
|
@@ -38,6 +38,10 @@ export default function Alert({
|
|
|
38
38
|
container: 'bg-warning-50 border-warning-200 text-warning-900',
|
|
39
39
|
icon: <AlertTriangle className="h-5 w-5 text-warning-600" />,
|
|
40
40
|
},
|
|
41
|
+
caution: {
|
|
42
|
+
container: 'bg-warning-100 border-warning-200 text-warning-800',
|
|
43
|
+
icon: <Info className="h-5 w-5 text-warning-700" />,
|
|
44
|
+
},
|
|
41
45
|
info: {
|
|
42
46
|
container: 'bg-primary-50 border-primary-200 text-primary-900',
|
|
43
47
|
icon: <Info className="h-5 w-5 text-primary-600" />,
|
|
@@ -54,6 +58,7 @@ export default function Alert({
|
|
|
54
58
|
success: 'bg-success-600 text-white hover:bg-success-700',
|
|
55
59
|
error: 'bg-error-600 text-white hover:bg-error-700',
|
|
56
60
|
warning: 'bg-warning-600 text-white hover:bg-warning-700',
|
|
61
|
+
caution: 'bg-warning-700 text-white hover:bg-warning-800',
|
|
57
62
|
info: 'bg-primary-600 text-white hover:bg-primary-700',
|
|
58
63
|
};
|
|
59
64
|
return `${base} ${variantClasses[variant]}`;
|
|
@@ -64,6 +69,7 @@ export default function Alert({
|
|
|
64
69
|
success: 'bg-white border border-success-300 text-success-700 hover:bg-success-50',
|
|
65
70
|
error: 'bg-white border border-error-300 text-error-700 hover:bg-error-50',
|
|
66
71
|
warning: 'bg-white border border-warning-300 text-warning-700 hover:bg-warning-50',
|
|
72
|
+
caution: 'bg-white border border-warning-300 text-warning-800 hover:bg-warning-50',
|
|
67
73
|
info: 'bg-white border border-primary-300 text-primary-700 hover:bg-primary-50',
|
|
68
74
|
};
|
|
69
75
|
return `${base} ${variantClasses[variant]}`;
|
|
@@ -14,7 +14,7 @@ const meta = {
|
|
|
14
14
|
Badge component for status indicators, labels, and tags with optional icons and removal.
|
|
15
15
|
|
|
16
16
|
## Features
|
|
17
|
-
- **Variants**: success, warning, error, info, neutral with semantic colors
|
|
17
|
+
- **Variants**: success, warning, caution, error, info, neutral with semantic colors
|
|
18
18
|
- **Sizes**: sm, md, lg
|
|
19
19
|
- **Icons**: Display icons alongside text
|
|
20
20
|
- **Removable**: Optional X button for dismissible badges
|
|
@@ -44,10 +44,10 @@ import { Check } from 'lucide-react';
|
|
|
44
44
|
argTypes: {
|
|
45
45
|
variant: {
|
|
46
46
|
control: 'select',
|
|
47
|
-
options: ['success', 'warning', 'error', 'info', 'neutral'],
|
|
47
|
+
options: ['success', 'warning', 'caution', 'error', 'info', 'neutral'],
|
|
48
48
|
description: 'Badge variant with semantic colors',
|
|
49
49
|
table: {
|
|
50
|
-
type: { summary: 'success | warning | error | info | neutral' },
|
|
50
|
+
type: { summary: 'success | warning | caution | error | info | neutral' },
|
|
51
51
|
defaultValue: { summary: 'neutral' },
|
|
52
52
|
},
|
|
53
53
|
},
|
|
@@ -113,6 +113,17 @@ export const Warning: Story = {
|
|
|
113
113
|
},
|
|
114
114
|
};
|
|
115
115
|
|
|
116
|
+
/**
|
|
117
|
+
* Caution variant for informational states that need context but aren't alarming.
|
|
118
|
+
* Use for demo/sandbox modes, wash sale notices, or exploratory features.
|
|
119
|
+
*/
|
|
120
|
+
export const Caution: Story = {
|
|
121
|
+
args: {
|
|
122
|
+
variant: 'caution',
|
|
123
|
+
children: 'Demo Mode',
|
|
124
|
+
},
|
|
125
|
+
};
|
|
126
|
+
|
|
116
127
|
export const Error: Story = {
|
|
117
128
|
args: {
|
|
118
129
|
variant: 'error',
|
|
@@ -199,10 +210,10 @@ export const DotWithText: Story = {
|
|
|
199
210
|
export const AllVariants: Story = {
|
|
200
211
|
render: () => (
|
|
201
212
|
<div style={{ display: 'flex', gap: '0.5rem', flexWrap: 'wrap' }}>
|
|
202
|
-
<Badge variant="
|
|
203
|
-
<Badge variant="primary">Primary</Badge>
|
|
213
|
+
<Badge variant="neutral">Neutral</Badge>
|
|
204
214
|
<Badge variant="success">Success</Badge>
|
|
205
215
|
<Badge variant="warning">Warning</Badge>
|
|
216
|
+
<Badge variant="caution">Caution</Badge>
|
|
206
217
|
<Badge variant="error">Error</Badge>
|
|
207
218
|
<Badge variant="info">Info</Badge>
|
|
208
219
|
</div>
|
|
@@ -224,10 +235,10 @@ export const StatusBadges: Story = {
|
|
|
224
235
|
<div style={{ display: 'flex', gap: '0.5rem', flexWrap: 'wrap' }}>
|
|
225
236
|
<Badge variant="success">Active</Badge>
|
|
226
237
|
<Badge variant="warning">Pending</Badge>
|
|
238
|
+
<Badge variant="caution">Demo</Badge>
|
|
227
239
|
<Badge variant="error">Inactive</Badge>
|
|
228
240
|
<Badge variant="info">Draft</Badge>
|
|
229
|
-
<Badge variant="
|
|
230
|
-
<Badge variant="default">Archived</Badge>
|
|
241
|
+
<Badge variant="neutral">Archived</Badge>
|
|
231
242
|
</div>
|
|
232
243
|
),
|
|
233
244
|
};
|
package/src/components/Badge.tsx
CHANGED
|
@@ -3,7 +3,7 @@ import { X } from 'lucide-react';
|
|
|
3
3
|
|
|
4
4
|
export interface BadgeProps {
|
|
5
5
|
children?: React.ReactNode;
|
|
6
|
-
variant?: 'success' | 'warning' | 'error' | 'info' | 'neutral';
|
|
6
|
+
variant?: 'success' | 'warning' | 'error' | 'caution' | 'info' | 'neutral';
|
|
7
7
|
size?: 'sm' | 'md' | 'lg';
|
|
8
8
|
icon?: React.ReactNode;
|
|
9
9
|
onRemove?: () => void;
|
|
@@ -37,6 +37,7 @@ export default function Badge({
|
|
|
37
37
|
success: 'bg-success-50 text-success-700 border-success-200',
|
|
38
38
|
warning: 'bg-warning-50 text-warning-700 border-warning-200',
|
|
39
39
|
error: 'bg-error-50 text-error-700 border-error-200',
|
|
40
|
+
caution: 'bg-warning-100 text-warning-800 border-warning-200',
|
|
40
41
|
info: 'bg-primary-50 text-primary-700 border-primary-200',
|
|
41
42
|
neutral: 'bg-paper-100 text-ink-700 border-paper-300',
|
|
42
43
|
};
|
|
@@ -45,6 +46,7 @@ export default function Badge({
|
|
|
45
46
|
success: 'bg-success-500',
|
|
46
47
|
warning: 'bg-warning-500',
|
|
47
48
|
error: 'bg-error-500',
|
|
49
|
+
caution: 'bg-warning-700',
|
|
48
50
|
info: 'bg-primary-500',
|
|
49
51
|
neutral: 'bg-ink-400',
|
|
50
52
|
};
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
2
|
+
import { PivotTable } from './PivotTable';
|
|
3
|
+
|
|
4
|
+
const meta: Meta<typeof PivotTable> = {
|
|
5
|
+
title: 'Data Display/PivotTable',
|
|
6
|
+
component: PivotTable,
|
|
7
|
+
parameters: {
|
|
8
|
+
layout: 'padded',
|
|
9
|
+
docs: {
|
|
10
|
+
description: {
|
|
11
|
+
component:
|
|
12
|
+
'PivotTable transforms flat data into a cross-tabulation table with row labels, column headers, and aggregated values. Ideal for financial reports, sales summaries, and time-based data analysis.',
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
tags: ['autodocs'],
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export default meta;
|
|
20
|
+
type Story = StoryObj<typeof PivotTable>;
|
|
21
|
+
|
|
22
|
+
// Sample commission data by principal and month
|
|
23
|
+
const commissionData = [
|
|
24
|
+
{ PrincipalName: 'Allwire', CommissionFiscalMonth: 1, MonthlyCommission: 1250.5 },
|
|
25
|
+
{ PrincipalName: 'Allwire', CommissionFiscalMonth: 2, MonthlyCommission: 1875.25 },
|
|
26
|
+
{ PrincipalName: 'Allwire', CommissionFiscalMonth: 3, MonthlyCommission: 2100.0 },
|
|
27
|
+
{ PrincipalName: 'Allwire', CommissionFiscalMonth: 4, MonthlyCommission: 1950.75 },
|
|
28
|
+
{ PrincipalName: 'AMSC', CommissionFiscalMonth: 1, MonthlyCommission: 3200.0 },
|
|
29
|
+
{ PrincipalName: 'AMSC', CommissionFiscalMonth: 2, MonthlyCommission: 2850.5 },
|
|
30
|
+
{ PrincipalName: 'AMSC', CommissionFiscalMonth: 3, MonthlyCommission: 3100.25 },
|
|
31
|
+
{ PrincipalName: 'AMSC', CommissionFiscalMonth: 4, MonthlyCommission: 3450.0 },
|
|
32
|
+
{ PrincipalName: 'Buckingham', CommissionFiscalMonth: 1, MonthlyCommission: 850.0 },
|
|
33
|
+
{ PrincipalName: 'Buckingham', CommissionFiscalMonth: 2, MonthlyCommission: 925.75 },
|
|
34
|
+
{ PrincipalName: 'Buckingham', CommissionFiscalMonth: 3, MonthlyCommission: 1100.5 },
|
|
35
|
+
{ PrincipalName: 'Buckingham', CommissionFiscalMonth: 4, MonthlyCommission: 975.25 },
|
|
36
|
+
{ PrincipalName: 'Delta Corp', CommissionFiscalMonth: 1, MonthlyCommission: 5500.0 },
|
|
37
|
+
{ PrincipalName: 'Delta Corp', CommissionFiscalMonth: 2, MonthlyCommission: 4800.25 },
|
|
38
|
+
{ PrincipalName: 'Delta Corp', CommissionFiscalMonth: 3, MonthlyCommission: 5200.5 },
|
|
39
|
+
{ PrincipalName: 'Delta Corp', CommissionFiscalMonth: 4, MonthlyCommission: 5750.75 },
|
|
40
|
+
];
|
|
41
|
+
|
|
42
|
+
const monthLabels: Record<number, string> = {
|
|
43
|
+
1: 'January',
|
|
44
|
+
2: 'February',
|
|
45
|
+
3: 'March',
|
|
46
|
+
4: 'April',
|
|
47
|
+
5: 'May',
|
|
48
|
+
6: 'June',
|
|
49
|
+
7: 'July',
|
|
50
|
+
8: 'August',
|
|
51
|
+
9: 'September',
|
|
52
|
+
10: 'October',
|
|
53
|
+
11: 'November',
|
|
54
|
+
12: 'December',
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Default pivot table showing commission by principal and month
|
|
59
|
+
*/
|
|
60
|
+
export const Default: Story = {
|
|
61
|
+
args: {
|
|
62
|
+
data: commissionData,
|
|
63
|
+
rowField: 'PrincipalName',
|
|
64
|
+
columnField: 'CommissionFiscalMonth',
|
|
65
|
+
valueField: 'MonthlyCommission',
|
|
66
|
+
columnLabels: monthLabels,
|
|
67
|
+
rowLabel: 'Principal',
|
|
68
|
+
showRowTotals: true,
|
|
69
|
+
showRowAverages: true,
|
|
70
|
+
showColumnTotals: true,
|
|
71
|
+
},
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Without averages column
|
|
76
|
+
*/
|
|
77
|
+
export const WithoutAverages: Story = {
|
|
78
|
+
args: {
|
|
79
|
+
...Default.args,
|
|
80
|
+
showRowAverages: false,
|
|
81
|
+
},
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Without totals row
|
|
86
|
+
*/
|
|
87
|
+
export const WithoutColumnTotals: Story = {
|
|
88
|
+
args: {
|
|
89
|
+
...Default.args,
|
|
90
|
+
showColumnTotals: false,
|
|
91
|
+
},
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Minimal - just the pivot data
|
|
96
|
+
*/
|
|
97
|
+
export const Minimal: Story = {
|
|
98
|
+
args: {
|
|
99
|
+
...Default.args,
|
|
100
|
+
showRowTotals: false,
|
|
101
|
+
showRowAverages: false,
|
|
102
|
+
showColumnTotals: false,
|
|
103
|
+
},
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
// Sales data by region and quarter
|
|
107
|
+
const salesData = [
|
|
108
|
+
{ Region: 'North', Quarter: 'Q1', Sales: 125000 },
|
|
109
|
+
{ Region: 'North', Quarter: 'Q2', Sales: 145000 },
|
|
110
|
+
{ Region: 'North', Quarter: 'Q3', Sales: 132000 },
|
|
111
|
+
{ Region: 'North', Quarter: 'Q4', Sales: 178000 },
|
|
112
|
+
{ Region: 'South', Quarter: 'Q1', Sales: 98000 },
|
|
113
|
+
{ Region: 'South', Quarter: 'Q2', Sales: 112000 },
|
|
114
|
+
{ Region: 'South', Quarter: 'Q3', Sales: 105000 },
|
|
115
|
+
{ Region: 'South', Quarter: 'Q4', Sales: 142000 },
|
|
116
|
+
{ Region: 'East', Quarter: 'Q1', Sales: 210000 },
|
|
117
|
+
{ Region: 'East', Quarter: 'Q2', Sales: 195000 },
|
|
118
|
+
{ Region: 'East', Quarter: 'Q3', Sales: 225000 },
|
|
119
|
+
{ Region: 'East', Quarter: 'Q4', Sales: 248000 },
|
|
120
|
+
{ Region: 'West', Quarter: 'Q1', Sales: 175000 },
|
|
121
|
+
{ Region: 'West', Quarter: 'Q2', Sales: 168000 },
|
|
122
|
+
{ Region: 'West', Quarter: 'Q3', Sales: 192000 },
|
|
123
|
+
{ Region: 'West', Quarter: 'Q4', Sales: 215000 },
|
|
124
|
+
];
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Sales by region and quarter
|
|
128
|
+
*/
|
|
129
|
+
export const SalesByRegion: Story = {
|
|
130
|
+
args: {
|
|
131
|
+
data: salesData,
|
|
132
|
+
rowField: 'Region',
|
|
133
|
+
columnField: 'Quarter',
|
|
134
|
+
valueField: 'Sales',
|
|
135
|
+
rowLabel: 'Region',
|
|
136
|
+
showRowTotals: true,
|
|
137
|
+
showRowAverages: true,
|
|
138
|
+
showColumnTotals: true,
|
|
139
|
+
},
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Custom number formatter (no currency symbol)
|
|
144
|
+
*/
|
|
145
|
+
export const CustomFormatter: Story = {
|
|
146
|
+
args: {
|
|
147
|
+
...Default.args,
|
|
148
|
+
formatValue: (value: number | null) => {
|
|
149
|
+
if (value === null) return '-';
|
|
150
|
+
return new Intl.NumberFormat('en-US', {
|
|
151
|
+
minimumFractionDigits: 0,
|
|
152
|
+
maximumFractionDigits: 0,
|
|
153
|
+
}).format(value);
|
|
154
|
+
},
|
|
155
|
+
},
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
// Sparse data with missing values
|
|
159
|
+
const sparseData = [
|
|
160
|
+
{ Product: 'Widget A', Month: 1, Units: 150 },
|
|
161
|
+
{ Product: 'Widget A', Month: 3, Units: 200 },
|
|
162
|
+
{ Product: 'Widget A', Month: 4, Units: 175 },
|
|
163
|
+
{ Product: 'Widget B', Month: 1, Units: 300 },
|
|
164
|
+
{ Product: 'Widget B', Month: 2, Units: 280 },
|
|
165
|
+
{ Product: 'Widget B', Month: 4, Units: 320 },
|
|
166
|
+
{ Product: 'Widget C', Month: 2, Units: 90 },
|
|
167
|
+
{ Product: 'Widget C', Month: 3, Units: 110 },
|
|
168
|
+
];
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Sparse data with empty cells
|
|
172
|
+
*/
|
|
173
|
+
export const SparseData: Story = {
|
|
174
|
+
args: {
|
|
175
|
+
data: sparseData,
|
|
176
|
+
rowField: 'Product',
|
|
177
|
+
columnField: 'Month',
|
|
178
|
+
valueField: 'Units',
|
|
179
|
+
columnLabels: monthLabels,
|
|
180
|
+
rowLabel: 'Product',
|
|
181
|
+
showRowTotals: true,
|
|
182
|
+
showColumnTotals: true,
|
|
183
|
+
formatValue: (value: number | null) => {
|
|
184
|
+
if (value === null) return '-';
|
|
185
|
+
return value.toLocaleString();
|
|
186
|
+
},
|
|
187
|
+
},
|
|
188
|
+
};
|