@amsterdamdatalabs/enact-design-system 0.1.2 → 0.1.10

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 (43) hide show
  1. package/README.md +186 -0
  2. package/dist/components/core/Avatar/Avatar.d.ts +3 -2
  3. package/dist/components/core/Badge/Badge.d.ts +3 -2
  4. package/dist/components/core/Button/Button.d.ts +3 -2
  5. package/dist/components/core/Card/Card.d.ts +3 -2
  6. package/dist/components/core/IconButton/IconButton.d.ts +3 -2
  7. package/dist/components/core/Stat/Stat.d.ts +3 -2
  8. package/dist/components/core/Tag/Tag.d.ts +3 -2
  9. package/dist/components/feedback/Alert/Alert.d.ts +3 -2
  10. package/dist/components/feedback/Progress/Progress.d.ts +3 -2
  11. package/dist/components/feedback/Tooltip/Tooltip.d.ts +3 -2
  12. package/dist/components/forms/Checkbox/Checkbox.d.ts +3 -2
  13. package/dist/components/forms/Field/Field.d.ts +3 -2
  14. package/dist/components/forms/Input/Input.d.ts +3 -2
  15. package/dist/components/forms/Select/Select.d.ts +3 -2
  16. package/dist/components/forms/Switch/Switch.d.ts +3 -2
  17. package/dist/components/layout/Box/Box.d.ts +10 -0
  18. package/dist/components/layout/Box/index.d.ts +1 -0
  19. package/dist/components/layout/Container/Container.d.ts +9 -0
  20. package/dist/components/layout/Container/index.d.ts +1 -0
  21. package/dist/components/layout/Grid/Grid.d.ts +8 -0
  22. package/dist/components/layout/Grid/index.d.ts +1 -0
  23. package/dist/components/layout/Inline/Inline.d.ts +10 -0
  24. package/dist/components/layout/Inline/index.d.ts +1 -0
  25. package/dist/components/layout/Stack/Stack.d.ts +9 -0
  26. package/dist/components/layout/Stack/index.d.ts +1 -0
  27. package/dist/components/layout/scale.d.ts +36 -0
  28. package/dist/components/navigation/Breadcrumb/Breadcrumb.d.ts +3 -2
  29. package/dist/components/navigation/Tabs/Tabs.d.ts +3 -2
  30. package/dist/components/overlay/Modal/Modal.d.ts +17 -0
  31. package/dist/components/overlay/Modal/index.d.ts +1 -0
  32. package/dist/components/system/ThemeProvider/ThemeProvider.d.ts +15 -0
  33. package/dist/components/system/ThemeProvider/index.d.ts +2 -0
  34. package/dist/components/system/ThemeProvider/themeInitScript.d.ts +37 -0
  35. package/dist/components/typography/Heading/Heading.d.ts +9 -0
  36. package/dist/components/typography/Heading/index.d.ts +1 -0
  37. package/dist/components/typography/Text/Text.d.ts +12 -0
  38. package/dist/components/typography/Text/index.d.ts +1 -0
  39. package/dist/enact-design-system.css +1 -1
  40. package/dist/index.d.ts +9 -0
  41. package/dist/index.js +1136 -430
  42. package/dist/tokens.css +14 -0
  43. package/package.json +1 -1
package/README.md CHANGED
@@ -29,8 +29,28 @@ bun run check # typecheck + lint + test (the pre-merge gate)
29
29
  bun run build # dist/: ESM + .d.ts + design-system.css + tokens.css
30
30
  ```
31
31
 
32
+ ## Local development against a consumer app
33
+
34
+ `dev-install-and-run.sh` builds the library and installs the **real publishable
35
+ tarball** (`bun pm pack`) into a consumer app — so it resolves exactly like a
36
+ registry install (built `dist/` + the `exports` map), not a source symlink. This
37
+ mirrors what apps get from npm, for rapid local iteration.
38
+
39
+ ```bash
40
+ bash dev-install-and-run.sh --target ../net-revenue-demo # build → test → pack → install into the app
41
+ bash dev-install-and-run.sh pack # just build + produce the tarball
42
+ bash dev-install-and-run.sh link # global `bun link`; then `bun link <pkg>` in the app
43
+ bash dev-install-and-run.sh doctor # list exactly what the published tarball contains
44
+ bash dev-install-and-run.sh --dry-run --target ../app # print the plan without running it
45
+ ```
46
+
47
+ Use `--skip-build` to re-pack without reinstalling deps, and `--docs` to launch
48
+ the showcase afterwards.
49
+
32
50
  ## Usage in a product app
33
51
 
52
+ Import styles first, then components — all from the single public entry point:
53
+
34
54
  ```tsx
