tempest-react-sdk 0.24.0 → 0.25.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.
Files changed (106) hide show
  1. package/README.md +11 -3
  2. package/dist/charts/AreaChart.cjs +1 -1
  3. package/dist/charts/AreaChart.cjs.map +1 -1
  4. package/dist/charts/AreaChart.js +7 -7
  5. package/dist/charts/AreaChart.js.map +1 -1
  6. package/dist/charts/BarChart.cjs +1 -1
  7. package/dist/charts/BarChart.cjs.map +1 -1
  8. package/dist/charts/BarChart.js +7 -7
  9. package/dist/charts/BarChart.js.map +1 -1
  10. package/dist/charts/LineChart.cjs +1 -1
  11. package/dist/charts/LineChart.cjs.map +1 -1
  12. package/dist/charts/LineChart.js +6 -6
  13. package/dist/charts/LineChart.js.map +1 -1
  14. package/dist/charts/PieChart.cjs +1 -1
  15. package/dist/charts/PieChart.cjs.map +1 -1
  16. package/dist/charts/PieChart.js +6 -6
  17. package/dist/charts/PieChart.js.map +1 -1
  18. package/dist/charts/RadarChart.cjs +1 -1
  19. package/dist/charts/RadarChart.cjs.map +1 -1
  20. package/dist/charts/RadarChart.js +6 -6
  21. package/dist/charts/RadarChart.js.map +1 -1
  22. package/dist/charts/palette.cjs +1 -1
  23. package/dist/charts/palette.cjs.map +1 -1
  24. package/dist/charts/palette.js +19 -2
  25. package/dist/charts/palette.js.map +1 -1
  26. package/dist/charts/use-chart-colors.cjs +2 -0
  27. package/dist/charts/use-chart-colors.cjs.map +1 -0
  28. package/dist/charts/use-chart-colors.js +29 -0
  29. package/dist/charts/use-chart-colors.js.map +1 -0
  30. package/dist/charts.cjs +1 -1
  31. package/dist/charts.d.ts +59 -10
  32. package/dist/charts.js +8 -7
  33. package/dist/components/AvatarGroup/AvatarGroup.cjs +2 -0
  34. package/dist/components/AvatarGroup/AvatarGroup.cjs.map +1 -0
  35. package/dist/components/AvatarGroup/AvatarGroup.js +39 -0
  36. package/dist/components/AvatarGroup/AvatarGroup.js.map +1 -0
  37. package/dist/components/AvatarGroup/AvatarGroup.module.cjs +2 -0
  38. package/dist/components/AvatarGroup/AvatarGroup.module.cjs.map +1 -0
  39. package/dist/components/AvatarGroup/AvatarGroup.module.js +16 -0
  40. package/dist/components/AvatarGroup/AvatarGroup.module.js.map +1 -0
  41. package/dist/components/Lightbox/Lightbox.cjs +2 -0
  42. package/dist/components/Lightbox/Lightbox.cjs.map +1 -0
  43. package/dist/components/Lightbox/Lightbox.js +148 -0
  44. package/dist/components/Lightbox/Lightbox.js.map +1 -0
  45. package/dist/components/Lightbox/Lightbox.module.cjs +2 -0
  46. package/dist/components/Lightbox/Lightbox.module.cjs.map +1 -0
  47. package/dist/components/Lightbox/Lightbox.module.js +21 -0
  48. package/dist/components/Lightbox/Lightbox.module.js.map +1 -0
  49. package/dist/components/SignaturePad/SignaturePad.cjs +2 -0
  50. package/dist/components/SignaturePad/SignaturePad.cjs.map +1 -0
  51. package/dist/components/SignaturePad/SignaturePad.js +115 -0
  52. package/dist/components/SignaturePad/SignaturePad.js.map +1 -0
  53. package/dist/components/SignaturePad/SignaturePad.module.cjs +2 -0
  54. package/dist/components/SignaturePad/SignaturePad.module.cjs.map +1 -0
  55. package/dist/components/SignaturePad/SignaturePad.module.js +11 -0
  56. package/dist/components/SignaturePad/SignaturePad.module.js.map +1 -0
  57. package/dist/components/Stepper/Stepper.cjs +1 -1
  58. package/dist/components/Stepper/Stepper.cjs.map +1 -1
  59. package/dist/components/Stepper/Stepper.js +43 -19
  60. package/dist/components/Stepper/Stepper.js.map +1 -1
  61. package/dist/components/Stepper/Stepper.module.cjs +1 -1
  62. package/dist/components/Stepper/Stepper.module.cjs.map +1 -1
  63. package/dist/components/Stepper/Stepper.module.js +6 -3
  64. package/dist/components/Stepper/Stepper.module.js.map +1 -1
  65. package/dist/components/TreeView/TreeView.cjs +2 -0
  66. package/dist/components/TreeView/TreeView.cjs.map +1 -0
  67. package/dist/components/TreeView/TreeView.js +124 -0
  68. package/dist/components/TreeView/TreeView.js.map +1 -0
  69. package/dist/components/TreeView/TreeView.module.cjs +2 -0
  70. package/dist/components/TreeView/TreeView.module.cjs.map +1 -0
  71. package/dist/components/TreeView/TreeView.module.js +17 -0
  72. package/dist/components/TreeView/TreeView.module.js.map +1 -0
  73. package/dist/components/Wizard/Wizard.cjs +2 -0
  74. package/dist/components/Wizard/Wizard.cjs.map +1 -0
  75. package/dist/components/Wizard/Wizard.js +111 -0
  76. package/dist/components/Wizard/Wizard.js.map +1 -0
  77. package/dist/components/Wizard/Wizard.module.cjs +2 -0
  78. package/dist/components/Wizard/Wizard.module.cjs.map +1 -0
  79. package/dist/components/Wizard/Wizard.module.js +10 -0
  80. package/dist/components/Wizard/Wizard.module.js.map +1 -0
  81. package/dist/offline/create-offline-sync.cjs +1 -1
  82. package/dist/offline/create-offline-sync.cjs.map +1 -1
  83. package/dist/offline/create-offline-sync.js +8 -2
  84. package/dist/offline/create-offline-sync.js.map +1 -1
  85. package/dist/styles.css +1 -1
  86. package/dist/tempest-react-sdk.cjs +1 -1
  87. package/dist/tempest-react-sdk.d.ts +605 -2
  88. package/dist/tempest-react-sdk.js +255 -246
  89. package/dist/theme/apply-theme.cjs +2 -0
  90. package/dist/theme/apply-theme.cjs.map +1 -0
  91. package/dist/theme/apply-theme.js +24 -0
  92. package/dist/theme/apply-theme.js.map +1 -0
  93. package/dist/theme/color.cjs +2 -0
  94. package/dist/theme/color.cjs.map +1 -0
  95. package/dist/theme/color.js +130 -0
  96. package/dist/theme/color.js.map +1 -0
  97. package/dist/theme/create-theme.cjs +5 -0
  98. package/dist/theme/create-theme.cjs.map +1 -0
  99. package/dist/theme/create-theme.js +135 -0
  100. package/dist/theme/create-theme.js.map +1 -0
  101. package/dist/theme/theme-presets.cjs +2 -0
  102. package/dist/theme/theme-presets.cjs.map +1 -0
  103. package/dist/theme/theme-presets.js +82 -0
  104. package/dist/theme/theme-presets.js.map +1 -0
  105. package/dist/utilities.css +432 -0
  106. package/package.json +4 -3
