@particle-academy/fancy-sheets 0.6.4 → 0.7.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.
@@ -61,6 +61,8 @@ Takes `SheetData` directly — no workbook wrapper, no tabs, no toolbar:
61
61
  | rowHeight | `number` | `28` | Row height in px |
62
62
  | readOnly | `boolean` | `false` | Disable editing |
63
63
  | contextMenuItems | `ContextMenuItem[] \| (addr) => ContextMenuItem[]` | - | Custom right-click items |
64
+ | highlights | `CellHighlightMap` | - | Consumer-driven cell highlights (address → color/label) |
65
+ | onActiveCellChange | `(addr, cell?) => void` | - | Fires when the active cell changes |
64
66
  | className | `string` | - | Additional CSS classes |
65
67
 
66
68
  ### Spreadsheet.Toolbar
@@ -129,6 +131,7 @@ interface CellData {
129
131
  computedValue?: CellValue;
130
132
  format?: CellFormat;
131
133
  comment?: CellComment;
134
+ meta?: Record<string, unknown>; // consumer-defined metadata
132
135
  }
133
136
  ```
134
137
 
@@ -148,6 +151,7 @@ interface CellFormat {
148
151
  borderRight?: string;
149
152
  borderBottom?: string;
150
153
  borderLeft?: string;
154
+ className?: string; // custom CSS class(es) on the cell element
151
155
  }
152
156
  ```
153
157
 
@@ -353,6 +357,90 @@ contextMenuItems={(addr) => [
353
357
 
354
358
  Submenus nest arbitrarily deep — each item with `items` renders as a hover-to-open submenu with a chevron indicator.
355
359
 
360
+ ## Cell Metadata
361
+
362
+ The `meta` field on `CellData` stores arbitrary consumer-defined data. The package preserves it through edits but never reads it — consumers use it to build domain-specific features like grouping, tagging, or variable bindings.
363
+
364
+ ```tsx
365
+ s.cells = {
366
+ A1: { value: "Revenue", meta: { group: "rev", role: "label" } },
367
+ B1: { value: 50000, meta: { group: "rev", role: "variable" } },
368
+ };
369
+ ```
370
+
371
+ ## Custom CSS Classes
372
+
373
+ The `className` field on `CellFormat` applies custom CSS classes to individual cell elements. Use it for Tailwind utilities, conditional styling, animations, or any CSS your app needs.
374
+
375
+ ```tsx
376
+ s.cells = {
377
+ A1: { value: "Header", format: { className: "font-semibold tracking-wide" } },
378
+ B1: { value: 42, format: { className: "tabular-nums text-right" } },
379
+ C1: { value: "Alert", format: { className: "animate-pulse bg-red-100" } },
380
+ };
381
+ ```
382
+
383
+ Classes are merged after the built-in cell classes via `cn()`, so Tailwind utilities work and can override defaults.
384
+
385
+ ## Cell Highlights
386
+
387
+ The `highlights` prop renders visual overlays on cells independent of selection and formatting — colored outlines, background tints, and optional label badges.
388
+
389
+ ```ts
390
+ interface CellHighlight {
391
+ color: string; // outline color (CSS)
392
+ backgroundColor?: string; // tint (auto-derived at 10% opacity from hex if omitted)
393
+ label?: string; // small badge in top-left corner
394
+ }
395
+
396
+ type CellHighlightMap = Record<string, CellHighlight>;
397
+ ```
398
+
399
+ ### Static highlights
400
+
401
+ ```tsx
402
+ <Sheet
403
+ data={sheet}
404
+ onChange={setSheet}
405
+ highlights={{
406
+ A1: { color: "#8b5cf6", label: "src" },
407
+ B1: { color: "#8b5cf6", label: "dst" },
408
+ }}
409
+ />
410
+ ```
411
+
412
+ ### Reactive highlights (grouping pattern)
413
+
414
+ Use `onActiveCellChange` + `meta` to highlight related cells when the user clicks:
415
+
416
+ ```tsx
417
+ const [activeAddr, setActiveAddr] = useState("A1");
418
+
419
+ const highlights = useMemo<CellHighlightMap>(() => {
420
+ const group = (sheet.cells[activeAddr]?.meta as any)?.group;
421
+ if (!group) return {};
422
+ const map: CellHighlightMap = {};
423
+ for (const [addr, cell] of Object.entries(sheet.cells)) {
424
+ if ((cell.meta as any)?.group === group) {
425
+ map[addr] = {
426
+ color: "#8b5cf6",
427
+ label: (cell.meta as any)?.role,
428
+ };
429
+ }
430
+ }
431
+ return map;
432
+ }, [activeAddr, sheet.cells]);
433
+
434
+ <Sheet
435
+ data={sheet}
436
+ onChange={setSheet}
437
+ highlights={highlights}
438
+ onActiveCellChange={(addr) => setActiveAddr(addr)}
439
+ />
440
+ ```
441
+
442
+ Click a cell tagged with `meta: { group: "rev" }` and all cells in that group highlight with a purple outline, tinted background, and role badges ("var", "lbl").
443
+
356
444
  ## Custom Formulas
357
445
 
358
446
  Register custom functions that users can call in cell formulas with `=FUNCTION_NAME(...)`.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@particle-academy/fancy-sheets",
3
- "version": "0.6.4",
3
+ "version": "0.7.0",
4
4
  "description": "Spreadsheet editor with formula engine, multi-sheet tabs, and full cell editing",
5
5
  "repository": {
6
6
  "type": "git",