hazo_ui 6.0.0 → 6.1.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,14 @@ 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.1.0 (unreleased)
9
+
10
+ ### New
11
+ - feat: add `permissionToast` helper (FR-017) — an opinionated wrapper around
12
+ `errorToast` that standardizes permission-failure toasts (fixed "Permission
13
+ required" title, composed missing-permission description, optional action
14
+ button). Exported alongside `PermissionToastOptions` from `hazo_ui`.
15
+
8
16
  ## v6.0.0 (2026-07-11)
9
17
 
10
18
  Major — the P1 hazo_theme rehome. hazo_ui stops owning theme tokens, preset, and provider;
package/README.md CHANGED
@@ -226,7 +226,7 @@ Lightweight, opinionated components for the four ubiquitous async states: **load
226
226
  - **[ErrorPage](#errorpage)** - Full-page error fallback with title, description, error code tag, correlation id, and CTAs.
227
227
  - **[LoadingTimeout](#loadingtimeout)** - Wraps a loading region and escalates messaging at 5s / 15s / 30s thresholds before showing a retry banner.
228
228
  - **[ProgressiveImage](#progressiveimage)** - Three-stage image render: grey placeholder → blurred LQIP → sharp final image.
229
- - **[HazoUiToaster + toast helpers](#toasts-hazouitoaster--successtoast--errortoast)** - `sonner`-backed toaster with `successToast()` and `errorToast()` imperative helpers.
229
+ - **[HazoUiToaster + toast helpers](#toasts-hazouitoaster--successtoast--errortoast)** - `sonner`-backed toaster with `successToast()`, `errorToast()`, and `permissionToast()` imperative helpers.
230
230
  - **[useLoadingState](#useloadingstate)** hook - `{ isLoading, setLoading, withLoading }` with an async wrapper.
231
231
  - **[useErrorDisplay](#useerrordisplay)** hook - Passive `{ error, setError, clearError }` that coerces `Error` instances to strings.
232
232
 
@@ -3443,6 +3443,29 @@ try { await sync(); } catch (e) {
3443
3443
  | `duration` | `number` (ms) | `3000` success / `5000` error |
3444
3444
  | `action` | `{ label: string; onClick: () => void }` | — |
3445
3445
 
3446
+ **`permissionToast(opts: PermissionToastOptions)`** — an opinionated wrapper around
3447
+ `errorToast` for permission-failure UX. Always titles the toast `"Permission required"`
3448
+ and composes a description from the missing permission key(s) (and optional human
3449
+ descriptions), so every "you can't do that" moment in the app reads consistently:
3450
+
3451
+ ```tsx
3452
+ import { permissionToast } from "hazo_ui";
3453
+
3454
+ permissionToast({
3455
+ missingPermissions: ["env.migrate"],
3456
+ descriptions: { "env.migrate": "Migrate environments" },
3457
+ action: { label: "Request access", onClick: () => requestAccess() },
3458
+ });
3459
+ // → "Permission required" / "Missing: `env.migrate` — Migrate environments"
3460
+ ```
3461
+
3462
+ | Prop | Type | Default |
3463
+ |---|---|---|
3464
+ | `missingPermissions` | `string[]` | **required** |
3465
+ | `descriptions` | `Record<string, string>` | — |
3466
+ | `action` | `{ label: string; onClick: () => void }` | — |
3467
+ | `duration` | `number` (ms) | `5000` |
3468
+
3446
3469
  Also exports `rawToast` (re-export of sonner's `toast`) for advanced use cases.
3447
3470
 
3448
3471
  ### useWakeLock / use_wake_lock
package/dist/index.cjs CHANGED
@@ -8819,6 +8819,23 @@ function errorToast({ title, description, duration = 5e3, action }) {
8819
8819
  action: action ? { label: action.label, onClick: action.onClick } : void 0
8820
8820
  });
8821
8821
  }
8822
+ function permissionToast({
8823
+ missingPermissions,
8824
+ descriptions,
8825
+ action,
8826
+ duration = 5e3
8827
+ }) {
8828
+ const description = missingPermissions.length === 0 ? "You do not have permission to perform this action." : `Missing: ${missingPermissions.map((key) => {
8829
+ const label = descriptions?.[key];
8830
+ return label ? `\`${key}\` \u2014 ${label}` : `\`${key}\``;
8831
+ }).join("; ")}`;
8832
+ return errorToast({
8833
+ title: "Permission required",
8834
+ description,
8835
+ action,
8836
+ duration
8837
+ });
8838
+ }
8822
8839
  function useLoadingState(initial = false) {
8823
8840
  const [isLoading, setLoading] = React27.useState(initial);
8824
8841
  const withLoading = React27.useCallback(async (fn) => {
@@ -12135,6 +12152,7 @@ exports.get_logger = get_logger;
12135
12152
  exports.isLucideValue = isLucideValue;
12136
12153
  exports.median = median;
12137
12154
  exports.parse_commands_from_text = parse_commands_from_text;
12155
+ exports.permissionToast = permissionToast;
12138
12156
  exports.pick_x_label_indices = pick_x_label_indices;
12139
12157
  exports.reset_hazo_ui_config = reset_hazo_ui_config;
12140
12158
  exports.resolve_animation_classes = resolve_animation_classes;