@amsterdamdatalabs/enact-design-system 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/README.md +115 -0
  2. package/dist/components/core/Avatar/Avatar.d.ts +7 -0
  3. package/dist/components/core/Avatar/index.d.ts +1 -0
  4. package/dist/components/core/Badge/Badge.d.ts +7 -0
  5. package/dist/components/core/Badge/index.d.ts +1 -0
  6. package/dist/components/core/Button/Button.d.ts +10 -0
  7. package/dist/components/core/Button/index.d.ts +1 -0
  8. package/dist/components/core/Card/Card.d.ts +9 -0
  9. package/dist/components/core/Card/index.d.ts +1 -0
  10. package/dist/components/core/IconButton/IconButton.d.ts +9 -0
  11. package/dist/components/core/IconButton/index.d.ts +1 -0
  12. package/dist/components/core/Stat/Stat.d.ts +9 -0
  13. package/dist/components/core/Stat/index.d.ts +1 -0
  14. package/dist/components/core/Tag/Tag.d.ts +7 -0
  15. package/dist/components/core/Tag/index.d.ts +1 -0
  16. package/dist/components/feedback/Alert/Alert.d.ts +9 -0
  17. package/dist/components/feedback/Alert/index.d.ts +1 -0
  18. package/dist/components/feedback/Progress/Progress.d.ts +10 -0
  19. package/dist/components/feedback/Progress/index.d.ts +1 -0
  20. package/dist/components/feedback/Tooltip/Tooltip.d.ts +7 -0
  21. package/dist/components/feedback/Tooltip/index.d.ts +1 -0
  22. package/dist/components/forms/Checkbox/Checkbox.d.ts +9 -0
  23. package/dist/components/forms/Checkbox/index.d.ts +1 -0
  24. package/dist/components/forms/Field/Field.d.ts +11 -0
  25. package/dist/components/forms/Field/index.d.ts +1 -0
  26. package/dist/components/forms/Input/Input.d.ts +6 -0
  27. package/dist/components/forms/Input/index.d.ts +1 -0
  28. package/dist/components/forms/Select/Select.d.ts +7 -0
  29. package/dist/components/forms/Select/index.d.ts +1 -0
  30. package/dist/components/forms/Switch/Switch.d.ts +9 -0
  31. package/dist/components/forms/Switch/index.d.ts +1 -0
  32. package/dist/components/navigation/Breadcrumb/Breadcrumb.d.ts +10 -0
  33. package/dist/components/navigation/Breadcrumb/index.d.ts +1 -0
  34. package/dist/components/navigation/Tabs/Tabs.d.ts +15 -0
  35. package/dist/components/navigation/Tabs/index.d.ts +1 -0
  36. package/dist/enact-design-system.css +1 -0
  37. package/dist/index.d.ts +24 -0
  38. package/dist/index.js +749 -0
  39. package/dist/lib/cx.d.ts +2 -0
  40. package/dist/tokens.css +449 -0
  41. package/package.json +61 -0
