@khanhminh/design-system 1.10.8 → 1.12.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.
Files changed (44) hide show
  1. package/dist/components/base/Badge/Badge.d.ts +3 -0
  2. package/dist/components/base/Badge/Badge.types.d.ts +2 -0
  3. package/dist/components/base/Badge/index.d.ts +2 -0
  4. package/dist/components/base/Button/Button.d.ts +2 -0
  5. package/dist/components/base/Button/Button.types.d.ts +3 -0
  6. package/dist/components/base/Button/index.d.ts +2 -0
  7. package/dist/components/base/Checkbox/Checkbox.d.ts +2 -0
  8. package/dist/components/base/Checkbox/Checkbox.types.d.ts +3 -0
  9. package/dist/components/base/Checkbox/index.d.ts +2 -0
  10. package/dist/components/base/Input/Input.d.ts +2 -0
  11. package/dist/components/base/Input/Input.types.d.ts +3 -0
  12. package/dist/components/base/Input/index.d.ts +2 -0
  13. package/dist/components/base/Label/Label.d.ts +2 -0
  14. package/dist/components/base/Label/Label.types.d.ts +3 -0
  15. package/dist/components/base/Label/index.d.ts +2 -0
  16. package/dist/components/base/ScrollArea/ScrollArea.d.ts +3 -0
  17. package/dist/components/base/ScrollArea/ScrollArea.type.d.ts +5 -0
  18. package/dist/components/base/ScrollArea/index.d.ts +2 -0
  19. package/dist/components/base/Separator/Separator.d.ts +2 -0
  20. package/dist/components/base/Separator/Separator.types.d.ts +3 -0
  21. package/dist/components/base/Separator/index.d.ts +2 -0
  22. package/dist/components/base/Spinner/Spinner.d.ts +2 -0
  23. package/dist/components/base/Spinner/Spinner.types.d.ts +3 -0
  24. package/dist/components/base/Spinner/index.d.ts +2 -0
  25. package/dist/components/base/Switch/Switch.d.ts +3 -0
  26. package/dist/components/base/Switch/Switch.types.d.ts +5 -0
  27. package/dist/components/base/Switch/index.d.ts +2 -0
  28. package/dist/components/index.d.ts +8 -6
  29. package/dist/components/ui/badge.d.ts +9 -0
  30. package/dist/components/ui/scroll-area.d.ts +5 -0
  31. package/dist/components/ui/switch.d.ts +6 -0
  32. package/dist/index.cjs +136 -16
  33. package/dist/index.css +1 -1
  34. package/dist/index.d.ts +2 -0
  35. package/dist/index.js +133 -17
  36. package/dist/lib/index.d.ts +1 -0
  37. package/dist/lib/theme.d.ts +1 -0
  38. package/dist/providers/index.d.ts +1 -0
  39. package/dist/providers/theme-provider.d.ts +3 -0
  40. package/dist/store/index.d.ts +1 -0
  41. package/dist/store/theme-store.d.ts +7 -0
  42. package/dist/test/setup.d.ts +1 -0
  43. package/dist/types/index.d.ts +1 -0
  44. package/package.json +17 -5
