@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.
Files changed (139) hide show
  1. package/README.MD +77 -0
  2. package/package.json +23 -17
  3. package/registry/nocobase-acl/demo/prompt-generator.tsx +6 -39
  4. package/registry/nocobase-acl/demo/role-switcher-prompt-generator.tsx +6 -42
  5. package/registry/nocobase-ai/demo/page-context-prompt-generator.tsx +1 -1
  6. package/registry/nocobase-ai/demo/prompt-card.tsx +7 -28
  7. package/registry/nocobase-ai/demo/prompt-generator.tsx +9 -30
  8. package/registry/nocobase-ai/demo/shortcut.tsx +1 -1
  9. package/registry/nocobase-ai/demo/tool-cards.tsx +10 -30
  10. package/registry/nocobase-auth-cas/README.md +6 -0
  11. package/registry/nocobase-auth-cas/cas-sign-in-button.tsx +41 -0
  12. package/registry/nocobase-auth-cas/demo.tsx +20 -0
  13. package/registry/nocobase-auth-cas/extension.tsx +46 -0
  14. package/registry/nocobase-auth-cas/index.ts +1 -0
  15. package/registry/nocobase-auth-cas/use-cas-sign-in.ts +29 -0
  16. package/registry/nocobase-auth-dingtalk/README.md +7 -0
  17. package/registry/nocobase-auth-dingtalk/auto-login-provider.tsx +154 -0
  18. package/registry/nocobase-auth-dingtalk/demo.tsx +23 -0
  19. package/registry/nocobase-auth-dingtalk/dingtalk-sign-in-button.tsx +45 -0
  20. package/registry/nocobase-auth-dingtalk/extension.tsx +55 -0
  21. package/registry/nocobase-auth-dingtalk/index.ts +4 -0
  22. package/registry/nocobase-auth-dingtalk/use-dingtalk-sign-in.ts +64 -0
  23. package/registry/nocobase-auth-ldap/README.md +6 -0
  24. package/registry/nocobase-auth-ldap/demo.tsx +21 -0
  25. package/registry/nocobase-auth-ldap/extension.tsx +46 -0
  26. package/registry/nocobase-auth-ldap/index.ts +1 -0
  27. package/registry/nocobase-auth-ldap/ldap-sign-in-form.tsx +69 -0
  28. package/registry/nocobase-auth-ldap/use-ldap-sign-in.ts +5 -0
  29. package/registry/nocobase-auth-oidc/README.md +11 -0
  30. package/registry/nocobase-auth-oidc/auto-redirect-provider.tsx +13 -0
  31. package/registry/nocobase-auth-oidc/demo.tsx +20 -0
  32. package/registry/nocobase-auth-oidc/extension.tsx +51 -0
  33. package/registry/nocobase-auth-oidc/index.ts +1 -0
  34. package/registry/nocobase-auth-oidc/oidc-sign-in-button.tsx +44 -0
  35. package/registry/nocobase-auth-oidc/use-oidc-sign-in.ts +58 -0
  36. package/registry/nocobase-auth-saml/README.md +6 -0
  37. package/registry/nocobase-auth-saml/auto-redirect-provider.tsx +13 -0
  38. package/registry/nocobase-auth-saml/demo.tsx +20 -0
  39. package/registry/nocobase-auth-saml/extension.tsx +51 -0
  40. package/registry/nocobase-auth-saml/index.ts +1 -0
  41. package/registry/nocobase-auth-saml/saml-sign-in-button.tsx +43 -0
  42. package/registry/nocobase-auth-saml/use-saml-sign-in.ts +51 -0
  43. package/registry/nocobase-auth-sms/README.md +7 -0
  44. package/registry/nocobase-auth-sms/demo.tsx +25 -0
  45. package/registry/nocobase-auth-sms/extension.tsx +46 -0
  46. package/registry/nocobase-auth-sms/index.ts +1 -0
  47. package/registry/nocobase-auth-sms/sms-sign-in-form.tsx +107 -0
  48. package/registry/nocobase-auth-sms/use-sms-sign-in.ts +88 -0
  49. package/registry/nocobase-auth-wecom/README.md +6 -0
  50. package/registry/nocobase-auth-wecom/auto-login-provider.tsx +21 -0
  51. package/registry/nocobase-auth-wecom/demo.tsx +23 -0
  52. package/registry/nocobase-auth-wecom/extension.tsx +49 -0
  53. package/registry/nocobase-auth-wecom/index.ts +1 -0
  54. package/registry/nocobase-auth-wecom/use-wecom-sign-in.ts +62 -0
  55. package/registry/nocobase-auth-wecom/wecom-sign-in-button.tsx +70 -0
  56. package/registry/nocobase-i18n/demo/prompt-generator.tsx +30 -54
  57. package/registry/nocobase-route-surfaces/demo/prompt-generator.tsx +18 -21
  58. package/registry.config.json +112 -0
  59. package/scripts/build-html.mjs +106 -0
  60. package/src/App.tsx +34 -8
  61. package/src/app/extension.ts +4 -0
  62. package/src/app/extensions.tsx +24 -1
  63. package/src/components/auth/authenticator-adapters.ts +20 -0
  64. package/src/components/auth/auto-redirect-provider.tsx +84 -0
  65. package/src/components/auth/basic-sign-in-form.tsx +101 -0
  66. package/src/components/auth/default-sign-in-page.tsx +20 -0
  67. package/src/components/auth/demo/auth-demo-page.tsx +236 -0
  68. package/src/components/auth/demo/auth-demo-prompt-generator.tsx +93 -0
  69. package/src/components/auth/demo/auth-demo-route.tsx +11 -0
  70. package/src/components/auth/demo/auth-method-demo.tsx +48 -0
  71. package/src/components/auth/demo/index.ts +4 -0
  72. package/src/components/auth/dynamic-sign-in.tsx +191 -0
  73. package/src/components/auth/forgot-password-form.tsx +13 -5
  74. package/src/components/auth/index.ts +13 -0
  75. package/src/components/auth/sign-in-form.tsx +1 -111
  76. package/src/components/auth/sign-up-form.tsx +14 -37
  77. package/src/components/auth/types.ts +38 -0
  78. package/src/components/auth/use-authenticator-sign-in.ts +14 -0
  79. package/src/components/auth/use-public-authenticators.ts +26 -0
  80. package/src/components/data-table/data-table-filter.tsx +107 -153
  81. package/src/components/demo/prompt-output.tsx +71 -0
  82. package/src/components/ui/alert-dialog.tsx +2 -0
  83. package/src/components/ui/attachment.tsx +207 -0
  84. package/src/components/ui/bubble.tsx +128 -0
  85. package/src/components/ui/button-group.tsx +87 -0
  86. package/src/components/ui/button.tsx +6 -6
  87. package/src/components/ui/calendar.tsx +0 -2
  88. package/src/components/ui/card.tsx +1 -1
  89. package/src/components/ui/carousel.tsx +2 -0
  90. package/src/components/ui/combobox.tsx +297 -0
  91. package/src/components/ui/command.tsx +43 -41
  92. package/src/components/ui/dialog.tsx +0 -2
  93. package/src/components/ui/direction.tsx +4 -0
  94. package/src/components/ui/drawer.tsx +2 -0
  95. package/src/components/ui/dropdown-menu.tsx +0 -2
  96. package/src/components/ui/empty.tsx +104 -0
  97. package/src/components/ui/field.tsx +238 -0
  98. package/src/components/ui/hover-card.tsx +2 -0
  99. package/src/components/ui/input-group.tsx +0 -2
  100. package/src/components/ui/input-otp.tsx +0 -2
  101. package/src/components/ui/input.tsx +1 -1
  102. package/src/components/ui/item.tsx +201 -0
  103. package/src/components/ui/kbd.tsx +26 -0
  104. package/src/components/ui/label.tsx +2 -0
  105. package/src/components/ui/marker.tsx +71 -0
  106. package/src/components/ui/message-scroller.tsx +131 -0
  107. package/src/components/ui/message.tsx +92 -0
  108. package/src/components/ui/native-select.tsx +61 -0
  109. package/src/components/ui/popover.tsx +0 -2
  110. package/src/components/ui/progress.tsx +2 -0
  111. package/src/components/ui/radio-group.tsx +0 -2
  112. package/src/components/ui/resizable.tsx +2 -0
  113. package/src/components/ui/scroll-area.tsx +0 -2
  114. package/src/components/ui/select.tsx +6 -4
  115. package/src/components/ui/separator.tsx +0 -2
  116. package/src/components/ui/sheet.tsx +21 -22
  117. package/src/components/ui/sidebar.tsx +1 -3
  118. package/src/components/ui/sonner.tsx +2 -0
  119. package/src/components/ui/spinner.tsx +10 -0
  120. package/src/components/ui/switch.tsx +0 -2
  121. package/src/components/ui/table.tsx +4 -2
  122. package/src/components/ui/tabs.tsx +0 -2
  123. package/src/components/ui/textarea.tsx +1 -1
  124. package/src/components/ui/toggle-group.tsx +2 -0
  125. package/src/components/ui/toggle.tsx +2 -0
  126. package/src/components/ui/tooltip.tsx +0 -2
  127. package/src/index.tsx +3 -0
  128. package/src/lib/nocobase/client.ts +32 -2
  129. package/src/lib/utils.ts +2 -1
  130. package/src/locales/en-US.ts +4 -2
  131. package/src/locales/zh-CN.ts +4 -2
  132. package/src/pages/login/index.tsx +2 -2
  133. package/src/pages/users/list.tsx +144 -16
  134. package/src/providers/auth-callback.ts +21 -0
  135. package/src/providers/auth.ts +108 -22
  136. package/src/providers/constants.ts +4 -1
  137. package/src/providers/runtime-config.ts +19 -0
  138. package/src/vite-env.d.ts +5 -0
  139. package/vite.config.ts +55 -2