@@ -304,6 +304,41 @@ export declare interface AppBarProps extends Omit<HTMLAttributes<HTMLElement>, "
304
304
 
305
305
  export declare type AppBarTone = "surface" | "primary" | "transparent";
306
306
 
307
+ /**
308
+ * Install a generated theme (or raw CSS) into the document.
309
+ *
310
+ * Safe to call outside a browser: with no `document` it is a no-op returning a
311
+ * no-op disposer, so app bootstrap code does not need a `typeof window` guard.
312
+ *
313
+ * @param theme - A {@link GeneratedTheme} from `createTheme`, or CSS text.
314
+ * @param options - Style element id and mount target.
315
+ * @returns A function that removes the injected `<style>` element.
316
+ *
317
+ * @example
318
+ * ```ts
319
+ * import { applyTheme, createTheme, themePresets } from "tempest-react-sdk";
320
+ *
321
+ * const dispose = applyTheme(createTheme(themePresets.violet));
322
+ * // later: dispose();
323
+ * ```
324
+ */
325
+ export declare function applyTheme(theme: GeneratedTheme | string, options?: ApplyThemeOptions): () => void;
326
+
327
+ /** Options for {@link applyTheme}. */
328
+ export declare interface ApplyThemeOptions {
329
+ /**
330
+ * `id` of the managed `<style>` element. Reusing the same id replaces the
331
+ * previous theme; a distinct id lets two themes coexist (e.g. a scoped
332
+ * preview under its own selector). Default `"tempest-theme"`.
333
+ */
334
+ id?: string;
335
+ /**
336
+ * Node the `<style>` is appended to. Default `document.head`. Pass a shadow
337
+ * root to theme a single web component.
338
+ */
339
+ target?: Document | ShadowRoot | HTMLElement;
340
+ }
341
+
307
342
  /**
308
343
  * Compose the Tempest app-wide providers in one place: error boundary →
309
344
  * TanStack Query → theme → i18n. Query and theme are on by default; i18n and
@@ -498,6 +533,55 @@ export declare interface AuthState<TUser> {
498
533
  */
499
534
  export declare function Avatar({ src, alt, name, size, status, className, onClick, }: AvatarProps): JSX.Element;
500
535
 
536
+ /**
537
+ * Overlapping row of avatars with a `+N` overflow chip — participants of a
538
+ * meeting, assignees of a task, members of a team.
539
+ *
540
+ * The whole row is one `role="group"` with a single accessible name, and each
541
+ * avatar's name is exposed as its label. That is deliberate: announcing seven
542
+ * separate images with no relation between them is noise, and the overflow chip
543
+ * carries the remaining count so the total is never hidden from a screen reader.
544
+ *
545
+ * @example
546
+ * ```tsx
547
+ * <AvatarGroup
548
+ * label="Participantes"
549
+ * max={3}
550
+ * items={[
551
+ * { name: "Ada Lovelace", src: ada },
552
+ * { name: "Grace Hopper" },
553
+ * { name: "Alan Turing" },
554
+ * { name: "Edsger Dijkstra" },
555
+ * ]}
556
+ * onOverflowClick={() => setDrawerOpen(true)}
557
+ * />
558
+ * ```
559
+ */
560
+ export declare function AvatarGroup({ items, max, size, label, onOverflowClick, className, }: AvatarGroupProps): JSX.Element;
561
+
562
+ /** One participant of the group. */
563
+ export declare interface AvatarGroupItem {
564
+ /** Image URL. Falls back to initials from `name`. */
565
+ src?: string;
566
+ /** Full name — drives the initials and the accessible label. */
567
+ name: string;
568
+ }
569
+
570
+ export declare interface AvatarGroupProps {
571
+ items: AvatarGroupItem[];
572
+ /** How many avatars to show before collapsing into `+N`. Default `4`. */
573
+ max?: number;
574
+ size?: AvatarSize;
575
+ /** Accessible name of the group, e.g. `"Participantes"`. */
576
+ label?: string;
577
+ /**
578
+ * Called when the `+N` chip is activated — a natural hook for "see all
579
+ * participants". Without it the chip is plain text and not focusable.
580
+ */
581
+ onOverflowClick?: () => void;
582
+ className?: string;
583
+ }
584
+
501
585
  export declare interface AvatarProps {
502
586
  src?: string;
503
587
  alt?: string;
@@ -1134,6 +1218,9 @@ export declare interface CollapsibleProps extends HTMLAttributes<HTMLDivElement>
1134
1218
  children: ReactNode;
1135
1219
  }
