hazo_ui 6.10.0 → 6.11.2

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,129 @@ 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
+ ## v6.11.2 (2026-09-01)
9
+
10
+ ### Fixed — `hazo_state` peer dependency range never resolved
11
+
12
+ `peerDependencies.hazo_state` was `^0.5.0`, but `hazo_state` never published a
13
+ 0.5.x release on the registry (its version history jumps `0.4.0` → `0.6.0`
14
+ directly). Any fresh install of `hazo_ui` requiring registry resolution of
15
+ this peer range failed with `ETARGET`. Only symbol used from `hazo_state` is
16
+ the `StateLevel` type, unchanged since `0.4.0`, so the range is corrected to
17
+ `^0.6.0` with no consumer-facing behavior change.
18
+
19
+ ## v6.11.1 (2026-08-25)
20
+
21
+ ### Added — `data-lane-key` on `HazoUiKanban` swimlane hooks
22
+
23
+ `KanbanColumn` already exposes `data-column-key` on its shell so a consumer
24
+ can style/select one column via CSS (`cls_hazo_kanban_column[data-column-key='...']`,
25
+ pubsos's own board chrome). Lanes had no equivalent — the per-lane row
26
+ wrapper, heading and collapsed strip carried only the shared
27
+ `cls_hazo_kanban_lane*` hooks, with no way to target one specific lane (e.g.
28
+ a "Marked Items" lane that should read louder than an ordinary tag lane)
29
+ without matching on lane title text. `data-lane-key={lane.key}` is now on
30
+ the lane row wrapper (`cls_hazo_kanban_lane`), the heading
31
+ (`cls_hazo_kanban_lane_head`) and the collapsed strip
32
+ (`cls_hazo_kanban_lane_strip`) — same attribute name and placement pattern
33
+ as the column hook.
34
+
35
+ ## v6.11.0 (2026-08-24)
36
+
37
+ ### Added — `LocalePicker` + `createPackageT` i18n infrastructure (FR-030)
38
+
39
+ First of the i18n-prerequisite work for the still-unbuilt `hazo_i18n`
40
+ package (see `00.lib/design/PRD-hazo_i18n.md`, §2.1 / §11 / §16.3).
41
+ `hazo_i18n` is headless by design, so the locale picker component lives
42
+ here; `hazo_ui` also starts routing its own ~150 baked-in English strings
43
+ through an i18n bridge instead of hardcoding them. Everything in this
44
+ release works identically whether `hazo_i18n` is installed or not —
45
+ **an English-only consumer sees zero change** (same text, same markup, same
46
+ `en-US` number/currency formatting).
47
+
48
+ - **New `<LocalePicker>`** (`hazo_ui` and the slim `hazo_ui/locale-picker`
49
+ entry) — a standard language-switcher dropdown, purely prop-driven, no
50
+ `hazo_i18n` dependency:
51
+ ```tsx
52
+ <LocalePicker
53
+ variant="dropdown" // "dropdown" | "inline" | "compact"
54
+ show="auto" // "auto" (renders null below 2 locales) | "always" | "never"
55
+ display="native" // "native" | "native+code" | "code"
56
+ flags={false}
57
+ alternates={{ en: "https://x.com/", de: "https://x.com/de" }}
58
+ />
59
+ ```
60
+ Built on the same Radix `DropdownMenu`/`DropdownMenuRadioGroup` primitives
61
+ as `src/components/ui/dropdown-menu.tsx`. Every option is a real `<a href>`
62
+ (via Radix `asChild`), not a JS-only click handler, so it stays crawlable
63
+ and middle-click-openable — options can only ever point at URLs present in
64
+ the `alternates` map (the same map a consumer already builds for `<head>`
65
+ hreflang). Native language names come from `Intl.DisplayNames`,
66
+ instantiated per-language in that language's own locale, so German shows
67
+ "Deutsch" and Swedish shows "svenska" — never an English name. `flags:
68
+ true` renders inline SVG (a small embedded set for common locales, a
69
+ generic globe icon otherwise) — **never emoji**, since Segoe UI Emoji ships
70
+ no regional-indicator glyphs and flag emoji render as broken letter-boxes
71
+ on Windows Chrome/Edge. `lang={code}` is set on both the trigger and each
72
+ option.
73
+
74
+ - **New `createPackageT(namespace, fallbackCatalog)`**
75
+ (`src/lib/create_package_t.ts`) — the i18n bridge every `hazo_*` package
76
+ will eventually adopt for its own strings. Probes for `hazo_i18n` once via
77
+ `optional_import("hazo_i18n")` from `hazo_core/client` (the same
78
+ optional-peer pattern used elsewhere in this package); the returned `t()`
79
+ delegates to `hazo_i18n`'s translator when present and resolvable, and
80
+ otherwise looks up the key in the bundled fallback catalog with simple
81
+ `{{var}}` interpolation. Pure function, no React dependency. Also exports
82
+ `resolvePackageLocale(defaultLocale)`, used by the table's number
83
+ formatting (see below) — it only ever overrides the default when
84
+ `hazo_i18n` exposes a synchronous, SSR/CSR-identical locale getter, and
85
+ falls back to the static default otherwise, so it can never introduce a
86
+ hydration mismatch.
87
+
88
+ - **`src/locales/en.json`** — the bundled English catalog, ~69 keys covering
89
+ the four files below.
90
+
91
+ - **Wired `t()` into the four files that hold 55%+ of this package's
92
+ translatable strings** (per the FR's own survey):
93
+ `hazo_ui_table/index.tsx` (pagination: "Showing X–Y of Z", Prev/Next +
94
+ their aria-labels, search placeholder, sort tooltip, empty/no-results/error
95
+ states), `hazo_ui_rte/toolbar/toolbar.tsx` (all 28 `tooltip=` values —
96
+ Bold, Italic, Undo, Align left, etc. — popover body copy is deferred, not
97
+ in scope), `hazo_ui_rte/types.ts` (new `get_translated_block_types()`
98
+ helper for the block-type dropdown's 9 labels; `BLOCK_TYPES` itself is
99
+ unchanged for any direct consumer), and
100
+ `hazo_ui_multi_filter_dialog/index.tsx` (dialog title/description,
101
+ field-input placeholders, On/Off, Active filters tooltip, footer buttons,
102
+ ~21 keys total). Every existing `labels`/default-prop override
103
+ (`HazoUiTableProps.empty`/`.noResults`, `booleanLabels`, the dialog's
104
+ `title`/`description`, etc.) still takes precedence over `t()` — verified
105
+ by regression tests. The remaining ~40 strings across the rest of the
106
+ package are explicitly deferred to `hazo_i18n`'s own creation.
107
+
108
+ - **Number-locale threading** — `hazo_ui_table`'s `DEFAULT_NUMBER_LOCALE`
109
+ pin now resolves through `resolvePackageLocale("en-US")` instead of a bare
110
+ constant. **Behavior for everyone without `hazo_i18n` installed is
111
+ unchanged** (still pinned to `"en-US"`, still hydration-safe by
112
+ construction); this only starts mattering once `hazo_i18n` exists and
113
+ exposes a synchronous locale getter. Date formatting (`date-fns`'s
114
+ `"MMM d, yyyy"` pattern in the table and the filter dialog) is unchanged —
115
+ deferred, since locale-aware date formatting needs a `date-fns/locale`
116
+ import per BCP-47 code, out of scope for this pass.
117
+
118
+ - **`hazo_i18n` added as an optional peer** (`peerDependencies` +
119
+ `peerDependenciesMeta.hazo_i18n.optional: true`) — it doesn't exist on npm
120
+ yet, so this is forward-declaration; `optional_import` means a missing or
121
+ unpublished `hazo_i18n` never breaks `npm install` or the build.
122
+
123
+ - **New test infrastructure** — this package had no unit test runner before
124
+ this release. Added `jest.config.cjs` (ESM + ts-jest + jsdom, mirrors
125
+ `hazo_theme`'s config) and `npm run test`; 32 tests across 4 files cover
126
+ `createPackageT`'s fallback/interpolation/delegation behavior,
127
+ `LocalePicker`'s auto-hide/real-`<a>`/flag/no-emoji/precedence rules, the
128
+ table's translated-catalog wiring and empty/noResults override precedence,
129
+ and an SSR-vs-CSR hydration-safety check for formatted currency.
130
+
8
131
  ## v6.10.0 (2026-08-15)
9
132
 
10
133
  ### Added — `HazoUiKanban.renderColumnHeaderExtra`