@srcroot/ui 0.0.55 → 0.0.58

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 (107) hide show
  1. package/README.md +151 -151
  2. package/dist/index.d.ts +0 -0
  3. package/dist/index.js +120 -93
  4. package/package.json +7 -2
  5. package/src/registry/analytics/google-analytics.tsx +36 -39
  6. package/src/registry/analytics/google-tag-manager.tsx +62 -65
  7. package/src/registry/analytics/meta-pixel.tsx +44 -47
  8. package/src/registry/analytics/microsoft-clarity.tsx +31 -34
  9. package/src/registry/analytics/tiktok-pixel.tsx +34 -37
  10. package/src/registry/lib/utils.ts +0 -0
  11. package/src/registry/themes/v3/blue.css +157 -157
  12. package/src/registry/themes/v3/glass.css +153 -153
  13. package/src/registry/themes/v3/gray.css +157 -157
  14. package/src/registry/themes/v3/green.css +157 -157
  15. package/src/registry/themes/v3/neutral.css +157 -157
  16. package/src/registry/themes/v3/orange.css +157 -157
  17. package/src/registry/themes/v3/rose.css +157 -157
  18. package/src/registry/themes/v3/slate.css +157 -157
  19. package/src/registry/themes/v3/stone.css +157 -157
  20. package/src/registry/themes/v3/violet.css +186 -186
  21. package/src/registry/themes/v3/zinc.css +157 -157
  22. package/src/registry/themes/v4/blue.css +184 -184
  23. package/src/registry/themes/v4/glass.css +180 -180
  24. package/src/registry/themes/v4/gray.css +184 -184
  25. package/src/registry/themes/v4/green.css +184 -184
  26. package/src/registry/themes/v4/neutral.css +184 -184
  27. package/src/registry/themes/v4/orange.css +184 -184
  28. package/src/registry/themes/v4/rose.css +184 -184
  29. package/src/registry/themes/v4/slate.css +184 -184
  30. package/src/registry/themes/v4/stone.css +184 -184
  31. package/src/registry/themes/v4/violet.css +184 -184
  32. package/src/registry/themes/v4/zinc.css +184 -184
  33. package/src/registry/ui/accordion.tsx +164 -165
  34. package/src/registry/ui/alert-dialog.tsx +213 -214
  35. package/src/registry/ui/alert.tsx +73 -76
  36. package/src/registry/ui/aspect-ratio.tsx +44 -47
  37. package/src/registry/ui/avatar.tsx +96 -97
  38. package/src/registry/ui/badge.tsx +52 -55
  39. package/src/registry/ui/breadcrumb.tsx +147 -150
  40. package/src/registry/ui/button-group.tsx +64 -67
  41. package/src/registry/ui/button.tsx +71 -72
  42. package/src/registry/ui/calendar.tsx +514 -515
  43. package/src/registry/ui/card.tsx +88 -91
  44. package/src/registry/ui/carousel.tsx +214 -214
  45. package/src/registry/ui/chart.tsx +373 -373
  46. package/src/registry/ui/chatbot.tsx +86 -13
  47. package/src/registry/ui/checkbox.tsx +93 -94
  48. package/src/registry/ui/collapsible.tsx +107 -108
  49. package/src/registry/ui/combobox.tsx +171 -171
  50. package/src/registry/ui/command.tsx +300 -300
  51. package/src/registry/ui/container.tsx +44 -47
  52. package/src/registry/ui/context-menu.tsx +221 -221
  53. package/src/registry/ui/date-picker.tsx +228 -228
  54. package/src/registry/ui/dialog.tsx +269 -270
  55. package/src/registry/ui/drawer.tsx +10 -4
  56. package/src/registry/ui/dropdown-menu.tsx +529 -530
  57. package/src/registry/ui/empty-state.tsx +0 -2
  58. package/src/registry/ui/file-upload.tsx +0 -0
  59. package/src/registry/ui/floating-dock.tsx +0 -0
  60. package/src/registry/ui/form-field.tsx +91 -94
  61. package/src/registry/ui/google-analytics.tsx +38 -0
  62. package/src/registry/ui/google-tag-manager.tsx +64 -0
  63. package/src/registry/ui/hover-card.tsx +223 -223
  64. package/src/registry/ui/image.tsx +144 -147
  65. package/src/registry/ui/input-group.tsx +82 -85
  66. package/src/registry/ui/input.tsx +125 -125
  67. package/src/registry/ui/kbd.tsx +60 -63
  68. package/src/registry/ui/label.tsx +36 -37
  69. package/src/registry/ui/loading-spinner.tsx +108 -111
  70. package/src/registry/ui/map.tsx +0 -0
  71. package/src/registry/ui/marquee.tsx +2 -0
  72. package/src/registry/ui/menubar.tsx +246 -246
  73. package/src/registry/ui/meta-pixel.tsx +46 -0
  74. package/src/registry/ui/microsoft-clarity.tsx +33 -0
  75. package/src/registry/ui/native-select.tsx +49 -52
  76. package/src/registry/ui/otp-input.tsx +163 -155
  77. package/src/registry/ui/pagination.tsx +149 -152
  78. package/src/registry/ui/patterns.tsx +28 -0
  79. package/src/registry/ui/popover.tsx +226 -227
  80. package/src/registry/ui/progress.tsx +51 -52
  81. package/src/registry/ui/radio.tsx +99 -102
  82. package/src/registry/ui/resizable.tsx +314 -314
  83. package/src/registry/ui/scroll-animation.tsx +45 -0
  84. package/src/registry/ui/scroll-area.tsx +121 -122
  85. package/src/registry/ui/scroll-to-top.tsx +0 -0
  86. package/src/registry/ui/search.tsx +162 -150
  87. package/src/registry/ui/select.tsx +292 -293
  88. package/src/registry/ui/separator.tsx +46 -47
  89. package/src/registry/ui/sheet.tsx +6 -3
  90. package/src/registry/ui/sidebar.tsx +628 -628
  91. package/src/registry/ui/skeleton.tsx +26 -29
  92. package/src/registry/ui/slider.tsx +196 -197
  93. package/src/registry/ui/slot.tsx +69 -72
  94. package/src/registry/ui/star-rating.tsx +146 -134
  95. package/src/registry/ui/switch.tsx +72 -73
  96. package/src/registry/ui/table-of-contents.tsx +96 -96
  97. package/src/registry/ui/table.tsx +138 -139
  98. package/src/registry/ui/tabs.tsx +124 -125
  99. package/src/registry/ui/text.tsx +61 -64
  100. package/src/registry/ui/textarea.tsx +41 -42
  101. package/src/registry/ui/theme-switcher.tsx +66 -66
  102. package/src/registry/ui/tiktok-pixel.tsx +36 -0
  103. package/src/registry/ui/toast.tsx +97 -98
  104. package/src/registry/ui/toggle-group.tsx +129 -129
  105. package/src/registry/ui/toggle.tsx +72 -72
  106. package/src/registry/ui/tooltip.tsx +143 -144
  107. package/src/registry/ui/whatsapp.tsx +0 -0
