@autono/create-open-pages 0.4.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/dist/cli.js +1 -1
  2. package/package.json +1 -1
  3. package/template/.agents/skills/create-page/SKILL.md +1 -1
  4. package/template/.agents/skills/page-authoring/SKILL.md +2 -2
  5. package/template/.agents/skills/page-authoring/references/interactivity.md +13 -21
  6. package/template/components.json +19 -3
  7. package/template/package.json +7 -7
  8. package/template/styles/globals.css +83 -66
  9. package/template/ui/accordion.tsx +22 -7
  10. package/template/ui/alert-dialog.tsx +22 -21
  11. package/template/ui/alert.tsx +15 -5
  12. package/template/ui/avatar.tsx +7 -4
  13. package/template/ui/badge.tsx +8 -7
  14. package/template/ui/breadcrumb.tsx +21 -8
  15. package/template/ui/button-group.tsx +5 -5
  16. package/template/ui/button.tsx +18 -15
  17. package/template/ui/calendar.tsx +28 -24
  18. package/template/ui/card.tsx +17 -6
  19. package/template/ui/carousel.tsx +10 -11
  20. package/template/ui/chart.tsx +1 -2
  21. package/template/ui/checkbox.tsx +5 -6
  22. package/template/ui/collapsible.tsx +2 -0
  23. package/template/ui/combobox.tsx +9 -20
  24. package/template/ui/command.tsx +39 -26
  25. package/template/ui/context-menu.tsx +69 -60
  26. package/template/ui/dialog.tsx +26 -14
  27. package/template/ui/drawer.tsx +8 -9
  28. package/template/ui/dropdown-menu.tsx +34 -22
  29. package/template/ui/empty.tsx +8 -8
  30. package/template/ui/field.tsx +15 -25
  31. package/template/ui/hover-card.tsx +1 -1
  32. package/template/ui/input-group.tsx +10 -24
  33. package/template/ui/input-otp.tsx +16 -6
  34. package/template/ui/input.tsx +1 -3
  35. package/template/ui/item.tsx +17 -14
  36. package/template/ui/kbd.tsx +1 -3
  37. package/template/ui/menubar.tsx +28 -24
  38. package/template/ui/message-scroller.tsx +5 -4
  39. package/template/ui/native-select.tsx +13 -14
  40. package/template/ui/navigation-menu.tsx +8 -12
  41. package/template/ui/pagination.tsx +35 -33
  42. package/template/ui/popover.tsx +5 -5
  43. package/template/ui/progress.tsx +2 -2
  44. package/template/ui/radio-group.tsx +4 -5
  45. package/template/ui/resizable.tsx +2 -5
  46. package/template/ui/scroll-area.tsx +2 -5
  47. package/template/ui/select.tsx +26 -24
  48. package/template/ui/separator.tsx +1 -1
  49. package/template/ui/sheet.tsx +20 -16
  50. package/template/ui/sidebar.tsx +39 -63
  51. package/template/ui/skeleton.tsx +1 -1
  52. package/template/ui/slider.tsx +6 -8
  53. package/template/ui/sonner.tsx +21 -14
  54. package/template/ui/spinner.tsx +2 -8
  55. package/template/ui/switch.tsx +4 -4
  56. package/template/ui/table.tsx +2 -4
  57. package/template/ui/tabs.tsx +9 -8
  58. package/template/ui/textarea.tsx +1 -1
  59. package/template/ui/toggle-group.tsx +14 -8
  60. package/template/ui/toggle.tsx +8 -10
  61. package/template/ui/tooltip.tsx +4 -2
  62. package/template/ui/form.tsx +0 -167
@@ -1,5 +1,3 @@
1
- "use client"
2
-
3
1
  import * as React from "react"
4
2
 
5
3
  import { cn } from "@/lib/utils"