35
55
  import "@amsterdamdatalabs/enact-design-system/tokens.css"; // design tokens (incl. dark mode)
36
56
  import "@amsterdamdatalabs/enact-design-system/styles.css"; // component styles
@@ -48,6 +68,172 @@ export function Example() {
48
68
 
49
69
  Dark mode: set `data-theme="dark"` on `<html>` (or any subtree root).
50
70
 
71
+ ## ThemeProvider and useTheme
72
+
73
+ Wrap your application root with `ThemeProvider` to enable theme switching.
74
+ `useTheme` surfaces the current theme and a setter anywhere in the tree.
75
+
76
+ ```tsx
77
+ import {
78
+ ThemeProvider,
79
+ useTheme,
80
+ } from "@amsterdamdatalabs/enact-design-system";
81
+
82
+ // 1. Wrap the app root
83
+ export function App() {
84
+ return (
85
+ <ThemeProvider defaultTheme="system">
86
+ <Shell />
87
+ </ThemeProvider>
88
+ );
89
+ }
90
+
91
+ // 2. Read and change the theme from any descendant
92
+ function ThemeToggle() {
93
+ const { theme, resolvedTheme, setTheme } = useTheme();
94
+
95
+ return (
96
+ <button
97
+ type="button"
98
+ onClick={() => setTheme(resolvedTheme === "dark" ? "light" : "dark")}
99
+ >
100
+ Switch to {resolvedTheme === "dark" ? "light" : "dark"} mode
101
+ </button>
102
+ );
103
+ }
104
+ ```
105
+
106
+ `ThemeProvider` persists the user's choice to `localStorage` under the key
107
+ `"enact-theme"` (configurable via the `storageKey` prop). The resolved theme
108
+ (`"light"` or `"dark"`) is derived from the user's explicit choice or from
109
+ `window.matchMedia("(prefers-color-scheme: dark)")` when the theme is `"system"`.
110
+
111
+ ### Preventing theme flash on first paint
112
+
113
+ Without extra work the page renders in the default (light) state for one frame
114
+ while React hydrates — producing a visible flash when the user prefers dark.
115
+ Inline `themeInitScript` in `<head>` **before** your app bundle to apply the
116
+ correct `data-theme` attribute at browser-parse time, before any paint:
117
+
118
+ ```tsx
119
+ import {
120
+ themeInitScript,
121
+ } from "@amsterdamdatalabs/enact-design-system";
122
+
123
+ // In your HTML template, _document.tsx, or root layout:
124
+ export function Document() {
125
+ return (
126
+ <html lang="en">
127
+ <head>
128
+ {/* Must come before the app bundle — runs at parse time, before paint. */}
129
+ <script dangerouslySetInnerHTML={{ __html: themeInitScript }} />
130
+ {/* ...other head tags, then the app bundle */}
131
+ </head>
132
+ <body>...</body>
133
+ </html>
134
+ );
135
+ }
136
+ ```
137
+
138
+ If your app uses a non-default storage key, use `getThemeInitScript` to
139
+ produce a matching script:
140
+
141
+ ```tsx
142
+ import {
143
+ getThemeInitScript,
144
+ } from "@amsterdamdatalabs/enact-design-system";
145
+
146
+ const script = getThemeInitScript("my-app-theme");
147
+
148
+ // Pass the same key to ThemeProvider:
149
+ // <ThemeProvider storageKey="my-app-theme">...</ThemeProvider>
150
+ ```
151
+
152
+ The script is a self-contained IIFE:
153
+ - reads `localStorage[storageKey]`
154
+ - `"dark"` → sets `data-theme="dark"` on `<html>`
155
+ - `"light"` → ensures `data-theme` is absent
156
+ - `"system"` or missing → falls back to `window.matchMedia("(prefers-color-scheme: dark)")`
157
+ - wrapped in `try/catch` so storage or matchMedia failures are inert
158
+
159
+ Keying is identical to `ThemeProvider` so there is no conflict on hydration.
160
+
161
+ ## Layout primitives
162
+
163
+ Five composable, token-based layout components handle spacing, alignment, and
164
+ grid structure. All accept standard HTML `div` attributes in addition to the
165
+ props below.
166
+
167
+ ```tsx
168
+ import {
169
+ Box,
170
+ Container,
171
+ Grid,
172
+ Inline,
173
+ Stack,
174
+ } from "@amsterdamdatalabs/enact-design-system";
175
+
176
+ // Box — single block with optional padding, surface tint, and radius
177
+ <Box padding="4" surface="raised" radius="md">
178
+ content
179
+ </Box>
180
+
181
+ // Stack — vertical flex container
182
+ <Stack gap="4" align="center">
183
+ <div>Item A</div>
184
+ <div>Item B</div>
185
+ </Stack>
186
+
187
+ // Inline — horizontal flex container
188
+ <Inline gap="2">
189
+ <Button variant="primary">Save</Button>
190
+ <Button variant="ghost">Cancel</Button>
191
+ </Inline>
192
+
193
+ // Grid — CSS grid with a named column count
194
+ <Grid columns={3} gap="6">
195
+ <Card>One</Card>
196
+ <Card>Two</Card>
197
+ <Card>Three</Card>
198
+ </Grid>
199
+
200
+ // Container — centred, max-width wrapper
201
+ <Container width="narrow">
202
+ <Stack gap="4">...</Stack>
203
+ </Container>
204
+ ```
205
+
206
+ ## Typography
207
+
208
+ `Heading` and `Text` map directly to the system's type scale.
209
+
210
+ ```tsx
211
+ import {
212
+ Heading,
213
+ Text,
214
+ } from "@amsterdamdatalabs/enact-design-system";
215
+
216
+ // Heading — semantic element + visual size, decoupled for accessibility
217
+ <Heading level={1} size="xl">Page title</Heading>
218
+ <Heading level={2} size="md">Section title</Heading>
219
+ ```
220
+
221
+ **Accessibility note — `level` vs `size`:**
222
+ `level` controls the rendered HTML tag (`h1`–`h6`) and therefore the document
223
+ outline used by screen readers. `size` is a purely visual override — you can
224
+ render an `h2` that looks like an `h4` (or vice versa) without affecting
225
+ semantics. Always set `level` to match the document hierarchy; use `size` only
226
+ to meet visual design requirements.
227
+
228
+ ```tsx
229
+ // Text — inline/block body copy
230
+ <Text size="sm" tone="secondary">Last updated 3 days ago</Text>
231
+ <Text size="md" tone="primary">Main body copy</Text>
232
+ ```
233
+
234
+ Available sizes for both: `"xs"` `"sm"` `"md"` `"lg"` `"xl"` `"2xl"`.
235
+ Available tones: `"primary"` `"secondary"` `"muted"` `"inverse"` `"link"`.
236
+
51
237
  ## Components (17)
52
238
 
53
239
  | Group | Components |
@@ -1,7 +1,8 @@
1
- import type { HTMLAttributes } from "react";
1
+ import type { HTMLAttributes, Ref } from "react";
2
2
  export interface AvatarProps extends HTMLAttributes<HTMLSpanElement> {
3
3
  name?: string;
4
+ ref?: Ref<HTMLSpanElement>;
4
5
  size?: "sm" | "md" | "lg" | "xl";
5
6
  src?: string;
6
7
  }
7
- export declare function Avatar({ name, src, size, className, ...rest }: AvatarProps): import("react").JSX.Element;
8
+ export declare function Avatar({ name, src, size, className, ref, ...rest }: AvatarProps): import("react").JSX.Element;
@@ -1,7 +1,8 @@
1
- import type { HTMLAttributes, ReactNode } from "react";
1
+ import type { HTMLAttributes, ReactNode, Ref } from "react";
2
2
  export interface BadgeProps extends HTMLAttributes<HTMLSpanElement> {
3
3
  children?: ReactNode;
4
4
  dot?: boolean;
5
+ ref?: Ref<HTMLSpanElement>;
5
6
  tone?: "neutral" | "brand" | "info" | "success" | "warning" | "danger";
6
7
  }
7
- export declare function Badge({ tone, dot, className, children, ...rest }: BadgeProps): import("react").JSX.Element;
8
+ export declare function Badge({ tone, dot, className, children, ref, ...rest }: BadgeProps): import("react").JSX.Element;
@@ -1,10 +1,11 @@
1
- import type { ButtonHTMLAttributes, ReactNode } from "react";
1
+ import type { ButtonHTMLAttributes, ReactNode, Ref } from "react";
2
2
  export interface ButtonProps extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, "type"> {
3
3
  children?: ReactNode;
4
4
  fullWidth?: boolean;
5
5
  iconLeft?: ReactNode;
6
6
  iconRight?: ReactNode;
7
+ ref?: Ref<HTMLButtonElement>;
7
8
  size?: "sm" | "md" | "lg";
8
9
  variant?: "primary" | "secondary" | "ghost" | "danger";
9
10
  }
10
- export declare function Button({ variant, size, iconLeft, iconRight, fullWidth, disabled, className, children, ...rest }: ButtonProps): import("react").JSX.Element;
11
+ export declare function Button({ variant, size, iconLeft, iconRight, fullWidth, disabled, className, children, ref, ...rest }: ButtonProps): import("react").JSX.Element;
@@ -1,9 +1,10 @@
1
- import type { HTMLAttributes, ReactNode } from "react";
1
+ import type { HTMLAttributes, ReactNode, Ref } from "react";
2
2
  export interface CardProps extends HTMLAttributes<HTMLDivElement> {
3
3
  children?: ReactNode;
4
4
  /** Adds hover elevation + pointer affordance for clickable cards. */
5
5
  interactive?: boolean;
6
6
  padding?: "none" | "sm" | "md" | "lg";
7
+ ref?: Ref<HTMLDivElement>;
7
8
  variant?: "default" | "raised" | "sunken" | "inverse";
8
9
  }
9
- export declare function Card({ variant, padding, interactive, className, children, ...rest }: CardProps): import("react").JSX.Element;
10
+ export declare function Card({ variant, padding, interactive, className, children, ref, ...rest }: CardProps): import("react").JSX.Element;
@@ -1,9 +1,10 @@
1
- import type { ButtonHTMLAttributes, ReactNode } from "react";
1
+ import type { ButtonHTMLAttributes, ReactNode, Ref } from "react";
2
2
  export interface IconButtonProps extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, "type" | "aria-label"> {
3
3
  children?: ReactNode;
4
4
  /** Accessible label — also used as the native tooltip. Required. */
5
5
  label: string;
6
+ ref?: Ref<HTMLButtonElement>;
6
7
  size?: "sm" | "md" | "lg";
7
8
  variant?: "ghost" | "outline" | "primary";
8
9
  }
9
- export declare function IconButton({ label, size, variant, disabled, className, children, ...rest }: IconButtonProps): import("react").JSX.Element;
10
+ export declare function IconButton({ label, size, variant, disabled, className, children, ref, ...rest }: IconButtonProps): import("react").JSX.Element;
@@ -1,9 +1,10 @@
1
- import type { HTMLAttributes, ReactNode } from "react";
1
+ import type { HTMLAttributes, ReactNode, Ref } from "react";
2
2
  export interface StatProps extends HTMLAttributes<HTMLDivElement> {
3
3
  caption?: ReactNode;
4
4
  delta?: ReactNode;
5
5
  deltaDirection?: "up" | "down" | "flat";
6
6
  label: string;
7
+ ref?: Ref<HTMLDivElement>;
7
8
  value: ReactNode;
8
9
  }
9
- export declare function Stat({ label, value, delta, deltaDirection, caption, className, ...rest }: StatProps): import("react").JSX.Element;
10
+ export declare function Stat({ label, value, delta, deltaDirection, caption, className, ref, ...rest }: StatProps): import("react").JSX.Element;
@@ -1,7 +1,8 @@
1
- import type { HTMLAttributes, ReactNode } from "react";
1
+ import type { HTMLAttributes, ReactNode, Ref } from "react";
2
2
  export interface TagProps extends HTMLAttributes<HTMLSpanElement> {
3
3
  children?: ReactNode;
4
4
  /** When provided, renders a remove (×) button that calls this handler. */
5
5
  onRemove?: () => void;
6
+ ref?: Ref<HTMLSpanElement>;
6
7
  }
7
- export declare function Tag({ onRemove, className, children, ...rest }: TagProps): import("react").JSX.Element;
8
+ export declare function Tag({ onRemove, className, children, ref, ...rest }: TagProps): import("react").JSX.Element;
@@ -1,9 +1,10 @@
1
- import type { HTMLAttributes, ReactNode } from "react";
1
+ import type { HTMLAttributes, ReactNode, Ref } from "react";
2
2
  export type AlertTone = "info" | "success" | "warning" | "danger";
3
3
  export interface AlertProps extends HTMLAttributes<HTMLDivElement> {
4
4
  children?: ReactNode;
5
5
  onDismiss?: () => void;
6
+ ref?: Ref<HTMLDivElement>;
6
7
  title?: string;
7
8
  tone?: AlertTone;
8
9
  }
9
- export declare function Alert({ tone, title, onDismiss, className, children, ...rest }: AlertProps): import("react").JSX.Element;
10
+ export declare function Alert({ tone, title, onDismiss, className, children, ref, ...rest }: AlertProps): import("react").JSX.Element;
@@ -1,10 +1,11 @@
1
- import type { HTMLAttributes } from "react";
1
+ import type { HTMLAttributes, Ref } from "react";
2
2
  export type ProgressTone = "brand" | "success" | "warning" | "danger" | "accent";
3
3
  export interface ProgressProps extends HTMLAttributes<HTMLDivElement> {
4
4
  label?: string;
5
5
  max?: number;
6
+ ref?: Ref<HTMLDivElement>;
6
7
  showValue?: boolean;
7
8
  tone?: ProgressTone;
8
9
  value?: number;
9
10
  }
10
- export declare function Progress({ value, max, tone, label, showValue, className, ...rest }: ProgressProps): import("react").JSX.Element;
11
+ export declare function Progress({ value, max, tone, label, showValue, className, ref, ...rest }: ProgressProps): import("react").JSX.Element;
@@ -1,7 +1,8 @@
1
- import type { HTMLAttributes, ReactNode } from "react";
1
+ import type { HTMLAttributes, ReactNode, Ref } from "react";
2
2
  export interface TooltipProps extends Omit<HTMLAttributes<HTMLSpanElement>, "content"> {
3
3
  children?: ReactNode;
4
4
  content: ReactNode;
5
5
  placement?: "top" | "bottom" | "left" | "right";
6
+ ref?: Ref<HTMLSpanElement>;
6
7
  }
7
- export declare function Tooltip({ content, placement, className, children, ...rest }: TooltipProps): import("react").JSX.Element;
8
+ export declare function Tooltip({ content, placement, className, children, ref, ...rest }: TooltipProps): import("react").JSX.Element;
@@ -1,9 +1,10 @@
1
- import { type ChangeEvent, type LabelHTMLAttributes, type ReactNode } from "react";
1
+ import { type ChangeEvent, type LabelHTMLAttributes, type ReactNode, type Ref } from "react";
2
2
  export interface CheckboxProps extends Omit<LabelHTMLAttributes<HTMLLabelElement>, "onChange"> {
3
3
  checked?: boolean;
4
4
  defaultChecked?: boolean;
5
5
  disabled?: boolean;
6
6
  label?: ReactNode;
7
7
  onChange?: (checked: boolean, event: ChangeEvent<HTMLInputElement>) => void;
8
+ ref?: Ref<HTMLInputElement>;
8
9
  }
9
- export declare function Checkbox({ checked, defaultChecked, onChange, label, disabled, className, ...rest }: CheckboxProps): import("react").JSX.Element;
10
+ export declare function Checkbox({ checked, defaultChecked, onChange, label, disabled, className, ref, ...rest }: CheckboxProps): import("react").JSX.Element;
@@ -1,4 +1,4 @@
1
- import type { HTMLAttributes, ReactNode } from "react";
1
+ import type { HTMLAttributes, ReactNode, Ref } from "react";
2
2
  export interface FieldProps extends HTMLAttributes<HTMLDivElement> {
3
3
  children?: ReactNode;
4
4
  error?: string;
@@ -6,6 +6,7 @@ export interface FieldProps extends HTMLAttributes<HTMLDivElement> {
6
6
  /** Forwarded to the label's `for` attribute. */
7
7
  htmlFor?: string;
8
8
  label?: string;
9
+ ref?: Ref<HTMLDivElement>;
9
10
  required?: boolean;
10
11
  }
11
- export declare function Field({ label, hint, error, required, htmlFor, className, children, ...rest }: FieldProps): import("react").JSX.Element;
12
+ export declare function Field({ label, hint, error, required, htmlFor, className, children, ref, ...rest }: FieldProps): import("react").JSX.Element;
@@ -1,6 +1,7 @@
1
- import type { InputHTMLAttributes } from "react";
1
+ import type { InputHTMLAttributes, Ref } from "react";
2
2
  export interface InputProps extends Omit<InputHTMLAttributes<HTMLInputElement>, "size"> {
3
3
  invalid?: boolean;
4
+ ref?: Ref<HTMLInputElement>;
4
5
  size?: "sm" | "md" | "lg";
5
6
  }
6
- export declare function Input({ size, invalid, disabled, className, ...rest }: InputProps): import("react").JSX.Element;
7
+ export declare function Input({ size, invalid, disabled, className, ref, ...rest }: InputProps): import("react").JSX.Element;
@@ -1,7 +1,8 @@
1
- import type { ReactNode, SelectHTMLAttributes } from "react";
1
+ import type { ReactNode, Ref, SelectHTMLAttributes } from "react";
2
2
  export interface SelectProps extends Omit<SelectHTMLAttributes<HTMLSelectElement>, "size"> {
3
3
  children?: ReactNode;
4
4
  invalid?: boolean;
5
+ ref?: Ref<HTMLSelectElement>;
5
6
  size?: "sm" | "md" | "lg";
6
7
  }
7
- export declare function Select({ size, invalid, disabled, className, children, ...rest }: SelectProps): import("react").JSX.Element;
8
+ export declare function Select({ size, invalid, disabled, className, children, ref, ...rest }: SelectProps): import("react").JSX.Element;
@@ -1,9 +1,10 @@
1
- import { type ChangeEvent, type LabelHTMLAttributes, type ReactNode } from "react";
1
+ import { type ChangeEvent, type LabelHTMLAttributes, type ReactNode, type Ref } from "react";
2
2
  export interface SwitchProps extends Omit<LabelHTMLAttributes<HTMLLabelElement>, "onChange"> {
3
3
  checked?: boolean;
4
4
  defaultChecked?: boolean;
5
5
  disabled?: boolean;
6
6
  label?: ReactNode;
7
7
  onChange?: (checked: boolean, event: ChangeEvent<HTMLInputElement>) => void;
8
+ ref?: Ref<HTMLInputElement>;
8
9
  }
9
- export declare function Switch({ checked, defaultChecked, onChange, label, disabled, className, ...rest }: SwitchProps): import("react").JSX.Element;
10
+ export declare function Switch({ checked, defaultChecked, onChange, label, disabled, className, ref, ...rest }: SwitchProps): import("react").JSX.Element;
@@ -0,0 +1,10 @@
1
+ import type { HTMLAttributes, Ref } from "react";
2
+ import type { Space } from "../scale";
3
+ export interface BoxProps extends HTMLAttributes<HTMLDivElement> {
4
+ border?: boolean;
5
+ padding?: Space;
6
+ radius?: "none" | "xs" | "sm" | "md" | "lg" | "xl" | "full";
7
+ ref?: Ref<HTMLDivElement>;
8
+ surface?: "default" | "raised" | "sunken";
9
+ }
10
+ export declare function Box({ padding, radius, surface, border, className, children, ref, ...rest }: BoxProps): import("react").JSX.Element;
@@ -0,0 +1 @@
1
+ export { Box, type BoxProps } from "./Box";
@@ -0,0 +1,9 @@
1
+ import type { HTMLAttributes, Ref } from "react";
2
+ import type { Space } from "../scale";
3
+ export interface ContainerProps extends HTMLAttributes<HTMLDivElement> {
4
+ /** Horizontal padding (padding-inline). */
5
+ gutter?: Space;
6
+ ref?: Ref<HTMLDivElement>;
7
+ width?: "max" | "narrow";
8
+ }
9
+ export declare function Container({ width, gutter, className, children, ref, ...rest }: ContainerProps): import("react").JSX.Element;
@@ -0,0 +1 @@
1
+ export { Container, type ContainerProps } from "./Container";
@@ -0,0 +1,8 @@
1
+ import type { HTMLAttributes, Ref } from "react";
2
+ import { type Space } from "../scale";
3
+ export interface GridProps extends HTMLAttributes<HTMLDivElement> {
4
+ columns?: 1 | 2 | 3 | 4 | 6 | 12;
5
+ gap?: Space;
6
+ ref?: Ref<HTMLDivElement>;
7
+ }
8
+ export declare function Grid({ columns, gap, className, children, ref, ...rest }: GridProps): import("react").JSX.Element;
@@ -0,0 +1 @@
1
+ export { Grid, type GridProps } from "./Grid";
@@ -0,0 +1,10 @@
1
+ import type { HTMLAttributes, Ref } from "react";
2
+ import { type Align, type Justify, type Space } from "../scale";
3
+ export interface InlineProps extends HTMLAttributes<HTMLDivElement> {
4
+ align?: Align;
5
+ gap?: Space;
6
+ justify?: Justify;
7
+ ref?: Ref<HTMLDivElement>;
8
+ wrap?: boolean;
9
+ }
10
+ export declare function Inline({ gap, align, justify, wrap, className, children, ref, ...rest }: InlineProps): import("react").JSX.Element;
@@ -0,0 +1 @@
1
+ export { Inline, type InlineProps } from "./Inline";
@@ -0,0 +1,9 @@
1
+ import type { HTMLAttributes, Ref } from "react";
2
+ import { type Align, type Justify, type Space } from "../scale";
3
+ export interface StackProps extends HTMLAttributes<HTMLDivElement> {
4
+ align?: Align;
5
+ gap?: Space;
6
+ justify?: Justify;
7
+ ref?: Ref<HTMLDivElement>;
8
+ }
9
+ export declare function Stack({ gap, align, justify, className, children, ref, ...rest }: StackProps): import("react").JSX.Element;
@@ -0,0 +1 @@
1
+ export { Stack, type StackProps } from "./Stack";
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Shared scales for layout primitives. Keep these unions in sync with the
3
+ * spacing tokens (--space-0…16) and flex/grid alignment keywords so every
4
+ * primitive speaks the same vocabulary.
5
+ */
6
+ export type Space = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "8" | "10" | "12" | "16";
7
+ export type Align = "start" | "center" | "end" | "stretch";
8
+ export type Justify = "start" | "center" | "end" | "between";
9
+ /** prop union → CSS-module gap class name (defined per module). */
10
+ export declare const gapClass: {
11
+ readonly "0": "gap0";
12
+ readonly "1": "gap1";
13
+ readonly "2": "gap2";
14
+ readonly "3": "gap3";
15
+ readonly "4": "gap4";
16
+ readonly "5": "gap5";
17
+ readonly "6": "gap6";
18
+ readonly "8": "gap8";
19
+ readonly "10": "gap10";
20
+ readonly "12": "gap12";
21
+ readonly "16": "gap16";
22
+ };
23
+ /** prop union → CSS-module align class name (defined per module). */
24
+ export declare const alignClass: {
25
+ readonly start: "alignStart";
26
+ readonly center: "alignCenter";
27
+ readonly end: "alignEnd";
28
+ readonly stretch: "alignStretch";
29
+ };
30
+ /** prop union → CSS-module justify class name (defined per module). */
31
+ export declare const justifyClass: {
32
+ readonly start: "justifyStart";
33
+ readonly center: "justifyCenter";
34
+ readonly end: "justifyEnd";
35
+ readonly between: "justifyBetween";
36
+ };
@@ -1,4 +1,4 @@
1
- import type { HTMLAttributes, MouseEventHandler } from "react";
1
+ import type { HTMLAttributes, MouseEventHandler, Ref } from "react";
2
2
  export interface BreadcrumbItem {
3
3
  href?: string;
4
4
  label: string;
@@ -6,5 +6,6 @@ export interface BreadcrumbItem {
6
6
  }
7
7
  export interface BreadcrumbProps extends HTMLAttributes<HTMLElement> {
8
8
  items: BreadcrumbItem[];
9
+ ref?: Ref<HTMLElement>;
9
10
  }
10
- export declare function Breadcrumb({ items, className, ...rest }: BreadcrumbProps): import("react").JSX.Element;
11
+ export declare function Breadcrumb({ items, className, ref, ...rest }: BreadcrumbProps): import("react").JSX.Element;
@@ -1,4 +1,4 @@
1
- import { type HTMLAttributes } from "react";
1
+ import { type HTMLAttributes, type Ref } from "react";
2
2
  export interface TabItem {
3
3
  /** Optional count pill rendered after the label. */
4
4
  count?: number;
@@ -10,6 +10,7 @@ export interface TabsProps extends Omit<HTMLAttributes<HTMLDivElement>, "onChang
10
10
  defaultActive?: string;
11
11
  items: TabItem[];
12
12
  onChange?: (id: string) => void;
13
+ ref?: Ref<HTMLDivElement>;
13
14
  size?: "sm" | "md";
14
15
  }
15
- export declare function Tabs({ items, active, defaultActive, onChange, size, className, ...rest }: TabsProps): import("react").JSX.Element;
16
+ export declare function Tabs({ items, active, defaultActive, onChange, size, className, ref, ...rest }: TabsProps): import("react").JSX.Element;
@@ -0,0 +1,17 @@
1
+ import { type HTMLAttributes, type ReactNode, type Ref } from "react";
2
+ export interface ModalProps extends Omit<HTMLAttributes<HTMLDivElement>, "title"> {
3
+ children: ReactNode;
4
+ /** Close when the backdrop (not the panel) is clicked. Defaults to true. */
5
+ closeOnBackdrop?: boolean;
6
+ /** Called on Escape, backdrop click (when allowed), or any dismissal. */
7
+ onClose: () => void;
8
+ /** Whether the modal is open. Renders nothing when false. */
9
+ open: boolean;
10
+ /** Ref to the dialog PANEL element. */
11
+ ref?: Ref<HTMLDivElement>;
12
+ /** Panel max-width preset. */
13
+ size?: "sm" | "md" | "lg";
14
+ /** Optional heading; when set, wires `aria-labelledby` to its element. */
15
+ title?: ReactNode;
16
+ }
17
+ export declare function Modal({ open, onClose, title, size, closeOnBackdrop, className, children, ref, ...rest }: ModalProps): import("react").ReactPortal | null;
@@ -0,0 +1 @@
1
+ export { Modal, type ModalProps } from "./Modal";
@@ -0,0 +1,15 @@
1
+ import { type ReactNode } from "react";
2
+ export type Theme = "light" | "dark" | "system";
3
+ export type ResolvedTheme = "light" | "dark";
4
+ export interface ThemeContextValue {
5
+ resolvedTheme: ResolvedTheme;
6
+ setTheme: (theme: Theme) => void;
7
+ theme: Theme;
8
+ }
9
+ export interface ThemeProviderProps {
10
+ children: ReactNode;
11
+ defaultTheme?: Theme;
12
+ storageKey?: string;
13
+ }
14
+ export declare function ThemeProvider({ children, defaultTheme, storageKey, }: ThemeProviderProps): import("react").JSX.Element;
15
+ export declare function useTheme(): ThemeContextValue;
@@ -0,0 +1,2 @@
1
+ export { type ResolvedTheme, type Theme, type ThemeContextValue, ThemeProvider, type ThemeProviderProps, useTheme, } from "./ThemeProvider";
2
+ export { getThemeInitScript, themeInitScript } from "./themeInitScript";
@@ -0,0 +1,37 @@
1
+ /**
2
+ * No-flash theme initialisation script.
3
+ *
4
+ * `themeInitScript` is a string containing a self-contained IIFE that can be
5
+ * inlined in `<head>` **before** the app bundle. When the browser executes it
6
+ * prior to first paint it sets (or removes) `data-theme="dark"` on
7
+ * `document.documentElement` so the page renders in the correct theme without a
8
+ * light-flash followed by a dark switch.
9
+ *
10
+ * Keying is identical to ThemeProvider:
11
+ * dark → `data-theme="dark"` on `<html>`
12
+ * light → attribute ABSENT on `<html>`
13
+ * system (or missing / unknown) → resolved via matchMedia
14
+ *
15
+ * The module is dependency-free and SSR-inert — importing it executes nothing.
16
+ * The IIFE only runs when the consumer inlines the string.
17
+ */
18
+ /**
19
+ * Build the no-flash IIFE string for a given storage key.
20
+ *
21
+ * @param storageKey localStorage key to read the persisted theme from.
22
+ * Must match the `storageKey` prop passed to `<ThemeProvider>`.
23
+ */
24
+ export declare function getThemeInitScript(storageKey?: string): string;
25
+ /**
26
+ * Pre-built no-flash script string using the default storage key (`"enact-theme"`).
27
+ *
28
+ * Inline this in a `<script>` tag in `<head>` before your app bundle:
29
+ *
30
+ * ```tsx
31
+ * import { themeInitScript } from "@enact/design-system";
32
+ *
33
+ * // In your HTML template / _document.tsx / root layout:
34
+ * <script dangerouslySetInnerHTML={{ __html: themeInitScript }} />
35
+ * ```
36
+ */
37
+ export declare const themeInitScript: string;
@@ -0,0 +1,9 @@
1
+ import type { HTMLAttributes, Ref } from "react";
2
+ export interface HeadingProps extends HTMLAttributes<HTMLHeadingElement> {
3
+ level: 1 | 2 | 3 | 4 | 5 | 6;
4
+ ref?: Ref<HTMLHeadingElement>;
5
+ size?: "xs" | "sm" | "md" | "lg" | "xl" | "2xl";
6
+ tone?: "primary" | "secondary" | "muted" | "inverse" | "link";
7
+ weight?: "regular" | "medium" | "semibold" | "bold";
8
+ }
9
+ export declare function Heading({ level, size, tone, weight, className, children, ref, ...rest }: HeadingProps): import("react").JSX.Element;
@@ -0,0 +1 @@
1
+ export { Heading, type HeadingProps } from "./Heading";