@oppulence/design-system 1.0.2
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 +115 -0
- package/components.json +21 -0
- package/hooks/use-mobile.tsx +21 -0
- package/lib/utils.ts +6 -0
- package/package.json +104 -0
- package/postcss.config.mjs +8 -0
- package/src/components/atoms/aspect-ratio.tsx +21 -0
- package/src/components/atoms/avatar.tsx +91 -0
- package/src/components/atoms/badge.tsx +47 -0
- package/src/components/atoms/button.tsx +128 -0
- package/src/components/atoms/checkbox.tsx +24 -0
- package/src/components/atoms/container.tsx +42 -0
- package/src/components/atoms/heading.tsx +56 -0
- package/src/components/atoms/index.ts +21 -0
- package/src/components/atoms/input.tsx +18 -0
- package/src/components/atoms/kbd.tsx +23 -0
- package/src/components/atoms/label.tsx +15 -0
- package/src/components/atoms/logo.tsx +52 -0
- package/src/components/atoms/progress.tsx +79 -0
- package/src/components/atoms/separator.tsx +17 -0
- package/src/components/atoms/skeleton.tsx +13 -0
- package/src/components/atoms/slider.tsx +56 -0
- package/src/components/atoms/spinner.tsx +14 -0
- package/src/components/atoms/stack.tsx +126 -0
- package/src/components/atoms/switch.tsx +26 -0
- package/src/components/atoms/text.tsx +69 -0
- package/src/components/atoms/textarea.tsx +19 -0
- package/src/components/atoms/toggle.tsx +40 -0
- package/src/components/molecules/accordion.tsx +72 -0
- package/src/components/molecules/ai-chat.tsx +251 -0
- package/src/components/molecules/alert.tsx +131 -0
- package/src/components/molecules/breadcrumb.tsx +301 -0
- package/src/components/molecules/button-group.tsx +96 -0
- package/src/components/molecules/card.tsx +184 -0
- package/src/components/molecules/collapsible.tsx +21 -0
- package/src/components/molecules/command-search.tsx +148 -0
- package/src/components/molecules/empty.tsx +98 -0
- package/src/components/molecules/field.tsx +217 -0
- package/src/components/molecules/grid.tsx +141 -0
- package/src/components/molecules/hover-card.tsx +45 -0
- package/src/components/molecules/index.ts +29 -0
- package/src/components/molecules/input-group.tsx +151 -0
- package/src/components/molecules/input-otp.tsx +74 -0
- package/src/components/molecules/item.tsx +194 -0
- package/src/components/molecules/page-header.tsx +89 -0
- package/src/components/molecules/pagination.tsx +130 -0
- package/src/components/molecules/popover.tsx +96 -0
- package/src/components/molecules/radio-group.tsx +37 -0
- package/src/components/molecules/resizable.tsx +52 -0
- package/src/components/molecules/scroll-area.tsx +45 -0
- package/src/components/molecules/section.tsx +108 -0
- package/src/components/molecules/select.tsx +201 -0
- package/src/components/molecules/settings.tsx +197 -0
- package/src/components/molecules/table.tsx +111 -0
- package/src/components/molecules/tabs.tsx +74 -0
- package/src/components/molecules/theme-switcher.tsx +187 -0
- package/src/components/molecules/toggle-group.tsx +89 -0
- package/src/components/molecules/tooltip.tsx +66 -0
- package/src/components/organisms/alert-dialog.tsx +152 -0
- package/src/components/organisms/app-shell.tsx +939 -0
- package/src/components/organisms/calendar.tsx +212 -0
- package/src/components/organisms/carousel.tsx +230 -0
- package/src/components/organisms/chart.tsx +333 -0
- package/src/components/organisms/combobox.tsx +274 -0
- package/src/components/organisms/command.tsx +200 -0
- package/src/components/organisms/context-menu.tsx +229 -0
- package/src/components/organisms/dialog.tsx +134 -0
- package/src/components/organisms/drawer.tsx +123 -0
- package/src/components/organisms/dropdown-menu.tsx +256 -0
- package/src/components/organisms/index.ts +17 -0
- package/src/components/organisms/menubar.tsx +203 -0
- package/src/components/organisms/navigation-menu.tsx +143 -0
- package/src/components/organisms/page-layout.tsx +105 -0
- package/src/components/organisms/sheet.tsx +126 -0
- package/src/components/organisms/sidebar.tsx +723 -0
- package/src/components/organisms/sonner.tsx +41 -0
- package/src/components/ui/index.ts +3 -0
- package/src/index.ts +3 -0
- package/src/styles/globals.css +297 -0
- package/tailwind.config.ts +77 -0
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { Command as CommandPrimitive } from "cmdk";
|
|
4
|
+
import * as React from "react";
|
|
5
|
+
|
|
6
|
+
import { Dialog as DialogPrimitive } from "@base-ui/react/dialog";
|
|
7
|
+
import { cva, type VariantProps } from "class-variance-authority";
|
|
8
|
+
import { CheckIcon, SearchIcon } from "lucide-react";
|
|
9
|
+
|
|
10
|
+
const commandVariants = cva(
|
|
11
|
+
"bg-popover text-popover-foreground rounded-xl p-1 flex size-full flex-col overflow-hidden",
|
|
12
|
+
{
|
|
13
|
+
variants: {
|
|
14
|
+
width: {
|
|
15
|
+
auto: "",
|
|
16
|
+
sm: "w-sm",
|
|
17
|
+
md: "w-md",
|
|
18
|
+
lg: "w-lg",
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
defaultVariants: {
|
|
22
|
+
width: "auto",
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
);
|
|
26
|
+
|
|
27
|
+
interface CommandProps
|
|
28
|
+
extends
|
|
29
|
+
Omit<React.ComponentProps<typeof CommandPrimitive>, "className">,
|
|
30
|
+
VariantProps<typeof commandVariants> {}
|
|
31
|
+
|
|
32
|
+
function Command({ width, ...props }: CommandProps) {
|
|
33
|
+
return (
|
|
34
|
+
<CommandPrimitive
|
|
35
|
+
data-slot="command"
|
|
36
|
+
className={commandVariants({ width })}
|
|
37
|
+
{...props}
|
|
38
|
+
/>
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function CommandDialog({
|
|
43
|
+
title = "Command Palette",
|
|
44
|
+
description = "Search for a command to run...",
|
|
45
|
+
children,
|
|
46
|
+
...props
|
|
47
|
+
}: Omit<DialogPrimitive.Root.Props, "children"> & {
|
|
48
|
+
title?: string;
|
|
49
|
+
description?: string;
|
|
50
|
+
children: React.ReactNode;
|
|
51
|
+
}) {
|
|
52
|
+
return (
|
|
53
|
+
<DialogPrimitive.Root data-slot="dialog" {...props}>
|
|
54
|
+
<DialogPrimitive.Portal>
|
|
55
|
+
<DialogPrimitive.Backdrop
|
|
56
|
+
data-slot="dialog-overlay"
|
|
57
|
+
className="data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 bg-black/10 duration-100 supports-backdrop-filter:backdrop-blur-xs fixed inset-0 isolate z-50"
|
|
58
|
+
/>
|
|
59
|
+
<DialogPrimitive.Popup
|
|
60
|
+
data-slot="command-dialog-content"
|
|
61
|
+
className="data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 bg-background ring-foreground/10 rounded-xl p-0 ring-1 duration-100 sm:max-w-lg group/dialog-content fixed top-1/2 left-1/2 z-50 grid w-full max-w-lg -translate-x-1/2 -translate-y-1/2 overflow-hidden outline-none"
|
|
62
|
+
>
|
|
63
|
+
<div
|
|
64
|
+
data-slot="dialog-header"
|
|
65
|
+
className="sr-only flex flex-col gap-1.5 text-center sm:text-left"
|
|
66
|
+
>
|
|
67
|
+
<DialogPrimitive.Title
|
|
68
|
+
data-slot="dialog-title"
|
|
69
|
+
className="text-lg font-medium"
|
|
70
|
+
>
|
|
71
|
+
{title}
|
|
72
|
+
</DialogPrimitive.Title>
|
|
73
|
+
<DialogPrimitive.Description
|
|
74
|
+
data-slot="dialog-description"
|
|
75
|
+
className="text-muted-foreground text-sm text-balance md:text-pretty"
|
|
76
|
+
>
|
|
77
|
+
{description}
|
|
78
|
+
</DialogPrimitive.Description>
|
|
79
|
+
</div>
|
|
80
|
+
{children}
|
|
81
|
+
</DialogPrimitive.Popup>
|
|
82
|
+
</DialogPrimitive.Portal>
|
|
83
|
+
</DialogPrimitive.Root>
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function CommandInput({
|
|
88
|
+
...props
|
|
89
|
+
}: Omit<React.ComponentProps<typeof CommandPrimitive.Input>, "className">) {
|
|
90
|
+
return (
|
|
91
|
+
<div data-slot="command-input-wrapper" className="p-1 pb-0">
|
|
92
|
+
<div
|
|
93
|
+
data-slot="input-group"
|
|
94
|
+
role="group"
|
|
95
|
+
className="border-input/30 bg-input/30 h-8 rounded-lg border shadow-none transition-[color,box-shadow] has-[[data-slot=input-group-control]:focus-visible]:border-ring has-[[data-slot=input-group-control]:focus-visible]:ring-ring/50 has-[[data-slot=input-group-control]:focus-visible]:ring-[3px] group/input-group relative flex w-full min-w-0 items-center outline-none"
|
|
96
|
+
>
|
|
97
|
+
<CommandPrimitive.Input
|
|
98
|
+
data-slot="command-input"
|
|
99
|
+
className="w-full flex-1 bg-transparent px-2.5 py-1 text-sm outline-hidden disabled:cursor-not-allowed disabled:opacity-50"
|
|
100
|
+
{...props}
|
|
101
|
+
/>
|
|
102
|
+
<div
|
|
103
|
+
data-slot="input-group-addon"
|
|
104
|
+
data-align="inline-end"
|
|
105
|
+
className="text-muted-foreground flex h-auto cursor-text items-center justify-center gap-2 pr-2 text-sm font-medium select-none"
|
|
106
|
+
>
|
|
107
|
+
<SearchIcon className="size-4 shrink-0 opacity-50" />
|
|
108
|
+
</div>
|
|
109
|
+
</div>
|
|
110
|
+
</div>
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function CommandList({
|
|
115
|
+
...props
|
|
116
|
+
}: Omit<React.ComponentProps<typeof CommandPrimitive.List>, "className">) {
|
|
117
|
+
return (
|
|
118
|
+
<CommandPrimitive.List
|
|
119
|
+
data-slot="command-list"
|
|
120
|
+
className="no-scrollbar max-h-72 scroll-py-1 outline-none overflow-x-hidden overflow-y-auto"
|
|
121
|
+
{...props}
|
|
122
|
+
/>
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function CommandEmpty({
|
|
127
|
+
...props
|
|
128
|
+
}: Omit<React.ComponentProps<typeof CommandPrimitive.Empty>, "className">) {
|
|
129
|
+
return (
|
|
130
|
+
<CommandPrimitive.Empty
|
|
131
|
+
data-slot="command-empty"
|
|
132
|
+
className="py-6 text-center text-sm"
|
|
133
|
+
{...props}
|
|
134
|
+
/>
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function CommandGroup({
|
|
139
|
+
...props
|
|
140
|
+
}: Omit<React.ComponentProps<typeof CommandPrimitive.Group>, "className">) {
|
|
141
|
+
return (
|
|
142
|
+
<CommandPrimitive.Group
|
|
143
|
+
data-slot="command-group"
|
|
144
|
+
className="text-foreground [&_[cmdk-group-heading]]:text-muted-foreground overflow-hidden p-1 [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium"
|
|
145
|
+
{...props}
|
|
146
|
+
/>
|
|
147
|
+
);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
function CommandSeparator({
|
|
151
|
+
...props
|
|
152
|
+
}: Omit<React.ComponentProps<typeof CommandPrimitive.Separator>, "className">) {
|
|
153
|
+
return (
|
|
154
|
+
<CommandPrimitive.Separator
|
|
155
|
+
data-slot="command-separator"
|
|
156
|
+
className="bg-border -mx-1 h-px w-auto"
|
|
157
|
+
{...props}
|
|
158
|
+
/>
|
|
159
|
+
);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
function CommandItem({
|
|
163
|
+
children,
|
|
164
|
+
...props
|
|
165
|
+
}: Omit<React.ComponentProps<typeof CommandPrimitive.Item>, "className">) {
|
|
166
|
+
return (
|
|
167
|
+
<CommandPrimitive.Item
|
|
168
|
+
data-slot="command-item"
|
|
169
|
+
className="data-[selected=true]:bg-muted data-[selected=true]:text-foreground data-[selected=true]:**:[svg]:text-foreground relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none [&_svg:not([class*='size-'])]:size-4 [[data-slot=dialog-content]_&]:rounded-lg group/command-item data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0"
|
|
170
|
+
{...props}
|
|
171
|
+
>
|
|
172
|
+
{children}
|
|
173
|
+
<CheckIcon className="ml-auto opacity-0 group-has-[[data-slot=command-shortcut]]/command-item:hidden group-data-[checked=true]/command-item:opacity-100" />
|
|
174
|
+
</CommandPrimitive.Item>
|
|
175
|
+
);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
function CommandShortcut({
|
|
179
|
+
...props
|
|
180
|
+
}: Omit<React.ComponentProps<"span">, "className">) {
|
|
181
|
+
return (
|
|
182
|
+
<span
|
|
183
|
+
data-slot="command-shortcut"
|
|
184
|
+
className="text-muted-foreground group-data-[selected=true]/command-item:text-foreground ml-auto text-xs tracking-widest"
|
|
185
|
+
{...props}
|
|
186
|
+
/>
|
|
187
|
+
);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
export {
|
|
191
|
+
Command,
|
|
192
|
+
CommandDialog,
|
|
193
|
+
CommandEmpty,
|
|
194
|
+
CommandGroup,
|
|
195
|
+
CommandInput,
|
|
196
|
+
CommandItem,
|
|
197
|
+
CommandList,
|
|
198
|
+
CommandSeparator,
|
|
199
|
+
CommandShortcut,
|
|
200
|
+
};
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
import { ContextMenu as ContextMenuPrimitive } from "@base-ui/react/context-menu";
|
|
2
|
+
|
|
3
|
+
import { CheckIcon, ChevronRightIcon } from "lucide-react";
|
|
4
|
+
|
|
5
|
+
function ContextMenu({ ...props }: ContextMenuPrimitive.Root.Props) {
|
|
6
|
+
return <ContextMenuPrimitive.Root data-slot="context-menu" {...props} />;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
function ContextMenuPortal({ ...props }: ContextMenuPrimitive.Portal.Props) {
|
|
10
|
+
return (
|
|
11
|
+
<ContextMenuPrimitive.Portal data-slot="context-menu-portal" {...props} />
|
|
12
|
+
);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function ContextMenuTrigger({
|
|
16
|
+
...props
|
|
17
|
+
}: Omit<ContextMenuPrimitive.Trigger.Props, "className">) {
|
|
18
|
+
return (
|
|
19
|
+
<ContextMenuPrimitive.Trigger
|
|
20
|
+
data-slot="context-menu-trigger"
|
|
21
|
+
className="select-none"
|
|
22
|
+
{...props}
|
|
23
|
+
/>
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function ContextMenuContent({
|
|
28
|
+
align = "start",
|
|
29
|
+
alignOffset = 4,
|
|
30
|
+
side = "right",
|
|
31
|
+
sideOffset = 0,
|
|
32
|
+
...props
|
|
33
|
+
}: Omit<ContextMenuPrimitive.Popup.Props, "className"> &
|
|
34
|
+
Pick<
|
|
35
|
+
ContextMenuPrimitive.Positioner.Props,
|
|
36
|
+
"align" | "alignOffset" | "side" | "sideOffset"
|
|
37
|
+
>) {
|
|
38
|
+
return (
|
|
39
|
+
<ContextMenuPrimitive.Portal>
|
|
40
|
+
<ContextMenuPrimitive.Positioner
|
|
41
|
+
className="isolate z-50 outline-none"
|
|
42
|
+
align={align}
|
|
43
|
+
alignOffset={alignOffset}
|
|
44
|
+
side={side}
|
|
45
|
+
sideOffset={sideOffset}
|
|
46
|
+
>
|
|
47
|
+
<ContextMenuPrimitive.Popup
|
|
48
|
+
data-slot="context-menu-content"
|
|
49
|
+
className="data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 ring-foreground/10 bg-popover text-popover-foreground min-w-36 rounded-md p-1 shadow-md ring-1 duration-100 z-50 max-h-(--available-height) origin-(--transform-origin) overflow-x-hidden overflow-y-auto outline-none"
|
|
50
|
+
{...props}
|
|
51
|
+
/>
|
|
52
|
+
</ContextMenuPrimitive.Positioner>
|
|
53
|
+
</ContextMenuPrimitive.Portal>
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function ContextMenuGroup({ ...props }: ContextMenuPrimitive.Group.Props) {
|
|
58
|
+
return (
|
|
59
|
+
<ContextMenuPrimitive.Group data-slot="context-menu-group" {...props} />
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function ContextMenuLabel({
|
|
64
|
+
inset,
|
|
65
|
+
...props
|
|
66
|
+
}: Omit<ContextMenuPrimitive.GroupLabel.Props, "className"> & {
|
|
67
|
+
inset?: boolean;
|
|
68
|
+
}) {
|
|
69
|
+
return (
|
|
70
|
+
<ContextMenuPrimitive.GroupLabel
|
|
71
|
+
data-slot="context-menu-label"
|
|
72
|
+
data-inset={inset}
|
|
73
|
+
className="text-muted-foreground px-2 py-1.5 text-xs font-medium data-[inset]:pl-8"
|
|
74
|
+
{...props}
|
|
75
|
+
/>
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function ContextMenuItem({
|
|
80
|
+
inset,
|
|
81
|
+
variant = "default",
|
|
82
|
+
...props
|
|
83
|
+
}: Omit<ContextMenuPrimitive.Item.Props, "className"> & {
|
|
84
|
+
inset?: boolean;
|
|
85
|
+
variant?: "default" | "destructive";
|
|
86
|
+
}) {
|
|
87
|
+
return (
|
|
88
|
+
<ContextMenuPrimitive.Item
|
|
89
|
+
data-slot="context-menu-item"
|
|
90
|
+
data-inset={inset}
|
|
91
|
+
data-variant={variant}
|
|
92
|
+
className="focus:bg-accent focus:text-accent-foreground data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 dark:data-[variant=destructive]:focus:bg-destructive/20 data-[variant=destructive]:focus:text-destructive data-[variant=destructive]:*:[svg]:text-destructive focus:*:[svg]:text-accent-foreground gap-2 rounded-sm px-2 py-1.5 text-sm [&_svg:not([class*='size-'])]:size-4 group/context-menu-item relative flex cursor-default items-center outline-hidden select-none data-disabled:pointer-events-none data-disabled:opacity-50 data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0"
|
|
93
|
+
{...props}
|
|
94
|
+
/>
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function ContextMenuSub({ ...props }: ContextMenuPrimitive.SubmenuRoot.Props) {
|
|
99
|
+
return (
|
|
100
|
+
<ContextMenuPrimitive.SubmenuRoot data-slot="context-menu-sub" {...props} />
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function ContextMenuSubTrigger({
|
|
105
|
+
inset,
|
|
106
|
+
children,
|
|
107
|
+
...props
|
|
108
|
+
}: Omit<ContextMenuPrimitive.SubmenuTrigger.Props, "className"> & {
|
|
109
|
+
inset?: boolean;
|
|
110
|
+
}) {
|
|
111
|
+
return (
|
|
112
|
+
<ContextMenuPrimitive.SubmenuTrigger
|
|
113
|
+
data-slot="context-menu-sub-trigger"
|
|
114
|
+
data-inset={inset}
|
|
115
|
+
className="focus:bg-accent focus:text-accent-foreground data-open:bg-accent data-open:text-accent-foreground rounded-sm px-2 py-1.5 text-sm [&_svg:not([class*='size-'])]:size-4 flex cursor-default items-center outline-hidden select-none data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0"
|
|
116
|
+
{...props}
|
|
117
|
+
>
|
|
118
|
+
{children}
|
|
119
|
+
<ChevronRightIcon className="ml-auto" />
|
|
120
|
+
</ContextMenuPrimitive.SubmenuTrigger>
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
function ContextMenuSubContent({
|
|
125
|
+
...props
|
|
126
|
+
}: Omit<React.ComponentProps<typeof ContextMenuContent>, "className">) {
|
|
127
|
+
return (
|
|
128
|
+
<ContextMenuContent
|
|
129
|
+
data-slot="context-menu-sub-content"
|
|
130
|
+
side="right"
|
|
131
|
+
{...props}
|
|
132
|
+
/>
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function ContextMenuCheckboxItem({
|
|
137
|
+
children,
|
|
138
|
+
checked,
|
|
139
|
+
...props
|
|
140
|
+
}: Omit<ContextMenuPrimitive.CheckboxItem.Props, "className">) {
|
|
141
|
+
return (
|
|
142
|
+
<ContextMenuPrimitive.CheckboxItem
|
|
143
|
+
data-slot="context-menu-checkbox-item"
|
|
144
|
+
className="focus:bg-accent focus:text-accent-foreground gap-2 rounded-sm py-1.5 pr-8 pl-2 text-sm [&_svg:not([class*='size-'])]:size-4 relative flex cursor-default items-center outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0"
|
|
145
|
+
checked={checked}
|
|
146
|
+
{...props}
|
|
147
|
+
>
|
|
148
|
+
<span className="absolute right-2 pointer-events-none">
|
|
149
|
+
<ContextMenuPrimitive.CheckboxItemIndicator>
|
|
150
|
+
<CheckIcon />
|
|
151
|
+
</ContextMenuPrimitive.CheckboxItemIndicator>
|
|
152
|
+
</span>
|
|
153
|
+
{children}
|
|
154
|
+
</ContextMenuPrimitive.CheckboxItem>
|
|
155
|
+
);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
function ContextMenuRadioGroup({
|
|
159
|
+
...props
|
|
160
|
+
}: ContextMenuPrimitive.RadioGroup.Props) {
|
|
161
|
+
return (
|
|
162
|
+
<ContextMenuPrimitive.RadioGroup
|
|
163
|
+
data-slot="context-menu-radio-group"
|
|
164
|
+
{...props}
|
|
165
|
+
/>
|
|
166
|
+
);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
function ContextMenuRadioItem({
|
|
170
|
+
children,
|
|
171
|
+
...props
|
|
172
|
+
}: Omit<ContextMenuPrimitive.RadioItem.Props, "className">) {
|
|
173
|
+
return (
|
|
174
|
+
<ContextMenuPrimitive.RadioItem
|
|
175
|
+
data-slot="context-menu-radio-item"
|
|
176
|
+
className="focus:bg-accent focus:text-accent-foreground gap-2 rounded-sm py-1.5 pr-8 pl-2 text-sm [&_svg:not([class*='size-'])]:size-4 relative flex cursor-default items-center outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0"
|
|
177
|
+
{...props}
|
|
178
|
+
>
|
|
179
|
+
<span className="absolute right-2 pointer-events-none">
|
|
180
|
+
<ContextMenuPrimitive.RadioItemIndicator>
|
|
181
|
+
<CheckIcon />
|
|
182
|
+
</ContextMenuPrimitive.RadioItemIndicator>
|
|
183
|
+
</span>
|
|
184
|
+
{children}
|
|
185
|
+
</ContextMenuPrimitive.RadioItem>
|
|
186
|
+
);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
function ContextMenuSeparator({
|
|
190
|
+
...props
|
|
191
|
+
}: Omit<ContextMenuPrimitive.Separator.Props, "className">) {
|
|
192
|
+
return (
|
|
193
|
+
<ContextMenuPrimitive.Separator
|
|
194
|
+
data-slot="context-menu-separator"
|
|
195
|
+
className="bg-border -mx-1 my-1 h-px"
|
|
196
|
+
{...props}
|
|
197
|
+
/>
|
|
198
|
+
);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
function ContextMenuShortcut({
|
|
202
|
+
...props
|
|
203
|
+
}: Omit<React.ComponentProps<"span">, "className">) {
|
|
204
|
+
return (
|
|
205
|
+
<span
|
|
206
|
+
data-slot="context-menu-shortcut"
|
|
207
|
+
className="text-muted-foreground group-focus/context-menu-item:text-accent-foreground ml-auto text-xs tracking-widest"
|
|
208
|
+
{...props}
|
|
209
|
+
/>
|
|
210
|
+
);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
export {
|
|
214
|
+
ContextMenu,
|
|
215
|
+
ContextMenuCheckboxItem,
|
|
216
|
+
ContextMenuContent,
|
|
217
|
+
ContextMenuGroup,
|
|
218
|
+
ContextMenuItem,
|
|
219
|
+
ContextMenuLabel,
|
|
220
|
+
ContextMenuPortal,
|
|
221
|
+
ContextMenuRadioGroup,
|
|
222
|
+
ContextMenuRadioItem,
|
|
223
|
+
ContextMenuSeparator,
|
|
224
|
+
ContextMenuShortcut,
|
|
225
|
+
ContextMenuSub,
|
|
226
|
+
ContextMenuSubContent,
|
|
227
|
+
ContextMenuSubTrigger,
|
|
228
|
+
ContextMenuTrigger,
|
|
229
|
+
};
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { Dialog as DialogPrimitive } from "@base-ui/react/dialog";
|
|
4
|
+
import * as React from "react";
|
|
5
|
+
|
|
6
|
+
import { XIcon } from "lucide-react";
|
|
7
|
+
import { Button } from "../atoms/button";
|
|
8
|
+
|
|
9
|
+
function Dialog({ ...props }: DialogPrimitive.Root.Props) {
|
|
10
|
+
return <DialogPrimitive.Root data-slot="dialog" {...props} />;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function DialogTrigger({ ...props }: DialogPrimitive.Trigger.Props) {
|
|
14
|
+
return <DialogPrimitive.Trigger data-slot="dialog-trigger" {...props} />;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function DialogPortal({ ...props }: DialogPrimitive.Portal.Props) {
|
|
18
|
+
return <DialogPrimitive.Portal data-slot="dialog-portal" {...props} />;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function DialogClose({ ...props }: DialogPrimitive.Close.Props) {
|
|
22
|
+
return <DialogPrimitive.Close data-slot="dialog-close" {...props} />;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function DialogOverlay({
|
|
26
|
+
...props
|
|
27
|
+
}: Omit<DialogPrimitive.Backdrop.Props, "className">) {
|
|
28
|
+
return (
|
|
29
|
+
<DialogPrimitive.Backdrop
|
|
30
|
+
data-slot="dialog-overlay"
|
|
31
|
+
className="data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 bg-black/10 duration-100 supports-backdrop-filter:backdrop-blur-xs fixed inset-0 isolate z-50"
|
|
32
|
+
{...props}
|
|
33
|
+
/>
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function DialogContent({
|
|
38
|
+
children,
|
|
39
|
+
showCloseButton = true,
|
|
40
|
+
...props
|
|
41
|
+
}: Omit<DialogPrimitive.Popup.Props, "className"> & {
|
|
42
|
+
showCloseButton?: boolean;
|
|
43
|
+
}) {
|
|
44
|
+
return (
|
|
45
|
+
<DialogPortal>
|
|
46
|
+
<DialogOverlay />
|
|
47
|
+
<DialogPrimitive.Popup
|
|
48
|
+
data-slot="dialog-content"
|
|
49
|
+
className="bg-background data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 ring-foreground/10 grid max-w-[calc(100%-2rem)] gap-4 rounded-xl p-4 text-sm ring-1 duration-100 sm:max-w-sm fixed top-1/2 left-1/2 z-50 w-full -translate-x-1/2 -translate-y-1/2 outline-none"
|
|
50
|
+
{...props}
|
|
51
|
+
>
|
|
52
|
+
{children}
|
|
53
|
+
{showCloseButton && (
|
|
54
|
+
<DialogPrimitive.Close
|
|
55
|
+
data-slot="dialog-close"
|
|
56
|
+
render={<Button variant="ghost" size="icon-sm" />}
|
|
57
|
+
className="absolute top-2 right-2"
|
|
58
|
+
>
|
|
59
|
+
<XIcon />
|
|
60
|
+
<span className="sr-only">Close</span>
|
|
61
|
+
</DialogPrimitive.Close>
|
|
62
|
+
)}
|
|
63
|
+
</DialogPrimitive.Popup>
|
|
64
|
+
</DialogPortal>
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function DialogHeader({
|
|
69
|
+
...props
|
|
70
|
+
}: Omit<React.ComponentProps<"div">, "className">) {
|
|
71
|
+
return (
|
|
72
|
+
<div data-slot="dialog-header" className="gap-2 flex flex-col" {...props} />
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function DialogFooter({
|
|
77
|
+
showCloseButton = false,
|
|
78
|
+
children,
|
|
79
|
+
...props
|
|
80
|
+
}: Omit<React.ComponentProps<"div">, "className"> & {
|
|
81
|
+
showCloseButton?: boolean;
|
|
82
|
+
}) {
|
|
83
|
+
return (
|
|
84
|
+
<div
|
|
85
|
+
data-slot="dialog-footer"
|
|
86
|
+
className="bg-muted/50 -mx-4 -mb-4 rounded-b-xl border-t p-4 flex flex-col-reverse gap-2 sm:flex-row sm:justify-end"
|
|
87
|
+
{...props}
|
|
88
|
+
>
|
|
89
|
+
{children}
|
|
90
|
+
{showCloseButton && (
|
|
91
|
+
<DialogPrimitive.Close render={<Button variant="outline" />}>
|
|
92
|
+
Close
|
|
93
|
+
</DialogPrimitive.Close>
|
|
94
|
+
)}
|
|
95
|
+
</div>
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function DialogTitle({
|
|
100
|
+
...props
|
|
101
|
+
}: Omit<DialogPrimitive.Title.Props, "className">) {
|
|
102
|
+
return (
|
|
103
|
+
<DialogPrimitive.Title
|
|
104
|
+
data-slot="dialog-title"
|
|
105
|
+
className="text-sm leading-none font-medium"
|
|
106
|
+
{...props}
|
|
107
|
+
/>
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function DialogDescription({
|
|
112
|
+
...props
|
|
113
|
+
}: Omit<DialogPrimitive.Description.Props, "className">) {
|
|
114
|
+
return (
|
|
115
|
+
<DialogPrimitive.Description
|
|
116
|
+
data-slot="dialog-description"
|
|
117
|
+
className="text-muted-foreground *:[a]:hover:text-foreground text-sm *:[a]:underline *:[a]:underline-offset-3"
|
|
118
|
+
{...props}
|
|
119
|
+
/>
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export {
|
|
124
|
+
Dialog,
|
|
125
|
+
DialogClose,
|
|
126
|
+
DialogContent,
|
|
127
|
+
DialogDescription,
|
|
128
|
+
DialogFooter,
|
|
129
|
+
DialogHeader,
|
|
130
|
+
DialogOverlay,
|
|
131
|
+
DialogPortal,
|
|
132
|
+
DialogTitle,
|
|
133
|
+
DialogTrigger,
|
|
134
|
+
};
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { Drawer as DrawerPrimitive } from "vaul";
|
|
5
|
+
|
|
6
|
+
function Drawer({
|
|
7
|
+
...props
|
|
8
|
+
}: React.ComponentProps<typeof DrawerPrimitive.Root>) {
|
|
9
|
+
return <DrawerPrimitive.Root data-slot="drawer" {...props} />;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function DrawerTrigger({
|
|
13
|
+
...props
|
|
14
|
+
}: React.ComponentProps<typeof DrawerPrimitive.Trigger>) {
|
|
15
|
+
return <DrawerPrimitive.Trigger data-slot="drawer-trigger" {...props} />;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function DrawerPortal({
|
|
19
|
+
...props
|
|
20
|
+
}: React.ComponentProps<typeof DrawerPrimitive.Portal>) {
|
|
21
|
+
return <DrawerPrimitive.Portal data-slot="drawer-portal" {...props} />;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function DrawerClose({
|
|
25
|
+
...props
|
|
26
|
+
}: React.ComponentProps<typeof DrawerPrimitive.Close>) {
|
|
27
|
+
return <DrawerPrimitive.Close data-slot="drawer-close" {...props} />;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function DrawerOverlay({
|
|
31
|
+
...props
|
|
32
|
+
}: Omit<React.ComponentProps<typeof DrawerPrimitive.Overlay>, "className">) {
|
|
33
|
+
return (
|
|
34
|
+
<DrawerPrimitive.Overlay
|
|
35
|
+
data-slot="drawer-overlay"
|
|
36
|
+
className="data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 bg-black/10 supports-backdrop-filter:backdrop-blur-xs fixed inset-0 z-50"
|
|
37
|
+
{...props}
|
|
38
|
+
/>
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function DrawerContent({
|
|
43
|
+
children,
|
|
44
|
+
...props
|
|
45
|
+
}: Omit<React.ComponentProps<typeof DrawerPrimitive.Content>, "className">) {
|
|
46
|
+
return (
|
|
47
|
+
<DrawerPortal data-slot="drawer-portal">
|
|
48
|
+
<DrawerOverlay />
|
|
49
|
+
<DrawerPrimitive.Content
|
|
50
|
+
data-slot="drawer-content"
|
|
51
|
+
className="bg-background flex h-auto flex-col text-sm data-[vaul-drawer-direction=bottom]:inset-x-0 data-[vaul-drawer-direction=bottom]:bottom-0 data-[vaul-drawer-direction=bottom]:mt-24 data-[vaul-drawer-direction=bottom]:max-h-[80vh] data-[vaul-drawer-direction=bottom]:rounded-t-xl data-[vaul-drawer-direction=bottom]:border-t data-[vaul-drawer-direction=left]:inset-y-0 data-[vaul-drawer-direction=left]:left-0 data-[vaul-drawer-direction=left]:w-3/4 data-[vaul-drawer-direction=left]:rounded-r-xl data-[vaul-drawer-direction=left]:border-r data-[vaul-drawer-direction=right]:inset-y-0 data-[vaul-drawer-direction=right]:right-0 data-[vaul-drawer-direction=right]:w-3/4 data-[vaul-drawer-direction=right]:rounded-l-xl data-[vaul-drawer-direction=right]:border-l data-[vaul-drawer-direction=top]:inset-x-0 data-[vaul-drawer-direction=top]:top-0 data-[vaul-drawer-direction=top]:mb-24 data-[vaul-drawer-direction=top]:max-h-[80vh] data-[vaul-drawer-direction=top]:rounded-b-xl data-[vaul-drawer-direction=top]:border-b data-[vaul-drawer-direction=left]:sm:max-w-sm data-[vaul-drawer-direction=right]:sm:max-w-sm group/drawer-content fixed z-50"
|
|
52
|
+
{...props}
|
|
53
|
+
>
|
|
54
|
+
<div className="bg-muted mx-auto mt-4 hidden h-1.5 w-[100px] shrink-0 rounded-full group-data-[vaul-drawer-direction=bottom]/drawer-content:block bg-muted mx-auto hidden shrink-0 group-data-[vaul-drawer-direction=bottom]/drawer-content:block" />
|
|
55
|
+
{children}
|
|
56
|
+
</DrawerPrimitive.Content>
|
|
57
|
+
</DrawerPortal>
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function DrawerHeader({
|
|
62
|
+
...props
|
|
63
|
+
}: Omit<React.ComponentProps<"div">, "className">) {
|
|
64
|
+
return (
|
|
65
|
+
<div
|
|
66
|
+
data-slot="drawer-header"
|
|
67
|
+
className="gap-0.5 p-4 group-data-[vaul-drawer-direction=bottom]/drawer-content:text-center group-data-[vaul-drawer-direction=top]/drawer-content:text-center md:gap-1.5 md:text-left flex flex-col"
|
|
68
|
+
{...props}
|
|
69
|
+
/>
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function DrawerFooter({
|
|
74
|
+
...props
|
|
75
|
+
}: Omit<React.ComponentProps<"div">, "className">) {
|
|
76
|
+
return (
|
|
77
|
+
<div
|
|
78
|
+
data-slot="drawer-footer"
|
|
79
|
+
className="gap-2 p-4 mt-auto flex flex-col"
|
|
80
|
+
{...props}
|
|
81
|
+
/>
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function DrawerTitle({
|
|
86
|
+
...props
|
|
87
|
+
}: Omit<React.ComponentProps<typeof DrawerPrimitive.Title>, "className">) {
|
|
88
|
+
return (
|
|
89
|
+
<DrawerPrimitive.Title
|
|
90
|
+
data-slot="drawer-title"
|
|
91
|
+
className="text-foreground font-medium"
|
|
92
|
+
{...props}
|
|
93
|
+
/>
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function DrawerDescription({
|
|
98
|
+
...props
|
|
99
|
+
}: Omit<
|
|
100
|
+
React.ComponentProps<typeof DrawerPrimitive.Description>,
|
|
101
|
+
"className"
|
|
102
|
+
>) {
|
|
103
|
+
return (
|
|
104
|
+
<DrawerPrimitive.Description
|
|
105
|
+
data-slot="drawer-description"
|
|
106
|
+
className="text-muted-foreground text-sm"
|
|
107
|
+
{...props}
|
|
108
|
+
/>
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export {
|
|
113
|
+
Drawer,
|
|
114
|
+
DrawerClose,
|
|
115
|
+
DrawerContent,
|
|
116
|
+
DrawerDescription,
|
|
117
|
+
DrawerFooter,
|
|
118
|
+
DrawerHeader,
|
|
119
|
+
DrawerOverlay,
|
|
120
|
+
DrawerPortal,
|
|
121
|
+
DrawerTitle,
|
|
122
|
+
DrawerTrigger,
|
|
123
|
+
};
|