hazo_ui 4.9.0 → 5.1.1

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,144 @@ 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
+ ## v5.1.0 (2026-07-10)
9
+
10
+ ### New
11
+ - **`HazoUiKanban` card editor: `richtext` field type** — `editorFields` now
12
+ accepts `type: 'richtext'`, which renders the package's existing
13
+ `HazoUiRte` (`hazo_ui_rte`) in place of a plain text input. No new
14
+ dependency — TipTap was already required by this package. Binds to a
15
+ string HTML key on the item; `on_change` writes `RteOutput.html` back
16
+ into the draft. As with `select`/`checkbox`, `required` gating is not
17
+ honored for `richtext` (an "empty" RTE still emits `<p></p>`, not `""`).
18
+ Auto-detected fields are unaffected — `richtext` is opt-in via
19
+ `editorFields` only.
20
+ - **`HazoUiKanban`: double-click to open the card editor** — double-clicking
21
+ a card now opens the same editor as the pencil icon, gated by the same
22
+ `showEdit`/`onEditRequest` props (no new prop). PointerSensor's 5px drag
23
+ activation distance means this doesn't interfere with drag-and-drop.
24
+
25
+ ## v5.0.0 (2026-07-09)
26
+
27
+ ### BREAKING — theming rehomed onto hazo_theme
28
+ hazo_ui no longer owns theme tokens, a Tailwind preset, or its own theme
29
+ provider — `hazo_theme` is now the single source, and is a **required** peer
30
+ dependency (was optional).
31
+
32
+ - **Removed exports:** `./styles.css` and `./tailwind-preset` package exports
33
+ are gone (`dist/styles.css`, `tailwind.preset.js` no longer ship). Import
34
+ `hazo_theme/theme.css` (+ optionally a `hazo_theme/themes/<name>.css` brand
35
+ palette) in your app's globals instead of `hazo_ui/styles.css`.
36
+ - **`useTheme()` return shape changed:** `{ theme, setTheme, resolvedTheme,
37
+ toggleTheme }` → `{ mode, setMode, resolvedMode, toggleMode, themeSet,
38
+ setThemeSet }`. `HazoThemeProvider`'s `defaultTheme` prop is now
39
+ `defaultMode`; add `defaultThemeSet` to opt into a shipped brand palette.
40
+ `Theme`/`ThemeProviderProps`/`ThemeContextValue` types are removed — use
41
+ `ThemeMode`/`HazoThemeProviderProps`/`HazoThemeContextValue` from
42
+ `hazo_theme/client` (re-exported from the `hazo_ui` root).
43
+ - **New export:** `ThemeSetPicker`, re-exported from `hazo_theme/client`,
44
+ lets consumers switch between shipped theme-sets (`indigo-sunset`,
45
+ `ops-dark`, `soft-studio`, ...) at runtime.
46
+ - **Persisted-preference reset (one-time):** the localStorage key changed
47
+ from `"theme"` to `"hazo-theme"` (with `-mode`/`-set` suffixes), so a
48
+ user's saved theme choice resets to `"system"` once after upgrading.
49
+ - **hazo_ui's own kanban tokens deleted** (`--hazo-kanban-*` in
50
+ `src/styles/globals.css`) — now sourced from `hazo_theme`'s Tier-1 tokens
51
+ (`hazo_theme@^0.2.0`), same values, zero visual change, but consumers
52
+ MUST import `hazo_theme/theme.css` for kanban components to render with
53
+ the intended colors (previously baked into `hazo_ui`'s own CSS).
54
+ - **Migration:** bump to `hazo_theme@^0.2.0` (now required, not optional),
55
+ swap `hazo_ui/styles.css` → `hazo_theme/theme.css` in your globals, and
56
+ update any `useTheme()`/`HazoThemeProvider` call sites for the
57
+ `theme`→`mode` rename.
58
+
59
+ ## Unreleased
60
+
61
+ ### New
62
+ - **`Logo`, `AppHeader`, `AppFooter` chrome components** (framework-neutral,
63
+ `"use client"`) — consume hazo_theme's `BrandIdentity` contract (type-only
64
+ import) plus the new `footer-public-*`/`footer-app-*` chrome tokens:
65
+ - `Logo({ logoUrl?, logoUrlDark?, appTitle?, href?, height?, className?,
66
+ imgClassName? })` — renders the light/dark logo image (swapped via
67
+ `dark:hidden`/`dark:block`), falling back to `appTitle` as text when no
68
+ `logoUrl` is set. Prop names intentionally mirror `BrandIdentity`'s fields
69
+ so a caller can spread an identity object directly: `<Logo {...identity}
70
+ />`.
71
+ - `AppHeader({ identity?, homeHref?, navItems?, actions?, className? })` — a
72
+ `bg-navbar`/`text-navbar-fg` header bar wrapping `Logo` plus nav/actions
73
+ slots.
74
+ - `AppFooter({ variant: 'public' | 'app', footer?, identity?, className? })`
75
+ — `'app'` renders the thin `bg-footer-app` strip (copyright + one link
76
+ row); `'public'` renders the taller multi-column `bg-footer-public` block
77
+ (brand row, link columns, social links), reading from `footer` or falling
78
+ back to `identity.footer[variant]`.
79
+ - All three are new exports from the package root; `hazo_theme` stays an
80
+ optional peer — the components don't import runtime code from it, only
81
+ the `BrandIdentity`/`FooterConfig` types.
82
+ - **`safeHref(url?: string): string | undefined`** exported from the package
83
+ root — scheme-allowlist for admin-configurable hrefs (`http://`, `https://`,
84
+ `mailto:`, or a same-origin `/path` that isn't protocol-relative `//host`;
85
+ anything else, including `javascript:`/`data:`, returns `undefined`). Every
86
+ `<a href>` sink inside the new chrome components (footer links, social
87
+ links) runs through it — XSS hardening for hrefs sourced from
88
+ admin-editable branding data.
89
+ - **`HazoUiDialog` header bar is now token-driven** — the header bar
90
+ background/foreground (previously hardcoded `#1e293b` background / white
91
+ text) now default to hazo_theme's `--dialog-header-bar-bg` /
92
+ `--dialog-header-bar-fg` tokens, and respect the existing per-variant
93
+ tinting (`headerColor`/`kind`) the same way the rest of the dialog does.
94
+ - **`HazoUiDialog` `kind` prop** (PRD hazo_theme §5.7) — orthogonal rendering/behavior
95
+ profile: `'form' | 'confirm' | 'status' | 'content'`. `kind` is a discriminated
96
+ union on `HazoUiDialogProps`: `title` is a required `string` for `'form'`/`'confirm'`,
97
+ and stays optional (defaulting to `"Action required"`) for `'status'`/`'content'`/
98
+ omitted — omitting `kind` entirely is byte-for-byte the pre-existing default
99
+ behavior (regression guard, verified via `npm run build` + `type-check`).
100
+ - `'form'` — comfortable body/label typography via the hazo_theme
101
+ `--dialog-body-size` / `--dialog-label-size` tokens.
102
+ - `'confirm'` — the compact centered-card layout previously hardcoded into
103
+ `HazoUiConfirmDialog` (see below).
104
+ - `'status'` — tinted header (via `--dialog-<variant>-bg/-fg`) with a single
105
+ acknowledge button (`showCancelButton=false`, `actionButtonText="OK"` by
106
+ default); `closeOnConfirm` defaults to `true` (self-closing) for this kind.
107
+ - `'content'` — unchanged sticky header/footer + scrollable body (this was
108
+ already the default structure).
109
+ - Added optional peer dependency `hazo_theme@^0.1.0` (`peerDependenciesMeta.hazo_theme.optional = true`).
110
+ hazo_ui does not import from hazo_theme; the `--dialog-*` CSS custom
111
+ properties referenced below only resolve when the CONSUMING app imports
112
+ `hazo_theme/tokens.css`.
113
+
114
+ ### Changed
115
+ - **`HazoUiConfirmDialog` is now a thin wrapper** over `<HazoUiDialog kind="confirm">`.
116
+ Its exported `HazoUiConfirmDialogProps` interface and `ConfirmDialogVariant` type
117
+ are UNCHANGED — zero prop-level breaking changes for existing consumers
118
+ (verified: `hazo_pay`'s `billing_admin_panel.tsx` and `hazo_config`'s
119
+ `app_config_list_editor.tsx` both still build with no changes on their end).
120
+ One documented behavior simplification: the old component allowed
121
+ independently-colored `accentColor` (border) vs. `confirmButtonColor` (button);
122
+ the new wrapper folds both into a single accent (`confirmButtonColor` wins if
123
+ both are set), since no known consumer relied on divergent values.
124
+ - **`VARIANT_PRESETS` (dialog) / `CONFIRM_VARIANT_PRESETS` (confirm dialog,
125
+ now deleted) hardcoded RGB → hazo_theme `--dialog-*` tokens.** This is a
126
+ **visual-only change** — flag it as a **major version bump** on the next
127
+ publish, since dialog/confirm-dialog appearance shifts for any consumer.
128
+ - Consumers that already import `hazo_theme/tokens.css` get the intended,
129
+ theme-consistent look automatically (dark/light + brand theme-sets).
130
+ - Consumers that do NOT import `hazo_theme/tokens.css` degrade gracefully:
131
+ an undefined CSS custom property used inside `hsl(var(--undefined-var))`
132
+ (or referenced directly, for the pre-wrapped `--dialog-<variant>-bg/-fg`
133
+ tokens) produces an invalid color value, which browsers simply ignore —
134
+ falling back to the previous/inherited value (e.g. transparent background,
135
+ inherited text color) rather than crashing or rendering `red`/broken
136
+ styles. Net effect: variant tinting silently disappears, dialogs still
137
+ render and function correctly. **Action for consumers wanting the
138
+ intended look: import `hazo_theme/tokens.css`.**
139
+ - hazo_theme exposes exactly one bg + one fg token per status (no separate
140
+ "header" vs. "description" shade), so the old two-tone split-header effect
141
+ is flattened to a single shade per variant.
142
+ - `kind="status"`/`kind="confirm"` at `variant="default"` (no per-status
143
+ token pair exists for "default") fall back to a neutral tint derived from
144
+ `--dialog-border` / `--dialog-fg` instead of leaving the header untinted.
145
+
8
146
  ## v4.9.0 (2026-07-06)