1136
1220
 
1221
+ /** A generated tint scale, keyed by step. */
1222
+ export declare type ColorScale = Record<ScaleStep, string>;
1223
+
1137
1224
  /**
1138
1225
  * Combobox — text input with a filterable dropdown of options.
1139
1226
  *
@@ -1311,6 +1398,9 @@ export declare interface ContextMenuProps {
1311
1398
  className?: string;
1312
1399
  }
1313
1400
 
1401
+ /** WCAG 2.x contrast ratio between two hex colors, from `1` to `21`. */
1402
+ export declare function contrastRatio(a: string, b: string): number;
1403
+
1314
1404
  export { Control }
1315
1405
 
1316
1406
  export { Controller }
@@ -1412,6 +1502,19 @@ export declare interface CreateAuthStoreOptions<TUser> {
1412
1502
  initialToken?: string | null;
1413
1503
  }
1414
1504
 
1505
+ /**
1506
+ * Build a ten-step tint scale from a single brand color.
1507
+ *
1508
+ * The input color's hue is kept throughout and its chroma sets the intensity of
1509
+ * the whole ramp, so a muted brand color yields a muted scale instead of being
1510
+ * "corrected" into something the brand never approved.
1511
+ *
1512
+ * @param hex - Any hex color (`#abc` or `#aabbcc`), the intended `500` step.
1513
+ * @param mode - `"light"` for a light→dark ramp, `"dark"` for the inverted ramp
1514
+ * used under `[data-tempest-theme="dark"]`.
1515
+ */
1516
+ export declare function createColorScale(hex: string, mode?: "light" | "dark"): ColorScale;
1517
+
1415
1518
  /**
1416
1519
  * Create a {@link DataProvider} bound to an {@link ApiClient}.
1417
1520
  *
@@ -1974,6 +2077,60 @@ export declare interface CreateTempestAuthOptions<TUser> {
1974
2077
  refreshBody?: (refreshToken: string | null) => unknown;
1975
2078
  }
1976
2079
 
2080
+ /**
2081
+ * Generate `--tempest-*` overrides from a small brand description.
2082
+ *
2083
+ * Only the families you pass are generated; everything else falls through to the
2084
+ * SDK's own tokens, so a theme stays a patch and not a fork of `colors.css`.
2085
+ *
2086
+ * @example
2087
+ * ```ts
2088
+ * import { applyTheme, createTheme } from "tempest-react-sdk";
2089
+ *
2090
+ * const theme = createTheme({
2091
+ * primary: "#7c3aed",
2092
+ * radius: "lg",
2093
+ * chart: ["#7c3aed", "#0ea5e9", "#22c55e", "#f59e0b"],
2094
+ * });
2095
+ *
2096
+ * applyTheme(theme);
2097
+ * ```
2098
+ *
2099
+ * @param options - Brand colors plus optional radius / chart / focus-ring tuning.
2100
+ * @returns The light and dark token maps and the CSS text that carries them.
2101
+ */
2102
+ export declare function createTheme(options?: CreateThemeOptions): GeneratedTheme;
2103
+
2104
+ /** Input for {@link createTheme}. Every field is optional — omitted families keep the built-in tokens. */
2105
+ export declare interface CreateThemeOptions {
2106
+ /** Brand color, used as the `500` step of the primary scale. */
2107
+ primary?: string;
2108
+ /** Neutral color, used as the `500` step of the gray scale (surfaces, borders, text). */
2109
+ gray?: string;
2110
+ /** Success color (`--tempest-success*`). */
2111
+ success?: string;
2112
+ /** Warning color (`--tempest-warning*`). */
2113
+ warning?: string;
2114
+ /** Danger color (`--tempest-danger*`). */
2115
+ danger?: string;
2116
+ /** Info color (`--tempest-info*`). */
2117
+ info?: string;
2118
+ /**
2119
+ * Categorical series colors for `tempest-react-sdk/charts`, in cycle order.
2120
+ * Written to `--tempest-chart-1` … `--tempest-chart-N`, so charts follow the
2121
+ * theme instead of a hardcoded palette.
2122
+ */
2123
+ chart?: string[];
2124
+ /** Corner radius scale. A preset name, or explicit per-step values. */
2125
+ radius?: ThemeRadius | Partial<Record<"xs" | "sm" | "md" | "lg" | "xl" | "2xl", string>>;
2126
+ /** Alpha of `--tempest-focus-ring-color`, derived from the brand color. Default `0.35`. */
2127
+ focusRingAlpha?: number;
2128
+ /** Selector the light tokens are written under. Default `":root"`. */
2129
+ selector?: string;
2130
+ /** Selector the dark tokens are written under. Default `'[data-tempest-theme="dark"]'`. */
2131
+ darkSelector?: string;
2132
+ }
2133
+
1977
2134
  /**
1978
2135
  * Open a WebSocket with automatic exponential-backoff reconnect, optional
1979
2136
  * heartbeat pings, and typed JSON parsing.
@@ -3068,6 +3225,16 @@ export declare interface ForProps<T> {
3068
3225
  fallback?: ReactNode;
3069
3226
  }
3070
3227
 
3228
+ /** A generated theme: token maps per color scheme, plus the CSS text that carries them. */
3229
+ export declare interface GeneratedTheme {
3230
+ /** Light-scheme custom properties, without the leading `--`-less names (keys include `--`). */
3231
+ light: Record<string, string>;
3232
+ /** Dark-scheme custom properties. */
3233
+ dark: Record<string, string>;
3234
+ /** Both blocks rendered as CSS, ready for {@link applyTheme} or a stylesheet. */
3235
+ css: string;
3236
+ }
3237
+
3071
3238
  /**
3072
3239
  * Generate an RFC4122 v4 idempotency key (UUID). Use as the value for an
3073
3240
  * `Idempotency-Key` header on POST/PATCH requests that must not run twice.
@@ -3138,6 +3305,15 @@ export declare interface GetListParams {
3138
3305
  filters?: DataFilters;
3139
3306
  }
3140
3307
 
3308
+ /**
3309
+ * Look up a preset by name.
3310
+ *
3311
+ * @param name - Preset name.
3312
+ * @returns The preset options, or `undefined` when the name is unknown (so a
3313
+ * value coming from `localStorage` or a query string cannot crash boot).
3314
+ */
3315
+ export declare function getThemePreset(name: string): CreateThemeOptions | undefined;
3316
+
3141
3317
  /**
3142
3318
  * Thin wrapper over `@react-oauth/google`'s `<GoogleLogin>` that:
3143
3319
  *
@@ -3258,6 +3434,19 @@ export { HashRouter }
3258
3434
  */
