ralfy-ui 1.0.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 ADDED
@@ -0,0 +1,95 @@
1
+ # Ralfy-UI
2
+
3
+ A design system extracted from a production React application, built to demonstrate how token-driven component architecture reduces engineering time and eliminates design-to-code drift.
4
+
5
+ > **Live Storybook:** [Browse Components on Chromatic](https://69983a8349303a08fb1562fd-xrtnonxtkh.chromatic.com/)
6
+
7
+ ## Why This Exists
8
+
9
+ This design system was extracted from [Ralfy](https://github.com/pavlelucic), a LinkedIn feed management tool built as a solo developer using Claude Code. The extraction process demonstrates a code-first philosophy: tokens and components are the source of truth, Figma mirrors them.
10
+
11
+ **The business case:** When UI patterns live only in Figma or only in a developer's head, every new screen requires re-interpretation. This system eliminates that overhead — a new engineer can build a compliant screen by importing components and reading CLAUDE.md, without studying a 50-page style guide.
12
+
13
+ ## Token Architecture
14
+
15
+ ```
16
+ Tier 1: Primitive → blue-600, gray-100, red-500
17
+ (raw values, used for Figma import)
18
+
19
+ Tier 2: Semantic → primary, muted, destructive
20
+ (role-based, used in all components)
21
+ ```
22
+
23
+ - **Format:** OKLch (perceptually uniform, CSS Color Level 4, Tailwind v4 native)
24
+ - **Modes:** Light + Dark (CSS custom properties swap under `.dark` class)
25
+ - **Mapping:** `@theme inline` block bridges CSS variables → Tailwind utility classes
26
+
27
+ See: [Token Architecture Deep Dive](docs/token-architecture.md)
28
+
29
+ ## Components
30
+
31
+ | Component | Type | Key Features |
32
+ |-----------|------|-------------|
33
+ | **Button** | Presentational | 4 variants, 3 sizes, loading state, `asChild` polymorphism |
34
+ | **Input** | Controlled | Label, helper text, error state, icon, `aria-describedby` |
35
+ | **Card** | Compound | Card + Header + Title + Description + Content + Footer |
36
+ | **Badge** | Presentational | 5 semantic variants (success, warning, error, info, neutral) |
37
+ | **Avatar** | Presentational | Image/initials/fallback, 3 sizes, online/offline status |
38
+ | **Toggle** | Controlled | Radix Switch, keyboard accessible, label association |
39
+
40
+ All components use `React.forwardRef`, accept `className` for customization, and use only design tokens — zero hardcoded values.
41
+
42
+ ## Quick Start
43
+
44
+ ```bash
45
+ git clone https://github.com/pavlelucic/ralfy-ui.git
46
+ cd ralfy-ui
47
+ pnpm install
48
+ pnpm storybook # Open Storybook on port 6006
49
+ pnpm dev # Vite dev server on port 5173
50
+ pnpm test:run # Run all tests
51
+ pnpm typecheck # TypeScript check
52
+ ```
53
+
54
+ ## AI-Ready
55
+
56
+ This design system includes a `CLAUDE.md` file — a machine-readable specification that enables AI tools (like Claude Code) to generate compliant UI code automatically.
57
+
58
+ **What this means in practice:** When an AI reads CLAUDE.md before generating code, it uses the correct tokens, imports, and component APIs without manual review. This eliminates a category of "fix the AI output" work.
59
+
60
+ See: [AI Workflow Documentation](docs/ai-workflow.md)
61
+
62
+ ## Design Decisions
63
+
64
+ | Decision | Rationale |
65
+ |----------|-----------|
66
+ | **OKLch over hex/HSL** | Perceptually uniform steps, better dark mode, Tailwind v4 native |
67
+ | **Radix UI primitives** | Battle-tested accessibility (keyboard, ARIA, focus management) without custom implementation |
68
+ | **Storybook over Styleguidist** | Richer addon ecosystem (a11y, visual regression via Chromatic), better docs generation |
69
+ | **cva + cn pattern** | Type-safe variants with className composition — the emerging standard for Tailwind components |
70
+ | **2-tier tokens (not 3)** | Component-level tokens add indirection without value at this scale |
71
+ | **Compound Card pattern** | Flexible composition over rigid prop drilling — aligns with Kit's component needs |
72
+
73
+ ## Tech Stack
74
+
75
+ | Technology | Version | Purpose |
76
+ |-----------|---------|---------|
77
+ | React | 19 | UI framework |
78
+ | TypeScript | 5.9 | Type safety |
79
+ | Vite | 7 | Build tool |
80
+ | Tailwind CSS | 4 | Utility-first styling |
81
+ | Radix UI | Latest | Accessible primitives |
82
+ | Storybook | 10 | Component documentation |
83
+ | Vitest | 4 | Testing |
84
+ | Testing Library | Latest | Component testing |
85
+ | cva | 0.7 | Variant management |
86
+
87
+ ## Documentation
88
+
89
+ - [Case Study](docs/case-study.md) — Full portfolio case study
90
+ - [Token Architecture](docs/token-architecture.md) — Deep dive on token decisions
91
+ - [AI Workflow](docs/ai-workflow.md) — AI-assisted design-to-code documentation
92
+
93
+ ## License
94
+
95
+ MIT
@@ -0,0 +1,24 @@
1
+ import { VariantProps } from 'class-variance-authority';
2
+ import * as React from 'react';
3
+ declare const avatarVariants: (props?: ({
4
+ size?: "sm" | "md" | "lg" | null | undefined;
5
+ } & import('class-variance-authority/types').ClassProp) | undefined) => string;
6
+ export type AvatarProps = {
7
+ src?: string;
8
+ alt?: string;
9
+ fallback: string;
10
+ size?: 'sm' | 'md' | 'lg';
11
+ status?: 'online' | 'offline';
12
+ className?: string;
13
+ } & VariantProps<typeof avatarVariants>;
14
+ declare const Avatar: React.ForwardRefExoticComponent<{
15
+ src?: string;
16
+ alt?: string;
17
+ fallback: string;
18
+ size?: "sm" | "md" | "lg";
19
+ status?: "online" | "offline";
20
+ className?: string;
21
+ } & VariantProps<(props?: ({
22
+ size?: "sm" | "md" | "lg" | null | undefined;
23
+ } & import('class-variance-authority/types').ClassProp) | undefined) => string> & React.RefAttributes<HTMLDivElement>>;
24
+ export { Avatar };
@@ -0,0 +1,71 @@
1
+ import { jsxs as n, jsx as e } from "react/jsx-runtime";
2
+ import * as f from "react";
3
+ import * as a from "@radix-ui/react-avatar";
4
+ import { cva as u } from "class-variance-authority";
5
+ import { cn as o } from "../../lib/cn.js";
6
+ const h = u("relative flex shrink-0 items-center justify-center", {
7
+ variants: {
8
+ size: {
9
+ sm: "h-8 w-8 text-xs",
10
+ md: "h-10 w-10 text-sm",
11
+ lg: "h-14 w-14 text-lg"
12
+ }
13
+ },
14
+ defaultVariants: {
15
+ size: "md"
16
+ }
17
+ }), g = {
18
+ sm: "h-2 w-2",
19
+ md: "h-2.5 w-2.5",
20
+ lg: "h-3 w-3"
21
+ };
22
+ function v({
23
+ status: t,
24
+ size: r = "md"
25
+ }) {
26
+ return /* @__PURE__ */ e(
27
+ "span",
28
+ {
29
+ "data-testid": "status-indicator",
30
+ "data-status": t,
31
+ className: o(
32
+ "absolute bottom-0 right-0 rounded-full ring-2 ring-background",
33
+ g[r],
34
+ t === "offline" && "bg-muted-foreground"
35
+ ),
36
+ style: t === "online" ? { backgroundColor: "oklch(0.64 0.17 155)" } : void 0
37
+ }
38
+ );
39
+ }
40
+ const x = f.forwardRef(
41
+ ({ src: t, alt: r, fallback: s, size: i = "md", status: l, className: m, ...d }, c) => /* @__PURE__ */ n("div", { ref: c, className: o("relative inline-flex", m), ...d, children: [
42
+ /* @__PURE__ */ n(
43
+ a.Root,
44
+ {
45
+ className: o(h({ size: i }), "overflow-hidden rounded-full"),
46
+ children: [
47
+ /* @__PURE__ */ e(
48
+ a.Image,
49
+ {
50
+ className: "h-full w-full object-cover",
51
+ src: t,
52
+ alt: r
53
+ }
54
+ ),
55
+ /* @__PURE__ */ e(
56
+ a.Fallback,
57
+ {
58
+ className: "flex h-full w-full items-center justify-center bg-muted text-muted-foreground font-medium",
59
+ children: s
60
+ }
61
+ )
62
+ ]
63
+ }
64
+ ),
65
+ l && /* @__PURE__ */ e(v, { status: l, size: i })
66
+ ] })
67
+ );
68
+ x.displayName = "Avatar";
69
+ export {
70
+ x as Avatar
71
+ };
@@ -0,0 +1,10 @@
1
+ import { VariantProps } from 'class-variance-authority';
2
+ import * as React from 'react';
3
+ declare const badgeVariants: (props?: ({
4
+ variant?: "success" | "warning" | "error" | "info" | "neutral" | null | undefined;
5
+ size?: "sm" | "md" | null | undefined;
6
+ } & import('class-variance-authority/types').ClassProp) | undefined) => string;
7
+ export interface BadgeProps extends React.HTMLAttributes<HTMLSpanElement>, VariantProps<typeof badgeVariants> {
8
+ }
9
+ declare const Badge: React.ForwardRefExoticComponent<BadgeProps & React.RefAttributes<HTMLSpanElement>>;
10
+ export { Badge, badgeVariants };
@@ -0,0 +1,40 @@
1
+ import { jsx as s } from "react/jsx-runtime";
2
+ import * as o from "react";
3
+ import { cva as i } from "class-variance-authority";
4
+ import { cn as d } from "../../lib/cn.js";
5
+ const c = i(
6
+ "inline-flex items-center rounded-full font-medium",
7
+ {
8
+ variants: {
9
+ variant: {
10
+ success: "bg-success text-success-foreground",
11
+ warning: "bg-warning text-warning-foreground",
12
+ error: "bg-destructive/10 text-destructive",
13
+ info: "bg-info text-info-foreground",
14
+ neutral: "bg-secondary text-secondary-foreground"
15
+ },
16
+ size: {
17
+ sm: "text-xs px-2 py-0.5",
18
+ md: "text-xs px-2.5 py-1"
19
+ }
20
+ },
21
+ defaultVariants: {
22
+ variant: "neutral",
23
+ size: "md"
24
+ }
25
+ }
26
+ ), f = o.forwardRef(
27
+ ({ className: e, variant: r, size: t, ...n }, a) => /* @__PURE__ */ s(
28
+ "span",
29
+ {
30
+ ref: a,
31
+ className: d(c({ variant: r, size: t }), e),
32
+ ...n
33
+ }
34
+ )
35
+ );
36
+ f.displayName = "Badge";
37
+ export {
38
+ f as Badge,
39
+ c as badgeVariants
40
+ };
@@ -0,0 +1,14 @@
1
+ import { VariantProps } from 'class-variance-authority';
2
+ import * as React from 'react';
3
+ declare const buttonVariants: (props?: ({
4
+ variant?: "primary" | "secondary" | "ghost" | "destructive" | null | undefined;
5
+ size?: "sm" | "md" | "lg" | null | undefined;
6
+ } & import('class-variance-authority/types').ClassProp) | undefined) => string;
7
+ export interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement>, VariantProps<typeof buttonVariants> {
8
+ /** When true, the button renders as its child element (e.g. an anchor tag). */
9
+ asChild?: boolean;
10
+ /** Shows a loading spinner and disables the button. */
11
+ loading?: boolean;
12
+ }
13
+ declare const Button: React.ForwardRefExoticComponent<ButtonProps & React.RefAttributes<HTMLButtonElement>>;
14
+ export { Button, buttonVariants };
@@ -0,0 +1,90 @@
1
+ import { jsx as e, jsxs as i, Fragment as u } from "react/jsx-runtime";
2
+ import * as l from "react";
3
+ import { cva as p } from "class-variance-authority";
4
+ import { Slot as f } from "@radix-ui/react-slot";
5
+ import { cn as v } from "../../lib/cn.js";
6
+ const g = p(
7
+ "inline-flex items-center justify-center gap-2 font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",
8
+ {
9
+ variants: {
10
+ variant: {
11
+ primary: "bg-primary text-primary-foreground hover:bg-primary/90",
12
+ secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
13
+ ghost: "hover:bg-accent hover:text-accent-foreground",
14
+ destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90"
15
+ },
16
+ size: {
17
+ sm: "h-8 px-3 text-xs rounded-md",
18
+ md: "h-10 px-4 text-sm rounded-md",
19
+ lg: "h-12 px-6 text-base rounded-lg"
20
+ }
21
+ },
22
+ defaultVariants: {
23
+ variant: "primary",
24
+ size: "md"
25
+ }
26
+ }
27
+ );
28
+ function b() {
29
+ return /* @__PURE__ */ i(
30
+ "svg",
31
+ {
32
+ className: "h-4 w-4 animate-spin",
33
+ xmlns: "http://www.w3.org/2000/svg",
34
+ fill: "none",
35
+ viewBox: "0 0 24 24",
36
+ "data-testid": "button-spinner",
37
+ children: [
38
+ /* @__PURE__ */ e(
39
+ "circle",
40
+ {
41
+ className: "opacity-25",
42
+ cx: "12",
43
+ cy: "12",
44
+ r: "10",
45
+ stroke: "currentColor",
46
+ strokeWidth: "4"
47
+ }
48
+ ),
49
+ /* @__PURE__ */ e(
50
+ "path",
51
+ {
52
+ className: "opacity-75",
53
+ fill: "currentColor",
54
+ d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
55
+ }
56
+ )
57
+ ]
58
+ }
59
+ );
60
+ }
61
+ const x = l.forwardRef(
62
+ ({
63
+ className: n,
64
+ variant: s,
65
+ size: a,
66
+ asChild: t = !1,
67
+ loading: r = !1,
68
+ disabled: c,
69
+ children: o,
70
+ ...d
71
+ }, m) => /* @__PURE__ */ e(
72
+ t ? f : "button",
73
+ {
74
+ className: v(g({ variant: s, size: a, className: n })),
75
+ ref: m,
76
+ disabled: c || r,
77
+ "aria-busy": r ? "true" : void 0,
78
+ ...d,
79
+ children: t ? o : /* @__PURE__ */ i(u, { children: [
80
+ r && /* @__PURE__ */ e(b, {}),
81
+ o
82
+ ] })
83
+ }
84
+ )
85
+ );
86
+ x.displayName = "Button";
87
+ export {
88
+ x as Button,
89
+ g as buttonVariants
90
+ };
@@ -0,0 +1,11 @@
1
+ import { VariantProps } from 'class-variance-authority';
2
+ import * as React from 'react';
3
+ declare const Card: React.ForwardRefExoticComponent<Omit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & VariantProps<(props?: ({
4
+ variant?: "default" | "outlined" | "elevated" | null | undefined;
5
+ } & import('class-variance-authority/types').ClassProp) | undefined) => string> & React.RefAttributes<HTMLDivElement>>;
6
+ declare const CardHeader: React.ForwardRefExoticComponent<Omit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
7
+ declare const CardTitle: React.ForwardRefExoticComponent<Omit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLHeadingElement>, HTMLHeadingElement>, "ref"> & React.RefAttributes<HTMLHeadingElement>>;
8
+ declare const CardDescription: React.ForwardRefExoticComponent<Omit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLParagraphElement>, HTMLParagraphElement>, "ref"> & React.RefAttributes<HTMLParagraphElement>>;
9
+ declare const CardContent: React.ForwardRefExoticComponent<Omit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
10
+ declare const CardFooter: React.ForwardRefExoticComponent<Omit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
11
+ export { Card, CardHeader, CardTitle, CardDescription, CardContent, CardFooter };
@@ -0,0 +1,79 @@
1
+ import { jsx as d } from "react/jsx-runtime";
2
+ import * as t from "react";
3
+ import { cva as n } from "class-variance-authority";
4
+ import { cn as o } from "../../lib/cn.js";
5
+ const i = n("", {
6
+ variants: {
7
+ variant: {
8
+ default: "bg-card text-card-foreground rounded-lg border border-border",
9
+ outlined: "bg-transparent text-card-foreground rounded-lg border-2 border-border",
10
+ elevated: "bg-card text-card-foreground rounded-lg border border-border shadow-lg"
11
+ }
12
+ },
13
+ defaultVariants: {
14
+ variant: "default"
15
+ }
16
+ }), l = t.forwardRef(
17
+ ({ className: r, variant: a, ...e }, s) => /* @__PURE__ */ d(
18
+ "div",
19
+ {
20
+ ref: s,
21
+ className: o(i({ variant: a }), r),
22
+ ...e
23
+ }
24
+ )
25
+ );
26
+ l.displayName = "Card";
27
+ const c = t.forwardRef(({ className: r, ...a }, e) => /* @__PURE__ */ d(
28
+ "div",
29
+ {
30
+ ref: e,
31
+ className: o("flex flex-col gap-1.5 p-6", r),
32
+ ...a
33
+ }
34
+ ));
35
+ c.displayName = "CardHeader";
36
+ const f = t.forwardRef(({ className: r, ...a }, e) => /* @__PURE__ */ d(
37
+ "h3",
38
+ {
39
+ ref: e,
40
+ className: o("text-lg font-semibold leading-tight tracking-tight", r),
41
+ ...a
42
+ }
43
+ ));
44
+ f.displayName = "CardTitle";
45
+ const m = t.forwardRef(({ className: r, ...a }, e) => /* @__PURE__ */ d(
46
+ "p",
47
+ {
48
+ ref: e,
49
+ className: o("text-sm text-muted-foreground", r),
50
+ ...a
51
+ }
52
+ ));
53
+ m.displayName = "CardDescription";
54
+ const p = t.forwardRef(({ className: r, ...a }, e) => /* @__PURE__ */ d(
55
+ "div",
56
+ {
57
+ ref: e,
58
+ className: o("p-6 pt-0", r),
59
+ ...a
60
+ }
61
+ ));
62
+ p.displayName = "CardContent";
63
+ const g = t.forwardRef(({ className: r, ...a }, e) => /* @__PURE__ */ d(
64
+ "div",
65
+ {
66
+ ref: e,
67
+ className: o("flex items-center p-6 pt-0", r),
68
+ ...a
69
+ }
70
+ ));
71
+ g.displayName = "CardFooter";
72
+ export {
73
+ l as Card,
74
+ p as CardContent,
75
+ m as CardDescription,
76
+ g as CardFooter,
77
+ c as CardHeader,
78
+ f as CardTitle
79
+ };
@@ -0,0 +1,17 @@
1
+ import * as React from 'react';
2
+ import * as DialogPrimitive from '@radix-ui/react-dialog';
3
+ declare const Dialog: React.FC<DialogPrimitive.DialogProps>;
4
+ declare const DialogTrigger: React.ForwardRefExoticComponent<DialogPrimitive.DialogTriggerProps & React.RefAttributes<HTMLButtonElement>>;
5
+ declare const DialogClose: React.ForwardRefExoticComponent<DialogPrimitive.DialogCloseProps & React.RefAttributes<HTMLButtonElement>>;
6
+ declare const DialogContent: React.ForwardRefExoticComponent<Omit<DialogPrimitive.DialogContentProps & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
7
+ declare const DialogHeader: {
8
+ ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>): import("react/jsx-runtime").JSX.Element;
9
+ displayName: string;
10
+ };
11
+ declare const DialogFooter: {
12
+ ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>): import("react/jsx-runtime").JSX.Element;
13
+ displayName: string;
14
+ };
15
+ declare const DialogTitle: React.ForwardRefExoticComponent<Omit<DialogPrimitive.DialogTitleProps & React.RefAttributes<HTMLHeadingElement>, "ref"> & React.RefAttributes<HTMLHeadingElement>>;
16
+ declare const DialogDescription: React.ForwardRefExoticComponent<Omit<DialogPrimitive.DialogDescriptionProps & React.RefAttributes<HTMLParagraphElement>, "ref"> & React.RefAttributes<HTMLParagraphElement>>;
17
+ export { Dialog, DialogTrigger, DialogContent, DialogHeader, DialogFooter, DialogTitle, DialogDescription, DialogClose, };
@@ -0,0 +1,108 @@
1
+ import { jsxs as l, jsx as t } from "react/jsx-runtime";
2
+ import * as r from "react";
3
+ import * as e from "@radix-ui/react-dialog";
4
+ import { cn as i } from "../../lib/cn.js";
5
+ const y = e.Root, N = e.Trigger, h = e.Close, n = r.forwardRef(({ className: o, ...a }, s) => /* @__PURE__ */ t(
6
+ e.Overlay,
7
+ {
8
+ ref: s,
9
+ className: i(
10
+ "fixed inset-0 z-50 bg-black/50 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
11
+ o
12
+ ),
13
+ ...a
14
+ }
15
+ ));
16
+ n.displayName = e.Overlay.displayName;
17
+ const c = r.forwardRef(({ className: o, children: a, ...s }, d) => /* @__PURE__ */ l(e.Portal, { children: [
18
+ /* @__PURE__ */ t(n, {}),
19
+ /* @__PURE__ */ l(
20
+ e.Content,
21
+ {
22
+ ref: d,
23
+ className: i(
24
+ "fixed left-1/2 top-1/2 z-50 w-full max-w-lg -translate-x-1/2 -translate-y-1/2 border border-border bg-background p-6 shadow-lg rounded-lg",
25
+ o
26
+ ),
27
+ ...s,
28
+ children: [
29
+ a,
30
+ /* @__PURE__ */ l(e.Close, { className: "absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2", children: [
31
+ /* @__PURE__ */ l(
32
+ "svg",
33
+ {
34
+ xmlns: "http://www.w3.org/2000/svg",
35
+ width: "16",
36
+ height: "16",
37
+ viewBox: "0 0 24 24",
38
+ fill: "none",
39
+ stroke: "currentColor",
40
+ strokeWidth: "2",
41
+ strokeLinecap: "round",
42
+ strokeLinejoin: "round",
43
+ children: [
44
+ /* @__PURE__ */ t("path", { d: "M18 6 6 18" }),
45
+ /* @__PURE__ */ t("path", { d: "m6 6 12 12" })
46
+ ]
47
+ }
48
+ ),
49
+ /* @__PURE__ */ t("span", { className: "sr-only", children: "Close" })
50
+ ] })
51
+ ]
52
+ }
53
+ )
54
+ ] }));
55
+ c.displayName = e.Content.displayName;
56
+ const m = ({
57
+ className: o,
58
+ ...a
59
+ }) => /* @__PURE__ */ t(
60
+ "div",
61
+ {
62
+ className: i("flex flex-col gap-1.5 text-center sm:text-left", o),
63
+ ...a
64
+ }
65
+ );
66
+ m.displayName = "DialogHeader";
67
+ const g = ({
68
+ className: o,
69
+ ...a
70
+ }) => /* @__PURE__ */ t(
71
+ "div",
72
+ {
73
+ className: i(
74
+ "flex flex-col-reverse sm:flex-row sm:justify-end sm:gap-2",
75
+ o
76
+ ),
77
+ ...a
78
+ }
79
+ );
80
+ g.displayName = "DialogFooter";
81
+ const f = r.forwardRef(({ className: o, ...a }, s) => /* @__PURE__ */ t(
82
+ e.Title,
83
+ {
84
+ ref: s,
85
+ className: i("text-lg font-semibold leading-tight", o),
86
+ ...a
87
+ }
88
+ ));
89
+ f.displayName = e.Title.displayName;
90
+ const p = r.forwardRef(({ className: o, ...a }, s) => /* @__PURE__ */ t(
91
+ e.Description,
92
+ {
93
+ ref: s,
94
+ className: i("text-sm text-muted-foreground", o),
95
+ ...a
96
+ }
97
+ ));
98
+ p.displayName = e.Description.displayName;
99
+ export {
100
+ y as Dialog,
101
+ h as DialogClose,
102
+ c as DialogContent,
103
+ p as DialogDescription,
104
+ g as DialogFooter,
105
+ m as DialogHeader,
106
+ f as DialogTitle,
107
+ N as DialogTrigger
108
+ };
@@ -0,0 +1,10 @@
1
+ import * as React from 'react';
2
+ export interface InputProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'className'> {
3
+ label?: string;
4
+ helperText?: string;
5
+ errorMessage?: string;
6
+ icon?: React.ReactNode;
7
+ className?: string;
8
+ }
9
+ declare const Input: React.ForwardRefExoticComponent<InputProps & React.RefAttributes<HTMLInputElement>>;
10
+ export { Input };
@@ -0,0 +1,61 @@
1
+ import { jsxs as a, jsx as e } from "react/jsx-runtime";
2
+ import * as s from "react";
3
+ import { cn as b } from "../../lib/cn.js";
4
+ const g = s.forwardRef(
5
+ ({
6
+ label: r,
7
+ helperText: i,
8
+ errorMessage: t,
9
+ icon: n,
10
+ disabled: o,
11
+ type: l,
12
+ className: u,
13
+ id: m,
14
+ ...f
15
+ }, p) => {
16
+ const x = s.useId(), d = m ?? x, c = `${d}-error`;
17
+ return /* @__PURE__ */ a("div", { className: "flex flex-col gap-1.5", children: [
18
+ r && /* @__PURE__ */ e(
19
+ "label",
20
+ {
21
+ htmlFor: d,
22
+ className: "text-sm font-medium text-foreground",
23
+ children: r
24
+ }
25
+ ),
26
+ /* @__PURE__ */ a(
27
+ "div",
28
+ {
29
+ className: b(
30
+ "flex items-center rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background focus-within:ring-2 focus-within:ring-ring focus-within:ring-offset-2",
31
+ t && "border-destructive",
32
+ o && "cursor-not-allowed opacity-50",
33
+ u
34
+ ),
35
+ children: [
36
+ n && /* @__PURE__ */ e("span", { className: "mr-2 text-muted-foreground", children: n }),
37
+ /* @__PURE__ */ e(
38
+ "input",
39
+ {
40
+ ref: p,
41
+ id: d,
42
+ type: l,
43
+ disabled: o,
44
+ "aria-describedby": t ? c : void 0,
45
+ "aria-invalid": t ? !0 : void 0,
46
+ className: "flex-1 bg-transparent outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50",
47
+ ...f
48
+ }
49
+ )
50
+ ]
51
+ }
52
+ ),
53
+ t && /* @__PURE__ */ e("p", { id: c, className: "text-xs text-destructive", children: t }),
54
+ i && !t && /* @__PURE__ */ e("p", { className: "text-xs text-muted-foreground", children: i })
55
+ ] });
56
+ }
57
+ );
58
+ g.displayName = "Input";
59
+ export {
60
+ g as Input
61
+ };
@@ -0,0 +1,13 @@
1
+ import * as React from 'react';
2
+ import * as SwitchPrimitive from '@radix-ui/react-switch';
3
+ export interface ToggleProps extends React.ComponentPropsWithoutRef<typeof SwitchPrimitive.Root> {
4
+ checked?: boolean;
5
+ defaultChecked?: boolean;
6
+ onCheckedChange?: (checked: boolean) => void;
7
+ disabled?: boolean;
8
+ label?: string;
9
+ id?: string;
10
+ className?: string;
11
+ }
12
+ declare const Toggle: React.ForwardRefExoticComponent<ToggleProps & React.RefAttributes<HTMLButtonElement>>;
13
+ export { Toggle };