@nocobase/portal-template-default 1.0.4 → 1.0.6
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 +77 -0
- package/package.json +23 -17
- package/registry/nocobase-acl/demo/prompt-generator.tsx +6 -39
- package/registry/nocobase-acl/demo/role-switcher-prompt-generator.tsx +6 -42
- package/registry/nocobase-ai/demo/page-context-prompt-generator.tsx +1 -1
- package/registry/nocobase-ai/demo/prompt-card.tsx +7 -28
- package/registry/nocobase-ai/demo/prompt-generator.tsx +9 -30
- package/registry/nocobase-ai/demo/shortcut.tsx +1 -1
- package/registry/nocobase-ai/demo/tool-cards.tsx +10 -30
- package/registry/nocobase-auth-cas/README.md +6 -0
- package/registry/nocobase-auth-cas/cas-sign-in-button.tsx +41 -0
- package/registry/nocobase-auth-cas/demo.tsx +20 -0
- package/registry/nocobase-auth-cas/extension.tsx +46 -0
- package/registry/nocobase-auth-cas/index.ts +1 -0
- package/registry/nocobase-auth-cas/use-cas-sign-in.ts +29 -0
- package/registry/nocobase-auth-dingtalk/README.md +7 -0
- package/registry/nocobase-auth-dingtalk/auto-login-provider.tsx +154 -0
- package/registry/nocobase-auth-dingtalk/demo.tsx +23 -0
- package/registry/nocobase-auth-dingtalk/dingtalk-sign-in-button.tsx +45 -0
- package/registry/nocobase-auth-dingtalk/extension.tsx +55 -0
- package/registry/nocobase-auth-dingtalk/index.ts +4 -0
- package/registry/nocobase-auth-dingtalk/use-dingtalk-sign-in.ts +64 -0
- package/registry/nocobase-auth-ldap/README.md +6 -0
- package/registry/nocobase-auth-ldap/demo.tsx +21 -0
- package/registry/nocobase-auth-ldap/extension.tsx +46 -0
- package/registry/nocobase-auth-ldap/index.ts +1 -0
- package/registry/nocobase-auth-ldap/ldap-sign-in-form.tsx +69 -0
- package/registry/nocobase-auth-ldap/use-ldap-sign-in.ts +5 -0
- package/registry/nocobase-auth-oidc/README.md +11 -0
- package/registry/nocobase-auth-oidc/auto-redirect-provider.tsx +13 -0
- package/registry/nocobase-auth-oidc/demo.tsx +20 -0
- package/registry/nocobase-auth-oidc/extension.tsx +51 -0
- package/registry/nocobase-auth-oidc/index.ts +1 -0
- package/registry/nocobase-auth-oidc/oidc-sign-in-button.tsx +44 -0
- package/registry/nocobase-auth-oidc/use-oidc-sign-in.ts +58 -0
- package/registry/nocobase-auth-saml/README.md +6 -0
- package/registry/nocobase-auth-saml/auto-redirect-provider.tsx +13 -0
- package/registry/nocobase-auth-saml/demo.tsx +20 -0
- package/registry/nocobase-auth-saml/extension.tsx +51 -0
- package/registry/nocobase-auth-saml/index.ts +1 -0
- package/registry/nocobase-auth-saml/saml-sign-in-button.tsx +43 -0
- package/registry/nocobase-auth-saml/use-saml-sign-in.ts +51 -0
- package/registry/nocobase-auth-sms/README.md +7 -0
- package/registry/nocobase-auth-sms/demo.tsx +25 -0
- package/registry/nocobase-auth-sms/extension.tsx +46 -0
- package/registry/nocobase-auth-sms/index.ts +1 -0
- package/registry/nocobase-auth-sms/sms-sign-in-form.tsx +107 -0
- package/registry/nocobase-auth-sms/use-sms-sign-in.ts +88 -0
- package/registry/nocobase-auth-wecom/README.md +6 -0
- package/registry/nocobase-auth-wecom/auto-login-provider.tsx +21 -0
- package/registry/nocobase-auth-wecom/demo.tsx +23 -0
- package/registry/nocobase-auth-wecom/extension.tsx +49 -0
- package/registry/nocobase-auth-wecom/index.ts +1 -0
- package/registry/nocobase-auth-wecom/use-wecom-sign-in.ts +62 -0
- package/registry/nocobase-auth-wecom/wecom-sign-in-button.tsx +70 -0
- package/registry/nocobase-i18n/demo/prompt-generator.tsx +30 -54
- package/registry/nocobase-route-surfaces/demo/prompt-generator.tsx +18 -21
- package/registry.config.json +112 -0
- package/scripts/build-html.mjs +106 -0
- package/src/App.tsx +34 -8
- package/src/app/extension.ts +4 -0
- package/src/app/extensions.tsx +24 -1
- package/src/components/auth/authenticator-adapters.ts +20 -0
- package/src/components/auth/auto-redirect-provider.tsx +84 -0
- package/src/components/auth/basic-sign-in-form.tsx +101 -0
- package/src/components/auth/default-sign-in-page.tsx +20 -0
- package/src/components/auth/demo/auth-demo-page.tsx +236 -0
- package/src/components/auth/demo/auth-demo-prompt-generator.tsx +93 -0
- package/src/components/auth/demo/auth-demo-route.tsx +11 -0
- package/src/components/auth/demo/auth-method-demo.tsx +48 -0
- package/src/components/auth/demo/index.ts +4 -0
- package/src/components/auth/dynamic-sign-in.tsx +191 -0
- package/src/components/auth/forgot-password-form.tsx +13 -5
- package/src/components/auth/index.ts +13 -0
- package/src/components/auth/sign-in-form.tsx +1 -111
- package/src/components/auth/sign-up-form.tsx +14 -37
- package/src/components/auth/types.ts +38 -0
- package/src/components/auth/use-authenticator-sign-in.ts +14 -0
- package/src/components/auth/use-public-authenticators.ts +26 -0
- package/src/components/data-table/data-table-filter.tsx +107 -153
- package/src/components/demo/prompt-output.tsx +71 -0
- package/src/components/ui/alert-dialog.tsx +2 -0
- package/src/components/ui/attachment.tsx +207 -0
- package/src/components/ui/bubble.tsx +128 -0
- package/src/components/ui/button-group.tsx +87 -0
- package/src/components/ui/button.tsx +6 -6
- package/src/components/ui/calendar.tsx +0 -2
- package/src/components/ui/card.tsx +1 -1
- package/src/components/ui/carousel.tsx +2 -0
- package/src/components/ui/combobox.tsx +297 -0
- package/src/components/ui/command.tsx +43 -41
- package/src/components/ui/dialog.tsx +0 -2
- package/src/components/ui/direction.tsx +4 -0
- package/src/components/ui/drawer.tsx +2 -0
- package/src/components/ui/dropdown-menu.tsx +0 -2
- package/src/components/ui/empty.tsx +104 -0
- package/src/components/ui/field.tsx +238 -0
- package/src/components/ui/hover-card.tsx +2 -0
- package/src/components/ui/input-group.tsx +0 -2
- package/src/components/ui/input-otp.tsx +0 -2
- package/src/components/ui/input.tsx +1 -1
- package/src/components/ui/item.tsx +201 -0
- package/src/components/ui/kbd.tsx +26 -0
- package/src/components/ui/label.tsx +2 -0
- package/src/components/ui/marker.tsx +71 -0
- package/src/components/ui/message-scroller.tsx +131 -0
- package/src/components/ui/message.tsx +92 -0
- package/src/components/ui/native-select.tsx +61 -0
- package/src/components/ui/popover.tsx +0 -2
- package/src/components/ui/progress.tsx +2 -0
- package/src/components/ui/radio-group.tsx +0 -2
- package/src/components/ui/resizable.tsx +2 -0
- package/src/components/ui/scroll-area.tsx +0 -2
- package/src/components/ui/select.tsx +6 -4
- package/src/components/ui/separator.tsx +0 -2
- package/src/components/ui/sheet.tsx +21 -22
- package/src/components/ui/sidebar.tsx +1 -3
- package/src/components/ui/sonner.tsx +2 -0
- package/src/components/ui/spinner.tsx +10 -0
- package/src/components/ui/switch.tsx +0 -2
- package/src/components/ui/table.tsx +4 -2
- package/src/components/ui/tabs.tsx +0 -2
- package/src/components/ui/textarea.tsx +1 -1
- package/src/components/ui/toggle-group.tsx +2 -0
- package/src/components/ui/toggle.tsx +2 -0
- package/src/components/ui/tooltip.tsx +0 -2
- package/src/index.tsx +3 -0
- package/src/lib/nocobase/client.ts +32 -2
- package/src/lib/utils.ts +2 -1
- package/src/locales/en-US.ts +4 -2
- package/src/locales/zh-CN.ts +4 -2
- package/src/pages/login/index.tsx +2 -2
- package/src/pages/users/list.tsx +144 -16
- package/src/providers/auth-callback.ts +21 -0
- package/src/providers/auth.ts +108 -22
- package/src/providers/constants.ts +4 -1
- package/src/providers/runtime-config.ts +19 -0
- package/src/vite-env.d.ts +5 -0
- package/vite.config.ts +55 -2
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as React from "react"
|
|
2
|
-
import {
|
|
2
|
+
import { Command as CommandPrimitive } from "cmdk"
|
|
3
3
|
|
|
4
4
|
import { cn } from "@/lib/utils"
|
|
5
5
|
import {
|
|
@@ -9,32 +9,25 @@ import {
|
|
|
9
9
|
DialogHeader,
|
|
10
10
|
DialogTitle,
|
|
11
11
|
} from "@/components/ui/dialog"
|
|
12
|
-
import {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
}
|
|
12
|
+
import {
|
|
13
|
+
InputGroup,
|
|
14
|
+
InputGroupAddon,
|
|
15
|
+
} from "@/components/ui/input-group"
|
|
16
|
+
import { SearchIcon, CheckIcon } from "lucide-react"
|
|
18
17
|
|
|
19
|
-
function Command
|
|
18
|
+
function Command({
|
|
19
|
+
className,
|
|
20
|
+
...props
|
|
21
|
+
}: React.ComponentProps<typeof CommandPrimitive>) {
|
|
20
22
|
return (
|
|
21
|
-
<
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
23
|
+
<CommandPrimitive
|
|
24
|
+
data-slot="command"
|
|
25
|
+
className={cn(
|
|
26
|
+
"flex size-full flex-col overflow-hidden rounded-xl! bg-popover p-1 text-popover-foreground",
|
|
27
|
+
className
|
|
28
|
+
)}
|
|
26
29
|
{...props}
|
|
27
|
-
|
|
28
|
-
<div
|
|
29
|
-
data-slot="command"
|
|
30
|
-
className={cn(
|
|
31
|
-
"flex size-full flex-col overflow-hidden rounded-xl! bg-popover p-1 text-popover-foreground",
|
|
32
|
-
className
|
|
33
|
-
)}
|
|
34
|
-
>
|
|
35
|
-
{children}
|
|
36
|
-
</div>
|
|
37
|
-
</ComboboxPrimitive.Root>
|
|
30
|
+
/>
|
|
38
31
|
)
|
|
39
32
|
}
|
|
40
33
|
|
|
@@ -74,11 +67,11 @@ function CommandDialog({
|
|
|
74
67
|
function CommandInput({
|
|
75
68
|
className,
|
|
76
69
|
...props
|
|
77
|
-
}:
|
|
70
|
+
}: React.ComponentProps<typeof CommandPrimitive.Input>) {
|
|
78
71
|
return (
|
|
79
72
|
<div data-slot="command-input-wrapper" className="p-1 pb-0">
|
|
80
73
|
<InputGroup className="h-8! rounded-lg! border-input/30 bg-input/30 shadow-none! *:data-[slot=input-group-addon]:pl-2!">
|
|
81
|
-
<
|
|
74
|
+
<CommandPrimitive.Input
|
|
82
75
|
data-slot="command-input"
|
|
83
76
|
className={cn(
|
|
84
77
|
"w-full text-sm outline-hidden disabled:cursor-not-allowed disabled:opacity-50",
|
|
@@ -97,9 +90,9 @@ function CommandInput({
|
|
|
97
90
|
function CommandList({
|
|
98
91
|
className,
|
|
99
92
|
...props
|
|
100
|
-
}:
|
|
93
|
+
}: React.ComponentProps<typeof CommandPrimitive.List>) {
|
|
101
94
|
return (
|
|
102
|
-
<
|
|
95
|
+
<CommandPrimitive.List
|
|
103
96
|
data-slot="command-list"
|
|
104
97
|
className={cn(
|
|
105
98
|
"no-scrollbar max-h-72 scroll-py-1 overflow-x-hidden overflow-y-auto outline-none",
|
|
@@ -113,9 +106,9 @@ function CommandList({
|
|
|
113
106
|
function CommandEmpty({
|
|
114
107
|
className,
|
|
115
108
|
...props
|
|
116
|
-
}:
|
|
109
|
+
}: React.ComponentProps<typeof CommandPrimitive.Empty>) {
|
|
117
110
|
return (
|
|
118
|
-
<
|
|
111
|
+
<CommandPrimitive.Empty
|
|
119
112
|
data-slot="command-empty"
|
|
120
113
|
className={cn("py-6 text-center text-sm", className)}
|
|
121
114
|
{...props}
|
|
@@ -126,11 +119,14 @@ function CommandEmpty({
|
|
|
126
119
|
function CommandGroup({
|
|
127
120
|
className,
|
|
128
121
|
...props
|
|
129
|
-
}:
|
|
122
|
+
}: React.ComponentProps<typeof CommandPrimitive.Group>) {
|
|
130
123
|
return (
|
|
131
|
-
<
|
|
124
|
+
<CommandPrimitive.Group
|
|
132
125
|
data-slot="command-group"
|
|
133
|
-
className={cn(
|
|
126
|
+
className={cn(
|
|
127
|
+
"overflow-hidden p-1 text-foreground **:[[cmdk-group-heading]]:px-2 **:[[cmdk-group-heading]]:py-1.5 **:[[cmdk-group-heading]]:text-xs **:[[cmdk-group-heading]]:font-medium **:[[cmdk-group-heading]]:text-muted-foreground",
|
|
128
|
+
className
|
|
129
|
+
)}
|
|
134
130
|
{...props}
|
|
135
131
|
/>
|
|
136
132
|
)
|
|
@@ -139,11 +135,10 @@ function CommandGroup({
|
|
|
139
135
|
function CommandSeparator({
|
|
140
136
|
className,
|
|
141
137
|
...props
|
|
142
|
-
}: React.ComponentProps<
|
|
138
|
+
}: React.ComponentProps<typeof CommandPrimitive.Separator>) {
|
|
143
139
|
return (
|
|
144
|
-
<
|
|
140
|
+
<CommandPrimitive.Separator
|
|
145
141
|
data-slot="command-separator"
|
|
146
|
-
role="separator"
|
|
147
142
|
className={cn("-mx-1 h-px bg-border", className)}
|
|
148
143
|
{...props}
|
|
149
144
|
/>
|
|
@@ -152,17 +147,21 @@ function CommandSeparator({
|
|
|
152
147
|
|
|
153
148
|
function CommandItem({
|
|
154
149
|
className,
|
|
150
|
+
children,
|
|
155
151
|
...props
|
|
156
|
-
}:
|
|
152
|
+
}: React.ComponentProps<typeof CommandPrimitive.Item>) {
|
|
157
153
|
return (
|
|
158
|
-
<
|
|
154
|
+
<CommandPrimitive.Item
|
|
159
155
|
data-slot="command-item"
|
|
160
156
|
className={cn(
|
|
161
|
-
"group/command-item relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none in-data-[slot=dialog-content]:rounded-lg! data-disabled:pointer-events-none data-disabled:opacity-50 data-
|
|
157
|
+
"group/command-item relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none in-data-[slot=dialog-content]:rounded-lg! data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50 data-selected:bg-muted data-selected:text-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 data-selected:*:[svg]:text-foreground",
|
|
162
158
|
className
|
|
163
159
|
)}
|
|
164
160
|
{...props}
|
|
165
|
-
|
|
161
|
+
>
|
|
162
|
+
{children}
|
|
163
|
+
<CheckIcon className="ml-auto opacity-0 group-has-data-[slot=command-shortcut]/command-item:hidden group-data-[checked=true]/command-item:opacity-100" />
|
|
164
|
+
</CommandPrimitive.Item>
|
|
166
165
|
)
|
|
167
166
|
}
|
|
168
167
|
|
|
@@ -173,7 +172,10 @@ function CommandShortcut({
|
|
|
173
172
|
return (
|
|
174
173
|
<span
|
|
175
174
|
data-slot="command-shortcut"
|
|
176
|
-
className={cn(
|
|
175
|
+
className={cn(
|
|
176
|
+
"ml-auto text-xs tracking-widest text-muted-foreground group-data-selected/command-item:text-foreground",
|
|
177
|
+
className
|
|
178
|
+
)}
|
|
177
179
|
{...props}
|
|
178
180
|
/>
|
|
179
181
|
)
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { cva, type VariantProps } from "class-variance-authority"
|
|
2
|
+
|
|
3
|
+
import { cn } from "@/lib/utils"
|
|
4
|
+
|
|
5
|
+
function Empty({ className, ...props }: React.ComponentProps<"div">) {
|
|
6
|
+
return (
|
|
7
|
+
<div
|
|
8
|
+
data-slot="empty"
|
|
9
|
+
className={cn(
|
|
10
|
+
"flex w-full min-w-0 flex-1 flex-col items-center justify-center gap-4 rounded-xl border-dashed p-6 text-center text-balance",
|
|
11
|
+
className
|
|
12
|
+
)}
|
|
13
|
+
{...props}
|
|
14
|
+
/>
|
|
15
|
+
)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function EmptyHeader({ className, ...props }: React.ComponentProps<"div">) {
|
|
19
|
+
return (
|
|
20
|
+
<div
|
|
21
|
+
data-slot="empty-header"
|
|
22
|
+
className={cn("flex max-w-sm flex-col items-center gap-2", className)}
|
|
23
|
+
{...props}
|
|
24
|
+
/>
|
|
25
|
+
)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const emptyMediaVariants = cva(
|
|
29
|
+
"mb-2 flex shrink-0 items-center justify-center [&_svg]:pointer-events-none [&_svg]:shrink-0",
|
|
30
|
+
{
|
|
31
|
+
variants: {
|
|
32
|
+
variant: {
|
|
33
|
+
default: "bg-transparent",
|
|
34
|
+
icon: "flex size-8 shrink-0 items-center justify-center rounded-lg bg-muted text-foreground [&_svg:not([class*='size-'])]:size-4",
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
defaultVariants: {
|
|
38
|
+
variant: "default",
|
|
39
|
+
},
|
|
40
|
+
}
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
function EmptyMedia({
|
|
44
|
+
className,
|
|
45
|
+
variant = "default",
|
|
46
|
+
...props
|
|
47
|
+
}: React.ComponentProps<"div"> & VariantProps<typeof emptyMediaVariants>) {
|
|
48
|
+
return (
|
|
49
|
+
<div
|
|
50
|
+
data-slot="empty-icon"
|
|
51
|
+
data-variant={variant}
|
|
52
|
+
className={cn(emptyMediaVariants({ variant, className }))}
|
|
53
|
+
{...props}
|
|
54
|
+
/>
|
|
55
|
+
)
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function EmptyTitle({ className, ...props }: React.ComponentProps<"div">) {
|
|
59
|
+
return (
|
|
60
|
+
<div
|
|
61
|
+
data-slot="empty-title"
|
|
62
|
+
className={cn(
|
|
63
|
+
"font-heading text-sm font-medium tracking-tight",
|
|
64
|
+
className
|
|
65
|
+
)}
|
|
66
|
+
{...props}
|
|
67
|
+
/>
|
|
68
|
+
)
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function EmptyDescription({ className, ...props }: React.ComponentProps<"p">) {
|
|
72
|
+
return (
|
|
73
|
+
<div
|
|
74
|
+
data-slot="empty-description"
|
|
75
|
+
className={cn(
|
|
76
|
+
"text-sm/relaxed text-muted-foreground [&>a]:underline [&>a]:underline-offset-4 [&>a:hover]:text-primary",
|
|
77
|
+
className
|
|
78
|
+
)}
|
|
79
|
+
{...props}
|
|
80
|
+
/>
|
|
81
|
+
)
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function EmptyContent({ className, ...props }: React.ComponentProps<"div">) {
|
|
85
|
+
return (
|
|
86
|
+
<div
|
|
87
|
+
data-slot="empty-content"
|
|
88
|
+
className={cn(
|
|
89
|
+
"flex w-full max-w-sm min-w-0 flex-col items-center gap-2.5 text-sm text-balance",
|
|
90
|
+
className
|
|
91
|
+
)}
|
|
92
|
+
{...props}
|
|
93
|
+
/>
|
|
94
|
+
)
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export {
|
|
98
|
+
Empty,
|
|
99
|
+
EmptyHeader,
|
|
100
|
+
EmptyTitle,
|
|
101
|
+
EmptyDescription,
|
|
102
|
+
EmptyContent,
|
|
103
|
+
EmptyMedia,
|
|
104
|
+
}
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
import { useMemo } from "react"
|
|
4
|
+
import { cva, type VariantProps } from "class-variance-authority"
|
|
5
|
+
|
|
6
|
+
import { cn } from "@/lib/utils"
|
|
7
|
+
import { Label } from "@/components/ui/label"
|
|
8
|
+
import { Separator } from "@/components/ui/separator"
|
|
9
|
+
|
|
10
|
+
function FieldSet({ className, ...props }: React.ComponentProps<"fieldset">) {
|
|
11
|
+
return (
|
|
12
|
+
<fieldset
|
|
13
|
+
data-slot="field-set"
|
|
14
|
+
className={cn(
|
|
15
|
+
"flex flex-col gap-4 has-[>[data-slot=checkbox-group]]:gap-3 has-[>[data-slot=radio-group]]:gap-3",
|
|
16
|
+
className
|
|
17
|
+
)}
|
|
18
|
+
{...props}
|
|
19
|
+
/>
|
|
20
|
+
)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function FieldLegend({
|
|
24
|
+
className,
|
|
25
|
+
variant = "legend",
|
|
26
|
+
...props
|
|
27
|
+
}: React.ComponentProps<"legend"> & { variant?: "legend" | "label" }) {
|
|
28
|
+
return (
|
|
29
|
+
<legend
|
|
30
|
+
data-slot="field-legend"
|
|
31
|
+
data-variant={variant}
|
|
32
|
+
className={cn(
|
|
33
|
+
"mb-1.5 font-medium data-[variant=label]:text-sm data-[variant=legend]:text-base",
|
|
34
|
+
className
|
|
35
|
+
)}
|
|
36
|
+
{...props}
|
|
37
|
+
/>
|
|
38
|
+
)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function FieldGroup({ className, ...props }: React.ComponentProps<"div">) {
|
|
42
|
+
return (
|
|
43
|
+
<div
|
|
44
|
+
data-slot="field-group"
|
|
45
|
+
className={cn(
|
|
46
|
+
"group/field-group @container/field-group flex w-full flex-col gap-5 data-[slot=checkbox-group]:gap-3 *:data-[slot=field-group]:gap-4",
|
|
47
|
+
className
|
|
48
|
+
)}
|
|
49
|
+
{...props}
|
|
50
|
+
/>
|
|
51
|
+
)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const fieldVariants = cva(
|
|
55
|
+
"group/field flex w-full gap-2 data-[invalid=true]:text-destructive",
|
|
56
|
+
{
|
|
57
|
+
variants: {
|
|
58
|
+
orientation: {
|
|
59
|
+
vertical: "flex-col *:w-full [&>.sr-only]:w-auto",
|
|
60
|
+
horizontal:
|
|
61
|
+
"flex-row items-center has-[>[data-slot=field-content]]:items-start *:data-[slot=field-label]:flex-auto has-[>[data-slot=field-content]]:[&>[role=checkbox],[role=radio]]:mt-px",
|
|
62
|
+
responsive:
|
|
63
|
+
"flex-col *:w-full @md/field-group:flex-row @md/field-group:items-center @md/field-group:*:w-auto @md/field-group:has-[>[data-slot=field-content]]:items-start @md/field-group:*:data-[slot=field-label]:flex-auto [&>.sr-only]:w-auto @md/field-group:has-[>[data-slot=field-content]]:[&>[role=checkbox],[role=radio]]:mt-px",
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
defaultVariants: {
|
|
67
|
+
orientation: "vertical",
|
|
68
|
+
},
|
|
69
|
+
}
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
function Field({
|
|
73
|
+
className,
|
|
74
|
+
orientation = "vertical",
|
|
75
|
+
...props
|
|
76
|
+
}: React.ComponentProps<"div"> & VariantProps<typeof fieldVariants>) {
|
|
77
|
+
return (
|
|
78
|
+
<div
|
|
79
|
+
role="group"
|
|
80
|
+
data-slot="field"
|
|
81
|
+
data-orientation={orientation}
|
|
82
|
+
className={cn(fieldVariants({ orientation }), className)}
|
|
83
|
+
{...props}
|
|
84
|
+
/>
|
|
85
|
+
)
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function FieldContent({ className, ...props }: React.ComponentProps<"div">) {
|
|
89
|
+
return (
|
|
90
|
+
<div
|
|
91
|
+
data-slot="field-content"
|
|
92
|
+
className={cn(
|
|
93
|
+
"group/field-content flex flex-1 flex-col gap-0.5 leading-snug",
|
|
94
|
+
className
|
|
95
|
+
)}
|
|
96
|
+
{...props}
|
|
97
|
+
/>
|
|
98
|
+
)
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function FieldLabel({
|
|
102
|
+
className,
|
|
103
|
+
...props
|
|
104
|
+
}: React.ComponentProps<typeof Label>) {
|
|
105
|
+
return (
|
|
106
|
+
<Label
|
|
107
|
+
data-slot="field-label"
|
|
108
|
+
className={cn(
|
|
109
|
+
"group/field-label peer/field-label flex w-fit gap-2 leading-snug group-data-[disabled=true]/field:opacity-50 has-data-checked:border-primary/30 has-data-checked:bg-primary/5 has-[>[data-slot=field]]:rounded-lg has-[>[data-slot=field]]:border *:data-[slot=field]:p-2.5 dark:has-data-checked:border-primary/20 dark:has-data-checked:bg-primary/10",
|
|
110
|
+
"has-[>[data-slot=field]]:w-full has-[>[data-slot=field]]:flex-col",
|
|
111
|
+
className
|
|
112
|
+
)}
|
|
113
|
+
{...props}
|
|
114
|
+
/>
|
|
115
|
+
)
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function FieldTitle({ className, ...props }: React.ComponentProps<"div">) {
|
|
119
|
+
return (
|
|
120
|
+
<div
|
|
121
|
+
data-slot="field-label"
|
|
122
|
+
className={cn(
|
|
123
|
+
"flex w-fit items-center gap-2 text-sm font-medium group-data-[disabled=true]/field:opacity-50",
|
|
124
|
+
className
|
|
125
|
+
)}
|
|
126
|
+
{...props}
|
|
127
|
+
/>
|
|
128
|
+
)
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function FieldDescription({ className, ...props }: React.ComponentProps<"p">) {
|
|
132
|
+
return (
|
|
133
|
+
<p
|
|
134
|
+
data-slot="field-description"
|
|
135
|
+
className={cn(
|
|
136
|
+
"text-left text-sm leading-normal font-normal text-muted-foreground group-has-data-horizontal/field:text-balance [[data-variant=legend]+&]:-mt-1.5",
|
|
137
|
+
"last:mt-0 nth-last-2:-mt-1",
|
|
138
|
+
"[&>a]:underline [&>a]:underline-offset-4 [&>a:hover]:text-primary",
|
|
139
|
+
className
|
|
140
|
+
)}
|
|
141
|
+
{...props}
|
|
142
|
+
/>
|
|
143
|
+
)
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function FieldSeparator({
|
|
147
|
+
children,
|
|
148
|
+
className,
|
|
149
|
+
...props
|
|
150
|
+
}: React.ComponentProps<"div"> & {
|
|
151
|
+
children?: React.ReactNode
|
|
152
|
+
}) {
|
|
153
|
+
return (
|
|
154
|
+
<div
|
|
155
|
+
data-slot="field-separator"
|
|
156
|
+
data-content={!!children}
|
|
157
|
+
className={cn(
|
|
158
|
+
"relative -my-2 h-5 text-sm group-data-[variant=outline]/field-group:-mb-2",
|
|
159
|
+
className
|
|
160
|
+
)}
|
|
161
|
+
{...props}
|
|
162
|
+
>
|
|
163
|
+
<Separator className="absolute inset-0 top-1/2" />
|
|
164
|
+
{children && (
|
|
165
|
+
<span
|
|
166
|
+
className="relative mx-auto block w-fit bg-background px-2 text-muted-foreground"
|
|
167
|
+
data-slot="field-separator-content"
|
|
168
|
+
>
|
|
169
|
+
{children}
|
|
170
|
+
</span>
|
|
171
|
+
)}
|
|
172
|
+
</div>
|
|
173
|
+
)
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
function FieldError({
|
|
177
|
+
className,
|
|
178
|
+
children,
|
|
179
|
+
errors,
|
|
180
|
+
...props
|
|
181
|
+
}: React.ComponentProps<"div"> & {
|
|
182
|
+
errors?: Array<{ message?: string } | undefined>
|
|
183
|
+
}) {
|
|
184
|
+
const content = useMemo(() => {
|
|
185
|
+
if (children) {
|
|
186
|
+
return children
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
if (!errors?.length) {
|
|
190
|
+
return null
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
const uniqueErrors = [
|
|
194
|
+
...new Map(errors.map((error) => [error?.message, error])).values(),
|
|
195
|
+
]
|
|
196
|
+
|
|
197
|
+
if (uniqueErrors?.length == 1) {
|
|
198
|
+
return uniqueErrors[0]?.message
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
return (
|
|
202
|
+
<ul className="ml-4 flex list-disc flex-col gap-1">
|
|
203
|
+
{uniqueErrors.map(
|
|
204
|
+
(error, index) =>
|
|
205
|
+
error?.message && <li key={index}>{error.message}</li>
|
|
206
|
+
)}
|
|
207
|
+
</ul>
|
|
208
|
+
)
|
|
209
|
+
}, [children, errors])
|
|
210
|
+
|
|
211
|
+
if (!content) {
|
|
212
|
+
return null
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
return (
|
|
216
|
+
<div
|
|
217
|
+
role="alert"
|
|
218
|
+
data-slot="field-error"
|
|
219
|
+
className={cn("text-sm font-normal text-destructive", className)}
|
|
220
|
+
{...props}
|
|
221
|
+
>
|
|
222
|
+
{content}
|
|
223
|
+
</div>
|
|
224
|
+
)
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
export {
|
|
228
|
+
Field,
|
|
229
|
+
FieldLabel,
|
|
230
|
+
FieldDescription,
|
|
231
|
+
FieldError,
|
|
232
|
+
FieldGroup,
|
|
233
|
+
FieldLegend,
|
|
234
|
+
FieldSeparator,
|
|
235
|
+
FieldSet,
|
|
236
|
+
FieldContent,
|
|
237
|
+
FieldTitle,
|
|
238
|
+
}
|
|
@@ -9,7 +9,7 @@ function Input({ className, type, ...props }: React.ComponentProps<"input">) {
|
|
|
9
9
|
type={type}
|
|
10
10
|
data-slot="input"
|
|
11
11
|
className={cn(
|
|
12
|
-
"h-
|
|
12
|
+
"h-8 w-full min-w-0 rounded-lg border border-input bg-transparent px-2.5 py-1 text-base transition-colors outline-none file:inline-flex file:h-6 file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:pointer-events-none disabled:cursor-not-allowed disabled:bg-input/50 disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 md:text-sm dark:bg-input/30 dark:disabled:bg-input/80 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40",
|
|
13
13
|
className
|
|
14
14
|
)}
|
|
15
15
|
{...props}
|