@particle-academy/fancy-sheets 0.4.5 → 0.4.6

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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/styles.css"],"sourcesContent":["/* @particle-academy/fancy-sheets — spreadsheet styles */\r\n\r\n/* Grid cell borders */\r\n[data-fancy-sheets-grid] {\r\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\r\n}\r\n\r\n/* Cell editor positioning */\r\n[data-fancy-sheets-cell-editor] {\r\n box-sizing: border-box;\r\n}\r\n\r\n/* Scrollbar styling */\r\n[data-fancy-sheets-grid]::-webkit-scrollbar {\r\n width: 10px;\r\n height: 10px;\r\n}\r\n\r\n[data-fancy-sheets-grid]::-webkit-scrollbar-track {\r\n background: transparent;\r\n}\r\n\r\n[data-fancy-sheets-grid]::-webkit-scrollbar-thumb {\r\n background: #a1a1aa;\r\n border-radius: 5px;\r\n}\r\n\r\n.dark [data-fancy-sheets-grid]::-webkit-scrollbar-thumb {\r\n background: #52525b;\r\n}\r\n"],"mappings":";AAGA,CAAC;AACC;AAAA,IAAa,aAAa;AAAA,IAAE,kBAAkB;AAAA,IAAE,UAAU;AAAA,IAAE,MAAM;AAAA,IAAE;AACtE;AAGA,CAAC;AACC,cAAY;AACd;AAGA,CAAC,uBAAuB;AACtB,SAAO;AACP,UAAQ;AACV;AAEA,CAAC,uBAAuB;AACtB,cAAY;AACd;AAEA,CAAC,uBAAuB;AACtB,cAAY;AACZ,iBAAe;AACjB;AAEA,CAAC,KAAK,CAAC,uBAAuB;AAC5B,cAAY;AACd;","names":[]}
1
+ {"version":3,"sources":["../src/styles.css"],"sourcesContent":["/* @particle-academy/fancy-sheets — spreadsheet styles */\n\n/* Grid cell borders */\n[data-fancy-sheets-grid] {\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n}\n\n/* Cell editor positioning */\n[data-fancy-sheets-cell-editor] {\n box-sizing: border-box;\n}\n\n/* Scrollbar styling */\n[data-fancy-sheets-grid]::-webkit-scrollbar {\n width: 10px;\n height: 10px;\n}\n\n[data-fancy-sheets-grid]::-webkit-scrollbar-track {\n background: transparent;\n}\n\n[data-fancy-sheets-grid]::-webkit-scrollbar-thumb {\n background: #a1a1aa;\n border-radius: 5px;\n}\n\n.dark [data-fancy-sheets-grid]::-webkit-scrollbar-thumb {\n background: #52525b;\n}\n"],"mappings":";AAGA,CAAC;AACC;AAAA,IAAa,aAAa;AAAA,IAAE,kBAAkB;AAAA,IAAE,UAAU;AAAA,IAAE,MAAM;AAAA,IAAE;AACtE;AAGA,CAAC;AACC,cAAY;AACd;AAGA,CAAC,uBAAuB;AACtB,SAAO;AACP,UAAQ;AACV;AAEA,CAAC,uBAAuB;AACtB,cAAY;AACd;AAEA,CAAC,uBAAuB;AACtB,cAAY;AACZ,iBAAe;AACjB;AAEA,CAAC,KAAK,CAAC,uBAAuB;AAC5B,cAAY;AACd;","names":[]}
@@ -0,0 +1,216 @@
1
+ # Spreadsheet
2
+
3
+ A full-featured spreadsheet component with formulas, formatting, selection, multi-sheet workbooks, clipboard, CSV import/export, and undo/redo. Compound API.
4
+
5
+ ## Import
6
+
7
+ ```tsx
8
+ import { Spreadsheet, useSpreadsheet } from "@particle-academy/fancy-sheets";
9
+ import "@particle-academy/fancy-sheets/styles.css";
10
+ ```
11
+
12
+ ## Basic Usage
13
+
14
+ ```tsx
15
+ <div style={{ height: 600 }}>
16
+ <Spreadsheet>
17
+ <Spreadsheet.Toolbar />
18
+ <Spreadsheet.Grid />
19
+ <Spreadsheet.SheetTabs />
20
+ </Spreadsheet>
21
+ </div>
22
+ ```
23
+
24
+ The component fills its container — wrap it in a sized element (height is required).
25
+
26
+ ## Props
27
+
28
+ ### Spreadsheet (root)
29
+
30
+ | Prop | Type | Default | Description |
31
+ |------|------|---------|-------------|
32
+ | data | `WorkbookData` | - | Controlled workbook |
33
+ | defaultData | `WorkbookData` | empty workbook | Initial workbook (uncontrolled) |
34
+ | onChange | `(data: WorkbookData) => void` | - | Called on any data change |
35
+ | columnCount | `number` | `26` | Number of columns |
36
+ | rowCount | `number` | `100` | Number of rows |
37
+ | defaultColumnWidth | `number` | `100` | Default column width in px |
38
+ | rowHeight | `number` | `28` | Row height in px |
39
+ | readOnly | `boolean` | `false` | Disable editing, formatting, and structural changes |
40
+ | className | `string` | - | Additional CSS classes |
41
+
42
+ ### Spreadsheet.Toolbar
43
+
44
+ Default toolbar with format buttons (bold, italic, align), undo/redo, and freeze controls. Pass `children` to replace entirely.
45
+
46
+ | Prop | Type | Description |
47
+ |------|------|-------------|
48
+ | children | `ReactNode` | Replace defaults |
49
+ | className | `string` | Additional CSS classes |
50
+
51
+ ### Spreadsheet.Grid
52
+
53
+ The main editable cell grid. Handles navigation, selection, editing, keyboard shortcuts, and clipboard.
54
+
55
+ | Prop | Type | Description |
56
+ |------|------|-------------|
57
+ | className | `string` | Additional CSS classes |
58
+
59
+ ### Spreadsheet.SheetTabs
60
+
61
+ Bottom tab bar for multi-sheet workbooks. Supports add/rename/delete/switch.
62
+
63
+ | Prop | Type | Description |
64
+ |------|------|-------------|
65
+ | className | `string` | Additional CSS classes |
66
+
67
+ ## Data Model
68
+
69
+ ### WorkbookData
70
+
71
+ ```ts
72
+ interface WorkbookData {
73
+ sheets: SheetData[];
74
+ activeSheetId: string;
75
+ }
76
+ ```
77
+
78
+ ### SheetData
79
+
80
+ ```ts
81
+ interface SheetData {
82
+ id: string;
83
+ name: string;
84
+ cells: Record<CellAddress, CellData>; // sparse — only non-empty cells
85
+ columnWidths: Record<number, number>; // sparse overrides
86
+ mergedRegions: MergedRegion[];
87
+ columnFilters: Record<number, string>;
88
+ sortColumn?: number;
89
+ sortDirection?: "asc" | "desc";
90
+ frozenRows: number;
91
+ frozenCols: number;
92
+ }
93
+ ```
94
+
95
+ ### CellData
96
+
97
+ ```ts
98
+ type CellAddress = string; // "A1", "AA99", ...
99
+ type CellValue = string | number | boolean | null;
100
+
101
+ interface CellData {
102
+ value: CellValue; // raw entered value
103
+ formula?: string; // original formula string (e.g. "=SUM(A1:A10)")
104
+ computedValue?: CellValue; // evaluated result
105
+ format?: CellFormat;
106
+ }
107
+ ```
108
+
109
+ ### CellFormat
110
+
111
+ ```ts
112
+ interface CellFormat {
113
+ bold?: boolean;
114
+ italic?: boolean;
115
+ textAlign?: "left" | "center" | "right";
116
+ displayFormat?: "auto" | "date" | "datetime" | "number" | "percent";
117
+ decimals?: number;
118
+ }
119
+ ```
120
+
121
+ ## Helpers
122
+
123
+ ```ts
124
+ import { createEmptyWorkbook, createEmptySheet } from "@particle-academy/fancy-sheets";
125
+
126
+ const workbook = createEmptyWorkbook();
127
+ const newSheet = createEmptySheet("sheet-2", "Summary");
128
+ ```
129
+
130
+ ## useSpreadsheet Hook
131
+
132
+ Access full workbook state and actions from any child of `<Spreadsheet>`.
133
+
134
+ ```tsx
135
+ import { useSpreadsheet } from "@particle-academy/fancy-sheets";
136
+
137
+ function ExportButton() {
138
+ const { workbook } = useSpreadsheet();
139
+ return (
140
+ <button onClick={() => download(workbookToCSV(workbook))}>
141
+ Export CSV
142
+ </button>
143
+ );
144
+ }
145
+ ```
146
+
147
+ See `SpreadsheetContextValue` in source for the full shape — key properties:
148
+
149
+ | Property | Description |
150
+ |----------|-------------|
151
+ | `workbook` | Current WorkbookData |
152
+ | `activeSheet` | Currently displayed SheetData |
153
+ | `selection` | `{ activeCell, ranges }` |
154
+ | `setCellValue(addr, val)` | Update a single cell |
155
+ | `setCellFormat(addrs[], fmt)` | Apply formatting to a list of cells |
156
+ | `navigate(dir, extend?)` | Move active cell (arrow-key equivalent) |
157
+ | `startEdit(val?) / confirmEdit() / cancelEdit()` | Edit lifecycle |
158
+ | `addSheet() / renameSheet() / deleteSheet() / setActiveSheet()` | Sheet management |
159
+ | `setFrozenRows(n) / setFrozenCols(n)` | Freeze controls |
160
+ | `undo() / redo()` | History navigation (50-step stack) |
161
+ | `canUndo / canRedo` | Booleans |
162
+
163
+ ## Controlled Usage
164
+
165
+ ```tsx
166
+ const [data, setData] = useState<WorkbookData>(createEmptyWorkbook());
167
+
168
+ <Spreadsheet data={data} onChange={setData}>
169
+ <Spreadsheet.Toolbar />
170
+ <Spreadsheet.Grid />
171
+ <Spreadsheet.SheetTabs />
172
+ </Spreadsheet>
173
+ ```
174
+
175
+ ## Read-Only Display
176
+
177
+ ```tsx
178
+ <Spreadsheet defaultData={reportData} readOnly>
179
+ <Spreadsheet.Grid />
180
+ </Spreadsheet>
181
+ ```
182
+
183
+ ## Keyboard Shortcuts
184
+
185
+ | Keys | Action |
186
+ |------|--------|
187
+ | Arrow keys | Move active cell |
188
+ | Shift + arrows | Extend selection |
189
+ | Ctrl/Cmd + arrows | Jump to edge |
190
+ | Enter / F2 | Start editing |
191
+ | Esc | Cancel edit |
192
+ | Tab / Shift+Tab | Move right/left |
193
+ | Ctrl/Cmd + C / X / V | Copy / Cut / Paste |
194
+ | Ctrl/Cmd + Z / Y | Undo / Redo |
195
+ | Ctrl/Cmd + B / I | Bold / Italic |
196
+
197
+ ## Data Attributes
198
+
199
+ | Attribute | Element |
200
+ |-----------|---------|
201
+ | `data-fancy-sheets` | Root container |
202
+ | `data-fancy-sheets-toolbar` | Toolbar |
203
+ | `data-fancy-sheets-formula-bar` | Formula bar |
204
+ | `data-fancy-sheets-grid` | Grid container |
205
+ | `data-fancy-sheets-column-headers` | Column header row |
206
+ | `data-fancy-sheets-row-header` | Row header cell |
207
+ | `data-fancy-sheets-cell` | Individual cell |
208
+ | `data-fancy-sheets-cell-editor` | Active edit input |
209
+ | `data-fancy-sheets-selection` | Selection overlay |
210
+ | `data-fancy-sheets-resize-handle` | Column resize handle |
211
+ | `data-fancy-sheets-tabs` | Sheet tabs |
212
+
213
+ ## See Also
214
+
215
+ - [Formulas](./formulas.md) — all 80+ built-in functions and how to register custom ones
216
+ - [CSV Import/Export](./csv.md) — `csvToWorkbook`, `workbookToCSV`, `parseCSV`, `stringifyCSV`
package/docs/csv.md ADDED
@@ -0,0 +1,75 @@
1
+ # CSV Import / Export
2
+
3
+ Four utility functions for moving data between CSV strings and workbook/sheet structures. Handles quoted fields, escaped quotes, and newlines inside quoted values.
4
+
5
+ ## Import
6
+
7
+ ```tsx
8
+ import {
9
+ parseCSV,
10
+ stringifyCSV,
11
+ csvToWorkbook,
12
+ workbookToCSV,
13
+ } from "@particle-academy/fancy-sheets";
14
+ ```
15
+
16
+ ## Low-Level: parseCSV / stringifyCSV
17
+
18
+ ```ts
19
+ function parseCSV(csv: string): string[][];
20
+ function stringifyCSV(rows: string[][]): string;
21
+ ```
22
+
23
+ ```tsx
24
+ const rows = parseCSV(`name,age\nAlice,30\nBob,25`);
25
+ // [["name", "age"], ["Alice", "30"], ["Bob", "25"]]
26
+
27
+ const csv = stringifyCSV(rows);
28
+ // "name,age\nAlice,30\nBob,25"
29
+ ```
30
+
31
+ Quoted strings are preserved, embedded commas/newlines survive the round-trip, and `""` is decoded as a literal `"`.
32
+
33
+ ## High-Level: csvToWorkbook / workbookToCSV
34
+
35
+ ```ts
36
+ function csvToWorkbook(csv: string, sheetName?: string): WorkbookData;
37
+ function workbookToCSV(workbook: WorkbookData): string;
38
+ ```
39
+
40
+ Use these for full workbook ↔ file conversions:
41
+
42
+ ```tsx
43
+ // Load a CSV file into the editor
44
+ const text = await file.text();
45
+ const workbook = csvToWorkbook(text, file.name.replace(/\.csv$/i, ""));
46
+ setData(workbook);
47
+
48
+ // Export current workbook to CSV
49
+ const csv = workbookToCSV(workbook);
50
+ downloadFile(csv, "export.csv", "text/csv");
51
+ ```
52
+
53
+ `workbookToCSV` concatenates all sheets separated by a blank line and `# <sheet name>` header lines. For single-sheet export, slice the returned string or pre-filter the workbook to one sheet.
54
+
55
+ ## Example: File Upload
56
+
57
+ ```tsx
58
+ function Importer() {
59
+ const { workbook } = useSpreadsheet();
60
+
61
+ const handleFile = async (e: ChangeEvent<HTMLInputElement>) => {
62
+ const file = e.target.files?.[0];
63
+ if (!file) return;
64
+ const text = await file.text();
65
+ const imported = csvToWorkbook(text, file.name);
66
+ // merge into existing workbook or replace...
67
+ };
68
+
69
+ return <input type="file" accept=".csv" onChange={handleFile} />;
70
+ }
71
+ ```
72
+
73
+ ## Clipboard
74
+
75
+ Clipboard paste into the grid already uses TSV (tab-separated) internally — paste a CSV from Excel / Sheets and it lands in the cells correctly. Use the CSV helpers for file-based import/export, not clipboard.
@@ -0,0 +1,161 @@
1
+ # Formulas
2
+
3
+ The engine evaluates Excel/Sheets-style formulas entered with a leading `=`. Parser and evaluator are custom — no third-party dependency.
4
+
5
+ ## Basics
6
+
7
+ ```
8
+ =A1+B1 addition
9
+ =SUM(A1:A10) range aggregate
10
+ =IF(A1>100, "hi", "lo") logic
11
+ =Sheet2!B3 cross-sheet reference
12
+ =A1 & " " & B1 string concatenation
13
+ ```
14
+
15
+ ## Operators
16
+
17
+ | Operator | Meaning |
18
+ |----------|---------|
19
+ | `+` `-` `*` `/` `^` | Arithmetic (`^` = power) |
20
+ | `=` `<>` `<` `<=` `>` `>=` | Comparison |
21
+ | `&` | String concatenation |
22
+ | `%` | Percentage (`50%` = 0.5) |
23
+ | `()` | Grouping |
24
+
25
+ ## Error Values
26
+
27
+ | Value | Cause |
28
+ |-------|-------|
29
+ | `#ERROR!` | Syntax error in formula |
30
+ | `#VALUE!` | Wrong argument type |
31
+ | `#DIV/0!` | Division by zero |
32
+ | `#NAME?` | Unknown function |
33
+ | `#CIRC!` | Circular reference |
34
+
35
+ ## Reference Forms
36
+
37
+ - `A1` — single cell
38
+ - `A1:B5` — range
39
+ - `Sheet2!A1` — cell on another sheet
40
+ - `Sheet2!A1:B5` — range on another sheet
41
+
42
+ ## Built-in Functions (80+)
43
+
44
+ ### Math (25)
45
+
46
+ | Function | Purpose |
47
+ |----------|---------|
48
+ | `SUM(range)` | Sum of numbers |
49
+ | `AVERAGE(range)` | Arithmetic mean |
50
+ | `MEDIAN(range)` | Median value |
51
+ | `MIN(range)` / `MAX(range)` | Min / max |
52
+ | `COUNT(range)` | Count of numeric cells |
53
+ | `PRODUCT(range)` | Product of numbers |
54
+ | `ROUND(n, digits)` | Round to `digits` decimals |
55
+ | `ABS(n)` | Absolute value |
56
+ | `SQRT(n)` | Square root |
57
+ | `POWER(base, exp)` | `base^exp` |
58
+ | `MOD(a, b)` | Remainder |
59
+ | `INT(n)` / `TRUNC(n)` | Truncate to int |
60
+ | `FLOOR(n)` / `CEILING(n)` | Round down / up |
61
+ | `SIGN(n)` | `-1`, `0`, or `1` |
62
+ | `FACT(n)` | Factorial |
63
+ | `PI()` | 3.14159… |
64
+ | `EXP(n)` | `e^n` |
65
+ | `LN(n)` / `LOG(n, base?)` / `LOG10(n)` | Logarithms |
66
+ | `RAND()` | 0 ≤ x < 1 |
67
+ | `RANDBETWEEN(lo, hi)` | Integer in range |
68
+
69
+ ### Text (19)
70
+
71
+ | Function | Purpose |
72
+ |----------|---------|
73
+ | `UPPER(s)` / `LOWER(s)` / `PROPER(s)` | Case conversion |
74
+ | `LEN(s)` | String length |
75
+ | `TRIM(s)` | Strip leading/trailing whitespace |
76
+ | `LEFT(s, n)` / `RIGHT(s, n)` / `MID(s, start, n)` | Substrings |
77
+ | `FIND(needle, haystack, start?)` | Case-sensitive position |
78
+ | `SEARCH(needle, haystack, start?)` | Case-insensitive position |
79
+ | `SUBSTITUTE(s, old, new, occurrence?)` | Replace |
80
+ | `REPLACE(s, start, count, new)` | Positional replace |
81
+ | `CONCAT(...args)` | Join strings |
82
+ | `REPT(s, n)` | Repeat |
83
+ | `EXACT(a, b)` | Case-sensitive equality |
84
+ | `VALUE(s)` | String → number |
85
+ | `TEXT(n, fmt)` | Number → formatted string |
86
+ | `CHAR(code)` / `CODE(s)` | Code ↔ character |
87
+
88
+ ### Logic (8)
89
+
90
+ | Function | Purpose |
91
+ |----------|---------|
92
+ | `IF(cond, then, else)` | Conditional |
93
+ | `AND(...args)` / `OR(...args)` / `NOT(a)` | Boolean |
94
+ | `IFERROR(val, fallback)` | Catch errors |
95
+ | `IFBLANK(val, fallback)` | Blank-cell fallback |
96
+ | `SWITCH(expr, case1, val1, ..., default?)` | Multi-branch |
97
+ | `CHOOSE(index, v1, v2, ...)` | Pick by 1-based index |
98
+
99
+ ### Conditional Aggregates (8)
100
+
101
+ | Function | Purpose |
102
+ |----------|---------|
103
+ | `SUMIF(range, criterion, sumRange?)` | Sum matching |
104
+ | `SUMIFS(sumRange, r1, c1, ...)` | Multi-criteria sum |
105
+ | `COUNTIF(range, criterion)` | Count matching |
106
+ | `COUNTIFS(r1, c1, ...)` | Multi-criteria count |
107
+ | `AVERAGEIF(range, criterion, avgRange?)` | Average matching |
108
+ | `AVERAGEIFS(avgRange, r1, c1, ...)` | Multi-criteria average |
109
+ | `MINIFS(minRange, r1, c1, ...)` | Min matching |
110
+ | `MAXIFS(maxRange, r1, c1, ...)` | Max matching |
111
+
112
+ Criteria support operators as strings: `">100"`, `"<=50"`, `"<>"`, `"=apple"`.
113
+
114
+ ### Lookup (8)
115
+
116
+ | Function | Purpose |
117
+ |----------|---------|
118
+ | `VLOOKUP(value, range, colIndex, exact?)` | Vertical lookup |
119
+ | `HLOOKUP(value, range, rowIndex, exact?)` | Horizontal lookup |
120
+ | `INDEX(range, row, col?)` | Index into a range |
121
+ | `MATCH(value, range, type?)` | Find position |
122
+ | `ROWS(range)` / `COLUMNS(range)` | Dimensions |
123
+ | `ROW(ref?)` / `COLUMN(ref?)` | Position of a ref |
124
+
125
+ ### Date / Time (12)
126
+
127
+ | Function | Purpose |
128
+ |----------|---------|
129
+ | `TODAY()` | Current date |
130
+ | `NOW()` | Current date + time |
131
+ | `DATE(y, m, d)` | Build a date |
132
+ | `YEAR(date)` / `MONTH(date)` / `DAY(date)` | Extract parts |
133
+ | `HOUR(t)` / `MINUTE(t)` / `SECOND(t)` | Extract time parts |
134
+ | `WEEKDAY(date, type?)` | Day of week |
135
+ | `DATEDIF(start, end, unit)` | Difference (`"Y"`, `"M"`, `"D"`) |
136
+ | `EDATE(start, months)` | Offset by months |
137
+
138
+ ### Info (6)
139
+
140
+ | Function | Purpose |
141
+ |----------|---------|
142
+ | `ISBLANK(ref)` | Cell is empty |
143
+ | `ISNUMBER(val)` / `ISTEXT(val)` / `ISLOGICAL(val)` | Type checks |
144
+ | `ISERROR(val)` | Is an error value |
145
+ | `TYPE(val)` | Type code (1=number, 2=text, 4=logical, 16=error) |
146
+
147
+ ## Registering Custom Functions
148
+
149
+ ```tsx
150
+ import { registerFunction } from "@particle-academy/fancy-sheets";
151
+
152
+ registerFunction("GREET", (name: string) => `Hello, ${name}`);
153
+
154
+ // In a cell: =GREET("world") → "Hello, world"
155
+ ```
156
+
157
+ Custom functions are called with resolved arguments (cell values, not tokens). Return any `CellValue`. Throwing is allowed — the value becomes `#ERROR!` in the grid.
158
+
159
+ ## Dependency Tracking
160
+
161
+ The evaluator builds a dependency graph between cells. When a cell changes, only transitively dependent cells are re-evaluated, in topological order. Circular references are detected and reported as `#CIRC!`.
package/package.json CHANGED
@@ -1,56 +1,63 @@
1
- {
2
- "name": "@particle-academy/fancy-sheets",
3
- "version": "0.4.5",
4
- "description": "Spreadsheet editor with formula engine, multi-sheet tabs, and full cell editing",
5
- "type": "module",
6
- "main": "./dist/index.cjs",
7
- "module": "./dist/index.js",
8
- "types": "./dist/index.d.ts",
9
- "exports": {
10
- ".": {
11
- "import": {
12
- "types": "./dist/index.d.ts",
13
- "default": "./dist/index.js"
14
- },
15
- "require": {
16
- "types": "./dist/index.d.cts",
17
- "default": "./dist/index.cjs"
18
- }
19
- },
20
- "./styles.css": "./dist/styles.css"
21
- },
22
- "files": [
23
- "dist",
24
- "README.md"
25
- ],
26
- "scripts": {
27
- "build": "tsup",
28
- "dev": "tsup --watch",
29
- "lint": "tsc --noEmit",
30
- "clean": "rm -rf dist",
31
- "prepublishOnly": "tsup"
32
- },
33
- "peerDependencies": {
34
- "react": "^18.0.0 || ^19.0.0",
35
- "react-dom": "^18.0.0 || ^19.0.0",
36
- "@particle-academy/react-fancy": "^1.5.0"
37
- },
38
- "dependencies": {},
39
- "devDependencies": {
40
- "@particle-academy/react-fancy": "workspace:*",
41
- "@types/react": "^19.0.0",
42
- "@types/react-dom": "^19.0.0",
43
- "react": "^19.0.0",
44
- "react-dom": "^19.0.0",
45
- "tsup": "^8.5.0",
46
- "typescript": "^5.8.0"
47
- },
48
- "publishConfig": {
49
- "access": "public"
50
- },
51
- "license": "MIT",
52
- "sideEffects": [
53
- "**/*.css",
54
- "src/engine/formula/functions/*.ts"
55
- ]
56
- }
1
+ {
2
+ "name": "@particle-academy/fancy-sheets",
3
+ "version": "0.4.6",
4
+ "description": "Spreadsheet editor with formula engine, multi-sheet tabs, and full cell editing",
5
+ "repository": {
6
+ "type": "git",
7
+ "url": "git+https://github.com/Particle-Academy/fancy-sheets.git"
8
+ },
9
+ "homepage": "https://github.com/Particle-Academy/fancy-sheets#readme",
10
+ "bugs": "https://github.com/Particle-Academy/fancy-sheets/issues",
11
+ "type": "module",
12
+ "main": "./dist/index.cjs",
13
+ "module": "./dist/index.js",
14
+ "types": "./dist/index.d.ts",
15
+ "exports": {
16
+ ".": {
17
+ "import": {
18
+ "types": "./dist/index.d.ts",
19
+ "default": "./dist/index.js"
20
+ },
21
+ "require": {
22
+ "types": "./dist/index.d.cts",
23
+ "default": "./dist/index.cjs"
24
+ }
25
+ },
26
+ "./styles.css": "./dist/styles.css"
27
+ },
28
+ "files": [
29
+ "dist",
30
+ "docs",
31
+ "README.md"
32
+ ],
33
+ "scripts": {
34
+ "build": "tsup",
35
+ "dev": "tsup --watch",
36
+ "lint": "tsc --noEmit",
37
+ "clean": "rm -rf dist",
38
+ "prepublishOnly": "tsup"
39
+ },
40
+ "peerDependencies": {
41
+ "react": "^18.0.0 || ^19.0.0",
42
+ "react-dom": "^18.0.0 || ^19.0.0",
43
+ "@particle-academy/react-fancy": "^1.5.0"
44
+ },
45
+ "dependencies": {},
46
+ "devDependencies": {
47
+ "@particle-academy/react-fancy": "*",
48
+ "@types/react": "^19.0.0",
49
+ "@types/react-dom": "^19.0.0",
50
+ "react": "^19.0.0",
51
+ "react-dom": "^19.0.0",
52
+ "tsup": "^8.5.0",
53
+ "typescript": "^5.8.0"
54
+ },
55
+ "publishConfig": {
56
+ "access": "public"
57
+ },
58
+ "license": "MIT",
59
+ "sideEffects": [
60
+ "**/*.css",
61
+ "src/engine/formula/functions/*.ts"
62
+ ]
63
+ }