@@ -0,0 +1,3 @@
1
+ import { PropsWithChildren } from 'react';
2
+ import { BadgeProps } from './Badge.types';
3
+ export declare const Badge: ({ children, ...props }: PropsWithChildren<BadgeProps>) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,2 @@
1
+ import { Badge as ShadBadge } from '../../ui/badge';
2
+ export type BadgeProps = React.ComponentProps<typeof ShadBadge>;
@@ -0,0 +1,2 @@
1
+ export { Badge } from './Badge';
2
+ export type { BadgeProps } from './Badge.types';
@@ -0,0 +1,2 @@
1
+ import type { ButtonProps } from './Button.types';
2
+ export declare const Button: (props: ButtonProps) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,3 @@
1
+ import type * as React from 'react';
2
+ import { Button as ShadButton } from '@/components/ui/button';
3
+ export type ButtonProps = React.ComponentProps<typeof ShadButton>;
@@ -0,0 +1,2 @@
1
+ export { Button } from './Button';
2
+ export type { ButtonProps } from './Button.types';
@@ -0,0 +1,2 @@
1
+ import type { CheckboxProps } from './Checkbox.types';
2
+ export declare const Checkbox: (props: CheckboxProps) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,3 @@
1
+ import type * as React from 'react';
2
+ import { Checkbox as ShadCheckbox } from '@/components/ui/checkbox';
3
+ export type CheckboxProps = React.ComponentProps<typeof ShadCheckbox>;
@@ -0,0 +1,2 @@
1
+ export { Checkbox } from './Checkbox';
2
+ export type { CheckboxProps } from './Checkbox.types';
@@ -0,0 +1,2 @@
1
+ import type { InputProps } from './Input.types';
2
+ export declare const Input: (props: InputProps) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,3 @@
1
+ import type * as React from 'react';
2
+ import { Input as ShadInput } from '@/components/ui/input';
3
+ export type InputProps = React.ComponentProps<typeof ShadInput>;
@@ -0,0 +1,2 @@
1
+ export { Input } from './Input';
2
+ export type { InputProps } from './Input.types';
@@ -0,0 +1,2 @@
1
+ import type { LabelProps } from './Label.types';
2
+ export declare const Label: (props: LabelProps) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,3 @@
1
+ import type * as React from 'react';
2
+ import { Label as ShadLabel } from '@/components/ui/label';
3
+ export type LabelProps = React.ComponentProps<typeof ShadLabel>;
@@ -0,0 +1,2 @@
1
+ export { Label } from './Label';
2
+ export type { LabelProps } from './Label.types';
@@ -0,0 +1,3 @@
1
+ import { ScrollAreaProps } from './ScrollArea.type';
2
+ declare const ScrollArea: ({ children, orientation, className, ...props }: ScrollAreaProps) => import("react/jsx-runtime").JSX.Element;
3
+ export default ScrollArea;
@@ -0,0 +1,5 @@
1
+ import { ScrollArea as ShadScrollArea } from '../../ui/scroll-area';
2
+ export type ScrollAreaProps = React.ComponentProps<typeof ShadScrollArea> & {
3
+ orientation?: 'horizontal' | 'vertical';
4
+ className?: string;
5
+ };
@@ -0,0 +1,2 @@
1
+ export { default as ScrollArea } from './ScrollArea';
2
+ export { type ScrollAreaProps } from './ScrollArea.type';
@@ -0,0 +1,2 @@
1
+ import type { SeparatorProps } from './Separator.types';
2
+ export declare const Separator: (props: SeparatorProps) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,3 @@
1
+ import type * as React from 'react';
2
+ import { Separator as ShadSeparator } from '@/components/ui/separator';
3
+ export type SeparatorProps = React.ComponentProps<typeof ShadSeparator>;
@@ -0,0 +1,2 @@
1
+ export { Separator } from './Separator';
2
+ export type { SeparatorProps } from './Separator.types';
@@ -0,0 +1,2 @@
1
+ import type { SpinnerProps } from './Spinner.types';
2
+ export declare const Spinner: (props: SpinnerProps) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,3 @@
1
+ import type * as React from 'react';
2
+ import { Spinner as ShadSpinner } from '@/components/ui/spinner';
3
+ export type SpinnerProps = React.ComponentProps<typeof ShadSpinner>;
@@ -0,0 +1,2 @@
1
+ export { Spinner } from './Spinner';
2
+ export type { SpinnerProps } from './Spinner.types';
@@ -0,0 +1,3 @@
1
+ import { SwitchProps } from './Switch.types';
2
+ declare const Switch: ({ id, label, ...props }: SwitchProps) => JSX.Element;
3
+ export default Switch;
@@ -0,0 +1,5 @@
1
+ import { Switch as ShadSwitch } from '../../ui/switch';
2
+ export type SwitchProps = {
3
+ id: string;
4
+ label: string;
5
+ } & React.ComponentProps<typeof ShadSwitch>;
@@ -0,0 +1,2 @@
1
+ export { default as Switch } from './Switch';
2
+ export type { SwitchProps } from './Switch.types';
@@ -1,6 +1,8 @@
1
- export { Button } from './ui/button';
2
- export { Input } from './ui/input';
3
- export { Spinner } from './ui/spinner';
4
- export { Checkbox } from './ui/checkbox';
5
- export { Label } from './ui/label';
6
- export { Separator } from './ui/separator';
1
+ export { Button, type ButtonProps } from './base/Button';
2
+ export { Input, type InputProps } from './base/Input';
3
+ export { Spinner, type SpinnerProps } from './base/Spinner';
4
+ export { Checkbox, type CheckboxProps } from './base/Checkbox';
5
+ export { Label, type LabelProps } from './base/Label';
6
+ export { Separator, type SeparatorProps } from './base/Separator';
7
+ export { Switch, type SwitchProps } from './base/Switch';
8
+ export { ScrollArea, type ScrollAreaProps } from './base/ScrollArea';
@@ -0,0 +1,9 @@
1
+ import * as React from 'react';
2
+ import { type VariantProps } from 'class-variance-authority';
3
+ declare const badgeVariants: (props?: ({
4
+ variant?: "default" | "destructive" | "outline" | "secondary" | "ghost" | "link" | null | undefined;
5
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
6
+ declare function Badge({ className, variant, asChild, ...props }: React.ComponentProps<'span'> & VariantProps<typeof badgeVariants> & {
7
+ asChild?: boolean;
8
+ }): import("react/jsx-runtime").JSX.Element;
9
+ export { Badge, badgeVariants };
@@ -0,0 +1,5 @@
1
+ import * as React from 'react';
2
+ import { ScrollArea as ScrollAreaPrimitive } from 'radix-ui';
3
+ declare function ScrollArea({ className, children, ...props }: React.ComponentProps<typeof ScrollAreaPrimitive.Root>): import("react/jsx-runtime").JSX.Element;
4
+ declare function ScrollBar({ className, orientation, ...props }: React.ComponentProps<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>): import("react/jsx-runtime").JSX.Element;
5
+ export { ScrollArea, ScrollBar };
@@ -0,0 +1,6 @@
1
+ import * as React from 'react';
2
+ import { Switch as SwitchPrimitive } from 'radix-ui';
3
+ declare function Switch({ className, size, ...props }: React.ComponentProps<typeof SwitchPrimitive.Root> & {
4
+ size?: 'sm' | 'default';
5
+ }): import("react/jsx-runtime").JSX.Element;
6
+ export { Switch };
package/dist/index.cjs CHANGED
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var require$$0 = require('react');
3
+ var React = require('react');
4
4
  var classVarianceAuthority = require('class-variance-authority');
5
5
  var radixUi = require('radix-ui');
6
6
  var clsx = require('clsx');
@@ -343,7 +343,7 @@ function requireReactJsxRuntime_development () {
343
343
  object.$$typeof === REACT_ELEMENT_TYPE
344
344
  );
345
345
  }
346
- var React = require$$0,
346
+ var React$1 = React,
347
347
  REACT_ELEMENT_TYPE = Symbol.for("react.transitional.element"),
348
348
  REACT_PORTAL_TYPE = Symbol.for("react.portal"),
349
349
  REACT_FRAGMENT_TYPE = Symbol.for("react.fragment"),
@@ -359,7 +359,7 @@ function requireReactJsxRuntime_development () {
359
359
  REACT_ACTIVITY_TYPE = Symbol.for("react.activity"),
360
360
  REACT_CLIENT_REFERENCE = Symbol.for("react.client.reference"),
361
361
  ReactSharedInternals =
362
- React.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,
362
+ React$1.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,
363
363
  hasOwnProperty = Object.prototype.hasOwnProperty,
364
364
  isArrayImpl = Array.isArray,
365
365
  createTask = console.createTask
@@ -367,15 +367,15 @@ function requireReactJsxRuntime_development () {
367
367
  : function () {
368
368
  return null;
369
369
  };
370
- React = {
370
+ React$1 = {
371
371
  react_stack_bottom_frame: function (callStackForError) {
372
372
  return callStackForError();
373
373
  }
374
374
  };
375
375
  var specialPropKeyWarningShown;
376
376
  var didWarnAboutElementRef = {};
377
- var unknownOwnerDebugStack = React.react_stack_bottom_frame.bind(
378
- React,
377
+ var unknownOwnerDebugStack = React$1.react_stack_bottom_frame.bind(
378
+ React$1,
379
379
  UnknownOwner
380
380
  )();
381
381
  var unknownOwnerDebugTask = createTask(getTaskName(UnknownOwner));
@@ -451,31 +451,74 @@ const buttonVariants = classVarianceAuthority.cva("inline-flex shrink-0 items-ce
451
451
  size: 'default',
452
452
  },
453
453
  });
454
- function Button({ className, variant = 'default', size = 'default', asChild = false, ...props }) {
454
+ function Button$1({ className, variant = 'default', size = 'default', asChild = false, ...props }) {
455
455
  const Comp = asChild ? radixUi.Slot.Root : 'button';
456
456
  return (jsxRuntimeExports.jsx(Comp, { className: cn(buttonVariants({ variant, size, className })), "data-size": size, "data-slot": "button", "data-variant": variant, ...props }));
457
457
  }
458
458
 
459
- function Input({ className, type, ...props }) {
459
+ const Button = (props) => {
460
+ return jsxRuntimeExports.jsx(Button$1, { ...props });
461
+ };
462
+
463
+ function Input$1({ className, type, ...props }) {
460
464
  return (jsxRuntimeExports.jsx("input", { className: cn('border-input selection:bg-primary selection:text-primary-foreground file:text-foreground placeholder:text-muted-foreground dark:bg-input/30 h-9 w-full min-w-0 rounded-md border bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm', 'focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]', 'aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40', className), "data-slot": "input", type: type, ...props }));
461
465
  }
462
466
 
463
- function Spinner({ className, ...props }) {
467
+ const Input = (props) => {
468
+ return jsxRuntimeExports.jsx(Input$1, { ...props });
469
+ };
470
+
471
+ function Spinner$1({ className, ...props }) {
464
472
  return jsxRuntimeExports.jsx(lucideReact.Loader2Icon, { "aria-label": "Loading", className: cn('size-4 animate-spin', className), role: "status", ...props });
465
473
  }
466
474
 
467
- function Checkbox({ className, ...props }) {
475
+ const Spinner = (props) => {
476
+ return jsxRuntimeExports.jsx(Spinner$1, { ...props });
477
+ };
478
+
479
+ function Checkbox$1({ className, ...props }) {
468
480
  return (jsxRuntimeExports.jsx(radixUi.Checkbox.Root, { className: cn('peer border-input focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 data-[state=checked]:border-primary data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground dark:bg-input/30 dark:aria-invalid:ring-destructive/40 dark:data-[state=checked]:bg-primary size-4 shrink-0 rounded-[4px] border shadow-xs transition-shadow outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50', className), "data-slot": "checkbox", ...props, children: jsxRuntimeExports.jsx(radixUi.Checkbox.Indicator, { className: "grid place-content-center text-current transition-none", "data-slot": "checkbox-indicator", children: jsxRuntimeExports.jsx(lucideReact.CheckIcon, { className: "size-3.5" }) }) }));
469
481
  }
470
482
 
471
- function Label({ className, ...props }) {
483
+ const Checkbox = (props) => {
484
+ return jsxRuntimeExports.jsx(Checkbox$1, { ...props });
485
+ };
486
+
487
+ function Label$1({ className, ...props }) {
472
488
  return (jsxRuntimeExports.jsx(radixUi.Label.Root, { className: cn('flex items-center gap-2 text-sm leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50', className), "data-slot": "label", ...props }));
473
489
  }
474
490
 
475
- function Separator({ className, orientation = 'horizontal', decorative = true, ...props }) {
491
+ const Label = (props) => {
492
+ return jsxRuntimeExports.jsx(Label$1, { ...props });
493
+ };
494
+
495
+ function Separator$1({ className, orientation = 'horizontal', decorative = true, ...props }) {
476
496
  return (jsxRuntimeExports.jsx(radixUi.Separator.Root, { className: cn('bg-border shrink-0 data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-px', className), "data-slot": "separator", decorative: decorative, orientation: orientation, ...props }));
477
497
  }
478
498
 
499
+ const Separator = (props) => {
500
+ return jsxRuntimeExports.jsx(Separator$1, { ...props });
501
+ };
502
+
503
+ function Switch$1({ className, size = 'default', ...props }) {
504
+ return (jsxRuntimeExports.jsx(radixUi.Switch.Root, { className: cn('peer group/switch focus-visible:border-ring focus-visible:ring-ring/50 data-[state=checked]:bg-primary data-[state=unchecked]:bg-input dark:data-[state=unchecked]:bg-input/80 inline-flex shrink-0 items-center rounded-full border border-transparent shadow-xs transition-all outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 data-[size=default]:h-[1.15rem] data-[size=default]:w-8 data-[size=sm]:h-3.5 data-[size=sm]:w-6', className), "data-size": size, "data-slot": "switch", ...props, children: jsxRuntimeExports.jsx(radixUi.Switch.Thumb, { className: cn('bg-background dark:data-[state=checked]:bg-primary-foreground dark:data-[state=unchecked]:bg-foreground pointer-events-none block rounded-full ring-0 transition-transform group-data-[size=default]/switch:size-4 group-data-[size=sm]/switch:size-3 data-[state=checked]:translate-x-[calc(100%-2px)] data-[state=unchecked]:translate-x-0'), "data-slot": "switch-thumb" }) }));
505
+ }
506
+
507
+ const Switch = ({ id, label, ...props }) => {
508
+ return (jsxRuntimeExports.jsxs("div", { className: "flex items-center space-x-2", children: [jsxRuntimeExports.jsx(Switch$1, { "data-slot": "switch", id: id, ...props }), jsxRuntimeExports.jsx(Label, { "data-slot": "label", htmlFor: id, children: label })] }));
509
+ };
510
+
511
+ function ScrollArea$1({ className, children, ...props }) {
512
+ return (jsxRuntimeExports.jsxs(radixUi.ScrollArea.Root, { className: cn('relative', className), "data-slot": "scroll-area", ...props, children: [jsxRuntimeExports.jsx(radixUi.ScrollArea.Viewport, { className: "focus-visible:ring-ring/50 size-full rounded-[inherit] transition-[color,box-shadow] outline-none focus-visible:ring-[3px] focus-visible:outline-1", "data-slot": "scroll-area-viewport", children: children }), jsxRuntimeExports.jsx(ScrollBar, {}), jsxRuntimeExports.jsx(radixUi.ScrollArea.Corner, {})] }));
513
+ }
514
+ function ScrollBar({ className, orientation = 'vertical', ...props }) {
515
+ return (jsxRuntimeExports.jsx(radixUi.ScrollArea.ScrollAreaScrollbar, { className: cn('flex touch-none p-px transition-colors select-none', orientation === 'vertical' && 'h-full w-2.5 border-l border-l-transparent', orientation === 'horizontal' && 'h-2.5 flex-col border-t border-t-transparent', className), "data-slot": "scroll-area-scrollbar", orientation: orientation, ...props, children: jsxRuntimeExports.jsx(radixUi.ScrollArea.ScrollAreaThumb, { className: "bg-border relative flex-1 rounded-full", "data-slot": "scroll-area-thumb" }) }));
516
+ }
517
+
518
+ const ScrollArea = ({ children, orientation = 'horizontal', className, ...props }) => {
519
+ return (jsxRuntimeExports.jsxs(ScrollArea$1, { className: className, "data-slot": "scroll-area", ...props, children: [jsxRuntimeExports.jsx("div", { "data-slot": "scroll-area-viewport", children: children }), jsxRuntimeExports.jsx("div", { "data-slot": "scroll-area-scrollbar", children: jsxRuntimeExports.jsx(ScrollBar, { orientation: orientation }) })] }));
520
+ };
521
+
479
522
  /**
480
523
  * A simple boolean toggle hook.
481
524
  *
@@ -483,18 +526,95 @@ function Separator({ className, orientation = 'horizontal', decorative = true, .
483
526
  * @returns an object with the current state and helpers to toggle / set on / set off
484
527
  */
485
528
  function useToggle(initial = false) {
486
- const [state, setState] = require$$0.useState(initial);
487
- const toggle = require$$0.useCallback(() => setState((s) => !s), []);
488
- const setOn = require$$0.useCallback(() => setState(true), []);
489
- const setOff = require$$0.useCallback(() => setState(false), []);
529
+ const [state, setState] = React.useState(initial);
530
+ const toggle = React.useCallback(() => setState((s) => !s), []);
531
+ const setOn = React.useCallback(() => setState(true), []);
532
+ const setOff = React.useCallback(() => setState(false), []);
490
533
  return { state, toggle, setOn, setOff };
491
534
  }
492
535
 
536
+ const applyTheme = (theme) => {
537
+ const root = window.document.documentElement;
538
+ const systemDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
539
+ const resolvedTheme = theme === 'system' ? (systemDark ? 'dark' : 'light') : theme;
540
+ root.classList.remove('light', 'dark');
541
+ root.classList.add(resolvedTheme);
542
+ };
543
+
544
+ const createStoreImpl = (createState) => {
545
+ let state;
546
+ const listeners = /* @__PURE__ */ new Set();
547
+ const setState = (partial, replace) => {
548
+ const nextState = typeof partial === "function" ? partial(state) : partial;
549
+ if (!Object.is(nextState, state)) {
550
+ const previousState = state;
551
+ state = (replace != null ? replace : typeof nextState !== "object" || nextState === null) ? nextState : Object.assign({}, state, nextState);
552
+ listeners.forEach((listener) => listener(state, previousState));
553
+ }
554
+ };
555
+ const getState = () => state;
556
+ const getInitialState = () => initialState;
557
+ const subscribe = (listener) => {
558
+ listeners.add(listener);
559
+ return () => listeners.delete(listener);
560
+ };
561
+ const api = { setState, getState, getInitialState, subscribe };
562
+ const initialState = state = createState(setState, getState, api);
563
+ return api;
564
+ };
565
+ const createStore = ((createState) => createState ? createStoreImpl(createState) : createStoreImpl);
566
+
567
+ const identity = (arg) => arg;
568
+ function useStore(api, selector = identity) {
569
+ const slice = React.useSyncExternalStore(
570
+ api.subscribe,
571
+ React.useCallback(() => selector(api.getState()), [api, selector]),
572
+ React.useCallback(() => selector(api.getInitialState()), [api, selector])
573
+ );
574
+ React.useDebugValue(slice);
575
+ return slice;
576
+ }
577
+ const createImpl = (createState) => {
578
+ const api = createStore(createState);
579
+ const useBoundStore = (selector) => useStore(api, selector);
580
+ Object.assign(useBoundStore, api);
581
+ return useBoundStore;
582
+ };
583
+ const create = ((createState) => createState ? createImpl(createState) : createImpl);
584
+
585
+ const useThemeStore = create((set) => ({
586
+ theme: 'system',
587
+ setTheme: (theme) => {
588
+ localStorage.setItem('theme', theme);
589
+ set({ theme });
590
+ },
591
+ }));
592
+
593
+ function ThemeProvider({ children }) {
594
+ const { theme, setTheme } = useThemeStore();
595
+ // Load from localStorage on mount
596
+ React.useEffect(() => {
597
+ const saved = localStorage.getItem('theme');
598
+ if (saved)
599
+ setTheme(saved);
600
+ // eslint-disable-next-line react-hooks/exhaustive-deps
601
+ }, []);
602
+ // Apply theme whenever it changes
603
+ React.useEffect(() => {
604
+ applyTheme(theme);
605
+ }, [theme]);
606
+ return jsxRuntimeExports.jsx(jsxRuntimeExports.Fragment, { children: children });
607
+ }
608
+
493
609
  exports.Button = Button;
494
610
  exports.Checkbox = Checkbox;
495
611
  exports.Input = Input;
496
612
  exports.Label = Label;
613
+ exports.ScrollArea = ScrollArea;
497
614
  exports.Separator = Separator;
498
615
  exports.Spinner = Spinner;
616
+ exports.Switch = Switch;
617
+ exports.ThemeProvider = ThemeProvider;
618
+ exports.applyTheme = applyTheme;
499
619
  exports.cn = cn;
500
620
  exports.useToggle = useToggle;
package/dist/index.css CHANGED
@@ -1 +1 @@
1
- /*! tailwindcss v4.1.7 | MIT License | https://tailwindcss.com */@layer theme, base, components, utilities;@layer theme{:host,:root{--font-sans:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--font-mono:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--color-gray-200:oklch(92.8% 0.006 264.531);--color-white:#fff;--spacing:0.25rem;--text-xs:0.75rem;--text-xs--line-height:1.33333;--text-sm:0.875rem;--text-sm--line-height:1.42857;--text-base:1rem;--text-base--line-height:1.5;--font-weight-medium:500;--animate-spin:spin 1s linear infinite;--default-transition-duration:150ms;--default-transition-timing-function:cubic-bezier(0.4,0,0.2,1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono)}}@layer base{*,::backdrop,::file-selector-button,:after,:before{border:0 solid;box-sizing:border-box;margin:0;padding:0}:host,html{-webkit-text-size-adjust:100%;font-feature-settings:var(--default-font-feature-settings,normal);-webkit-tap-highlight-color:transparent;font-family:var(--default-font-family,ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji");font-variation-settings:var(--default-font-variation-settings,normal);line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4}hr{border-top-width:1px;color:inherit;height:0}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-feature-settings:var(--default-mono-font-feature-settings,normal);font-family:var(--default-mono-font-family,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace);font-size:1em;font-variation-settings:var(--default-mono-font-variation-settings,normal)}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{border-collapse:collapse;border-color:inherit;text-indent:0}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}menu,ol,ul{list-style:none}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{height:auto;max-width:100%}::file-selector-button,button,input,optgroup,select,textarea{font-feature-settings:inherit;background-color:transparent;border-radius:0;color:inherit;font:inherit;font-variation-settings:inherit;letter-spacing:inherit;opacity:1}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::-moz-placeholder{opacity:1}::placeholder{opacity:1}@supports (not (-webkit-appearance:-apple-pay-button)) or (contain-intrinsic-size:1px){::-moz-placeholder{color:currentcolor;@supports (color:color-mix(in lab,red,red)){color:color-mix(in oklab,currentcolor 50%,transparent)}}::placeholder{color:currentcolor;@supports (color:color-mix(in lab,red,red)){color:color-mix(in oklab,currentcolor 50%,transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit,::-webkit-datetime-edit-day-field,::-webkit-datetime-edit-hour-field,::-webkit-datetime-edit-meridiem-field,::-webkit-datetime-edit-millisecond-field,::-webkit-datetime-edit-minute-field,::-webkit-datetime-edit-month-field,::-webkit-datetime-edit-second-field,::-webkit-datetime-edit-year-field{padding-block:0}:-moz-ui-invalid{box-shadow:none}::file-selector-button,button,input:where([type=button],[type=reset],[type=submit]){-webkit-appearance:button;-moz-appearance:button;appearance:button}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer utilities{.relative{position:relative}.contents{display:contents}.flex{display:flex}.grid{display:grid}.inline-flex{display:inline-flex}.size-3\.5{height:calc(var(--spacing)*3.5);width:calc(var(--spacing)*3.5)}.size-4{height:calc(var(--spacing)*4);width:calc(var(--spacing)*4)}.size-6{height:calc(var(--spacing)*6);width:calc(var(--spacing)*6)}.size-8{height:calc(var(--spacing)*8);width:calc(var(--spacing)*8)}.size-9{height:calc(var(--spacing)*9);width:calc(var(--spacing)*9)}.size-10{height:calc(var(--spacing)*10);width:calc(var(--spacing)*10)}.h-6{height:calc(var(--spacing)*6)}.h-8{height:calc(var(--spacing)*8)}.h-9{height:calc(var(--spacing)*9)}.h-10{height:calc(var(--spacing)*10)}.w-full{width:100%}.min-w-0{min-width:calc(var(--spacing)*0)}.shrink-0{flex-shrink:0}.animate-spin{animation:var(--animate-spin)}.place-content-center{place-content:center}.items-center{align-items:center}.justify-center{justify-content:center}.gap-1{gap:calc(var(--spacing)*1)}.gap-1\.5{gap:calc(var(--spacing)*1.5)}.gap-2{gap:calc(var(--spacing)*2)}.rounded-\[4px\]{border-radius:4px}.rounded-md{border-radius:calc(var(--radius) - 2px)}.border{border-style:var(--tw-border-style);border-width:1px}.border-input{border-color:var(--input)}.bg-background{background-color:var(--background)}.bg-border{background-color:var(--border)}.bg-destructive{background-color:var(--destructive)}.bg-primary{background-color:var(--primary)}.bg-secondary{background-color:var(--secondary)}.bg-transparent{background-color:transparent}.px-2{padding-inline:calc(var(--spacing)*2)}.px-3{padding-inline:calc(var(--spacing)*3)}.px-4{padding-inline:calc(var(--spacing)*4)}.px-6{padding-inline:calc(var(--spacing)*6)}.py-1{padding-block:calc(var(--spacing)*1)}.py-2{padding-block:calc(var(--spacing)*2)}.text-base{font-size:var(--text-base);line-height:var(--tw-leading,var(--text-base--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.leading-none{--tw-leading:1;line-height:1}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.whitespace-nowrap{white-space:nowrap}.text-current{color:currentcolor}.text-primary{color:var(--primary)}.text-primary-foreground{color:var(--primary-foreground)}.text-secondary-foreground{color:var(--secondary-foreground)}.text-white{color:var(--color-white)}.underline-offset-4{text-underline-offset:4px}.shadow-xs{--tw-shadow:0 1px 2px 0 var(--tw-shadow-color,rgba(0,0,0,.05));box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.outline{outline-style:var(--tw-outline-style);outline-width:1px}.transition-\[color\,box-shadow\]{transition-duration:var(--tw-duration,var(--default-transition-duration));transition-property:color,box-shadow;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function))}.transition-all{transition-duration:var(--tw-duration,var(--default-transition-duration));transition-property:all;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function))}.transition-shadow{transition-duration:var(--tw-duration,var(--default-transition-duration));transition-property:box-shadow;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function))}.transition-none{transition-property:none}.outline-none{--tw-outline-style:none;outline-style:none}.select-none{-webkit-user-select:none;-moz-user-select:none;user-select:none}.group-data-\[disabled\=true\]\:pointer-events-none{&:is(:where(.group)[data-disabled=true] *){pointer-events:none}}.group-data-\[disabled\=true\]\:opacity-50{&:is(:where(.group)[data-disabled=true] *){opacity:50%}}.peer-disabled\:cursor-not-allowed{&:is(:where(.peer):disabled~*){cursor:not-allowed}}.peer-disabled\:opacity-50{&:is(:where(.peer):disabled~*){opacity:50%}}.selection\:bg-primary{& ::-moz-selection{background-color:var(--primary)}& ::selection{background-color:var(--primary)}&::-moz-selection{background-color:var(--primary)}&::selection{background-color:var(--primary)}}.selection\:text-primary-foreground{& ::-moz-selection{color:var(--primary-foreground)}& ::selection{color:var(--primary-foreground)}&::-moz-selection{color:var(--primary-foreground)}&::selection{color:var(--primary-foreground)}}.file\:inline-flex{&::file-selector-button{display:inline-flex}}.file\:h-7{&::file-selector-button{height:calc(var(--spacing)*7)}}.file\:border-0{&::file-selector-button{border-style:var(--tw-border-style);border-width:0}}.file\:bg-transparent{&::file-selector-button{background-color:transparent}}.file\:text-sm{&::file-selector-button{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}}.file\:font-medium{&::file-selector-button{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}}.file\:text-foreground{&::file-selector-button{color:var(--foreground)}}.placeholder\:text-muted-foreground{&::-moz-placeholder{color:var(--muted-foreground)}&::placeholder{color:var(--muted-foreground)}}.hover\:bg-accent{&:hover{@media (hover:hover){background-color:var(--accent)}}}.hover\:bg-destructive\/90{&:hover{@media (hover:hover){background-color:var(--destructive);@supports (color:color-mix(in lab,red,red)){background-color:color-mix(in oklab,var(--destructive) 90%,transparent)}}}}.hover\:bg-primary\/90{&:hover{@media (hover:hover){background-color:var(--primary);@supports (color:color-mix(in lab,red,red)){background-color:color-mix(in oklab,var(--primary) 90%,transparent)}}}}.hover\:bg-secondary\/80{&:hover{@media (hover:hover){background-color:var(--secondary);@supports (color:color-mix(in lab,red,red)){background-color:color-mix(in oklab,var(--secondary) 80%,transparent)}}}}.hover\:text-accent-foreground{&:hover{@media (hover:hover){color:var(--accent-foreground)}}}.hover\:underline{&:hover{@media (hover:hover){text-decoration-line:underline}}}.focus-visible\:border-ring{&:focus-visible{border-color:var(--ring)}}.focus-visible\:ring-\[3px\]{&:focus-visible{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}}.focus-visible\:ring-destructive\/20{&:focus-visible{--tw-ring-color:var(--destructive);@supports (color:color-mix(in lab,red,red)){--tw-ring-color:color-mix(in oklab,var(--destructive) 20%,transparent)}}}.focus-visible\:ring-ring\/50{&:focus-visible{--tw-ring-color:var(--ring);@supports (color:color-mix(in lab,red,red)){--tw-ring-color:color-mix(in oklab,var(--ring) 50%,transparent)}}}.disabled\:pointer-events-none{&:disabled{pointer-events:none}}.disabled\:cursor-not-allowed{&:disabled{cursor:not-allowed}}.disabled\:opacity-50{&:disabled{opacity:50%}}.has-\[\>svg\]\:px-1\.5{&:has(>svg){padding-inline:calc(var(--spacing)*1.5)}}.has-\[\>svg\]\:px-2\.5{&:has(>svg){padding-inline:calc(var(--spacing)*2.5)}}.has-\[\>svg\]\:px-3{&:has(>svg){padding-inline:calc(var(--spacing)*3)}}.has-\[\>svg\]\:px-4{&:has(>svg){padding-inline:calc(var(--spacing)*4)}}.aria-invalid\:border-destructive{&[aria-invalid=true]{border-color:var(--destructive)}}.aria-invalid\:ring-destructive\/20{&[aria-invalid=true]{--tw-ring-color:var(--destructive);@supports (color:color-mix(in lab,red,red)){--tw-ring-color:color-mix(in oklab,var(--destructive) 20%,transparent)}}}.data-\[orientation\=horizontal\]\:h-px{&[data-orientation=horizontal]{height:1px}}.data-\[orientation\=horizontal\]\:w-full{&[data-orientation=horizontal]{width:100%}}.data-\[orientation\=vertical\]\:h-full{&[data-orientation=vertical]{height:100%}}.data-\[orientation\=vertical\]\:w-px{&[data-orientation=vertical]{width:1px}}.data-\[state\=checked\]\:border-primary{&[data-state=checked]{border-color:var(--primary)}}.data-\[state\=checked\]\:bg-primary{&[data-state=checked]{background-color:var(--primary)}}.data-\[state\=checked\]\:text-primary-foreground{&[data-state=checked]{color:var(--primary-foreground)}}.dark\:border-input,.md\:text-sm{&:is(.dark *){border-color:var(--input)}}.dark\:bg-destructive\/60{&:is(.dark *){background-color:var(--destructive);@supports (color:color-mix(in lab,red,red)){background-color:color-mix(in oklab,var(--destructive) 60%,transparent)}}}.dark\:bg-input\/30{&:is(.dark *){background-color:var(--input);@supports (color:color-mix(in lab,red,red)){background-color:color-mix(in oklab,var(--input) 30%,transparent)}}}.dark\:hover\:bg-accent\/50{&:is(.dark *){&:hover{@media (hover:hover){background-color:var(--accent);@supports (color:color-mix(in lab,red,red)){background-color:color-mix(in oklab,var(--accent) 50%,transparent)}}}}}.dark\:hover\:bg-input\/50{&:is(.dark *){&:hover{@media (hover:hover){background-color:var(--input);@supports (color:color-mix(in lab,red,red)){background-color:color-mix(in oklab,var(--input) 50%,transparent)}}}}}.dark\:focus-visible\:ring-destructive\/40{&:is(.dark *){&:focus-visible{--tw-ring-color:var(--destructive);@supports (color:color-mix(in lab,red,red)){--tw-ring-color:color-mix(in oklab,var(--destructive) 40%,transparent)}}}}.dark\:aria-invalid\:ring-destructive\/40{&:is(.dark *){&[aria-invalid=true]{--tw-ring-color:var(--destructive);@supports (color:color-mix(in lab,red,red)){--tw-ring-color:color-mix(in oklab,var(--destructive) 40%,transparent)}}}}.dark\:data-\[state\=checked\]\:bg-primary{&:is(.dark *){&[data-state=checked]{background-color:var(--primary)}}}.\[\&_svg\]\:pointer-events-none{& svg{pointer-events:none}}.\[\&_svg\]\:shrink-0{& svg{flex-shrink:0}}.\[\&_svg\:not\(\[class\*\=\'size-\'\]\)\]\:size-3{& svg:not([class*=size-]){height:calc(var(--spacing)*3);width:calc(var(--spacing)*3)}}.\[\&_svg\:not\(\[class\*\=\'size-\'\]\)\]\:size-4{& svg:not([class*=size-]){height:calc(var(--spacing)*4);width:calc(var(--spacing)*4)}}}@property --tw-animation-delay{syntax:"*";inherits:false;initial-value:0s}@property --tw-animation-direction{syntax:"*";inherits:false;initial-value:normal}@property --tw-animation-duration{syntax:"*";inherits:false}@property --tw-animation-fill-mode{syntax:"*";inherits:false;initial-value:none}@property --tw-animation-iteration-count{syntax:"*";inherits:false;initial-value:1}@property --tw-enter-blur{syntax:"*";inherits:false;initial-value:0}@property --tw-enter-opacity{syntax:"*";inherits:false;initial-value:1}@property --tw-enter-rotate{syntax:"*";inherits:false;initial-value:0}@property --tw-enter-scale{syntax:"*";inherits:false;initial-value:1}@property --tw-enter-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-enter-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-exit-blur{syntax:"*";inherits:false;initial-value:0}@property --tw-exit-opacity{syntax:"*";inherits:false;initial-value:1}@property --tw-exit-rotate{syntax:"*";inherits:false;initial-value:0}@property --tw-exit-scale{syntax:"*";inherits:false;initial-value:1}@property --tw-exit-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-exit-translate-y{syntax:"*";inherits:false;initial-value:0}@layer base{*,::backdrop,::file-selector-button,:after,:before{border-color:var(--color-gray-200,currentcolor)}*{border-color:var(--border);outline-color:var(--ring);@supports (color:color-mix(in lab,red,red)){outline-color:color-mix(in oklab,var(--ring) 50%,transparent)}}body{background-color:var(--background);color:var(--foreground)}}:root{--radius:0.625rem;--background:oklch(1 0 0);--foreground:oklch(0.145 0 0);--card:oklch(1 0 0);--card-foreground:oklch(0.145 0 0);--popover:oklch(1 0 0);--popover-foreground:oklch(0.145 0 0);--primary:oklch(0.205 0 0);--primary-foreground:oklch(0.985 0 0);--secondary:oklch(0.97 0 0);--secondary-foreground:oklch(0.205 0 0);--muted:oklch(0.97 0 0);--muted-foreground:oklch(0.556 0 0);--accent:oklch(0.97 0 0);--accent-foreground:oklch(0.205 0 0);--destructive:oklch(0.577 0.245 27.325);--border:oklch(0.922 0 0);--input:oklch(0.922 0 0);--ring:oklch(0.708 0 0);--chart-1:oklch(0.646 0.222 41.116);--chart-2:oklch(0.6 0.118 184.704);--chart-3:oklch(0.398 0.07 227.392);--chart-4:oklch(0.828 0.189 84.429);--chart-5:oklch(0.769 0.188 70.08);--sidebar:oklch(0.985 0 0);--sidebar-foreground:oklch(0.145 0 0);--sidebar-primary:oklch(0.205 0 0);--sidebar-primary-foreground:oklch(0.985 0 0);--sidebar-accent:oklch(0.97 0 0);--sidebar-accent-foreground:oklch(0.205 0 0);--sidebar-border:oklch(0.922 0 0);--sidebar-ring:oklch(0.708 0 0)}.dark{--background:oklch(0.145 0 0);--foreground:oklch(0.985 0 0);--card:oklch(0.205 0 0);--card-foreground:oklch(0.985 0 0);--popover:oklch(0.205 0 0);--popover-foreground:oklch(0.985 0 0);--primary:oklch(0.922 0 0);--primary-foreground:oklch(0.205 0 0);--secondary:oklch(0.269 0 0);--secondary-foreground:oklch(0.985 0 0);--muted:oklch(0.269 0 0);--muted-foreground:oklch(0.708 0 0);--accent:oklch(0.269 0 0);--accent-foreground:oklch(0.985 0 0);--destructive:oklch(0.704 0.191 22.216);--border:oklch(1 0 0/10%);--input:oklch(1 0 0/15%);--ring:oklch(0.556 0 0);--chart-1:oklch(0.488 0.243 264.376);--chart-2:oklch(0.696 0.17 162.48);--chart-3:oklch(0.769 0.188 70.08);--chart-4:oklch(0.627 0.265 303.9);--chart-5:oklch(0.645 0.246 16.439);--sidebar:oklch(0.205 0 0);--sidebar-foreground:oklch(0.985 0 0);--sidebar-primary:oklch(0.488 0.243 264.376);--sidebar-primary-foreground:oklch(0.985 0 0);--sidebar-accent:oklch(0.269 0 0);--sidebar-accent-foreground:oklch(0.985 0 0);--sidebar-border:oklch(1 0 0/10%);--sidebar-ring:oklch(0.556 0 0)}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}@keyframes spin{to{transform:rotate(1turn)}}@layer properties{@supports ((-webkit-hyphens:none) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,::backdrop,:after,:before{--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-outline-style:solid;--tw-animation-delay:0s;--tw-animation-direction:normal;--tw-animation-duration:initial;--tw-animation-fill-mode:none;--tw-animation-iteration-count:1;--tw-enter-blur:0;--tw-enter-opacity:1;--tw-enter-rotate:0;--tw-enter-scale:1;--tw-enter-translate-x:0;--tw-enter-translate-y:0;--tw-exit-blur:0;--tw-exit-opacity:1;--tw-exit-rotate:0;--tw-exit-scale:1;--tw-exit-translate-x:0;--tw-exit-translate-y:0}}}
1
+ /*! tailwindcss v4.1.7 | MIT License | https://tailwindcss.com */@layer theme, base, components, utilities;@layer theme{:host,:root{--font-sans:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--font-mono:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--color-gray-200:oklch(92.8% 0.006 264.531);--color-white:#fff;--spacing:0.25rem;--text-xs:0.75rem;--text-xs--line-height:1.33333;--text-sm:0.875rem;--text-sm--line-height:1.42857;--text-base:1rem;--text-base--line-height:1.5;--font-weight-medium:500;--animate-spin:spin 1s linear infinite;--default-transition-duration:150ms;--default-transition-timing-function:cubic-bezier(0.4,0,0.2,1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono)}}@layer base{*,::backdrop,::file-selector-button,:after,:before{border:0 solid;box-sizing:border-box;margin:0;padding:0}:host,html{-webkit-text-size-adjust:100%;font-feature-settings:var(--default-font-feature-settings,normal);-webkit-tap-highlight-color:transparent;font-family:var(--default-font-family,ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji");font-variation-settings:var(--default-font-variation-settings,normal);line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4}hr{border-top-width:1px;color:inherit;height:0}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-feature-settings:var(--default-mono-font-feature-settings,normal);font-family:var(--default-mono-font-family,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace);font-size:1em;font-variation-settings:var(--default-mono-font-variation-settings,normal)}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{border-collapse:collapse;border-color:inherit;text-indent:0}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}menu,ol,ul{list-style:none}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{height:auto;max-width:100%}::file-selector-button,button,input,optgroup,select,textarea{font-feature-settings:inherit;background-color:transparent;border-radius:0;color:inherit;font:inherit;font-variation-settings:inherit;letter-spacing:inherit;opacity:1}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::-moz-placeholder{opacity:1}::placeholder{opacity:1}@supports (not (-webkit-appearance:-apple-pay-button)) or (contain-intrinsic-size:1px){::-moz-placeholder{color:currentcolor;@supports (color:color-mix(in lab,red,red)){color:color-mix(in oklab,currentcolor 50%,transparent)}}::placeholder{color:currentcolor;@supports (color:color-mix(in lab,red,red)){color:color-mix(in oklab,currentcolor 50%,transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit,::-webkit-datetime-edit-day-field,::-webkit-datetime-edit-hour-field,::-webkit-datetime-edit-meridiem-field,::-webkit-datetime-edit-millisecond-field,::-webkit-datetime-edit-minute-field,::-webkit-datetime-edit-month-field,::-webkit-datetime-edit-second-field,::-webkit-datetime-edit-year-field{padding-block:0}:-moz-ui-invalid{box-shadow:none}::file-selector-button,button,input:where([type=button],[type=reset],[type=submit]){-webkit-appearance:button;-moz-appearance:button;appearance:button}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer utilities{.pointer-events-none{pointer-events:none}.relative{position:relative}.container{width:100%;@media (width >= 40rem){max-width:40rem}@media (width >= 48rem){max-width:48rem}@media (width >= 64rem){max-width:64rem}@media (width >= 80rem){max-width:80rem}@media (width >= 96rem){max-width:96rem}}.block{display:block}.contents{display:contents}.flex{display:flex}.grid{display:grid}.inline-flex{display:inline-flex}.size-3\.5{height:calc(var(--spacing)*3.5);width:calc(var(--spacing)*3.5)}.size-4{height:calc(var(--spacing)*4);width:calc(var(--spacing)*4)}.size-6{height:calc(var(--spacing)*6);width:calc(var(--spacing)*6)}.size-8{height:calc(var(--spacing)*8);width:calc(var(--spacing)*8)}.size-9{height:calc(var(--spacing)*9);width:calc(var(--spacing)*9)}.size-10{height:calc(var(--spacing)*10);width:calc(var(--spacing)*10)}.size-full{height:100%;width:100%}.h-2\.5{height:calc(var(--spacing)*2.5)}.h-6{height:calc(var(--spacing)*6)}.h-8{height:calc(var(--spacing)*8)}.h-9{height:calc(var(--spacing)*9)}.h-10{height:calc(var(--spacing)*10)}.h-full{height:100%}.w-2\.5{width:calc(var(--spacing)*2.5)}.w-fit{width:-moz-fit-content;width:fit-content}.w-full{width:100%}.min-w-0{min-width:calc(var(--spacing)*0)}.flex-1{flex:1}.shrink-0{flex-shrink:0}.animate-spin{animation:var(--animate-spin)}.touch-none{touch-action:none}.flex-col{flex-direction:column}.place-content-center{place-content:center}.items-center{align-items:center}.justify-center{justify-content:center}.gap-1{gap:calc(var(--spacing)*1)}.gap-1\.5{gap:calc(var(--spacing)*1.5)}.gap-2{gap:calc(var(--spacing)*2)}.space-x-2{:where(&>:not(:last-child)){--tw-space-x-reverse:0;margin-inline-end:calc(var(--spacing)*2*(1 - var(--tw-space-x-reverse)));margin-inline-start:calc(var(--spacing)*2*var(--tw-space-x-reverse))}}.overflow-hidden{overflow:hidden}.rounded-\[4px\]{border-radius:4px}.rounded-\[inherit\]{border-radius:inherit}.rounded-full{border-radius:calc(infinity * 1px)}.rounded-md{border-radius:calc(var(--radius) - 2px)}.border{border-style:var(--tw-border-style);border-width:1px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-l{border-left-style:var(--tw-border-style);border-left-width:1px}.border-border{border-color:var(--border)}.border-input{border-color:var(--input)}.border-transparent{border-color:transparent}.border-t-transparent{border-top-color:transparent}.border-l-transparent{border-left-color:transparent}.bg-background{background-color:var(--background)}.bg-border{background-color:var(--border)}.bg-destructive{background-color:var(--destructive)}.bg-primary{background-color:var(--primary)}.bg-secondary{background-color:var(--secondary)}.bg-transparent{background-color:transparent}.p-px{padding:1px}.px-2{padding-inline:calc(var(--spacing)*2)}.px-3{padding-inline:calc(var(--spacing)*3)}.px-4{padding-inline:calc(var(--spacing)*4)}.px-6{padding-inline:calc(var(--spacing)*6)}.py-0\.5{padding-block:calc(var(--spacing)*.5)}.py-1{padding-block:calc(var(--spacing)*1)}.py-2{padding-block:calc(var(--spacing)*2)}.text-base{font-size:var(--text-base);line-height:var(--tw-leading,var(--text-base--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.leading-none{--tw-leading:1;line-height:1}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.whitespace-nowrap{white-space:nowrap}.text-current{color:currentcolor}.text-foreground{color:var(--foreground)}.text-primary{color:var(--primary)}.text-primary-foreground{color:var(--primary-foreground)}.text-secondary-foreground{color:var(--secondary-foreground)}.text-white{color:var(--color-white)}.underline-offset-4{text-underline-offset:4px}.shadow-xs{--tw-shadow:0 1px 2px 0 var(--tw-shadow-color,rgba(0,0,0,.05))}.ring-0,.shadow-xs{box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.ring-0{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor)}.outline{outline-style:var(--tw-outline-style);outline-width:1px}.transition-\[color\,box-shadow\]{transition-duration:var(--tw-duration,var(--default-transition-duration));transition-property:color,box-shadow;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function))}.transition-all{transition-duration:var(--tw-duration,var(--default-transition-duration));transition-property:all;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function))}.transition-colors{transition-duration:var(--tw-duration,var(--default-transition-duration));transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function))}.transition-shadow{transition-duration:var(--tw-duration,var(--default-transition-duration));transition-property:box-shadow;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function))}.transition-transform{transition-duration:var(--tw-duration,var(--default-transition-duration));transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function))}.transition-none{transition-property:none}.outline-none{--tw-outline-style:none;outline-style:none}.select-none{-webkit-user-select:none;-moz-user-select:none;user-select:none}.group-data-\[disabled\=true\]\:pointer-events-none{&:is(:where(.group)[data-disabled=true] *){pointer-events:none}}.group-data-\[disabled\=true\]\:opacity-50{&:is(:where(.group)[data-disabled=true] *){opacity:50%}}.group-data-\[size\=default\]\/switch\:size-4{&:is(:where(.group\/switch)[data-size=default] *){height:calc(var(--spacing)*4);width:calc(var(--spacing)*4)}}.group-data-\[size\=sm\]\/switch\:size-3{&:is(:where(.group\/switch)[data-size=sm] *){height:calc(var(--spacing)*3);width:calc(var(--spacing)*3)}}.peer-disabled\:cursor-not-allowed{&:is(:where(.peer):disabled~*){cursor:not-allowed}}.peer-disabled\:opacity-50{&:is(:where(.peer):disabled~*){opacity:50%}}.selection\:bg-primary{& ::-moz-selection{background-color:var(--primary)}& ::selection{background-color:var(--primary)}&::-moz-selection{background-color:var(--primary)}&::selection{background-color:var(--primary)}}.selection\:text-primary-foreground{& ::-moz-selection{color:var(--primary-foreground)}& ::selection{color:var(--primary-foreground)}&::-moz-selection{color:var(--primary-foreground)}&::selection{color:var(--primary-foreground)}}.file\:inline-flex{&::file-selector-button{display:inline-flex}}.file\:h-7{&::file-selector-button{height:calc(var(--spacing)*7)}}.file\:border-0{&::file-selector-button{border-style:var(--tw-border-style);border-width:0}}.file\:bg-transparent{&::file-selector-button{background-color:transparent}}.file\:text-sm{&::file-selector-button{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}}.file\:font-medium{&::file-selector-button{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}}.file\:text-foreground{&::file-selector-button{color:var(--foreground)}}.placeholder\:text-muted-foreground{&::-moz-placeholder{color:var(--muted-foreground)}&::placeholder{color:var(--muted-foreground)}}.hover\:bg-accent{&:hover{@media (hover:hover){background-color:var(--accent)}}}.hover\:bg-destructive\/90{&:hover{@media (hover:hover){background-color:var(--destructive);@supports (color:color-mix(in lab,red,red)){background-color:color-mix(in oklab,var(--destructive) 90%,transparent)}}}}.hover\:bg-primary\/90{&:hover{@media (hover:hover){background-color:var(--primary);@supports (color:color-mix(in lab,red,red)){background-color:color-mix(in oklab,var(--primary) 90%,transparent)}}}}.hover\:bg-secondary\/80{&:hover{@media (hover:hover){background-color:var(--secondary);@supports (color:color-mix(in lab,red,red)){background-color:color-mix(in oklab,var(--secondary) 80%,transparent)}}}}.hover\:text-accent-foreground{&:hover{@media (hover:hover){color:var(--accent-foreground)}}}.hover\:underline{&:hover{@media (hover:hover){text-decoration-line:underline}}}.focus-visible\:border-ring{&:focus-visible{border-color:var(--ring)}}.focus-visible\:ring-\[3px\]{&:focus-visible{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}}.focus-visible\:ring-destructive\/20{&:focus-visible{--tw-ring-color:var(--destructive);@supports (color:color-mix(in lab,red,red)){--tw-ring-color:color-mix(in oklab,var(--destructive) 20%,transparent)}}}.focus-visible\:ring-ring\/50{&:focus-visible{--tw-ring-color:var(--ring);@supports (color:color-mix(in lab,red,red)){--tw-ring-color:color-mix(in oklab,var(--ring) 50%,transparent)}}}.focus-visible\:outline-1{&:focus-visible{outline-style:var(--tw-outline-style);outline-width:1px}}.disabled\:pointer-events-none{&:disabled{pointer-events:none}}.disabled\:cursor-not-allowed{&:disabled{cursor:not-allowed}}.disabled\:opacity-50{&:disabled{opacity:50%}}.has-\[\>svg\]\:px-1\.5{&:has(>svg){padding-inline:calc(var(--spacing)*1.5)}}.has-\[\>svg\]\:px-2\.5{&:has(>svg){padding-inline:calc(var(--spacing)*2.5)}}.has-\[\>svg\]\:px-3{&:has(>svg){padding-inline:calc(var(--spacing)*3)}}.has-\[\>svg\]\:px-4{&:has(>svg){padding-inline:calc(var(--spacing)*4)}}.aria-invalid\:border-destructive{&[aria-invalid=true]{border-color:var(--destructive)}}.aria-invalid\:ring-destructive\/20{&[aria-invalid=true]{--tw-ring-color:var(--destructive);@supports (color:color-mix(in lab,red,red)){--tw-ring-color:color-mix(in oklab,var(--destructive) 20%,transparent)}}}.data-\[orientation\=horizontal\]\:h-px{&[data-orientation=horizontal]{height:1px}}.data-\[orientation\=horizontal\]\:w-full{&[data-orientation=horizontal]{width:100%}}.data-\[orientation\=vertical\]\:h-full{&[data-orientation=vertical]{height:100%}}.data-\[orientation\=vertical\]\:w-px{&[data-orientation=vertical]{width:1px}}.data-\[size\=default\]\:h-\[1\.15rem\]{&[data-size=default]{height:1.15rem}}.data-\[size\=default\]\:w-8{&[data-size=default]{width:calc(var(--spacing)*8)}}.data-\[size\=sm\]\:h-3\.5{&[data-size=sm]{height:calc(var(--spacing)*3.5)}}.data-\[size\=sm\]\:w-6{&[data-size=sm]{width:calc(var(--spacing)*6)}}.data-\[state\=checked\]\:translate-x-\[calc\(100\%-2px\)\]{&[data-state=checked]{--tw-translate-x:calc(100% - 2px);translate:var(--tw-translate-x) var(--tw-translate-y)}}.data-\[state\=checked\]\:border-primary{&[data-state=checked]{border-color:var(--primary)}}.data-\[state\=checked\]\:bg-primary{&[data-state=checked]{background-color:var(--primary)}}.data-\[state\=checked\]\:text-primary-foreground{&[data-state=checked]{color:var(--primary-foreground)}}.data-\[state\=unchecked\]\:translate-x-0{&[data-state=unchecked]{--tw-translate-x:calc(var(--spacing)*0);translate:var(--tw-translate-x) var(--tw-translate-y)}}.data-\[state\=unchecked\]\:bg-input{&[data-state=unchecked]{background-color:var(--input)}}.dark\:border-input,.md\:text-sm{&:is(.dark *){border-color:var(--input)}}.dark\:bg-destructive\/60{&:is(.dark *){background-color:var(--destructive);@supports (color:color-mix(in lab,red,red)){background-color:color-mix(in oklab,var(--destructive) 60%,transparent)}}}.dark\:bg-input\/30{&:is(.dark *){background-color:var(--input);@supports (color:color-mix(in lab,red,red)){background-color:color-mix(in oklab,var(--input) 30%,transparent)}}}.dark\:hover\:bg-accent\/50{&:is(.dark *){&:hover{@media (hover:hover){background-color:var(--accent);@supports (color:color-mix(in lab,red,red)){background-color:color-mix(in oklab,var(--accent) 50%,transparent)}}}}}.dark\:hover\:bg-input\/50{&:is(.dark *){&:hover{@media (hover:hover){background-color:var(--input);@supports (color:color-mix(in lab,red,red)){background-color:color-mix(in oklab,var(--input) 50%,transparent)}}}}}.dark\:focus-visible\:ring-destructive\/40{&:is(.dark *){&:focus-visible{--tw-ring-color:var(--destructive);@supports (color:color-mix(in lab,red,red)){--tw-ring-color:color-mix(in oklab,var(--destructive) 40%,transparent)}}}}.dark\:aria-invalid\:ring-destructive\/40{&:is(.dark *){&[aria-invalid=true]{--tw-ring-color:var(--destructive);@supports (color:color-mix(in lab,red,red)){--tw-ring-color:color-mix(in oklab,var(--destructive) 40%,transparent)}}}}.dark\:data-\[state\=checked\]\:bg-primary{&:is(.dark *){&[data-state=checked]{background-color:var(--primary)}}}.dark\:data-\[state\=checked\]\:bg-primary-foreground{&:is(.dark *){&[data-state=checked]{background-color:var(--primary-foreground)}}}.dark\:data-\[state\=unchecked\]\:bg-foreground{&:is(.dark *){&[data-state=unchecked]{background-color:var(--foreground)}}}.dark\:data-\[state\=unchecked\]\:bg-input\/80{&:is(.dark *){&[data-state=unchecked]{background-color:var(--input);@supports (color:color-mix(in lab,red,red)){background-color:color-mix(in oklab,var(--input) 80%,transparent)}}}}.\[\&_svg\]\:pointer-events-none{& svg{pointer-events:none}}.\[\&_svg\]\:shrink-0{& svg{flex-shrink:0}}.\[\&_svg\:not\(\[class\*\=\'size-\'\]\)\]\:size-3{& svg:not([class*=size-]){height:calc(var(--spacing)*3);width:calc(var(--spacing)*3)}}.\[\&_svg\:not\(\[class\*\=\'size-\'\]\)\]\:size-4{& svg:not([class*=size-]){height:calc(var(--spacing)*4);width:calc(var(--spacing)*4)}}.\[\&\>svg\]\:pointer-events-none{&>svg{pointer-events:none}}.\[\&\>svg\]\:size-3{&>svg{height:calc(var(--spacing)*3);width:calc(var(--spacing)*3)}}.\[a\&\]\:hover\:bg-accent{a&{&:hover{@media (hover:hover){background-color:var(--accent)}}}}.\[a\&\]\:hover\:bg-destructive\/90{a&{&:hover{@media (hover:hover){background-color:var(--destructive);@supports (color:color-mix(in lab,red,red)){background-color:color-mix(in oklab,var(--destructive) 90%,transparent)}}}}}.\[a\&\]\:hover\:bg-primary\/90{a&{&:hover{@media (hover:hover){background-color:var(--primary);@supports (color:color-mix(in lab,red,red)){background-color:color-mix(in oklab,var(--primary) 90%,transparent)}}}}}.\[a\&\]\:hover\:bg-secondary\/90{a&{&:hover{@media (hover:hover){background-color:var(--secondary);@supports (color:color-mix(in lab,red,red)){background-color:color-mix(in oklab,var(--secondary) 90%,transparent)}}}}}.\[a\&\]\:hover\:text-accent-foreground{a&{&:hover{@media (hover:hover){color:var(--accent-foreground)}}}}.\[a\&\]\:hover\:underline{a&{&:hover{@media (hover:hover){text-decoration-line:underline}}}}}@property --tw-animation-delay{syntax:"*";inherits:false;initial-value:0s}@property --tw-animation-direction{syntax:"*";inherits:false;initial-value:normal}@property --tw-animation-duration{syntax:"*";inherits:false}@property --tw-animation-fill-mode{syntax:"*";inherits:false;initial-value:none}@property --tw-animation-iteration-count{syntax:"*";inherits:false;initial-value:1}@property --tw-enter-blur{syntax:"*";inherits:false;initial-value:0}@property --tw-enter-opacity{syntax:"*";inherits:false;initial-value:1}@property --tw-enter-rotate{syntax:"*";inherits:false;initial-value:0}@property --tw-enter-scale{syntax:"*";inherits:false;initial-value:1}@property --tw-enter-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-enter-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-exit-blur{syntax:"*";inherits:false;initial-value:0}@property --tw-exit-opacity{syntax:"*";inherits:false;initial-value:1}@property --tw-exit-rotate{syntax:"*";inherits:false;initial-value:0}@property --tw-exit-scale{syntax:"*";inherits:false;initial-value:1}@property --tw-exit-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-exit-translate-y{syntax:"*";inherits:false;initial-value:0}@layer base{*,::backdrop,::file-selector-button,:after,:before{border-color:var(--color-gray-200,currentcolor)}*{border-color:var(--border);outline-color:var(--ring);@supports (color:color-mix(in lab,red,red)){outline-color:color-mix(in oklab,var(--ring) 50%,transparent)}}body{background-color:var(--background);color:var(--foreground)}}:root{--radius:0.625rem;--background:oklch(1 0 0);--foreground:oklch(0.145 0 0);--card:oklch(1 0 0);--card-foreground:oklch(0.145 0 0);--popover:oklch(1 0 0);--popover-foreground:oklch(0.145 0 0);--primary:oklch(0.205 0 0);--primary-foreground:oklch(0.985 0 0);--secondary:oklch(0.97 0 0);--secondary-foreground:oklch(0.205 0 0);--muted:oklch(0.97 0 0);--muted-foreground:oklch(0.556 0 0);--accent:oklch(0.97 0 0);--accent-foreground:oklch(0.205 0 0);--destructive:oklch(0.577 0.245 27.325);--border:oklch(0.922 0 0);--input:oklch(0.922 0 0);--ring:oklch(0.708 0 0);--chart-1:oklch(0.646 0.222 41.116);--chart-2:oklch(0.6 0.118 184.704);--chart-3:oklch(0.398 0.07 227.392);--chart-4:oklch(0.828 0.189 84.429);--chart-5:oklch(0.769 0.188 70.08);--sidebar:oklch(0.985 0 0);--sidebar-foreground:oklch(0.145 0 0);--sidebar-primary:oklch(0.205 0 0);--sidebar-primary-foreground:oklch(0.985 0 0);--sidebar-accent:oklch(0.97 0 0);--sidebar-accent-foreground:oklch(0.205 0 0);--sidebar-border:oklch(0.922 0 0);--sidebar-ring:oklch(0.708 0 0)}.dark{--background:oklch(0.145 0 0);--foreground:oklch(0.985 0 0);--card:oklch(0.205 0 0);--card-foreground:oklch(0.985 0 0);--popover:oklch(0.205 0 0);--popover-foreground:oklch(0.985 0 0);--primary:oklch(0.922 0 0);--primary-foreground:oklch(0.205 0 0);--secondary:oklch(0.269 0 0);--secondary-foreground:oklch(0.985 0 0);--muted:oklch(0.269 0 0);--muted-foreground:oklch(0.708 0 0);--accent:oklch(0.269 0 0);--accent-foreground:oklch(0.985 0 0);--destructive:oklch(0.704 0.191 22.216);--border:oklch(1 0 0/10%);--input:oklch(1 0 0/15%);--ring:oklch(0.556 0 0);--chart-1:oklch(0.488 0.243 264.376);--chart-2:oklch(0.696 0.17 162.48);--chart-3:oklch(0.769 0.188 70.08);--chart-4:oklch(0.627 0.265 303.9);--chart-5:oklch(0.645 0.246 16.439);--sidebar:oklch(0.205 0 0);--sidebar-foreground:oklch(0.985 0 0);--sidebar-primary:oklch(0.488 0.243 264.376);--sidebar-primary-foreground:oklch(0.985 0 0);--sidebar-accent:oklch(0.269 0 0);--sidebar-accent-foreground:oklch(0.985 0 0);--sidebar-border:oklch(1 0 0/10%);--sidebar-ring:oklch(0.556 0 0)}@property --tw-space-x-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}@keyframes spin{to{transform:rotate(1turn)}}@layer properties{@supports ((-webkit-hyphens:none) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,::backdrop,:after,:before{--tw-space-x-reverse:0;--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-outline-style:solid;--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-animation-delay:0s;--tw-animation-direction:normal;--tw-animation-duration:initial;--tw-animation-fill-mode:none;--tw-animation-iteration-count:1;--tw-enter-blur:0;--tw-enter-opacity:1;--tw-enter-rotate:0;--tw-enter-scale:1;--tw-enter-translate-x:0;--tw-enter-translate-y:0;--tw-exit-blur:0;--tw-exit-opacity:1;--tw-exit-rotate:0;--tw-exit-scale:1;--tw-exit-translate-x:0;--tw-exit-translate-y:0}}}
package/dist/index.d.ts CHANGED
@@ -1,4 +1,6 @@
1
1
  export * from './components';
2
2
  export * from './hooks';
3
3
  export * from './lib';
4
+ export * from './providers';
5
+ export * from './types';
4
6
  import './index.css';
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
- import require$$0, { useState, useCallback } from 'react';
1
+ import React, { useState, useCallback, useEffect } from 'react';
2
2
  import { cva } from 'class-variance-authority';
3
- import { Slot, Checkbox as Checkbox$1, Label as Label$1, Separator as Separator$1 } from 'radix-ui';
3
+ import { Slot, Checkbox as Checkbox$2, Label as Label$2, Separator as Separator$2, Switch as Switch$2, ScrollArea as ScrollArea$2 } from 'radix-ui';
4
4
  import { clsx } from 'clsx';
5
5
  import { twMerge } from 'tailwind-merge';
6
6
  import { Loader2Icon, CheckIcon } from 'lucide-react';
@@ -341,7 +341,7 @@ function requireReactJsxRuntime_development () {
341
341
  object.$$typeof === REACT_ELEMENT_TYPE
342
342
  );
343
343
  }
344
- var React = require$$0,
344
+ var React$1 = React,
345
345
  REACT_ELEMENT_TYPE = Symbol.for("react.transitional.element"),
346
346
  REACT_PORTAL_TYPE = Symbol.for("react.portal"),
347
347
  REACT_FRAGMENT_TYPE = Symbol.for("react.fragment"),
@@ -357,7 +357,7 @@ function requireReactJsxRuntime_development () {
357
357
  REACT_ACTIVITY_TYPE = Symbol.for("react.activity"),
358
358
  REACT_CLIENT_REFERENCE = Symbol.for("react.client.reference"),
359
359
  ReactSharedInternals =
360
- React.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,
360
+ React$1.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,
361
361
  hasOwnProperty = Object.prototype.hasOwnProperty,
362
362
  isArrayImpl = Array.isArray,
363
363
  createTask = console.createTask
@@ -365,15 +365,15 @@ function requireReactJsxRuntime_development () {
365
365
  : function () {
366
366
  return null;
367
367
  };
368
- React = {
368
+ React$1 = {
369
369
  react_stack_bottom_frame: function (callStackForError) {
370
370
  return callStackForError();
371
371
  }
372
372
  };
373
373
  var specialPropKeyWarningShown;
374
374
  var didWarnAboutElementRef = {};
375
- var unknownOwnerDebugStack = React.react_stack_bottom_frame.bind(
376
- React,
375
+ var unknownOwnerDebugStack = React$1.react_stack_bottom_frame.bind(
376
+ React$1,
377
377
  UnknownOwner
378
378
  )();
379
379
  var unknownOwnerDebugTask = createTask(getTaskName(UnknownOwner));
@@ -449,31 +449,74 @@ const buttonVariants = cva("inline-flex shrink-0 items-center justify-center gap
449
449
  size: 'default',
450
450
  },
451
451
  });
452
- function Button({ className, variant = 'default', size = 'default', asChild = false, ...props }) {
452
+ function Button$1({ className, variant = 'default', size = 'default', asChild = false, ...props }) {
453
453
  const Comp = asChild ? Slot.Root : 'button';
454
454
  return (jsxRuntimeExports.jsx(Comp, { className: cn(buttonVariants({ variant, size, className })), "data-size": size, "data-slot": "button", "data-variant": variant, ...props }));
455
455
  }
456
456
 
457
- function Input({ className, type, ...props }) {
457
+ const Button = (props) => {
458
+ return jsxRuntimeExports.jsx(Button$1, { ...props });
459
+ };
460
+
461
+ function Input$1({ className, type, ...props }) {
458
462
  return (jsxRuntimeExports.jsx("input", { className: cn('border-input selection:bg-primary selection:text-primary-foreground file:text-foreground placeholder:text-muted-foreground dark:bg-input/30 h-9 w-full min-w-0 rounded-md border bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm', 'focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]', 'aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40', className), "data-slot": "input", type: type, ...props }));
459
463
  }
460
464
 
461
- function Spinner({ className, ...props }) {
465
+ const Input = (props) => {
466
+ return jsxRuntimeExports.jsx(Input$1, { ...props });
467
+ };
468
+
469
+ function Spinner$1({ className, ...props }) {
462
470
  return jsxRuntimeExports.jsx(Loader2Icon, { "aria-label": "Loading", className: cn('size-4 animate-spin', className), role: "status", ...props });
463
471
  }
464
472
 
465
- function Checkbox({ className, ...props }) {
466
- return (jsxRuntimeExports.jsx(Checkbox$1.Root, { className: cn('peer border-input focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 data-[state=checked]:border-primary data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground dark:bg-input/30 dark:aria-invalid:ring-destructive/40 dark:data-[state=checked]:bg-primary size-4 shrink-0 rounded-[4px] border shadow-xs transition-shadow outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50', className), "data-slot": "checkbox", ...props, children: jsxRuntimeExports.jsx(Checkbox$1.Indicator, { className: "grid place-content-center text-current transition-none", "data-slot": "checkbox-indicator", children: jsxRuntimeExports.jsx(CheckIcon, { className: "size-3.5" }) }) }));
473
+ const Spinner = (props) => {
474
+ return jsxRuntimeExports.jsx(Spinner$1, { ...props });
475
+ };
476
+
477
+ function Checkbox$1({ className, ...props }) {
478
+ return (jsxRuntimeExports.jsx(Checkbox$2.Root, { className: cn('peer border-input focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 data-[state=checked]:border-primary data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground dark:bg-input/30 dark:aria-invalid:ring-destructive/40 dark:data-[state=checked]:bg-primary size-4 shrink-0 rounded-[4px] border shadow-xs transition-shadow outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50', className), "data-slot": "checkbox", ...props, children: jsxRuntimeExports.jsx(Checkbox$2.Indicator, { className: "grid place-content-center text-current transition-none", "data-slot": "checkbox-indicator", children: jsxRuntimeExports.jsx(CheckIcon, { className: "size-3.5" }) }) }));
467
479
  }
468
480
 
469
- function Label({ className, ...props }) {
470
- return (jsxRuntimeExports.jsx(Label$1.Root, { className: cn('flex items-center gap-2 text-sm leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50', className), "data-slot": "label", ...props }));
481
+ const Checkbox = (props) => {
482
+ return jsxRuntimeExports.jsx(Checkbox$1, { ...props });
483
+ };
484
+
485
+ function Label$1({ className, ...props }) {
486
+ return (jsxRuntimeExports.jsx(Label$2.Root, { className: cn('flex items-center gap-2 text-sm leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50', className), "data-slot": "label", ...props }));
471
487
  }
472
488
 
473
- function Separator({ className, orientation = 'horizontal', decorative = true, ...props }) {
474
- return (jsxRuntimeExports.jsx(Separator$1.Root, { className: cn('bg-border shrink-0 data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-px', className), "data-slot": "separator", decorative: decorative, orientation: orientation, ...props }));
489
+ const Label = (props) => {
490
+ return jsxRuntimeExports.jsx(Label$1, { ...props });
491
+ };
492
+
493
+ function Separator$1({ className, orientation = 'horizontal', decorative = true, ...props }) {
494
+ return (jsxRuntimeExports.jsx(Separator$2.Root, { className: cn('bg-border shrink-0 data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-px', className), "data-slot": "separator", decorative: decorative, orientation: orientation, ...props }));
475
495
  }
476
496
 
497
+ const Separator = (props) => {
498
+ return jsxRuntimeExports.jsx(Separator$1, { ...props });
499
+ };
500
+
501
+ function Switch$1({ className, size = 'default', ...props }) {
502
+ return (jsxRuntimeExports.jsx(Switch$2.Root, { className: cn('peer group/switch focus-visible:border-ring focus-visible:ring-ring/50 data-[state=checked]:bg-primary data-[state=unchecked]:bg-input dark:data-[state=unchecked]:bg-input/80 inline-flex shrink-0 items-center rounded-full border border-transparent shadow-xs transition-all outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 data-[size=default]:h-[1.15rem] data-[size=default]:w-8 data-[size=sm]:h-3.5 data-[size=sm]:w-6', className), "data-size": size, "data-slot": "switch", ...props, children: jsxRuntimeExports.jsx(Switch$2.Thumb, { className: cn('bg-background dark:data-[state=checked]:bg-primary-foreground dark:data-[state=unchecked]:bg-foreground pointer-events-none block rounded-full ring-0 transition-transform group-data-[size=default]/switch:size-4 group-data-[size=sm]/switch:size-3 data-[state=checked]:translate-x-[calc(100%-2px)] data-[state=unchecked]:translate-x-0'), "data-slot": "switch-thumb" }) }));
503
+ }
504
+
505
+ const Switch = ({ id, label, ...props }) => {
506
+ return (jsxRuntimeExports.jsxs("div", { className: "flex items-center space-x-2", children: [jsxRuntimeExports.jsx(Switch$1, { "data-slot": "switch", id: id, ...props }), jsxRuntimeExports.jsx(Label, { "data-slot": "label", htmlFor: id, children: label })] }));
507
+ };
508
+
509
+ function ScrollArea$1({ className, children, ...props }) {
510
+ return (jsxRuntimeExports.jsxs(ScrollArea$2.Root, { className: cn('relative', className), "data-slot": "scroll-area", ...props, children: [jsxRuntimeExports.jsx(ScrollArea$2.Viewport, { className: "focus-visible:ring-ring/50 size-full rounded-[inherit] transition-[color,box-shadow] outline-none focus-visible:ring-[3px] focus-visible:outline-1", "data-slot": "scroll-area-viewport", children: children }), jsxRuntimeExports.jsx(ScrollBar, {}), jsxRuntimeExports.jsx(ScrollArea$2.Corner, {})] }));
511
+ }
512
+ function ScrollBar({ className, orientation = 'vertical', ...props }) {
513
+ return (jsxRuntimeExports.jsx(ScrollArea$2.ScrollAreaScrollbar, { className: cn('flex touch-none p-px transition-colors select-none', orientation === 'vertical' && 'h-full w-2.5 border-l border-l-transparent', orientation === 'horizontal' && 'h-2.5 flex-col border-t border-t-transparent', className), "data-slot": "scroll-area-scrollbar", orientation: orientation, ...props, children: jsxRuntimeExports.jsx(ScrollArea$2.ScrollAreaThumb, { className: "bg-border relative flex-1 rounded-full", "data-slot": "scroll-area-thumb" }) }));
514
+ }
515
+
516
+ const ScrollArea = ({ children, orientation = 'horizontal', className, ...props }) => {
517
+ return (jsxRuntimeExports.jsxs(ScrollArea$1, { className: className, "data-slot": "scroll-area", ...props, children: [jsxRuntimeExports.jsx("div", { "data-slot": "scroll-area-viewport", children: children }), jsxRuntimeExports.jsx("div", { "data-slot": "scroll-area-scrollbar", children: jsxRuntimeExports.jsx(ScrollBar, { orientation: orientation }) })] }));
518
+ };
519
+
477
520
  /**
478
521
  * A simple boolean toggle hook.
479
522
  *
@@ -488,4 +531,77 @@ function useToggle(initial = false) {
488
531
  return { state, toggle, setOn, setOff };
489
532
  }
490
533
 
491
- export { Button, Checkbox, Input, Label, Separator, Spinner, cn, useToggle };
534
+ const applyTheme = (theme) => {
535
+ const root = window.document.documentElement;
536
+ const systemDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
537
+ const resolvedTheme = theme === 'system' ? (systemDark ? 'dark' : 'light') : theme;
538
+ root.classList.remove('light', 'dark');
539
+ root.classList.add(resolvedTheme);
540
+ };
541
+
542
+ const createStoreImpl = (createState) => {
543
+ let state;
544
+ const listeners = /* @__PURE__ */ new Set();
545
+ const setState = (partial, replace) => {
546
+ const nextState = typeof partial === "function" ? partial(state) : partial;
547
+ if (!Object.is(nextState, state)) {
548
+ const previousState = state;
549
+ state = (replace != null ? replace : typeof nextState !== "object" || nextState === null) ? nextState : Object.assign({}, state, nextState);
550
+ listeners.forEach((listener) => listener(state, previousState));
551
+ }
552
+ };
553
+ const getState = () => state;
554
+ const getInitialState = () => initialState;
555
+ const subscribe = (listener) => {
556
+ listeners.add(listener);
557
+ return () => listeners.delete(listener);
558
+ };
559
+ const api = { setState, getState, getInitialState, subscribe };
560
+ const initialState = state = createState(setState, getState, api);
561
+ return api;
562
+ };
563
+ const createStore = ((createState) => createState ? createStoreImpl(createState) : createStoreImpl);
564
+
565
+ const identity = (arg) => arg;
566
+ function useStore(api, selector = identity) {
567
+ const slice = React.useSyncExternalStore(
568
+ api.subscribe,
569
+ React.useCallback(() => selector(api.getState()), [api, selector]),
570
+ React.useCallback(() => selector(api.getInitialState()), [api, selector])
571
+ );
572
+ React.useDebugValue(slice);
573
+ return slice;
574
+ }
575
+ const createImpl = (createState) => {
576
+ const api = createStore(createState);
577
+ const useBoundStore = (selector) => useStore(api, selector);
578
+ Object.assign(useBoundStore, api);
579
+ return useBoundStore;
580
+ };
581
+ const create = ((createState) => createState ? createImpl(createState) : createImpl);
582
+
583
+ const useThemeStore = create((set) => ({
584
+ theme: 'system',
585
+ setTheme: (theme) => {
586
+ localStorage.setItem('theme', theme);
587
+ set({ theme });
588
+ },
589
+ }));
590
+
591
+ function ThemeProvider({ children }) {
592
+ const { theme, setTheme } = useThemeStore();
593
+ // Load from localStorage on mount
594
+ useEffect(() => {
595
+ const saved = localStorage.getItem('theme');
596
+ if (saved)
597
+ setTheme(saved);
598
+ // eslint-disable-next-line react-hooks/exhaustive-deps
599
+ }, []);
600
+ // Apply theme whenever it changes
601
+ useEffect(() => {
602
+ applyTheme(theme);
603
+ }, [theme]);
604
+ return jsxRuntimeExports.jsx(jsxRuntimeExports.Fragment, { children: children });
605
+ }
606
+
607
+ export { Button, Checkbox, Input, Label, ScrollArea, Separator, Spinner, Switch, ThemeProvider, applyTheme, cn, useToggle };
@@ -1 +1,2 @@
1
1
  export { cn } from './utils';
2
+ export { applyTheme } from './theme';
@@ -0,0 +1 @@
1
+ export declare const applyTheme: (theme: "light" | "dark" | "system") => void;
@@ -0,0 +1 @@
1
+ export { ThemeProvider } from './theme-provider';
@@ -0,0 +1,3 @@
1
+ export declare function ThemeProvider({ children }: {
2
+ children: React.ReactNode;
3
+ }): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1 @@
1
+ export { useThemeStore } from './theme-store';
@@ -0,0 +1,7 @@
1
+ import { Theme } from '@/types';
2
+ type ThemeState = {
3
+ theme: Theme;
4
+ setTheme: (theme: Theme) => void;
5
+ };
6
+ export declare const useThemeStore: import("zustand").UseBoundStore<import("zustand").StoreApi<ThemeState>>;
7
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export type Theme = 'light' | 'dark' | 'system';
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@khanhminh/design-system",
3
3
  "description": "A reusable React component library built with TypeScript, Tailwind CSS, and Radix UI",
4
- "version": "1.10.8",
4
+ "version": "1.12.0",
5
5
  "type": "module",
6
6
  "private": false,
7
7
  "main": "dist/index.cjs",
@@ -30,7 +30,11 @@
30
30
  "build:lib": "rollup -c",
31
31
  "lint": "eslint .",
32
32
  "preview": "vite preview",
33
- "pre-commit": "lint-staged"
33
+ "pre-commit": "lint-staged",
34
+ "test": "vitest",
35
+ "test:run": "vitest run",
36
+ "test:ui": "vitest --ui",
37
+ "test:coverage": "vitest run --coverage"
34
38
  },
35
39
  "dependencies": {
36
40
  "@tailwindcss/vite": "^4.1.7",
@@ -43,7 +47,8 @@
43
47
  "radix-ui": "^1.4.3",
44
48
  "react": "^18 || ^19",
45
49
  "react-dom": "^18 || ^19",
46
- "tailwind-merge": "^3.5.0"
50
+ "tailwind-merge": "^3.5.0",
51
+ "zustand": "^5.0.12"
47
52
  },
48
53
  "devDependencies": {
49
54
  "@eslint/js": "^9.13.0",
@@ -51,10 +56,15 @@
51
56
  "@rollup/plugin-node-resolve": "^15.3.0",
52
57
  "@rollup/plugin-typescript": "^12.1.1",
53
58
  "@tailwindcss/postcss": "^4.1.7",
59
+ "@testing-library/jest-dom": "^6.9.1",
60
+ "@testing-library/react": "^16.3.2",
61
+ "@testing-library/user-event": "^14.6.1",
54
62
  "@types/node": "^25.3.3",
55
63
  "@types/react": "^18.3.12",
56
64
  "@types/react-dom": "^18.3.1",
57
65
  "@vitejs/plugin-react": "^4.3.3",
66
+ "@vitejs/plugin-react-swc": "^4.3.0",
67
+ "@vitest/coverage-v8": "^4.1.0",
58
68
  "autoprefixer": "^10.4.27",
59
69
  "eslint": "^9.13.0",
60
70
  "eslint-plugin-react": "^7.37.5",
@@ -62,6 +72,7 @@
62
72
  "eslint-plugin-react-refresh": "^0.4.14",
63
73
  "globals": "^15.11.0",
64
74
  "husky": "^8.0.0",
75
+ "jsdom": "^29.0.0",
65
76
  "lint-staged": "^15.2.10",
66
77
  "postcss": "^8.4.47",
67
78
  "rollup": "^4.12.0",
@@ -69,9 +80,10 @@
69
80
  "shadcn": "^3.8.5",
70
81
  "tailwindcss": "^4.1.7",
71
82
  "tw-animate-css": "^1.4.0",
72
- "typescript": "~5.6.2",
83
+ "typescript": "^5.9.3",
73
84
  "typescript-eslint": "^8.11.0",
74
- "vite": "^5.4.10"
85
+ "vite": "^5.4.10",
86
+ "vitest": "^4.1.0"
75
87
  },
76
88
  "peerDependencies": {
77
89
  "react": "^18 || ^19",