@srcroot/ui 0.0.54 → 0.0.56
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +151 -151
- package/dist/index.d.ts +0 -0
- package/dist/index.js +55 -1
- package/package.json +7 -2
- package/src/registry/analytics/google-analytics.tsx +36 -39
- package/src/registry/analytics/google-tag-manager.tsx +62 -65
- package/src/registry/analytics/meta-pixel.tsx +44 -47
- package/src/registry/analytics/microsoft-clarity.tsx +31 -34
- package/src/registry/analytics/tiktok-pixel.tsx +34 -37
- package/src/registry/lib/utils.ts +0 -0
- package/src/registry/themes/v3/blue.css +157 -157
- package/src/registry/themes/v3/glass.css +153 -153
- package/src/registry/themes/v3/gray.css +157 -157
- package/src/registry/themes/v3/green.css +157 -157
- package/src/registry/themes/v3/neutral.css +157 -157
- package/src/registry/themes/v3/orange.css +157 -157
- package/src/registry/themes/v3/rose.css +157 -157
- package/src/registry/themes/v3/slate.css +157 -157
- package/src/registry/themes/v3/stone.css +157 -157
- package/src/registry/themes/v3/violet.css +186 -186
- package/src/registry/themes/v3/zinc.css +157 -157
- package/src/registry/themes/v4/blue.css +184 -184
- package/src/registry/themes/v4/glass.css +180 -180
- package/src/registry/themes/v4/gray.css +184 -184
- package/src/registry/themes/v4/green.css +184 -184
- package/src/registry/themes/v4/neutral.css +184 -184
- package/src/registry/themes/v4/orange.css +184 -184
- package/src/registry/themes/v4/rose.css +184 -184
- package/src/registry/themes/v4/slate.css +184 -184
- package/src/registry/themes/v4/stone.css +184 -184
- package/src/registry/themes/v4/violet.css +184 -184
- package/src/registry/themes/v4/zinc.css +184 -184
- package/src/registry/ui/accordion.tsx +164 -165
- package/src/registry/ui/alert-dialog.tsx +213 -214
- package/src/registry/ui/alert.tsx +73 -76
- package/src/registry/ui/aspect-ratio.tsx +44 -47
- package/src/registry/ui/avatar.tsx +96 -97
- package/src/registry/ui/badge.tsx +52 -55
- package/src/registry/ui/breadcrumb.tsx +147 -150
- package/src/registry/ui/button-group.tsx +64 -67
- package/src/registry/ui/button.tsx +71 -72
- package/src/registry/ui/calendar.tsx +514 -515
- package/src/registry/ui/card.tsx +88 -91
- package/src/registry/ui/carousel.tsx +214 -214
- package/src/registry/ui/chart.tsx +373 -373
- package/src/registry/ui/chatbot.tsx +86 -13
- package/src/registry/ui/checkbox.tsx +93 -94
- package/src/registry/ui/collapsible.tsx +107 -108
- package/src/registry/ui/combobox.tsx +171 -171
- package/src/registry/ui/command.tsx +300 -300
- package/src/registry/ui/container.tsx +44 -47
- package/src/registry/ui/context-menu.tsx +221 -221
- package/src/registry/ui/date-picker.tsx +228 -228
- package/src/registry/ui/dialog.tsx +269 -270
- package/src/registry/ui/drawer.tsx +10 -4
- package/src/registry/ui/dropdown-menu.tsx +529 -530
- package/src/registry/ui/empty-state.tsx +0 -2
- package/src/registry/ui/file-upload.tsx +0 -0
- package/src/registry/ui/floating-dock.tsx +0 -0
- package/src/registry/ui/form-field.tsx +91 -94
- package/src/registry/ui/google-analytics.tsx +38 -0
- package/src/registry/ui/google-tag-manager.tsx +64 -0
- package/src/registry/ui/hover-card.tsx +223 -223
- package/src/registry/ui/image.tsx +144 -147
- package/src/registry/ui/input-group.tsx +82 -85
- package/src/registry/ui/input.tsx +125 -125
- package/src/registry/ui/kbd.tsx +60 -63
- package/src/registry/ui/label.tsx +36 -37
- package/src/registry/ui/loading-spinner.tsx +108 -111
- package/src/registry/ui/map.tsx +0 -0
- package/src/registry/ui/marquee.tsx +2 -0
- package/src/registry/ui/menubar.tsx +246 -246
- package/src/registry/ui/meta-pixel.tsx +46 -0
- package/src/registry/ui/microsoft-clarity.tsx +33 -0
- package/src/registry/ui/native-select.tsx +49 -52
- package/src/registry/ui/otp-input.tsx +152 -155
- package/src/registry/ui/pagination.tsx +149 -152
- package/src/registry/ui/patterns.tsx +28 -0
- package/src/registry/ui/popover.tsx +226 -227
- package/src/registry/ui/progress.tsx +51 -52
- package/src/registry/ui/radio.tsx +99 -102
- package/src/registry/ui/resizable.tsx +314 -314
- package/src/registry/ui/scroll-animation.tsx +45 -0
- package/src/registry/ui/scroll-area.tsx +121 -122
- package/src/registry/ui/scroll-to-top.tsx +0 -0
- package/src/registry/ui/search.tsx +147 -150
- package/src/registry/ui/select.tsx +292 -293
- package/src/registry/ui/separator.tsx +46 -47
- package/src/registry/ui/sheet.tsx +6 -3
- package/src/registry/ui/sidebar.tsx +628 -628
- package/src/registry/ui/skeleton.tsx +26 -29
- package/src/registry/ui/slider.tsx +196 -197
- package/src/registry/ui/slot.tsx +69 -72
- package/src/registry/ui/star-rating.tsx +131 -134
- package/src/registry/ui/switch.tsx +72 -73
- package/src/registry/ui/table-of-contents.tsx +96 -96
- package/src/registry/ui/table.tsx +138 -139
- package/src/registry/ui/tabs.tsx +124 -125
- package/src/registry/ui/text.tsx +61 -64
- package/src/registry/ui/textarea.tsx +41 -42
- package/src/registry/ui/theme-switcher.tsx +66 -66
- package/src/registry/ui/tiktok-pixel.tsx +36 -0
- package/src/registry/ui/toast.tsx +97 -98
- package/src/registry/ui/toggle-group.tsx +129 -129
- package/src/registry/ui/toggle.tsx +72 -72
- package/src/registry/ui/tooltip.tsx +143 -144
- package/src/registry/ui/whatsapp.tsx +0 -0
|
@@ -1,171 +1,171 @@
|
|
|
1
|
-
"use client"
|
|
2
|
-
|
|
3
|
-
import * as React from "react"
|
|
4
|
-
import { LuCheck, LuChevronsUpDown, LuX } from "react-icons/lu"
|
|
5
|
-
|
|
6
|
-
import { cn } from "@/lib/utils"
|
|
7
|
-
import { Button } from "@/components/ui/button"
|
|
8
|
-
import {
|
|
9
|
-
Command,
|
|
10
|
-
CommandEmpty,
|
|
11
|
-
CommandGroup,
|
|
12
|
-
CommandInput,
|
|
13
|
-
CommandItem,
|
|
14
|
-
CommandList,
|
|
15
|
-
} from "@/components/ui/command"
|
|
16
|
-
import {
|
|
17
|
-
Popover,
|
|
18
|
-
PopoverContent,
|
|
19
|
-
PopoverTrigger,
|
|
20
|
-
} from "@/components/ui/popover"
|
|
21
|
-
import { Badge } from "@/components/ui/badge"
|
|
22
|
-
|
|
23
|
-
export type ComboboxOption = {
|
|
24
|
-
value: string
|
|
25
|
-
label: string
|
|
26
|
-
icon?: React.ComponentType<{ className?: string }>
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
interface ComboboxProps {
|
|
30
|
-
options: ComboboxOption[]
|
|
31
|
-
value?: string | string[]
|
|
32
|
-
onValueChange?: (value: string | string[]) => void
|
|
33
|
-
placeholder?: string
|
|
34
|
-
searchPlaceholder?: string
|
|
35
|
-
emptyMessage?: string
|
|
36
|
-
multiple?: boolean
|
|
37
|
-
className?: string
|
|
38
|
-
disabled?: boolean
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
export function Combobox({
|
|
42
|
-
options,
|
|
43
|
-
value,
|
|
44
|
-
onValueChange,
|
|
45
|
-
placeholder = "Select option...",
|
|
46
|
-
searchPlaceholder = "Search...",
|
|
47
|
-
emptyMessage = "No option found.",
|
|
48
|
-
multiple = false,
|
|
49
|
-
className,
|
|
50
|
-
disabled = false,
|
|
51
|
-
}: ComboboxProps) {
|
|
52
|
-
const [open, setOpen] = React.useState(false)
|
|
53
|
-
|
|
54
|
-
// Helper to handle selection
|
|
55
|
-
const handleSelect = React.useCallback(
|
|
56
|
-
(currentValue: string) => {
|
|
57
|
-
if (multiple) {
|
|
58
|
-
const currentValues = Array.isArray(value) ? value : []
|
|
59
|
-
const newValues = currentValues.includes(currentValue)
|
|
60
|
-
? currentValues.filter((v) => v !== currentValue)
|
|
61
|
-
: [...currentValues, currentValue]
|
|
62
|
-
onValueChange?.(newValues)
|
|
63
|
-
} else {
|
|
64
|
-
onValueChange?.(currentValue === value ? "" : currentValue)
|
|
65
|
-
setOpen(false)
|
|
66
|
-
}
|
|
67
|
-
},
|
|
68
|
-
[multiple, value, onValueChange]
|
|
69
|
-
)
|
|
70
|
-
|
|
71
|
-
// Derived state for display
|
|
72
|
-
const selectedOptions = React.useMemo(() => {
|
|
73
|
-
if (multiple) {
|
|
74
|
-
const currentValues = Array.isArray(value) ? value : []
|
|
75
|
-
return currentValues
|
|
76
|
-
.map((v) => options.find((opt) => opt.value === v))
|
|
77
|
-
.filter(Boolean) as ComboboxOption[]
|
|
78
|
-
} else {
|
|
79
|
-
const option = options.find((opt) => opt.value === value)
|
|
80
|
-
return option ? [option] : []
|
|
81
|
-
}
|
|
82
|
-
}, [multiple, value, options])
|
|
83
|
-
|
|
84
|
-
return (
|
|
85
|
-
<Popover open={open} onOpenChange={setOpen}>
|
|
86
|
-
<PopoverTrigger asChild>
|
|
87
|
-
<Button
|
|
88
|
-
variant="outline"
|
|
89
|
-
role="combobox"
|
|
90
|
-
aria-expanded={open}
|
|
91
|
-
className={cn("w-full justify-between h-auto min-h-10", className)}
|
|
92
|
-
disabled={disabled}
|
|
93
|
-
>
|
|
94
|
-
<div className="flex gap-1 flex-wrap items-center text-left">
|
|
95
|
-
{selectedOptions.length > 0 ? (
|
|
96
|
-
multiple ? (
|
|
97
|
-
selectedOptions.length > 3 ? (
|
|
98
|
-
<Badge variant="secondary" className="rounded-sm px-1 font-normal">
|
|
99
|
-
{selectedOptions.length} selected
|
|
100
|
-
</Badge>
|
|
101
|
-
) : (
|
|
102
|
-
selectedOptions.map((opt) => {
|
|
103
|
-
const Icon = opt.icon
|
|
104
|
-
return (
|
|
105
|
-
<Badge
|
|
106
|
-
variant="secondary"
|
|
107
|
-
key={opt.value}
|
|
108
|
-
className="rounded-sm px-1 font-normal items-center gap-1"
|
|
109
|
-
onClick={(e: React.MouseEvent) => {
|
|
110
|
-
e.stopPropagation()
|
|
111
|
-
handleSelect(opt.value)
|
|
112
|
-
}}
|
|
113
|
-
>
|
|
114
|
-
{Icon && <Icon className="h-3 w-3" />}
|
|
115
|
-
{opt.label}
|
|
116
|
-
<LuX className="h-3 w-3 text-muted-foreground hover:text-foreground ml-0.5" />
|
|
117
|
-
</Badge>
|
|
118
|
-
)
|
|
119
|
-
})
|
|
120
|
-
)
|
|
121
|
-
) : (
|
|
122
|
-
<div className="flex items-center gap-2">
|
|
123
|
-
{(() => {
|
|
124
|
-
const Icon = selectedOptions[0].icon
|
|
125
|
-
return Icon ? <Icon className="h-4 w-4 text-muted-foreground" /> : null
|
|
126
|
-
})()}
|
|
127
|
-
<span>{selectedOptions[0].label}</span>
|
|
128
|
-
</div>
|
|
129
|
-
)
|
|
130
|
-
) : (
|
|
131
|
-
<span className="text-muted-foreground">{placeholder}</span>
|
|
132
|
-
)}
|
|
133
|
-
</div>
|
|
134
|
-
<LuChevronsUpDown className="ml-2 h-4 w-4 shrink-0 opacity-50" />
|
|
135
|
-
</Button>
|
|
136
|
-
</PopoverTrigger>
|
|
137
|
-
<PopoverContent className="w-full min-w-[200px] p-0">
|
|
138
|
-
<Command>
|
|
139
|
-
<CommandInput placeholder={searchPlaceholder} />
|
|
140
|
-
<CommandList>
|
|
141
|
-
<CommandEmpty>{emptyMessage}</CommandEmpty>
|
|
142
|
-
<CommandGroup>
|
|
143
|
-
{options.map((option) => (
|
|
144
|
-
<CommandItem
|
|
145
|
-
key={option.value}
|
|
146
|
-
value={option.label}
|
|
147
|
-
onSelect={() => handleSelect(option.value)}
|
|
148
|
-
>
|
|
149
|
-
<LuCheck
|
|
150
|
-
className={cn(
|
|
151
|
-
"mr-2 h-4 w-4",
|
|
152
|
-
multiple
|
|
153
|
-
? (Array.isArray(value) && value.includes(option.value)
|
|
154
|
-
? "opacity-100"
|
|
155
|
-
: "opacity-0")
|
|
156
|
-
: value === option.value
|
|
157
|
-
? "opacity-100"
|
|
158
|
-
: "opacity-0"
|
|
159
|
-
)}
|
|
160
|
-
/>
|
|
161
|
-
{option.icon && <option.icon className="mr-2 h-4 w-4 text-muted-foreground" />}
|
|
162
|
-
{option.label}
|
|
163
|
-
</CommandItem>
|
|
164
|
-
))}
|
|
165
|
-
</CommandGroup>
|
|
166
|
-
</CommandList>
|
|
167
|
-
</Command>
|
|
168
|
-
</PopoverContent>
|
|
169
|
-
</Popover>
|
|
170
|
-
)
|
|
171
|
-
}
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
import * as React from "react"
|
|
4
|
+
import { LuCheck, LuChevronsUpDown, LuX } from "react-icons/lu"
|
|
5
|
+
|
|
6
|
+
import { cn } from "@/lib/utils"
|
|
7
|
+
import { Button } from "@/components/ui/button"
|
|
8
|
+
import {
|
|
9
|
+
Command,
|
|
10
|
+
CommandEmpty,
|
|
11
|
+
CommandGroup,
|
|
12
|
+
CommandInput,
|
|
13
|
+
CommandItem,
|
|
14
|
+
CommandList,
|
|
15
|
+
} from "@/components/ui/command"
|
|
16
|
+
import {
|
|
17
|
+
Popover,
|
|
18
|
+
PopoverContent,
|
|
19
|
+
PopoverTrigger,
|
|
20
|
+
} from "@/components/ui/popover"
|
|
21
|
+
import { Badge } from "@/components/ui/badge"
|
|
22
|
+
|
|
23
|
+
export type ComboboxOption = {
|
|
24
|
+
value: string
|
|
25
|
+
label: string
|
|
26
|
+
icon?: React.ComponentType<{ className?: string }>
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
interface ComboboxProps {
|
|
30
|
+
options: ComboboxOption[]
|
|
31
|
+
value?: string | string[]
|
|
32
|
+
onValueChange?: (value: string | string[]) => void
|
|
33
|
+
placeholder?: string
|
|
34
|
+
searchPlaceholder?: string
|
|
35
|
+
emptyMessage?: string
|
|
36
|
+
multiple?: boolean
|
|
37
|
+
className?: string
|
|
38
|
+
disabled?: boolean
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function Combobox({
|
|
42
|
+
options,
|
|
43
|
+
value,
|
|
44
|
+
onValueChange,
|
|
45
|
+
placeholder = "Select option...",
|
|
46
|
+
searchPlaceholder = "Search...",
|
|
47
|
+
emptyMessage = "No option found.",
|
|
48
|
+
multiple = false,
|
|
49
|
+
className,
|
|
50
|
+
disabled = false,
|
|
51
|
+
}: ComboboxProps) {
|
|
52
|
+
const [open, setOpen] = React.useState(false)
|
|
53
|
+
|
|
54
|
+
// Helper to handle selection
|
|
55
|
+
const handleSelect = React.useCallback(
|
|
56
|
+
(currentValue: string) => {
|
|
57
|
+
if (multiple) {
|
|
58
|
+
const currentValues = Array.isArray(value) ? value : []
|
|
59
|
+
const newValues = currentValues.includes(currentValue)
|
|
60
|
+
? currentValues.filter((v) => v !== currentValue)
|
|
61
|
+
: [...currentValues, currentValue]
|
|
62
|
+
onValueChange?.(newValues)
|
|
63
|
+
} else {
|
|
64
|
+
onValueChange?.(currentValue === value ? "" : currentValue)
|
|
65
|
+
setOpen(false)
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
[multiple, value, onValueChange]
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
// Derived state for display
|
|
72
|
+
const selectedOptions = React.useMemo(() => {
|
|
73
|
+
if (multiple) {
|
|
74
|
+
const currentValues = Array.isArray(value) ? value : []
|
|
75
|
+
return currentValues
|
|
76
|
+
.map((v) => options.find((opt) => opt.value === v))
|
|
77
|
+
.filter(Boolean) as ComboboxOption[]
|
|
78
|
+
} else {
|
|
79
|
+
const option = options.find((opt) => opt.value === value)
|
|
80
|
+
return option ? [option] : []
|
|
81
|
+
}
|
|
82
|
+
}, [multiple, value, options])
|
|
83
|
+
|
|
84
|
+
return (
|
|
85
|
+
<Popover open={open} onOpenChange={setOpen}>
|
|
86
|
+
<PopoverTrigger asChild>
|
|
87
|
+
<Button
|
|
88
|
+
variant="outline"
|
|
89
|
+
role="combobox"
|
|
90
|
+
aria-expanded={open}
|
|
91
|
+
className={cn("w-full justify-between h-auto min-h-10", className)}
|
|
92
|
+
disabled={disabled}
|
|
93
|
+
>
|
|
94
|
+
<div className="flex gap-1 flex-wrap items-center text-left">
|
|
95
|
+
{selectedOptions.length > 0 ? (
|
|
96
|
+
multiple ? (
|
|
97
|
+
selectedOptions.length > 3 ? (
|
|
98
|
+
<Badge variant="secondary" className="rounded-sm px-1 font-normal">
|
|
99
|
+
{selectedOptions.length} selected
|
|
100
|
+
</Badge>
|
|
101
|
+
) : (
|
|
102
|
+
selectedOptions.map((opt) => {
|
|
103
|
+
const Icon = opt.icon
|
|
104
|
+
return (
|
|
105
|
+
<Badge
|
|
106
|
+
variant="secondary"
|
|
107
|
+
key={opt.value}
|
|
108
|
+
className="rounded-sm px-1 font-normal items-center gap-1"
|
|
109
|
+
onClick={(e: React.MouseEvent) => {
|
|
110
|
+
e.stopPropagation()
|
|
111
|
+
handleSelect(opt.value)
|
|
112
|
+
}}
|
|
113
|
+
>
|
|
114
|
+
{Icon && <Icon className="h-3 w-3" />}
|
|
115
|
+
{opt.label}
|
|
116
|
+
<LuX className="h-3 w-3 text-muted-foreground hover:text-foreground ml-0.5" />
|
|
117
|
+
</Badge>
|
|
118
|
+
)
|
|
119
|
+
})
|
|
120
|
+
)
|
|
121
|
+
) : (
|
|
122
|
+
<div className="flex items-center gap-2">
|
|
123
|
+
{(() => {
|
|
124
|
+
const Icon = selectedOptions[0].icon
|
|
125
|
+
return Icon ? <Icon className="h-4 w-4 text-muted-foreground" /> : null
|
|
126
|
+
})()}
|
|
127
|
+
<span>{selectedOptions[0].label}</span>
|
|
128
|
+
</div>
|
|
129
|
+
)
|
|
130
|
+
) : (
|
|
131
|
+
<span className="text-muted-foreground">{placeholder}</span>
|
|
132
|
+
)}
|
|
133
|
+
</div>
|
|
134
|
+
<LuChevronsUpDown className="ml-2 h-4 w-4 shrink-0 opacity-50" />
|
|
135
|
+
</Button>
|
|
136
|
+
</PopoverTrigger>
|
|
137
|
+
<PopoverContent className="w-full min-w-[200px] p-0">
|
|
138
|
+
<Command>
|
|
139
|
+
<CommandInput placeholder={searchPlaceholder} />
|
|
140
|
+
<CommandList>
|
|
141
|
+
<CommandEmpty>{emptyMessage}</CommandEmpty>
|
|
142
|
+
<CommandGroup>
|
|
143
|
+
{options.map((option) => (
|
|
144
|
+
<CommandItem
|
|
145
|
+
key={option.value}
|
|
146
|
+
value={option.label}
|
|
147
|
+
onSelect={() => handleSelect(option.value)}
|
|
148
|
+
>
|
|
149
|
+
<LuCheck
|
|
150
|
+
className={cn(
|
|
151
|
+
"mr-2 h-4 w-4",
|
|
152
|
+
multiple
|
|
153
|
+
? (Array.isArray(value) && value.includes(option.value)
|
|
154
|
+
? "opacity-100"
|
|
155
|
+
: "opacity-0")
|
|
156
|
+
: value === option.value
|
|
157
|
+
? "opacity-100"
|
|
158
|
+
: "opacity-0"
|
|
159
|
+
)}
|
|
160
|
+
/>
|
|
161
|
+
{option.icon && <option.icon className="mr-2 h-4 w-4 text-muted-foreground" />}
|
|
162
|
+
{option.label}
|
|
163
|
+
</CommandItem>
|
|
164
|
+
))}
|
|
165
|
+
</CommandGroup>
|
|
166
|
+
</CommandList>
|
|
167
|
+
</Command>
|
|
168
|
+
</PopoverContent>
|
|
169
|
+
</Popover>
|
|
170
|
+
)
|
|
171
|
+
}
|