9
147
 
10
148
  ### New
package/README.md CHANGED
@@ -3707,12 +3707,19 @@ on hover/focus). Clicking it opens a `HazoUiDialog` editor:
3707
3707
 
3708
3708
  Field types: `text`, `textarea`, `select`, `number`, `checkbox`,
3709
3709
  `priority` (a select pre-populated with `editorPriorities` —
3710
- defaults to `["P0","P1","P2","P3"]`).
3710
+ defaults to `["P0","P1","P2","P3"]`), `status` (a select pre-populated
3711
+ from `columns`, bound to `columnKey`), and `richtext` (renders the
3712
+ package's `HazoUiRte` rich text editor — binds to a string HTML key;
3713
+ `required` gating is not honored for this type, same as `select`/
3714
+ `checkbox`).
3711
3715
 
3712
3716
  If you don't pass `editorFields`, the library auto-detects all
3713
3717
  string-valued fields on the item (except `id`, `columnKey`, `priority`)
3714
3718
  and renders each as a text input with a humanized label.
3715
3719
 
3720
+ Besides the pencil icon, **double-clicking a card** also opens the
3721
+ editor — same `onCardSave`/`editorFields` config, no extra prop needed.
3722
+
3716
3723
  #### Custom form via renderCardEditor
3717
3724
 
3718
3725
  When the declarative config isn't enough, replace the dialog body