hazo_ui 2.11.0 → 2.17.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/CHANGE_LOG.md CHANGED
@@ -5,6 +5,234 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [2.17.0] - 2026-05-17
9
+
10
+ ### Added
11
+ - **`hazo_ui_charts` — new chart-primitives sub-section.** Six components
12
+ for the Site Ops Dashboard project, ported from its mockup HTML so the
13
+ app doesn't need a third-party chart lib:
14
+ - `Sparkline` — axisless trend line for KPI cards (12% area fill,
15
+ single endpoint dot, no hover — by design per PRD §6b).
16
+ - `InverseSparkline` — same shape but Y-axis inverted (lower = better)
17
+ for GSC position trends. 62×18 default, used inline in scrollable
18
+ query lists.
19
+ - `LineChart` — full anatomy (3 dashed gridlines, Y ticks max/mid/min,
20
+ X labels start/mid/end, marker dot + dashed guide-line to Y-axis +
21
+ above-left value label). Optional hover tooltip surfaces a cursor +
22
+ bubble at the nearest data index.
23
+ - `MultiLineChart` — shared Y-axis, per-series endpoint marker, no
24
+ area fill (avoids color collisions). Hover bubble shows all series
25
+ stacked. Optional legend below the SVG.
26
+ - `StackedBars` — generic stacked-bar over time. One bar per X
27
+ position; each bar split into top-to-bottom colored bands. Used by
28
+ the GSC position-bucket distribution view.
29
+ - `DateRangeSelector` — segmented control (`value` + `onChange`).
30
+ Framework-agnostic: no `next/navigation` import; consumer wires the
31
+ state. Active pill tints with `--primary`.
32
+ - Pure helpers: `format_num` (compact `1.2k` / `1.3M`),
33
+ `pick_x_label_indices`.
34
+ - Shared types: `ChartDataPoint`, `ChartDataSeries`, `MultiSeries`,
35
+ `StackedBar`, `DateRangeOption`.
36
+ - Dev-app demo at `/charts` with six sections (one per primitive)
37
+ covering rising / falling / flat / with-nulls / all-zeros /
38
+ single-point data shapes.
39
+
40
+ ### Notes
41
+ - Hover coordinate mapping uses `getBoundingClientRect()` to translate
42
+ client X → viewBox X. Assumes the SVG renders at `width: 100%` (the
43
+ default we ship). Documented in `src/components/hazo_ui_charts/AGENTS.md`.
44
+ - Axis label color and gridline color are pinned hex (`#8b949e`,
45
+ `#2a3441`) chosen for the Site Ops dark theme. Theming via CSS
46
+ variables is a follow-up if a second consumer needs it.
47
+ - All chart components ship as Client Components by default — the
48
+ library bundle is `"use client"`-stamped at build time, same as the
49
+ rest of hazo_ui. The pure-SVG primitives don't *require* JS to
50
+ render, but they don't get RSC-rendered either.
51
+
52
+ ### API
53
+ - No changes to existing components; this is purely additive.
54
+
55
+ ## [2.16.0] - 2026-05-17
56
+
57
+ ### Changed
58
+ - **Restyled `HazoUiMultiSortDialog` and `HazoUiMultiFilterDialog`** for a
59
+ modern, Linear/Notion-style appearance:
60
+ - Tighter dialog chrome: bordered header, padded body, bordered footer
61
+ bar with subtle muted background — replaces the flat, dated look.
62
+ - **Sort dialog**: each row now shows a numbered priority badge, a
63
+ segmented Asc/Desc pill (replaces the ambiguous switch), and a muted
64
+ delete affordance that reddens on hover.
65
+ - **Filter dialog**: rows have compact mathematical operator symbols
66
+ (`=`, `≠`, `>`, `<`, `≥`, `≤`) in a narrow select; inputs are 32px
67
+ tall for a denser layout; rows match the sort dialog visually.
68
+ - **Footer hierarchy fixed**: `Clear all` is a low-emphasis ghost
69
+ button on the left; `Cancel` (outline) and `Apply` (primary) are
70
+ grouped on the right — `Apply` is the rightmost / final action.
71
+ - Trigger buttons now show an active-count badge next to the icon.
72
+ - Empty state uses a dashed-border placeholder card; the "Add field"
73
+ affordance matches and disables itself when all fields are added.
74
+ - **Dialog animation**: removed `slide-in-from-left-1/2` /
75
+ `slide-out-to-left-1/2` classes from `DialogContent`. Modals now
76
+ fade + zoom in place from center — no more horizontal "drift" that
77
+ caught the dialog mid-animation looking off-screen.
78
+
79
+ ### API
80
+ - All component props (including the color-override props on both
81
+ dialogs) are unchanged; this is a visual refresh, not a contract
82
+ change. Existing consumers do not need to update call sites.
83
+
84
+ ## [2.15.1] - 2026-05-17
85
+
86
+ ### Fixed
87
+ - **SSR/CSR hydration mismatch in HazoUiTable number/currency/percent
88
+ formatters.** `Intl.NumberFormat(undefined, …)` resolved to the
89
+ runtime's host locale, which differs between Node (server) and the
90
+ browser (client) — e.g. server `$4,812,500.00` vs. client
91
+ `US$4,812,500.00` when the browser default is `en-GB`. The library
92
+ now pins to `"en-US"` so both environments produce the same string.
93
+
94
+ ### Added
95
+ - New `locale?: string` on `TableColumn` (BCP-47 tag, e.g. `"de-DE"`,
96
+ `"ja-JP"`) — opt-out for the new pinned default. Applies to `number`,
97
+ `currency`, and `percent` formatters. Date formatting was unaffected
98
+ and is unchanged (it uses `date-fns`, not `Intl`).
99
+
100
+ ## [2.15.0] - 2026-05-17
101
+
102
+ ### Added
103
+ - **Shift-click multi-sort on `HazoUiTable` headers.** Plain header
104
+ click still cycles asc → desc → none (single column). Shift-click
105
+ a header to append it as a secondary sort, cycling that column
106
+ asc → desc → removed without collapsing prior columns. Discoverable
107
+ via a `title=` tooltip on the sort button. `useTableState.cycleHeaderSort`
108
+ gains an `append?: boolean` parameter; new `cycleAppendColumn` helper
109
+ alongside the existing `cycleSingleColumn`.
110
+ - **Column-level `currency` override on `TableColumn`.** When `formatter`
111
+ is `"currency"`, the formatter reads `column.currency` (any ISO-4217
112
+ code, e.g. `"EUR"`, `"GBP"`) instead of the previously hard-coded
113
+ `"USD"`. Defaults to `"USD"` when omitted — fully backwards-compatible.
114
+ - **Structured `onLoad` error UX.** `HazoUiTableProps` gains
115
+ `error?: React.ReactNode | ((err: unknown) => React.ReactNode)`.
116
+ `useTableState` exposes `serverError` (always `null` outside server
117
+ mode). On `onLoad` rejection, the table renders the consumer's
118
+ `error` prop in place of rows; if none is provided, a default
119
+ `EmptyState` shows the thrown message. `console.warn` continues to
120
+ log every rejection. Branch added to both the desktop `TableBody`
121
+ and the mobile card view.
122
+ - Dev-app `/table` §9 demos the error state with a rejecting loader.
123
+ §2 copy mentions the new shift-click gesture.
124
+
125
+ ### Internal
126
+ - Renamed `use_table_state` → `useTableState` (function only — the
127
+ filename stays `use_table_state.ts`). Aligns with the package's
128
+ other hooks (`useMediaQuery`, `useLoadingState`, `useErrorDisplay`)
129
+ and unblocks the `react-hooks/rules-of-hooks` lint rule.
130
+ - New ESLint v9 flat config (`eslint.config.js`) so `npm run lint`
131
+ works again. Scoped to `src/**/*.{ts,tsx}` with
132
+ `@typescript-eslint` and `react-hooks` rules.
133
+
134
+ ### Notes
135
+ - The 200 ms search debounce default is unchanged — the spec §10
136
+ follow-up about tuning needs empirical data from the sister app.
137
+ Consumers can already override per-table via `searchDebounceMs`.
138
+
139
+ ## [2.14.0] - 2026-05-17
140
+
141
+ ### Added
142
+ - **`Table` shadcn primitive family.** Eight components (`Table`,
143
+ `TableHeader`, `TableBody`, `TableFooter`, `TableRow`, `TableHead`,
144
+ `TableCell`, `TableCaption`) re-exported under bare shadcn names.
145
+ Matches the canonical shadcn shape — drop-in for consumers that want
146
+ raw markup.
147
+ - **`HazoUiTable` composite.** Column-config-driven data table that
148
+ composes the primitive with an in-memory filter/sort/paginate
149
+ pipeline:
150
+ - `TableColumn` is the single source of truth for display, sort,
151
+ filter, and search metadata.
152
+ - Sortable headers cycle asc → desc → none and replace any
153
+ multi-column sort with single-column on click. Multi-column sort
154
+ via the optional `HazoUiMultiSortDialog` integration; indicators
155
+ show order numbers.
156
+ - Optional toolbar with debounced free-text search (200 ms),
157
+ `HazoUiMultiFilterDialog`, and `HazoUiMultiSortDialog`. Available
158
+ fields are derived from columns — declared once.
159
+ - Loading state via `SkeletonBar`; empty / no-results via
160
+ `EmptyState`.
161
+ - Optional pagination footer with "Showing X–Y of Z" + Prev/Next.
162
+ - Optional row click with full mouse + keyboard support (Enter,
163
+ Space) when `onRowClick` is set.
164
+ - Mobile card-per-row fallback below a configurable breakpoint
165
+ (default 768 px). Opt out with `mobileCardFallback={false}`.
166
+ - Optional `onLoad({ page, sort, filter })` for server-side data;
167
+ latest-request-wins.
168
+ - Dev-app `/table` route with eight demo sections covering every
169
+ acceptance scenario.
170
+
171
+ ### Dependencies
172
+ - No new dependencies. Composes existing `Skeleton`, `EmptyState`,
173
+ `Card`, `Input`, `Button`, `HazoUiMultiSortDialog`,
174
+ `HazoUiMultiFilterDialog`, `useMediaQuery` from this package, plus
175
+ `date-fns` and `lucide-react` (already deps).
176
+
177
+ ## [2.13.1] - 2026-05-16
178
+
179
+ ### Changed
180
+ - **`KanbanEditor` is now built on `HazoUiDialog`** (was raw shadcn `Dialog` primitives). Picks up the standardized header (with `title` + `description` so Radix's missing-`Description` warning is gone naturally), the standardized Save/Cancel footer with built-in `actionButtonLoading` spinner + `actionButtonDisabled`, and a priority-tinted full-width header bar via `headerBar` + `headerBarColor` — reads `hsl(var(--hazo-kanban-priority-{p0..p3}))` for visual continuity with the card left borders. The Save button gets a `Check` icon for clarity.
181
+ - Auto-detect default editor now appends a **Status** select at the end (sourced from the kanban's `columns`), so users can move the card between columns from the editor out of the box without configuring `editorFields`.
182
+ - Field labels rendered slightly smaller and muted (`text-xs font-medium text-muted-foreground`) for a more compact SaaS density.
183
+
184
+ ### Added
185
+ - New `'status'` value on `KanbanEditorFieldType`. Renders a `Select` pre-populated from the kanban's `columns` prop (label = `column.title`, value = `column.key`). Bound to `columnKey` by convention; saving with a different status moves the card to a new column through the consumer's `onCardSave` handler — same code path as `onMove`.
186
+ - Dev-app §7 editor declares `{ key: 'columnKey', type: 'status', label: 'Status' }` so the demo exercises the new field type.
187
+
188
+ ### Removed
189
+ - The explicit `aria-describedby={undefined}` workaround on `DialogContent` from v2.13.0 — `HazoUiDialog` exposes a proper `description` prop that satisfies Radix without the escape hatch.
190
+
191
+ ## [2.13.0] - 2026-05-16
192
+
193
+ ### Changed (breaking, but pre-publish)
194
+ - **Renamed `HazoUiBoard` family to `HazoUiKanban`.** v2.12.0 was committed to git but never `npm publish`'d, so this is a hard rename with no deprecation shim. Affected exports: `HazoUiBoard` → `HazoUiKanban`, `HazoUiBoardFilter` → `HazoUiKanbanFilter`, `applyBoardFilter` → `applyKanbanFilter`, plus the corresponding type aliases (`BoardItem` → `KanbanItem`, etc.). CSS class prefixes `cls_hazo_board_*` → `cls_hazo_kanban_*`; CSS variables `--hazo-board-*` → `--hazo-kanban-*`. Dev-app route `/board` → `/kanban`.
195
+
196
+ ### Added
197
+ - **Out-of-the-box card editor.** Each card now carries a pencil icon (top-right, opacity-0 idle, opacity-100 on hover/focus). Clicking opens a `HazoUiDialog`-shell editor. Three rendering modes:
198
+ 1. `renderCardEditor` render-prop — full control over the body.
199
+ 2. `editorFields` declarative config — library renders one row per field declaration. Six built-in types: `text`, `textarea`, `select`, `number`, `checkbox`, `priority`. Required-field gating disables Save when text/textarea/number fields are empty.
200
+ 3. Neither — library auto-detects string-typed fields on the item (skipping `id`, `columnKey`, `priority`).
201
+ - **Async save lifecycle.** `onCardSave` returns `void | Promise<void>`. A returned Promise gates dialog close and shows a "Saving…" spinner; a rejected Promise keeps the dialog open with `ctx.error` populated. Consumer is responsible for updating `items` on success (symmetric with `onMove`).
202
+ - Seven new props on `HazoUiKanbanProps<T>`: `editorFields`, `editorPriorities`, `editorTitle`, `renderCardEditor`, `hideEditorFooter`, `onCardSave`, `disableEdit`.
203
+ - Four new public types: `KanbanEditorField`, `KanbanEditorFieldType`, `KanbanEditorCtx<T>`, `KanbanSaveEvent<T>`.
204
+ - Dev-app demo at `/kanban` extended with three new sections (§6 default editor, §7 declarative editor, §8 renderCardEditor override).
205
+
206
+ ### Fixed
207
+ - Suppressed Radix `DialogContent` missing-`Description` warning in `KanbanEditor` by setting `aria-describedby={undefined}` explicitly. Caught during the v2.13.0 smoke test — every editor open emitted a console warning under React strict mode.
208
+
209
+ ### Notes
210
+ - No new CSS variables — the editor uses existing shadcn Dialog tokens and input/select/checkbox/textarea/button variables.
211
+ - The pencil icon is hidden when `disableEdit={true}` OR `onCardSave` is not provided (no point letting the user edit if nothing happens on save).
212
+ - The pencil's `pointerdown`/`mousedown`/`keydown` events stop propagation so dnd-kit's PointerSensor doesn't interpret the click as the start of a drag.
213
+ - One shared `<KanbanEditor>` instance mounts at the orchestrator level, not one Dialog per card.
214
+ - No `SETUP_CHECKLIST.md` changes (no new setup steps for consumers).
215
+
216
+ ## [2.12.0] - 2026-05-16
217
+
218
+ ### Added
219
+ - **`HazoUiBoard`** — drag-drop kanban board primitive with mobile tab-strip / desktop column-grid layout switch via pure CSS. Wraps `@dnd-kit/*` internally; consumers see only the `HazoUi*` API. Optimistic-overlay state model: `items` is consumer-controlled; failed moves snap back via `handle.revert()` carried on the `BoardMoveEvent`.
220
+ - **`HazoUiBoardFilter`** — controlled-or-uncontrolled filter bar with free-text search, multi-select category chips (`ToggleGroup type="multiple"`), and single-select priority chips. Decoupled from `HazoUiBoard` — consumer applies the filter to `items` before passing in.
221
+ - **`applyBoardFilter`** — pure helper that filters `items` by search / categories / priority. Convenience export; consumers can swap in their own filter function.
222
+ - Keyboard navigation per `@dnd-kit/accessibility` patterns (Tab focus → Space pick up → Arrow keys → Space drop → Esc cancel).
223
+ - Custom screen-reader announcements that name the action and column; override-able via the `announcements` prop.
224
+ - New CSS custom properties in both `src/styles/globals.css` (dev-app input) and `src/styles/hazo-ui.css` (shipped to `dist/styles.css`): `--hazo-board-priority-p0..p3` (HSL channels), `--hazo-board-card-bg`, `--hazo-board-card-border`, `--hazo-board-column-gap`. Apps can re-theme by overriding any variable in their cascade.
225
+ - Dev-app demo at `dev-app/app/board/page.tsx` (route `/board`) with 5 sections: default kanban, controlled filter, uncontrolled filter, keyboard-only walkthrough, and optimistic-update + revert.
226
+
227
+ ### Fixed (during the v2.12.0 cycle)
228
+ - **dev-app `next build` failure on pre-existing UI components.** `dev-app/package.json` pinned `@types/react` to `18.3.28` (workspace-root version) so type-check no longer fails in `src/components/ui/button-group.tsx` and `toggle-group.tsx` with "Type 'bigint' is not assignable to type 'ReactNode'". Pre-existing infrastructure issue surfaced during board demo wiring.
229
+
230
+ ### Notes
231
+ - Sub-components `BoardColumn` and `BoardCard` are intentionally internal — the data-driven `HazoUiBoard` API (`columns`, `items`, `renderCard`) is the only entry point.
232
+ - `HazoUiBoard` passes a `React.useId()`-derived value as `DndContext`'s `id` prop so multiple boards on one page produce stable, SSR-deterministic `aria-describedby` IDs (no hydration warnings).
233
+ - No new dependencies (`@dnd-kit/*` was already in `dependencies` from prior versions).
234
+ - No `SETUP_CHECKLIST.md` changes (no new setup steps for consumers).
235
+
8
236
  ## [2.11.0] - 2026-05-16
9
237
 
10
238
  ### Fixed