@srcroot/ui 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/README.md +151 -0
  2. package/dist/index.d.ts +2 -0
  3. package/dist/index.js +640 -0
  4. package/package.json +43 -0
  5. package/registry/accordion.tsx +158 -0
  6. package/registry/alert-dialog.tsx +206 -0
  7. package/registry/alert.tsx +73 -0
  8. package/registry/aspect-ratio.tsx +44 -0
  9. package/registry/avatar.tsx +94 -0
  10. package/registry/badge.tsx +68 -0
  11. package/registry/breadcrumb.tsx +151 -0
  12. package/registry/button-group.tsx +84 -0
  13. package/registry/button.tsx +102 -0
  14. package/registry/calendar.tsx +238 -0
  15. package/registry/card.tsx +114 -0
  16. package/registry/carousel.tsx +169 -0
  17. package/registry/checkbox.tsx +79 -0
  18. package/registry/collapsible.tsx +110 -0
  19. package/registry/container.tsx +60 -0
  20. package/registry/dialog.tsx +264 -0
  21. package/registry/dropdown-menu.tsx +387 -0
  22. package/registry/image.tsx +144 -0
  23. package/registry/input.tsx +44 -0
  24. package/registry/label.tsx +34 -0
  25. package/registry/loading-spinner.tsx +108 -0
  26. package/registry/otp-input.tsx +152 -0
  27. package/registry/pagination.tsx +146 -0
  28. package/registry/popover.tsx +135 -0
  29. package/registry/progress.tsx +49 -0
  30. package/registry/radio.tsx +99 -0
  31. package/registry/search.tsx +146 -0
  32. package/registry/select.tsx +190 -0
  33. package/registry/separator.tsx +44 -0
  34. package/registry/sheet.tsx +180 -0
  35. package/registry/skeleton.tsx +26 -0
  36. package/registry/slider.tsx +115 -0
  37. package/registry/star-rating.tsx +131 -0
  38. package/registry/switch.tsx +70 -0
  39. package/registry/table.tsx +136 -0
  40. package/registry/tabs.tsx +122 -0
  41. package/registry/text.tsx +70 -0
  42. package/registry/textarea.tsx +39 -0
  43. package/registry/toast.tsx +95 -0
  44. package/registry/tooltip.tsx +122 -0