package/README.md ADDED
@@ -0,0 +1,115 @@
1
+ # @amsterdamdatalabs/enact-design-system
2
+
3
+ The single source of truth for Enact product UI: React components + a 3-tier
4
+ design-token system. Change a token or a component once, and every product that
5
+ consumes the package updates everywhere. **Product code uses only the public
6
+ components and semantic tokens — never raw colors, pixels, fonts, or component
7
+ internals.**
8
+
9
+ Ported from the proven Amsterdam Data Labs (ADL) system in `net-revenue-demo`.
10
+
11
+ ## Stack
12
+
13
+ - **Bun** for install/scripts, **React 19** + **TypeScript**, styled with **CSS Modules**.
14
+ - Tokens are plain **CSS custom properties** (primitive `--adl-*` → semantic → dark mode).
15
+ - Built with **Vite** (library mode, ESM) + `tsc` for declarations.
16
+
17
+ ## Install & develop
18
+
19
+ ```bash
20
+ bun install
21
+ bun run docs # browsable component showcase (light/dark toggle) at localhost:5180
22
+ bun run typecheck # tsc --noEmit (also enforces prop/variant contracts)
23
+ bun run lint # Biome + Ultracite + GritQL adherence (see below)
24
+ bun run format # Biome formatter (write)
25
+ bun run test # bun test — render/behavior + contract + styling guards
26
+ bun run test:visual # Playwright visual regression (light + dark)
27
+ bun run test:visual:update # refresh visual baselines after an intended change
28
+ bun run check # typecheck + lint + test (the pre-merge gate)
29
+ bun run build # dist/: ESM + .d.ts + design-system.css + tokens.css
30
+ ```
31
+
32
+ ## Usage in a product app
33
+
34
+ ```tsx
35
+ import "@amsterdamdatalabs/enact-design-system/tokens.css"; // design tokens (incl. dark mode)
36
+ import "@amsterdamdatalabs/enact-design-system/styles.css"; // component styles
37
+ import { Button, Card, Stat } from "@amsterdamdatalabs/enact-design-system";
38
+
39
+ export function Example() {
40
+ return (
41
+ <Card variant="raised">
42
+ <Stat label="Net revenue" value="$1.24M" delta="12.4%" deltaDirection="up" />
43
+ <Button variant="primary">View report</Button>
44
+ </Card>
45
+ );
46
+ }
47
+ ```
48
+
49
+ Dark mode: set `data-theme="dark"` on `<html>` (or any subtree root).
50
+
51
+ ## Components (17)
52
+
53
+ | Group | Components |
54
+ |---|---|
55
+ | core | `Button` `IconButton` `Badge` `Avatar` `Card` `Stat` `Tag` |
56
+ | feedback | `Alert` `Progress` `Tooltip` |
57
+ | forms | `Input` `Select` `Checkbox` `Switch` `Field` |
58
+ | navigation | `Tabs` `Breadcrumb` |
59
+
60
+ ## Tooling
61
+
62
+ **Biome + Ultracite** is the linter/formatter (`bun run lint` / `format`), with
63
+ strict accessibility, correctness, and style rules. Ultracite's a11y rules are
64
+ enforced — decorative SVGs are hidden, roles/labels are required, etc.
65
+
66
+ ## Enforcement — "no local overrides"
67
+
68
+ Four mechanisms, each independently verified to *fire*:
69
+
70
+ | Rule | Enforced by |
71
+ |---|---|
72
+ | no raw hex colors in TS/JS | **GritQL plugin** `.grit/no-raw-hex.grit` |
73
+ | no raw `px` in TS/JS | **GritQL plugin** `.grit/no-raw-px.grit` |
74
+ | only system fonts (Space Grotesk / Manrope / IBM Plex Mono) | **GritQL plugin** `.grit/no-offsystem-font.grit` |
75
+ | valid component props + enum values (`variant="huge"` fails) | **TypeScript** (`bun run typecheck`) |
76
+ | no deep imports into internals | the package `exports` map (physical — deep paths aren't exported) |
77
+
78
+ Biome lacks ESLint's `no-restricted-syntax`, so the raw-value rules are authored as
79
+ GritQL plugins (`engine biome(1.0)`, matching `JsStringLiteralExpression`). Biome
80
+ **errors on a broken plugin**, so the enforcement can't silently rot. The library
81
+ lints itself, and the showcase doubles as a live adherence example.
82
+
83
+ ## Testing — drift protection
84
+
85
+ | Layer | What it catches | Run |
86
+ |---|---|---|
87
+ | **A. Render + behavior** | a component breaks; controlled/uncontrolled state; ARIA roles | `bun test` |
88
+ | **B. Contract snapshots** | a token or variant renamed/removed | `bun test` |
89
+ | **C. Styling guard** | raw hex in component CSS; a `var(--…)` that references an undefined token | `bun test` |
90
+ | **D. Visual regression** | contrast/visual drift in light **or** dark, every section | `bun run test:visual` |
91
+
92
+ After an *intended* visual change, refresh baselines with `bun run test:visual:update`.
93
+
94
+ ## Layout
95
+
96
+ ```
97
+ src/
98
+ tokens/ CSS custom properties (ported): colors typography spacing effects fonts base + index.css
99
+ components/ core/ feedback/ forms/ navigation/ — each: Name.tsx + Name.module.css + index.ts
100
+ index.ts the ONLY public entry point
101
+ docs/ HTML showcase (bun run docs)
102
+ .grit/ GritQL adherence plugins (raw hex/px/font bans)
103
+ test/ bun test (A/B/C) + visual/ Playwright specs (D)
104
+ biome.jsonc Biome + Ultracite config (extends + GritQL plugins)
105
+ ```
106
+
107
+ ## Notes
108
+
109
+ - Components were re-authored from the ADL bundle's source (the bundle's behavior is
110
+ the reference). Visual values map 1:1 to the same semantic tokens.
111
+ - Prop contracts are TypeScript types: components extend the native HTML attribute
112
+ types, so standard attributes (`id`, `aria-*`, form attrs) are allowed by design —
113
+ required for accessible label association (`Field htmlFor` → input `id`).
114
+ - Distribution model (npm publish vs. monorepo workspace) is intentionally deferred;
115
+ the build artifact supports either.
@@ -0,0 +1,7 @@
1
+ import type { HTMLAttributes } from "react";
2
+ export interface AvatarProps extends HTMLAttributes<HTMLSpanElement> {
3
+ name?: string;
4
+ size?: "sm" | "md" | "lg" | "xl";
5
+ src?: string;
6
+ }
7
+ export declare function Avatar({ name, src, size, className, ...rest }: AvatarProps): import("react").JSX.Element;
@@ -0,0 +1 @@
1
+ export { Avatar, type AvatarProps } from "./Avatar";
@@ -0,0 +1,7 @@
1
+ import type { HTMLAttributes, ReactNode } from "react";
2
+ export interface BadgeProps extends HTMLAttributes<HTMLSpanElement> {
3
+ children?: ReactNode;
4
+ dot?: boolean;
5
+ tone?: "neutral" | "brand" | "info" | "success" | "warning" | "danger";
6
+ }
7
+ export declare function Badge({ tone, dot, className, children, ...rest }: BadgeProps): import("react").JSX.Element;
@@ -0,0 +1 @@
1
+ export { Badge, type BadgeProps } from "./Badge";
@@ -0,0 +1,10 @@
1
+ import type { ButtonHTMLAttributes, ReactNode } from "react";
2
+ export interface ButtonProps extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, "type"> {
3
+ children?: ReactNode;
4
+ fullWidth?: boolean;
5
+ iconLeft?: ReactNode;
6
+ iconRight?: ReactNode;
7
+ size?: "sm" | "md" | "lg";
8
+ variant?: "primary" | "secondary" | "ghost" | "danger";
9
+ }
10
+ export declare function Button({ variant, size, iconLeft, iconRight, fullWidth, disabled, className, children, ...rest }: ButtonProps): import("react").JSX.Element;
@@ -0,0 +1 @@
1
+ export { Button, type ButtonProps } from "./Button";
@@ -0,0 +1,9 @@
1
+ import type { HTMLAttributes, ReactNode } from "react";
2
+ export interface CardProps extends HTMLAttributes<HTMLDivElement> {
3
+ children?: ReactNode;
4
+ /** Adds hover elevation + pointer affordance for clickable cards. */
5
+ interactive?: boolean;
6
+ padding?: "none" | "sm" | "md" | "lg";
7
+ variant?: "default" | "raised" | "sunken" | "inverse";
8
+ }
9
+ export declare function Card({ variant, padding, interactive, className, children, ...rest }: CardProps): import("react").JSX.Element;
@@ -0,0 +1 @@
1
+ export { Card, type CardProps } from "./Card";
@@ -0,0 +1,9 @@
1
+ import type { ButtonHTMLAttributes, ReactNode } from "react";
2
+ export interface IconButtonProps extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, "type" | "aria-label"> {
3
+ children?: ReactNode;
4
+ /** Accessible label — also used as the native tooltip. Required. */
5
+ label: string;
6
+ size?: "sm" | "md" | "lg";
7
+ variant?: "ghost" | "outline" | "primary";
8
+ }
9
+ export declare function IconButton({ label, size, variant, disabled, className, children, ...rest }: IconButtonProps): import("react").JSX.Element;
@@ -0,0 +1 @@
1
+ export { IconButton, type IconButtonProps } from "./IconButton";
@@ -0,0 +1,9 @@
1
+ import type { HTMLAttributes, ReactNode } from "react";
2
+ export interface StatProps extends HTMLAttributes<HTMLDivElement> {
3
+ caption?: ReactNode;
4
+ delta?: ReactNode;
5
+ deltaDirection?: "up" | "down" | "flat";
6
+ label: string;
7
+ value: ReactNode;
8
+ }
9
+ export declare function Stat({ label, value, delta, deltaDirection, caption, className, ...rest }: StatProps): import("react").JSX.Element;
@@ -0,0 +1 @@
1
+ export { Stat, type StatProps } from "./Stat";
@@ -0,0 +1,7 @@
1
+ import type { HTMLAttributes, ReactNode } from "react";
2
+ export interface TagProps extends HTMLAttributes<HTMLSpanElement> {
3
+ children?: ReactNode;
4
+ /** When provided, renders a remove (×) button that calls this handler. */
5
+ onRemove?: () => void;
6
+ }
7
+ export declare function Tag({ onRemove, className, children, ...rest }: TagProps): import("react").JSX.Element;
@@ -0,0 +1 @@
1
+ export { Tag, type TagProps } from "./Tag";
@@ -0,0 +1,9 @@
1
+ import type { HTMLAttributes, ReactNode } from "react";
2
+ export type AlertTone = "info" | "success" | "warning" | "danger";
3
+ export interface AlertProps extends HTMLAttributes<HTMLDivElement> {
4
+ children?: ReactNode;
5
+ onDismiss?: () => void;
6
+ title?: string;
7
+ tone?: AlertTone;
8
+ }
9
+ export declare function Alert({ tone, title, onDismiss, className, children, ...rest }: AlertProps): import("react").JSX.Element;
@@ -0,0 +1 @@
1
+ export { Alert, type AlertProps, type AlertTone } from "./Alert";
@@ -0,0 +1,10 @@
1
+ import type { HTMLAttributes } from "react";
2
+ export type ProgressTone = "brand" | "success" | "warning" | "danger" | "accent";
3
+ export interface ProgressProps extends HTMLAttributes<HTMLDivElement> {
4
+ label?: string;
5
+ max?: number;
6
+ showValue?: boolean;
7
+ tone?: ProgressTone;
8
+ value?: number;
9
+ }
10
+ export declare function Progress({ value, max, tone, label, showValue, className, ...rest }: ProgressProps): import("react").JSX.Element;
@@ -0,0 +1 @@
1
+ export { Progress, type ProgressProps, type ProgressTone } from "./Progress";
@@ -0,0 +1,7 @@
1
+ import type { HTMLAttributes, ReactNode } from "react";
2
+ export interface TooltipProps extends Omit<HTMLAttributes<HTMLSpanElement>, "content"> {
3
+ children?: ReactNode;
4
+ content: ReactNode;
5
+ placement?: "top" | "bottom" | "left" | "right";
6
+ }
7
+ export declare function Tooltip({ content, placement, className, children, ...rest }: TooltipProps): import("react").JSX.Element;
@@ -0,0 +1 @@
1
+ export { Tooltip, type TooltipProps } from "./Tooltip";
@@ -0,0 +1,9 @@
1
+ import { type ChangeEvent, type LabelHTMLAttributes, type ReactNode } from "react";
2
+ export interface CheckboxProps extends Omit<LabelHTMLAttributes<HTMLLabelElement>, "onChange"> {
3
+ checked?: boolean;
4
+ defaultChecked?: boolean;
5
+ disabled?: boolean;
6
+ label?: ReactNode;
7
+ onChange?: (checked: boolean, event: ChangeEvent<HTMLInputElement>) => void;
8
+ }
9
+ export declare function Checkbox({ checked, defaultChecked, onChange, label, disabled, className, ...rest }: CheckboxProps): import("react").JSX.Element;
@@ -0,0 +1 @@
1
+ export { Checkbox, type CheckboxProps } from "./Checkbox";
@@ -0,0 +1,11 @@
1
+ import type { HTMLAttributes, ReactNode } from "react";
2
+ export interface FieldProps extends HTMLAttributes<HTMLDivElement> {
3
+ children?: ReactNode;
4
+ error?: string;
5
+ hint?: string;
6
+ /** Forwarded to the label's `for` attribute. */
7
+ htmlFor?: string;
8
+ label?: string;
9
+ required?: boolean;
10
+ }
11
+ export declare function Field({ label, hint, error, required, htmlFor, className, children, ...rest }: FieldProps): import("react").JSX.Element;
@@ -0,0 +1 @@
1
+ export { Field, type FieldProps } from "./Field";
@@ -0,0 +1,6 @@
1
+ import type { InputHTMLAttributes } from "react";
2
+ export interface InputProps extends Omit<InputHTMLAttributes<HTMLInputElement>, "size"> {
3
+ invalid?: boolean;
4
+ size?: "sm" | "md" | "lg";
5
+ }
6
+ export declare function Input({ size, invalid, disabled, className, ...rest }: InputProps): import("react").JSX.Element;
@@ -0,0 +1 @@
1
+ export { Input, type InputProps } from "./Input";
@@ -0,0 +1,7 @@
1
+ import type { ReactNode, SelectHTMLAttributes } from "react";
2
+ export interface SelectProps extends Omit<SelectHTMLAttributes<HTMLSelectElement>, "size"> {
3
+ children?: ReactNode;
4
+ invalid?: boolean;
5
+ size?: "sm" | "md" | "lg";
6
+ }
7
+ export declare function Select({ size, invalid, disabled, className, children, ...rest }: SelectProps): import("react").JSX.Element;
@@ -0,0 +1 @@
1
+ export { Select, type SelectProps } from "./Select";
@@ -0,0 +1,9 @@
1
+ import { type ChangeEvent, type LabelHTMLAttributes, type ReactNode } from "react";
2
+ export interface SwitchProps extends Omit<LabelHTMLAttributes<HTMLLabelElement>, "onChange"> {
3
+ checked?: boolean;
4
+ defaultChecked?: boolean;
5
+ disabled?: boolean;
6
+ label?: ReactNode;
7
+ onChange?: (checked: boolean, event: ChangeEvent<HTMLInputElement>) => void;
8
+ }
9
+ export declare function Switch({ checked, defaultChecked, onChange, label, disabled, className, ...rest }: SwitchProps): import("react").JSX.Element;
@@ -0,0 +1 @@
1
+ export { Switch, type SwitchProps } from "./Switch";
@@ -0,0 +1,10 @@
1
+ import type { HTMLAttributes, MouseEventHandler } from "react";
2
+ export interface BreadcrumbItem {
3
+ href?: string;
4
+ label: string;
5
+ onClick?: MouseEventHandler<HTMLAnchorElement>;
6
+ }
7
+ export interface BreadcrumbProps extends HTMLAttributes<HTMLElement> {
8
+ items: BreadcrumbItem[];
9
+ }
10
+ export declare function Breadcrumb({ items, className, ...rest }: BreadcrumbProps): import("react").JSX.Element;
@@ -0,0 +1 @@
1
+ export { Breadcrumb, type BreadcrumbItem, type BreadcrumbProps, } from "./Breadcrumb";
@@ -0,0 +1,15 @@
1
+ import { type HTMLAttributes } from "react";
2
+ export interface TabItem {
3
+ /** Optional count pill rendered after the label. */
4
+ count?: number;
5
+ id: string;
6
+ label: string;
7
+ }
8
+ export interface TabsProps extends Omit<HTMLAttributes<HTMLDivElement>, "onChange"> {
9
+ active?: string;
10
+ defaultActive?: string;
11
+ items: TabItem[];
12
+ onChange?: (id: string) => void;
13
+ size?: "sm" | "md";
14
+ }
15
+ export declare function Tabs({ items, active, defaultActive, onChange, size, className, ...rest }: TabsProps): import("react").JSX.Element;
@@ -0,0 +1 @@
1
+ export { type TabItem, Tabs, type TabsProps } from "./Tabs";
@@ -0,0 +1 @@
1
+ ._avatar_yqge8_1{display:inline-flex;flex-shrink:0;align-items:center;justify-content:center;overflow:hidden;font-family:var(--font-display);font-weight:var(--weight-semibold);color:var(--adl-teal-800);background:var(--adl-teal-100);border-radius:var(--radius-full)}._hasImage_yqge8_15{background:var(--bg-muted)}._img_yqge8_19{width:100%;height:100%;object-fit:cover}._sm_yqge8_26{width:28px;height:28px;font-size:11px}._md_yqge8_31{width:36px;height:36px;font-size:14px}._lg_yqge8_36{width:48px;height:48px;font-size:18px}._xl_yqge8_41{width:64px;height:64px;font-size:24px}._badge_1ndhf_1{display:inline-flex;gap:var(--space-1-5);align-items:center;height:22px;padding:0 var(--space-2);font-family:var(--font-body);font-size:var(--text-xs);font-weight:var(--weight-semibold);line-height:1;white-space:nowrap;border-radius:var(--radius-xs)}._dot_1ndhf_15{width:6px;height:6px;background:currentColor;border-radius:var(--radius-full)}._neutral_1ndhf_23{color:var(--text-secondary);background:var(--bg-muted)}._brand_1ndhf_27{color:var(--tint-brand-fg);background:var(--brand-primary-subtle)}._info_1ndhf_31{color:var(--tint-info-fg);background:var(--feedback-info-subtle)}._success_1ndhf_35{color:var(--tint-success-fg);background:var(--feedback-success-subtle)}._warning_1ndhf_39{color:var(--tint-warning-fg);background:var(--feedback-warning-subtle)}._danger_1ndhf_43{color:var(--tint-danger-fg);background:var(--feedback-danger-subtle)}._btn_1m6dq_1{display:inline-flex;align-items:center;justify-content:center;font-family:var(--font-body);font-weight:var(--weight-semibold);line-height:1;white-space:nowrap;cursor:pointer;border:1px solid transparent;border-radius:var(--radius-sm);transition:background var(--duration-fast) var(--ease-out)}._btn_1m6dq_1:disabled{cursor:not-allowed;opacity:.45}._fullWidth_1m6dq_20{display:flex;width:100%}._sm_1m6dq_26{gap:var(--space-1-5);height:32px;padding:0 var(--space-3);font-size:var(--text-xs)}._md_1m6dq_32{gap:var(--space-2);height:40px;padding:0 var(--space-4);font-size:var(--text-sm)}._lg_1m6dq_38{gap:var(--space-2-5);height:48px;padding:0 var(--space-6);font-size:var(--text-md)}._primary_1m6dq_46{color:var(--text-on-brand);background:var(--brand-primary)}._primary_1m6dq_46:hover:not(:disabled){background:var(--brand-primary-hover)}._primary_1m6dq_46:active:not(:disabled){background:var(--brand-primary-active)}._secondary_1m6dq_57{color:var(--text-primary);background:var(--surface-default);border-color:var(--border-strong)}._secondary_1m6dq_57:hover:not(:disabled){background:var(--bg-subtle)}._secondary_1m6dq_57:active:not(:disabled){background:var(--bg-muted)}._ghost_1m6dq_71{color:var(--text-secondary);background:transparent}._ghost_1m6dq_71:hover:not(:disabled){background:var(--bg-subtle)}._ghost_1m6dq_71:active:not(:disabled){background:var(--bg-muted)}._danger_1m6dq_82{color:var(--text-inverse);background:var(--feedback-danger)}._danger_1m6dq_82:hover:not(:disabled){background:var(--adl-red-600)}._danger_1m6dq_82:active:not(:disabled){background:var(--adl-red-700)}._card_1tzae_1{border-radius:var(--radius-md);transition:box-shadow var(--duration-base) var(--ease-out),border-color var(--duration-base) var(--ease-out)}._padNone_1tzae_9{padding:0}._padSm_1tzae_12{padding:var(--space-4)}._padMd_1tzae_15{padding:var(--space-6)}._padLg_1tzae_18{padding:var(--space-8)}._default_1tzae_23{background:var(--surface-default);border:1px solid var(--border-subtle);box-shadow:var(--shadow-xs)}._raised_1tzae_28{background:var(--surface-default);border:1px solid var(--border-subtle);box-shadow:var(--shadow-md)}._sunken_1tzae_33{background:var(--surface-sunken);border:1px solid var(--border-subtle);box-shadow:none}._inverse_1tzae_38{--text-primary: var(--adl-neutral-50);--text-secondary: var(--adl-blue-200);--text-muted: var(--adl-navy-300);color:var(--text-primary);background:var(--adl-navy-900);border:1px solid var(--adl-navy-700);box-shadow:var(--shadow-sm)}._interactive_1tzae_49{cursor:pointer}._interactive_1tzae_49:hover{border-color:var(--border-default);box-shadow:var(--shadow-md)}._btn_2g73d_1{display:inline-flex;align-items:center;justify-content:center;cursor:pointer;border:1px solid transparent;border-radius:var(--radius-sm);transition:background var(--duration-fast) var(--ease-out)}._btn_2g73d_1:disabled{cursor:not-allowed;opacity:.45}._sm_2g73d_17{width:28px;height:28px}._md_2g73d_21{width:36px;height:36px}._lg_2g73d_25{width:44px;height:44px}._ghost_2g73d_31{color:var(--text-secondary);background:transparent}._ghost_2g73d_31:hover:not(:disabled){background:var(--bg-subtle)}._outline_2g73d_39{color:var(--text-secondary);background:var(--surface-default);border-color:var(--border-strong)}._outline_2g73d_39:hover:not(:disabled){background:var(--bg-subtle)}._primary_2g73d_48{color:var(--text-on-brand);background:var(--brand-primary)}._primary_2g73d_48:hover:not(:disabled){background:var(--brand-primary-hover)}._stat_1uc8c_1{display:flex;flex-direction:column;gap:var(--space-1)}._label_1uc8c_7{font-family:var(--font-body);font-size:var(--text-xs);font-weight:var(--weight-semibold);color:var(--text-muted);text-transform:uppercase;letter-spacing:var(--tracking-wide)}._valueRow_1uc8c_16{display:flex;gap:var(--space-2);align-items:baseline}._value_1uc8c_16{font-family:var(--font-display);font-size:var(--text-3xl);font-weight:var(--weight-bold);line-height:var(--leading-tight);color:var(--text-primary);letter-spacing:var(--tracking-tight)}._delta_1uc8c_31{display:inline-flex;gap:3px;align-items:center;font-family:var(--font-body);font-size:var(--text-xs);font-weight:var(--weight-semibold)}._deltaUp_1uc8c_40{color:var(--feedback-success)}._deltaDown_1uc8c_43{color:var(--feedback-danger)}._deltaFlat_1uc8c_46{color:var(--text-muted)}._flip_1uc8c_50{transform:scaleY(-1)}._caption_1uc8c_54{font-size:var(--text-xs);color:var(--text-muted)}._tag_11jaq_1{display:inline-flex;gap:var(--space-1-5);align-items:center;height:26px;padding:0 var(--space-2-5);font-family:var(--font-body);font-size:var(--text-xs);font-weight:var(--weight-medium);line-height:1;color:var(--text-secondary);white-space:nowrap;background:var(--surface-default);border:1px solid var(--border-default);border-radius:var(--radius-full)}._remove_11jaq_18{display:inline-flex;align-items:center;justify-content:center;width:14px;height:14px;padding:0;line-height:1;color:inherit;cursor:pointer;background:transparent;border:none;border-radius:var(--radius-full)}._remove_11jaq_18:hover{background:var(--bg-muted)}._alert_1217n_1{display:flex;gap:var(--space-3);padding:var(--space-3) var(--space-4);font-family:var(--font-body);font-size:var(--text-sm);line-height:var(--leading-normal);color:var(--alert-fg);background:var(--alert-bg);border:1px solid;border-color:color-mix(in srgb,var(--alert-border) 40%,transparent);border-radius:var(--radius-sm)}._icon_1217n_16{flex-shrink:0;margin-top:1px;color:var(--alert-border)}._body_1217n_22{flex:1}._title_1217n_26{font-weight:var(--weight-bold)}._titleSpaced_1217n_29{margin-bottom:2px}._dismiss_1217n_33{display:inline-flex;align-items:center;height:20px;padding:2px;color:inherit;cursor:pointer;background:transparent;border:none}._info_1217n_45{--alert-border: var(--feedback-info);--alert-bg: var(--feedback-info-subtle);--alert-fg: var(--tint-info-fg)}._success_1217n_50{--alert-border: var(--feedback-success);--alert-bg: var(--feedback-success-subtle);--alert-fg: var(--tint-success-fg)}._warning_1217n_55{--alert-border: var(--feedback-warning);--alert-bg: var(--feedback-warning-subtle);--alert-fg: var(--tint-warning-fg)}._danger_1217n_60{--alert-border: var(--feedback-danger);--alert-bg: var(--feedback-danger-subtle);--alert-fg: var(--tint-danger-fg)}._progress_tptlj_1{display:flex;flex-direction:column;gap:var(--space-1-5)}._header_tptlj_7{display:flex;justify-content:space-between;font-family:var(--font-body);font-size:var(--text-xs);font-weight:var(--weight-medium);color:var(--text-secondary)}._percent_tptlj_16{font-family:var(--font-mono)}._track_tptlj_20{height:6px;overflow:hidden;background:var(--bg-muted);border-radius:var(--radius-full)}._fill_tptlj_27{height:100%;border-radius:var(--radius-full);transition:width var(--duration-slow) var(--ease-out)}._brand_tptlj_34{background:var(--brand-primary)}._success_tptlj_37{background:var(--feedback-success)}._warning_tptlj_40{background:var(--feedback-warning)}._danger_tptlj_43{background:var(--feedback-danger)}._accent_tptlj_46{background:var(--brand-accent)}._wrap_82rh0_1{position:relative;display:inline-flex}._tip_82rh0_6{position:absolute;z-index:var(--z-tooltip);visibility:hidden;padding:6px 10px;font-family:var(--font-body);font-size:var(--text-xs);font-weight:var(--weight-medium);line-height:1.4;color:var(--text-inverse);white-space:nowrap;pointer-events:none;background:var(--bg-inverse);border-radius:var(--radius-xs);box-shadow:var(--shadow-md);opacity:0;transition:opacity var(--duration-fast) var(--ease-out),visibility var(--duration-fast) var(--ease-out)}._wrap_82rh0_1:hover ._tip_82rh0_6,._wrap_82rh0_1:focus-within ._tip_82rh0_6{visibility:visible;opacity:1}._top_82rh0_34{bottom:calc(100% + 8px);left:50%;transform:translate(-50%)}._bottom_82rh0_39{top:calc(100% + 8px);left:50%;transform:translate(-50%)}._left_82rh0_44{top:50%;right:calc(100% + 8px);transform:translateY(-50%)}._right_82rh0_49{top:50%;left:calc(100% + 8px);transform:translateY(-50%)}._root_1t9ke_1{display:inline-flex;gap:var(--space-2);align-items:center;font-family:var(--font-body);font-size:var(--text-sm);color:var(--text-primary);cursor:pointer;-webkit-user-select:none;user-select:none}._disabled_1t9ke_12{cursor:not-allowed;opacity:.45}._input_1t9ke_18{position:absolute;width:0;height:0;opacity:0}._box_1t9ke_25{display:inline-flex;flex-shrink:0;align-items:center;justify-content:center;width:18px;height:18px;background:var(--surface-default);border:1px solid var(--border-strong);border-radius:var(--radius-xs);transition:background var(--duration-fast) var(--ease-out),border-color var(--duration-fast) var(--ease-out)}._checked_1t9ke_40{background:var(--brand-primary);border-color:var(--brand-primary)}._input_1t9ke_18:focus-visible+._box_1t9ke_25{box-shadow:var(--shadow-focus)}._field_1d54c_1{display:flex;flex-direction:column;gap:var(--space-1-5)}._label_1d54c_7{font-family:var(--font-body);font-size:var(--text-sm);font-weight:var(--weight-semibold);color:var(--text-primary)}._required_1d54c_14{color:var(--feedback-danger)}._error_1d54c_18{font-size:var(--text-xs);color:var(--feedback-danger)}._hint_1d54c_23{font-size:var(--text-xs);color:var(--text-muted)}._input_nhfx3_1{box-sizing:border-box;width:100%;padding:0 var(--space-3);font-family:var(--font-body);color:var(--text-primary);outline:none;background:var(--surface-default);border:1px solid var(--border-default);border-radius:var(--radius-sm);transition:border-color var(--duration-fast) var(--ease-out),box-shadow var(--duration-fast) var(--ease-out)}._input_nhfx3_1::placeholder{color:var(--text-muted)}._input_nhfx3_1:focus{border-color:var(--border-focus);box-shadow:var(--shadow-focus)}._input_nhfx3_1:disabled{cursor:not-allowed;background:var(--bg-muted);opacity:.6}._invalid_nhfx3_31,._invalid_nhfx3_31:focus{border-color:var(--feedback-danger)}._sm_nhfx3_37{height:32px;font-size:var(--text-xs)}._md_nhfx3_41{height:40px;font-size:var(--text-sm)}._lg_nhfx3_45{height:48px;font-size:var(--text-sm)}._wrap_1nxaj_1{position:relative;display:inline-flex;width:100%}._select_1nxaj_7{box-sizing:border-box;width:100%;padding:0 var(--space-8) 0 var(--space-3);font-family:var(--font-body);color:var(--text-primary);-webkit-appearance:none;-moz-appearance:none;appearance:none;cursor:pointer;outline:none;background:var(--surface-default);border:1px solid var(--border-default);border-radius:var(--radius-sm);transition:border-color var(--duration-fast) var(--ease-out),box-shadow var(--duration-fast) var(--ease-out)}._select_1nxaj_7:focus{border-color:var(--border-focus);box-shadow:var(--shadow-focus)}._select_1nxaj_7:disabled{cursor:not-allowed;background:var(--bg-muted);opacity:.6}._invalid_1nxaj_36,._invalid_1nxaj_36:focus{border-color:var(--feedback-danger)}._chevron_1nxaj_41{position:absolute;top:50%;right:10px;color:var(--text-muted);pointer-events:none;transform:translateY(-50%)}._sm_1nxaj_51{height:32px;font-size:var(--text-xs)}._md_1nxaj_55{height:40px;font-size:var(--text-sm)}._lg_1nxaj_59{height:48px;font-size:var(--text-sm)}._root_ctdye_1{display:inline-flex;gap:var(--space-2);align-items:center;font-family:var(--font-body);font-size:var(--text-sm);color:var(--text-primary);cursor:pointer;-webkit-user-select:none;user-select:none}._disabled_ctdye_12{cursor:not-allowed;opacity:.45}._input_ctdye_17{position:absolute;width:0;height:0;opacity:0}._track_ctdye_24{position:relative;flex-shrink:0;width:36px;height:20px;background:var(--adl-neutral-300);border-radius:var(--radius-full);transition:background var(--duration-base) var(--ease-out)}._on_ctdye_34{background:var(--brand-primary)}._knob_ctdye_38{position:absolute;top:2px;left:2px;width:16px;height:16px;background:var(--adl-neutral-0);border-radius:var(--radius-full);box-shadow:var(--shadow-sm);transition:left var(--duration-base) var(--ease-out)}._on_ctdye_34 ._knob_ctdye_38{left:18px}._input_ctdye_17:focus-visible+._track_ctdye_24{box-shadow:var(--shadow-focus)}._list_1e7it_1{display:flex;gap:var(--space-1-5);align-items:center;padding:0;margin:0;font-family:var(--font-body);font-size:var(--text-sm);list-style:none}._item_1e7it_12{display:flex;gap:var(--space-1-5);align-items:center}._current_1e7it_18{font-weight:var(--weight-semibold);color:var(--text-primary)}._link_1e7it_23{color:var(--text-muted);text-decoration:none}._link_1e7it_23:hover{color:var(--text-secondary);text-decoration:underline;text-underline-offset:3px}._sep_1e7it_34{color:var(--adl-neutral-400)}._tablist_1khzs_1{display:flex;gap:var(--space-1);border-bottom:1px solid var(--border-subtle)}._tab_1khzs_1{display:inline-flex;gap:var(--space-1-5);align-items:center;margin-bottom:-1px;font-family:var(--font-body);font-weight:var(--weight-semibold);color:var(--text-muted);cursor:pointer;background:transparent;border:none;border-bottom:2px solid transparent;transition:color var(--duration-fast) var(--ease-out),border-color var(--duration-fast) var(--ease-out)}._tab_1khzs_1:hover:not(._active_1khzs_24){color:var(--text-secondary)}._active_1khzs_24{color:var(--text-primary);border-bottom-color:var(--brand-primary)}._sm_1khzs_34{padding:var(--space-2) var(--space-2-5);font-size:var(--text-xs)}._md_1khzs_38{padding:var(--space-2-5) 14px;font-size:var(--text-sm)}._count_1khzs_44{padding:2px 6px;font-size:11px;line-height:1;color:var(--text-muted);background:var(--bg-muted);border-radius:var(--radius-full)}._countActive_1khzs_53{color:var(--tint-brand-fg);background:var(--brand-primary-subtle)}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * @enact/design-system — public API.
3
+ *
4
+ * This barrel is the ONLY supported entry point. Import components and their
5
+ * prop types from here; never reach into component internals. Design tokens are
6
+ * shipped separately as `@enact/design-system/tokens.css`.
7
+ */
8
+ export { Avatar, type AvatarProps } from "./components/core/Avatar";
9
+ export { Badge, type BadgeProps } from "./components/core/Badge";
10
+ export { Button, type ButtonProps } from "./components/core/Button";
11
+ export { Card, type CardProps } from "./components/core/Card";
12
+ export { IconButton, type IconButtonProps } from "./components/core/IconButton";
13
+ export { Stat, type StatProps } from "./components/core/Stat";
14
+ export { Tag, type TagProps } from "./components/core/Tag";
15
+ export { Alert, type AlertProps, type AlertTone, } from "./components/feedback/Alert";
16
+ export { Progress, type ProgressProps, type ProgressTone, } from "./components/feedback/Progress";
17
+ export { Tooltip, type TooltipProps } from "./components/feedback/Tooltip";
18
+ export { Checkbox, type CheckboxProps } from "./components/forms/Checkbox";
19
+ export { Field, type FieldProps } from "./components/forms/Field";
20
+ export { Input, type InputProps } from "./components/forms/Input";
21
+ export { Select, type SelectProps } from "./components/forms/Select";
22
+ export { Switch, type SwitchProps } from "./components/forms/Switch";
23
+ export { Breadcrumb, type BreadcrumbItem, type BreadcrumbProps, } from "./components/navigation/Breadcrumb";
24
+ export { type TabItem, Tabs, type TabsProps, } from "./components/navigation/Tabs";