@papernote/ui 1.1.0 → 1.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.
- package/LICENSE +21 -21
- package/README.md +455 -455
- package/dist/components/CurrencyInput.d.ts +52 -0
- package/dist/components/CurrencyInput.d.ts.map +1 -0
- package/dist/components/DataTable.d.ts +3 -1
- package/dist/components/DataTable.d.ts.map +1 -1
- package/dist/components/Modal.d.ts.map +1 -1
- package/dist/components/Page.d.ts +2 -0
- package/dist/components/Page.d.ts.map +1 -1
- package/dist/components/PageLayout.d.ts +5 -1
- package/dist/components/PageLayout.d.ts.map +1 -1
- package/dist/components/index.d.ts +4 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/index.d.ts +204 -4
- package/dist/index.esm.js +415 -88
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +413 -82
- package/dist/index.js.map +1 -1
- package/dist/styles.css +2877 -2675
- package/dist/utils/excelExport.d.ts +143 -0
- package/dist/utils/excelExport.d.ts.map +1 -0
- package/dist/utils/index.d.ts +2 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/components/AdminModal.css +49 -49
- package/src/components/CurrencyInput.stories.tsx +290 -0
- package/src/components/CurrencyInput.tsx +193 -0
- package/src/components/DataTable.tsx +78 -14
- package/src/components/Modal.stories.tsx +64 -0
- package/src/components/Modal.tsx +15 -2
- package/src/components/Page.stories.tsx +76 -0
- package/src/components/Page.tsx +35 -3
- package/src/components/PageLayout.stories.tsx +75 -0
- package/src/components/PageLayout.tsx +28 -9
- package/src/components/RoleManager.css +10 -10
- package/src/components/Spreadsheet.css +216 -216
- package/src/components/Spreadsheet.stories.tsx +362 -362
- package/src/components/Spreadsheet.tsx +351 -351
- package/src/components/SpreadsheetSimple.stories.tsx +27 -27
- package/src/components/Tabs.tsx +152 -152
- package/src/components/index.ts +5 -0
- package/src/styles/index.css +41 -4
- package/src/utils/excelExport.stories.tsx +535 -0
- package/src/utils/excelExport.ts +225 -0
- package/src/utils/index.ts +3 -0
- package/tailwind.config.js +253 -253
- package/dist/components/Button.stories.d.ts +0 -51
- package/dist/components/Button.stories.d.ts.map +0 -1
- package/dist/components/ChartVisualizationUI.d.ts +0 -21
- package/dist/components/ChartVisualizationUI.d.ts.map +0 -1
- package/dist/components/ChatUI.d.ts +0 -23
- package/dist/components/ChatUI.d.ts.map +0 -1
- package/dist/components/CommissionDashboardUI.d.ts +0 -25
- package/dist/components/CommissionDashboardUI.d.ts.map +0 -1
- package/dist/components/DataTable.stories.d.ts +0 -23
- package/dist/components/DataTable.stories.d.ts.map +0 -1
- package/dist/components/FormField.d.ts +0 -35
- package/dist/components/FormField.d.ts.map +0 -1
- package/dist/components/Input.stories.d.ts +0 -366
- package/dist/components/Input.stories.d.ts.map +0 -1
- package/dist/components/InsightsPanelUI.d.ts +0 -21
- package/dist/components/InsightsPanelUI.d.ts.map +0 -1
- package/dist/components/PaymentHistoryTimeline.d.ts +0 -34
- package/dist/components/PaymentHistoryTimeline.d.ts.map +0 -1
- package/dist/components/RelationshipManagerUI.d.ts +0 -60
- package/dist/components/RelationshipManagerUI.d.ts.map +0 -1
- package/dist/components/RoleManager.d.ts +0 -19
- package/dist/components/RoleManager.d.ts.map +0 -1
- package/dist/components/SplitCommissionBadge.d.ts +0 -18
- package/dist/components/SplitCommissionBadge.d.ts.map +0 -1
- package/dist/components/Spreadsheet.css +0 -216
- package/dist/components/__tests__/Button.test.d.ts +0 -2
- package/dist/components/__tests__/Button.test.d.ts.map +0 -1
- package/dist/components/__tests__/Input.test.d.ts +0 -2
- package/dist/components/__tests__/Input.test.d.ts.map +0 -1
|
@@ -1,362 +1,362 @@
|
|
|
1
|
-
import type { Meta, StoryObj } from '@storybook/react';
|
|
2
|
-
import { Spreadsheet, SpreadsheetReport } from './Spreadsheet';
|
|
3
|
-
import type { SpreadsheetCell, Matrix } from './Spreadsheet';
|
|
4
|
-
import { useState } from 'react';
|
|
5
|
-
import Button from './Button';
|
|
6
|
-
import { Calculator } from 'lucide-react';
|
|
7
|
-
|
|
8
|
-
const meta: Meta<typeof Spreadsheet> = {
|
|
9
|
-
title: 'Components/Spreadsheet',
|
|
10
|
-
component: Spreadsheet,
|
|
11
|
-
parameters: {
|
|
12
|
-
docs: {
|
|
13
|
-
description: {
|
|
14
|
-
component:
|
|
15
|
-
'Interactive spreadsheet component with Excel formula support (280+ formulas via Fast Formula Parser), import/export functionality, and save capabilities. Perfect for report designers and data editing interfaces.',
|
|
16
|
-
},
|
|
17
|
-
},
|
|
18
|
-
},
|
|
19
|
-
tags: ['autodocs'],
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
export default meta;
|
|
23
|
-
type Story = StoryObj<typeof Spreadsheet>;
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* Basic spreadsheet with default settings
|
|
27
|
-
*/
|
|
28
|
-
export const Basic: Story = {
|
|
29
|
-
args: {
|
|
30
|
-
rows: 10,
|
|
31
|
-
columns: 5,
|
|
32
|
-
},
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Spreadsheet with toolbar showing import/export/save actions
|
|
37
|
-
*/
|
|
38
|
-
export const WithToolbar: Story = {
|
|
39
|
-
args: {
|
|
40
|
-
rows: 15,
|
|
41
|
-
columns: 8,
|
|
42
|
-
showToolbar: true,
|
|
43
|
-
enableImport: true,
|
|
44
|
-
enableExport: true,
|
|
45
|
-
enableSave: true,
|
|
46
|
-
title: 'Data Editor',
|
|
47
|
-
exportFileName: 'my-data.xlsx',
|
|
48
|
-
},
|
|
49
|
-
render: (args) => {
|
|
50
|
-
const [data, setData] = useState<Matrix<SpreadsheetCell>>();
|
|
51
|
-
|
|
52
|
-
return (
|
|
53
|
-
<Spreadsheet
|
|
54
|
-
{...args}
|
|
55
|
-
data={data}
|
|
56
|
-
onChange={setData}
|
|
57
|
-
onSave={async (data) => {
|
|
58
|
-
console.log('Saving data:', data);
|
|
59
|
-
// Simulate API call
|
|
60
|
-
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
61
|
-
}}
|
|
62
|
-
/>
|
|
63
|
-
);
|
|
64
|
-
},
|
|
65
|
-
};
|
|
66
|
-
|
|
67
|
-
/**
|
|
68
|
-
* Spreadsheet wrapped in Card component for better presentation
|
|
69
|
-
*/
|
|
70
|
-
export const InCard: Story = {
|
|
71
|
-
args: {
|
|
72
|
-
rows: 12,
|
|
73
|
-
columns: 6,
|
|
74
|
-
showToolbar: true,
|
|
75
|
-
enableImport: true,
|
|
76
|
-
enableExport: true,
|
|
77
|
-
enableSave: true,
|
|
78
|
-
title: 'Financial Report',
|
|
79
|
-
wrapInCard: true,
|
|
80
|
-
},
|
|
81
|
-
render: (args) => {
|
|
82
|
-
const [data, setData] = useState<Matrix<SpreadsheetCell>>();
|
|
83
|
-
|
|
84
|
-
return (
|
|
85
|
-
<Spreadsheet
|
|
86
|
-
{...args}
|
|
87
|
-
data={data}
|
|
88
|
-
onChange={setData}
|
|
89
|
-
onSave={async (data) => {
|
|
90
|
-
console.log('Saving:', data);
|
|
91
|
-
await new Promise((resolve) => setTimeout(resolve, 800));
|
|
92
|
-
}}
|
|
93
|
-
/>
|
|
94
|
-
);
|
|
95
|
-
},
|
|
96
|
-
};
|
|
97
|
-
|
|
98
|
-
/**
|
|
99
|
-
* Pre-populated spreadsheet with formula examples
|
|
100
|
-
*/
|
|
101
|
-
export const WithFormulas: Story = {
|
|
102
|
-
render: () => {
|
|
103
|
-
const initialData: Matrix<SpreadsheetCell> = [
|
|
104
|
-
[
|
|
105
|
-
{ value: 'Product', readOnly: true, className: 'font-bold' },
|
|
106
|
-
{ value: 'Q1', readOnly: true, className: 'font-bold' },
|
|
107
|
-
{ value: 'Q2', readOnly: true, className: 'font-bold' },
|
|
108
|
-
{ value: 'Q3', readOnly: true, className: 'font-bold' },
|
|
109
|
-
{ value: 'Q4', readOnly: true, className: 'font-bold' },
|
|
110
|
-
{ value: 'Total', readOnly: true, className: 'font-bold' },
|
|
111
|
-
],
|
|
112
|
-
[
|
|
113
|
-
{ value: 'Widget A' },
|
|
114
|
-
{ value: 15000 },
|
|
115
|
-
{ value: 18000 },
|
|
116
|
-
{ value: 22000 },
|
|
117
|
-
{ value: 19000 },
|
|
118
|
-
{ formula: '=SUM(B2:E2)' },
|
|
119
|
-
],
|
|
120
|
-
[
|
|
121
|
-
{ value: 'Widget B' },
|
|
122
|
-
{ value: 12000 },
|
|
123
|
-
{ value: 13500 },
|
|
124
|
-
{ value: 14200 },
|
|
125
|
-
{ value: 15800 },
|
|
126
|
-
{ formula: '=SUM(B3:E3)' },
|
|
127
|
-
],
|
|
128
|
-
[
|
|
129
|
-
{ value: 'Widget C' },
|
|
130
|
-
{ value: 8500 },
|
|
131
|
-
{ value: 9200 },
|
|
132
|
-
{ value: 11000 },
|
|
133
|
-
{ value: 12300 },
|
|
134
|
-
{ formula: '=SUM(B4:E4)' },
|
|
135
|
-
],
|
|
136
|
-
[],
|
|
137
|
-
[
|
|
138
|
-
{ value: 'Quarterly Total', readOnly: true, className: 'font-bold' },
|
|
139
|
-
{ formula: '=SUM(B2:B4)' },
|
|
140
|
-
{ formula: '=SUM(C2:C4)' },
|
|
141
|
-
{ formula: '=SUM(D2:D4)' },
|
|
142
|
-
{ formula: '=SUM(E2:E4)' },
|
|
143
|
-
{ formula: '=SUM(F2:F4)' },
|
|
144
|
-
],
|
|
145
|
-
[
|
|
146
|
-
{ value: 'Average per Product', readOnly: true, className: 'font-bold' },
|
|
147
|
-
{ formula: '=AVERAGE(B2:B4)' },
|
|
148
|
-
{ formula: '=AVERAGE(C2:C4)' },
|
|
149
|
-
{ formula: '=AVERAGE(D2:D4)' },
|
|
150
|
-
{ formula: '=AVERAGE(E2:E4)' },
|
|
151
|
-
{ formula: '=AVERAGE(F2:F4)' },
|
|
152
|
-
],
|
|
153
|
-
];
|
|
154
|
-
|
|
155
|
-
const [data, setData] = useState<Matrix<SpreadsheetCell>>(initialData);
|
|
156
|
-
|
|
157
|
-
return (
|
|
158
|
-
<div className="p-4">
|
|
159
|
-
<h3 className="text-lg font-semibold mb-4">Sales Report with Formulas</h3>
|
|
160
|
-
<p className="text-sm text-ink-600 mb-4">
|
|
161
|
-
This example demonstrates SUM and AVERAGE formulas. Try editing the values in Q1-Q4 columns
|
|
162
|
-
and watch the totals update automatically!
|
|
163
|
-
</p>
|
|
164
|
-
<Spreadsheet
|
|
165
|
-
data={data}
|
|
166
|
-
onChange={setData}
|
|
167
|
-
showToolbar
|
|
168
|
-
enableExport
|
|
169
|
-
enableSave
|
|
170
|
-
title="Quarterly Sales Report"
|
|
171
|
-
wrapInCard
|
|
172
|
-
exportFileName="sales-report.xlsx"
|
|
173
|
-
onSave={async (data) => {
|
|
174
|
-
console.log('Saving report:', data);
|
|
175
|
-
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
176
|
-
}}
|
|
177
|
-
/>
|
|
178
|
-
</div>
|
|
179
|
-
);
|
|
180
|
-
},
|
|
181
|
-
};
|
|
182
|
-
|
|
183
|
-
/**
|
|
184
|
-
* Read-only spreadsheet for viewing reports
|
|
185
|
-
*/
|
|
186
|
-
export const ReadOnly: Story = {
|
|
187
|
-
render: () => {
|
|
188
|
-
const reportData: Matrix<SpreadsheetCell> = [
|
|
189
|
-
[
|
|
190
|
-
{ value: 'Metric', readOnly: true },
|
|
191
|
-
{ value: 'Value', readOnly: true },
|
|
192
|
-
{ value: 'Target', readOnly: true },
|
|
193
|
-
{ value: 'Status', readOnly: true },
|
|
194
|
-
],
|
|
195
|
-
[{ value: 'Revenue' }, { value: 125000 }, { value: 120000 }, { value: '✓ Met' }],
|
|
196
|
-
[{ value: 'Expenses' }, { value: 85000 }, { value: 90000 }, { value: '✓ Under' }],
|
|
197
|
-
[{ value: 'Profit' }, { formula: '=B2-B3' }, { formula: '=C2-C3' }, { value: '✓ Above' }],
|
|
198
|
-
[{ value: 'Margin %' }, { formula: '=B4/B2*100' }, { formula: '=C4/C2*100' }, { value: '' }],
|
|
199
|
-
];
|
|
200
|
-
|
|
201
|
-
return (
|
|
202
|
-
<Spreadsheet
|
|
203
|
-
data={reportData}
|
|
204
|
-
readOnly
|
|
205
|
-
title="Financial Summary (Read-Only)"
|
|
206
|
-
showToolbar
|
|
207
|
-
enableExport
|
|
208
|
-
wrapInCard
|
|
209
|
-
exportFileName="financial-summary.xlsx"
|
|
210
|
-
/>
|
|
211
|
-
);
|
|
212
|
-
},
|
|
213
|
-
};
|
|
214
|
-
|
|
215
|
-
/**
|
|
216
|
-
* SpreadsheetReport component - pre-configured for report designer use
|
|
217
|
-
*/
|
|
218
|
-
export const ReportDesigner: Story = {
|
|
219
|
-
render: () => {
|
|
220
|
-
const [reportData, setReportData] = useState<Matrix<SpreadsheetCell>>([
|
|
221
|
-
[
|
|
222
|
-
{ value: 'Month', readOnly: true },
|
|
223
|
-
{ value: 'Sales', readOnly: true },
|
|
224
|
-
{ value: 'Costs', readOnly: true },
|
|
225
|
-
{ value: 'Profit', readOnly: true },
|
|
226
|
-
],
|
|
227
|
-
[{ value: 'January' }, { value: 50000 }, { value: 30000 }, { formula: '=B2-C2' }],
|
|
228
|
-
[{ value: 'February' }, { value: 55000 }, { value: 32000 }, { formula: '=B3-C3' }],
|
|
229
|
-
[{ value: 'March' }, { value: 62000 }, { value: 35000 }, { formula: '=B4-C4' }],
|
|
230
|
-
[],
|
|
231
|
-
[
|
|
232
|
-
{ value: 'Total', readOnly: true },
|
|
233
|
-
{ formula: '=SUM(B2:B4)' },
|
|
234
|
-
{ formula: '=SUM(C2:C4)' },
|
|
235
|
-
{ formula: '=SUM(D2:D4)' },
|
|
236
|
-
],
|
|
237
|
-
]);
|
|
238
|
-
|
|
239
|
-
return (
|
|
240
|
-
<div className="max-w-6xl mx-auto p-6">
|
|
241
|
-
<h2 className="text-2xl font-bold mb-4">Report Designer</h2>
|
|
242
|
-
<p className="text-ink-600 mb-6">
|
|
243
|
-
The SpreadsheetReport component comes pre-configured with toolbar, import/export, and save
|
|
244
|
-
functionality. Perfect for building interactive reports!
|
|
245
|
-
</p>
|
|
246
|
-
|
|
247
|
-
<SpreadsheetReport
|
|
248
|
-
data={reportData}
|
|
249
|
-
onChange={setReportData}
|
|
250
|
-
title="Monthly Financial Report"
|
|
251
|
-
exportFileName="monthly-report.xlsx"
|
|
252
|
-
onSave={async (data) => {
|
|
253
|
-
console.log('Saving report:', data);
|
|
254
|
-
await new Promise((resolve) => setTimeout(resolve, 1200));
|
|
255
|
-
}}
|
|
256
|
-
/>
|
|
257
|
-
|
|
258
|
-
<div className="mt-6 p-4 bg-paper-50 border border-stone-200 rounded-lg">
|
|
259
|
-
<h3 className="font-semibold mb-2">Formula Support</h3>
|
|
260
|
-
<p className="text-sm text-ink-600 mb-2">
|
|
261
|
-
Fast Formula Parser provides 280+ Excel formulas including:
|
|
262
|
-
</p>
|
|
263
|
-
<ul className="text-sm text-ink-600 list-disc list-inside space-y-1">
|
|
264
|
-
<li>Math: SUM, AVERAGE, ROUND, ABS, POWER, SQRT</li>
|
|
265
|
-
<li>Logical: IF, AND, OR, NOT, IFERROR</li>
|
|
266
|
-
<li>Lookup: VLOOKUP, HLOOKUP, INDEX</li>
|
|
267
|
-
<li>Text: CONCATENATE, LEFT, RIGHT, TRIM, UPPER, LOWER</li>
|
|
268
|
-
<li>Date/Time: DATE, TODAY, YEAR, MONTH, DAY</li>
|
|
269
|
-
<li>Statistical: COUNT, COUNTIF, MAX, MIN, STDEV</li>
|
|
270
|
-
</ul>
|
|
271
|
-
</div>
|
|
272
|
-
</div>
|
|
273
|
-
);
|
|
274
|
-
},
|
|
275
|
-
};
|
|
276
|
-
|
|
277
|
-
/**
|
|
278
|
-
* Spreadsheet with custom actions in toolbar
|
|
279
|
-
*/
|
|
280
|
-
export const WithCustomActions: Story = {
|
|
281
|
-
render: () => {
|
|
282
|
-
const [data, setData] = useState<Matrix<SpreadsheetCell>>();
|
|
283
|
-
|
|
284
|
-
return (
|
|
285
|
-
<Spreadsheet
|
|
286
|
-
data={data}
|
|
287
|
-
onChange={setData}
|
|
288
|
-
rows={10}
|
|
289
|
-
columns={6}
|
|
290
|
-
showToolbar
|
|
291
|
-
enableImport
|
|
292
|
-
enableExport
|
|
293
|
-
title="Custom Actions Demo"
|
|
294
|
-
actions={
|
|
295
|
-
<>
|
|
296
|
-
<Button
|
|
297
|
-
variant="ghost"
|
|
298
|
-
size="sm"
|
|
299
|
-
icon={<Calculator className="h-4 w-4" />}
|
|
300
|
-
onClick={() => console.log('Calculate clicked')}
|
|
301
|
-
>
|
|
302
|
-
Calculate
|
|
303
|
-
</Button>
|
|
304
|
-
<Button
|
|
305
|
-
variant="secondary"
|
|
306
|
-
size="sm"
|
|
307
|
-
onClick={() => console.log('Clear clicked')}
|
|
308
|
-
>
|
|
309
|
-
Clear
|
|
310
|
-
</Button>
|
|
311
|
-
</>
|
|
312
|
-
}
|
|
313
|
-
wrapInCard
|
|
314
|
-
/>
|
|
315
|
-
);
|
|
316
|
-
},
|
|
317
|
-
};
|
|
318
|
-
|
|
319
|
-
/**
|
|
320
|
-
* Compact spreadsheet for smaller spaces
|
|
321
|
-
*/
|
|
322
|
-
export const Compact: Story = {
|
|
323
|
-
args: {
|
|
324
|
-
rows: 8,
|
|
325
|
-
columns: 4,
|
|
326
|
-
showToolbar: false,
|
|
327
|
-
className: 'text-sm',
|
|
328
|
-
},
|
|
329
|
-
};
|
|
330
|
-
|
|
331
|
-
/**
|
|
332
|
-
* Large spreadsheet for complex data entry
|
|
333
|
-
*/
|
|
334
|
-
export const Large: Story = {
|
|
335
|
-
args: {
|
|
336
|
-
rows: 50,
|
|
337
|
-
columns: 20,
|
|
338
|
-
showToolbar: true,
|
|
339
|
-
enableImport: true,
|
|
340
|
-
enableExport: true,
|
|
341
|
-
enableSave: true,
|
|
342
|
-
title: 'Large Dataset Editor',
|
|
343
|
-
wrapInCard: true,
|
|
344
|
-
},
|
|
345
|
-
render: (args) => {
|
|
346
|
-
const [data, setData] = useState<Matrix<SpreadsheetCell>>();
|
|
347
|
-
|
|
348
|
-
return (
|
|
349
|
-
<div style={{ height: '600px' }}>
|
|
350
|
-
<Spreadsheet
|
|
351
|
-
{...args}
|
|
352
|
-
data={data}
|
|
353
|
-
onChange={setData}
|
|
354
|
-
onSave={async (data) => {
|
|
355
|
-
console.log('Saving large dataset');
|
|
356
|
-
await new Promise((resolve) => setTimeout(resolve, 1500));
|
|
357
|
-
}}
|
|
358
|
-
/>
|
|
359
|
-
</div>
|
|
360
|
-
);
|
|
361
|
-
},
|
|
362
|
-
};
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
2
|
+
import { Spreadsheet, SpreadsheetReport } from './Spreadsheet';
|
|
3
|
+
import type { SpreadsheetCell, Matrix } from './Spreadsheet';
|
|
4
|
+
import { useState } from 'react';
|
|
5
|
+
import Button from './Button';
|
|
6
|
+
import { Calculator } from 'lucide-react';
|
|
7
|
+
|
|
8
|
+
const meta: Meta<typeof Spreadsheet> = {
|
|
9
|
+
title: 'Components/Spreadsheet',
|
|
10
|
+
component: Spreadsheet,
|
|
11
|
+
parameters: {
|
|
12
|
+
docs: {
|
|
13
|
+
description: {
|
|
14
|
+
component:
|
|
15
|
+
'Interactive spreadsheet component with Excel formula support (280+ formulas via Fast Formula Parser), import/export functionality, and save capabilities. Perfect for report designers and data editing interfaces.',
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
tags: ['autodocs'],
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export default meta;
|
|
23
|
+
type Story = StoryObj<typeof Spreadsheet>;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Basic spreadsheet with default settings
|
|
27
|
+
*/
|
|
28
|
+
export const Basic: Story = {
|
|
29
|
+
args: {
|
|
30
|
+
rows: 10,
|
|
31
|
+
columns: 5,
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Spreadsheet with toolbar showing import/export/save actions
|
|
37
|
+
*/
|
|
38
|
+
export const WithToolbar: Story = {
|
|
39
|
+
args: {
|
|
40
|
+
rows: 15,
|
|
41
|
+
columns: 8,
|
|
42
|
+
showToolbar: true,
|
|
43
|
+
enableImport: true,
|
|
44
|
+
enableExport: true,
|
|
45
|
+
enableSave: true,
|
|
46
|
+
title: 'Data Editor',
|
|
47
|
+
exportFileName: 'my-data.xlsx',
|
|
48
|
+
},
|
|
49
|
+
render: (args) => {
|
|
50
|
+
const [data, setData] = useState<Matrix<SpreadsheetCell>>();
|
|
51
|
+
|
|
52
|
+
return (
|
|
53
|
+
<Spreadsheet
|
|
54
|
+
{...args}
|
|
55
|
+
data={data}
|
|
56
|
+
onChange={setData}
|
|
57
|
+
onSave={async (data) => {
|
|
58
|
+
console.log('Saving data:', data);
|
|
59
|
+
// Simulate API call
|
|
60
|
+
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
61
|
+
}}
|
|
62
|
+
/>
|
|
63
|
+
);
|
|
64
|
+
},
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Spreadsheet wrapped in Card component for better presentation
|
|
69
|
+
*/
|
|
70
|
+
export const InCard: Story = {
|
|
71
|
+
args: {
|
|
72
|
+
rows: 12,
|
|
73
|
+
columns: 6,
|
|
74
|
+
showToolbar: true,
|
|
75
|
+
enableImport: true,
|
|
76
|
+
enableExport: true,
|
|
77
|
+
enableSave: true,
|
|
78
|
+
title: 'Financial Report',
|
|
79
|
+
wrapInCard: true,
|
|
80
|
+
},
|
|
81
|
+
render: (args) => {
|
|
82
|
+
const [data, setData] = useState<Matrix<SpreadsheetCell>>();
|
|
83
|
+
|
|
84
|
+
return (
|
|
85
|
+
<Spreadsheet
|
|
86
|
+
{...args}
|
|
87
|
+
data={data}
|
|
88
|
+
onChange={setData}
|
|
89
|
+
onSave={async (data) => {
|
|
90
|
+
console.log('Saving:', data);
|
|
91
|
+
await new Promise((resolve) => setTimeout(resolve, 800));
|
|
92
|
+
}}
|
|
93
|
+
/>
|
|
94
|
+
);
|
|
95
|
+
},
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Pre-populated spreadsheet with formula examples
|
|
100
|
+
*/
|
|
101
|
+
export const WithFormulas: Story = {
|
|
102
|
+
render: () => {
|
|
103
|
+
const initialData: Matrix<SpreadsheetCell> = [
|
|
104
|
+
[
|
|
105
|
+
{ value: 'Product', readOnly: true, className: 'font-bold' },
|
|
106
|
+
{ value: 'Q1', readOnly: true, className: 'font-bold' },
|
|
107
|
+
{ value: 'Q2', readOnly: true, className: 'font-bold' },
|
|
108
|
+
{ value: 'Q3', readOnly: true, className: 'font-bold' },
|
|
109
|
+
{ value: 'Q4', readOnly: true, className: 'font-bold' },
|
|
110
|
+
{ value: 'Total', readOnly: true, className: 'font-bold' },
|
|
111
|
+
],
|
|
112
|
+
[
|
|
113
|
+
{ value: 'Widget A' },
|
|
114
|
+
{ value: 15000 },
|
|
115
|
+
{ value: 18000 },
|
|
116
|
+
{ value: 22000 },
|
|
117
|
+
{ value: 19000 },
|
|
118
|
+
{ formula: '=SUM(B2:E2)' },
|
|
119
|
+
],
|
|
120
|
+
[
|
|
121
|
+
{ value: 'Widget B' },
|
|
122
|
+
{ value: 12000 },
|
|
123
|
+
{ value: 13500 },
|
|
124
|
+
{ value: 14200 },
|
|
125
|
+
{ value: 15800 },
|
|
126
|
+
{ formula: '=SUM(B3:E3)' },
|
|
127
|
+
],
|
|
128
|
+
[
|
|
129
|
+
{ value: 'Widget C' },
|
|
130
|
+
{ value: 8500 },
|
|
131
|
+
{ value: 9200 },
|
|
132
|
+
{ value: 11000 },
|
|
133
|
+
{ value: 12300 },
|
|
134
|
+
{ formula: '=SUM(B4:E4)' },
|
|
135
|
+
],
|
|
136
|
+
[],
|
|
137
|
+
[
|
|
138
|
+
{ value: 'Quarterly Total', readOnly: true, className: 'font-bold' },
|
|
139
|
+
{ formula: '=SUM(B2:B4)' },
|
|
140
|
+
{ formula: '=SUM(C2:C4)' },
|
|
141
|
+
{ formula: '=SUM(D2:D4)' },
|
|
142
|
+
{ formula: '=SUM(E2:E4)' },
|
|
143
|
+
{ formula: '=SUM(F2:F4)' },
|
|
144
|
+
],
|
|
145
|
+
[
|
|
146
|
+
{ value: 'Average per Product', readOnly: true, className: 'font-bold' },
|
|
147
|
+
{ formula: '=AVERAGE(B2:B4)' },
|
|
148
|
+
{ formula: '=AVERAGE(C2:C4)' },
|
|
149
|
+
{ formula: '=AVERAGE(D2:D4)' },
|
|
150
|
+
{ formula: '=AVERAGE(E2:E4)' },
|
|
151
|
+
{ formula: '=AVERAGE(F2:F4)' },
|
|
152
|
+
],
|
|
153
|
+
];
|
|
154
|
+
|
|
155
|
+
const [data, setData] = useState<Matrix<SpreadsheetCell>>(initialData);
|
|
156
|
+
|
|
157
|
+
return (
|
|
158
|
+
<div className="p-4">
|
|
159
|
+
<h3 className="text-lg font-semibold mb-4">Sales Report with Formulas</h3>
|
|
160
|
+
<p className="text-sm text-ink-600 mb-4">
|
|
161
|
+
This example demonstrates SUM and AVERAGE formulas. Try editing the values in Q1-Q4 columns
|
|
162
|
+
and watch the totals update automatically!
|
|
163
|
+
</p>
|
|
164
|
+
<Spreadsheet
|
|
165
|
+
data={data}
|
|
166
|
+
onChange={setData}
|
|
167
|
+
showToolbar
|
|
168
|
+
enableExport
|
|
169
|
+
enableSave
|
|
170
|
+
title="Quarterly Sales Report"
|
|
171
|
+
wrapInCard
|
|
172
|
+
exportFileName="sales-report.xlsx"
|
|
173
|
+
onSave={async (data) => {
|
|
174
|
+
console.log('Saving report:', data);
|
|
175
|
+
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
176
|
+
}}
|
|
177
|
+
/>
|
|
178
|
+
</div>
|
|
179
|
+
);
|
|
180
|
+
},
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Read-only spreadsheet for viewing reports
|
|
185
|
+
*/
|
|
186
|
+
export const ReadOnly: Story = {
|
|
187
|
+
render: () => {
|
|
188
|
+
const reportData: Matrix<SpreadsheetCell> = [
|
|
189
|
+
[
|
|
190
|
+
{ value: 'Metric', readOnly: true },
|
|
191
|
+
{ value: 'Value', readOnly: true },
|
|
192
|
+
{ value: 'Target', readOnly: true },
|
|
193
|
+
{ value: 'Status', readOnly: true },
|
|
194
|
+
],
|
|
195
|
+
[{ value: 'Revenue' }, { value: 125000 }, { value: 120000 }, { value: '✓ Met' }],
|
|
196
|
+
[{ value: 'Expenses' }, { value: 85000 }, { value: 90000 }, { value: '✓ Under' }],
|
|
197
|
+
[{ value: 'Profit' }, { formula: '=B2-B3' }, { formula: '=C2-C3' }, { value: '✓ Above' }],
|
|
198
|
+
[{ value: 'Margin %' }, { formula: '=B4/B2*100' }, { formula: '=C4/C2*100' }, { value: '' }],
|
|
199
|
+
];
|
|
200
|
+
|
|
201
|
+
return (
|
|
202
|
+
<Spreadsheet
|
|
203
|
+
data={reportData}
|
|
204
|
+
readOnly
|
|
205
|
+
title="Financial Summary (Read-Only)"
|
|
206
|
+
showToolbar
|
|
207
|
+
enableExport
|
|
208
|
+
wrapInCard
|
|
209
|
+
exportFileName="financial-summary.xlsx"
|
|
210
|
+
/>
|
|
211
|
+
);
|
|
212
|
+
},
|
|
213
|
+
};
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* SpreadsheetReport component - pre-configured for report designer use
|
|
217
|
+
*/
|
|
218
|
+
export const ReportDesigner: Story = {
|
|
219
|
+
render: () => {
|
|
220
|
+
const [reportData, setReportData] = useState<Matrix<SpreadsheetCell>>([
|
|
221
|
+
[
|
|
222
|
+
{ value: 'Month', readOnly: true },
|
|
223
|
+
{ value: 'Sales', readOnly: true },
|
|
224
|
+
{ value: 'Costs', readOnly: true },
|
|
225
|
+
{ value: 'Profit', readOnly: true },
|
|
226
|
+
],
|
|
227
|
+
[{ value: 'January' }, { value: 50000 }, { value: 30000 }, { formula: '=B2-C2' }],
|
|
228
|
+
[{ value: 'February' }, { value: 55000 }, { value: 32000 }, { formula: '=B3-C3' }],
|
|
229
|
+
[{ value: 'March' }, { value: 62000 }, { value: 35000 }, { formula: '=B4-C4' }],
|
|
230
|
+
[],
|
|
231
|
+
[
|
|
232
|
+
{ value: 'Total', readOnly: true },
|
|
233
|
+
{ formula: '=SUM(B2:B4)' },
|
|
234
|
+
{ formula: '=SUM(C2:C4)' },
|
|
235
|
+
{ formula: '=SUM(D2:D4)' },
|
|
236
|
+
],
|
|
237
|
+
]);
|
|
238
|
+
|
|
239
|
+
return (
|
|
240
|
+
<div className="max-w-6xl mx-auto p-6">
|
|
241
|
+
<h2 className="text-2xl font-bold mb-4">Report Designer</h2>
|
|
242
|
+
<p className="text-ink-600 mb-6">
|
|
243
|
+
The SpreadsheetReport component comes pre-configured with toolbar, import/export, and save
|
|
244
|
+
functionality. Perfect for building interactive reports!
|
|
245
|
+
</p>
|
|
246
|
+
|
|
247
|
+
<SpreadsheetReport
|
|
248
|
+
data={reportData}
|
|
249
|
+
onChange={setReportData}
|
|
250
|
+
title="Monthly Financial Report"
|
|
251
|
+
exportFileName="monthly-report.xlsx"
|
|
252
|
+
onSave={async (data) => {
|
|
253
|
+
console.log('Saving report:', data);
|
|
254
|
+
await new Promise((resolve) => setTimeout(resolve, 1200));
|
|
255
|
+
}}
|
|
256
|
+
/>
|
|
257
|
+
|
|
258
|
+
<div className="mt-6 p-4 bg-paper-50 border border-stone-200 rounded-lg">
|
|
259
|
+
<h3 className="font-semibold mb-2">Formula Support</h3>
|
|
260
|
+
<p className="text-sm text-ink-600 mb-2">
|
|
261
|
+
Fast Formula Parser provides 280+ Excel formulas including:
|
|
262
|
+
</p>
|
|
263
|
+
<ul className="text-sm text-ink-600 list-disc list-inside space-y-1">
|
|
264
|
+
<li>Math: SUM, AVERAGE, ROUND, ABS, POWER, SQRT</li>
|
|
265
|
+
<li>Logical: IF, AND, OR, NOT, IFERROR</li>
|
|
266
|
+
<li>Lookup: VLOOKUP, HLOOKUP, INDEX</li>
|
|
267
|
+
<li>Text: CONCATENATE, LEFT, RIGHT, TRIM, UPPER, LOWER</li>
|
|
268
|
+
<li>Date/Time: DATE, TODAY, YEAR, MONTH, DAY</li>
|
|
269
|
+
<li>Statistical: COUNT, COUNTIF, MAX, MIN, STDEV</li>
|
|
270
|
+
</ul>
|
|
271
|
+
</div>
|
|
272
|
+
</div>
|
|
273
|
+
);
|
|
274
|
+
},
|
|
275
|
+
};
|
|
276
|
+
|
|
277
|
+
/**
|
|
278
|
+
* Spreadsheet with custom actions in toolbar
|
|
279
|
+
*/
|
|
280
|
+
export const WithCustomActions: Story = {
|
|
281
|
+
render: () => {
|
|
282
|
+
const [data, setData] = useState<Matrix<SpreadsheetCell>>();
|
|
283
|
+
|
|
284
|
+
return (
|
|
285
|
+
<Spreadsheet
|
|
286
|
+
data={data}
|
|
287
|
+
onChange={setData}
|
|
288
|
+
rows={10}
|
|
289
|
+
columns={6}
|
|
290
|
+
showToolbar
|
|
291
|
+
enableImport
|
|
292
|
+
enableExport
|
|
293
|
+
title="Custom Actions Demo"
|
|
294
|
+
actions={
|
|
295
|
+
<>
|
|
296
|
+
<Button
|
|
297
|
+
variant="ghost"
|
|
298
|
+
size="sm"
|
|
299
|
+
icon={<Calculator className="h-4 w-4" />}
|
|
300
|
+
onClick={() => console.log('Calculate clicked')}
|
|
301
|
+
>
|
|
302
|
+
Calculate
|
|
303
|
+
</Button>
|
|
304
|
+
<Button
|
|
305
|
+
variant="secondary"
|
|
306
|
+
size="sm"
|
|
307
|
+
onClick={() => console.log('Clear clicked')}
|
|
308
|
+
>
|
|
309
|
+
Clear
|
|
310
|
+
</Button>
|
|
311
|
+
</>
|
|
312
|
+
}
|
|
313
|
+
wrapInCard
|
|
314
|
+
/>
|
|
315
|
+
);
|
|
316
|
+
},
|
|
317
|
+
};
|
|
318
|
+
|
|
319
|
+
/**
|
|
320
|
+
* Compact spreadsheet for smaller spaces
|
|
321
|
+
*/
|
|
322
|
+
export const Compact: Story = {
|
|
323
|
+
args: {
|
|
324
|
+
rows: 8,
|
|
325
|
+
columns: 4,
|
|
326
|
+
showToolbar: false,
|
|
327
|
+
className: 'text-sm',
|
|
328
|
+
},
|
|
329
|
+
};
|
|
330
|
+
|
|
331
|
+
/**
|
|
332
|
+
* Large spreadsheet for complex data entry
|
|
333
|
+
*/
|
|
334
|
+
export const Large: Story = {
|
|
335
|
+
args: {
|
|
336
|
+
rows: 50,
|
|
337
|
+
columns: 20,
|
|
338
|
+
showToolbar: true,
|
|
339
|
+
enableImport: true,
|
|
340
|
+
enableExport: true,
|
|
341
|
+
enableSave: true,
|
|
342
|
+
title: 'Large Dataset Editor',
|
|
343
|
+
wrapInCard: true,
|
|
344
|
+
},
|
|
345
|
+
render: (args) => {
|
|
346
|
+
const [data, setData] = useState<Matrix<SpreadsheetCell>>();
|
|
347
|
+
|
|
348
|
+
return (
|
|
349
|
+
<div style={{ height: '600px' }}>
|
|
350
|
+
<Spreadsheet
|
|
351
|
+
{...args}
|
|
352
|
+
data={data}
|
|
353
|
+
onChange={setData}
|
|
354
|
+
onSave={async (data) => {
|
|
355
|
+
console.log('Saving large dataset');
|
|
356
|
+
await new Promise((resolve) => setTimeout(resolve, 1500));
|
|
357
|
+
}}
|
|
358
|
+
/>
|
|
359
|
+
</div>
|
|
360
|
+
);
|
|
361
|
+
},
|
|
362
|
+
};
|