@particle-academy/react-fancy 5.54.2 → 5.55.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/CHANGELOG.md CHANGED
@@ -11,6 +11,57 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
11
11
 
12
12
  ## [Unreleased]
13
13
 
14
+ ## [5.55.0] - 2026-10-21
15
+
16
+ ### Added
17
+
18
+ - **`TimeGrid` typed cells and range selection.** Pass `cells` (with `states`)
19
+ and the grid renders the host's own vocabulary instead of on/off. **Nothing
20
+ to do for an existing grid:** without `cells` it is the same boolean grid,
21
+ with the same DOM (byte-identical in Chrome against 5.54.2) and the same
22
+ timings. `value` / `onChange` are now optional in the type because a typed
23
+ grid does not use them.
24
+ - `cells: TimeGridCell[][]`: each cell is `{ state, disabled?, reasons?,
25
+ marks?, meta? }`. `meta` is handed back untouched in every callback.
26
+ - `states: Record<id, { tone?, label?, className? }>`: the exclusive
27
+ dimension (open / closed / booked …). `marks: Record<id, { tone?, icon?,
28
+ label? }>`: non-exclusive overlays. The kit declares the shape; the host
29
+ declares the vocabulary.
30
+ - `selectionShape: "rectangle" | "linear"`. A rectangle is the same window
31
+ across rows (09:00-17:00 Mon-Fri); a linear run goes in reading order and
32
+ crosses row ends (23:54 Mon to 00:06 Tue). `selection` is a discriminated
33
+ union, controlled or uncontrolled; `onSelectionChange(next, cells)` hands
34
+ the cells in selection order; `onSelectionCommit` fires when a drag ends
35
+ or Enter is pressed.
36
+ - Selection is derived from anchor + current cell, so a fast drag no longer
37
+ leaves gaps, and pointer capture keeps a drag tracking (clamped to the
38
+ edge) after it leaves the grid.
39
+ - `disabledRange: "clamp" | "refuse" | "span"` (default `clamp`) decides what
40
+ a range crossing a disabled cell does, identically in both shapes.
41
+ `onBlockedSelect(blocked)` reports clipped or refused cells with their
42
+ `reasons`.
43
+ - A disabled cell's `reasons` reach the `title`, the cell's
44
+ `aria-description`, and a tooltip shown while the cell has keyboard focus.
45
+ - Keyboard: the grid takes focus (`aria-activedescendant`), not every cell.
46
+ Arrows move, Shift+arrows extend from the anchor, Space selects the
47
+ focused cell, Enter commits, Escape clears. Header clicks select a whole
48
+ row or column.
49
+ - `onCellHover(cell, { r, c })` for a host-owned detail panel; `null, null`
50
+ on leave. `aria-label` names the grid.
51
+ - `cells` without `states` throws in development: an unknown vocabulary
52
+ would otherwise render as one colour. An unknown state id warns once and
53
+ renders neutral.
54
+ - Colours: state and mark tones from the existing `TimeGridTone` set; the
55
+ neutral fill, selection wash, focus outline, headers and tooltip read the
56
+ `--fancy-*` tokens. Dark mode follows `.dark` and `[data-theme="dark"]`.
57
+ - A mark's `icon` is a `ReactNode` (e.g. `<Icon name="lock" />`), not an
58
+ icon name: resolving names would import every Lucide glyph into any bundle
59
+ that uses TimeGrid (measured: 16k to 56k lines).
60
+ - **Measured (Chrome, 4x CPU throttle, 240 columns, median of 7):** typed grid
61
+ mount 157 ms at 7 days, 260 ms at 14 days, 552 ms at 31 days; update
62
+ 44-75 ms. The 14-day mount is still over the 200 ms budget. Column windowing
63
+ is the next release.
64
+
14
65
  ## [5.54.2] - 2026-10-21
15
66
 
16
67
  ### Fixed