@@ -0,0 +1,95 @@
1
+ import * as React from "react"
2
+ import { cva, type VariantProps } from "class-variance-authority"
3
+ import { cn } from "@/lib/utils"
4
+
5
+ const toastVariants = cva(
6
+ "group pointer-events-auto relative flex w-full items-center justify-between space-x-2 overflow-hidden rounded-md border p-4 pr-6 shadow-lg transition-all",
7
+ {
8
+ variants: {
9
+ variant: {
10
+ default: "border bg-background text-foreground",
11
+ destructive:
12
+ "destructive group border-destructive bg-destructive text-destructive-foreground",
13
+ },
14
+ },
15
+ defaultVariants: {
16
+ variant: "default",
17
+ },
18
+ }
19
+ )
20
+
21
+ interface ToastProps extends React.HTMLAttributes<HTMLDivElement>, VariantProps<typeof toastVariants> {
22
+ onClose?: () => void
23
+ }
24
+
25
+ /**
26
+ * Toast notification component
27
+ *
28
+ * For a complete toast system, use with a ToastProvider context.
29
+ * This is the individual toast component.
30
+ *
31
+ * @example
32
+ * <Toast variant="default">
33
+ * <ToastTitle>Success</ToastTitle>
34
+ * <ToastDescription>Your action was completed.</ToastDescription>
35
+ * </Toast>
36
+ */
37
+ const Toast = React.forwardRef<HTMLDivElement, ToastProps>(
38
+ ({ className, variant, onClose, children, ...props }, ref) => {
39
+ return (
40
+ <div
41
+ ref={ref}
42
+ role={variant === "destructive" ? "alert" : "status"}
43
+ aria-live={variant === "destructive" ? "assertive" : "polite"}
44
+ className={cn(toastVariants({ variant }), className)}
45
+ {...props}
46
+ >
47
+ <div className="grid gap-1">{children}</div>
48
+ {onClose && (
49
+ <button
50
+ className="absolute right-1 top-1 rounded-md p-1 text-foreground/50 opacity-0 transition-opacity hover:text-foreground focus:opacity-100 focus:outline-none focus:ring-1 group-hover:opacity-100"
51
+ onClick={onClose}
52
+ >
53
+ <svg className="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
54
+ <path strokeLinecap="round" strokeLinejoin="round" d="M6 18L18 6M6 6l12 12" />
55
+ </svg>
56
+ </button>
57
+ )}
58
+ </div>
59
+ )
60
+ }
61
+ )
62
+ Toast.displayName = "Toast"
63
+
64
+ const ToastTitle = React.forwardRef<
65
+ HTMLDivElement,
66
+ React.HTMLAttributes<HTMLDivElement>
67
+ >(({ className, ...props }, ref) => (
68
+ <div ref={ref} className={cn("text-sm font-semibold [&+div]:text-xs", className)} {...props} />
69
+ ))
70
+ ToastTitle.displayName = "ToastTitle"
71
+
72
+ const ToastDescription = React.forwardRef<
73
+ HTMLDivElement,
74
+ React.HTMLAttributes<HTMLDivElement>
75
+ >(({ className, ...props }, ref) => (
76
+ <div ref={ref} className={cn("text-sm opacity-90", className)} {...props} />
77
+ ))
78
+ ToastDescription.displayName = "ToastDescription"
79
+
80
+ const ToastAction = React.forwardRef<
81
+ HTMLButtonElement,
82
+ React.ButtonHTMLAttributes<HTMLButtonElement>
83
+ >(({ className, ...props }, ref) => (
84
+ <button
85
+ ref={ref}
86
+ className={cn(
87
+ "inline-flex h-8 shrink-0 items-center justify-center rounded-md border bg-transparent px-3 text-sm font-medium transition-colors hover:bg-secondary focus:outline-none focus:ring-1 focus:ring-ring disabled:pointer-events-none disabled:opacity-50",
88
+ className
89
+ )}
90
+ {...props}
91
+ />
92
+ ))
93
+ ToastAction.displayName = "ToastAction"
94
+
95
+ export { Toast, ToastTitle, ToastDescription, ToastAction, toastVariants }
@@ -0,0 +1,122 @@
1
+ import * as React from "react"
2
+ import { cn } from "@/lib/utils"
3
+
4
+ interface TooltipContextValue {
5
+ open: boolean
6
+ setOpen: (open: boolean) => void
7
+ }
8
+
9
+ const TooltipContext = React.createContext<TooltipContextValue | null>(null)
10
+
11
+ interface TooltipProviderProps {
12
+ children: React.ReactNode
13
+ delayDuration?: number
14
+ }
15
+
16
+ /**
17
+ * TooltipProvider wraps your app to enable tooltips
18
+ */
19
+ function TooltipProvider({ children }: TooltipProviderProps) {
20
+ return <>{children}</>
21
+ }
22
+
23
+ interface TooltipProps {
24
+ children: React.ReactNode
25
+ open?: boolean
26
+ onOpenChange?: (open: boolean) => void
27
+ defaultOpen?: boolean
28
+ }
29
+
30
+ /**
31
+ * Tooltip component for hover hints
32
+ *
33
+ * @example
34
+ * <TooltipProvider>
35
+ * <Tooltip>
36
+ * <TooltipTrigger>Hover me</TooltipTrigger>
37
+ * <TooltipContent>Tooltip text</TooltipContent>
38
+ * </Tooltip>
39
+ * </TooltipProvider>
40
+ */
41
+ function Tooltip({ children, open: controlledOpen, onOpenChange, defaultOpen = false }: TooltipProps) {
42
+ const [uncontrolledOpen, setUncontrolledOpen] = React.useState(defaultOpen)
43
+
44
+ const open = controlledOpen !== undefined ? controlledOpen : uncontrolledOpen
45
+ const setOpen = onOpenChange || setUncontrolledOpen
46
+
47
+ return (
48
+ <TooltipContext.Provider value={{ open, setOpen }}>
49
+ <span className="relative inline-block">
50
+ {children}
51
+ </span>
52
+ </TooltipContext.Provider>
53
+ )
54
+ }
55
+
56
+ interface TooltipTriggerProps extends React.HTMLAttributes<HTMLSpanElement> {
57
+ asChild?: boolean
58
+ }
59
+
60
+ const TooltipTrigger = React.forwardRef<HTMLSpanElement, TooltipTriggerProps>(
61
+ ({ children, asChild, ...props }, ref) => {
62
+ const context = React.useContext(TooltipContext)
63
+ if (!context) throw new Error("TooltipTrigger must be used within Tooltip")
64
+
65
+ const handleMouseEnter = () => context.setOpen(true)
66
+ const handleMouseLeave = () => context.setOpen(false)
67
+ const handleFocus = () => context.setOpen(true)
68
+ const handleBlur = () => context.setOpen(false)
69
+
70
+ if (asChild && React.isValidElement(children)) {
71
+ return React.cloneElement(children as React.ReactElement<any>, {
72
+ onMouseEnter: handleMouseEnter,
73
+ onMouseLeave: handleMouseLeave,
74
+ onFocus: handleFocus,
75
+ onBlur: handleBlur,
76
+ ref,
77
+ })
78
+ }
79
+
80
+ return (
81
+ <span
82
+ ref={ref}
83
+ onMouseEnter={handleMouseEnter}
84
+ onMouseLeave={handleMouseLeave}
85
+ onFocus={handleFocus}
86
+ onBlur={handleBlur}
87
+ tabIndex={0}
88
+ {...props}
89
+ >
90
+ {children}
91
+ </span>
92
+ )
93
+ }
94
+ )
95
+ TooltipTrigger.displayName = "TooltipTrigger"
96
+
97
+ const TooltipContent = React.forwardRef<
98
+ HTMLDivElement,
99
+ React.HTMLAttributes<HTMLDivElement>
100
+ >(({ className, children, ...props }, ref) => {
101
+ const context = React.useContext(TooltipContext)
102
+ if (!context) throw new Error("TooltipContent must be used within Tooltip")
103
+
104
+ if (!context.open) return null
105
+
106
+ return (
107
+ <div
108
+ ref={ref}
109
+ role="tooltip"
110
+ className={cn(
111
+ "absolute left-1/2 bottom-full z-50 mb-2 -translate-x-1/2 overflow-hidden rounded-md bg-primary px-3 py-1.5 text-xs text-primary-foreground animate-in fade-in-0 zoom-in-95",
112
+ className
113
+ )}
114
+ {...props}
115
+ >
116
+ {children}
117
+ </div>
118
+ )
119
+ })
120
+ TooltipContent.displayName = "TooltipContent"
121
+
122
+ export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider }