tempest-react-sdk 0.1.5 → 0.2.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/README.md CHANGED
@@ -17,7 +17,7 @@ The goal is to start every new React frontend with the same opinionated foundati
17
17
 
18
18
  - [Recommended stack](#recommended-stack)
19
19
  - [Install](#install)
20
- - [Peer dependencies](#peer-dependencies)
20
+ - [Peer & bundled dependencies](#peer--bundled-dependencies)
21
21
  - [CSS import](#css-import)
22
22
  - [What's inside](#whats-inside)
23
23
  - [Architecture overview](#architecture-overview)
@@ -109,28 +109,33 @@ Via `package.json`:
109
109
 
110
110
  Requires React `>=18` and Node `>=20.19` to build.
111
111
 
112
- ### Peer dependencies
112
+ ### Peer & bundled dependencies
113
113
 
114
- `react` and `react-dom` are **required** peer dependencies. Everything else is **optional** install only the packages the modules you import actually need. Importing `tempest-react-sdk` without an optional peer never throws; the failure surfaces only when you instantiate the helper that uses it.
114
+ Only **react** and **react-dom** are peer dependencies — those must come from the host app so a single React copy lives in the tree.
115
115
 
116
- | Peer | Required by | Status |
117
- | --------------------------------------------- | ------------------------------------------------------------------- | ------------ |
118
- | `react`, `react-dom` (`^18.0.0 \|\| ^19.0.0`) | Everything | **Required** |
119
- | `@tanstack/react-query` (`^5`) | `QueryProvider`, `createQueryKeys` | Optional |
120
- | `zod` (`^3.23 \|\| ^4`) | `parseResponse`, `validateForm`, `zodResolver`, `useZodForm` | Optional |
121
- | `zustand` (`^4 \|\| ^5`) | `createAuthStore` | Optional |
122
- | `dexie` (`^4.4`) | `createOfflineStore` | Optional |
123
- | `react-hook-form` (`^7.76`) | `zodResolver`, `useZodForm`, masked inputs | Optional |
124
- | `lucide-react` (`>=0.400`) | Component icons (`leftIcon`/`rightIcon` on `Input`, `Button`, etc.) | Optional |
116
+ Everything else (`zod`, `zustand`, `dexie`, `react-hook-form`, `@tanstack/react-query`, `lucide-react`) is a **direct dependency** of the SDK, installed automatically by `npm install tempest-react-sdk`. You never need to install them manually.
125
117
 
126
- Quick recipe for a "typical" app that uses HTTP + Query + Auth + Forms:
118
+ | Package | Status | Used by |
119
+ | ------------------------------------- | ------------------- | ------------------------------------------------------------------- |
120
+ | `react`, `react-dom` (`^18 \|\| ^19`) | **Peer (required)** | Everything |
121
+ | `@tanstack/react-query` (`^5`) | Direct dep (auto) | `QueryProvider`, `createQueryKeys` |
122
+ | `zod` (`^3.23 \|\| ^4`) | Direct dep (auto) | `parseResponse`, `validateForm`, `zodResolver`, `useZodForm` |
123
+ | `zustand` (`^4 \|\| ^5`) | Direct dep (auto) | `createAuthStore` |
124
+ | `dexie` (`^4.4`) | Direct dep (auto) | `createOfflineStore` |
125
+ | `react-hook-form` (`^7.76`) | Direct dep (auto) | `zodResolver`, `useZodForm`, masked inputs |
126
+ | `lucide-react` (`>=0.400`) | Direct dep (auto) | Component icons (`leftIcon`/`rightIcon` on `Input`, `Button`, etc.) |
127
+
128
+ The minimum install is just:
127
129
 
128
130
  ```bash
129
- npm install tempest-react-sdk react react-dom \
130
- @tanstack/react-query zod zustand react-hook-form lucide-react
131
+ npm install tempest-react-sdk react react-dom
131
132
  ```
132
133
 
133
- If a module is missing its peer dep at runtime, the bundler will flag the missing import at build timethere is no "silent fallback" behaviour. Add only what you actually consume.
134
+ **Bundle impact**: every bundled dep is externalised in the SDK's Rollup config, so the SDK's published bundle stays at ~104 KB ESM. Your app's bundler (Vite / webpack / Rspack) resolves these from `node_modules` and tree-shakes if you never call `createOfflineStore`, Dexie never enters your final bundle.
135
+
136
+ **Version conflicts**: if your app already pins (say) `zod@3.20`, npm dedupes when the range is compatible. If ranges diverge you get two copies — pin a single version in your own `package.json` to force one, or open an issue if the SDK's range is too tight.
137
+
138
+ Adapters for external SDKs (`@sentry/browser`, `posthog-js`, `@growthbook/growthbook`, `launchdarkly-js-client-sdk`) are **not** bundled — install those only when you opt into the adapter. The caller passes the SDK instance to the factory.
134
139
 
135
140
  ### CSS import
136
141
 
package/dist/index.d.ts CHANGED
@@ -28,6 +28,30 @@ import { UseFormProps } from 'react-hook-form';
28
28
  import { UseFormReturn } from 'react-hook-form';
29
29
  import { z } from 'zod';
30
30
 
31
+ /**
32
+ * Inline alert / notice with tone (info/success/warning/danger) and appearance
33
+ * (soft/solid/outline). Accepts optional `icon`, `title`, `description` and
34
+ * a dismiss button via `onClose`.
35
+ */
36
+ export declare function Alert({ variant, appearance, title, description, icon, onClose, closeLabel, className, children, ...props }: AlertProps): JSX.Element;
37
+
38
+ export declare type AlertAppearance = "soft" | "solid" | "outline";
39
+
40
+ export declare interface AlertProps extends Omit<HTMLAttributes<HTMLDivElement>, "title"> {
41
+ variant?: AlertVariant;
42
+ /** Visual style: soft (default tinted bg), solid (filled), outline (bordered). */
43
+ appearance?: AlertAppearance;
44
+ title?: ReactNode;
45
+ description?: ReactNode;
46
+ icon?: ReactNode;
47
+ /** Show a close button and invoke this when clicked. */
48
+ onClose?: () => void;
49
+ /** Custom close button label for screen readers. */
50
+ closeLabel?: string;
51
+ }
52
+
53
+ export declare type AlertVariant = "neutral" | "info" | "success" | "warning" | "danger";
54
+
31
55
  export declare interface ApiClient {
32
56
  request<T>(path: string, options?: RequestOptions): Promise<T>;
33
57
  get<T>(path: string, options?: RequestOptions): Promise<T>;
@@ -177,6 +201,30 @@ export declare interface BreadcrumbsProps {
177
201
  className?: string;
178
202
  }
179
203
 
204
+ /**
205
+ * Breakpoint keys exposed by the SDK. Values mirror the CSS tokens
206
+ * `--tempest-bp-xs|sm|md|lg|xl|2xl` defined in `styles/colors.css`.
207
+ */
208
+ export declare type Breakpoint = "xs" | "sm" | "md" | "lg" | "xl" | "2xl";
209
+
210
+ export declare interface BreakpointHelpers {
211
+ /** Current breakpoint key (the largest one whose min-width is matched). */
212
+ current: Breakpoint;
213
+ /** Window width in pixels at last update. `0` when SSR. */
214
+ width: number;
215
+ /** True when viewport width is `>=` the given breakpoint. */
216
+ above: (bp: Breakpoint) => boolean;
217
+ /** True when viewport width is `<` the given breakpoint. */
218
+ below: (bp: Breakpoint) => boolean;
219
+ /** Convenience flags mapping to typical device shapes. */
220
+ isMobile: boolean;
221
+ isTablet: boolean;
222
+ isDesktop: boolean;
223
+ }
224
+
225
+ /** Pixel value paired with each breakpoint key. */
226
+ export declare const BREAKPOINTS: Record<Breakpoint, number>;
227
+
180
228
  /**
181
229
  * Primary action button with variants, sizes and a loading state that
182
230
  * preserves layout via an absolutely-positioned spinner.
@@ -316,7 +364,10 @@ export declare const consoleSink: LoggerSink;
316
364
  */
317
365
  export declare const consoleTelemetryAdapter: TelemetryAdapter;
318
366
 
319
- /** Page-level horizontal container with a max-width preset and side padding. */
367
+ /**
368
+ * Page-level horizontal container with a max-width preset and responsive
369
+ * side padding (`space-4` mobile / `space-6` tablet / `space-8` desktop).
370
+ */
320
371
  export declare function Container({ size, className, children, ...props }: ContainerProps): JSX.Element;
321
372
 
322
373
  export declare interface ContainerProps extends HTMLAttributes<HTMLDivElement> {
@@ -723,13 +774,34 @@ export declare interface DecodedJWT {
723
774
  */
724
775
  export declare function decodeJWT(token: string): DecodedJWT;
725
776
 
777
+ /**
778
+ * Horizontal or vertical visual separator. When `label` is provided in
779
+ * horizontal mode the divider splits and centers the label between two lines.
780
+ */
781
+ export declare function Divider({ orientation, variant, label, align, className, ...props }: DividerProps): JSX.Element;
782
+
783
+ export declare type DividerAlign = "start" | "center" | "end";
784
+
785
+ export declare type DividerOrientation = "horizontal" | "vertical";
786
+
787
+ export declare interface DividerProps extends Omit<HTMLAttributes<HTMLDivElement>, "children"> {
788
+ orientation?: DividerOrientation;
789
+ variant?: DividerVariant;
790
+ /** Optional label rendered inside the divider (horizontal only). */
791
+ label?: ReactNode;
792
+ /** Label horizontal position (only when `label` provided). Defaults to `center`. */
793
+ align?: DividerAlign;
794
+ }
795
+
796
+ export declare type DividerVariant = "solid" | "dashed";
797
+
726
798
  export declare type DocumentVisibility = "visible" | "hidden";
727
799
 
728
800
  /**
729
801
  * Sliding side panel. Same building blocks as {@link Modal} but anchored to
730
802
  * an edge. Locks body scroll while open.
731
803
  */
732
- export declare function Drawer({ open, onClose, placement, title, children, footer, closeOnBackdrop, closeOnEsc, hideCloseButton, className, }: DrawerProps): ReactPortal | null;
804
+ export declare function Drawer({ open, onClose, placement, title, children, footer, closeOnBackdrop, closeOnEsc, hideCloseButton, className, mobilePlacement, showHandle, }: DrawerProps): ReactPortal | null;
733
805
 
734
806
  export declare type DrawerPlacement = "right" | "left" | "top" | "bottom";
735
807
 
@@ -744,6 +816,14 @@ export declare interface DrawerProps {
744
816
  closeOnEsc?: boolean;
745
817
  hideCloseButton?: boolean;
746
818
  className?: string;
819
+ /**
820
+ * Auto-switch to bottom-sheet placement on mobile viewports (< md).
821
+ * Modern mobile apps default to bottom drawers; on desktop the original
822
+ * `placement` is preserved.
823
+ */
824
+ mobilePlacement?: DrawerPlacement;
825
+ /** Render a drag handle indicator at the leading edge (bottom-sheet style). */
826
+ showHandle?: boolean;
747
827
  }
748
828
 
749
829
  export declare interface ElementSize {
@@ -1062,10 +1142,10 @@ export declare interface GetInitialThemeOptions {
1062
1142
  export declare function Grid({ columns, gap, className, style, children, ...props }: GridProps): JSX.Element;
1063
1143
 
1064
1144
  export declare interface GridProps extends HTMLAttributes<HTMLDivElement> {
1065
- /** Number of columns or a custom `grid-template-columns` value. */
1066
- columns?: number | string;
1067
- /** Gap as a CSS length. Numbers map to a multiple of the 4px scale. */
1068
- gap?: number | string;
1145
+ /** Number of columns or a custom `grid-template-columns` value. Accepts responsive object. */
1146
+ columns?: ResponsiveValue<number | string>;
1147
+ /** Gap as a CSS length. Numbers map to a multiple of the 4px scale. Accepts responsive object. */
1148
+ gap?: ResponsiveValue<number | string>;
1069
1149
  children?: ReactNode;
1070
1150
  }
1071
1151
 
@@ -1080,6 +1160,19 @@ export declare interface GrowthBookLike {
1080
1160
  setRenderer?: (renderer: () => void) => void;
1081
1161
  }
1082
1162
 
1163
+ /** Inverse of `<Show>` — hides children when the condition matches. */
1164
+ export declare function Hide({ above, below, only, children }: HideProps): ReactNode;
1165
+
1166
+ export declare interface HideProps {
1167
+ /** Hide children when viewport width is `>=` this breakpoint. */
1168
+ above?: Breakpoint;
1169
+ /** Hide children when viewport width is `<` this breakpoint. */
1170
+ below?: Breakpoint;
1171
+ /** Hide on specific breakpoints. */
1172
+ only?: Breakpoint | Breakpoint[];
1173
+ children: ReactNode;
1174
+ }
1175
+
1083
1176
  export declare interface I18n {
1084
1177
  /** Currently active locale. */
1085
1178
  locale: string;
@@ -1207,6 +1300,18 @@ export declare function isPushSupported(): boolean;
1207
1300
  /** True when the Web Share API is available in this environment. */
1208
1301
  export declare function isShareSupported(): boolean;
1209
1302
 
1303
+ /**
1304
+ * Renders a `<kbd>` styled like a keyboard key — useful for shortcut hints.
1305
+ * Compose multiple keys by rendering siblings: `<Kbd>Ctrl</Kbd> + <Kbd>K</Kbd>`.
1306
+ */
1307
+ export declare function Kbd({ size, className, children, ...props }: KbdProps): JSX.Element;
1308
+
1309
+ export declare interface KbdProps extends HTMLAttributes<HTMLElement> {
1310
+ size?: KbdSize;
1311
+ }
1312
+
1313
+ export declare type KbdSize = "sm" | "md" | "lg";
1314
+
1210
1315
  export declare interface KeyboardShortcut {
1211
1316
  /** Key name (`"k"`, `"Enter"`, `"Escape"`, `"ArrowDown"`, etc.). Case-insensitive. */
1212
1317
  key: string;
@@ -1306,7 +1411,7 @@ export declare type Messages = Record<string, string>;
1306
1411
  * Portal-rendered modal dialog with backdrop, Esc handler, and slots for
1307
1412
  * header/body/footer. Locks body scroll while open.
1308
1413
  */
1309
- export declare function Modal({ open, onClose, title, children, footer, size, closeOnBackdrop, closeOnEsc, className, hideCloseButton, }: ModalProps): ReactPortal | null;
1414
+ export declare function Modal({ open, onClose, title, children, footer, size, closeOnBackdrop, closeOnEsc, className, hideCloseButton, fullscreen, fullscreenOnMobile, }: ModalProps): ReactPortal | null;
1310
1415
 
1311
1416
  export declare interface ModalProps {
1312
1417
  open: boolean;
@@ -1319,9 +1424,13 @@ export declare interface ModalProps {
1319
1424
  closeOnEsc?: boolean;
1320
1425
  className?: string;
1321
1426
  hideCloseButton?: boolean;
1427
+ /** Force fullscreen at all breakpoints. */
1428
+ fullscreen?: boolean;
1429
+ /** Auto-fullscreen on mobile viewports (< 640px). Default `false`. */
1430
+ fullscreenOnMobile?: boolean;
1322
1431
  }
1323
1432
 
1324
- export declare type ModalSize = "sm" | "md" | "lg" | "xl";
1433
+ export declare type ModalSize = "sm" | "md" | "lg" | "xl" | "2xl" | "3xl";
1325
1434
 
1326
1435
  /**
1327
1436
  * Currency-masked input. Stores the value as an integer number of cents to
@@ -1610,6 +1719,17 @@ declare interface ResolverOutput<T> {
1610
1719
  errors: Record<string, ResolverError | object>;
1611
1720
  }
1612
1721
 
1722
+ /**
1723
+ * Responsive value — either a single value applied at all breakpoints, or
1724
+ * an object with `mobile` / `tablet` / `desktop` overrides. Apps can mix
1725
+ * any combination; `mobile` is the base, `tablet` / `desktop` cascade up.
1726
+ */
1727
+ export declare type ResponsiveValue<T> = T | {
1728
+ mobile?: T;
1729
+ tablet?: T;
1730
+ desktop?: T;
1731
+ };
1732
+
1613
1733
  /**
1614
1734
  * Run `factory()` with exponential backoff. Each attempt awaits an
1615
1735
  * increasing delay capped at `maxDelay`. Throws the last error if every
@@ -1722,6 +1842,28 @@ export declare interface ShareResult {
1722
1842
  error?: unknown;
1723
1843
  }
1724
1844
 
1845
+ /**
1846
+ * Conditionally render children based on the viewport breakpoint.
1847
+ *
1848
+ * - `above` — render when viewport width is `>=` the given breakpoint.
1849
+ * - `below` — render when viewport width is `<` the given breakpoint.
1850
+ * - `only` — render only on the listed breakpoint(s).
1851
+ *
1852
+ * SSR-safe: first render uses `xs` (renders mobile content first); the
1853
+ * component re-renders once `useBreakpoint` has the real viewport width.
1854
+ */
1855
+ export declare function Show({ above, below, only, children }: ShowProps): ReactNode;
1856
+
1857
+ export declare interface ShowProps {
1858
+ /** Render children only when viewport width is `>=` this breakpoint. */
1859
+ above?: Breakpoint;
1860
+ /** Render children only when viewport width is `<` this breakpoint. */
1861
+ below?: Breakpoint;
1862
+ /** Render only on specific breakpoints. Wins over `above`/`below` when set. */
1863
+ only?: Breakpoint | Breakpoint[];
1864
+ children: ReactNode;
1865
+ }
1866
+
1725
1867
  /** Loading placeholder block. Use `variant="text"` for inline lines, `circle` for avatars. */
1726
1868
  export declare function Skeleton({ variant, width, height, className, style }: SkeletonProps): JSX.Element;
1727
1869
 
@@ -1739,7 +1881,7 @@ export declare interface SkeletonProps {
1739
1881
  */
1740
1882
  export declare function skipWaiting(worker: ServiceWorker): void;
1741
1883
 
1742
- /** Loading spinner with three preset sizes. Provide `label` for screen readers. */
1884
+ /** Loading spinner with preset sizes (xs..xl). Provide `label` for screen readers. */
1743
1885
  export declare function Spinner({ size, className, label }: SpinnerProps): JSX.Element;
1744
1886
 
1745
1887
  export declare interface SpinnerProps {
@@ -1748,20 +1890,22 @@ export declare interface SpinnerProps {
1748
1890
  label?: string;
1749
1891
  }
1750
1892
 
1751
- export declare type SpinnerSize = "sm" | "md" | "lg";
1893
+ export declare type SpinnerSize = "xs" | "sm" | "md" | "lg" | "xl";
1752
1894
 
1753
1895
  /** Flex-based vertical or horizontal stack with a numeric `gap`. */
1754
1896
  export declare function Stack({ direction, gap, align, justify, wrap, className, style, children, ...props }: StackProps): JSX.Element;
1755
1897
 
1756
1898
  export declare type StackAlign = "start" | "center" | "end" | "stretch";
1757
1899
 
1900
+ export declare type StackDirection = "vertical" | "horizontal";
1901
+
1758
1902
  export declare type StackJustify = "start" | "center" | "end" | "between";
1759
1903
 
1760
1904
  export declare interface StackProps extends HTMLAttributes<HTMLDivElement> {
1761
- /** Direction. Default `vertical`. */
1762
- direction?: "vertical" | "horizontal";
1763
- /** Gap as a CSS length. Numbers map to a multiple of the 4px scale. */
1764
- gap?: number | string;
1905
+ /** Direction. Accepts responsive object — e.g. `{ mobile: "vertical", desktop: "horizontal" }`. */
1906
+ direction?: ResponsiveValue<StackDirection>;
1907
+ /** Gap as a CSS length. Numbers map to a multiple of the 4px scale. Accepts responsive object. */
1908
+ gap?: ResponsiveValue<number | string>;
1765
1909
  align?: StackAlign;
1766
1910
  justify?: StackJustify;
1767
1911
  wrap?: boolean;
@@ -1824,11 +1968,13 @@ export declare interface TabItem {
1824
1968
  }
1825
1969
 
1826
1970
  /**
1827
- * Lightweight table that maps a list of rows through declarative `columns`.
1828
- * Provide `rowKey` so React reconciliation works. Rows become clickable when
1829
- * `onRowClick` is supplied.
1971
+ * Lightweight table with declarative columns + mobile niceties.
1972
+ *
1973
+ * - `priority` per column lets less-important data hide on narrow viewports.
1974
+ * - `stackOnMobile` re-renders each row as a label/value card on mobile,
1975
+ * avoiding horizontal scroll for dense data.
1830
1976
  */
1831
- export declare function Table<T>({ columns, data, rowKey, onRowClick, emptyMessage, className, }: TableProps<T>): JSX.Element;
1977
+ export declare function Table<T>({ columns, data, rowKey, onRowClick, emptyMessage, className, stackOnMobile, }: TableProps<T>): JSX.Element;
1832
1978
 
1833
1979
  export declare type TableAlign = "left" | "right" | "center";
1834
1980
 
@@ -1840,8 +1986,15 @@ export declare interface TableColumn<T> {
1840
1986
  align?: TableAlign;
1841
1987
  width?: string | number;
1842
1988
  className?: string;
1989
+ /**
1990
+ * Visibility priority: `always` (default) shows on every viewport,
1991
+ * `tablet` hides below md (< 768px), `desktop` hides below lg (< 1024px).
1992
+ */
1993
+ priority?: TablePriority;
1843
1994
  }
1844
1995
 
1996
+ export declare type TablePriority = "always" | "tablet" | "desktop";
1997
+
1845
1998
  export declare interface TableProps<T> {
1846
1999
  columns: TableColumn<T>[];
1847
2000
  data: T[];
@@ -1849,6 +2002,11 @@ export declare interface TableProps<T> {
1849
2002
  onRowClick?: (row: T) => void;
1850
2003
  emptyMessage?: ReactNode;
1851
2004
  className?: string;
2005
+ /**
2006
+ * Stack mode — render rows as label/value cards on mobile (< md).
2007
+ * Better than horizontal scroll when each row has 3+ columns of dense data.
2008
+ */
2009
+ stackOnMobile?: boolean;
1852
2010
  }
1853
2011
 
1854
2012
  /**
@@ -1983,15 +2141,19 @@ export declare interface ToastOptions {
1983
2141
  duration?: number;
1984
2142
  }
1985
2143
 
2144
+ export declare type ToastPosition = "top-right" | "top-left" | "top-center" | "bottom-right" | "bottom-left" | "bottom-center";
2145
+
1986
2146
  /**
1987
2147
  * Renders a portalled toast container and exposes the imperative {@link useToast} API.
1988
2148
  */
1989
- export declare function ToastProvider({ children, defaultDuration }: ToastProviderProps): JSX.Element;
2149
+ export declare function ToastProvider({ children, defaultDuration, position, }: ToastProviderProps): JSX.Element;
1990
2150
 
1991
2151
  export declare interface ToastProviderProps {
1992
2152
  children: ReactNode;
1993
2153
  /** Default auto-dismiss duration (ms). Default 4000. */
1994
2154
  defaultDuration?: number;
2155
+ /** Stack position on screen. Default `"top-right"`. */
2156
+ position?: ToastPosition;
1995
2157
  }
1996
2158
 
1997
2159
  export declare type ToastVariant = "success" | "warning" | "error" | "info";
@@ -2109,6 +2271,15 @@ export declare interface UseBeforeInstallPromptResult {
2109
2271
  prompt: () => Promise<"accepted" | "dismissed" | "unsupported">;
2110
2272
  }
2111
2273
 
2274
+ /**
2275
+ * Reactive viewport-breakpoint hook.
2276
+ *
2277
+ * Returns the current breakpoint key plus `above` / `below` helpers and
2278
+ * `isMobile` / `isTablet` / `isDesktop` flags. SSR-safe — returns `xs` /
2279
+ * `width: 0` on the server, then updates after mount.
2280
+ */
2281
+ export declare function useBreakpoint(): BreakpointHelpers;
2282
+
2112
2283
  /**
2113
2284
  * Client-side filter helper. Performs a case-insensitive match on the listed
2114
2285
  * keys when no custom predicate is provided.