@cntyclub/ui-react 0.1.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 (124) hide show
  1. package/dist/chunk-HDGMSYQS.js +26461 -0
  2. package/dist/chunk-HDGMSYQS.js.map +1 -0
  3. package/dist/chunk-PR4QN5HX.js +39 -0
  4. package/dist/chunk-PR4QN5HX.js.map +1 -0
  5. package/dist/form.d.ts +175 -0
  6. package/dist/form.js +5207 -0
  7. package/dist/form.js.map +1 -0
  8. package/dist/index.d.ts +1462 -0
  9. package/dist/index.js +81862 -0
  10. package/dist/index.js.map +1 -0
  11. package/dist/input-CZvh825j.d.ts +24 -0
  12. package/dist/qr-code-styling-3Y6LZH6V.js +1123 -0
  13. package/dist/qr-code-styling-3Y6LZH6V.js.map +1 -0
  14. package/package.json +79 -0
  15. package/src/components/form/checkbox-group-field.tsx +101 -0
  16. package/src/components/form/date-field.tsx +79 -0
  17. package/src/components/form/date-range-field.tsx +106 -0
  18. package/src/components/form/form-context.ts +10 -0
  19. package/src/components/form/form.tsx +54 -0
  20. package/src/components/form/number-field.tsx +69 -0
  21. package/src/components/form/select-field.tsx +76 -0
  22. package/src/components/form/submit-button.tsx +28 -0
  23. package/src/components/form/text-field.tsx +107 -0
  24. package/src/components/layout/dashboard-header.tsx +54 -0
  25. package/src/components/layout/dashboard-panel.tsx +34 -0
  26. package/src/components/theme-provider.tsx +403 -0
  27. package/src/components/ui/accordion.tsx +69 -0
  28. package/src/components/ui/alert-dialog.tsx +169 -0
  29. package/src/components/ui/alert.tsx +80 -0
  30. package/src/components/ui/animated-theme-toggler.tsx +265 -0
  31. package/src/components/ui/app-store-buttons.tsx +182 -0
  32. package/src/components/ui/aspect-ratio.tsx +23 -0
  33. package/src/components/ui/autocomplete.tsx +296 -0
  34. package/src/components/ui/avatar-group.tsx +95 -0
  35. package/src/components/ui/avatar.tsx +285 -0
  36. package/src/components/ui/badge-group.tsx +160 -0
  37. package/src/components/ui/badge.tsx +172 -0
  38. package/src/components/ui/breadcrumb.tsx +112 -0
  39. package/src/components/ui/button.tsx +77 -0
  40. package/src/components/ui/calendar.tsx +137 -0
  41. package/src/components/ui/card.tsx +244 -0
  42. package/src/components/ui/carousel.tsx +258 -0
  43. package/src/components/ui/chart.tsx +379 -0
  44. package/src/components/ui/checkbox-group.tsx +16 -0
  45. package/src/components/ui/checkbox.tsx +82 -0
  46. package/src/components/ui/collapsible.tsx +45 -0
  47. package/src/components/ui/combobox.tsx +411 -0
  48. package/src/components/ui/command.tsx +264 -0
  49. package/src/components/ui/context-menu.tsx +271 -0
  50. package/src/components/ui/credit-card.tsx +214 -0
  51. package/src/components/ui/dialog.tsx +196 -0
  52. package/src/components/ui/drawer.tsx +135 -0
  53. package/src/components/ui/empty.tsx +127 -0
  54. package/src/components/ui/featured-icon.tsx +149 -0
  55. package/src/components/ui/field.tsx +88 -0
  56. package/src/components/ui/fieldset.tsx +29 -0
  57. package/src/components/ui/form.tsx +17 -0
  58. package/src/components/ui/frame.tsx +82 -0
  59. package/src/components/ui/generic-empty.tsx +142 -0
  60. package/src/components/ui/group.tsx +97 -0
  61. package/src/components/ui/horizontal-scroll-fader.tsx +228 -0
  62. package/src/components/ui/input-group.tsx +102 -0
  63. package/src/components/ui/input-otp.tsx +96 -0
  64. package/src/components/ui/input.tsx +66 -0
  65. package/src/components/ui/item.tsx +198 -0
  66. package/src/components/ui/kbd.tsx +30 -0
  67. package/src/components/ui/label.tsx +28 -0
  68. package/src/components/ui/menu.tsx +312 -0
  69. package/src/components/ui/menubar.tsx +93 -0
  70. package/src/components/ui/meter.tsx +67 -0
  71. package/src/components/ui/multi-select.tsx +308 -0
  72. package/src/components/ui/navigation-menu.tsx +143 -0
  73. package/src/components/ui/number-field.tsx +160 -0
  74. package/src/components/ui/pagination-controls.tsx +74 -0
  75. package/src/components/ui/pagination.tsx +149 -0
  76. package/src/components/ui/popover.tsx +119 -0
  77. package/src/components/ui/preview-card.tsx +55 -0
  78. package/src/components/ui/progress.tsx +289 -0
  79. package/src/components/ui/qr-code.tsx +150 -0
  80. package/src/components/ui/radio-group.tsx +103 -0
  81. package/src/components/ui/resizable.tsx +56 -0
  82. package/src/components/ui/scroll-area.tsx +90 -0
  83. package/src/components/ui/scroller.tsx +38 -0
  84. package/src/components/ui/section-header.tsx +118 -0
  85. package/src/components/ui/select.tsx +181 -0
  86. package/src/components/ui/separator.tsx +23 -0
  87. package/src/components/ui/sheet.tsx +224 -0
  88. package/src/components/ui/sidebar.tsx +744 -0
  89. package/src/components/ui/skeleton.tsx +16 -0
  90. package/src/components/ui/slider.tsx +108 -0
  91. package/src/components/ui/smooth-scroll.tsx +143 -0
  92. package/src/components/ui/social-button.tsx +247 -0
  93. package/src/components/ui/spinner-on-demand.tsx +32 -0
  94. package/src/components/ui/spinner.tsx +18 -0
  95. package/src/components/ui/stat.tsx +187 -0
  96. package/src/components/ui/stepper.tsx +167 -0
  97. package/src/components/ui/switch.tsx +56 -0
  98. package/src/components/ui/table.tsx +126 -0
  99. package/src/components/ui/tabs.tsx +90 -0
  100. package/src/components/ui/tag.tsx +229 -0
  101. package/src/components/ui/target-countdown.tsx +46 -0
  102. package/src/components/ui/text-editor.tsx +313 -0
  103. package/src/components/ui/textarea.tsx +51 -0
  104. package/src/components/ui/timeline.tsx +116 -0
  105. package/src/components/ui/toast.tsx +268 -0
  106. package/src/components/ui/toggle-group.tsx +101 -0
  107. package/src/components/ui/toggle.tsx +45 -0
  108. package/src/components/ui/toolbar.tsx +89 -0
  109. package/src/components/ui/tooltip.tsx +102 -0
  110. package/src/components/ui/vertical-scroll-fader.tsx +250 -0
  111. package/src/components/ui/video-player.tsx +275 -0
  112. package/src/components/upload/avatar-upload-base.tsx +131 -0
  113. package/src/components/upload/image-upload-base.tsx +112 -0
  114. package/src/form.ts +17 -0
  115. package/src/index.ts +125 -0
  116. package/src/lib/hooks/use-callback-ref.ts +15 -0
  117. package/src/lib/hooks/use-first-render.ts +11 -0
  118. package/src/lib/hooks/use-hover.ts +53 -0
  119. package/src/lib/hooks/use-is-tab-active.ts +17 -0
  120. package/src/lib/hooks/use-media-query.ts +164 -0
  121. package/src/lib/utils/css.ts +6 -0
  122. package/src/styles.css +300 -0
  123. package/src/types/helpers.ts +24 -0
  124. package/src/types/react.d.ts +7 -0