3259
3435
  export declare function haversineKm(origin: Coordinate, destination: Coordinate): number;
3260
3436
 
3437
+ /** Convert a hex color to OKLCH. */
3438
+ export declare function hexToOklch(hex: string): Oklch;
3439
+
3440
+ /** Parse a hex color into sRGB channels in the `0`–`1` range. */
3441
+ export declare function hexToRgb(hex: string): {
3442
+ r: number;
3443
+ g: number;
3444
+ b: number;
3445
+ };
3446
+
3447
+ /** Format a hex color as `rgb(r g b / alpha)`, for focus rings and overlays. */
3448
+ export declare function hexToRgbaString(hex: string, alpha: number): string;
3449
+
3261
3450
  /** Inverse of `<Show>` — hides children when the condition matches. */
3262
3451
  export declare function Hide({ above, below, only, children }: HideProps): ReactNode;
3263
3452
 
@@ -3902,6 +4091,67 @@ export declare interface LDClientLike {
3902
4091
  off?: (event: string, handler: () => void) => void;
3903
4092
  }
3904
4093
 
4094
+ /**
4095
+ * Full-screen image viewer with keyboard navigation.
4096
+ *
4097
+ * `Esc` closes, `←`/`→` walk the gallery, `Home`/`End` jump to the ends. Focus is
4098
+ * trapped inside while open and the page behind is scroll-locked, so the overlay
4099
+ * behaves like the dialog it is instead of a fancy `<div>` the keyboard can escape.
4100
+ *
4101
+ * Only the current image is mounted; neighbours are **preloaded** via `Image()` so
4102
+ * pressing `→` does not flash an empty frame.
4103
+ *
4104
+ * @example
4105
+ * ```tsx
4106
+ * const [open, setOpen] = useState(false);
4107
+ * const [index, setIndex] = useState(0);
4108
+ *
4109
+ * <Lightbox
4110
+ * open={open}
4111
+ * items={photos.map((p) => ({ src: p.url, alt: p.description }))}
4112
+ * index={index}
4113
+ * onIndexChange={setIndex}
4114
+ * onClose={() => setOpen(false)}
4115
+ * />
4116
+ * ```
4117
+ */
4118
+ export declare function Lightbox({ items, open, index, onIndexChange, onClose, showThumbnails, showCounter, loop, closeLabel, previousLabel, nextLabel, className, }: LightboxProps): JSX.Element | null;
4119
+
4120
+ /** One item of the gallery. */
4121
+ export declare interface LightboxItem {
4122
+ /** Full-size image URL. */
4123
+ src: string;
4124
+ /** Alt text. Required: a gallery of unlabeled images is unusable with a screen reader. */
4125
+ alt: string;
4126
+ /** Caption rendered under the image. */
4127
+ caption?: string;
4128
+ /** Thumbnail URL for the strip. Falls back to `src`. */
4129
+ thumbnail?: string;
4130
+ }
4131
+
4132
+ export declare interface LightboxProps {
4133
+ items: LightboxItem[];
4134
+ /** Whether the overlay is open. */
4135
+ open: boolean;
4136
+ /** Index shown while open. Default `0`. */
4137
+ index?: number;
4138
+ onIndexChange?: (index: number) => void;
4139
+ onClose: () => void;
4140
+ /** Renders the thumbnail strip. Default `true` when there is more than one item. */
4141
+ showThumbnails?: boolean;
4142
+ /** Renders the `3 / 12` counter. Default `true`. */
4143
+ showCounter?: boolean;
4144
+ /**
4145
+ * Wrap around at the ends. Default `true` — in a photo viewer, hitting a dead
4146
+ * end at the last image reads as a bug more often than as a boundary.
4147
+ */
4148
+ loop?: boolean;
4149
+ closeLabel?: string;
4150
+ previousLabel?: string;
4151
+ nextLabel?: string;
4152
+ className?: string;
4153
+ }
4154
+
3905
4155
  export { Link }
3906
4156
 