@@ -70,7 +68,7 @@ function TableHead({ className, ...props }: React.ComponentProps<"th">) {
70
68
  <th
71
69
  data-slot="table-head"
72
70
  className={cn(
73
- "h-10 px-2 text-left align-middle font-medium whitespace-nowrap text-foreground [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]",
71
+ "h-10 px-2 text-left align-middle font-medium whitespace-nowrap text-foreground [&:has([role=checkbox])]:pr-0",
74
72
  className
75
73
  )}
76
74
  {...props}
@@ -83,7 +81,7 @@ function TableCell({ className, ...props }: React.ComponentProps<"td">) {
83
81
  <td
84
82
  data-slot="table-cell"
85
83
  className={cn(
86
- "p-2 align-middle whitespace-nowrap [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]",
84
+ "p-2 align-middle whitespace-nowrap [&:has([role=checkbox])]:pr-0",
87
85
  className
88
86
  )}
89
87
  {...props}
@@ -1,3 +1,5 @@
1
+ "use client"
2
+
1
3
  import * as React from "react"
2
4
  import { cva, type VariantProps } from "class-variance-authority"
3
5
  import { Tabs as TabsPrimitive } from "radix-ui"
@@ -13,9 +15,8 @@ function Tabs({
13
15
  <TabsPrimitive.Root
14
16
  data-slot="tabs"
15
17
  data-orientation={orientation}
16
- orientation={orientation}
17
18
  className={cn(
18
- "group/tabs flex gap-2 data-[orientation=horizontal]:flex-col",
19
+ "group/tabs flex gap-2 data-horizontal:flex-col",
19
20
  className
20
21
  )}
21
22
  {...props}
@@ -24,7 +25,7 @@ function Tabs({
24
25
  }
25
26
 
26
27
  const tabsListVariants = cva(
27
- "group/tabs-list inline-flex w-fit items-center justify-center rounded-lg p-[3px] text-muted-foreground group-data-[orientation=horizontal]/tabs:h-9 group-data-[orientation=vertical]/tabs:h-fit group-data-[orientation=vertical]/tabs:flex-col data-[variant=line]:rounded-none",
28
+ "group/tabs-list inline-flex w-fit items-center justify-center rounded-lg p-[3px] text-muted-foreground group-data-horizontal/tabs:h-8 group-data-vertical/tabs:h-fit group-data-vertical/tabs:flex-col data-[variant=line]:rounded-none",
28
29
  {
29
30
  variants: {
30
31
  variant: {
@@ -62,10 +63,10 @@ function TabsTrigger({
62
63
  <TabsPrimitive.Trigger
63
64
  data-slot="tabs-trigger"
64
65
  className={cn(
65
- "relative inline-flex h-[calc(100%-1px)] flex-1 items-center justify-center gap-1.5 rounded-md border border-transparent px-2 py-1 text-sm font-medium whitespace-nowrap text-foreground/60 transition-all group-data-[orientation=vertical]/tabs:w-full group-data-[orientation=vertical]/tabs:justify-start hover:text-foreground focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 focus-visible:outline-1 focus-visible:outline-ring disabled:pointer-events-none disabled:opacity-50 group-data-[variant=default]/tabs-list:data-[state=active]:shadow-sm group-data-[variant=line]/tabs-list:data-[state=active]:shadow-none dark:text-muted-foreground dark:hover:text-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
66
- "group-data-[variant=line]/tabs-list:bg-transparent group-data-[variant=line]/tabs-list:data-[state=active]:bg-transparent dark:group-data-[variant=line]/tabs-list:data-[state=active]:border-transparent dark:group-data-[variant=line]/tabs-list:data-[state=active]:bg-transparent",
67
- "data-[state=active]:bg-background data-[state=active]:text-foreground dark:data-[state=active]:border-input dark:data-[state=active]:bg-input/30 dark:data-[state=active]:text-foreground",
68
- "after:absolute after:bg-foreground after:opacity-0 after:transition-opacity group-data-[orientation=horizontal]/tabs:after:inset-x-0 group-data-[orientation=horizontal]/tabs:after:bottom-[-5px] group-data-[orientation=horizontal]/tabs:after:h-0.5 group-data-[orientation=vertical]/tabs:after:inset-y-0 group-data-[orientation=vertical]/tabs:after:-right-1 group-data-[orientation=vertical]/tabs:after:w-0.5 group-data-[variant=line]/tabs-list:data-[state=active]:after:opacity-100",
66
+ "relative inline-flex h-[calc(100%-1px)] flex-1 items-center justify-center gap-1.5 rounded-md border border-transparent px-1.5 py-0.5 text-sm font-medium whitespace-nowrap text-foreground/60 transition-all group-data-vertical/tabs:w-full group-data-vertical/tabs:justify-start hover:text-foreground focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 focus-visible:outline-1 focus-visible:outline-ring disabled:pointer-events-none disabled:opacity-50 has-data-[icon=inline-end]:pr-1 has-data-[icon=inline-start]:pl-1 dark:text-muted-foreground dark:hover:text-foreground group-data-[variant=default]/tabs-list:data-active:shadow-sm group-data-[variant=line]/tabs-list:data-active:shadow-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
67
+ "group-data-[variant=line]/tabs-list:bg-transparent group-data-[variant=line]/tabs-list:data-active:bg-transparent dark:group-data-[variant=line]/tabs-list:data-active:border-transparent dark:group-data-[variant=line]/tabs-list:data-active:bg-transparent",
68
+ "data-active:bg-background data-active:text-foreground dark:data-active:border-input dark:data-active:bg-input/30 dark:data-active:text-foreground",
69
+ "after:absolute after:bg-foreground after:opacity-0 after:transition-opacity group-data-horizontal/tabs:after:inset-x-0 group-data-horizontal/tabs:after:bottom-[-5px] group-data-horizontal/tabs:after:h-0.5 group-data-vertical/tabs:after:inset-y-0 group-data-vertical/tabs:after:-right-1 group-data-vertical/tabs:after:w-0.5 group-data-[variant=line]/tabs-list:data-active:after:opacity-100",
69
70
  className
70
71
  )}
71
72
  {...props}
@@ -80,7 +81,7 @@ function TabsContent({
80
81
  return (
81
82
  <TabsPrimitive.Content
82
83
  data-slot="tabs-content"
83
- className={cn("flex-1 outline-none", className)}
84
+ className={cn("flex-1 text-sm outline-none", className)}
84
85
  {...props}
85
86
  />
86
87
  )
@@ -7,7 +7,7 @@ function Textarea({ className, ...props }: React.ComponentProps<"textarea">) {
7
7
  <textarea
8
8
  data-slot="textarea"
9
9
  className={cn(
10
- "flex field-sizing-content min-h-16 w-full rounded-md border border-input bg-transparent px-3 py-2 text-base shadow-xs transition-[color,box-shadow] outline-none placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 md:text-sm dark:bg-input/30 dark:aria-invalid:ring-destructive/40",
10
+ "flex field-sizing-content min-h-16 w-full rounded-lg border border-input bg-transparent px-2.5 py-2 text-base transition-colors outline-none placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 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",
11
11
  className
12
12
  )}
13
13
  {...props}
@@ -8,23 +8,27 @@ import { toggleVariants } from "@/ui/toggle"
8
8
  const ToggleGroupContext = React.createContext<
9
9
  VariantProps<typeof toggleVariants> & {
10
10
  spacing?: number
11
+ orientation?: "horizontal" | "vertical"
11
12
  }
12
13
  >({
13
14
  size: "default",
14
15
  variant: "default",
15
- spacing: 0,
16
+ spacing: 2,
17
+ orientation: "horizontal",
16
18
  })
17
19
 
18
20
  function ToggleGroup({
19
21
  className,
20
22
  variant,
21
23
  size,
22
- spacing = 0,
24
+ spacing = 2,
25
+ orientation = "horizontal",
23
26
  children,
24
27
  ...props
25
28
  }: React.ComponentProps<typeof ToggleGroupPrimitive.Root> &
26
29
  VariantProps<typeof toggleVariants> & {
27
30
  spacing?: number
31
+ orientation?: "horizontal" | "vertical"
28
32
  }) {
29
33
  return (
30
34
  <ToggleGroupPrimitive.Root
@@ -32,14 +36,17 @@ function ToggleGroup({
32
36
  data-variant={variant}
33
37
  data-size={size}
34
38
  data-spacing={spacing}
39
+ data-orientation={orientation}
35
40
  style={{ "--gap": spacing } as React.CSSProperties}
36
41
  className={cn(
37
- "group/toggle-group flex w-fit items-center gap-[--spacing(var(--gap))] rounded-md data-[spacing=default]:data-[variant=outline]:shadow-xs",
42
+ "group/toggle-group flex w-fit flex-row items-center gap-[--spacing(var(--gap))] rounded-lg data-[size=sm]:rounded-[min(var(--radius-md),10px)] data-vertical:flex-col data-vertical:items-stretch",
38
43
  className
39
44
  )}
40
45
  {...props}
41
46
  >
42
- <ToggleGroupContext.Provider value={{ variant, size, spacing }}>
47
+ <ToggleGroupContext.Provider
48
+ value={{ variant, size, spacing, orientation }}
49
+ >
43
50
  {children}
44
51
  </ToggleGroupContext.Provider>
45
52
  </ToggleGroupPrimitive.Root>
@@ -49,8 +56,8 @@ function ToggleGroup({
49
56
  function ToggleGroupItem({
50
57
  className,
51
58
  children,
52
- variant,
53
- size,
59
+ variant = "default",
60
+ size = "default",
54
61
  ...props
55
62
  }: React.ComponentProps<typeof ToggleGroupPrimitive.Item> &
56
63
  VariantProps<typeof toggleVariants>) {
@@ -63,12 +70,11 @@ function ToggleGroupItem({
63
70
  data-size={context.size || size}
64
71
  data-spacing={context.spacing}
65
72
  className={cn(
73
+ "shrink-0 group-data-[spacing=0]/toggle-group:rounded-none group-data-[spacing=0]/toggle-group:px-2 focus:z-10 focus-visible:z-10 group-data-[spacing=0]/toggle-group:has-data-[icon=inline-end]:pr-1.5 group-data-[spacing=0]/toggle-group:has-data-[icon=inline-start]:pl-1.5 group-data-horizontal/toggle-group:data-[spacing=0]:first:rounded-l-lg group-data-vertical/toggle-group:data-[spacing=0]:first:rounded-t-lg group-data-horizontal/toggle-group:data-[spacing=0]:last:rounded-r-lg group-data-vertical/toggle-group:data-[spacing=0]:last:rounded-b-lg group-data-horizontal/toggle-group:data-[spacing=0]:data-[variant=outline]:border-l-0 group-data-vertical/toggle-group:data-[spacing=0]:data-[variant=outline]:border-t-0 group-data-horizontal/toggle-group:data-[spacing=0]:data-[variant=outline]:first:border-l group-data-vertical/toggle-group:data-[spacing=0]:data-[variant=outline]:first:border-t",
66
74
  toggleVariants({
67
75
  variant: context.variant || variant,
68
76
  size: context.size || size,
69
77
  }),
70
- "w-auto min-w-0 shrink-0 px-3 focus:z-10 focus-visible:z-10",
71
- "data-[spacing=0]:rounded-none data-[spacing=0]:shadow-none data-[spacing=0]:first:rounded-l-md data-[spacing=0]:last:rounded-r-md data-[spacing=0]:data-[variant=outline]:border-l-0 data-[spacing=0]:data-[variant=outline]:first:border-l",
72
78
  className
73
79
  )}
74
80
  {...props}
@@ -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
  import { Toggle as TogglePrimitive } from "radix-ui"
@@ -7,18 +5,18 @@ import { Toggle as TogglePrimitive } from "radix-ui"
7
5
  import { cn } from "@/lib/utils"
8
6
 
9
7
  const toggleVariants = cva(
10
- "inline-flex items-center justify-center gap-2 rounded-md text-sm font-medium whitespace-nowrap transition-[color,box-shadow] outline-none hover:bg-muted hover:text-muted-foreground focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 data-[state=on]:bg-accent data-[state=on]:text-accent-foreground dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
8
+ "group/toggle inline-flex items-center justify-center gap-1 rounded-lg text-sm font-medium whitespace-nowrap transition-all outline-none hover:bg-muted hover:text-foreground focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 aria-pressed:bg-muted data-[state=on]:bg-muted dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
11
9
  {
12
10
  variants: {
13
11
  variant: {
14
12
  default: "bg-transparent",
15
- outline:
16
- "border border-input bg-transparent shadow-xs hover:bg-accent hover:text-accent-foreground",
13
+ outline: "border border-input bg-transparent hover:bg-muted",
17
14
  },
18
15
  size: {
19
- default: "h-9 min-w-9 px-2",
20
- sm: "h-8 min-w-8 px-1.5",
21
- lg: "h-10 min-w-10 px-2.5",
16
+ default:
17
+ "h-8 min-w-8 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2",
18
+ sm: "h-7 min-w-7 rounded-[min(var(--radius-md),12px)] px-2.5 text-[0.8rem] has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3.5",
19
+ lg: "h-9 min-w-9 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2",
22
20
  },
23
21
  },
24
22
  defaultVariants: {
@@ -30,8 +28,8 @@ const toggleVariants = cva(
30
28
 
31
29
  function Toggle({
32
30
  className,
33
- variant,
34
- size,
31
+ variant = "default",
32
+ size = "default",
35
33
  ...props
36
34
  }: React.ComponentProps<typeof TogglePrimitive.Root> &
37
35
  VariantProps<typeof toggleVariants>) {
@@ -1,3 +1,5 @@
1
+ "use client"
2
+
1
3
  import * as React from "react"
2
4
  import { Tooltip as TooltipPrimitive } from "radix-ui"
3
5
 
@@ -40,7 +42,7 @@ function TooltipContent({
40
42
  data-slot="tooltip-content"
41
43
  sideOffset={sideOffset}
42
44
  className={cn(
43
- "z-50 w-fit origin-(--radix-tooltip-content-transform-origin) animate-in rounded-md bg-foreground px-3 py-1.5 text-xs text-balance text-background fade-in-0 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 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95",
45
+ "z-50 inline-flex w-fit max-w-xs origin-(--radix-tooltip-content-transform-origin) items-center gap-1.5 rounded-md bg-foreground px-3 py-1.5 text-xs text-background has-data-[slot=kbd]:pr-1.5 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-[slot=kbd]:relative **:data-[slot=kbd]:isolate **:data-[slot=kbd]:z-50 **:data-[slot=kbd]:rounded-sm data-[state=delayed-open]:animate-in data-[state=delayed-open]:fade-in-0 data-[state=delayed-open]:zoom-in-95 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",
44
46
  className
45
47
  )}
46
48
  {...props}
@@ -52,4 +54,4 @@ function TooltipContent({
52
54
  )
53
55
  }
54
56
 
55
- export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider }
57
+ export { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger }
@@ -1,167 +0,0 @@
1
- "use client"
2
-
3
- import * as React from "react"
4
- import type { Label as LabelPrimitive } from "radix-ui"
5
- import { Slot } from "radix-ui"
6
- import {
7
- Controller,
8
- FormProvider,
9
- useFormContext,
10
- useFormState,
11
- type ControllerProps,
12
- type FieldPath,
13
- type FieldValues,
14
- } from "react-hook-form"
15
-
16
- import { cn } from "@/lib/utils"
17
- import { Label } from "@/ui/label"
18
-
19
- const Form = FormProvider
20
-
21
- type FormFieldContextValue<
22
- TFieldValues extends FieldValues = FieldValues,
23
- TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
24
- > = {
25
- name: TName
26
- }
27
-
28
- const FormFieldContext = React.createContext<FormFieldContextValue>(
29
- {} as FormFieldContextValue
30
- )
31
-
32
- const FormField = <
33
- TFieldValues extends FieldValues = FieldValues,
34
- TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
35
- >({
36
- ...props
37
- }: ControllerProps<TFieldValues, TName>) => {
38
- return (
39
- <FormFieldContext.Provider value={{ name: props.name }}>
40
- <Controller {...props} />
41
- </FormFieldContext.Provider>
42
- )
43
- }
44
-
45
- const useFormField = () => {
46
- const fieldContext = React.useContext(FormFieldContext)
47
- const itemContext = React.useContext(FormItemContext)
48
- const { getFieldState } = useFormContext()
49
- const formState = useFormState({ name: fieldContext.name })
50
- const fieldState = getFieldState(fieldContext.name, formState)
51
-
52
- if (!fieldContext) {
53
- throw new Error("useFormField should be used within <FormField>")
54
- }
55
-
56
- const { id } = itemContext
57
-
58
- return {
59
- id,
60
- name: fieldContext.name,
61
- formItemId: `${id}-form-item`,
62
- formDescriptionId: `${id}-form-item-description`,
63
- formMessageId: `${id}-form-item-message`,
64
- ...fieldState,
65
- }
66
- }
67
-
68
- type FormItemContextValue = {
69
- id: string
70
- }
71
-
72
- const FormItemContext = React.createContext<FormItemContextValue>(
73
- {} as FormItemContextValue
74
- )
75
-
76
- function FormItem({ className, ...props }: React.ComponentProps<"div">) {
77
- const id = React.useId()
78
-
79
- return (
80
- <FormItemContext.Provider value={{ id }}>
81
- <div
82
- data-slot="form-item"
83
- className={cn("grid gap-2", className)}
84
- {...props}
85
- />
86
- </FormItemContext.Provider>
87
- )
88
- }
89
-
90
- function FormLabel({
91
- className,
92
- ...props
93
- }: React.ComponentProps<typeof LabelPrimitive.Root>) {
94
- const { error, formItemId } = useFormField()
95
-
96
- return (
97
- <Label
98
- data-slot="form-label"
99
- data-error={!!error}
100
- className={cn("data-[error=true]:text-destructive", className)}
101
- htmlFor={formItemId}
102
- {...props}
103
- />
104
- )
105
- }
106
-
107
- function FormControl({ ...props }: React.ComponentProps<typeof Slot.Root>) {
108
- const { error, formItemId, formDescriptionId, formMessageId } = useFormField()
109
-
110
- return (
111
- <Slot.Root
112
- data-slot="form-control"
113
- id={formItemId}
114
- aria-describedby={
115
- !error
116
- ? `${formDescriptionId}`
117
- : `${formDescriptionId} ${formMessageId}`
118
- }
119
- aria-invalid={!!error}
120
- {...props}
121
- />
122
- )
123
- }
124
-
125
- function FormDescription({ className, ...props }: React.ComponentProps<"p">) {
126
- const { formDescriptionId } = useFormField()
127
-
128
- return (
129
- <p
130
- data-slot="form-description"
131
- id={formDescriptionId}
132
- className={cn("text-sm text-muted-foreground", className)}
133
- {...props}
134
- />
135
- )
136
- }
137
-
138
- function FormMessage({ className, ...props }: React.ComponentProps<"p">) {
139
- const { error, formMessageId } = useFormField()
140
- const body = error ? String(error?.message ?? "") : props.children
141
-
142
- if (!body) {
143
- return null
144
- }
145
-
146
- return (
147
- <p
148
- data-slot="form-message"
149
- id={formMessageId}
150
- className={cn("text-sm text-destructive", className)}
151
- {...props}
152
- >
153
- {body}
154
- </p>
155
- )
156
- }
157
-
158
- export {
159
- useFormField,
160
- Form,
161
- FormItem,
162
- FormLabel,
163
- FormControl,
164
- FormDescription,
165
- FormMessage,
166
- FormField,
167
- }