@dimaan/ui 0.0.10 → 0.0.11

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/dist/index.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import * as react from 'react';
3
- import { HTMLAttributes, ReactNode, ReactElement, ButtonHTMLAttributes, InputHTMLAttributes, ChangeEvent, FieldsetHTMLAttributes, AnchorHTMLAttributes, Ref, TextareaHTMLAttributes } from 'react';
3
+ import { HTMLAttributes, ReactNode, ReactElement, ButtonHTMLAttributes, InputHTMLAttributes, ChangeEvent, ComponentPropsWithoutRef, FieldsetHTMLAttributes, Ref, AnchorHTMLAttributes, TextareaHTMLAttributes } from 'react';
4
+ import * as RadixDropdown from '@radix-ui/react-dropdown-menu';
4
5
  import { FieldValues, FieldPath, Control } from 'react-hook-form';
5
6
  import * as RadixRadioGroup from '@radix-ui/react-radio-group';
6
7
  import { ClassValue } from 'clsx';
@@ -132,6 +133,43 @@ interface AvatarProps extends HTMLAttributes<HTMLSpanElement> {
132
133
  }
133
134
  declare function Avatar({ src, alt, fallback, size, className, ...props }: AvatarProps): react_jsx_runtime.JSX.Element;
134
135
 
136
+ type BadgeVariant = 'default' | 'primary' | 'success' | 'warning' | 'destructive' | 'outline';
137
+ type BadgeSize = 'sm' | 'md';
138
+ declare const badgeVariantClass: Record<BadgeVariant, string>;
139
+ declare const badgeSizeClass: Record<BadgeSize, string>;
140
+ /** The dot-indicator size for each badge size. */
141
+ declare const badgeDotSizeClass: Record<BadgeSize, string>;
142
+ declare const badgeBaseClass = "inline-flex shrink-0 items-center rounded-full border font-medium leading-none whitespace-nowrap select-none transition-colors";
143
+
144
+ interface BadgeProps extends HTMLAttributes<HTMLSpanElement> {
145
+ variant?: BadgeVariant;
146
+ size?: BadgeSize;
147
+ /** Render a small dot before the label (useful for online/status indicators). */
148
+ dot?: boolean;
149
+ }
150
+ /**
151
+ * Inline status pill. Most common use: status column in a table (Active /
152
+ * Pending / Archived), category labels, or counts in nav items.
153
+ *
154
+ * @example Status pill in a table cell
155
+ * ```tsx
156
+ * <Badge variant="success">Active</Badge>
157
+ * <Badge variant="warning">Pending</Badge>
158
+ * <Badge variant="default">Archived</Badge>
159
+ * ```
160
+ *
161
+ * @example With status dot
162
+ * ```tsx
163
+ * <Badge variant="success" dot>Online</Badge>
164
+ * ```
165
+ *
166
+ * @example Outline (border-only, no fill)
167
+ * ```tsx
168
+ * <Badge variant="outline">Beta</Badge>
169
+ * ```
170
+ */
171
+ declare const Badge: react.ForwardRefExoticComponent<BadgeProps & react.RefAttributes<HTMLSpanElement>>;
172
+
135
173
  type ButtonVariant = 'primary' | 'secondary' | 'outline' | 'ghost' | 'destructive' | 'success' | 'warning' | 'link';
136
174
  type ButtonSize = 'sm' | 'md' | 'lg' | 'icon' | 'icon-sm';
137
175
  declare const buttonVariantClass: Record<ButtonVariant, string>;
@@ -194,6 +232,153 @@ interface CheckboxProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'typ
194
232
  }
195
233
  declare const Checkbox: react.ForwardRefExoticComponent<CheckboxProps & react.RefAttributes<HTMLInputElement>>;
196
234
 