3907
4157
  export declare interface ListOptions<TItem> {
@@ -4701,6 +4951,35 @@ export declare interface OffsetParams {
4701
4951
  ascending?: boolean;
4702
4952
  }
4703
4953
 
4954
+ /**
4955
+ * Color math behind {@link createTheme} — OKLab/OKLCH conversions, tint scale
4956
+ * generation and WCAG contrast picking.
4957
+ *
4958
+ * Everything here is pure and dependency-free: the SDK generates brand ramps at
4959
+ * runtime in the browser, so a color library would be a disproportionate cost
4960
+ * for ~150 lines of well-specified math. OKLCH is used instead of HSL because
4961
+ * HSL lightness is not perceptual — an HSL ramp of a yellow and of a blue at the
4962
+ * same `L` read as wildly different brightness, which is exactly what breaks a
4963
+ * generated palette.
4964
+ */
4965
+ /** A color in the OKLCH space: perceptual lightness, chroma and hue. */
4966
+ export declare interface Oklch {
4967
+ /** Perceptual lightness, `0` (black) to `1` (white). */
4968
+ l: number;
4969
+ /** Chroma (colorfulness). `0` is gray; sRGB rarely exceeds `~0.37`. */
4970
+ c: number;
4971
+ /** Hue angle in degrees, `0`–`360`. */
4972
+ h: number;
4973
+ }
4974
+
4975
+ /**
4976
+ * Convert OKLCH to a hex color, reducing chroma until the result fits sRGB.
4977
+ *
4978
+ * Lightness and hue are preserved: desaturating is far less noticeable than
4979
+ * shifting either of them, and a naive channel clamp would do both.
4980
+ */
4981
+ export declare function oklchToHex(color: Oklch): string;
4982
+
4704
4983
  /**
4705
4984
  * Create a new object with the given `keys` removed from `obj`.
4706
4985
  *
@@ -4785,7 +5064,12 @@ export declare interface OutboxEntry<TPayload = unknown> {
4785
5064
  op: OutboxOp;
4786
5065
  /** Primary key of the record the mutation targets. */
4787
5066
  recordId: string;
4788
- /** Epoch milliseconds when the mutation was queued. */
5067
+ /**
5068
+ * Epoch milliseconds when the mutation was queued, and the FIFO sort key for
5069
+ * `listPending()` and the delivery loop. Strictly increasing per engine
5070
+ * instance: entries queued inside the same millisecond are spaced by 1ms so
5071
+ * the order never depends on how the index breaks a tie.
5072
+ */
4789
5073
  enqueuedAt: number;
4790
5074
  /** How many delivery attempts have been made so far. */
4791
5075
  attempts: number;
@@ -5351,6 +5635,29 @@ export declare interface RatingStarsProps {
5351
5635
  className?: string;
5352
5636
  }
5353
5637
 
5638
+ /**
5639
+ * Pick the readable foreground for a background, by contrast ratio.
5640
+ *
5641
+ * Used for `--tempest-primary-foreground`: a generated brand color can land
5642
+ * anywhere on the lightness axis, and hardcoding white would silently produce
5643
+ * unreadable buttons for light brands (yellow, lime, cyan).
5644
+ */
5645
+ export declare function readableForeground(background: string, light?: string, dark?: string): string;
5646
+
5647
+ /**
5648
+ * Read a token's computed value from an element (default: `<html>`).
5649
+ *
5650
+ * Useful to bridge CSS tokens into JS that cannot take a `var()` — canvas
5651
+ * drawing, chart libraries that set SVG attributes, `<meta name="theme-color">`.
5652
+ *
5653
+ * @param name - Token name, with or without the leading `--`.
5654
+ * @param element - Element to resolve against. Omit for `document.documentElement`;
5655
+ * an explicit `null` (a ref that has not attached yet) reads nothing rather than
5656
+ * silently falling back to the root, whose value may be a different theme.
5657
+ * @returns The trimmed value, or `""` when unset or outside a browser.
5658
+ */
5659
+ export declare function readThemeToken(name: string, element?: Element | null): string;
5660
+
5354
5661
  export { redirect }
5355
5662
 
5356
5663
  /** Recommended refetch intervals (milliseconds). */
@@ -5472,6 +5779,9 @@ export declare interface RegisterServiceWorkerOptions {
5472
5779
  reloadOnActivate?: boolean;
5473
5780
  }
5474
5781
 
5782
+ /** WCAG 2.x relative luminance of a hex color. */
5783
+ export declare function relativeLuminance(hex: string): number;
5784
+
5475
5785
  /**
5476
5786
  * Render a date as a human-friendly relative-time string (e.g. "5 min atrás")
5477
5787
  * inside a semantic `<time>` element with a machine-readable `dateTime`.
@@ -5635,6 +5945,9 @@ export declare interface RetryOptions {
5635
5945
  signal?: AbortSignal;
5636
5946
  }
5637
5947
 
5948
+ /** Serialize sRGB channels (`0`–`1`, clamped) back to a `#rrggbb` string. */
5949
+ export declare function rgbToHex(r: number, g: number, b: number): string;
5950
+
5638
5951
  export declare interface RoleAccessControlConfig {
5639
5952
  /** Permission strings granted directly, regardless of role. */
5640
5953
  permissions?: string[];
@@ -5759,6 +6072,9 @@ export declare interface SafeAreaProps extends HTMLAttributes<HTMLDivElement> {
5759
6072
  children?: ReactNode;
5760
6073
  }
5761
6074
 
6075
+ /** The ten steps of a Tempest tint scale, lightest to darkest. */
6076
+ export declare type ScaleStep = 50 | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900;
6077
+
5762
6078
  /**
5763
6079
  * A styled scroll container that overflows on the chosen axis and renders a
5764
6080
  * thin custom scrollbar (WebKit) while staying fully functional in browsers
@@ -5988,6 +6304,77 @@ export declare interface SidebarProps extends Omit<HTMLAttributes<HTMLElement>,
5988
6304
  collapsedWidth?: number | string;
5989
6305
  }
5990
6306
 
6307
+ /**
6308
+ * Signature capture on a canvas — the "sign here" field of a delivery receipt,
6309
+ * a service order, a term of acceptance.
6310
+ *
6311
+ * Strokes are kept as point lists and the canvas is **redrawn** from them, which
6312
+ * is what makes `undo` possible at all: a canvas holds pixels, not history, so
6313
+ * removing the last stroke means replaying the rest.
6314
+ *
6315
+ * The backing store is scaled by `devicePixelRatio`, so the line is crisp on a
6316
+ * phone instead of the blurry 1x bitmap a naive canvas produces.
6317
+ *
6318
+ * @example
6319
+ * ```tsx
6320
+ * const pad = useRef<SignaturePadHandle>(null);
6321
+ * const [empty, setEmpty] = useState(true);
6322
+ *
6323
+ * async function submit() {
6324
+ * const blob = await pad.current?.toBlob("image/png");
6325
+ * if (blob) await api.upload("/receipts/42/signature", blob);
6326
+ * }
6327
+ *
6328
+ * <SignaturePad ref={pad} label="Assinatura do cliente" onEmptyChange={setEmpty} />
6329
+ * <Button disabled={empty} onClick={submit}>Enviar</Button>
6330
+ * ```
6331
+ */
6332
+ export declare const SignaturePad: ForwardRefExoticComponent<SignaturePadProps & RefAttributes<SignaturePadHandle>>;
6333
+
6334
+ /** Imperative handle exposed through `ref`. */
6335
+ export declare interface SignaturePadHandle {
6336
+ /** Drop every stroke. */
6337
+ clear: () => void;
6338
+ /** Drop the last stroke. */
6339
+ undo: () => void;
6340
+ /** `true` while nothing has been drawn. */
6341
+ isEmpty: () => boolean;
6342
+ /** Export as a data URL. Returns `""` when the canvas is unavailable. */
6343
+ toDataURL: (type?: string, quality?: number) => string;
6344
+ /** Export as a `Blob` — what you actually upload. `null` when unavailable. */
6345
+ toBlob: (type?: string, quality?: number) => Promise<Blob | null>;
6346
+ }
6347
+
6348
+ export declare interface SignaturePadProps {
6349
+ /** Drawing surface width in CSS pixels. Default `400`. */
6350
+ width?: number;
6351
+ /** Drawing surface height in CSS pixels. Default `160`. */
6352
+ height?: number;
6353
+ /**
6354
+ * Stroke color. Defaults to the canvas' computed `color`, which the
6355
+ * stylesheet binds to `--tempest-text` — so the signature follows the theme
6356
+ * (including dark mode) instead of being hardcoded black.
6357
+ */
6358
+ penColor?: string;
6359
+ /** Stroke width in CSS pixels. Default `2`. */
6360
+ penWidth?: number;
6361
+ /** Blocks drawing and dims the surface. */
6362
+ disabled?: boolean;
6363
+ /** Accessible name of the surface. Default `"Signature"`. */
6364
+ label?: string;
6365
+ /** Called on the first move of each stroke. */
6366
+ onBegin?: () => void;
6367
+ /** Called when a stroke ends, with the current image as a data URL. */
6368
+ onEnd?: (dataUrl: string) => void;
6369
+ /** Called whenever the emptiness changes — wire it to a submit button. */
6370
+ onEmptyChange?: (isEmpty: boolean) => void;
6371
+ /** Renders the Clear/Undo buttons. Default `true`. */
6372
+ showActions?: boolean;
6373
+ clearLabel?: string;
6374
+ undoLabel?: string;
6375
+ className?: string;
6376
+ }
6377
+
5991
6378
  /** Loading placeholder block. Use `variant="text"` for inline lines, `circle` for avatars. */
5992
6379
  export declare function Skeleton({ variant, width, height, className, style }: SkeletonProps): JSX.Element;
5993
6380
 
@@ -6158,6 +6545,8 @@ export declare type StatTrend = "up" | "down" | "flat";
6158
6545
 
6159
6546
  export declare interface StepItem {
6160
6547
  label: ReactNode;
6548
+ /** Secondary line under the label — a hint, or "optional". */
6549
+ description?: ReactNode;
6161
6550
  }
6162
6551
 
6163
6552
  /**
@@ -6165,7 +6554,7 @@ export declare interface StepItem {
6165
6554
  * render as completed; the step at `current` is active; later steps are
6166
6555
  * upcoming.
6167
6556
  */
6168
- export declare function Stepper({ steps, current, orientation, className }: StepperProps): JSX.Element;
6557
+ export declare function Stepper({ steps, current, orientation, onStepClick, className, }: StepperProps): JSX.Element;
6169
6558
 
6170
6559
  /**
6171
6560
  * Numeric +/− stepper. Common in checkout quantity selectors and admin
@@ -6208,6 +6597,12 @@ export declare interface StepperProps {
6208
6597
  /** Index of the currently active step (0-based). */
6209
6598
  current: number;
6210
6599
  orientation?: "horizontal" | "vertical";
6600
+ /**
6601
+ * Makes each step activatable. Without it the steps are a read-only
6602
+ * indicator, which is the right default — in a gated flow, jumping ahead
6603
+ * would skip the gates.
6604
+ */
6605
+ onStepClick?: (index: number) => void;
6211
6606
  className?: string;
6212
6607
  }
6213
6608
 
@@ -6601,6 +6996,9 @@ export declare interface TextareaProps extends TextareaHTMLAttributes<HTMLTextAr
6601
6996
  wrapperClassName?: string;
6602
6997
  }
