@usevyre/react 1.3.0 → 1.4.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.
@@ -0,0 +1,52 @@
1
+ /**
2
+ * @usevyre/react — Carousel + CarouselSlide
3
+ *
4
+ * AI CONTEXT:
5
+ * ┌──────────────────────────────────────────────────────────────────┐
6
+ * │ Component: Carousel (+ CarouselSlide) │
7
+ * │ Import: import { Carousel, CarouselSlide } from "@usevyre/react" │
8
+ * │ │
9
+ * │ Accessible content slider (galleries / onboarding / testimonials).│
10
+ * │ CONTROLLED by a 0-based slide index. Slide order = index. │
11
+ * │ │
12
+ * │ <Carousel> │
13
+ * │ value? = number (controlled active slide) │
14
+ * │ defaultValue = number (uncontrolled, default 0) │
15
+ * │ onChange? = (index: number) => void │
16
+ * │ loop? = boolean (wrap past the ends) │
17
+ * │ autoPlay? = boolean interval = ms (default 5000) │
18
+ * │ showArrows? = boolean (default true) │
19
+ * │ showIndicators= boolean (default true) │
20
+ * │ <CarouselSlide> any content </CarouselSlide> │
21
+ * │ │
22
+ * │ Snap scrolling, clickable dot indicators, ←/→ keyboard, │
23
+ * │ autoplay pauses on hover/focus. │
24
+ * └──────────────────────────────────────────────────────────────────┘
25
+ *
26
+ * @example
27
+ * const [i, setI] = useState(0);
28
+ * <Carousel value={i} onChange={setI} loop>
29
+ * <CarouselSlide><img src="/a.jpg" alt="A" /></CarouselSlide>
30
+ * <CarouselSlide><img src="/b.jpg" alt="B" /></CarouselSlide>
31
+ * </Carousel>
32
+ */
33
+ import React from "react";
34
+ import type { BaseProps } from "../../types";
35
+ export interface CarouselSlideProps extends BaseProps {
36
+ children?: React.ReactNode;
37
+ }
38
+ export declare const CarouselSlide: React.ForwardRefExoticComponent<CarouselSlideProps & React.RefAttributes<HTMLDivElement>>;
39
+ export interface CarouselProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "onChange">, BaseProps {
40
+ value?: number;
41
+ defaultValue?: number;
42
+ onChange?: (index: number) => void;
43
+ loop?: boolean;
44
+ autoPlay?: boolean;
45
+ /** Autoplay interval in ms */
46
+ interval?: number;
47
+ showArrows?: boolean;
48
+ showIndicators?: boolean;
49
+ children?: React.ReactNode;
50
+ "aria-label"?: string;
51
+ }
52
+ export declare const Carousel: React.ForwardRefExoticComponent<CarouselProps & React.RefAttributes<HTMLDivElement>>;
@@ -0,0 +1,50 @@
1
+ /**
2
+ * @usevyre/react — EmptyState
3
+ *
4
+ * AI CONTEXT:
5
+ * ┌──────────────────────────────────────────────────────────────────┐
6
+ * │ Component: EmptyState │
7
+ * │ Import: import { EmptyState } from "@usevyre/react" │
8
+ * │ │
9
+ * │ Presentational placeholder for empty lists, tables, and search │
10
+ * │ results. No state. The optional call-to-action goes in children. │
11
+ * │ │
12
+ * │ title = string (required) │
13
+ * │ description? = string │
14
+ * │ variant = "default"(box) | "search"(magnifier) │
15
+ * │ | "error"(warning) — picks a preset icon │
16
+ * │ icon? = ReactNode (overrides the preset) │
17
+ * │ size = "sm" | "md"(default) | "lg" │
18
+ * │ children? = the CTA (Button, or two buttons in a Stack) │
19
+ * └──────────────────────────────────────────────────────────────────┘
20
+ *
21
+ * @example
22
+ * <EmptyState
23
+ * variant="search"
24
+ * title="No results"
25
+ * description="Try a different search term."
26
+ * >
27
+ * <Button variant="secondary" onClick={reset}>Clear filters</Button>
28
+ * </EmptyState>
29
+ */
30
+ import React from "react";
31
+ import type { BaseProps } from "../../types";
32
+ declare const PRESET_ICONS: {
33
+ readonly default: () => import("react/jsx-runtime").JSX.Element;
34
+ readonly search: () => import("react/jsx-runtime").JSX.Element;
35
+ readonly error: () => import("react/jsx-runtime").JSX.Element;
36
+ };
37
+ export type EmptyStateVariant = keyof typeof PRESET_ICONS;
38
+ export interface EmptyStateProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "title">, BaseProps {
39
+ /** Headline (required) */
40
+ title: string;
41
+ /** Supporting text under the title */
42
+ description?: string;
43
+ /** Picks a preset icon */
44
+ variant?: EmptyStateVariant;
45
+ /** Custom icon, overrides the variant preset */
46
+ icon?: React.ReactNode;
47
+ size?: "sm" | "md" | "lg";
48
+ }
49
+ export declare const EmptyState: React.ForwardRefExoticComponent<EmptyStateProps & React.RefAttributes<HTMLDivElement>>;
50
+ export {};
@@ -0,0 +1,96 @@
1
+ /**
2
+ * @usevyre/react — Form + FormField
3
+ *
4
+ * AI CONTEXT:
5
+ * ┌──────────────────────────────────────────────────────────────────┐
6
+ * │ Components: Form, FormField │
7
+ * │ Import: import { Form, FormField } from "@usevyre/react" │
8
+ * │ │
9
+ * │ Controlled, data-driven form. Zero dependencies. Validation runs │
10
+ * │ on submit and (after the first submit) on blur. Errors map into │
11
+ * │ the wrapped Field automatically (state="error" + hint=message). │
12
+ * │ │
13
+ * │ <Form> │
14
+ * │ values? = Record<string, any> (controlled) │
15
+ * │ defaultValues?= Record<string, any> (uncontrolled) │
16
+ * │ onChange? = (values) => void │
17
+ * │ onSubmit = (values) => void | Promise<void> (valid only) │
18
+ * │ onInvalid? = (errors: Record<string,string>) => void │
19
+ * │ │
20
+ * │ <FormField name="email" label="Email" rules={{ ... }}> │
21
+ * │ <Input type="email" /> ← single control child │
22
+ * │ </FormField> │
23
+ * │ rules = { required?: boolean | string, │
24
+ * │ minLength?, maxLength?, min?, max?: number, │
25
+ * │ pattern?: RegExp, email?: boolean, │
26
+ * │ validate?: (value, allValues) => string | null } │
27
+ * │ │
28
+ * │ FormField injects name / value / onChange / onBlur into its │
29
+ * │ child and wraps it in <Field label state hint>. │
30
+ * └──────────────────────────────────────────────────────────────────┘
31
+ *
32
+ * @example
33
+ * const [values, setValues] = useState({ email: "", password: "" });
34
+ * <Form
35
+ * values={values}
36
+ * onChange={setValues}
37
+ * onSubmit={(v) => signIn(v)}
38
+ * >
39
+ * <FormField name="email" label="Email" rules={{ required: true, email: true }}>
40
+ * <Input type="email" />
41
+ * </FormField>
42
+ * <FormField name="password" label="Password" rules={{ required: true, minLength: 8 }}>
43
+ * <Input type="password" />
44
+ * </FormField>
45
+ * <Button type="submit" variant="primary">Sign in</Button>
46
+ * </Form>
47
+ */
48
+ import React from "react";
49
+ export interface FormRules {
50
+ /** Non-empty required. Pass a string to use it as the message. */
51
+ required?: boolean | string;
52
+ /** Minimum string length */
53
+ minLength?: number;
54
+ /** Maximum string length */
55
+ maxLength?: number;
56
+ /** Minimum numeric value */
57
+ min?: number;
58
+ /** Maximum numeric value */
59
+ max?: number;
60
+ /** Must match this pattern */
61
+ pattern?: RegExp;
62
+ /** Must be a valid email address */
63
+ email?: boolean;
64
+ /** Custom validator — return an error message string, or null if valid */
65
+ validate?: (value: unknown, allValues: Record<string, unknown>) => string | null | undefined;
66
+ }
67
+ type Values = Record<string, unknown>;
68
+ type Errors = Record<string, string>;
69
+ export interface FormProps extends Omit<React.FormHTMLAttributes<HTMLFormElement>, "onSubmit" | "onChange" | "onInvalid"> {
70
+ /** Controlled values map */
71
+ values?: Values;
72
+ /** Initial values when uncontrolled */
73
+ defaultValues?: Values;
74
+ /** Called whenever any field value changes */
75
+ onChange?: (values: Values) => void;
76
+ /** Called with the values when the form is submitted AND valid */
77
+ onSubmit?: (values: Values) => void | Promise<void>;
78
+ /** Called with the error map when submitted but invalid */
79
+ onInvalid?: (errors: Errors) => void;
80
+ }
81
+ export declare const Form: React.ForwardRefExoticComponent<FormProps & React.RefAttributes<HTMLFormElement>>;
82
+ export interface FormFieldProps {
83
+ /** Key into the form's values map */
84
+ name: string;
85
+ /** Label rendered by the wrapping Field */
86
+ label?: string;
87
+ /** Helper text shown when there is no error */
88
+ hint?: string;
89
+ /** Validation rules */
90
+ rules?: FormRules;
91
+ /** Single form control element (Input, Textarea, Select, …) */
92
+ children: React.ReactElement;
93
+ className?: string;
94
+ }
95
+ export declare const FormField: React.FC<FormFieldProps>;
96
+ export {};
@@ -0,0 +1,52 @@
1
+ /**
2
+ * @usevyre/react — NumberInput
3
+ *
4
+ * AI CONTEXT:
5
+ * ┌──────────────────────────────────────────────────────────────────┐
6
+ * │ Component: NumberInput │
7
+ * │ Import: import { NumberInput } from "@usevyre/react" │
8
+ * │ │
9
+ * │ Controlled numeric input with −/+ stepper buttons. onChange emits │
10
+ * │ a NUMBER (or null when empty) — not an event. Drops straight into │
11
+ * │ <FormField> (Form handles the non-event value automatically). │
12
+ * │ │
13
+ * │ value = number | null (controlled) │
14
+ * │ onChange = (value: number | null) => void │
15
+ * │ min max step = number (step default 1) │
16
+ * │ precision = number (decimal places to round to) │
17
+ * │ size = "sm" | "md"(default) | "lg" │
18
+ * │ disabled readOnly = boolean │
19
+ * │ │
20
+ * │ Clamps to min/max on blur. Keyboard: ArrowUp/Down ±step, │
21
+ * │ Shift+Arrow ±step×10. Empty input → null. │
22
+ * └──────────────────────────────────────────────────────────────────┘
23
+ *
24
+ * @example
25
+ * const [qty, setQty] = useState<number | null>(1);
26
+ * <NumberInput value={qty} onChange={setQty} min={1} max={99} />
27
+ *
28
+ * @example
29
+ * <FormField name="age" label="Age" rules={{ required: true, min: 18 }}>
30
+ * <NumberInput min={0} max={120} />
31
+ * </FormField>
32
+ */
33
+ import React from "react";
34
+ import type { Size, BaseProps } from "../../types";
35
+ export interface NumberInputProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, "size" | "value" | "onChange" | "defaultValue" | "type">, BaseProps {
36
+ /** Controlled value. null = empty. */
37
+ value?: number | null;
38
+ /** Uncontrolled initial value */
39
+ defaultValue?: number | null;
40
+ /** Called with the parsed number, or null when the field is empty */
41
+ onChange?: (value: number | null) => void;
42
+ min?: number;
43
+ max?: number;
44
+ /** Increment/decrement amount (default 1) */
45
+ step?: number;
46
+ /** Decimal places to round to */
47
+ precision?: number;
48
+ size?: Exclude<Size, "icon">;
49
+ disabled?: boolean;
50
+ readOnly?: boolean;
51
+ }
52
+ export declare const NumberInput: React.ForwardRefExoticComponent<NumberInputProps & React.RefAttributes<HTMLInputElement>>;
@@ -0,0 +1,55 @@
1
+ /**
2
+ * @usevyre/react — OTPInput
3
+ *
4
+ * AI CONTEXT:
5
+ * ┌──────────────────────────────────────────────────────────────────┐
6
+ * │ Component: OTPInput │
7
+ * │ Import: import { OTPInput } from "@usevyre/react" │
8
+ * │ │
9
+ * │ Segmented one-time-code input (verification / 2FA). CONTROLLED. │
10
+ * │ onChange emits the STRING value (not an event) — drops into │
11
+ * │ <FormField>. Paste-aware, auto-advance/backspace, arrow keys. │
12
+ * │ │
13
+ * │ value = string (controlled, length ≤ `length`) │
14
+ * │ onChange = (value: string) => void │
15
+ * │ onComplete?= (value: string) => void (all slots filled) │
16
+ * │ length = number (default 6) │
17
+ * │ type = "numeric"(default) | "alphanumeric" │
18
+ * │ mask = boolean (dots instead of chars, like a password) │
19
+ * │ size = "sm" | "md"(default) | "lg" │
20
+ * │ disabled = boolean autoFocus = boolean │
21
+ * │ │
22
+ * │ Pasting a full code fills every slot. Backspace on an empty slot │
23
+ * │ moves to the previous one. │
24
+ * └──────────────────────────────────────────────────────────────────┘
25
+ *
26
+ * @example
27
+ * const [code, setCode] = useState("");
28
+ * <OTPInput value={code} onChange={setCode} onComplete={verify} />
29
+ *
30
+ * @example
31
+ * <FormField name="otp" label="Verification code"
32
+ * rules={{ required: true, minLength: 6 }}>
33
+ * <OTPInput length={6} />
34
+ * </FormField>
35
+ */
36
+ import React from "react";
37
+ import type { BaseProps } from "../../types";
38
+ export interface OTPInputProps extends BaseProps {
39
+ value?: string;
40
+ defaultValue?: string;
41
+ onChange?: (value: string) => void;
42
+ /** Fired once when every slot is filled */
43
+ onComplete?: (value: string) => void;
44
+ length?: number;
45
+ type?: "numeric" | "alphanumeric";
46
+ /** Render dots instead of characters */
47
+ mask?: boolean;
48
+ size?: "sm" | "md" | "lg";
49
+ disabled?: boolean;
50
+ autoFocus?: boolean;
51
+ /** Forwarded to FormField wiring (used as the field name) */
52
+ name?: string;
53
+ onBlur?: React.FocusEventHandler<HTMLInputElement>;
54
+ }
55
+ export declare const OTPInput: React.ForwardRefExoticComponent<OTPInputProps & React.RefAttributes<HTMLDivElement>>;
@@ -0,0 +1,55 @@
1
+ /**
2
+ * @usevyre/react — Stat + StatGroup
3
+ *
4
+ * AI CONTEXT:
5
+ * ┌──────────────────────────────────────────────────────────────────┐
6
+ * │ Component: Stat (+ StatGroup) │
7
+ * │ Import: import { Stat, StatGroup } from "@usevyre/react" │
8
+ * │ │
9
+ * │ Presentational dashboard KPI. No state. │
10
+ * │ │
11
+ * │ label = string (required) │
12
+ * │ value = string | number (required, large) │
13
+ * │ delta? = string | number (the change amount) │
14
+ * │ trend? = "up" | "down" | "neutral" (CONTROLS the color │
15
+ * │ — up=success, down=danger, neutral=muted) │
16
+ * │ deltaLabel? = string (e.g. "vs last month") │
17
+ * │ icon? = ReactNode │
18
+ * │ size = "sm" | "md"(default) | "lg" │
19
+ * │ │
20
+ * │ trend is EXPLICIT so "churn down = good" can stay green. │
21
+ * │ Wrap several in <StatGroup> for an evenly-split row with dividers.│
22
+ * └──────────────────────────────────────────────────────────────────┘
23
+ *
24
+ * @example
25
+ * <StatGroup>
26
+ * <Stat label="Revenue" value="$48.2k" delta="+12%" trend="up"
27
+ * deltaLabel="vs last month" />
28
+ * <Stat label="Churn" value="2.1%" delta="-0.4%" trend="up"
29
+ * deltaLabel="lower is better" />
30
+ * <Stat label="Orders" value="1,204" delta="0%" trend="neutral" />
31
+ * </StatGroup>
32
+ */
33
+ import React from "react";
34
+ import type { BaseProps } from "../../types";
35
+ export type StatTrend = "up" | "down" | "neutral";
36
+ export interface StatProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "title">, BaseProps {
37
+ /** Metric name (required) */
38
+ label: string;
39
+ /** The headline figure (required) */
40
+ value: string | number;
41
+ /** The change amount, e.g. "+12%" or 24 */
42
+ delta?: string | number;
43
+ /** Explicitly sets the delta color — up=success, down=danger, neutral=muted */
44
+ trend?: StatTrend;
45
+ /** Context for the delta, e.g. "vs last month" */
46
+ deltaLabel?: string;
47
+ /** Optional leading icon */
48
+ icon?: React.ReactNode;
49
+ size?: "sm" | "md" | "lg";
50
+ }
51
+ export declare const Stat: React.ForwardRefExoticComponent<StatProps & React.RefAttributes<HTMLDivElement>>;
52
+ export interface StatGroupProps extends React.HTMLAttributes<HTMLDivElement>, BaseProps {
53
+ children?: React.ReactNode;
54
+ }
55
+ export declare const StatGroup: React.ForwardRefExoticComponent<StatGroupProps & React.RefAttributes<HTMLDivElement>>;
@@ -0,0 +1,76 @@
1
+ /**
2
+ * @usevyre/react — Stepper + Step + StepPanel
3
+ *
4
+ * AI CONTEXT:
5
+ * ┌──────────────────────────────────────────────────────────────────┐
6
+ * │ Component: Stepper (+ StepperNav, Step, StepPanel) │
7
+ * │ Import: import { Stepper, StepperNav, Step, StepPanel } │
8
+ * │ from "@usevyre/react" │
9
+ * │ │
10
+ * │ Multi-step flow indicator + controller (onboarding/checkout/ │
11
+ * │ wizard). CONTROLLED by a 0-based index. Indices come from order. │
12
+ * │ │
13
+ * │ <Stepper> │
14
+ * │ value? = number (controlled active index) │
15
+ * │ defaultValue = number (uncontrolled, default 0) │
16
+ * │ onChange? = (index: number) => void │
17
+ * │ orientation = "horizontal"(default) | "vertical" │
18
+ * │ clickable? = boolean (click a completed Step to go back) │
19
+ * │ <StepperNav> <Step label description? icon? /> … </StepperNav> │
20
+ * │ <StepPanel> … </StepPanel> ← rendered when its order == active │
21
+ * │ │
22
+ * │ Each Step auto-gets state completed | current | upcoming. │
23
+ * │ NOT Tabs (peer panels) — Stepper is an ORDERED linear flow. │
24
+ * └──────────────────────────────────────────────────────────────────┘
25
+ *
26
+ * @example
27
+ * const [step, setStep] = useState(0);
28
+ * <Stepper value={step} onChange={setStep}>
29
+ * <StepperNav>
30
+ * <Step label="Account" />
31
+ * <Step label="Profile" />
32
+ * <Step label="Done" />
33
+ * </StepperNav>
34
+ * <StepPanel><AccountForm /></StepPanel>
35
+ * <StepPanel><ProfileForm /></StepPanel>
36
+ * <StepPanel><Summary /></StepPanel>
37
+ * </Stepper>
38
+ */
39
+ import React from "react";
40
+ import type { BaseProps } from "../../types";
41
+ export interface StepperProps extends BaseProps {
42
+ /** Controlled active step (0-based) */
43
+ value?: number;
44
+ /** Initial active step when uncontrolled */
45
+ defaultValue?: number;
46
+ /** Called with the new active index */
47
+ onChange?: (index: number) => void;
48
+ orientation?: "horizontal" | "vertical";
49
+ /** Allow clicking a completed Step to jump back to it */
50
+ clickable?: boolean;
51
+ children?: React.ReactNode;
52
+ }
53
+ export declare const Stepper: React.ForwardRefExoticComponent<StepperProps & React.RefAttributes<HTMLDivElement>>;
54
+ export interface StepperNavProps extends BaseProps {
55
+ children?: React.ReactNode;
56
+ }
57
+ export declare const StepperNav: React.ForwardRefExoticComponent<StepperNavProps & React.RefAttributes<HTMLDivElement>>;
58
+ export interface StepProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "title"> {
59
+ label?: React.ReactNode;
60
+ description?: React.ReactNode;
61
+ /** Custom indicator content (defaults to step number / ✓ when done) */
62
+ icon?: React.ReactNode;
63
+ /** Explicit 0-based index. Optional — inferred from order otherwise. */
64
+ index?: number;
65
+ /** @internal injected by StepperNav */
66
+ __index?: number;
67
+ }
68
+ export declare const Step: React.ForwardRefExoticComponent<StepProps & React.RefAttributes<HTMLDivElement>>;
69
+ export interface StepPanelProps extends BaseProps {
70
+ children?: React.ReactNode;
71
+ /** Explicit 0-based index. Optional — inferred from order otherwise. */
72
+ index?: number;
73
+ /** @internal injected by Stepper */
74
+ __index?: number;
75
+ }
76
+ export declare const StepPanel: React.FC<StepPanelProps>;
@@ -0,0 +1,70 @@
1
+ /**
2
+ * @usevyre/react — Timeline + TimelineItem
3
+ *
4
+ * AI CONTEXT:
5
+ * ┌──────────────────────────────────────────────────────────────────┐
6
+ * │ Component: Timeline (+ TimelineItem) │
7
+ * │ Import: import { Timeline, TimelineItem } from "@usevyre/react"│
8
+ * │ │
9
+ * │ Vertical activity feed for audit logs / history. Presentational. │
10
+ * │ A marker dot per item + a connector line between them. │
11
+ * │ │
12
+ * │ <Timeline items={[{ title, time?, description?, status?, │
13
+ * │ icon? }]} /> │
14
+ * │ — OR — │
15
+ * │ <Timeline> │
16
+ * │ <TimelineItem title="…" time="…" status="success"> │
17
+ * │ rich content (links, badges, …) │
18
+ * │ </TimelineItem> │
19
+ * │ </Timeline> │
20
+ * │ │
21
+ * │ status = "default"|"success"|"warning"|"danger"|"info" │
22
+ * │ (colors the dot) │
23
+ * │ icon = ReactNode (overrides the dot) │
24
+ * │ │
25
+ * │ Use `items` for plain logs; use TimelineItem children for rich │
26
+ * │ per-item content. Newest-first or oldest-first is up to you — │
27
+ * │ Timeline does not reorder. │
28
+ * └──────────────────────────────────────────────────────────────────┘
29
+ *
30
+ * @example
31
+ * <Timeline
32
+ * items={[
33
+ * { title: "Deployed v2.1", time: "2m ago", status: "success" },
34
+ * { title: "Build started", time: "5m ago", status: "info" },
35
+ * { title: "Push to main", time: "6m ago" },
36
+ * ]}
37
+ * />
38
+ *
39
+ * @example
40
+ * <Timeline>
41
+ * <TimelineItem title="Invoice paid" time="Apr 2" status="success">
42
+ * <Text size="sm">$1,200 — <a href="#">view receipt</a></Text>
43
+ * </TimelineItem>
44
+ * </Timeline>
45
+ */
46
+ import React from "react";
47
+ import type { BaseProps } from "../../types";
48
+ export type TimelineStatus = "default" | "success" | "warning" | "danger" | "info";
49
+ export interface TimelineItemData {
50
+ title: React.ReactNode;
51
+ time?: React.ReactNode;
52
+ description?: React.ReactNode;
53
+ status?: TimelineStatus;
54
+ icon?: React.ReactNode;
55
+ }
56
+ export interface TimelineProps extends React.HTMLAttributes<HTMLOListElement>, BaseProps {
57
+ /** Plain items — alternative to TimelineItem children */
58
+ items?: TimelineItemData[];
59
+ children?: React.ReactNode;
60
+ }
61
+ export declare const Timeline: React.ForwardRefExoticComponent<TimelineProps & React.RefAttributes<HTMLOListElement>>;
62
+ export interface TimelineItemProps extends Omit<React.LiHTMLAttributes<HTMLLIElement>, "title">, BaseProps {
63
+ title: React.ReactNode;
64
+ time?: React.ReactNode;
65
+ status?: TimelineStatus;
66
+ /** Overrides the status dot */
67
+ icon?: React.ReactNode;
68
+ children?: React.ReactNode;
69
+ }
70
+ export declare const TimelineItem: React.ForwardRefExoticComponent<TimelineItemProps & React.RefAttributes<HTMLLIElement>>;
@@ -0,0 +1,79 @@
1
+ /**
2
+ * @usevyre/react — ToggleGroup + ToggleItem
3
+ *
4
+ * AI CONTEXT:
5
+ * ┌──────────────────────────────────────────────────────────────────┐
6
+ * │ Component: ToggleGroup (+ ToggleItem) │
7
+ * │ Import: import { ToggleGroup, ToggleItem } from "@usevyre/react"│
8
+ * │ │
9
+ * │ Segmented control. CONTROLLED — the group owns the value. │
10
+ * │ onChange emits the VALUE (string|null or string[]), not an event. │
11
+ * │ │
12
+ * │ type = "single"(default) | "multiple" │
13
+ * │ single → value: string | null, onChange(string | null) │
14
+ * │ multiple → value: string[], onChange(string[]) │
15
+ * │ options? = { value; label?; icon?; disabled? }[] │
16
+ * │ size = "sm" | "md"(default) | "lg" │
17
+ * │ disabled = boolean (disables the whole group) │
18
+ * │ │
19
+ * │ Use `options` for simple lists, or <ToggleItem value> children │
20
+ * │ for custom content. Keyboard: arrows move, Space/Enter toggles. │
21
+ * │ │
22
+ * │ NOT Switch (boolean), NOT ButtonGroup (layout only), │
23
+ * │ NOT RadioGroup (form radios, single only). │
24
+ * └──────────────────────────────────────────────────────────────────┘
25
+ *
26
+ * @example
27
+ * const [view, setView] = useState<string | null>("grid");
28
+ * <ToggleGroup
29
+ * value={view}
30
+ * onChange={setView}
31
+ * options={[
32
+ * { value: "grid", label: "Grid" },
33
+ * { value: "list", label: "List" },
34
+ * ]}
35
+ * />
36
+ *
37
+ * @example // multiple, composable
38
+ * const [fmt, setFmt] = useState<string[]>(["bold"]);
39
+ * <ToggleGroup type="multiple" value={fmt} onChange={setFmt}>
40
+ * <ToggleItem value="bold">B</ToggleItem>
41
+ * <ToggleItem value="italic">I</ToggleItem>
42
+ * </ToggleGroup>
43
+ */
44
+ import React from "react";
45
+ import type { BaseProps } from "../../types";
46
+ export interface ToggleOption {
47
+ value: string;
48
+ label?: React.ReactNode;
49
+ icon?: React.ReactNode;
50
+ disabled?: boolean;
51
+ }
52
+ type ToggleSize = "sm" | "md" | "lg";
53
+ type SingleProps = {
54
+ type?: "single";
55
+ value?: string | null;
56
+ onChange?: (value: string | null) => void;
57
+ };
58
+ type MultipleProps = {
59
+ type: "multiple";
60
+ value?: string[];
61
+ onChange?: (value: string[]) => void;
62
+ };
63
+ export type ToggleGroupProps = (SingleProps | MultipleProps) & BaseProps & {
64
+ options?: ToggleOption[];
65
+ size?: ToggleSize;
66
+ disabled?: boolean;
67
+ orientation?: "horizontal" | "vertical";
68
+ /** Accessible label for the group */
69
+ "aria-label"?: string;
70
+ children?: React.ReactNode;
71
+ };
72
+ export declare const ToggleGroup: React.ForwardRefExoticComponent<ToggleGroupProps & React.RefAttributes<HTMLDivElement>>;
73
+ export interface ToggleItemProps extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, "value"> {
74
+ value: string;
75
+ icon?: React.ReactNode;
76
+ disabled?: boolean;
77
+ }
78
+ export declare const ToggleItem: React.ForwardRefExoticComponent<ToggleItemProps & React.RefAttributes<HTMLButtonElement>>;
79
+ export {};
@@ -0,0 +1,62 @@
1
+ /**
2
+ * @usevyre/react — Tree
3
+ *
4
+ * AI CONTEXT:
5
+ * ┌──────────────────────────────────────────────────────────────────┐
6
+ * │ Component: Tree │
7
+ * │ Import: import { Tree } from "@usevyre/react" │
8
+ * │ │
9
+ * │ Hierarchical tree view (file explorer / nested nav). DATA-DRIVEN │
10
+ * │ and CONTROLLED. Pass a nested array; the Tree renders recursively.│
11
+ * │ │
12
+ * │ data = TreeNode[] where TreeNode = { │
13
+ * │ id: string; label: ReactNode; │
14
+ * │ icon?: ReactNode; disabled?: boolean; │
15
+ * │ children?: TreeNode[] │
16
+ * │ } │
17
+ * │ expandedIds? = string[] (controlled) │
18
+ * │ defaultExpandedIds = string[] (uncontrolled) │
19
+ * │ onExpandedChange? = (ids: string[]) => void │
20
+ * │ selectedId? = string | null (controlled) │
21
+ * │ defaultSelectedId = string | null (uncontrolled) │
22
+ * │ onSelect? = (id: string) => void │
23
+ * │ │
24
+ * │ Single selection. A node with `children` is a folder (toggles │
25
+ * │ expand on click); a leaf fires onSelect. Keyboard: ↑/↓ move, │
26
+ * │ →/← expand/collapse, Enter/Space select. │
27
+ * └──────────────────────────────────────────────────────────────────┘
28
+ *
29
+ * @example
30
+ * const [sel, setSel] = useState<string | null>("a/b.ts");
31
+ * <Tree
32
+ * data={[
33
+ * { id: "src", label: "src", children: [
34
+ * { id: "a.ts", label: "a.ts" },
35
+ * { id: "b", label: "b", children: [{ id: "b/c.ts", label: "c.ts" }] },
36
+ * ]},
37
+ * { id: "readme", label: "README.md" },
38
+ * ]}
39
+ * selectedId={sel}
40
+ * onSelect={setSel}
41
+ * defaultExpandedIds={["src"]}
42
+ * />
43
+ */
44
+ import React from "react";
45
+ import type { BaseProps } from "../../types";
46
+ export interface TreeNode {
47
+ id: string;
48
+ label: React.ReactNode;
49
+ icon?: React.ReactNode;
50
+ disabled?: boolean;
51
+ children?: TreeNode[];
52
+ }
53
+ export interface TreeProps extends Omit<React.HTMLAttributes<HTMLUListElement>, "onSelect">, BaseProps {
54
+ data: TreeNode[];
55
+ expandedIds?: string[];
56
+ defaultExpandedIds?: string[];
57
+ onExpandedChange?: (ids: string[]) => void;
58
+ selectedId?: string | null;
59
+ defaultSelectedId?: string | null;
60
+ onSelect?: (id: string) => void;
61
+ }
62
+ export declare const Tree: React.ForwardRefExoticComponent<TreeProps & React.RefAttributes<HTMLUListElement>>;