@@ -1,5 +1,5 @@
1
1
  import * as React from "react"
2
- import { Combobox as ComboboxPrimitive } from "@base-ui/react/combobox"
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 { InputGroup, InputGroupAddon } from "@/components/ui/input-group"
13
- import { SearchIcon } from "lucide-react"
14
-
15
- type CommandProps<Value> = ComboboxPrimitive.Root.Props<Value> & {
16
- className?: string
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<Value>({ className, children, ...props }: CommandProps<Value>) {
18
+ function Command({
19
+ className,
20
+ ...props
21
+ }: React.ComponentProps<typeof CommandPrimitive>) {
20
22
  return (
21
- <ComboboxPrimitive.Root
22
- inline
23
- open
24
- autoHighlight
25
- value={null}
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
- }: ComboboxPrimitive.Input.Props) {
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
- <ComboboxPrimitive.Input
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
- }: ComboboxPrimitive.List.Props) {
93
+ }: React.ComponentProps<typeof CommandPrimitive.List>) {
101
94
  return (
102
- <ComboboxPrimitive.List
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
- }: ComboboxPrimitive.Empty.Props) {
109
+ }: React.ComponentProps<typeof CommandPrimitive.Empty>) {
117
110
  return (
118
- <ComboboxPrimitive.Empty
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
- }: ComboboxPrimitive.Group.Props) {
122
+ }: React.ComponentProps<typeof CommandPrimitive.Group>) {
130
123
  return (
131
- <ComboboxPrimitive.Group
124
+ <CommandPrimitive.Group
132
125
  data-slot="command-group"
133
- className={cn("overflow-hidden p-1 text-foreground", className)}
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<"div">) {
138
+ }: React.ComponentProps<typeof CommandPrimitive.Separator>) {
143
139
  return (
144
- <div
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
- }: ComboboxPrimitive.Item.Props) {
152
+ }: React.ComponentProps<typeof CommandPrimitive.Item>) {
157
153
  return (
158
- <ComboboxPrimitive.Item
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-highlighted:bg-muted data-highlighted:text-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
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("ml-auto text-xs tracking-widest text-muted-foreground", className)}
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
  )
