@allbluecn/ui 0.2.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.
- package/package.json +85 -0
- package/src/ai-command-button.tsx +36 -0
- package/src/ai-stream-text.tsx +37 -0
- package/src/alert-dialog.tsx +216 -0
- package/src/animated-theme-toggler.tsx +272 -0
- package/src/auth-client.ts +108 -0
- package/src/auth-layout.tsx +66 -0
- package/src/avatar.tsx +129 -0
- package/src/badge.tsx +66 -0
- package/src/button.tsx +84 -0
- package/src/card.tsx +120 -0
- package/src/checkbox.tsx +50 -0
- package/src/context-menu.tsx +280 -0
- package/src/dialog.tsx +183 -0
- package/src/dropdown-menu.tsx +286 -0
- package/src/empty.tsx +121 -0
- package/src/grid-pattern.tsx +87 -0
- package/src/icon-packs/index.ts +27 -0
- package/src/icon-packs/knowledge.ts +55 -0
- package/src/icon-packs/prd.ts +63 -0
- package/src/icon-packs/project.ts +59 -0
- package/src/icon-picker.tsx +68 -0
- package/src/index.ts +23 -0
- package/src/input.tsx +36 -0
- package/src/item.tsx +213 -0
- package/src/kbd.tsx +33 -0
- package/src/label.tsx +39 -0
- package/src/layout-panel-top.tsx +160 -0
- package/src/name-confirm-dialog.tsx +153 -0
- package/src/nav-float-button.tsx +301 -0
- package/src/notion-avatar.tsx +126 -0
- package/src/placeholder-page.tsx +42 -0
- package/src/popover.tsx +106 -0
- package/src/reference-inline.tsx +53 -0
- package/src/reference-search.tsx +52 -0
- package/src/resizable.tsx +67 -0
- package/src/select.tsx +207 -0
- package/src/separator.tsx +45 -0
- package/src/sheet.tsx +164 -0
- package/src/sidebar.tsx +708 -0
- package/src/skeleton.tsx +30 -0
- package/src/sonner.tsx +37 -0
- package/src/switch.tsx +48 -0
- package/src/textarea.tsx +35 -0
- package/src/timezone-provider.tsx +55 -0
- package/src/tooltip.tsx +72 -0
- package/src/use-mobile.ts +36 -0
- package/src/user-avatar.tsx +79 -0
- package/src/utils.ts +6 -0
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
|
+
// AllBlue - 理想之海
|
|
3
|
+
// Copyright (C) 2026 AllBlue Contributors
|
|
4
|
+
//
|
|
5
|
+
// This program is free software: you can redistribute it and/or modify
|
|
6
|
+
// it under the terms of the GNU Affero General Public License as published by
|
|
7
|
+
// the Free Software Foundation, either version 3 of the License, or
|
|
8
|
+
// (at your option) any later version.
|
|
9
|
+
//
|
|
10
|
+
// This program is distributed in the hope that it will be useful,
|
|
11
|
+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13
|
+
// GNU Affero General Public License for more details.
|
|
14
|
+
//
|
|
15
|
+
// You should have received a copy of the GNU Affero General Public License
|
|
16
|
+
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
17
|
+
|
|
18
|
+
"use client"
|
|
19
|
+
|
|
20
|
+
import * as React from "react"
|
|
21
|
+
import { ContextMenu as ContextMenuPrimitive } from "radix-ui"
|
|
22
|
+
|
|
23
|
+
import { cn } from "./utils"
|
|
24
|
+
import { ChevronRightIcon, CheckIcon } from "lucide-react"
|
|
25
|
+
|
|
26
|
+
function ContextMenu({
|
|
27
|
+
...props
|
|
28
|
+
}: React.ComponentProps<typeof ContextMenuPrimitive.Root>) {
|
|
29
|
+
return <ContextMenuPrimitive.Root data-slot="context-menu" {...props} />
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function ContextMenuTrigger({
|
|
33
|
+
className,
|
|
34
|
+
...props
|
|
35
|
+
}: React.ComponentProps<typeof ContextMenuPrimitive.Trigger>) {
|
|
36
|
+
return (
|
|
37
|
+
<ContextMenuPrimitive.Trigger
|
|
38
|
+
data-slot="context-menu-trigger"
|
|
39
|
+
className={cn("select-none", className)}
|
|
40
|
+
{...props}
|
|
41
|
+
/>
|
|
42
|
+
)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function ContextMenuGroup({
|
|
46
|
+
...props
|
|
47
|
+
}: React.ComponentProps<typeof ContextMenuPrimitive.Group>) {
|
|
48
|
+
return (
|
|
49
|
+
<ContextMenuPrimitive.Group data-slot="context-menu-group" {...props} />
|
|
50
|
+
)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function ContextMenuPortal({
|
|
54
|
+
...props
|
|
55
|
+
}: React.ComponentProps<typeof ContextMenuPrimitive.Portal>) {
|
|
56
|
+
return (
|
|
57
|
+
<ContextMenuPrimitive.Portal data-slot="context-menu-portal" {...props} />
|
|
58
|
+
)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function ContextMenuSub({
|
|
62
|
+
...props
|
|
63
|
+
}: React.ComponentProps<typeof ContextMenuPrimitive.Sub>) {
|
|
64
|
+
return <ContextMenuPrimitive.Sub data-slot="context-menu-sub" {...props} />
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function ContextMenuRadioGroup({
|
|
68
|
+
...props
|
|
69
|
+
}: React.ComponentProps<typeof ContextMenuPrimitive.RadioGroup>) {
|
|
70
|
+
return (
|
|
71
|
+
<ContextMenuPrimitive.RadioGroup
|
|
72
|
+
data-slot="context-menu-radio-group"
|
|
73
|
+
{...props}
|
|
74
|
+
/>
|
|
75
|
+
)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function ContextMenuContent({
|
|
79
|
+
className,
|
|
80
|
+
...props
|
|
81
|
+
}: React.ComponentProps<typeof ContextMenuPrimitive.Content> & {
|
|
82
|
+
side?: "top" | "right" | "bottom" | "left"
|
|
83
|
+
}) {
|
|
84
|
+
return (
|
|
85
|
+
<ContextMenuPrimitive.Portal>
|
|
86
|
+
<ContextMenuPrimitive.Content
|
|
87
|
+
data-slot="context-menu-content"
|
|
88
|
+
className={cn("z-50 max-h-(--radix-context-menu-content-available-height) min-w-36 origin-(--radix-context-menu-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-lg bg-popover p-1 text-popover-foreground shadow-md ring-1 ring-foreground/10 duration-100 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 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95", className )}
|
|
89
|
+
{...props}
|
|
90
|
+
/>
|
|
91
|
+
</ContextMenuPrimitive.Portal>
|
|
92
|
+
)
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function ContextMenuItem({
|
|
96
|
+
className,
|
|
97
|
+
inset,
|
|
98
|
+
variant = "default",
|
|
99
|
+
...props
|
|
100
|
+
}: React.ComponentProps<typeof ContextMenuPrimitive.Item> & {
|
|
101
|
+
inset?: boolean
|
|
102
|
+
variant?: "default" | "destructive"
|
|
103
|
+
}) {
|
|
104
|
+
return (
|
|
105
|
+
<ContextMenuPrimitive.Item
|
|
106
|
+
data-slot="context-menu-item"
|
|
107
|
+
data-inset={inset}
|
|
108
|
+
data-variant={variant}
|
|
109
|
+
className={cn(
|
|
110
|
+
"group/context-menu-item relative flex cursor-default items-center gap-1.5 rounded-md px-1.5 py-1 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground data-inset:pl-7 data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 data-[variant=destructive]:focus:text-destructive dark:data-[variant=destructive]:focus:bg-destructive/20 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 focus:*:[svg]:text-accent-foreground data-[variant=destructive]:*:[svg]:text-destructive",
|
|
111
|
+
className
|
|
112
|
+
)}
|
|
113
|
+
{...props}
|
|
114
|
+
/>
|
|
115
|
+
)
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function ContextMenuSubTrigger({
|
|
119
|
+
className,
|
|
120
|
+
inset,
|
|
121
|
+
children,
|
|
122
|
+
...props
|
|
123
|
+
}: React.ComponentProps<typeof ContextMenuPrimitive.SubTrigger> & {
|
|
124
|
+
inset?: boolean
|
|
125
|
+
}) {
|
|
126
|
+
return (
|
|
127
|
+
<ContextMenuPrimitive.SubTrigger
|
|
128
|
+
data-slot="context-menu-sub-trigger"
|
|
129
|
+
data-inset={inset}
|
|
130
|
+
className={cn(
|
|
131
|
+
"flex cursor-default items-center gap-1.5 rounded-md px-1.5 py-1 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground data-inset:pl-7 data-open:bg-accent data-open:text-accent-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
|
132
|
+
className
|
|
133
|
+
)}
|
|
134
|
+
{...props}
|
|
135
|
+
>
|
|
136
|
+
{children}
|
|
137
|
+
<ChevronRightIcon className="ml-auto" />
|
|
138
|
+
</ContextMenuPrimitive.SubTrigger>
|
|
139
|
+
)
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function ContextMenuSubContent({
|
|
143
|
+
className,
|
|
144
|
+
...props
|
|
145
|
+
}: React.ComponentProps<typeof ContextMenuPrimitive.SubContent>) {
|
|
146
|
+
return (
|
|
147
|
+
<ContextMenuPrimitive.SubContent
|
|
148
|
+
data-slot="context-menu-sub-content"
|
|
149
|
+
className={cn("z-50 min-w-32 origin-(--radix-context-menu-content-transform-origin) overflow-hidden rounded-lg border bg-popover p-1 text-popover-foreground shadow-lg duration-100 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 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95", className )}
|
|
150
|
+
{...props}
|
|
151
|
+
/>
|
|
152
|
+
)
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
function ContextMenuCheckboxItem({
|
|
156
|
+
className,
|
|
157
|
+
children,
|
|
158
|
+
checked,
|
|
159
|
+
inset,
|
|
160
|
+
...props
|
|
161
|
+
}: React.ComponentProps<typeof ContextMenuPrimitive.CheckboxItem> & {
|
|
162
|
+
inset?: boolean
|
|
163
|
+
}) {
|
|
164
|
+
return (
|
|
165
|
+
<ContextMenuPrimitive.CheckboxItem
|
|
166
|
+
data-slot="context-menu-checkbox-item"
|
|
167
|
+
data-inset={inset}
|
|
168
|
+
className={cn(
|
|
169
|
+
"relative flex cursor-default items-center gap-1.5 rounded-md py-1 pr-8 pl-1.5 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground data-inset:pl-7 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
|
170
|
+
className
|
|
171
|
+
)}
|
|
172
|
+
checked={checked}
|
|
173
|
+
{...props}
|
|
174
|
+
>
|
|
175
|
+
<span className="pointer-events-none absolute right-2">
|
|
176
|
+
<ContextMenuPrimitive.ItemIndicator>
|
|
177
|
+
<CheckIcon
|
|
178
|
+
/>
|
|
179
|
+
</ContextMenuPrimitive.ItemIndicator>
|
|
180
|
+
</span>
|
|
181
|
+
{children}
|
|
182
|
+
</ContextMenuPrimitive.CheckboxItem>
|
|
183
|
+
)
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
function ContextMenuRadioItem({
|
|
187
|
+
className,
|
|
188
|
+
children,
|
|
189
|
+
inset,
|
|
190
|
+
...props
|
|
191
|
+
}: React.ComponentProps<typeof ContextMenuPrimitive.RadioItem> & {
|
|
192
|
+
inset?: boolean
|
|
193
|
+
}) {
|
|
194
|
+
return (
|
|
195
|
+
<ContextMenuPrimitive.RadioItem
|
|
196
|
+
data-slot="context-menu-radio-item"
|
|
197
|
+
data-inset={inset}
|
|
198
|
+
className={cn(
|
|
199
|
+
"relative flex cursor-default items-center gap-1.5 rounded-md py-1 pr-8 pl-1.5 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground data-inset:pl-7 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
|
200
|
+
className
|
|
201
|
+
)}
|
|
202
|
+
{...props}
|
|
203
|
+
>
|
|
204
|
+
<span className="pointer-events-none absolute right-2">
|
|
205
|
+
<ContextMenuPrimitive.ItemIndicator>
|
|
206
|
+
<CheckIcon
|
|
207
|
+
/>
|
|
208
|
+
</ContextMenuPrimitive.ItemIndicator>
|
|
209
|
+
</span>
|
|
210
|
+
{children}
|
|
211
|
+
</ContextMenuPrimitive.RadioItem>
|
|
212
|
+
)
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
function ContextMenuLabel({
|
|
216
|
+
className,
|
|
217
|
+
inset,
|
|
218
|
+
...props
|
|
219
|
+
}: React.ComponentProps<typeof ContextMenuPrimitive.Label> & {
|
|
220
|
+
inset?: boolean
|
|
221
|
+
}) {
|
|
222
|
+
return (
|
|
223
|
+
<ContextMenuPrimitive.Label
|
|
224
|
+
data-slot="context-menu-label"
|
|
225
|
+
data-inset={inset}
|
|
226
|
+
className={cn(
|
|
227
|
+
"px-1.5 py-1 text-xs font-medium text-muted-foreground data-inset:pl-7",
|
|
228
|
+
className
|
|
229
|
+
)}
|
|
230
|
+
{...props}
|
|
231
|
+
/>
|
|
232
|
+
)
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
function ContextMenuSeparator({
|
|
236
|
+
className,
|
|
237
|
+
...props
|
|
238
|
+
}: React.ComponentProps<typeof ContextMenuPrimitive.Separator>) {
|
|
239
|
+
return (
|
|
240
|
+
<ContextMenuPrimitive.Separator
|
|
241
|
+
data-slot="context-menu-separator"
|
|
242
|
+
className={cn("-mx-1 my-1 h-px bg-border", className)}
|
|
243
|
+
{...props}
|
|
244
|
+
/>
|
|
245
|
+
)
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
function ContextMenuShortcut({
|
|
249
|
+
className,
|
|
250
|
+
...props
|
|
251
|
+
}: React.ComponentProps<"span">) {
|
|
252
|
+
return (
|
|
253
|
+
<span
|
|
254
|
+
data-slot="context-menu-shortcut"
|
|
255
|
+
className={cn(
|
|
256
|
+
"ml-auto text-xs tracking-widest text-muted-foreground group-focus/context-menu-item:text-accent-foreground",
|
|
257
|
+
className
|
|
258
|
+
)}
|
|
259
|
+
{...props}
|
|
260
|
+
/>
|
|
261
|
+
)
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
export {
|
|
265
|
+
ContextMenu,
|
|
266
|
+
ContextMenuTrigger,
|
|
267
|
+
ContextMenuContent,
|
|
268
|
+
ContextMenuItem,
|
|
269
|
+
ContextMenuCheckboxItem,
|
|
270
|
+
ContextMenuRadioItem,
|
|
271
|
+
ContextMenuLabel,
|
|
272
|
+
ContextMenuSeparator,
|
|
273
|
+
ContextMenuShortcut,
|
|
274
|
+
ContextMenuGroup,
|
|
275
|
+
ContextMenuPortal,
|
|
276
|
+
ContextMenuSub,
|
|
277
|
+
ContextMenuSubContent,
|
|
278
|
+
ContextMenuSubTrigger,
|
|
279
|
+
ContextMenuRadioGroup,
|
|
280
|
+
}
|
package/src/dialog.tsx
ADDED
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
|
+
// AllBlue - 理想之海
|
|
3
|
+
// Copyright (C) 2026 AllBlue Contributors
|
|
4
|
+
//
|
|
5
|
+
// This program is free software: you can redistribute it and/or modify
|
|
6
|
+
// it under the terms of the GNU Affero General Public License as published by
|
|
7
|
+
// the Free Software Foundation, either version 3 of the License, or
|
|
8
|
+
// (at your option) any later version.
|
|
9
|
+
//
|
|
10
|
+
// This program is distributed in the hope that it will be useful,
|
|
11
|
+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13
|
+
// GNU Affero General Public License for more details.
|
|
14
|
+
//
|
|
15
|
+
// You should have received a copy of the GNU Affero General Public License
|
|
16
|
+
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
17
|
+
|
|
18
|
+
import * as React from "react"
|
|
19
|
+
import { Dialog as DialogPrimitive } from "radix-ui"
|
|
20
|
+
|
|
21
|
+
import { cn } from "./utils"
|
|
22
|
+
import { Button } from "./button"
|
|
23
|
+
import { XIcon } from "lucide-react"
|
|
24
|
+
|
|
25
|
+
function Dialog({
|
|
26
|
+
...props
|
|
27
|
+
}: React.ComponentProps<typeof DialogPrimitive.Root>) {
|
|
28
|
+
return <DialogPrimitive.Root data-slot="dialog" {...props} />
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function DialogTrigger({
|
|
32
|
+
...props
|
|
33
|
+
}: React.ComponentProps<typeof DialogPrimitive.Trigger>) {
|
|
34
|
+
return <DialogPrimitive.Trigger data-slot="dialog-trigger" {...props} />
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function DialogPortal({
|
|
38
|
+
...props
|
|
39
|
+
}: React.ComponentProps<typeof DialogPrimitive.Portal>) {
|
|
40
|
+
return <DialogPrimitive.Portal data-slot="dialog-portal" {...props} />
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function DialogClose({
|
|
44
|
+
...props
|
|
45
|
+
}: React.ComponentProps<typeof DialogPrimitive.Close>) {
|
|
46
|
+
return <DialogPrimitive.Close data-slot="dialog-close" {...props} />
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function DialogOverlay({
|
|
50
|
+
className,
|
|
51
|
+
...props
|
|
52
|
+
}: React.ComponentProps<typeof DialogPrimitive.Overlay>) {
|
|
53
|
+
return (
|
|
54
|
+
<DialogPrimitive.Overlay
|
|
55
|
+
data-slot="dialog-overlay"
|
|
56
|
+
className={cn(
|
|
57
|
+
"fixed inset-0 isolate z-50 bg-black/10 duration-100 supports-backdrop-filter:backdrop-blur-xs data-open:animate-in data-open:fade-in-0 data-closed:animate-out data-closed:fade-out-0",
|
|
58
|
+
className
|
|
59
|
+
)}
|
|
60
|
+
{...props}
|
|
61
|
+
/>
|
|
62
|
+
)
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function DialogContent({
|
|
66
|
+
className,
|
|
67
|
+
children,
|
|
68
|
+
showCloseButton = true,
|
|
69
|
+
...props
|
|
70
|
+
}: React.ComponentProps<typeof DialogPrimitive.Content> & {
|
|
71
|
+
showCloseButton?: boolean
|
|
72
|
+
}) {
|
|
73
|
+
return (
|
|
74
|
+
<DialogPortal>
|
|
75
|
+
<DialogOverlay />
|
|
76
|
+
<DialogPrimitive.Content
|
|
77
|
+
data-slot="dialog-content"
|
|
78
|
+
className={cn(
|
|
79
|
+
"fixed top-1/2 left-1/2 z-50 grid w-full max-w-[calc(100%-2rem)] -translate-x-1/2 -translate-y-1/2 gap-4 rounded-xl bg-popover p-4 text-sm text-popover-foreground ring-1 ring-foreground/10 duration-100 outline-none sm:max-w-sm data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95 dark:border dark:border-primary/15",
|
|
80
|
+
className
|
|
81
|
+
)}
|
|
82
|
+
{...props}
|
|
83
|
+
>
|
|
84
|
+
{children}
|
|
85
|
+
{showCloseButton && (
|
|
86
|
+
<DialogPrimitive.Close data-slot="dialog-close" asChild>
|
|
87
|
+
<Button
|
|
88
|
+
variant="ghost"
|
|
89
|
+
className="absolute top-2 right-2"
|
|
90
|
+
size="icon-sm"
|
|
91
|
+
>
|
|
92
|
+
<XIcon
|
|
93
|
+
/>
|
|
94
|
+
<span className="sr-only">Close</span>
|
|
95
|
+
</Button>
|
|
96
|
+
</DialogPrimitive.Close>
|
|
97
|
+
)}
|
|
98
|
+
</DialogPrimitive.Content>
|
|
99
|
+
</DialogPortal>
|
|
100
|
+
)
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function DialogHeader({ className, ...props }: React.ComponentProps<"div">) {
|
|
104
|
+
return (
|
|
105
|
+
<div
|
|
106
|
+
data-slot="dialog-header"
|
|
107
|
+
className={cn("flex flex-col gap-2", className)}
|
|
108
|
+
{...props}
|
|
109
|
+
/>
|
|
110
|
+
)
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function DialogFooter({
|
|
114
|
+
className,
|
|
115
|
+
showCloseButton = false,
|
|
116
|
+
children,
|
|
117
|
+
...props
|
|
118
|
+
}: React.ComponentProps<"div"> & {
|
|
119
|
+
showCloseButton?: boolean
|
|
120
|
+
}) {
|
|
121
|
+
return (
|
|
122
|
+
<div
|
|
123
|
+
data-slot="dialog-footer"
|
|
124
|
+
className={cn(
|
|
125
|
+
"-mx-4 -mb-4 flex flex-col-reverse gap-2 rounded-b-xl border-t bg-muted/50 p-4 sm:flex-row sm:justify-end",
|
|
126
|
+
className
|
|
127
|
+
)}
|
|
128
|
+
{...props}
|
|
129
|
+
>
|
|
130
|
+
{children}
|
|
131
|
+
{showCloseButton && (
|
|
132
|
+
<DialogPrimitive.Close asChild>
|
|
133
|
+
<Button variant="outline">Close</Button>
|
|
134
|
+
</DialogPrimitive.Close>
|
|
135
|
+
)}
|
|
136
|
+
</div>
|
|
137
|
+
)
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
function DialogTitle({
|
|
141
|
+
className,
|
|
142
|
+
...props
|
|
143
|
+
}: React.ComponentProps<typeof DialogPrimitive.Title>) {
|
|
144
|
+
return (
|
|
145
|
+
<DialogPrimitive.Title
|
|
146
|
+
data-slot="dialog-title"
|
|
147
|
+
className={cn(
|
|
148
|
+
"font-heading text-base leading-none font-medium",
|
|
149
|
+
className
|
|
150
|
+
)}
|
|
151
|
+
{...props}
|
|
152
|
+
/>
|
|
153
|
+
)
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
function DialogDescription({
|
|
157
|
+
className,
|
|
158
|
+
...props
|
|
159
|
+
}: React.ComponentProps<typeof DialogPrimitive.Description>) {
|
|
160
|
+
return (
|
|
161
|
+
<DialogPrimitive.Description
|
|
162
|
+
data-slot="dialog-description"
|
|
163
|
+
className={cn(
|
|
164
|
+
"text-sm text-muted-foreground *:[a]:underline *:[a]:underline-offset-3 *:[a]:hover:text-foreground",
|
|
165
|
+
className
|
|
166
|
+
)}
|
|
167
|
+
{...props}
|
|
168
|
+
/>
|
|
169
|
+
)
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
export {
|
|
173
|
+
Dialog,
|
|
174
|
+
DialogClose,
|
|
175
|
+
DialogContent,
|
|
176
|
+
DialogDescription,
|
|
177
|
+
DialogFooter,
|
|
178
|
+
DialogHeader,
|
|
179
|
+
DialogOverlay,
|
|
180
|
+
DialogPortal,
|
|
181
|
+
DialogTitle,
|
|
182
|
+
DialogTrigger,
|
|
183
|
+
}
|