@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,38 @@
1
+ import { Slot } from "@radix-ui/react-slot";
2
+ import { cn } from "../../lib/utils/css";
3
+ import type { AsChildProps } from "../../types/helpers";
4
+
5
+ const scrollerClassName =
6
+ "absolute top-1/2 z-10 -translate-y-1/2 data-closed:opacity-0";
7
+
8
+ const LeftScroller = ({
9
+ className,
10
+ asChild,
11
+ ...props
12
+ }: AsChildProps<"button">) => {
13
+ const Comp = asChild ? Slot : "button";
14
+ return (
15
+ <Comp
16
+ {...(asChild ? {} : { type: "button" })}
17
+ className={cn(scrollerClassName, "left-0", className)}
18
+ {...props}
19
+ />
20
+ );
21
+ };
22
+
23
+ const RightScroller = ({
24
+ className,
25
+ asChild,
26
+ ...props
27
+ }: AsChildProps<"button">) => {
28
+ const Comp = asChild ? Slot : "button";
29
+ return (
30
+ <Comp
31
+ {...(asChild ? {} : { type: "button" })}
32
+ className={cn(scrollerClassName, "right-0", className)}
33
+ {...props}
34
+ />
35
+ );
36
+ };
37
+
38
+ export { LeftScroller, RightScroller };
@@ -0,0 +1,118 @@
1
+ "use client";
2
+
3
+ import { cva, type VariantProps } from "class-variance-authority";
4
+ import type * as React from "react";
5
+
6
+ import { cn } from "../../lib/utils/css";
7
+
8
+ const sectionHeaderTitleVariants = cva(
9
+ "min-w-0 font-semibold text-foreground tracking-tight",
10
+ {
11
+ defaultVariants: { size: "default" },
12
+ variants: {
13
+ size: {
14
+ sm: "text-sm",
15
+ default: "text-base",
16
+ lg: "text-lg",
17
+ },
18
+ },
19
+ },
20
+ );
21
+
22
+ const sectionHeaderDescriptionVariants = cva(
23
+ "text-muted-foreground leading-relaxed",
24
+ {
25
+ defaultVariants: { size: "default" },
26
+ variants: {
27
+ size: {
28
+ sm: "text-xs",
29
+ default: "text-sm",
30
+ lg: "text-sm",
31
+ },
32
+ },
33
+ },
34
+ );
35
+
36
+ interface SectionHeaderProps
37
+ extends Omit<React.ComponentProps<"div">, "title">,
38
+ VariantProps<typeof sectionHeaderTitleVariants> {
39
+ title?: React.ReactNode;
40
+ description?: React.ReactNode;
41
+ /** Right-aligned actions (buttons, counts, menus). */
42
+ actions?: React.ReactNode;
43
+ /** A leading node — e.g. a `<FeaturedIcon />` or a count badge. */
44
+ icon?: React.ReactNode;
45
+ /** Adds a bottom hairline + padding, so the header sits above a list/grid. */
46
+ border?: boolean;
47
+ }
48
+
49
+ /**
50
+ * A titled section heading: title + optional description on the left, optional
51
+ * actions on the right, with an optional leading icon. One altitude below the
52
+ * page-level `DashboardHeader` — use it to introduce a card body, a list, or a
53
+ * settings group.
54
+ */
55
+ function SectionHeader({
56
+ className,
57
+ title,
58
+ description,
59
+ actions,
60
+ icon,
61
+ size,
62
+ border,
63
+ children,
64
+ ...props
65
+ }: SectionHeaderProps) {
66
+ return (
67
+ <div
68
+ className={cn(
69
+ "flex items-start justify-between gap-3",
70
+ border && "border-b pb-4",
71
+ className,
72
+ )}
73
+ data-slot="section-header"
74
+ {...props}
75
+ >
76
+ <div className="flex min-w-0 items-start gap-3">
77
+ {icon ? (
78
+ <div className="shrink-0" data-slot="section-header-icon">
79
+ {icon}
80
+ </div>
81
+ ) : null}
82
+ <div className="min-w-0 space-y-0.5">
83
+ {title ? (
84
+ <div
85
+ className={cn(sectionHeaderTitleVariants({ size }))}
86
+ data-slot="section-header-title"
87
+ >
88
+ {title}
89
+ </div>
90
+ ) : null}
91
+ {description ? (
92
+ <p
93
+ className={cn(sectionHeaderDescriptionVariants({ size }))}
94
+ data-slot="section-header-description"
95
+ >
96
+ {description}
97
+ </p>
98
+ ) : null}
99
+ {children}
100
+ </div>
101
+ </div>
102
+ {actions ? (
103
+ <div
104
+ className="flex shrink-0 items-center gap-2"
105
+ data-slot="section-header-actions"
106
+ >
107
+ {actions}
108
+ </div>
109
+ ) : null}
110
+ </div>
111
+ );
112
+ }
113
+
114
+ export {
115
+ SectionHeader,
116
+ sectionHeaderTitleVariants,
117
+ sectionHeaderDescriptionVariants,
118
+ };
@@ -0,0 +1,181 @@
1
+ "use client";
2
+
3
+ import { Select as SelectPrimitive } from "@base-ui/react/select";
4
+ import {
5
+ ChevronDownIcon,
6
+ ChevronsUpDownIcon,
7
+ ChevronUpIcon,
8
+ } from "lucide-react";
9
+
10
+ import { cn } from "../../lib/utils/css";
11
+
12
+ const Select = SelectPrimitive.Root;
13
+
14
+ function SelectTrigger({
15
+ className,
16
+ size = "default",
17
+ children,
18
+ ...props
19
+ }: SelectPrimitive.Trigger.Props & {
20
+ size?: "sm" | "default" | "lg";
21
+ }) {
22
+ return (
23
+ <SelectPrimitive.Trigger
24
+ className={cn(
25
+ "relative inline-flex min-h-9 w-full min-w-36 select-none items-center justify-center gap-2 rounded-lg border border-input bg-background not-dark:bg-clip-padding px-[calc(--spacing(3)-1px)] text-left text-base text-foreground shadow-xs/5 outline-none ring-ring/24 transition-shadow before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-lg)-1px)] not-data-disabled:not-focus-visible:not-aria-invalid:not-data-pressed:before:shadow-[0_1px_--theme(--color-black/4%)] pointer-coarse:after:absolute pointer-coarse:after:size-full pointer-coarse:after:min-h-11 focus-visible:border-ring focus-visible:ring-[3px] aria-invalid:border-destructive/36 focus-visible:aria-invalid:border-destructive/64 focus-visible:aria-invalid:ring-destructive/16 data-disabled:pointer-events-none data-disabled:opacity-64 sm:min-h-8 sm:text-sm dark:aria-invalid:ring-destructive/24 dark:not-data-disabled:not-focus-visible:not-aria-invalid:not-data-pressed:before:shadow-[0_-1px_--theme(--color-white/6%)] [&_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 [[data-disabled],:focus-visible,[aria-invalid],[data-pressed]]:shadow-none",
26
+ size === "sm" &&
27
+ "min-h-8 gap-1.5 px-[calc(--spacing(2.5)-1px)] sm:min-h-7",
28
+ size === "lg" && "min-h-10 sm:min-h-9",
29
+ className,
30
+ )}
31
+ data-slot="select-trigger"
32
+ {...props}
33
+ >
34
+ {children}
35
+ <SelectPrimitive.Icon data-slot="select-icon">
36
+ <ChevronsUpDownIcon className="-me-1 size-4.5 opacity-80 sm:size-4" />
37
+ </SelectPrimitive.Icon>
38
+ </SelectPrimitive.Trigger>
39
+ );
40
+ }
41
+
42
+ function SelectValue({ className, ...props }: SelectPrimitive.Value.Props) {
43
+ return (
44
+ <SelectPrimitive.Value
45
+ className={cn(
46
+ "flex-1 truncate data-placeholder:text-muted-foreground",
47
+ className,
48
+ )}
49
+ data-slot="select-value"
50
+ {...props}
51
+ />
52
+ );
53
+ }
54
+
55
+ function SelectPopup({
56
+ className,
57
+ children,
58
+ sideOffset = 4,
59
+ alignItemWithTrigger = true,
60
+ ...props
61
+ }: SelectPrimitive.Popup.Props & {
62
+ sideOffset?: SelectPrimitive.Positioner.Props["sideOffset"];
63
+ alignItemWithTrigger?: SelectPrimitive.Positioner.Props["alignItemWithTrigger"];
64
+ }) {
65
+ return (
66
+ <SelectPrimitive.Portal>
67
+ <SelectPrimitive.Positioner
68
+ alignItemWithTrigger={alignItemWithTrigger}
69
+ className="z-50 select-none"
70
+ data-slot="select-positioner"
71
+ sideOffset={sideOffset}
72
+ >
73
+ <SelectPrimitive.Popup
74
+ className="origin-(--transform-origin) text-foreground transition-[transform,scale,opacity] duration-150 ease-out data-ending-style:scale-95 data-ending-style:opacity-0 data-starting-style:scale-95 data-starting-style:opacity-0"
75
+ data-slot="select-popup"
76
+ {...props}
77
+ >
78
+ <SelectPrimitive.ScrollUpArrow
79
+ className="top-0 z-50 flex h-6 w-full cursor-default items-center justify-center before:pointer-events-none before:absolute before:inset-x-px before:top-px before:h-[200%] before:rounded-t-[calc(var(--radius-lg)-1px)] before:bg-linear-to-b before:from-50% before:from-popover"
80
+ data-slot="select-scroll-up-arrow"
81
+ >
82
+ <ChevronUpIcon className="relative size-4.5 sm:size-4" />
83
+ </SelectPrimitive.ScrollUpArrow>
84
+ <div className="relative h-full rounded-lg border bg-popover not-dark:bg-clip-padding shadow-lg/5 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%)]">
85
+ <SelectPrimitive.List
86
+ className={cn(
87
+ "max-h-(--available-height) min-w-(--anchor-width) overflow-y-auto p-1",
88
+ className,
89
+ )}
90
+ data-slot="select-list"
91
+ >
92
+ {children}
93
+ </SelectPrimitive.List>
94
+ </div>
95
+ <SelectPrimitive.ScrollDownArrow
96
+ className="bottom-0 z-50 flex h-6 w-full cursor-default items-center justify-center before:pointer-events-none before:absolute before:inset-x-px before:bottom-px before:h-[200%] before:rounded-b-[calc(var(--radius-lg)-1px)] before:bg-linear-to-t before:from-50% before:from-popover"
97
+ data-slot="select-scroll-down-arrow"
98
+ >
99
+ <ChevronDownIcon className="relative size-4.5 sm:size-4" />
100
+ </SelectPrimitive.ScrollDownArrow>
101
+ </SelectPrimitive.Popup>
102
+ </SelectPrimitive.Positioner>
103
+ </SelectPrimitive.Portal>
104
+ );
105
+ }
106
+
107
+ function SelectItem({
108
+ className,
109
+ children,
110
+ ...props
111
+ }: SelectPrimitive.Item.Props) {
112
+ return (
113
+ <SelectPrimitive.Item
114
+ className={cn(
115
+ "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 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",
116
+ className,
117
+ )}
118
+ data-slot="select-item"
119
+ {...props}
120
+ >
121
+ <SelectPrimitive.ItemIndicator className="col-start-1">
122
+ {/** biome-ignore lint/a11y/noSvgWithoutTitle: Imported from library */}
123
+ <svg
124
+ fill="none"
125
+ height="24"
126
+ stroke="currentColor"
127
+ strokeLinecap="round"
128
+ strokeLinejoin="round"
129
+ strokeWidth="2"
130
+ viewBox="0 0 24 24"
131
+ width="24"
132
+ xmlns="http://www.w3.org/1500/svg"
133
+ >
134
+ <path d="M5.252 12.7 10.2 18.63 18.748 5.37" />
135
+ </svg>
136
+ </SelectPrimitive.ItemIndicator>
137
+ <SelectPrimitive.ItemText className="col-start-2 min-w-0">
138
+ {children}
139
+ </SelectPrimitive.ItemText>
140
+ </SelectPrimitive.Item>
141
+ );
142
+ }
143
+
144
+ function SelectSeparator({
145
+ className,
146
+ ...props
147
+ }: SelectPrimitive.Separator.Props) {
148
+ return (
149
+ <SelectPrimitive.Separator
150
+ className={cn("mx-2 my-1 h-px bg-border", className)}
151
+ data-slot="select-separator"
152
+ {...props}
153
+ />
154
+ );
155
+ }
156
+
157
+ function SelectGroup(props: SelectPrimitive.Group.Props) {
158
+ return <SelectPrimitive.Group data-slot="select-group" {...props} />;
159
+ }
160
+
161
+ function SelectGroupLabel(props: SelectPrimitive.GroupLabel.Props) {
162
+ return (
163
+ <SelectPrimitive.GroupLabel
164
+ className="px-2 py-1.5 font-medium text-muted-foreground text-xs"
165
+ data-slot="select-group-label"
166
+ {...props}
167
+ />
168
+ );
169
+ }
170
+
171
+ export {
172
+ Select,
173
+ SelectTrigger,
174
+ SelectValue,
175
+ SelectPopup,
176
+ SelectPopup as SelectContent,
177
+ SelectItem,
178
+ SelectSeparator,
179
+ SelectGroup,
180
+ SelectGroupLabel,
181
+ };
@@ -0,0 +1,23 @@
1
+ import { Separator as SeparatorPrimitive } from "@base-ui/react/separator";
2
+
3
+ import { cn } from "../../lib/utils/css";
4
+
5
+ function Separator({
6
+ className,
7
+ orientation = "horizontal",
8
+ ...props
9
+ }: SeparatorPrimitive.Props) {
10
+ return (
11
+ <SeparatorPrimitive
12
+ className={cn(
13
+ "shrink-0 bg-border 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",
14
+ className,
15
+ )}
16
+ data-slot="separator"
17
+ orientation={orientation}
18
+ {...props}
19
+ />
20
+ );
21
+ }
22
+
23
+ export { Separator };
@@ -0,0 +1,224 @@
1
+ "use client";
2
+
3
+ import { Dialog as SheetPrimitive } from "@base-ui/react/dialog";
4
+ import { cva } from "class-variance-authority";
5
+ import { XIcon } from "lucide-react";
6
+ import { Button } from "./button";
7
+ import { ScrollArea } from "./scroll-area";
8
+ import { cn } from "../../lib/utils/css";
9
+
10
+ const Sheet = SheetPrimitive.Root;
11
+
12
+ const SheetPortal = SheetPrimitive.Portal;
13
+
14
+ function SheetTrigger(props: SheetPrimitive.Trigger.Props) {
15
+ return <SheetPrimitive.Trigger data-slot="sheet-trigger" {...props} />;
16
+ }
17
+
18
+ function SheetClose(props: SheetPrimitive.Close.Props) {
19
+ return <SheetPrimitive.Close data-slot="sheet-close" {...props} />;
20
+ }
21
+
22
+ function SheetBackdrop({ className, ...props }: SheetPrimitive.Backdrop.Props) {
23
+ return (
24
+ <SheetPrimitive.Backdrop
25
+ className={cn(
26
+ "fixed inset-0 z-50 bg-black/32 backdrop-blur-sm transition-all duration-200 data-ending-style:opacity-0 data-starting-style:opacity-0",
27
+ className,
28
+ )}
29
+ data-slot="sheet-backdrop"
30
+ {...props}
31
+ />
32
+ );
33
+ }
34
+
35
+ export const sheetViewportVariants = cva("fixed inset-0 z-50 grid", {
36
+ variants: {
37
+ side: {
38
+ bottom: "grid grid-rows-[1fr_auto] pt-12",
39
+ top: "grid grid-rows-[auto_1fr] pb-12",
40
+ left: "flex justify-start",
41
+ right: "flex justify-end",
42
+ },
43
+ variant: {
44
+ default: "",
45
+ inset: "sm:p-4",
46
+ },
47
+ },
48
+ });
49
+
50
+ function SheetViewport({
51
+ className,
52
+ side,
53
+ variant = "default",
54
+ ...props
55
+ }: SheetPrimitive.Viewport.Props & {
56
+ side?: "right" | "left" | "top" | "bottom";
57
+ variant?: "default" | "inset";
58
+ }) {
59
+ return (
60
+ <SheetPrimitive.Viewport
61
+ className={cn(sheetViewportVariants({ side, variant }), className)}
62
+ data-slot="sheet-viewport"
63
+ {...props}
64
+ />
65
+ );
66
+ }
67
+
68
+ export const sheetPopupVariants = cva(
69
+ "relative flex max-h-full min-h-0 w-full min-w-0 flex-col bg-popover not-dark:bg-clip-padding text-popover-foreground shadow-lg/5 transition-[opacity,translate] duration-200 ease-in-out will-change-transform before:pointer-events-none before:absolute before:inset-0 before:shadow-[0_1px_--theme(--color-black/6%)] data-ending-style:opacity-0 data-starting-style:opacity-0 max-sm:before:hidden dark:before:shadow-[0_-1px_--theme(--color-white/6%)]",
70
+ {
71
+ defaultVariants: {
72
+ variant: "default",
73
+ },
74
+ variants: {
75
+ side: {
76
+ bottom:
77
+ "row-start-2 border-t data-ending-style:translate-y-8 data-starting-style:translate-y-8",
78
+ top: "data-ending-style:-translate-y-8 data-starting-style:-translate-y-8 border-b",
79
+ left: "data-ending-style:-translate-x-8 data-starting-style:-translate-x-8 w-[calc(100%-(--spacing(12)))] max-w-md border-e",
80
+ right:
81
+ "col-start-2 w-[calc(100%-(--spacing(12)))] max-w-md border-s data-ending-style:translate-x-8 data-starting-style:translate-x-8",
82
+ },
83
+ variant: {
84
+ default: "",
85
+ inset:
86
+ "before:hidden sm:rounded-2xl sm:border sm:before:rounded-[calc(var(--radius-2xl)-1px)] sm:**:data-[slot=sheet-footer]:rounded-b-[calc(var(--radius-2xl)-1px)]",
87
+ },
88
+ },
89
+ },
90
+ );
91
+
92
+ function SheetPopup({
93
+ className,
94
+ children,
95
+ showCloseButton = true,
96
+ side = "right",
97
+ variant = "default",
98
+ ...props
99
+ }: SheetPrimitive.Popup.Props & {
100
+ showCloseButton?: boolean;
101
+ side?: "right" | "left" | "top" | "bottom";
102
+ variant?: "default" | "inset";
103
+ }) {
104
+ return (
105
+ <SheetPortal>
106
+ <SheetBackdrop />
107
+ <SheetViewport side={side} variant={variant}>
108
+ <SheetPrimitive.Popup
109
+ className={cn(sheetPopupVariants({ side, variant }), className)}
110
+ data-slot="sheet-popup"
111
+ {...props}
112
+ >
113
+ {children}
114
+ {showCloseButton && (
115
+ <SheetPrimitive.Close
116
+ aria-label="Close"
117
+ className="absolute end-2 top-2"
118
+ render={<Button size="icon" variant="ghost" />}
119
+ >
120
+ <XIcon />
121
+ </SheetPrimitive.Close>
122
+ )}
123
+ </SheetPrimitive.Popup>
124
+ </SheetViewport>
125
+ </SheetPortal>
126
+ );
127
+ }
128
+
129
+ function SheetHeader({ className, ...props }: React.ComponentProps<"div">) {
130
+ return (
131
+ <div
132
+ className={cn(
133
+ "flex flex-col gap-2 p-6 in-[[data-slot=sheet-popup]:has([data-slot=sheet-panel])]:pb-3 max-sm:pb-4",
134
+ className,
135
+ )}
136
+ data-slot="sheet-header"
137
+ {...props}
138
+ />
139
+ );
140
+ }
141
+
142
+ function SheetFooter({
143
+ className,
144
+ variant = "default",
145
+ ...props
146
+ }: React.ComponentProps<"div"> & {
147
+ variant?: "default" | "bare";
148
+ }) {
149
+ return (
150
+ <div
151
+ className={cn(
152
+ "flex flex-col-reverse gap-2 px-6 sm:flex-row sm:justify-end",
153
+ variant === "default" && "border-t bg-muted/72 py-4",
154
+ variant === "bare" &&
155
+ "in-[[data-slot=sheet-popup]:has([data-slot=sheet-panel])]:pt-3 pt-4 pb-6",
156
+ className,
157
+ )}
158
+ data-slot="sheet-footer"
159
+ {...props}
160
+ />
161
+ );
162
+ }
163
+
164
+ function SheetTitle({ className, ...props }: SheetPrimitive.Title.Props) {
165
+ return (
166
+ <SheetPrimitive.Title
167
+ className={cn(
168
+ "font-heading font-semibold text-xl leading-none",
169
+ className,
170
+ )}
171
+ data-slot="sheet-title"
172
+ {...props}
173
+ />
174
+ );
175
+ }
176
+
177
+ function SheetDescription({
178
+ className,
179
+ ...props
180
+ }: SheetPrimitive.Description.Props) {
181
+ return (
182
+ <SheetPrimitive.Description
183
+ className={cn("text-muted-foreground text-sm", className)}
184
+ data-slot="sheet-description"
185
+ {...props}
186
+ />
187
+ );
188
+ }
189
+
190
+ function SheetPanel({
191
+ className,
192
+ scrollFade = true,
193
+ ...props
194
+ }: React.ComponentProps<"div"> & { scrollFade?: boolean }) {
195
+ return (
196
+ <ScrollArea scrollFade={scrollFade}>
197
+ <div
198
+ className={cn(
199
+ "p-6 in-[[data-slot=sheet-popup]:has([data-slot=sheet-header])]:pt-1 in-[[data-slot=sheet-popup]:has([data-slot=sheet-footer]:not(.border-t))]:pb-1",
200
+ className,
201
+ )}
202
+ data-slot="sheet-panel"
203
+ {...props}
204
+ />
205
+ </ScrollArea>
206
+ );
207
+ }
208
+
209
+ export {
210
+ Sheet,
211
+ SheetTrigger,
212
+ SheetPortal,
213
+ SheetClose,
214
+ SheetBackdrop,
215
+ SheetViewport,
216
+ SheetBackdrop as SheetOverlay,
217
+ SheetPopup,
218
+ SheetPopup as SheetContent,
219
+ SheetHeader,
220
+ SheetFooter,
221
+ SheetTitle,
222
+ SheetDescription,
223
+ SheetPanel,
224
+ };