@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,129 +1,129 @@
|
|
|
1
|
-
"use client"
|
|
2
|
-
|
|
3
|
-
import * as React from "react"
|
|
4
|
-
import { cn } from "@/lib/utils"
|
|
5
|
-
import { toggleVariants } from "./toggle"
|
|
6
|
-
import { type VariantProps } from "class-variance-authority"
|
|
7
|
-
|
|
8
|
-
// ToggleGroup Context
|
|
9
|
-
interface ToggleGroupContextValue {
|
|
10
|
-
type: "single" | "multiple"
|
|
11
|
-
value: string[]
|
|
12
|
-
onValueChange: (value: string) => void
|
|
13
|
-
variant?: VariantProps<typeof toggleVariants>["variant"]
|
|
14
|
-
size?: VariantProps<typeof toggleVariants>["size"]
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
const ToggleGroupContext = React.createContext<ToggleGroupContextValue | null>(null)
|
|
18
|
-
|
|
19
|
-
function useToggleGroup() {
|
|
20
|
-
const context = React.useContext(ToggleGroupContext)
|
|
21
|
-
if (!context) {
|
|
22
|
-
throw new Error("useToggleGroup must be used within a ToggleGroup")
|
|
23
|
-
}
|
|
24
|
-
return context
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
// ToggleGroup Props
|
|
28
|
-
interface ToggleGroupSingleProps {
|
|
29
|
-
type: "single"
|
|
30
|
-
value?: string
|
|
31
|
-
defaultValue?: string
|
|
32
|
-
onValueChange?: (value: string) => void
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
interface ToggleGroupMultipleProps {
|
|
36
|
-
type: "multiple"
|
|
37
|
-
value?: string[]
|
|
38
|
-
defaultValue?: string[]
|
|
39
|
-
onValueChange?: (value: string[]) => void
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
type ToggleGroupProps = (ToggleGroupSingleProps | ToggleGroupMultipleProps) &
|
|
43
|
-
React.HTMLAttributes<HTMLDivElement> &
|
|
44
|
-
VariantProps<typeof toggleVariants>
|
|
45
|
-
|
|
46
|
-
const ToggleGroup = React.forwardRef<HTMLDivElement, ToggleGroupProps>(
|
|
47
|
-
({ className, type, value: controlledValue, defaultValue, onValueChange, variant, size, children, ...props }, ref) => {
|
|
48
|
-
// Handle both single and multiple types
|
|
49
|
-
const [uncontrolledValue, setUncontrolledValue] = React.useState<string[]>(() => {
|
|
50
|
-
if (type === "single") {
|
|
51
|
-
return defaultValue ? [defaultValue as string] : []
|
|
52
|
-
}
|
|
53
|
-
return (defaultValue as string[]) || []
|
|
54
|
-
})
|
|
55
|
-
|
|
56
|
-
const value = controlledValue !== undefined
|
|
57
|
-
? (type === "single" ? [controlledValue as string] : controlledValue as string[])
|
|
58
|
-
: uncontrolledValue
|
|
59
|
-
|
|
60
|
-
const handleValueChange = (itemValue: string) => {
|
|
61
|
-
let newValue: string[]
|
|
62
|
-
|
|
63
|
-
if (type === "single") {
|
|
64
|
-
// Toggle off if clicking same value, otherwise set new value
|
|
65
|
-
newValue = value.includes(itemValue) ? [] : [itemValue]
|
|
66
|
-
if (controlledValue === undefined) {
|
|
67
|
-
setUncontrolledValue(newValue)
|
|
68
|
-
}
|
|
69
|
-
; (onValueChange as ((value: string) => void))?.(newValue[0] || "")
|
|
70
|
-
} else {
|
|
71
|
-
// Toggle item in array
|
|
72
|
-
newValue = value.includes(itemValue)
|
|
73
|
-
? value.filter(v => v !== itemValue)
|
|
74
|
-
: [...value, itemValue]
|
|
75
|
-
if (controlledValue === undefined) {
|
|
76
|
-
setUncontrolledValue(newValue)
|
|
77
|
-
}
|
|
78
|
-
; (onValueChange as ((value: string[]) => void))?.(newValue)
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
return (
|
|
83
|
-
<ToggleGroupContext.Provider value={{ type, value, onValueChange: handleValueChange, variant, size }}>
|
|
84
|
-
<div
|
|
85
|
-
ref={ref}
|
|
86
|
-
role="group"
|
|
87
|
-
className={cn("flex items-center justify-center gap-1", className)}
|
|
88
|
-
{...props}
|
|
89
|
-
>
|
|
90
|
-
{children}
|
|
91
|
-
</div>
|
|
92
|
-
</ToggleGroupContext.Provider>
|
|
93
|
-
)
|
|
94
|
-
}
|
|
95
|
-
)
|
|
96
|
-
ToggleGroup.displayName = "ToggleGroup"
|
|
97
|
-
|
|
98
|
-
// ToggleGroupItem
|
|
99
|
-
interface ToggleGroupItemProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
|
100
|
-
value: string
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
const ToggleGroupItem = React.forwardRef<HTMLButtonElement, ToggleGroupItemProps>(
|
|
104
|
-
({ className, value, children, ...props }, ref) => {
|
|
105
|
-
const context = useToggleGroup()
|
|
106
|
-
const pressed = context.value.includes(value)
|
|
107
|
-
|
|
108
|
-
return (
|
|
109
|
-
<button
|
|
110
|
-
ref={ref}
|
|
111
|
-
type="button"
|
|
112
|
-
aria-pressed={pressed}
|
|
113
|
-
data-state={pressed ? "on" : "off"}
|
|
114
|
-
className={cn(
|
|
115
|
-
toggleVariants({ variant: context.variant, size: context.size }),
|
|
116
|
-
pressed && "bg-accent text-accent-foreground",
|
|
117
|
-
className
|
|
118
|
-
)}
|
|
119
|
-
onClick={() => context.onValueChange(value)}
|
|
120
|
-
{...props}
|
|
121
|
-
>
|
|
122
|
-
{children}
|
|
123
|
-
</button>
|
|
124
|
-
)
|
|
125
|
-
}
|
|
126
|
-
)
|
|
127
|
-
ToggleGroupItem.displayName = "ToggleGroupItem"
|
|
128
|
-
|
|
129
|
-
export { ToggleGroup, ToggleGroupItem }
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
import * as React from "react"
|
|
4
|
+
import { cn } from "@/lib/utils"
|
|
5
|
+
import { toggleVariants } from "./toggle"
|
|
6
|
+
import { type VariantProps } from "class-variance-authority"
|
|
7
|
+
|
|
8
|
+
// ToggleGroup Context
|
|
9
|
+
interface ToggleGroupContextValue {
|
|
10
|
+
type: "single" | "multiple"
|
|
11
|
+
value: string[]
|
|
12
|
+
onValueChange: (value: string) => void
|
|
13
|
+
variant?: VariantProps<typeof toggleVariants>["variant"]
|
|
14
|
+
size?: VariantProps<typeof toggleVariants>["size"]
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const ToggleGroupContext = React.createContext<ToggleGroupContextValue | null>(null)
|
|
18
|
+
|
|
19
|
+
function useToggleGroup() {
|
|
20
|
+
const context = React.useContext(ToggleGroupContext)
|
|
21
|
+
if (!context) {
|
|
22
|
+
throw new Error("useToggleGroup must be used within a ToggleGroup")
|
|
23
|
+
}
|
|
24
|
+
return context
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// ToggleGroup Props
|
|
28
|
+
interface ToggleGroupSingleProps {
|
|
29
|
+
type: "single"
|
|
30
|
+
value?: string
|
|
31
|
+
defaultValue?: string
|
|
32
|
+
onValueChange?: (value: string) => void
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
interface ToggleGroupMultipleProps {
|
|
36
|
+
type: "multiple"
|
|
37
|
+
value?: string[]
|
|
38
|
+
defaultValue?: string[]
|
|
39
|
+
onValueChange?: (value: string[]) => void
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
type ToggleGroupProps = (ToggleGroupSingleProps | ToggleGroupMultipleProps) &
|
|
43
|
+
React.HTMLAttributes<HTMLDivElement> &
|
|
44
|
+
VariantProps<typeof toggleVariants>
|
|
45
|
+
|
|
46
|
+
const ToggleGroup = React.forwardRef<HTMLDivElement, ToggleGroupProps>(
|
|
47
|
+
({ className, type, value: controlledValue, defaultValue, onValueChange, variant, size, children, ...props }, ref) => {
|
|
48
|
+
// Handle both single and multiple types
|
|
49
|
+
const [uncontrolledValue, setUncontrolledValue] = React.useState<string[]>(() => {
|
|
50
|
+
if (type === "single") {
|
|
51
|
+
return defaultValue ? [defaultValue as string] : []
|
|
52
|
+
}
|
|
53
|
+
return (defaultValue as string[]) || []
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
const value = controlledValue !== undefined
|
|
57
|
+
? (type === "single" ? [controlledValue as string] : controlledValue as string[])
|
|
58
|
+
: uncontrolledValue
|
|
59
|
+
|
|
60
|
+
const handleValueChange = (itemValue: string) => {
|
|
61
|
+
let newValue: string[]
|
|
62
|
+
|
|
63
|
+
if (type === "single") {
|
|
64
|
+
// Toggle off if clicking same value, otherwise set new value
|
|
65
|
+
newValue = value.includes(itemValue) ? [] : [itemValue]
|
|
66
|
+
if (controlledValue === undefined) {
|
|
67
|
+
setUncontrolledValue(newValue)
|
|
68
|
+
}
|
|
69
|
+
; (onValueChange as ((value: string) => void))?.(newValue[0] || "")
|
|
70
|
+
} else {
|
|
71
|
+
// Toggle item in array
|
|
72
|
+
newValue = value.includes(itemValue)
|
|
73
|
+
? value.filter(v => v !== itemValue)
|
|
74
|
+
: [...value, itemValue]
|
|
75
|
+
if (controlledValue === undefined) {
|
|
76
|
+
setUncontrolledValue(newValue)
|
|
77
|
+
}
|
|
78
|
+
; (onValueChange as ((value: string[]) => void))?.(newValue)
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return (
|
|
83
|
+
<ToggleGroupContext.Provider value={{ type, value, onValueChange: handleValueChange, variant, size }}>
|
|
84
|
+
<div
|
|
85
|
+
ref={ref}
|
|
86
|
+
role="group"
|
|
87
|
+
className={cn("flex items-center justify-center gap-1", className)}
|
|
88
|
+
{...props}
|
|
89
|
+
>
|
|
90
|
+
{children}
|
|
91
|
+
</div>
|
|
92
|
+
</ToggleGroupContext.Provider>
|
|
93
|
+
)
|
|
94
|
+
}
|
|
95
|
+
)
|
|
96
|
+
ToggleGroup.displayName = "ToggleGroup"
|
|
97
|
+
|
|
98
|
+
// ToggleGroupItem
|
|
99
|
+
interface ToggleGroupItemProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
|
100
|
+
value: string
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const ToggleGroupItem = React.forwardRef<HTMLButtonElement, ToggleGroupItemProps>(
|
|
104
|
+
({ className, value, children, ...props }, ref) => {
|
|
105
|
+
const context = useToggleGroup()
|
|
106
|
+
const pressed = context.value.includes(value)
|
|
107
|
+
|
|
108
|
+
return (
|
|
109
|
+
<button
|
|
110
|
+
ref={ref}
|
|
111
|
+
type="button"
|
|
112
|
+
aria-pressed={pressed}
|
|
113
|
+
data-state={pressed ? "on" : "off"}
|
|
114
|
+
className={cn(
|
|
115
|
+
toggleVariants({ variant: context.variant, size: context.size }),
|
|
116
|
+
pressed && "bg-accent text-accent-foreground",
|
|
117
|
+
className
|
|
118
|
+
)}
|
|
119
|
+
onClick={() => context.onValueChange(value)}
|
|
120
|
+
{...props}
|
|
121
|
+
>
|
|
122
|
+
{children}
|
|
123
|
+
</button>
|
|
124
|
+
)
|
|
125
|
+
}
|
|
126
|
+
)
|
|
127
|
+
ToggleGroupItem.displayName = "ToggleGroupItem"
|
|
128
|
+
|
|
129
|
+
export { ToggleGroup, ToggleGroupItem }
|
|
@@ -1,72 +1,72 @@
|
|
|
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 toggleVariants = cva(
|
|
8
|
-
"inline-flex items-center justify-center rounded-md text-sm font-medium ring-offset-background transition-colors hover:bg-muted hover:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",
|
|
9
|
-
{
|
|
10
|
-
variants: {
|
|
11
|
-
variant: {
|
|
12
|
-
default: "bg-transparent",
|
|
13
|
-
outline: "border border-input bg-transparent hover:bg-accent hover:text-accent-foreground",
|
|
14
|
-
},
|
|
15
|
-
size: {
|
|
16
|
-
default: "h-10 px-3",
|
|
17
|
-
sm: "h-9 px-2.5",
|
|
18
|
-
lg: "h-11 px-5",
|
|
19
|
-
},
|
|
20
|
-
},
|
|
21
|
-
defaultVariants: {
|
|
22
|
-
variant: "default",
|
|
23
|
-
size: "default",
|
|
24
|
-
},
|
|
25
|
-
}
|
|
26
|
-
)
|
|
27
|
-
|
|
28
|
-
export interface ToggleProps
|
|
29
|
-
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
|
|
30
|
-
VariantProps<typeof toggleVariants> {
|
|
31
|
-
/** Controlled pressed state */
|
|
32
|
-
pressed?: boolean
|
|
33
|
-
/** Default pressed state for uncontrolled usage */
|
|
34
|
-
defaultPressed?: boolean
|
|
35
|
-
/** Callback when pressed state changes */
|
|
36
|
-
onPressedChange?: (pressed: boolean) => void
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
const Toggle = React.forwardRef<HTMLButtonElement, ToggleProps>(
|
|
40
|
-
({ className, variant, size, pressed: controlledPressed, defaultPressed = false, onPressedChange, ...props }, ref) => {
|
|
41
|
-
const [uncontrolledPressed, setUncontrolledPressed] = React.useState(defaultPressed)
|
|
42
|
-
const pressed = controlledPressed ?? uncontrolledPressed
|
|
43
|
-
|
|
44
|
-
const handleClick = (e: React.MouseEvent<HTMLButtonElement>) => {
|
|
45
|
-
const newPressed = !pressed
|
|
46
|
-
if (controlledPressed === undefined) {
|
|
47
|
-
setUncontrolledPressed(newPressed)
|
|
48
|
-
}
|
|
49
|
-
onPressedChange?.(newPressed)
|
|
50
|
-
props.onClick?.(e)
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
return (
|
|
54
|
-
<button
|
|
55
|
-
ref={ref}
|
|
56
|
-
type="button"
|
|
57
|
-
aria-pressed={pressed}
|
|
58
|
-
data-state={pressed ? "on" : "off"}
|
|
59
|
-
className={cn(
|
|
60
|
-
toggleVariants({ variant, size }),
|
|
61
|
-
pressed && "bg-accent text-accent-foreground",
|
|
62
|
-
className
|
|
63
|
-
)}
|
|
64
|
-
onClick={handleClick}
|
|
65
|
-
{...props}
|
|
66
|
-
/>
|
|
67
|
-
)
|
|
68
|
-
}
|
|
69
|
-
)
|
|
70
|
-
Toggle.displayName = "Toggle"
|
|
71
|
-
|
|
72
|
-
export { Toggle, toggleVariants }
|
|
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 toggleVariants = cva(
|
|
8
|
+
"inline-flex items-center justify-center rounded-md text-sm font-medium ring-offset-background transition-colors hover:bg-muted hover:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",
|
|
9
|
+
{
|
|
10
|
+
variants: {
|
|
11
|
+
variant: {
|
|
12
|
+
default: "bg-transparent",
|
|
13
|
+
outline: "border border-input bg-transparent hover:bg-accent hover:text-accent-foreground",
|
|
14
|
+
},
|
|
15
|
+
size: {
|
|
16
|
+
default: "h-10 px-3",
|
|
17
|
+
sm: "h-9 px-2.5",
|
|
18
|
+
lg: "h-11 px-5",
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
defaultVariants: {
|
|
22
|
+
variant: "default",
|
|
23
|
+
size: "default",
|
|
24
|
+
},
|
|
25
|
+
}
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
export interface ToggleProps
|
|
29
|
+
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
|
|
30
|
+
VariantProps<typeof toggleVariants> {
|
|
31
|
+
/** Controlled pressed state */
|
|
32
|
+
pressed?: boolean
|
|
33
|
+
/** Default pressed state for uncontrolled usage */
|
|
34
|
+
defaultPressed?: boolean
|
|
35
|
+
/** Callback when pressed state changes */
|
|
36
|
+
onPressedChange?: (pressed: boolean) => void
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const Toggle = React.forwardRef<HTMLButtonElement, ToggleProps>(
|
|
40
|
+
({ className, variant, size, pressed: controlledPressed, defaultPressed = false, onPressedChange, ...props }, ref) => {
|
|
41
|
+
const [uncontrolledPressed, setUncontrolledPressed] = React.useState(defaultPressed)
|
|
42
|
+
const pressed = controlledPressed ?? uncontrolledPressed
|
|
43
|
+
|
|
44
|
+
const handleClick = (e: React.MouseEvent<HTMLButtonElement>) => {
|
|
45
|
+
const newPressed = !pressed
|
|
46
|
+
if (controlledPressed === undefined) {
|
|
47
|
+
setUncontrolledPressed(newPressed)
|
|
48
|
+
}
|
|
49
|
+
onPressedChange?.(newPressed)
|
|
50
|
+
props.onClick?.(e)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return (
|
|
54
|
+
<button
|
|
55
|
+
ref={ref}
|
|
56
|
+
type="button"
|
|
57
|
+
aria-pressed={pressed}
|
|
58
|
+
data-state={pressed ? "on" : "off"}
|
|
59
|
+
className={cn(
|
|
60
|
+
toggleVariants({ variant, size }),
|
|
61
|
+
pressed && "bg-accent text-accent-foreground",
|
|
62
|
+
className
|
|
63
|
+
)}
|
|
64
|
+
onClick={handleClick}
|
|
65
|
+
{...props}
|
|
66
|
+
/>
|
|
67
|
+
)
|
|
68
|
+
}
|
|
69
|
+
)
|
|
70
|
+
Toggle.displayName = "Toggle"
|
|
71
|
+
|
|
72
|
+
export { Toggle, toggleVariants }
|