@@ -0,0 +1,66 @@
1
+ "use client";
2
+
3
+ import { Input as InputPrimitive } from "@base-ui/react/input";
4
+ import type * as React from "react";
5
+
6
+ import { cn } from "../../lib/utils/css";
7
+
8
+ type InputProps = Omit<
9
+ InputPrimitive.Props & React.RefAttributes<HTMLInputElement>,
10
+ "size"
11
+ > & {
12
+ size?: "sm" | "default" | "lg" | number;
13
+ unstyled?: boolean;
14
+ nativeInput?: boolean;
15
+ };
16
+
17
+ function Input({
18
+ className,
19
+ size = "default",
20
+ unstyled = false,
21
+ nativeInput = false,
22
+ ...props
23
+ }: InputProps) {
24
+ const inputClassName = cn(
25
+ "h-8.5 w-full min-w-0 rounded-[inherit] px-[calc(--spacing(3)-1px)] leading-8.5 outline-none placeholder:text-muted-foreground/72 sm:h-7.5 sm:leading-7.5",
26
+ size === "sm" &&
27
+ "h-7.5 px-[calc(--spacing(2.5)-1px)] leading-7.5 sm:h-6.5 sm:leading-6.5",
28
+ size === "lg" && "h-9.5 leading-9.5 sm:h-8.5 sm:leading-8.5",
29
+ props.type === "search" &&
30
+ "[&::-webkit-search-cancel-button]:appearance-none [&::-webkit-search-decoration]:appearance-none [&::-webkit-search-results-button]:appearance-none [&::-webkit-search-results-decoration]:appearance-none",
31
+ props.type === "file" &&
32
+ "text-muted-foreground file:me-3 file:bg-transparent file:font-medium file:text-foreground file:text-sm",
33
+ );
34
+
35
+ return (
36
+ <span
37
+ className={
38
+ cn(
39
+ !unstyled &&
40
+ "relative inline-flex w-full rounded-lg border border-input bg-background not-dark:bg-clip-padding text-base text-foreground shadow-xs/5 ring-ring/24 transition-shadow before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-lg)-1px)] not-has-disabled:not-has-focus-visible:not-has-aria-invalid:before:shadow-[0_1px_--theme(--color-black/6%)] has-focus-visible:has-aria-invalid:border-destructive/64 has-focus-visible:has-aria-invalid:ring-destructive/16 has-aria-invalid:border-destructive/36 has-focus-visible:border-ring has-disabled:opacity-64 has-[:disabled,:focus-visible,[aria-invalid]]:shadow-none has-focus-visible:ring-[3px] sm:text-sm dark:bg-input/32 dark:has-aria-invalid:ring-destructive/24 dark:not-has-disabled:not-has-focus-visible:not-has-aria-invalid:before:shadow-[0_-1px_--theme(--color-white/6%)]",
41
+ className,
42
+ ) || undefined
43
+ }
44
+ data-size={size}
45
+ data-slot="input-control"
46
+ >
47
+ {nativeInput ? (
48
+ <input
49
+ className={inputClassName}
50
+ data-slot="input"
51
+ size={typeof size === "number" ? size : undefined}
52
+ {...props}
53
+ />
54
+ ) : (
55
+ <InputPrimitive
56
+ className={inputClassName}
57
+ data-slot="input"
58
+ size={typeof size === "number" ? size : undefined}
59
+ {...props}
60
+ />
61
+ )}
62
+ </span>
63
+ );
64
+ }
65
+
66
+ export { Input, type InputProps };
@@ -0,0 +1,198 @@
1
+ "use client";
2
+
3
+ import { mergeProps } from "@base-ui/react/merge-props";
4
+ import { useRender } from "@base-ui/react/use-render";
5
+ import { cva, type VariantProps } from "class-variance-authority";
6
+ import type * as React from "react";
7
+
8
+ import { cn } from "../../lib/utils/css";
9
+ import { Separator } from "./separator";
10
+
11
+ function ItemGroup({ className, ...props }: React.ComponentProps<"div">) {
12
+ return (
13
+ <div
14
+ className={cn("group/item-group flex flex-col", className)}
15
+ data-slot="item-group"
16
+ role="list"
17
+ {...props}
18
+ />
19
+ );
20
+ }
21
+
22
+ function ItemSeparator({
23
+ className,
24
+ ...props
25
+ }: React.ComponentProps<typeof Separator>) {
26
+ return (
27
+ <Separator
28
+ className={cn("my-0", className)}
29
+ data-slot="item-separator"
30
+ orientation="horizontal"
31
+ {...props}
32
+ />
33
+ );
34
+ }
35
+
36
+ const itemVariants = cva(
37
+ "group/item flex flex-wrap items-center rounded-lg border border-transparent text-base outline-none transition-colors duration-100 focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:ring-offset-background sm:text-sm [a]:transition-colors [a]:hover:bg-accent/50",
38
+ {
39
+ defaultVariants: {
40
+ size: "default",
41
+ variant: "default",
42
+ },
43
+ variants: {
44
+ size: {
45
+ default: "gap-4 p-4",
46
+ sm: "gap-2.5 px-4 py-3",
47
+ },
48
+ variant: {
49
+ default: "bg-transparent",
50
+ muted: "bg-muted/50",
51
+ outline:
52
+ "border-border bg-card not-dark:bg-clip-padding shadow-xs/5 dark:bg-input/32",
53
+ },
54
+ },
55
+ },
56
+ );
57
+
58
+ interface ItemProps extends useRender.ComponentProps<"div"> {
59
+ variant?: VariantProps<typeof itemVariants>["variant"];
60
+ size?: VariantProps<typeof itemVariants>["size"];
61
+ }
62
+
63
+ function Item({ className, variant, size, render, ...props }: ItemProps) {
64
+ const defaultProps = {
65
+ className: cn(itemVariants({ className, size, variant })),
66
+ "data-size": size ?? "default",
67
+ "data-slot": "item",
68
+ "data-variant": variant ?? "default",
69
+ };
70
+
71
+ return useRender({
72
+ defaultTagName: "div",
73
+ props: mergeProps<"div">(defaultProps, props),
74
+ render,
75
+ });
76
+ }
77
+
78
+ const itemMediaVariants = cva(
79
+ "flex shrink-0 items-center justify-center gap-2 group-has-[[data-slot=item-description]]/item:translate-y-0.5 group-has-[[data-slot=item-description]]/item:self-start [&_svg]:pointer-events-none",
80
+ {
81
+ defaultVariants: {
82
+ variant: "default",
83
+ },
84
+ variants: {
85
+ variant: {
86
+ default: "bg-transparent",
87
+ icon: "size-8 rounded-sm border bg-muted [&_svg:not([class*='size-'])]:size-4",
88
+ image:
89
+ "size-10 overflow-hidden rounded-sm [&_img]:size-full [&_img]:object-cover",
90
+ },
91
+ },
92
+ },
93
+ );
94
+
95
+ function ItemMedia({
96
+ className,
97
+ variant = "default",
98
+ ...props
99
+ }: React.ComponentProps<"div"> & VariantProps<typeof itemMediaVariants>) {
100
+ return (
101
+ <div
102
+ className={cn(itemMediaVariants({ className, variant }))}
103
+ data-slot="item-media"
104
+ data-variant={variant}
105
+ {...props}
106
+ />
107
+ );
108
+ }
109
+
110
+ function ItemContent({ className, ...props }: React.ComponentProps<"div">) {
111
+ return (
112
+ <div
113
+ className={cn(
114
+ "flex flex-1 flex-col gap-1 [&+[data-slot=item-content]]:flex-none",
115
+ className,
116
+ )}
117
+ data-slot="item-content"
118
+ {...props}
119
+ />
120
+ );
121
+ }
122
+
123
+ function ItemTitle({ className, ...props }: React.ComponentProps<"div">) {
124
+ return (
125
+ <div
126
+ className={cn(
127
+ "flex w-fit items-center gap-2 font-medium leading-snug",
128
+ className,
129
+ )}
130
+ data-slot="item-title"
131
+ {...props}
132
+ />
133
+ );
134
+ }
135
+
136
+ function ItemDescription({ className, ...props }: React.ComponentProps<"p">) {
137
+ return (
138
+ <p
139
+ className={cn(
140
+ "line-clamp-2 text-balance font-normal text-muted-foreground text-sm leading-normal sm:text-xs",
141
+ "[&>a]:underline [&>a]:underline-offset-4 [&>a:hover]:text-primary",
142
+ className,
143
+ )}
144
+ data-slot="item-description"
145
+ {...props}
146
+ />
147
+ );
148
+ }
149
+
150
+ function ItemActions({ className, ...props }: React.ComponentProps<"div">) {
151
+ return (
152
+ <div
153
+ className={cn("flex items-center gap-2", className)}
154
+ data-slot="item-actions"
155
+ {...props}
156
+ />
157
+ );
158
+ }
159
+
160
+ function ItemHeader({ className, ...props }: React.ComponentProps<"div">) {
161
+ return (
162
+ <div
163
+ className={cn(
164
+ "flex basis-full items-center justify-between gap-2",
165
+ className,
166
+ )}
167
+ data-slot="item-header"
168
+ {...props}
169
+ />
170
+ );
171
+ }
172
+
173
+ function ItemFooter({ className, ...props }: React.ComponentProps<"div">) {
174
+ return (
175
+ <div
176
+ className={cn(
177
+ "flex basis-full items-center justify-between gap-2",
178
+ className,
179
+ )}
180
+ data-slot="item-footer"
181
+ {...props}
182
+ />
183
+ );
184
+ }
185
+
186
+ export {
187
+ Item,
188
+ ItemMedia,
189
+ ItemContent,
190
+ ItemActions,
191
+ ItemGroup,
192
+ ItemSeparator,
193
+ ItemTitle,
194
+ ItemDescription,
195
+ ItemHeader,
196
+ ItemFooter,
197
+ itemVariants,
198
+ };
@@ -0,0 +1,30 @@
1
+ "use client";
2
+
3
+ import type * as React from "react";
4
+
5
+ import { cn } from "../../lib/utils/css";
6
+
7
+ function Kbd({ className, ...props }: React.ComponentProps<"kbd">) {
8
+ return (
9
+ <kbd
10
+ className={cn(
11
+ "pointer-events-none inline-flex h-5 min-w-5 select-none items-center justify-center gap-1 rounded bg-muted px-1 font-medium font-sans text-muted-foreground text-xs [&_svg:not([class*='size-'])]:size-3",
12
+ className,
13
+ )}
14
+ data-slot="kbd"
15
+ {...props}
16
+ />
17
+ );
18
+ }
19
+
20
+ function KbdGroup({ className, ...props }: React.ComponentProps<"kbd">) {
21
+ return (
22
+ <kbd
23
+ className={cn("inline-flex items-center gap-1", className)}
24
+ data-slot="kbd-group"
25
+ {...props}
26
+ />
27
+ );
28
+ }
29
+
30
+ export { Kbd, KbdGroup };
@@ -0,0 +1,28 @@
1
+ "use client";
2
+
3
+ import { mergeProps } from "@base-ui/react/merge-props";
4
+ import { useRender } from "@base-ui/react/use-render";
5
+
6
+ import { cn } from "../../lib/utils/css";
7
+
8
+ function Label({
9
+ className,
10
+ render,
11
+ ...props
12
+ }: useRender.ComponentProps<"label">) {
13
+ const defaultProps = {
14
+ className: cn(
15
+ "inline-flex items-center gap-2 text-base/4.5 sm:text-sm/4 font-medium text-foreground",
16
+ className,
17
+ ),
18
+ "data-slot": "label",
19
+ };
20
+
21
+ return useRender({
22
+ defaultTagName: "label",
23
+ props: mergeProps<"label">(defaultProps, props),
24
+ render,
25
+ });
26
+ }
27
+
28
+ export { Label };
@@ -0,0 +1,312 @@
1
+ "use client";
2
+
3
+ import { Menu as MenuPrimitive } from "@base-ui/react/menu";
4
+ import { ChevronRightIcon } from "lucide-react";
5
+ import type * as React from "react";
6
+ import { cn } from "../../lib/utils/css";
7
+
8
+ const MenuCreateHandle = MenuPrimitive.createHandle;
9
+
10
+ const Menu = MenuPrimitive.Root;
11
+
12
+ const MenuPortal = MenuPrimitive.Portal;
13
+
14
+ function MenuTrigger(props: MenuPrimitive.Trigger.Props) {
15
+ return <MenuPrimitive.Trigger data-slot="menu-trigger" {...props} />;
16
+ }
17
+
18
+ function MenuPopup({
19
+ children,
20
+ className,
21
+ sideOffset = 4,
22
+ align = "center",
23
+ alignOffset,
24
+ side = "bottom",
25
+ ...props
26
+ }: MenuPrimitive.Popup.Props & {
27
+ align?: MenuPrimitive.Positioner.Props["align"];
28
+ sideOffset?: MenuPrimitive.Positioner.Props["sideOffset"];
29
+ alignOffset?: MenuPrimitive.Positioner.Props["alignOffset"];
30
+ side?: MenuPrimitive.Positioner.Props["side"];
31
+ }) {
32
+ return (
33
+ <MenuPrimitive.Portal>
34
+ <MenuPrimitive.Positioner
35
+ align={align}
36
+ alignOffset={alignOffset}
37
+ className="z-50"
38
+ data-slot="menu-positioner"
39
+ side={side}
40
+ sideOffset={sideOffset}
41
+ >
42
+ <MenuPrimitive.Popup
43
+ className={cn(
44
+ "relative flex not-[class*='w-']:min-w-32 origin-(--transform-origin) rounded-lg border bg-popover not-dark:bg-clip-padding shadow-lg/5 outline-none transition-[transform,scale,opacity] duration-150 ease-out before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-lg)-1px)] before:shadow-[0_1px_--theme(--color-black/6%)] focus:outline-none data-ending-style:scale-95 data-ending-style:opacity-0 data-starting-style:scale-95 data-starting-style:opacity-0 dark:before:shadow-[0_-1px_--theme(--color-white/6%)]",
45
+ className,
46
+ )}
47
+ data-slot="menu-popup"
48
+ {...props}
49
+ >
50
+ <div className="max-h-(--available-height) w-full overflow-y-auto p-1">
51
+ {children}
52
+ </div>
53
+ </MenuPrimitive.Popup>
54
+ </MenuPrimitive.Positioner>
55
+ </MenuPrimitive.Portal>
56
+ );
57
+ }
58
+
59
+ function MenuGroup(props: MenuPrimitive.Group.Props) {
60
+ return <MenuPrimitive.Group data-slot="menu-group" {...props} />;
61
+ }
62
+
63
+ function MenuItem({
64
+ className,
65
+ inset,
66
+ variant = "default",
67
+ ...props
68
+ }: MenuPrimitive.Item.Props & {
69
+ inset?: boolean;
70
+ variant?: "default" | "destructive";
71
+ }) {
72
+ return (
73
+ <MenuPrimitive.Item
74
+ className={cn(
75
+ "[&>svg]:-mx-0.5 flex min-h-8 cursor-default select-none items-center gap-2 rounded-sm px-2 py-1 text-base text-foreground outline-none data-disabled:pointer-events-none data-highlighted:bg-accent data-inset:ps-8 data-[variant=destructive]:text-destructive-foreground data-highlighted:text-accent-foreground data-disabled:opacity-64 sm:min-h-7 sm:text-sm [&>svg:not([class*='opacity-'])]:opacity-80 [&>svg:not([class*='size-'])]:size-4.5 sm:[&>svg:not([class*='size-'])]:size-4 [&>svg]:pointer-events-none [&>svg]:shrink-0",
76
+ className,
77
+ )}
78
+ data-inset={inset}
79
+ data-slot="menu-item"
80
+ data-variant={variant}
81
+ {...props}
82
+ />
83
+ );
84
+ }
85
+
86
+ function MenuCheckboxItem({
87
+ className,
88
+ children,
89
+ checked,
90
+ variant = "default",
91
+ ...props
92
+ }: MenuPrimitive.CheckboxItem.Props & {
93
+ variant?: "default" | "switch";
94
+ }) {
95
+ return (
96
+ <MenuPrimitive.CheckboxItem
97
+ checked={checked}
98
+ className={cn(
99
+ "grid min-h-8 in-data-[side=none]:min-w-[calc(var(--anchor-width)+1.25rem)] cursor-default items-center gap-2 rounded-sm py-1 ps-2 text-base text-foreground outline-none data-disabled:pointer-events-none data-highlighted:bg-accent data-highlighted:text-accent-foreground data-disabled:opacity-64 sm:min-h-7 sm:text-sm [&_svg:not([class*='size-'])]:size-4.5 sm:[&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none [&_svg]:shrink-0",
100
+ variant === "switch"
101
+ ? "grid-cols-[1fr_auto] gap-4 pe-1.5"
102
+ : "grid-cols-[1rem_1fr] pe-4",
103
+ className,
104
+ )}
105
+ data-slot="menu-checkbox-item"
106
+ {...props}
107
+ >
108
+ {variant === "switch" ? (
109
+ <>
110
+ <span className="col-start-1">{children}</span>
111
+ <MenuPrimitive.CheckboxItemIndicator
112
+ className="inset-shadow-[0_1px_--theme(--color-black/6%)] inline-flex h-[calc(var(--thumb-size)+2px)] w-[calc(var(--thumb-size)*2-2px)] shrink-0 items-center rounded-full p-px outline-none transition-[background-color,box-shadow] duration-200 [--thumb-size:--spacing(4)] focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:ring-offset-background data-checked:bg-primary data-unchecked:bg-input data-disabled:opacity-64 sm:[--thumb-size:--spacing(3)]"
113
+ keepMounted
114
+ >
115
+ <span className="pointer-events-none block aspect-square h-full in-[[data-slot=menu-checkbox-item][data-checked]]:origin-[var(--thumb-size)_50%] origin-left in-[[data-slot=menu-checkbox-item][data-checked]]:translate-x-[calc(var(--thumb-size)-4px)] in-[[data-slot=menu-checkbox-item]:active]:not-data-disabled:scale-x-110 in-[[data-slot=menu-checkbox-item]:active]:rounded-[var(--thumb-size)/calc(var(--thumb-size)*1.10)] rounded-(--thumb-size) bg-background shadow-sm/5 will-change-transform [transition:translate_.15s,border-radius_.15s,scale_.1s_.1s,transform-origin_.15s]" />
116
+ </MenuPrimitive.CheckboxItemIndicator>
117
+ </>
118
+ ) : (
119
+ <>
120
+ <MenuPrimitive.CheckboxItemIndicator className="col-start-1">
121
+ <svg
122
+ fill="none"
123
+ height="24"
124
+ stroke="currentColor"
125
+ strokeLinecap="round"
126
+ strokeLinejoin="round"
127
+ strokeWidth="2"
128
+ viewBox="0 0 24 24"
129
+ width="24"
130
+ xmlns="http://www.w3.org/2000/svg"
131
+ >
132
+ <title>Check</title>
133
+ <path d="M5.252 12.7 10.2 18.63 18.748 5.37" />
134
+ </svg>
135
+ </MenuPrimitive.CheckboxItemIndicator>
136
+ <span className="col-start-2">{children}</span>
137
+ </>
138
+ )}
139
+ </MenuPrimitive.CheckboxItem>
140
+ );
141
+ }
142
+
143
+ function MenuRadioGroup(props: MenuPrimitive.RadioGroup.Props) {
144
+ return <MenuPrimitive.RadioGroup data-slot="menu-radio-group" {...props} />;
145
+ }
146
+
147
+ function MenuRadioItem({
148
+ className,
149
+ children,
150
+ ...props
151
+ }: MenuPrimitive.RadioItem.Props) {
152
+ return (
153
+ <MenuPrimitive.RadioItem
154
+ className={cn(
155
+ "grid min-h-8 in-data-[side=none]:min-w-[calc(var(--anchor-width)+1.25rem)] cursor-default grid-cols-[1rem_1fr] items-center gap-2 rounded-sm py-1 ps-2 pe-4 text-base text-foreground outline-none data-disabled:pointer-events-none data-highlighted:bg-accent data-highlighted:text-accent-foreground data-disabled:opacity-64 sm:min-h-7 sm:text-sm [&_svg:not([class*='size-'])]:size-4.5 sm:[&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none [&_svg]:shrink-0",
156
+ className,
157
+ )}
158
+ data-slot="menu-radio-item"
159
+ {...props}
160
+ >
161
+ <MenuPrimitive.RadioItemIndicator className="col-start-1">
162
+ <svg
163
+ fill="none"
164
+ height="24"
165
+ stroke="currentColor"
166
+ strokeLinecap="round"
167
+ strokeLinejoin="round"
168
+ strokeWidth="2"
169
+ viewBox="0 0 24 24"
170
+ width="24"
171
+ xmlns="http://www.w3.org/2000/svg"
172
+ >
173
+ <title>Check</title>
174
+ <path d="M5.252 12.7 10.2 18.63 18.748 5.37" />
175
+ </svg>
176
+ </MenuPrimitive.RadioItemIndicator>
177
+ <span className="col-start-2">{children}</span>
178
+ </MenuPrimitive.RadioItem>
179
+ );
180
+ }
181
+
182
+ function MenuGroupLabel({
183
+ className,
184
+ inset,
185
+ ...props
186
+ }: MenuPrimitive.GroupLabel.Props & {
187
+ inset?: boolean;
188
+ }) {
189
+ return (
190
+ <MenuPrimitive.GroupLabel
191
+ className={cn(
192
+ "px-2 py-1.5 font-medium text-muted-foreground text-xs data-inset:ps-9 sm:data-inset:ps-8",
193
+ className,
194
+ )}
195
+ data-inset={inset}
196
+ data-slot="menu-label"
197
+ {...props}
198
+ />
199
+ );
200
+ }
201
+
202
+ function MenuSeparator({ className, ...props }: MenuPrimitive.Separator.Props) {
203
+ return (
204
+ <MenuPrimitive.Separator
205
+ className={cn("mx-2 my-1 h-px bg-border", className)}
206
+ data-slot="menu-separator"
207
+ {...props}
208
+ />
209
+ );
210
+ }
211
+
212
+ function MenuShortcut({ className, ...props }: React.ComponentProps<"kbd">) {
213
+ return (
214
+ <kbd
215
+ className={cn(
216
+ "ms-auto font-medium font-sans text-muted-foreground/72 text-xs tracking-widest",
217
+ className,
218
+ )}
219
+ data-slot="menu-shortcut"
220
+ {...props}
221
+ />
222
+ );
223
+ }
224
+
225
+ function MenuSub(props: MenuPrimitive.SubmenuRoot.Props) {
226
+ return <MenuPrimitive.SubmenuRoot data-slot="menu-sub" {...props} />;
227
+ }
228
+
229
+ function MenuSubTrigger({
230
+ className,
231
+ inset,
232
+ children,
233
+ ...props
234
+ }: MenuPrimitive.SubmenuTrigger.Props & {
235
+ inset?: boolean;
236
+ }) {
237
+ return (
238
+ <MenuPrimitive.SubmenuTrigger
239
+ className={cn(
240
+ "flex min-h-8 items-center gap-2 rounded-sm px-2 py-1 text-base text-foreground outline-none data-disabled:pointer-events-none data-highlighted:bg-accent data-popup-open:bg-accent data-inset:ps-8 data-highlighted:text-accent-foreground data-popup-open:text-accent-foreground data-disabled:opacity-64 sm:min-h-7 sm:text-sm [&_svg:not([class*='size-'])]:size-4.5 sm:[&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none",
241
+ className,
242
+ )}
243
+ data-inset={inset}
244
+ data-slot="menu-sub-trigger"
245
+ {...props}
246
+ >
247
+ {children}
248
+ <ChevronRightIcon className="-me-0.5 ms-auto opacity-80" />
249
+ </MenuPrimitive.SubmenuTrigger>
250
+ );
251
+ }
252
+
253
+ function MenuSubPopup({
254
+ className,
255
+ sideOffset = 0,
256
+ alignOffset,
257
+ align = "start",
258
+ ...props
259
+ }: MenuPrimitive.Popup.Props & {
260
+ align?: MenuPrimitive.Positioner.Props["align"];
261
+ sideOffset?: MenuPrimitive.Positioner.Props["sideOffset"];
262
+ alignOffset?: MenuPrimitive.Positioner.Props["alignOffset"];
263
+ }) {
264
+ const defaultAlignOffset = align !== "center" ? -5 : undefined;
265
+
266
+ return (
267
+ <MenuPopup
268
+ align={align}
269
+ alignOffset={alignOffset ?? defaultAlignOffset}
270
+ className={className}
271
+ data-slot="menu-sub-content"
272
+ side="inline-end"
273
+ sideOffset={sideOffset}
274
+ {...props}
275
+ />
276
+ );
277
+ }
278
+
279
+ export {
280
+ MenuCreateHandle,
281
+ MenuCreateHandle as DropdownMenuCreateHandle,
282
+ Menu,
283
+ Menu as DropdownMenu,
284
+ MenuPortal,
285
+ MenuPortal as DropdownMenuPortal,
286
+ MenuTrigger,
287
+ MenuTrigger as DropdownMenuTrigger,
288
+ MenuPopup,
289
+ MenuPopup as DropdownMenuContent,
290
+ MenuGroup,
291
+ MenuGroup as DropdownMenuGroup,
292
+ MenuItem,
293
+ MenuItem as DropdownMenuItem,
294
+ MenuCheckboxItem,
295
+ MenuCheckboxItem as DropdownMenuCheckboxItem,
296
+ MenuRadioGroup,
297
+ MenuRadioGroup as DropdownMenuRadioGroup,
298
+ MenuRadioItem,
299
+ MenuRadioItem as DropdownMenuRadioItem,
300
+ MenuGroupLabel,
301
+ MenuGroupLabel as DropdownMenuLabel,
302
+ MenuSeparator,
303
+ MenuSeparator as DropdownMenuSeparator,
304
+ MenuShortcut,
305
+ MenuShortcut as DropdownMenuShortcut,
306
+ MenuSub,
307
+ MenuSub as DropdownMenuSub,
308
+ MenuSubTrigger,
309
+ MenuSubTrigger as DropdownMenuSubTrigger,
310
+ MenuSubPopup,
311
+ MenuSubPopup as DropdownMenuSubContent,
312
+ };