@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,116 @@
1
+ "use client";
2
+
3
+ import * as React from "react";
4
+
5
+ import { cn } from "../../lib/utils/css";
6
+
7
+ function Timeline({ className, ...props }: React.ComponentProps<"ol">) {
8
+ return (
9
+ <ol
10
+ className={cn(
11
+ "flex flex-col [&>li:last-child_[data-slot=timeline-connector]]:hidden",
12
+ className,
13
+ )}
14
+ data-slot="timeline"
15
+ {...props}
16
+ />
17
+ );
18
+ }
19
+
20
+ function TimelineItem({ className, ...props }: React.ComponentProps<"li">) {
21
+ return (
22
+ <li
23
+ className={cn("group/timeline-item flex gap-4", className)}
24
+ data-slot="timeline-item"
25
+ {...props}
26
+ />
27
+ );
28
+ }
29
+
30
+ /** The marker column: a dot and the connecting line beneath it. */
31
+ function TimelineDot({
32
+ className,
33
+ children,
34
+ ...props
35
+ }: React.ComponentProps<"div">) {
36
+ return (
37
+ <div
38
+ className="flex w-7 shrink-0 flex-col items-center"
39
+ data-slot="timeline-marker"
40
+ >
41
+ <div
42
+ className={cn(
43
+ "mt-0.5 flex size-3 shrink-0 items-center justify-center rounded-full border-2 border-primary bg-background [&_svg]:size-3.5 has-[svg]:mt-0 has-[svg]:size-7 has-[svg]:border-transparent has-[svg]:bg-primary has-[svg]:text-primary-foreground",
44
+ className,
45
+ )}
46
+ data-slot="timeline-dot"
47
+ {...props}
48
+ >
49
+ {children}
50
+ </div>
51
+ <div
52
+ className="my-1 w-0.5 flex-1 rounded-full bg-border"
53
+ data-slot="timeline-connector"
54
+ />
55
+ </div>
56
+ );
57
+ }
58
+
59
+ function TimelineContent({ className, ...props }: React.ComponentProps<"div">) {
60
+ return (
61
+ <div
62
+ className={cn(
63
+ "flex flex-1 flex-col gap-1 pb-8 group-last/timeline-item:pb-0",
64
+ className,
65
+ )}
66
+ data-slot="timeline-content"
67
+ {...props}
68
+ />
69
+ );
70
+ }
71
+
72
+ function TimelineTitle({ className, ...props }: React.ComponentProps<"div">) {
73
+ return (
74
+ <div
75
+ className={cn("font-medium text-sm leading-tight", className)}
76
+ data-slot="timeline-title"
77
+ {...props}
78
+ />
79
+ );
80
+ }
81
+
82
+ function TimelineTime({ className, ...props }: React.ComponentProps<"div">) {
83
+ return (
84
+ <div
85
+ className={cn(
86
+ "font-medium text-muted-foreground text-xs tabular-nums",
87
+ className,
88
+ )}
89
+ data-slot="timeline-time"
90
+ {...props}
91
+ />
92
+ );
93
+ }
94
+
95
+ function TimelineDescription({
96
+ className,
97
+ ...props
98
+ }: React.ComponentProps<"div">) {
99
+ return (
100
+ <div
101
+ className={cn("text-muted-foreground text-sm", className)}
102
+ data-slot="timeline-description"
103
+ {...props}
104
+ />
105
+ );
106
+ }
107
+
108
+ export {
109
+ Timeline,
110
+ TimelineItem,
111
+ TimelineDot,
112
+ TimelineContent,
113
+ TimelineTitle,
114
+ TimelineTime,
115
+ TimelineDescription,
116
+ };
@@ -0,0 +1,268 @@
1
+ "use client";
2
+
3
+ import { Toast } from "@base-ui/react/toast";
4
+ import {
5
+ CircleAlertIcon,
6
+ CircleCheckIcon,
7
+ InfoIcon,
8
+ LoaderCircleIcon,
9
+ TriangleAlertIcon,
10
+ } from "lucide-react";
11
+ import { buttonVariants } from "./button";
12
+ import { cn } from "../../lib/utils/css";
13
+
14
+ const toastManager = Toast.createToastManager();
15
+ const anchoredToastManager = Toast.createToastManager();
16
+
17
+ const TOAST_ICONS = {
18
+ error: CircleAlertIcon,
19
+ info: InfoIcon,
20
+ loading: LoaderCircleIcon,
21
+ success: CircleCheckIcon,
22
+ warning: TriangleAlertIcon,
23
+ } as const;
24
+
25
+ type ToastPosition =
26
+ | "top-left"
27
+ | "top-center"
28
+ | "top-right"
29
+ | "bottom-left"
30
+ | "bottom-center"
31
+ | "bottom-right";
32
+
33
+ interface ToastProviderProps extends Toast.Provider.Props {
34
+ position?: ToastPosition;
35
+ }
36
+
37
+ function ToastProvider({
38
+ children,
39
+ position = "bottom-right",
40
+ ...props
41
+ }: ToastProviderProps) {
42
+ return (
43
+ <Toast.Provider toastManager={toastManager} {...props}>
44
+ {children}
45
+ <Toasts position={position} />
46
+ </Toast.Provider>
47
+ );
48
+ }
49
+
50
+ function Toasts({ position = "bottom-right" }: { position: ToastPosition }) {
51
+ const { toasts } = Toast.useToastManager();
52
+ const isTop = position.startsWith("top");
53
+
54
+ return (
55
+ <Toast.Portal data-slot="toast-portal">
56
+ <Toast.Viewport
57
+ className={cn(
58
+ "fixed z-60 mx-auto flex w-[calc(100%-var(--toast-inset)*2)] max-w-90 [--toast-inset:--spacing(4)] sm:[--toast-inset:--spacing(8)]",
59
+ // Vertical positioning
60
+ "data-[position*=top]:top-(--toast-inset)",
61
+ "data-[position*=bottom]:bottom-(--toast-inset)",
62
+ // Horizontal positioning
63
+ "data-[position*=left]:left-(--toast-inset)",
64
+ "data-[position*=right]:right-(--toast-inset)",
65
+ "data-[position*=center]:-translate-x-1/2 data-[position*=center]:left-1/2",
66
+ )}
67
+ data-position={position}
68
+ data-slot="toast-viewport"
69
+ >
70
+ {toasts.map((toast) => {
71
+ const Icon = toast.type
72
+ ? TOAST_ICONS[toast.type as keyof typeof TOAST_ICONS]
73
+ : null;
74
+
75
+ return (
76
+ <Toast.Root
77
+ className={cn(
78
+ "absolute z-[calc(9999-var(--toast-index))] h-(--toast-calc-height) w-full select-none rounded-lg border bg-popover not-dark:bg-clip-padding text-popover-foreground shadow-lg/5 [transition:transform_.5s_cubic-bezier(.22,1,.36,1),opacity_.5s,height_.15s] before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-lg)-1px)] before:shadow-[0_1px_--theme(--color-black/6%)] dark:before:shadow-[0_-1px_--theme(--color-white/6%)]",
79
+ // Base positioning using data-position
80
+ "data-[position*=right]:right-0 data-[position*=right]:left-auto",
81
+ "data-[position*=left]:right-auto data-[position*=left]:left-0",
82
+ "data-[position*=center]:right-0 data-[position*=center]:left-0",
83
+ "data-[position*=top]:top-0 data-[position*=top]:bottom-auto data-[position*=top]:origin-top",
84
+ "data-[position*=bottom]:top-auto data-[position*=bottom]:bottom-0 data-[position*=bottom]:origin-bottom",
85
+ // Gap fill for hover
86
+ "after:absolute after:left-0 after:h-[calc(var(--toast-gap)+1px)] after:w-full",
87
+ "data-[position*=top]:after:top-full",
88
+ "data-[position*=bottom]:after:bottom-full",
89
+ // Define some variables
90
+ "[--toast-calc-height:var(--toast-frontmost-height,var(--toast-height))] [--toast-gap:--spacing(3)] [--toast-peek:--spacing(3)] [--toast-scale:calc(max(0,1-(var(--toast-index)*.1)))] [--toast-shrink:calc(1-var(--toast-scale))]",
91
+ // Define offset-y variable
92
+ "data-[position*=top]:[--toast-calc-offset-y:calc(var(--toast-offset-y)+var(--toast-index)*var(--toast-gap)+var(--toast-swipe-movement-y))]",
93
+ "data-[position*=bottom]:[--toast-calc-offset-y:calc(var(--toast-offset-y)*-1+var(--toast-index)*var(--toast-gap)*-1+var(--toast-swipe-movement-y))]",
94
+ // Default state transform
95
+ "data-[position*=top]:transform-[translateX(var(--toast-swipe-movement-x))_translateY(calc(var(--toast-swipe-movement-y)+(var(--toast-index)*var(--toast-peek))+(var(--toast-shrink)*var(--toast-calc-height))))_scale(var(--toast-scale))]",
96
+ "data-[position*=bottom]:transform-[translateX(var(--toast-swipe-movement-x))_translateY(calc(var(--toast-swipe-movement-y)-(var(--toast-index)*var(--toast-peek))-(var(--toast-shrink)*var(--toast-calc-height))))_scale(var(--toast-scale))]",
97
+ // Limited state
98
+ "data-limited:opacity-0",
99
+ // Expanded state
100
+ "data-expanded:h-(--toast-height)",
101
+ "data-position:data-expanded:transform-[translateX(var(--toast-swipe-movement-x))_translateY(var(--toast-calc-offset-y))]",
102
+ // Starting and ending animations
103
+ "data-[position*=top]:data-starting-style:transform-[translateY(calc(-100%-var(--toast-inset)))]",
104
+ "data-[position*=bottom]:data-starting-style:transform-[translateY(calc(100%+var(--toast-inset)))]",
105
+ "data-ending-style:opacity-0",
106
+ // Ending animations (direction-aware)
107
+ "data-ending-style:not-data-limited:not-data-swipe-direction:transform-[translateY(calc(100%+var(--toast-inset)))]",
108
+ "data-ending-style:data-[swipe-direction=left]:transform-[translateX(calc(var(--toast-swipe-movement-x)-100%-var(--toast-inset)))_translateY(var(--toast-calc-offset-y))]",
109
+ "data-ending-style:data-[swipe-direction=right]:transform-[translateX(calc(var(--toast-swipe-movement-x)+100%+var(--toast-inset)))_translateY(var(--toast-calc-offset-y))]",
110
+ "data-ending-style:data-[swipe-direction=up]:transform-[translateY(calc(var(--toast-swipe-movement-y)-100%-var(--toast-inset)))]",
111
+ "data-ending-style:data-[swipe-direction=down]:transform-[translateY(calc(var(--toast-swipe-movement-y)+100%+var(--toast-inset)))]",
112
+ // Ending animations (expanded)
113
+ "data-expanded:data-ending-style:data-[swipe-direction=left]:transform-[translateX(calc(var(--toast-swipe-movement-x)-100%-var(--toast-inset)))_translateY(var(--toast-calc-offset-y))]",
114
+ "data-expanded:data-ending-style:data-[swipe-direction=right]:transform-[translateX(calc(var(--toast-swipe-movement-x)+100%+var(--toast-inset)))_translateY(var(--toast-calc-offset-y))]",
115
+ "data-expanded:data-ending-style:data-[swipe-direction=up]:transform-[translateY(calc(var(--toast-swipe-movement-y)-100%-var(--toast-inset)))]",
116
+ "data-expanded:data-ending-style:data-[swipe-direction=down]:transform-[translateY(calc(var(--toast-swipe-movement-y)+100%+var(--toast-inset)))]",
117
+ )}
118
+ data-position={position}
119
+ key={toast.id}
120
+ swipeDirection={
121
+ position.includes("center")
122
+ ? [isTop ? "up" : "down"]
123
+ : position.includes("left")
124
+ ? ["left", isTop ? "up" : "down"]
125
+ : ["right", isTop ? "up" : "down"]
126
+ }
127
+ toast={toast}
128
+ >
129
+ <Toast.Content className="pointer-events-auto flex items-center justify-between gap-1.5 overflow-hidden px-3.5 py-3 text-sm transition-opacity duration-250 data-behind:not-data-expanded:pointer-events-none data-behind:opacity-0 data-expanded:opacity-100">
130
+ <div className="flex gap-2">
131
+ {Icon && (
132
+ <div
133
+ className="[&>svg]:h-lh [&>svg]:w-4 [&_svg]:pointer-events-none [&_svg]:shrink-0"
134
+ data-slot="toast-icon"
135
+ >
136
+ <Icon className="in-data-[type=loading]:animate-spin in-data-[type=error]:text-destructive in-data-[type=info]:text-info in-data-[type=success]:text-success in-data-[type=warning]:text-warning in-data-[type=loading]:opacity-80" />
137
+ </div>
138
+ )}
139
+
140
+ <div className="flex flex-col gap-0.5">
141
+ <Toast.Title
142
+ className="font-medium"
143
+ data-slot="toast-title"
144
+ />
145
+ <Toast.Description
146
+ className="text-muted-foreground"
147
+ data-slot="toast-description"
148
+ />
149
+ </div>
150
+ </div>
151
+ {toast.actionProps && (
152
+ <Toast.Action
153
+ className={buttonVariants({ size: "xs" })}
154
+ data-slot="toast-action"
155
+ >
156
+ {toast.actionProps.children}
157
+ </Toast.Action>
158
+ )}
159
+ </Toast.Content>
160
+ </Toast.Root>
161
+ );
162
+ })}
163
+ </Toast.Viewport>
164
+ </Toast.Portal>
165
+ );
166
+ }
167
+
168
+ function AnchoredToastProvider({ children, ...props }: Toast.Provider.Props) {
169
+ return (
170
+ <Toast.Provider toastManager={anchoredToastManager} {...props}>
171
+ {children}
172
+ <AnchoredToasts />
173
+ </Toast.Provider>
174
+ );
175
+ }
176
+
177
+ function AnchoredToasts() {
178
+ const { toasts } = Toast.useToastManager();
179
+
180
+ return (
181
+ <Toast.Portal data-slot="toast-portal-anchored">
182
+ <Toast.Viewport
183
+ className="outline-none"
184
+ data-slot="toast-viewport-anchored"
185
+ >
186
+ {toasts.map((toast) => {
187
+ const Icon = toast.type
188
+ ? TOAST_ICONS[toast.type as keyof typeof TOAST_ICONS]
189
+ : null;
190
+ const tooltipStyle =
191
+ (toast.data as { tooltipStyle?: boolean })?.tooltipStyle ?? false;
192
+ const positionerProps = toast.positionerProps;
193
+
194
+ if (!positionerProps?.anchor) {
195
+ return null;
196
+ }
197
+
198
+ return (
199
+ <Toast.Positioner
200
+ className="z-50 max-w-[min(--spacing(64),var(--available-width))]"
201
+ data-slot="toast-positioner"
202
+ key={toast.id}
203
+ sideOffset={positionerProps.sideOffset ?? 4}
204
+ toast={toast}
205
+ >
206
+ <Toast.Root
207
+ className={cn(
208
+ "relative text-balance border bg-popover not-dark:bg-clip-padding text-popover-foreground text-xs transition-[scale,opacity] before:pointer-events-none before:absolute before:inset-0 before:shadow-[0_1px_--theme(--color-black/6%)] data-ending-style:scale-98 data-starting-style:scale-98 data-ending-style:opacity-0 data-starting-style:opacity-0 dark:before:shadow-[0_-1px_--theme(--color-white/6%)]",
209
+ tooltipStyle
210
+ ? "rounded-md shadow-md/5 before:rounded-[calc(var(--radius-md)-1px)]"
211
+ : "rounded-lg shadow-lg/5 before:rounded-[calc(var(--radius-lg)-1px)]",
212
+ )}
213
+ data-slot="toast-popup"
214
+ toast={toast}
215
+ >
216
+ {tooltipStyle ? (
217
+ <Toast.Content className="pointer-events-auto px-2 py-1">
218
+ <Toast.Title data-slot="toast-title" />
219
+ </Toast.Content>
220
+ ) : (
221
+ <Toast.Content className="pointer-events-auto flex items-center justify-between gap-1.5 overflow-hidden px-3.5 py-3 text-sm">
222
+ <div className="flex gap-2">
223
+ {Icon && (
224
+ <div
225
+ className="[&>svg]:h-lh [&>svg]:w-4 [&_svg]:pointer-events-none [&_svg]:shrink-0"
226
+ data-slot="toast-icon"
227
+ >
228
+ <Icon className="in-data-[type=loading]:animate-spin in-data-[type=error]:text-destructive in-data-[type=info]:text-info in-data-[type=success]:text-success in-data-[type=warning]:text-warning in-data-[type=loading]:opacity-80" />
229
+ </div>
230
+ )}
231
+
232
+ <div className="flex flex-col gap-0.5">
233
+ <Toast.Title
234
+ className="font-medium"
235
+ data-slot="toast-title"
236
+ />
237
+ <Toast.Description
238
+ className="text-muted-foreground"
239
+ data-slot="toast-description"
240
+ />
241
+ </div>
242
+ </div>
243
+ {toast.actionProps && (
244
+ <Toast.Action
245
+ className={buttonVariants({ size: "xs" })}
246
+ data-slot="toast-action"
247
+ >
248
+ {toast.actionProps.children}
249
+ </Toast.Action>
250
+ )}
251
+ </Toast.Content>
252
+ )}
253
+ </Toast.Root>
254
+ </Toast.Positioner>
255
+ );
256
+ })}
257
+ </Toast.Viewport>
258
+ </Toast.Portal>
259
+ );
260
+ }
261
+
262
+ export {
263
+ ToastProvider,
264
+ type ToastPosition,
265
+ toastManager,
266
+ AnchoredToastProvider,
267
+ anchoredToastManager,
268
+ };
@@ -0,0 +1,101 @@
1
+ "use client";
2
+
3
+ import type { Toggle as TogglePrimitive } from "@base-ui/react/toggle";
4
+ import { ToggleGroup as ToggleGroupPrimitive } from "@base-ui/react/toggle-group";
5
+ import type { VariantProps } from "class-variance-authority";
6
+ import * as React from "react";
7
+ import { Separator } from "./separator";
8
+ import {
9
+ Toggle as ToggleComponent,
10
+ type toggleVariants,
11
+ } from "./toggle";
12
+ import { cn } from "../../lib/utils/css";
13
+
14
+ const ToggleGroupContext = React.createContext<
15
+ VariantProps<typeof toggleVariants>
16
+ >({
17
+ size: "default",
18
+ variant: "default",
19
+ });
20
+
21
+ function ToggleGroup({
22
+ className,
23
+ variant = "default",
24
+ size = "default",
25
+ orientation = "horizontal",
26
+ children,
27
+ ...props
28
+ }: ToggleGroupPrimitive.Props & VariantProps<typeof toggleVariants>) {
29
+ return (
30
+ <ToggleGroupPrimitive
31
+ className={cn(
32
+ "flex w-fit *:focus-visible:z-10 dark:*:[[data-slot=separator]:has(+[data-slot=toggle]:hover)]:before:bg-input/64 dark:*:[[data-slot=separator]:has(+[data-slot=toggle][data-pressed])]:before:bg-input dark:*:[[data-slot=toggle]:hover+[data-slot=separator]]:before:bg-input/64 dark:*:[[data-slot=toggle][data-pressed]+[data-slot=separator]]:before:bg-input",
33
+ orientation === "horizontal"
34
+ ? "*:pointer-coarse:after:min-w-auto"
35
+ : "*:pointer-coarse:after:min-h-auto",
36
+ variant === "default"
37
+ ? "gap-0.5"
38
+ : orientation === "horizontal"
39
+ ? "*:not-first:not-data-[slot=separator]:before:-start-[0.5px] *:not-last:not-data-[slot=separator]:before:-end-[0.5px] *:not-first:rounded-s-none *:not-last:rounded-e-none *:not-first:border-s-0 *:not-last:border-e-0 *:not-first:before:rounded-s-none *:not-last:before:rounded-e-none"
40
+ : "*:not-first:not-data-[slot=separator]:before:-top-[0.5px] *:not-last:not-data-[slot=separator]:before:-bottom-[0.5px] flex-col *:not-first:rounded-t-none *:not-last:rounded-b-none *:not-first:border-t-0 *:not-last:border-b-0 *:not-first:before:rounded-t-none *:not-last:before:rounded-b-none *:data-[slot=toggle]:not-last:before:hidden dark:*:last:before:hidden dark:*:first:before:block",
41
+ className,
42
+ )}
43
+ data-size={size}
44
+ data-slot="toggle-group"
45
+ data-variant={variant}
46
+ orientation={orientation}
47
+ {...props}
48
+ >
49
+ <ToggleGroupContext.Provider value={{ size, variant }}>
50
+ {children}
51
+ </ToggleGroupContext.Provider>
52
+ </ToggleGroupPrimitive>
53
+ );
54
+ }
55
+
56
+ function Toggle({
57
+ className,
58
+ children,
59
+ variant,
60
+ size,
61
+ ...props
62
+ }: TogglePrimitive.Props & VariantProps<typeof toggleVariants>) {
63
+ const context = React.useContext(ToggleGroupContext);
64
+
65
+ const resolvedVariant = context.variant || variant;
66
+ const resolvedSize = context.size || size;
67
+
68
+ return (
69
+ <ToggleComponent
70
+ className={className}
71
+ data-size={resolvedSize}
72
+ data-variant={resolvedVariant}
73
+ size={resolvedSize}
74
+ variant={resolvedVariant}
75
+ {...props}
76
+ >
77
+ {children}
78
+ </ToggleComponent>
79
+ );
80
+ }
81
+
82
+ function ToggleGroupSeparator({
83
+ className,
84
+ orientation = "vertical",
85
+ ...props
86
+ }: {
87
+ className?: string;
88
+ } & React.ComponentProps<typeof Separator>) {
89
+ return (
90
+ <Separator
91
+ className={cn(
92
+ "pointer-events-none relative bg-input before:absolute before:inset-0 dark:before:bg-input/32",
93
+ className,
94
+ )}
95
+ orientation={orientation}
96
+ {...props}
97
+ />
98
+ );
99
+ }
100
+
101
+ export { ToggleGroup, Toggle, Toggle as ToggleGroupItem, ToggleGroupSeparator };
@@ -0,0 +1,45 @@
1
+ "use client";
2
+
3
+ import { Toggle as TogglePrimitive } from "@base-ui/react/toggle";
4
+ import { cva, type VariantProps } from "class-variance-authority";
5
+
6
+ import { cn } from "../../lib/utils/css";
7
+
8
+ const toggleVariants = cva(
9
+ "[&_svg]:-mx-0.5 relative inline-flex shrink-0 cursor-pointer select-none items-center justify-center gap-2 whitespace-nowrap rounded-lg border font-medium text-base text-foreground outline-none transition-[box-shadow,background-color] duration-100 before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-lg)-1px)] pointer-coarse:after:absolute pointer-coarse:after:size-full pointer-coarse:after:min-h-11 pointer-coarse:after:min-w-11 hover:bg-accent focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:ring-offset-background disabled:pointer-events-none disabled:opacity-64 data-pressed:bg-input/64 data-pressed:text-accent-foreground 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 [&_svg]:transition-transform [&_svg]:duration-150 [&_svg]:ease-[cubic-bezier(0.34,1.56,0.64,1)] data-pressed:[&_svg]:scale-115",
10
+ {
11
+ defaultVariants: {
12
+ size: "default",
13
+ variant: "default",
14
+ },
15
+ variants: {
16
+ size: {
17
+ default: "h-9 min-w-9 px-[calc(--spacing(2)-1px)] sm:h-8 sm:min-w-8",
18
+ lg: "h-10 min-w-10 px-[calc(--spacing(2.5)-1px)] sm:h-9 sm:min-w-9",
19
+ sm: "h-8 min-w-8 px-[calc(--spacing(1.5)-1px)] sm:h-7 sm:min-w-7",
20
+ },
21
+ variant: {
22
+ default: "border-transparent",
23
+ outline:
24
+ "border-input bg-background not-dark:bg-clip-padding shadow-xs/5 not-disabled:not-active:not-data-pressed:before:shadow-[0_1px_--theme(--color-black/6%)] dark:bg-input/32 dark:data-pressed:bg-input dark:hover:bg-input/64 dark:not-disabled:not-active:not-data-pressed:before:shadow-[0_-1px_--theme(--color-white/6%)] dark:not-disabled:not-data-pressed:before:shadow-[0_-1px_--theme(--color-white/2%)] [:disabled,:active,[data-pressed]]:shadow-none",
25
+ },
26
+ },
27
+ },
28
+ );
29
+
30
+ function Toggle({
31
+ className,
32
+ variant,
33
+ size,
34
+ ...props
35
+ }: TogglePrimitive.Props & VariantProps<typeof toggleVariants>) {
36
+ return (
37
+ <TogglePrimitive
38
+ className={cn(toggleVariants({ className, size, variant }))}
39
+ data-slot="toggle"
40
+ {...props}
41
+ />
42
+ );
43
+ }
44
+
45
+ export { Toggle, toggleVariants };
@@ -0,0 +1,89 @@
1
+ "use client";
2
+
3
+ import { Toolbar as ToolbarPrimitive } from "@base-ui/react/toolbar";
4
+
5
+ import { cn } from "../../lib/utils/css";
6
+
7
+ function Toolbar({ className, ...props }: ToolbarPrimitive.Root.Props) {
8
+ return (
9
+ <ToolbarPrimitive.Root
10
+ className={cn(
11
+ "relative flex gap-2 rounded-xl border bg-card not-dark:bg-clip-padding p-1 text-card-foreground",
12
+ className,
13
+ )}
14
+ data-slot="toolbar"
15
+ {...props}
16
+ />
17
+ );
18
+ }
19
+
20
+ function ToolbarButton({ className, ...props }: ToolbarPrimitive.Button.Props) {
21
+ return (
22
+ <ToolbarPrimitive.Button
23
+ className={cn(
24
+ "transition-[box-shadow,background-color,color,filter] duration-150 ease-out [:active:not(:disabled)]:brightness-95",
25
+ className,
26
+ )}
27
+ data-slot="toolbar-button"
28
+ {...props}
29
+ />
30
+ );
31
+ }
32
+
33
+ function ToolbarLink({ className, ...props }: ToolbarPrimitive.Link.Props) {
34
+ return (
35
+ <ToolbarPrimitive.Link
36
+ className={cn(
37
+ "transition-[color,opacity] duration-150 ease-out",
38
+ className,
39
+ )}
40
+ data-slot="toolbar-link"
41
+ {...props}
42
+ />
43
+ );
44
+ }
45
+
46
+ function ToolbarInput({ className, ...props }: ToolbarPrimitive.Input.Props) {
47
+ return (
48
+ <ToolbarPrimitive.Input
49
+ className={cn(className)}
50
+ data-slot="toolbar-input"
51
+ {...props}
52
+ />
53
+ );
54
+ }
55
+
56
+ function ToolbarGroup({ className, ...props }: ToolbarPrimitive.Group.Props) {
57
+ return (
58
+ <ToolbarPrimitive.Group
59
+ className={cn("flex items-center gap-1", className)}
60
+ data-slot="toolbar-group"
61
+ {...props}
62
+ />
63
+ );
64
+ }
65
+
66
+ function ToolbarSeparator({
67
+ className,
68
+ ...props
69
+ }: ToolbarPrimitive.Separator.Props) {
70
+ return (
71
+ <ToolbarPrimitive.Separator
72
+ className={cn(
73
+ "shrink-0 bg-border data-[orientation=horizontal]:my-0.5 data-[orientation=vertical]:my-1.5 data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:w-px data-[orientation=vertical]:not-[[class^='h-']]:not-[[class*='_h-']]:self-stretch",
74
+ className,
75
+ )}
76
+ data-slot="toolbar-separator"
77
+ {...props}
78
+ />
79
+ );
80
+ }
81
+
82
+ export {
83
+ Toolbar,
84
+ ToolbarGroup,
85
+ ToolbarSeparator,
86
+ ToolbarButton,
87
+ ToolbarLink,
88
+ ToolbarInput,
89
+ };