@@ -1,5 +1,3 @@
1
- "use client"
2
-
3
1
  import * as React from "react"
4
2
  import { Dialog as DialogPrimitive } from "@base-ui/react/dialog"
5
3
 
@@ -0,0 +1,4 @@
1
+ export {
2
+ DirectionProvider,
3
+ useDirection,
4
+ } from "@base-ui/react/direction-provider"
@@ -1,3 +1,5 @@
1
+ "use client"
2
+
1
3
  import * as React from "react"
2
4
  import { Drawer as DrawerPrimitive } from "@base-ui/react/drawer"
3
5
 
@@ -1,5 +1,3 @@
1
- "use client"
2
-
3
1
  import * as React from "react"
4
2
  import { Menu as MenuPrimitive } from "@base-ui/react/menu"
5
3
 
@@ -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
+ }
@@ -1,3 +1,5 @@
1
+ "use client"
2
+
1
3
  import { PreviewCard as PreviewCardPrimitive } from "@base-ui/react/preview-card"
2
4
 
3
5
  import { cn } from "@/lib/utils"
@@ -1,5 +1,3 @@
1
- "use client"
2
-
3
1
  import * as React from "react"
4
2
  import { cva, type VariantProps } from "class-variance-authority"
5
3
 
@@ -1,5 +1,3 @@
1
- "use client"
2
-
3
1
  import * as React from "react"
4
2
  import { OTPInput, OTPInputContext } from "input-otp"
5
3
 
@@ -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-9 w-full min-w-0 rounded-lg border border-input bg-transparent px-3 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/30 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",
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}