6603
6998
 
6999
+ /** The default `<style>` element id owned by {@link applyTheme}. */
7000
+ export declare const THEME_STYLE_ID = "tempest-theme";
7001
+
6604
7002
  export declare interface ThemeContextValue {
6605
7003
  /** Raw user preference (light / dark / system). */
6606
7004
  theme: ThemeMode;
@@ -6612,6 +7010,17 @@ export declare interface ThemeContextValue {
6612
7010
  toggle: () => void;
6613
7011
  }
6614
7012
 
7013
+ /**
7014
+ * Contrast ratio of `--tempest-primary-foreground` over the brand color.
7015
+ *
7016
+ * Exposed so an app (or a test) can assert its own brand clears WCAG AA (4.5) for
7017
+ * body text or AA-large (3.0) for button labels, instead of trusting the pick.
7018
+ *
7019
+ * @param options - The same input given to {@link createTheme}.
7020
+ * @returns The ratio, or `null` when no `primary` was provided.
7021
+ */
7022
+ export declare function themeContrast(options: CreateThemeOptions): number | null;
7023
+
6615
7024
  /**
6616
7025
  * Plain HTML snippet that sets `data-tempest-theme` on `<html>` before React
6617
7026
  * hydrates. Inline this in `<head>` to avoid a flash of the wrong theme on
@@ -6624,6 +7033,17 @@ export declare function themeInitScript(options?: GetInitialThemeOptions): strin
6624
7033
 
6625
7034
  export declare type ThemeMode = "light" | "dark" | "system";
6626
7035
 
7036
+ /** Name of a bundled preset. */
7037
+ export declare type ThemePresetName = "tempest" | "violet" | "emerald" | "rose" | "slate" | "amber";
7038
+
7039
+ /**
7040
+ * The bundled presets.
7041
+ *
7042
+ * `tempest` restates the SDK's own defaults — useful as a starting point to
7043
+ * tweak, and as the "reset to default" entry in a theme picker.
7044
+ */
7045
+ export declare const themePresets: Record<ThemePresetName, CreateThemeOptions>;
7046
+
6627
7047
  /**
6628
7048
  * Wire dark/light theming. Writes a data attribute on a target element (the
6629
7049
  * `<html>` element by default) and exposes the current preference via
@@ -6667,6 +7087,12 @@ export declare interface ThemeProviderProps {
6667
7087
  };
6668
7088
  }
6669
7089
 
7090
+ /** Radius presets, applied to the whole `--tempest-radius-*` family at once. */
7091
+ export declare type ThemeRadius = "none" | "sm" | "md" | "lg" | "xl" | "full";
7092
+
7093
+ /** Status token families that {@link createTheme} can regenerate. */
7094
+ export declare type ThemeStatus = "success" | "warning" | "danger" | "info";
7095
+
6670
7096
  /**
6671
7097
  * Create a throttled version of `fn` with leading and trailing edges.
6672
7098
  *
@@ -6973,6 +7399,80 @@ export declare interface TravelEstimate {
6973
7399
  */
6974
7400
  export declare type TravelMode = "car" | "motorcycle" | "bus";
6975
7401
 
7402
+ /** One node of the tree. Children make it a branch; no children makes it a leaf. */
7403
+ export declare interface TreeNode {
7404
+ /** Stable identifier, unique across the whole tree. */
7405
+ id: string;
7406
+ /** Rendered label. */
7407
+ label: ReactNode;
7408
+ /** Child nodes. An empty array still renders as a branch (an empty folder). */
7409
+ children?: TreeNode[];
7410
+ /** Icon rendered before the label. */
7411
+ icon?: ReactNode;
7412
+ /** Blocks selection and expansion, and skips the node in keyboard navigation. */
7413
+ disabled?: boolean;
7414
+ }
7415
+
7416
+ /**
7417
+ * Accessible tree for hierarchical data — categories, permissions, folders, an
7418
+ * org chart.
7419
+ *
7420
+ * Implements the `tree` role with **roving tabindex**: exactly one row is
7421
+ * tabbable, and the arrow keys move focus within the widget. That is what keeps a
7422
+ * 500-node tree from adding 500 stops to the page's tab order.
7423
+ *
7424
+ * Keyboard map: `↓`/`↑` move, `→` expands (or descends), `←` collapses (or goes to
7425
+ * the parent), `Home`/`End` jump to the first/last visible row, `Enter`/`Space`
7426
+ * select.
7427
+ *
7428
+ * The chevron is decoration (`aria-hidden`), not a button: the row itself carries
7429
+ * `aria-expanded`, so a second focusable control there would only add noise for a
7430
+ * screen reader while duplicating an action the keyboard map already has. It still
7431
+ * accepts a click, with the event stopped so it toggles without also selecting.
7432
+ *
7433
+ * @example
7434
+ * ```tsx
7435
+ * const nodes: TreeNode[] = [
7436
+ * {
7437
+ * id: "vendas",
7438
+ * label: "Vendas",
7439
+ * children: [
7440
+ * { id: "vendas.ler", label: "Ler" },
7441
+ * { id: "vendas.editar", label: "Editar" },
7442
+ * ],
7443
+ * },
7444
+ * { id: "config", label: "Configurações", children: [] },
7445
+ * ];
7446
+ *
7447
+ * <TreeView nodes={nodes} defaultExpandedIds={["vendas"]} onSelect={(node) => console.log(node.id)} />
7448
+ * ```
7449
+ */
7450
+ export declare function TreeView({ nodes, expandedIds, defaultExpandedIds, onExpandedChange, selectedId, defaultSelectedId, onSelect, toggleOnSelect, label, className, }: TreeViewProps): JSX.Element;
7451
+
7452
+ export declare interface TreeViewProps {
7453
+ /** Root nodes. */
7454
+ nodes: TreeNode[];
7455
+ /** Controlled expanded ids. */
7456
+ expandedIds?: string[];
7457
+ /** Uncontrolled initial expanded ids. */
7458
+ defaultExpandedIds?: string[];
7459
+ onExpandedChange?: (expandedIds: string[]) => void;
7460
+ /** Controlled selected id. `null` means nothing selected. */
7461
+ selectedId?: string | null;
7462
+ /** Uncontrolled initial selection. */
7463
+ defaultSelectedId?: string | null;
7464
+ onSelect?: (node: TreeNode) => void;
7465
+ /**
7466
+ * Selecting a branch also toggles it. Default `true` — matches how a file
7467
+ * explorer behaves; set `false` when a branch is itself a meaningful choice
7468
+ * (a category that owns items, for instance).
7469
+ */
7470
+ toggleOnSelect?: boolean;
7471
+ /** Accessible name for the tree. */
7472
+ label?: string;
7473
+ className?: string;
7474
+ }
7475
+
6976
7476
  /**
6977
7477
  * Truncate a string to `max` characters, appending `suffix` when cut.
6978
7478
  * Returns the original when shorter than (or equal to) `max`.
@@ -9067,6 +9567,109 @@ export declare type WithSelectors<S> = S extends {
9067
9567
  */
9068
9568
  export declare function withTimeout<T>(promise: Promise<T>, ms: number, message?: string): Promise<T>;
9069
9569
 
9570
+ /**
9571
+ * Multi-step flow: step indicator, one body at a time, and navigation that
9572
+ * respects per-step validation.
9573
+ *
9574
+ * `Stepper` draws the indicator; this owns the part every app was rewriting — the
9575
+ * active index, the async gate before advancing, the disabled/pending buttons and
9576
+ * the completion call.
9577
+ *
9578
+ * Only the active step's body is mounted. Uncommitted input in a step you leave is
9579
+ * therefore lost unless the state lives outside (react-hook-form's `FormProvider`,
9580
+ * a store, a parent `useState`) — which is the right place for it anyway, since
9581
+ * the last step usually needs to submit everything at once.
9582
+ *
9583
+ * @example
9584
+ * ```tsx
9585
+ * const form = useZodForm(schema);
9586
+ *
9587
+ * <FormProvider {...form}>
9588
+ * <Wizard
9589
+ * steps={[
9590
+ * {
9591
+ * id: "dados",
9592
+ * label: "Dados",
9593
+ * validate: () => form.trigger(["nome", "email"]),
9594
+ * content: (
9595
+ * <>
9596
+ * <FormField name="nome" label="Nome"><Input /></FormField>
9597
+ * <FormField name="email" label="E-mail"><Input type="email" /></FormField>
9598
+ * </>
9599
+ * ),
9600
+ * },
9601
+ * { id: "revisao", label: "Revisão", content: <Review /> },
9602
+ * ]}
9603
+ * onComplete={form.handleSubmit(onSubmit)}
9604
+ * />
9605
+ * </FormProvider>
9606
+ * ```
9607
+ */
9608
+ export declare function Wizard({ steps, activeIndex, defaultActiveIndex, onStepChange, onComplete, nextLabel, backLabel, finishLabel, clickableSteps, renderActions, className, }: WizardProps): JSX.Element;
9609
+
9610
+ /** Flow controls handed to a step body and to `renderActions`. */
9611
+ export declare interface WizardControls {
9612
+ /** Zero-based index of the current step. */
9613
+ activeIndex: number;
9614
+ /** The current step. */
9615
+ step: WizardStep;
9616
+ /** `true` while a `validate` promise is pending. */
9617
+ validating: boolean;
9618
+ isFirst: boolean;
9619
+ isLast: boolean;
9620
+ /** Run the current step's `validate` and advance when it passes. */
9621
+ next: () => Promise<void>;
9622
+ /** Go back one step. No validation — going back never blocks. */
9623
+ back: () => void;
9624
+ /** Jump to an index. Forward jumps validate every step in between. */
9625
+ goTo: (index: number) => Promise<void>;
9626
+ }
9627
+
9628
+ export declare interface WizardProps {
9629
+ steps: WizardStep[];
9630
+ /** Controlled active index. */
9631
+ activeIndex?: number;
9632
+ /** Uncontrolled initial index. Default `0`. */
9633
+ defaultActiveIndex?: number;
9634
+ onStepChange?: (index: number, step: WizardStep) => void;
9635
+ /** Called when the last step passes validation. */
9636
+ onComplete?: () => void | Promise<void>;
9637
+ /** Label of the advance button. Default `"Next"`. */
9638
+ nextLabel?: string;
9639
+ /** Label of the back button. Default `"Back"`. */
9640
+ backLabel?: string;
9641
+ /** Label of the button on the last step. Default `"Finish"`. */
9642
+ finishLabel?: string;
9643
+ /**
9644
+ * Allow clicking the indicator to jump. Default `false` — a wizard exists
9645
+ * because order matters, and a free jump skips the gates.
9646
+ */
9647
+ clickableSteps?: boolean;
9648
+ /** Replace the default button row. */
9649
+ renderActions?: (controls: WizardControls) => ReactNode;
9650
+ className?: string;
9651
+ }
9652
+
9653
+ /** One step of the flow. */
9654
+ export declare interface WizardStep {
9655
+ /** Stable identifier. */
9656
+ id: string;
9657
+ /** Step label shown in the indicator. */
9658
+ label: string;
9659
+ /** Optional description under the label. */
9660
+ description?: string;
9661
+ /** Step body. A function receives the flow controls, for a "skip" link inside the form. */
9662
+ content: ReactNode | ((controls: WizardControls) => ReactNode);
9663
+ /**
9664
+ * Gate for leaving this step forward. Return `false` (or a rejected/`false`
9665
+ * promise) to keep the user here — typically `() => form.trigger()`.
9666
+ * Async is supported: the Next button shows a pending state while it runs.
9667
+ */
9668
+ validate?: () => boolean | Promise<boolean>;
9669
+ /** Marks the step as optional, so `onComplete` can ignore it. */
9670
+ optional?: boolean;
9671
+ }
9672
+
9070
9673
  /**
9071
9674
  * Write a minimal single-sheet Office Open XML (`.xlsx`) workbook and return
9072
9675
  * its bytes. No extra dependency beyond `fflate` — the archive is assembled and