@@ -1,147 +1,144 @@
1
- "use client"
2
-
3
- import * as React from "react"
4
- import { cva, type VariantProps } from "class-variance-authority"
5
- import { cn } from "@/lib/utils"
6
-
7
- const imageVariants = cva("", {
8
- variants: {
9
- rounded: {
10
- none: "rounded-none",
11
- sm: "rounded-sm",
12
- default: "rounded-md",
13
- md: "rounded-md",
14
- lg: "rounded-lg",
15
- xl: "rounded-xl",
16
- full: "rounded-full",
17
- },
18
- objectFit: {
19
- cover: "object-cover",
20
- contain: "object-contain",
21
- fill: "object-fill",
22
- none: "object-none",
23
- },
24
- },
25
- defaultVariants: {
26
- rounded: "default",
27
- objectFit: "cover",
28
- },
29
- })
30
-
31
- type ImageVariants = VariantProps<typeof imageVariants>
32
-
33
- interface ImageProps
34
- extends Omit<React.ImgHTMLAttributes<HTMLImageElement>, "onLoad" | "onError">,
35
- ImageVariants {
36
- /** Fallback content or URL when image fails to load */
37
- fallback?: React.ReactNode | string
38
- /** Show skeleton loading state */
39
- showSkeleton?: boolean
40
- /** Aspect ratio (width/height) */
41
- aspectRatio?: number
42
- }
43
-
44
- /**
45
- * Enhanced Image with loading states and fallback
46
- *
47
- * @example
48
- * <Image src="/photo.jpg" alt="Photo" aspectRatio={16/9} />
49
- * <Image src="/avatar.jpg" alt="User" rounded="full" fallback="JD" />
50
- */
51
- const Image = React.forwardRef<HTMLImageElement, ImageProps>(
52
- (
53
- {
54
- className,
55
- src,
56
- alt,
57
- fallback,
58
- showSkeleton = true,
59
- aspectRatio,
60
- rounded,
61
- objectFit,
62
- style,
63
- ...props
64
- },
65
- ref
66
- ) => {
67
- const [status, setStatus] = React.useState<"loading" | "loaded" | "error">("loading")
68
-
69
- React.useEffect(() => {
70
- setStatus("loading")
71
- }, [src])
72
-
73
- const containerStyle: React.CSSProperties = aspectRatio
74
- ? { paddingBottom: `${100 / aspectRatio}%`, ...(style || {}) }
75
- : (style || {})
76
-
77
- // Render fallback
78
- if (status === "error" && fallback) {
79
- if (typeof fallback === "string") {
80
- // If fallback is a string, check if it's a URL or initials
81
- if (fallback.startsWith("http") || fallback.startsWith("/")) {
82
- return (
83
- <img
84
- ref={ref}
85
- src={fallback}
86
- alt={alt}
87
- className={cn(imageVariants({ rounded, objectFit }), className)}
88
- style={style}
89
- {...props}
90
- />
91
- )
92
- }
93
- // Initials fallback
94
- return (
95
- <div
96
- className={cn(
97
- "flex items-center justify-center bg-muted text-muted-foreground font-medium",
98
- imageVariants({ rounded }),
99
- className
100
- )}
101
- style={containerStyle}
102
- >
103
- {fallback}
104
- </div>
105
- )
106
- }
107
- return <>{fallback}</>
108
- }
109
-
110
- return (
111
- <div
112
- className={cn("relative overflow-hidden", aspectRatio && "w-full")}
113
- style={aspectRatio ? { paddingBottom: `${100 / aspectRatio}%` } : undefined}
114
- >
115
- {/* Skeleton */}
116
- {status === "loading" && showSkeleton && (
117
- <div
118
- className={cn(
119
- "absolute inset-0 animate-pulse bg-muted",
120
- imageVariants({ rounded })
121
- )}
122
- />
123
- )}
124
-
125
- <img
126
- ref={ref}
127
- src={src}
128
- alt={alt}
129
- className={cn(
130
- imageVariants({ rounded, objectFit }),
131
- aspectRatio && "absolute inset-0 h-full w-full",
132
- status === "loading" && "opacity-0",
133
- status === "loaded" && "opacity-100 transition-opacity duration-300",
134
- className
135
- )}
136
- onLoad={() => setStatus("loaded")}
137
- onError={() => setStatus("error")}
138
- {...props}
139
- />
140
- </div>
141
- )
142
- }
143
- )
144
- Image.displayName = "Image"
145
-
146
- export { Image, imageVariants }
147
-
1
+ import * as React from "react"
2
+ import { cva, type VariantProps } from "class-variance-authority"
3
+ import { cn } from "@/lib/utils"
4
+
5
+ const imageVariants = cva("", {
6
+ variants: {
7
+ rounded: {
8
+ none: "rounded-none",
9
+ sm: "rounded-sm",
10
+ default: "rounded-md",
11
+ md: "rounded-md",
12
+ lg: "rounded-lg",
13
+ xl: "rounded-xl",
14
+ full: "rounded-full",
15
+ },
16
+ objectFit: {
17
+ cover: "object-cover",
18
+ contain: "object-contain",
19
+ fill: "object-fill",
20
+ none: "object-none",
21
+ },
22
+ },
23
+ defaultVariants: {
24
+ rounded: "default",
25
+ objectFit: "cover",
26
+ },
27
+ })
28
+
29
+ type ImageVariants = VariantProps<typeof imageVariants>
30
+
31
+ interface ImageProps
32
+ extends Omit<React.ImgHTMLAttributes<HTMLImageElement>, "onLoad" | "onError">,
33
+ ImageVariants {
34
+ /** Fallback content or URL when image fails to load */
35
+ fallback?: React.ReactNode | string
36
+ /** Show skeleton loading state */
37
+ showSkeleton?: boolean
38
+ /** Aspect ratio (width/height) */
39
+ aspectRatio?: number
40
+ }
41
+
42
+ /**
43
+ * Enhanced Image with loading states and fallback
44
+ *
45
+ * @example
46
+ * <Image src="/photo.jpg" alt="Photo" aspectRatio={16/9} />
47
+ * <Image src="/avatar.jpg" alt="User" rounded="full" fallback="JD" />
48
+ */
49
+ const Image = React.forwardRef<HTMLImageElement, ImageProps>(
50
+ (
51
+ {
52
+ className,
53
+ src,
54
+ alt,
55
+ fallback,
56
+ showSkeleton = true,
57
+ aspectRatio,
58
+ rounded,
59
+ objectFit,
60
+ style,
61
+ ...props
62
+ },
63
+ ref
64
+ ) => {
65
+ const [status, setStatus] = React.useState<"loading" | "loaded" | "error">("loading")
66
+
67
+ React.useEffect(() => {
68
+ setStatus("loading")
69
+ }, [src])
70
+
71
+ const containerStyle: React.CSSProperties = aspectRatio
72
+ ? { paddingBottom: `${100 / aspectRatio}%`, ...(style || {}) }
73
+ : (style || {})
74
+
75
+ // Render fallback
76
+ if (status === "error" && fallback) {
77
+ if (typeof fallback === "string") {
78
+ // If fallback is a string, check if it's a URL or initials
79
+ if (fallback.startsWith("http") || fallback.startsWith("/")) {
80
+ return (
81
+ <img
82
+ ref={ref}
83
+ src={fallback}
84
+ alt={alt}
85
+ className={cn(imageVariants({ rounded, objectFit }), className)}
86
+ style={style}
87
+ {...props}
88
+ />
89
+ )
90
+ }
91
+ // Initials fallback
92
+ return (
93
+ <div
94
+ className={cn(
95
+ "flex items-center justify-center bg-muted text-muted-foreground font-medium",
96
+ imageVariants({ rounded }),
97
+ className
98
+ )}
99
+ style={containerStyle}
100
+ >
101
+ {fallback}
102
+ </div>
103
+ )
104
+ }
105
+ return <>{fallback}</>
106
+ }
107
+
108
+ return (
109
+ <div
110
+ className={cn("relative overflow-hidden", aspectRatio && "w-full")}
111
+ style={aspectRatio ? { paddingBottom: `${100 / aspectRatio}%` } : undefined}
112
+ >
113
+ {/* Skeleton */}
114
+ {status === "loading" && showSkeleton && (
115
+ <div
116
+ className={cn(
117
+ "absolute inset-0 animate-pulse bg-muted",
118
+ imageVariants({ rounded })
119
+ )}
120
+ />
121
+ )}
122
+
123
+ <img
124
+ ref={ref}
125
+ src={src}
126
+ alt={alt}
127
+ className={cn(
128
+ imageVariants({ rounded, objectFit }),
129
+ aspectRatio && "absolute inset-0 h-full w-full",
130
+ status === "loading" && "opacity-0",
131
+ status === "loaded" && "opacity-100 transition-opacity duration-300",
132
+ className
133
+ )}
134
+ onLoad={() => setStatus("loaded")}
135
+ onError={() => setStatus("error")}
136
+ {...props}
137
+ />
138
+ </div>
139
+ )
140
+ }
141
+ )
142
+ Image.displayName = "Image"
143
+
144
+ export { Image, imageVariants }
@@ -1,85 +1,82 @@
1
- "use client"
2
-
3
- import * as React from "react"
4
- import { cn } from "@/lib/utils"
5
-
6
- const InputGroup = React.forwardRef<
7
- HTMLDivElement,
8
- React.HTMLAttributes<HTMLDivElement> & { error?: boolean }
9
- >(({ className, children, error, ...props }, ref) => {
10
- return (
11
- <div
12
- ref={ref}
13
- className={cn(
14
- "flex w-full items-center rounded-md",
15
- "focus-within:ring-1 focus-within:ring-ring",
16
- error && "focus-within:ring-destructive focus-within:border-destructive",
17
- // First child: rounded-l only, remove right border if not last
18
- "[&>*:first-child]:rounded-r-none",
19
- // Last child: rounded-r only, remove left border if not first
20
- "[&>*:last-child]:rounded-l-none",
21
- // Middle children: no rounding
22
- "[&>*:not(:first-child):not(:last-child)]:rounded-none",
23
- // Negative margin to merge borders
24
- "[&>*:not(:first-child)]:-ml-px",
25
- // Bring hovered element to front
26
- "[&>*:hover]:z-10",
27
- className
28
- )}
29
- {...props}
30
- >
31
- {React.Children.map(children, (child) => {
32
- if (!React.isValidElement(child)) return child
33
- const element = child as React.ReactElement<{ className?: string, error?: boolean }>
34
-
35
- // Only pass error to custom components, not DOM elements
36
- const additionalProps: { className: string; error?: boolean } = {
37
- className: cn(
38
- element.props.className,
39
- "focus-visible:ring-0 focus-visible:ring-offset-0",
40
- error && "border-destructive focus-visible:ring-destructive"
41
- )
42
- }
43
-
44
- if (typeof element.type !== "string") {
45
- additionalProps.error = error
46
- }
47
-
48
- return React.cloneElement(element, additionalProps)
49
- })}
50
- </div>
51
- )
52
- })
53
- InputGroup.displayName = "InputGroup"
54
-
55
- const InputAddon = React.forwardRef<
56
- HTMLDivElement,
57
- React.HTMLAttributes<HTMLDivElement> & { error?: boolean }
58
- >(({ className, children, error, ...props }, ref) => {
59
- return (
60
- <div
61
- ref={ref}
62
- className={cn(
63
- "flex h-9 items-center justify-center rounded-md border border-input bg-muted px-3 text-sm text-muted-foreground shadow-sm",
64
- error && "border-destructive",
65
- className
66
- )}
67
- {...props}
68
- >
69
- {React.Children.map(children, (child: React.ReactNode) => {
70
- if (!React.isValidElement(child)) return child
71
- const element = child as React.ReactElement<{ className?: string }>
72
- return React.cloneElement(element, {
73
- className: cn(
74
- element.props.className,
75
- "focus-visible:ring-0 focus-visible:ring-offset-0"
76
- ),
77
- })
78
- })}
79
- </div>
80
- )
81
- })
82
- InputAddon.displayName = "InputAddon"
83
-
84
- export { InputGroup, InputAddon }
85
-
1
+ import * as React from "react"
2
+ import { cn } from "@/lib/utils"
3
+
4
+ const InputGroup = React.forwardRef<
5
+ HTMLDivElement,
6
+ React.HTMLAttributes<HTMLDivElement> & { error?: boolean }
7
+ >(({ className, children, error, ...props }, ref) => {
8
+ return (
9
+ <div
10
+ ref={ref}
11
+ className={cn(
12
+ "flex w-full items-center rounded-md",
13
+ "focus-within:ring-1 focus-within:ring-ring",
14
+ error && "focus-within:ring-destructive focus-within:border-destructive",
15
+ // First child: rounded-l only, remove right border if not last
16
+ "[&>*:first-child]:rounded-r-none",
17
+ // Last child: rounded-r only, remove left border if not first
18
+ "[&>*:last-child]:rounded-l-none",
19
+ // Middle children: no rounding
20
+ "[&>*:not(:first-child):not(:last-child)]:rounded-none",
21
+ // Negative margin to merge borders
22
+ "[&>*:not(:first-child)]:-ml-px",
23
+ // Bring hovered element to front
24
+ "[&>*:hover]:z-10",
25
+ className
26
+ )}
27
+ {...props}
28
+ >
29
+ {React.Children.map(children, (child) => {
30
+ if (!React.isValidElement(child)) return child
31
+ const element = child as React.ReactElement<{ className?: string, error?: boolean }>
32
+
33
+ // Only pass error to custom components, not DOM elements
34
+ const additionalProps: { className: string; error?: boolean } = {
35
+ className: cn(
36
+ element.props.className,
37
+ "focus-visible:ring-0 focus-visible:ring-offset-0",
38
+ error && "border-destructive focus-visible:ring-destructive"
39
+ )
40
+ }
41
+
42
+ if (typeof element.type !== "string") {
43
+ additionalProps.error = error
44
+ }
45
+
46
+ return React.cloneElement(element, additionalProps)
47
+ })}
48
+ </div>
49
+ )
50
+ })
51
+ InputGroup.displayName = "InputGroup"
52
+
53
+ const InputAddon = React.forwardRef<
54
+ HTMLDivElement,
55
+ React.HTMLAttributes<HTMLDivElement> & { error?: boolean }
56
+ >(({ className, children, error, ...props }, ref) => {
57
+ return (
58
+ <div
59
+ ref={ref}
60
+ className={cn(
61
+ "flex h-9 items-center justify-center rounded-md border border-input bg-muted px-3 text-sm text-muted-foreground shadow-sm",
62
+ error && "border-destructive",
63
+ className
64
+ )}
65
+ {...props}
66
+ >
67
+ {React.Children.map(children, (child: React.ReactNode) => {
68
+ if (!React.isValidElement(child)) return child
69
+ const element = child as React.ReactElement<{ className?: string }>
70
+ return React.cloneElement(element, {
71
+ className: cn(
72
+ element.props.className,
73
+ "focus-visible:ring-0 focus-visible:ring-offset-0"
74
+ ),
75
+ })
76
+ })}
77
+ </div>
78
+ )
79
+ })
80
+ InputAddon.displayName = "InputAddon"
81
+
82
+ export { InputGroup, InputAddon }