235
+ type DropdownMenuItemVariant = 'default' | 'destructive';
236
+ declare const dropdownMenuContentClass = "z-50 min-w-32 overflow-hidden rounded-md border border-border bg-popover p-1 text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95";
237
+ declare const dropdownMenuItemBaseClass = "relative flex w-full cursor-pointer select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none transition-colors data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:size-4 [&_svg]:shrink-0";
238
+ declare const dropdownMenuItemVariantClass: Record<DropdownMenuItemVariant, string>;
239
+ /** Indent items without an icon so they align with items that have one. */
240
+ declare const dropdownMenuItemInsetClass = "ps-8";
241
+ declare const dropdownMenuSeparatorClass = "-mx-1 my-1 h-px bg-border";
242
+ declare const dropdownMenuLabelClass = "px-2 py-1.5 text-xs font-semibold text-muted-foreground select-none";
243
+ declare const dropdownMenuShortcutClass = "ms-auto text-xs tracking-widest text-muted-foreground";
244
+
245
+ /**
246
+ * Compound dropdown menu built on `@radix-ui/react-dropdown-menu`. Use for
247
+ * row actions (⋯ menu in tables), header overflow menus, user avatar menus.
248
+ *
249
+ * @example Row actions in a table
250
+ * ```tsx
251
+ * <DropdownMenu>
252
+ * <DropdownMenuTrigger asChild>
253
+ * <Button variant="ghost" size="icon" aria-label="More actions">
254
+ * <MoreHorizontal />
255
+ * </Button>
256
+ * </DropdownMenuTrigger>
257
+ * <DropdownMenuContent align="end">
258
+ * <DropdownMenuItem onSelect={() => edit(row)}>
259
+ * <Pencil />
260
+ * Edit
261
+ * </DropdownMenuItem>
262
+ * <DropdownMenuItem onSelect={() => archive(row)}>
263
+ * <Archive />
264
+ * Archive
265
+ * </DropdownMenuItem>
266
+ * <DropdownMenuSeparator />
267
+ * <DropdownMenuItem variant="destructive" onSelect={() => del(row)}>
268
+ * <Trash2 />
269
+ * Delete
270
+ * </DropdownMenuItem>
271
+ * </DropdownMenuContent>
272
+ * </DropdownMenu>
273
+ * ```
274
+ *
275
+ * @example With label, group, and keyboard shortcut
276
+ * ```tsx
277
+ * <DropdownMenu>
278
+ * <DropdownMenuTrigger asChild>
279
+ * <Button variant="outline">Options</Button>
280
+ * </DropdownMenuTrigger>
281
+ * <DropdownMenuContent>
282
+ * <DropdownMenuLabel>My account</DropdownMenuLabel>
283
+ * <DropdownMenuItem>
284
+ * Profile
285
+ * <DropdownMenuShortcut>⌘P</DropdownMenuShortcut>
286
+ * </DropdownMenuItem>
287
+ * <DropdownMenuItem>
288
+ * Settings
289
+ * <DropdownMenuShortcut>⌘,</DropdownMenuShortcut>
290
+ * </DropdownMenuItem>
291
+ * </DropdownMenuContent>
292
+ * </DropdownMenu>
293
+ * ```
294
+ */
295
+ declare const DropdownMenu: react.FC<RadixDropdown.DropdownMenuProps>;
296
+ declare const DropdownMenuTrigger: react.ForwardRefExoticComponent<RadixDropdown.DropdownMenuTriggerProps & react.RefAttributes<HTMLButtonElement>>;
297
+ declare const DropdownMenuGroup: react.ForwardRefExoticComponent<RadixDropdown.DropdownMenuGroupProps & react.RefAttributes<HTMLDivElement>>;
298
+ declare const DropdownMenuPortal: react.FC<RadixDropdown.DropdownMenuPortalProps>;
299
+ interface DropdownMenuContentProps extends ComponentPropsWithoutRef<typeof RadixDropdown.Content> {
300
+ }
301
+ declare const DropdownMenuContent: react.ForwardRefExoticComponent<DropdownMenuContentProps & react.RefAttributes<HTMLDivElement>>;
302
+ interface DropdownMenuItemProps extends ComponentPropsWithoutRef<typeof RadixDropdown.Item> {
303
+ variant?: DropdownMenuItemVariant;
304
+ /** Indent items without a leading icon so they align with iconed siblings. */
305
+ inset?: boolean;
306
+ }
307
+ declare const DropdownMenuItem: react.ForwardRefExoticComponent<DropdownMenuItemProps & react.RefAttributes<HTMLDivElement>>;
308
+ interface DropdownMenuSeparatorProps extends ComponentPropsWithoutRef<typeof RadixDropdown.Separator> {
309
+ }
310
+ declare const DropdownMenuSeparator: react.ForwardRefExoticComponent<DropdownMenuSeparatorProps & react.RefAttributes<HTMLDivElement>>;
311
+ interface DropdownMenuLabelProps extends ComponentPropsWithoutRef<typeof RadixDropdown.Label> {
312
+ /** Indent to align with iconed items. */
313
+ inset?: boolean;
314
+ }
315
+ declare const DropdownMenuLabel: react.ForwardRefExoticComponent<DropdownMenuLabelProps & react.RefAttributes<HTMLDivElement>>;
316
+ /**
317
+ * Visual hint for a keyboard shortcut, rendered at the trailing edge of an
318
+ * item. Pure presentation — does **not** register a keyboard handler.
319
+ */
320
+ interface DropdownMenuShortcutProps extends HTMLAttributes<HTMLSpanElement> {
321
+ children: ReactNode;
322
+ }
323
+ declare const DropdownMenuShortcut: react.ForwardRefExoticComponent<DropdownMenuShortcutProps & react.RefAttributes<HTMLSpanElement>>;
324
+
325
+ type EmptyStateSize = 'sm' | 'md' | 'lg';
326
+ declare const emptyStateContainerSizeClass: Record<EmptyStateSize, string>;
327
+ declare const emptyStateIconWrapperSizeClass: Record<EmptyStateSize, string>;
328
+ declare const emptyStateTitleSizeClass: Record<EmptyStateSize, string>;
329
+ declare const emptyStateDescriptionSizeClass: Record<EmptyStateSize, string>;
330
+ declare const emptyStateActionsSpacingClass: Record<EmptyStateSize, string>;
331
+ declare const emptyStateBaseClass = "flex flex-col items-center justify-center text-center px-4";
332
+ declare const emptyStateIconWrapperBaseClass = "inline-flex items-center justify-center rounded-full bg-muted text-muted-foreground";
333
+
334
+ interface EmptyStateProps extends Omit<HTMLAttributes<HTMLDivElement>, 'title'> {
335
+ /** Optional icon rendered in a circular muted background. Sized via `size` prop. */
336
+ icon?: ReactNode;
337
+ /** Required title — what's missing or what state we're in. */
338
+ title: ReactNode;
339
+ /** Secondary text — explain why the state is empty, suggest next action. */
340
+ description?: ReactNode;
341
+ /** Slot for primary (and optional secondary) action buttons. Rendered below description. */
342
+ action?: ReactNode;
343
+ /** Visual size — `sm` for inline empties (e.g. inside a popover), `md` (default) for table cells, `lg` for full-page empties. */
344
+ size?: EmptyStateSize;
345
+ }
346
+ /**
347
+ * Inline empty-state placeholder. Use when a list, table, or section has no
348
+ * data to show — either because the user hasn't created anything yet, or
349
+ * because filters/search returned zero results.
350
+ *
351
+ * The most common dashboard pattern: render inside a table's `tbody` colspan
352
+ * cell, or as a sibling to a list when the list is empty.
353
+ *
354
+ * @example No-results in a filtered table
355
+ * ```tsx
356
+ * <EmptyState
357
+ * icon={<SearchX />}
358
+ * title="No users match your filters"
359
+ * description="Try clearing the search or changing the status filter."
360
+ * action={<Button variant="outline" onClick={resetFilters}>Reset filters</Button>}
361
+ * />
362
+ * ```
363
+ *
364
+ * @example First-run empty (encourage creation)
365
+ * ```tsx
366
+ * <EmptyState
367
+ * size="lg"
368
+ * icon={<Users />}
369
+ * title="No users yet"
370
+ * description="Add your first team member to get started."
371
+ * action={<Button onClick={openCreate}>Add user</Button>}
372
+ * />
373
+ * ```
374
+ *
375
+ * @example Compact (inline)
376
+ * ```tsx
377
+ * <EmptyState size="sm" title="No notifications" />
378
+ * ```
379
+ */
380
+ declare const EmptyState: react.ForwardRefExoticComponent<EmptyStateProps & react.RefAttributes<HTMLDivElement>>;
381
+
197
382
  interface FieldRHFProps<TValues extends FieldValues = FieldValues, TName extends FieldPath<TValues> = FieldPath<TValues>> {
198
383
  /**
199
384
  * RHF `Control` returned from `useForm()`. Optional when `Field` is rendered
@@ -371,126 +556,6 @@ interface LanguageSwitcherProps<TCode extends string = string> extends Omit<Fiel
371
556
  }
372
557
  declare function LanguageSwitcher<TCode extends string = string>({ languages, value, onChange, ariaLabel, className, ...props }: LanguageSwitcherProps<TCode>): react_jsx_runtime.JSX.Element;
373
558
 
374
- type RadioGroupSize = 'sm' | 'md' | 'lg';
375
- /** Outer circle (radio button itself) — sized + bordered. */
376
- declare const radioItemSizeClass: Record<RadioGroupSize, string>;
377
- /** Inner indicator (the filled dot when selected). Centred via flex on the parent. */
378
- declare const radioIndicatorSizeClass: Record<RadioGroupSize, string>;
379
- /** Label text size that pairs naturally with each radio size. */
380
- declare const radioLabelSizeClass: Record<RadioGroupSize, string>;
381
- declare const radioItemBaseClass = "aspect-square shrink-0 rounded-full border border-input bg-background text-primary outline-none transition-colors focus-visible:ring-2 focus-visible:ring-ring/40 focus-visible:ring-offset-2 focus-visible:ring-offset-background hover:border-ring disabled:cursor-not-allowed disabled:opacity-50 aria-[invalid=true]:border-destructive aria-[invalid=true]:focus-visible:ring-destructive/40 data-[state=checked]:border-primary";
382
- declare const radioIndicatorBaseClass = "flex h-full w-full items-center justify-center";
383
- declare const radioIndicatorDotClass = "rounded-full bg-primary";
384
- /** Each option row: radio + label + optional description. */
385
- declare const radioOptionRowClass = "flex cursor-pointer items-start gap-2 has-[button:disabled]:cursor-not-allowed";
386
- /** The group container — vertical stack by default, horizontal row when orientation="horizontal". */
387
- declare const radioGroupBaseClass = "flex gap-3";
388
- declare const radioGroupOrientationClass: {
389
- readonly vertical: "flex-col";
390
- readonly horizontal: "flex-row flex-wrap";
391
- };
392
-
393
- interface RadioGroupOption {
394
- value: string;
395
- /** Visible label rendered next to the radio button. */
396
- label: ReactNode;
397
- /** Optional secondary text rendered below the label (e.g. plan description). */
398
- description?: ReactNode;
399
- disabled?: boolean;
400
- }
401
- type RadioGroupOrientation = 'vertical' | 'horizontal';
402
- interface RadioGroupProps {
403
- /** Visual size of each radio + label. */
404
- radioSize?: RadioGroupSize;
405
- /** Layout direction within the group. `'vertical'` (default) stacks options; `'horizontal'` lays them out in a row. */
406
- orientation?: RadioGroupOrientation;
407
- /** Controlled selected value (Radix-style). */
408
- value?: string;
409
- /** Initial selected value for uncontrolled usage. */
410
- defaultValue?: string;
411
- /** Radix-style change handler — receives the new value directly. */
412
- onValueChange?: (value: string) => void;
413
- /** Synthetic-event handler for `react-hook-form`'s `field.onChange` and other consumers. */
414
- onChange?: (event: ChangeEvent<HTMLInputElement>) => void;
415
- /** Called when focus leaves the group. */
416
- onBlur?: () => void;
417
- /** Form name (for native form submission). */
418
- name?: string;
419
- /** Disables the entire group. */
420
- disabled?: boolean;
421
- /** Marks the group as required. */
422
- required?: boolean;
423
- /** Override id (otherwise auto-generated via useId). */
424
- id?: string;
425
- /** Declarative options. When `children` is provided it wins (escape hatch for custom content). */
426
- options?: RadioGroupOption[];
427
- /** Class on the outer group container. */
428
- className?: string;
429
- 'aria-label'?: string;
430
- 'aria-labelledby'?: string;
431
- 'aria-describedby'?: string;
432
- 'aria-invalid'?: boolean | 'true' | 'false';
433
- /** Radix children — used for advanced composition (custom RadioGroupItem layouts). */
434
- children?: ReactNode;
435
- }
436
- /**
437
- * Group of mutually-exclusive radio buttons built on `@radix-ui/react-radio-group`.
438
- * Use for **3–5 options** where Select would be overkill (pricing tier, privacy
439
- * level, single-choice settings). Bare component — wrap in `<Field label="…">`
440
- * for the GROUP label, helper, and error rendering.
441
- *
442
- * Each option carries its own per-radio `label` (and optional `description`).
443
- * The Field's outer label names the group; the option labels name each choice.
444
- *
445
- * @example Inside a Field (RHF + Zod)
446
- * ```tsx
447
- * <Field name="plan" label="Subscription plan" description="You can change anytime.">
448
- * <RadioGroup
449
- * options={[
450
- * { value: 'free', label: 'Free', description: 'Up to 3 projects' },
451
- * { value: 'pro', label: 'Pro', description: 'Unlimited projects' },
452
- * { value: 'enterprise', label: 'Enterprise', description: 'Custom limits' },
453
- * ]}
454
- * />
455
- * </Field>
456
- * ```
457
- *
458
- * @example Horizontal row in a settings card
459
- * ```tsx
460
- * <Field label="Visibility" orientation="horizontal">
461
- * <RadioGroup
462
- * orientation="horizontal"
463
- * value={visibility}
464
- * onValueChange={setVisibility}
465
- * options={[
466
- * { value: 'public', label: 'Public' },
467
- * { value: 'private', label: 'Private' },
468
- * ]}
469
- * />
470
- * </Field>
471
- * ```
472
- */
473
- declare const RadioGroup: react.ForwardRefExoticComponent<RadioGroupProps & react.RefAttributes<HTMLDivElement>>;
474
- /**
475
- * `<RadioGroupItem>` — re-exported for consumers building custom option layouts
476
- * (icons, badges, etc.) via the `children` escape hatch.
477
- *
478
- * @example
479
- * ```tsx
480
- * <RadioGroup value={plan} onValueChange={setPlan}>
481
- * {plans.map((p) => (
482
- * <label key={p.value} htmlFor={p.value} className="flex items-center gap-2">
483
- * <RadioGroupItem id={p.value} value={p.value} />
484
- * <PlanCard {...p} />
485
- * </label>
486
- * ))}
487
- * </RadioGroup>
488
- * ```
489
- */
490
- declare const RadioGroupItem: react.ForwardRefExoticComponent<Omit<RadixRadioGroup.RadioGroupItemProps & react.RefAttributes<HTMLButtonElement>, "ref"> & {
491
- radioSize?: RadioGroupSize;
492
- } & react.RefAttributes<HTMLButtonElement>>;
493
-
494
559
  type SelectVariant = 'default' | 'filled' | 'ghost';
495
560
  type SelectSize = 'sm' | 'md' | 'lg';
496
561
  declare const selectVariantClass: Record<SelectVariant, string>;
@@ -586,159 +651,31 @@ interface SelectProps {
586
651
  */
587
652
  declare const Select: react.ForwardRefExoticComponent<SelectProps & react.RefAttributes<HTMLButtonElement>>;
588
653
 
589
- type SidebarProps = HTMLAttributes<HTMLElement>;
590
- declare function Sidebar({ className, children, ...props }: SidebarProps): react_jsx_runtime.JSX.Element;
591
-
592
- type SidebarFooterProps = HTMLAttributes<HTMLDivElement>;
593
- declare function SidebarFooter({ className, children, ...props }: SidebarFooterProps): react_jsx_runtime.JSX.Element;
594
-
595
- interface SidebarGroupProps extends HTMLAttributes<HTMLDivElement> {
596
- label?: ReactNode;
654
+ type TableSize = 'sm' | 'md' | 'lg';
655
+ interface TableSizeClasses {
656
+ /** Applied to <tr> when needed (currently empty — present for symmetry). */
657
+ row: string;
658
+ /** Applied to <td>. */
659
+ cell: string;
660
+ /** Applied to <th>. */
661
+ head: string;
597
662
  }
598
- declare function SidebarGroup({ label, className, children, ...props }: SidebarGroupProps): react_jsx_runtime.JSX.Element;
599
-
600
- type SidebarHeaderProps = HTMLAttributes<HTMLDivElement>;
601
- declare function SidebarHeader({ className, children, ...props }: SidebarHeaderProps): react_jsx_runtime.JSX.Element;
602
-
603
- type SidebarNavProps = HTMLAttributes<HTMLElement>;
604
- declare function SidebarNav({ className, children, ...props }: SidebarNavProps): react_jsx_runtime.JSX.Element;
663
+ declare const tableSizeClass: Record<TableSize, TableSizeClasses>;
664
+ declare const tableBaseClass = "w-full caption-bottom border-collapse";
665
+ declare const selectedRowClass = "bg-muted/40";
666
+ declare const sortIconClass = "inline-flex h-3 w-3 shrink-0 items-center justify-center";
667
+ declare const alignClass: Record<ColumnAlign, string>;
605
668
 
606
- interface SidebarNavGroupProps extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'children'> {
607
- icon?: ReactNode;
608
- label?: ReactNode;
609
- endSlot?: ReactNode;
610
- /** Highlight the parent (e.g. when one of its children is active). */
611
- active?: boolean;
612
- /** Uncontrolled initial state. */
613
- defaultOpen?: boolean;
614
- /** Controlled open state. */
615
- open?: boolean;
616
- onOpenChange?: (open: boolean) => void;
617
- children: ReactNode;
669
+ type SortDirection = 'asc' | 'desc';
670
+ interface SortState {
671
+ /** Column id being sorted, or `null` when no sort is active. */
672
+ columnId: string | null;
673
+ direction: SortDirection;
618
674
  }
619
- declare function SidebarNavGroup({ icon, label, endSlot, active, defaultOpen, open: openProp, onOpenChange, className, children, onClick, ...props }: SidebarNavGroupProps): react_jsx_runtime.JSX.Element;
620
-
621
- type SidebarNavItemRenderProps = {
622
- className: string;
623
- children: ReactNode;
624
- title?: string;
625
- 'aria-current'?: 'page';
626
- 'data-active'?: 'true';
627
- };
628
- interface SidebarNavItemProps extends AnchorHTMLAttributes<HTMLAnchorElement> {
629
- icon?: ReactNode;
630
- active?: boolean;
631
- label?: ReactNode;
632
- endSlot?: ReactNode;
633
- /**
634
- * Override the rendered element. Use this to plug in routing-library link
635
- * components (e.g. react-router `<Link>`) while keeping the styling.
636
- */
637
- render?: (props: SidebarNavItemRenderProps) => ReactElement;
638
- }
639
- declare function SidebarNavItem({ icon, active, label, endSlot, className, children, render, ...props }: SidebarNavItemProps): react_jsx_runtime.JSX.Element;
640
-
641
- type SwitchSize = 'sm' | 'md' | 'lg';
642
- /**
643
- * Each size is a tuple: track dimensions + thumb size + thumb travel distance.
644
- * Track is `w` x `h`; thumb is `w/h size-X`; travel is the translation distance
645
- * when checked (= track width − thumb size − padding).
646
- */
647
- declare const switchTrackClass: Record<SwitchSize, string>;
648
- declare const switchThumbClass: Record<SwitchSize, string>;
649
- declare const switchTrackBaseClass = "relative inline-flex shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent bg-input transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/40 focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary aria-[invalid=true]:ring-2 aria-[invalid=true]:ring-destructive/40";
650
- declare const switchThumbBaseClass = "pointer-events-none block rounded-full bg-background shadow-sm ring-0 transition-transform";
651
-
652
- interface SwitchProps {
653
- /** Visual size. */
654
- switchSize?: SwitchSize;
655
- /** Controlled checked state (Radix-style). */
656
- checked?: boolean;
657
- /** Initial checked state for uncontrolled usage. */
658
- defaultChecked?: boolean;
659
- /** Radix-style change handler — receives the new boolean directly. */
660
- onCheckedChange?: (checked: boolean) => void;
661
- /**
662
- * Form-library compatibility props. `value` mirrors what `<Field>` injects
663
- * (RHF passes `field.value` as a boolean). `onChange` fires alongside
664
- * `onCheckedChange` with a synthetic event so `field.onChange` works too.
665
- */
666
- value?: boolean | string | number;
667
- onChange?: (event: ChangeEvent<HTMLButtonElement>) => void;
668
- onBlur?: () => void;
669
- /** Form name for native form submission. */
670
- name?: string;
671
- /** Disable interaction. */
672
- disabled?: boolean;
673
- /** Mark required for form validation. */
674
- required?: boolean;
675
- /** Override id (otherwise auto-generated via useId). */
676
- id?: string;
677
- /** Class on the track (the switch itself). */
678
- className?: string;
679
- 'aria-label'?: string;
680
- 'aria-describedby'?: string;
681
- 'aria-invalid'?: boolean | 'true' | 'false';
682
- }
683
- /**
684
- * Boolean toggle built on `@radix-ui/react-switch`. Renders only the track +
685
- * thumb — wrap it in `<Field orientation="horizontal" label="…">` to add a
686
- * label, helper text, error, and aria wiring without duplicating that logic
687
- * inside every form control.
688
- *
689
- * @example Inside a Field (RHF + Zod)
690
- * ```tsx
691
- * <Field name="darkMode" label="Dark mode" orientation="horizontal">
692
- * <Switch />
693
- * </Field>
694
- * ```
695
- *
696
- * @example Bare in a settings list (custom layout)
697
- * ```tsx
698
- * <ul className="divide-y divide-border">
699
- * <li className="flex items-center justify-between py-3">
700
- * <span>Email digest</span>
701
- * <Switch checked={digest} onCheckedChange={setDigest} aria-label="Email digest" />
702
- * </li>
703
- * </ul>
704
- * ```
705
- *
706
- * @example Standalone controlled
707
- * ```tsx
708
- * <Switch
709
- * checked={enabled}
710
- * onCheckedChange={setEnabled}
711
- * aria-label="Enable notifications"
712
- * />
713
- * ```
714
- */
715
- declare const Switch: react.ForwardRefExoticComponent<SwitchProps & react.RefAttributes<HTMLButtonElement>>;
716
-
717
- type TableSize = 'sm' | 'md' | 'lg';
718
- interface TableSizeClasses {
719
- /** Applied to <tr> when needed (currently empty — present for symmetry). */
720
- row: string;
721
- /** Applied to <td>. */
722
- cell: string;
723
- /** Applied to <th>. */
724
- head: string;
725
- }
726
- declare const tableSizeClass: Record<TableSize, TableSizeClasses>;
727
- declare const tableBaseClass = "w-full caption-bottom border-collapse";
728
- declare const selectedRowClass = "bg-muted/40";
729
- declare const sortIconClass = "inline-flex h-3 w-3 shrink-0 items-center justify-center";
730
- declare const alignClass: Record<ColumnAlign, string>;
731
-
732
- type SortDirection = 'asc' | 'desc';
733
- interface SortState {
734
- /** Column id being sorted, or `null` when no sort is active. */
735
- columnId: string | null;
736
- direction: SortDirection;
737
- }
738
- interface PaginationState {
739
- /** 0-based page index. */
740
- pageIndex: number;
741
- pageSize: number;
675
+ interface PaginationState {
676
+ /** 0-based page index. */
677
+ pageIndex: number;
678
+ pageSize: number;
742
679
  }
743
680
  /** Set of row ids (returned from `getRowId`) that are currently selected. */
744
681
  type RowSelectionState = ReadonlySet<string>;
@@ -825,6 +762,462 @@ interface TableProps<T> {
825
762
 
826
763
  declare function Table<T>(props: TableProps<T>): react_jsx_runtime.JSX.Element;
827
764
 
765
+ /**
766
+ * One filter dropdown definition for `<ListPage>`. ListPage manages each
767
+ * filter's state internally — you provide options + accessor.
768
+ */
769
+ interface ListPageFilter<T> {
770
+ /** Unique key for state tracking. */
771
+ key: string;
772
+ /** Aria-label on the Select trigger. */
773
+ ariaLabel?: string;
774
+ /** Returns the row value to match against the filter selection. */
775
+ accessor: (row: T) => string;
776
+ /** Options to choose from. The first option's value is treated as "no filter / show all". */
777
+ options: SelectOption[];
778
+ /** Override the "no filter" default. Defaults to the first option's `value`. */
779
+ defaultValue?: string;
780
+ /** Width of the Select. Defaults to `'default'` (~11rem). */
781
+ width?: 'narrow' | 'default' | 'wide';
782
+ }
783
+ interface ListPageEmptyState {
784
+ icon?: ReactNode;
785
+ title?: ReactNode;
786
+ description?: ReactNode;
787
+ /** Override the default "Reset filters" action button. Pass `null` to hide entirely. */
788
+ action?: ReactNode | null;
789
+ }
790
+ interface ListPageLabels {
791
+ /** Default search input placeholder. */
792
+ searchPlaceholder?: string;
793
+ /** Default search aria-label (falls back to placeholder). */
794
+ searchAriaLabel?: string;
795
+ /** Default "Reset filters" button label. */
796
+ reset?: string;
797
+ /** Default empty-state title (when filters return zero). */
798
+ emptyTitle?: string;
799
+ /** Default empty-state description. */
800
+ emptyDescription?: string;
801
+ }
802
+ interface ListPageProps<T> {
803
+ title: ReactNode;
804
+ description?: ReactNode;
805
+ /** Page-header bordered separator. Defaults to `true` for list pages. */
806
+ bordered?: boolean;
807
+ /** Header action slot — primary "Add" button, etc. */
808
+ actions?: ReactNode;
809
+ data: T[];
810
+ columns: Column<T>[];
811
+ getRowId: (row: T) => string;
812
+ /** Keys on `T` to search. Search input only renders when this is provided. */
813
+ searchKeys?: Array<keyof T>;
814
+ filters?: ListPageFilter<T>[];
815
+ enableRowSelection?: boolean;
816
+ bulkActions?: (selected: T[]) => ReactNode;
817
+ emptyState?: ListPageEmptyState;
818
+ labels?: ListPageLabels;
819
+ className?: string;
820
+ }
821
+ /**
822
+ * Declarative list-page template — composes `PageHeader + search input +
823
+ * filter selects + Table + EmptyState` into a single configurable component.
824
+ *
825
+ * **Owns state internally** for search and filter selections — you pass raw
826
+ * `data` and ListPage filters it for you. For server-side data fetching or URL
827
+ * sync, drop down to the underlying primitives directly (see the
828
+ * `RecipeListPage` playground page for the manual composition pattern).
829
+ *
830
+ * @example Basic — Users list
831
+ * ```tsx
832
+ * <ListPage
833
+ * title="Users"
834
+ * description="Manage your team members."
835
+ * actions={<Button onClick={openCreate}>Add user</Button>}
836
+ * data={users}
837
+ * columns={USER_COLUMNS}
838
+ * getRowId={(u) => u.id}
839
+ * searchKeys={['name', 'email']}
840
+ * filters={[
841
+ * {
842
+ * key: 'status',
843
+ * ariaLabel: 'Status',
844
+ * accessor: (u) => u.status,
845
+ * options: [
846
+ * { value: 'all', label: 'All statuses' },
847
+ * { value: 'active', label: 'Active' },
848
+ * { value: 'invited', label: 'Invited' },
849
+ * ],
850
+ * },
851
+ * ]}
852
+ * enableRowSelection
853
+ * bulkActions={(rows) => <Button variant="destructive">Delete ({rows.length})</Button>}
854
+ * />
855
+ * ```
856
+ *
857
+ * @example With localized labels
858
+ * ```tsx
859
+ * <ListPage
860
+ * {...props}
861
+ * labels={{
862
+ * searchPlaceholder: 'ابحث…',
863
+ * reset: 'إعادة الفلاتر',
864
+ * emptyTitle: 'لا توجد نتائج',
865
+ * emptyDescription: 'حاول مسح البحث أو تغيير الفلاتر.',
866
+ * }}
867
+ * />
868
+ * ```
869
+ */
870
+ declare function ListPage<T>({ title, description, bordered, actions, data, columns, getRowId, searchKeys, filters, enableRowSelection, bulkActions, emptyState, labels: labelsProp, className, }: ListPageProps<T>): react_jsx_runtime.JSX.Element;
871
+
872
+ type PageHeaderHeadingLevel = 'h1' | 'h2' | 'h3' | 'h4';
873
+ /** Props passed to the routing-library `render` slot of the back button. */
874
+ interface PageHeaderBackRenderProps {
875
+ href?: string;
876
+ className?: string;
877
+ children: ReactNode;
878
+ onClick?: () => void;
879
+ }
880
+ interface PageHeaderBackProps {
881
+ /** Visible label next to the arrow. Defaults to `"Back"`. */
882
+ label?: ReactNode;
883
+ /** Target href — renders an `<a>`. */
884
+ href?: string;
885
+ /** Click handler — renders a `<button>` (or wraps the `render` element). */
886
+ onClick?: () => void;
887
+ /** Routing-library render prop (e.g. wrap React Router `<Link>`). Wins over `href`. */
888
+ render?: (props: PageHeaderBackRenderProps) => ReactElement;
889
+ }
890
+ interface PageHeaderProps extends Omit<HTMLAttributes<HTMLElement>, 'title'> {
891
+ /** Page title (required). */
892
+ title: ReactNode;
893
+ /** Optional secondary text under the title. */
894
+ description?: ReactNode;
895
+ /** Slot above the title for breadcrumbs (e.g. `<Breadcrumbs items={…} />` or your own JSX). */
896
+ breadcrumbs?: ReactNode;
897
+ /** Optional back button rendered above the title row. */
898
+ back?: PageHeaderBackProps;
899
+ /** Slot on the trailing side of the title row — buttons, dropdowns, etc. */
900
+ actions?: ReactNode;
901
+ /** Heading level for the title element. Defaults to `'h1'`. */
902
+ as?: PageHeaderHeadingLevel;
903
+ /** Add a bottom border separator. Default: `false`. */
904
+ bordered?: boolean;
905
+ }
906
+ /**
907
+ * Top-of-page header — title, optional description, breadcrumbs, back button,
908
+ * and actions slot. The first thing a user sees on any list / detail / form
909
+ * page in a dashboard.
910
+ *
911
+ * Designed to drop directly into `<DashboardContent>` (or any padded page
912
+ * container). Has no outer padding of its own — the surrounding layout owns
913
+ * spacing.
914
+ *
915
+ * @example List page header with primary action
916
+ * ```tsx
917
+ * <PageHeader
918
+ * title="Users"
919
+ * description="Manage your team members and their roles."
920
+ * actions={<Button onClick={openCreate}>Add user</Button>}
921
+ * bordered
922
+ * />
923
+ * ```
924
+ *
925
+ * @example Detail page header with back button
926
+ * ```tsx
927
+ * <PageHeader
928
+ * title={user.name}
929
+ * description={user.email}
930
+ * back={{
931
+ * label: 'Users',
932
+ * render: (props) => <Link to="/users" {...props} />,
933
+ * }}
934
+ * actions={
935
+ * <>
936
+ * <Button variant="outline">Edit</Button>
937
+ * <Button variant="destructive">Delete</Button>
938
+ * </>
939
+ * }
940
+ * />
941
+ * ```
942
+ *
943
+ * @example With breadcrumbs slot
944
+ * ```tsx
945
+ * <PageHeader
946
+ * breadcrumbs={
947
+ * <nav aria-label="Breadcrumb">
948
+ * <ol className="flex items-center gap-1">
949
+ * <li><Link to="/">Home</Link></li>
950
+ * <li>/</li>
951
+ * <li>Users</li>
952
+ * </ol>
953
+ * </nav>
954
+ * }
955
+ * title="Users"
956
+ * />
957
+ * ```
958
+ */
959
+ declare const PageHeader: react.ForwardRefExoticComponent<PageHeaderProps & react.RefAttributes<HTMLElement>>;
960
+
961
+ declare const pageHeaderBaseClass = "flex w-full flex-col gap-3";
962
+ /** Adds a bottom border separator below the header. */
963
+ declare const pageHeaderBorderedClass = "border-b border-border pb-4";
964
+ declare const pageHeaderTitleRowClass = "flex flex-wrap items-start justify-between gap-3 sm:gap-4";
965
+ declare const pageHeaderTitleBlockClass = "min-w-0 flex-1 space-y-1";
966
+ declare const pageHeaderTitleClass = "text-2xl font-semibold tracking-tight text-foreground";
967
+ declare const pageHeaderDescriptionClass = "text-sm text-muted-foreground";
968
+ declare const pageHeaderActionsClass = "flex shrink-0 flex-wrap items-center gap-2";
969
+ declare const pageHeaderBackClass = "inline-flex items-center gap-1.5 self-start text-sm text-muted-foreground transition-colors hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/40 focus-visible:ring-offset-2 focus-visible:ring-offset-background rounded-md";
970
+ declare const pageHeaderBackIconClass = "size-4 shrink-0 rtl:rotate-180";
971
+ declare const pageHeaderBreadcrumbsClass = "text-xs text-muted-foreground";
972
+
973
+ type RadioGroupSize = 'sm' | 'md' | 'lg';
974
+ /** Outer circle (radio button itself) — sized + bordered. */
975
+ declare const radioItemSizeClass: Record<RadioGroupSize, string>;
976
+ /** Inner indicator (the filled dot when selected). Centred via flex on the parent. */
977
+ declare const radioIndicatorSizeClass: Record<RadioGroupSize, string>;
978
+ /** Label text size that pairs naturally with each radio size. */
979
+ declare const radioLabelSizeClass: Record<RadioGroupSize, string>;
980
+ declare const radioItemBaseClass = "aspect-square shrink-0 rounded-full border border-input bg-background text-primary outline-none transition-colors focus-visible:ring-2 focus-visible:ring-ring/40 focus-visible:ring-offset-2 focus-visible:ring-offset-background hover:border-ring disabled:cursor-not-allowed disabled:opacity-50 aria-[invalid=true]:border-destructive aria-[invalid=true]:focus-visible:ring-destructive/40 data-[state=checked]:border-primary";
981
+ declare const radioIndicatorBaseClass = "flex h-full w-full items-center justify-center";
982
+ declare const radioIndicatorDotClass = "rounded-full bg-primary";
983
+ /** Each option row: radio + label + optional description. */
984
+ declare const radioOptionRowClass = "flex cursor-pointer items-start gap-2 has-[button:disabled]:cursor-not-allowed";
985
+ /** The group container — vertical stack by default, horizontal row when orientation="horizontal". */
986
+ declare const radioGroupBaseClass = "flex gap-3";
987
+ declare const radioGroupOrientationClass: {
988
+ readonly vertical: "flex-col";
989
+ readonly horizontal: "flex-row flex-wrap";
990
+ };
991
+
992
+ interface RadioGroupOption {
993
+ value: string;
994
+ /** Visible label rendered next to the radio button. */
995
+ label: ReactNode;
996
+ /** Optional secondary text rendered below the label (e.g. plan description). */
997
+ description?: ReactNode;
998
+ disabled?: boolean;
999
+ }
1000
+ type RadioGroupOrientation = 'vertical' | 'horizontal';
1001
+ interface RadioGroupProps {
1002
+ /** Visual size of each radio + label. */
1003
+ radioSize?: RadioGroupSize;
1004
+ /** Layout direction within the group. `'vertical'` (default) stacks options; `'horizontal'` lays them out in a row. */
1005
+ orientation?: RadioGroupOrientation;
1006
+ /** Controlled selected value (Radix-style). */
1007
+ value?: string;
1008
+ /** Initial selected value for uncontrolled usage. */
1009
+ defaultValue?: string;
1010
+ /** Radix-style change handler — receives the new value directly. */
1011
+ onValueChange?: (value: string) => void;
1012
+ /** Synthetic-event handler for `react-hook-form`'s `field.onChange` and other consumers. */
1013
+ onChange?: (event: ChangeEvent<HTMLInputElement>) => void;
1014
+ /** Called when focus leaves the group. */
1015
+ onBlur?: () => void;
1016
+ /** Form name (for native form submission). */
1017
+ name?: string;
1018
+ /** Disables the entire group. */
1019
+ disabled?: boolean;
1020
+ /** Marks the group as required. */
1021
+ required?: boolean;
1022
+ /** Override id (otherwise auto-generated via useId). */
1023
+ id?: string;
1024
+ /** Declarative options. When `children` is provided it wins (escape hatch for custom content). */
1025
+ options?: RadioGroupOption[];
1026
+ /** Class on the outer group container. */
1027
+ className?: string;
1028
+ 'aria-label'?: string;
1029
+ 'aria-labelledby'?: string;
1030
+ 'aria-describedby'?: string;
1031
+ 'aria-invalid'?: boolean | 'true' | 'false';
1032
+ /** Radix children — used for advanced composition (custom RadioGroupItem layouts). */
1033
+ children?: ReactNode;
1034
+ }
1035
+ /**
1036
+ * Group of mutually-exclusive radio buttons built on `@radix-ui/react-radio-group`.
1037
+ * Use for **3–5 options** where Select would be overkill (pricing tier, privacy
1038
+ * level, single-choice settings). Bare component — wrap in `<Field label="…">`
1039
+ * for the GROUP label, helper, and error rendering.
1040
+ *
1041
+ * Each option carries its own per-radio `label` (and optional `description`).
1042
+ * The Field's outer label names the group; the option labels name each choice.
1043
+ *
1044
+ * @example Inside a Field (RHF + Zod)
1045
+ * ```tsx
1046
+ * <Field name="plan" label="Subscription plan" description="You can change anytime.">
1047
+ * <RadioGroup
1048
+ * options={[
1049
+ * { value: 'free', label: 'Free', description: 'Up to 3 projects' },
1050
+ * { value: 'pro', label: 'Pro', description: 'Unlimited projects' },
1051
+ * { value: 'enterprise', label: 'Enterprise', description: 'Custom limits' },
1052
+ * ]}
1053
+ * />
1054
+ * </Field>
1055
+ * ```
1056
+ *
1057
+ * @example Horizontal row in a settings card
1058
+ * ```tsx
1059
+ * <Field label="Visibility" orientation="horizontal">
1060
+ * <RadioGroup
1061
+ * orientation="horizontal"
1062
+ * value={visibility}
1063
+ * onValueChange={setVisibility}
1064
+ * options={[
1065
+ * { value: 'public', label: 'Public' },
1066
+ * { value: 'private', label: 'Private' },
1067
+ * ]}
1068
+ * />
1069
+ * </Field>
1070
+ * ```
1071
+ */
1072
+ declare const RadioGroup: react.ForwardRefExoticComponent<RadioGroupProps & react.RefAttributes<HTMLDivElement>>;
1073
+ /**
1074
+ * `<RadioGroupItem>` — re-exported for consumers building custom option layouts
1075
+ * (icons, badges, etc.) via the `children` escape hatch.
1076
+ *
1077
+ * @example
1078
+ * ```tsx
1079
+ * <RadioGroup value={plan} onValueChange={setPlan}>
1080
+ * {plans.map((p) => (
1081
+ * <label key={p.value} htmlFor={p.value} className="flex items-center gap-2">
1082
+ * <RadioGroupItem id={p.value} value={p.value} />
1083
+ * <PlanCard {...p} />
1084
+ * </label>
1085
+ * ))}
1086
+ * </RadioGroup>
1087
+ * ```
1088
+ */
1089
+ declare const RadioGroupItem: react.ForwardRefExoticComponent<Omit<RadixRadioGroup.RadioGroupItemProps & react.RefAttributes<HTMLButtonElement>, "ref"> & {
1090
+ radioSize?: RadioGroupSize;
1091
+ } & react.RefAttributes<HTMLButtonElement>>;
1092
+
1093
+ type SidebarProps = HTMLAttributes<HTMLElement>;
1094
+ declare function Sidebar({ className, children, ...props }: SidebarProps): react_jsx_runtime.JSX.Element;
1095
+
1096
+ type SidebarFooterProps = HTMLAttributes<HTMLDivElement>;
1097
+ declare function SidebarFooter({ className, children, ...props }: SidebarFooterProps): react_jsx_runtime.JSX.Element;
1098
+
1099
+ interface SidebarGroupProps extends HTMLAttributes<HTMLDivElement> {
1100
+ label?: ReactNode;
1101
+ }
1102
+ declare function SidebarGroup({ label, className, children, ...props }: SidebarGroupProps): react_jsx_runtime.JSX.Element;
1103
+
1104
+ type SidebarHeaderProps = HTMLAttributes<HTMLDivElement>;
1105
+ declare function SidebarHeader({ className, children, ...props }: SidebarHeaderProps): react_jsx_runtime.JSX.Element;
1106
+
1107
+ type SidebarNavProps = HTMLAttributes<HTMLElement>;
1108
+ declare function SidebarNav({ className, children, ...props }: SidebarNavProps): react_jsx_runtime.JSX.Element;
1109
+
1110
+ interface SidebarNavGroupProps extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'children'> {
1111
+ icon?: ReactNode;
1112
+ label?: ReactNode;
1113
+ endSlot?: ReactNode;
1114
+ /** Highlight the parent (e.g. when one of its children is active). */
1115
+ active?: boolean;
1116
+ /** Uncontrolled initial state. */
1117
+ defaultOpen?: boolean;
1118
+ /** Controlled open state. */
1119
+ open?: boolean;
1120
+ onOpenChange?: (open: boolean) => void;
1121
+ children: ReactNode;
1122
+ }
1123
+ declare function SidebarNavGroup({ icon, label, endSlot, active, defaultOpen, open: openProp, onOpenChange, className, children, onClick, ...props }: SidebarNavGroupProps): react_jsx_runtime.JSX.Element;
1124
+
1125
+ type SidebarNavItemRenderProps = {
1126
+ className: string;
1127
+ children: ReactNode;
1128
+ title?: string;
1129
+ 'aria-current'?: 'page';
1130
+ 'data-active'?: 'true';
1131
+ };
1132
+ interface SidebarNavItemProps extends AnchorHTMLAttributes<HTMLAnchorElement> {
1133
+ icon?: ReactNode;
1134
+ active?: boolean;
1135
+ label?: ReactNode;
1136
+ endSlot?: ReactNode;
1137
+ /**
1138
+ * Override the rendered element. Use this to plug in routing-library link
1139
+ * components (e.g. react-router `<Link>`) while keeping the styling.
1140
+ */
1141
+ render?: (props: SidebarNavItemRenderProps) => ReactElement;
1142
+ }
1143
+ declare function SidebarNavItem({ icon, active, label, endSlot, className, children, render, ...props }: SidebarNavItemProps): react_jsx_runtime.JSX.Element;
1144
+
1145
+ type SwitchSize = 'sm' | 'md' | 'lg';
1146
+ /**
1147
+ * Each size is a tuple: track dimensions + thumb size + thumb travel distance.
1148
+ * Track is `w` x `h`; thumb is `w/h size-X`; travel is the translation distance
1149
+ * when checked (= track width − thumb size − padding).
1150
+ */
1151
+ declare const switchTrackClass: Record<SwitchSize, string>;
1152
+ declare const switchThumbClass: Record<SwitchSize, string>;
1153
+ declare const switchTrackBaseClass = "relative inline-flex shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent bg-input transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/40 focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary aria-[invalid=true]:ring-2 aria-[invalid=true]:ring-destructive/40";
1154
+ declare const switchThumbBaseClass = "pointer-events-none block rounded-full bg-background shadow-sm ring-0 transition-transform";
1155
+
1156
+ interface SwitchProps {
1157
+ /** Visual size. */
1158
+ switchSize?: SwitchSize;
1159
+ /** Controlled checked state (Radix-style). */
1160
+ checked?: boolean;
1161
+ /** Initial checked state for uncontrolled usage. */
1162
+ defaultChecked?: boolean;
1163
+ /** Radix-style change handler — receives the new boolean directly. */
1164
+ onCheckedChange?: (checked: boolean) => void;
1165
+ /**
1166
+ * Form-library compatibility props. `value` mirrors what `<Field>` injects
1167
+ * (RHF passes `field.value` as a boolean). `onChange` fires alongside
1168
+ * `onCheckedChange` with a synthetic event so `field.onChange` works too.
1169
+ */
1170
+ value?: boolean | string | number;
1171
+ onChange?: (event: ChangeEvent<HTMLButtonElement>) => void;
1172
+ onBlur?: () => void;
1173
+ /** Form name for native form submission. */
1174
+ name?: string;
1175
+ /** Disable interaction. */
1176
+ disabled?: boolean;
1177
+ /** Mark required for form validation. */
1178
+ required?: boolean;
1179
+ /** Override id (otherwise auto-generated via useId). */
1180
+ id?: string;
1181
+ /** Class on the track (the switch itself). */
1182
+ className?: string;
1183
+ 'aria-label'?: string;
1184
+ 'aria-describedby'?: string;
1185
+ 'aria-invalid'?: boolean | 'true' | 'false';
1186
+ }
1187
+ /**
1188
+ * Boolean toggle built on `@radix-ui/react-switch`. Renders only the track +
1189
+ * thumb — wrap it in `<Field orientation="horizontal" label="…">` to add a
1190
+ * label, helper text, error, and aria wiring without duplicating that logic
1191
+ * inside every form control.
1192
+ *
1193
+ * @example Inside a Field (RHF + Zod)
1194
+ * ```tsx
1195
+ * <Field name="darkMode" label="Dark mode" orientation="horizontal">
1196
+ * <Switch />
1197
+ * </Field>
1198
+ * ```
1199
+ *
1200
+ * @example Bare in a settings list (custom layout)
1201
+ * ```tsx
1202
+ * <ul className="divide-y divide-border">
1203
+ * <li className="flex items-center justify-between py-3">
1204
+ * <span>Email digest</span>
1205
+ * <Switch checked={digest} onCheckedChange={setDigest} aria-label="Email digest" />
1206
+ * </li>
1207
+ * </ul>
1208
+ * ```
1209
+ *
1210
+ * @example Standalone controlled
1211
+ * ```tsx
1212
+ * <Switch
1213
+ * checked={enabled}
1214
+ * onCheckedChange={setEnabled}
1215
+ * aria-label="Enable notifications"
1216
+ * />
1217
+ * ```
1218
+ */
1219
+ declare const Switch: react.ForwardRefExoticComponent<SwitchProps & react.RefAttributes<HTMLButtonElement>>;
1220
+
828
1221
  type TextareaVariant = 'default' | 'filled' | 'ghost';
829
1222
  type TextareaSize = 'sm' | 'md' | 'lg';
830
1223
  type TextareaResize = 'none' | 'vertical' | 'horizontal' | 'both';
@@ -868,4 +1261,4 @@ declare function useDirection(): Direction;
868
1261
 
869
1262
  declare function cn(...inputs: ClassValue[]): string;
870
1263
 
871
- export { AppShell, type AppShellBrand, type AppShellNavGroup, type AppShellNavItem, type AppShellProps, Avatar, type AvatarProps, Button, type ButtonProps, type ButtonSize, type ButtonVariant, Checkbox, type CheckboxProps, type CheckboxSize, type Column, type ColumnAlign, DashboardContent, type DashboardContentProps, DashboardHeader, type DashboardHeaderProps, DashboardLayout, type DashboardLayoutContextValue, type DashboardLayoutProps, DashboardMain, type DashboardMainProps, type Direction, Field, type FieldOrientation, type FieldProps, type FieldRHFProps, HeaderActions, type HeaderActionsProps, HeaderCollapseTrigger, type HeaderCollapseTriggerProps, HeaderMobileTrigger, type HeaderMobileTriggerProps, HeaderSearch, type HeaderSearchProps, HeaderTitle, type HeaderTitleProps, Input, type InputProps, type InputSize, type InputVariant, type LanguageOption, LanguageSwitcher, type LanguageSwitcherProps, type PaginationState, RadioGroup, RadioGroupItem, type RadioGroupOption, type RadioGroupOrientation, type RadioGroupProps, type RadioGroupSize, type RowSelectionState, Select, type SelectOption, type SelectProps, type SelectSize, type SelectVariant, Sidebar, SidebarFooter, type SidebarFooterProps, SidebarGroup, type SidebarGroupProps, SidebarHeader, type SidebarHeaderProps, SidebarNav, SidebarNavGroup, type SidebarNavGroupProps, SidebarNavItem, type SidebarNavItemProps, type SidebarNavItemRenderProps, type SidebarNavProps, type SidebarProps, type SortDirection, type SortState, type SortableValue, Switch, type SwitchProps, type SwitchSize, Table, type TableProps, type TableSize, type TableSizeClasses, Textarea, type TextareaProps, type TextareaResize, type TextareaSize, type TextareaVariant, buttonBaseClass, buttonSizeClass, buttonVariantClass, cn, inputBaseClass, inputSizeClass, inputVariantClass, radioGroupBaseClass, radioGroupOrientationClass, radioIndicatorBaseClass, radioIndicatorDotClass, radioIndicatorSizeClass, radioItemBaseClass, radioItemSizeClass, radioLabelSizeClass, radioOptionRowClass, selectBaseClass, selectSizeClass, selectVariantClass, switchThumbBaseClass, switchThumbClass, switchTrackBaseClass, switchTrackClass, alignClass as tableAlignClass, tableBaseClass, selectedRowClass as tableSelectedRowClass, tableSizeClass, sortIconClass as tableSortIconClass, textareaBaseClass, textareaResizeClass, textareaSizeClass, textareaVariantClass, useDashboardLayout, useDirection };
1264
+ export { AppShell, type AppShellBrand, type AppShellNavGroup, type AppShellNavItem, type AppShellProps, Avatar, type AvatarProps, Badge, type BadgeProps, type BadgeSize, type BadgeVariant, Button, type ButtonProps, type ButtonSize, type ButtonVariant, Checkbox, type CheckboxProps, type CheckboxSize, type Column, type ColumnAlign, DashboardContent, type DashboardContentProps, DashboardHeader, type DashboardHeaderProps, DashboardLayout, type DashboardLayoutContextValue, type DashboardLayoutProps, DashboardMain, type DashboardMainProps, type Direction, DropdownMenu, DropdownMenuContent, type DropdownMenuContentProps, DropdownMenuGroup, DropdownMenuItem, type DropdownMenuItemProps, type DropdownMenuItemVariant, DropdownMenuLabel, type DropdownMenuLabelProps, DropdownMenuPortal, DropdownMenuSeparator, type DropdownMenuSeparatorProps, DropdownMenuShortcut, type DropdownMenuShortcutProps, DropdownMenuTrigger, EmptyState, type EmptyStateProps, type EmptyStateSize, Field, type FieldOrientation, type FieldProps, type FieldRHFProps, HeaderActions, type HeaderActionsProps, HeaderCollapseTrigger, type HeaderCollapseTriggerProps, HeaderMobileTrigger, type HeaderMobileTriggerProps, HeaderSearch, type HeaderSearchProps, HeaderTitle, type HeaderTitleProps, Input, type InputProps, type InputSize, type InputVariant, type LanguageOption, LanguageSwitcher, type LanguageSwitcherProps, ListPage, type ListPageEmptyState, type ListPageFilter, type ListPageLabels, type ListPageProps, PageHeader, type PageHeaderBackProps, type PageHeaderBackRenderProps, type PageHeaderHeadingLevel, type PageHeaderProps, type PaginationState, RadioGroup, RadioGroupItem, type RadioGroupOption, type RadioGroupOrientation, type RadioGroupProps, type RadioGroupSize, type RowSelectionState, Select, type SelectOption, type SelectProps, type SelectSize, type SelectVariant, Sidebar, SidebarFooter, type SidebarFooterProps, SidebarGroup, type SidebarGroupProps, SidebarHeader, type SidebarHeaderProps, SidebarNav, SidebarNavGroup, type SidebarNavGroupProps, SidebarNavItem, type SidebarNavItemProps, type SidebarNavItemRenderProps, type SidebarNavProps, type SidebarProps, type SortDirection, type SortState, type SortableValue, Switch, type SwitchProps, type SwitchSize, Table, type TableProps, type TableSize, type TableSizeClasses, Textarea, type TextareaProps, type TextareaResize, type TextareaSize, type TextareaVariant, badgeBaseClass, badgeDotSizeClass, badgeSizeClass, badgeVariantClass, buttonBaseClass, buttonSizeClass, buttonVariantClass, cn, dropdownMenuContentClass, dropdownMenuItemBaseClass, dropdownMenuItemInsetClass, dropdownMenuItemVariantClass, dropdownMenuLabelClass, dropdownMenuSeparatorClass, dropdownMenuShortcutClass, emptyStateActionsSpacingClass, emptyStateBaseClass, emptyStateContainerSizeClass, emptyStateDescriptionSizeClass, emptyStateIconWrapperBaseClass, emptyStateIconWrapperSizeClass, emptyStateTitleSizeClass, inputBaseClass, inputSizeClass, inputVariantClass, pageHeaderActionsClass, pageHeaderBackClass, pageHeaderBackIconClass, pageHeaderBaseClass, pageHeaderBorderedClass, pageHeaderBreadcrumbsClass, pageHeaderDescriptionClass, pageHeaderTitleBlockClass, pageHeaderTitleClass, pageHeaderTitleRowClass, radioGroupBaseClass, radioGroupOrientationClass, radioIndicatorBaseClass, radioIndicatorDotClass, radioIndicatorSizeClass, radioItemBaseClass, radioItemSizeClass, radioLabelSizeClass, radioOptionRowClass, selectBaseClass, selectSizeClass, selectVariantClass, switchThumbBaseClass, switchThumbClass, switchTrackBaseClass, switchTrackClass, alignClass as tableAlignClass, tableBaseClass, selectedRowClass as tableSelectedRowClass, tableSizeClass, sortIconClass as tableSortIconClass, textareaBaseClass, textareaResizeClass, textareaSizeClass, textareaVariantClass, useDashboardLayout, useDirection };