@leitware/dockets 0.1.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 (135) hide show
  1. package/dist/cli.d.ts +3 -0
  2. package/dist/cli.d.ts.map +1 -0
  3. package/dist/cli.js +18 -0
  4. package/dist/cli.js.map +1 -0
  5. package/dist/commands/add.d.ts +3 -0
  6. package/dist/commands/add.d.ts.map +1 -0
  7. package/dist/commands/add.js +86 -0
  8. package/dist/commands/add.js.map +1 -0
  9. package/dist/commands/list.d.ts +3 -0
  10. package/dist/commands/list.d.ts.map +1 -0
  11. package/dist/commands/list.js +36 -0
  12. package/dist/commands/list.js.map +1 -0
  13. package/dist/registry.d.ts +18 -0
  14. package/dist/registry.d.ts.map +1 -0
  15. package/dist/registry.js +712 -0
  16. package/dist/registry.js.map +1 -0
  17. package/package.json +40 -0
  18. package/templates/accordion.tsx +77 -0
  19. package/templates/alert-dialog.tsx +66 -0
  20. package/templates/alert.tsx +41 -0
  21. package/templates/aspect-ratio.tsx +15 -0
  22. package/templates/avatar.tsx +27 -0
  23. package/templates/badge.tsx +1 -0
  24. package/templates/block-loader.tsx +1 -0
  25. package/templates/breadcrumb.tsx +31 -0
  26. package/templates/button.tsx +1 -0
  27. package/templates/calendar.tsx +45 -0
  28. package/templates/card.tsx +35 -0
  29. package/templates/carousel.tsx +39 -0
  30. package/templates/checkbox.tsx +50 -0
  31. package/templates/code-block.tsx +1 -0
  32. package/templates/collapsible.tsx +35 -0
  33. package/templates/combobox.tsx +154 -0
  34. package/templates/command.tsx +50 -0
  35. package/templates/contact-footer.tsx +193 -0
  36. package/templates/context-menu.tsx +16 -0
  37. package/templates/dialog.tsx +67 -0
  38. package/templates/drawer.tsx +12 -0
  39. package/templates/dropdown-menu.tsx +95 -0
  40. package/templates/form-input.tsx +64 -0
  41. package/templates/form.tsx +10 -0
  42. package/templates/hover-card.tsx +5 -0
  43. package/templates/input-otp.tsx +6 -0
  44. package/templates/label.tsx +1 -0
  45. package/templates/layout-primitives.tsx +11 -0
  46. package/templates/layouts.tsx +346 -0
  47. package/templates/lib/utils.ts +49 -0
  48. package/templates/list-item.tsx +1 -0
  49. package/templates/list-items.tsx +41 -0
  50. package/templates/list.tsx +89 -0
  51. package/templates/logo.tsx +12 -0
  52. package/templates/marketing-footer.tsx +33 -0
  53. package/templates/marketing-header.tsx +46 -0
  54. package/templates/menubar.tsx +16 -0
  55. package/templates/navigation-menu.tsx +11 -0
  56. package/templates/pagination.tsx +86 -0
  57. package/templates/popover.tsx +8 -0
  58. package/templates/pricing-receipt.tsx +71 -0
  59. package/templates/pricing-tabs.tsx +60 -0
  60. package/templates/progress.tsx +29 -0
  61. package/templates/radio-group.tsx +58 -0
  62. package/templates/receipt-card.tsx +1 -0
  63. package/templates/receipt.tsx +269 -0
  64. package/templates/resizable.tsx +1 -0
  65. package/templates/scroll-area.tsx +1 -0
  66. package/templates/select.tsx +110 -0
  67. package/templates/separator.tsx +1 -0
  68. package/templates/sheet.tsx +12 -0
  69. package/templates/sidebar.tsx +15 -0
  70. package/templates/simple-footer.tsx +43 -0
  71. package/templates/simple-header.tsx +77 -0
  72. package/templates/skeleton.tsx +33 -0
  73. package/templates/slider.tsx +55 -0
  74. package/templates/styles/dockets.css +104 -0
  75. package/templates/switch.tsx +49 -0
  76. package/templates/table.tsx +73 -0
  77. package/templates/tabs.tsx +61 -0
  78. package/templates/theme-toggle.tsx +46 -0
  79. package/templates/toast.tsx +1 -0
  80. package/templates/toggle-group.tsx +1 -0
  81. package/templates/toggle.tsx +1 -0
  82. package/templates/tooltip.tsx +31 -0
  83. package/templates/tree-view.tsx +1 -0
  84. package/templates/ui/accordion.tsx +73 -0
  85. package/templates/ui/alert-dialog.tsx +128 -0
  86. package/templates/ui/alert.tsx +56 -0
  87. package/templates/ui/aspect-ratio.tsx +19 -0
  88. package/templates/ui/avatar.tsx +74 -0
  89. package/templates/ui/badge.tsx +48 -0
  90. package/templates/ui/block-loader.tsx +40 -0
  91. package/templates/ui/button.tsx +77 -0
  92. package/templates/ui/calendar.tsx +160 -0
  93. package/templates/ui/card.tsx +73 -0
  94. package/templates/ui/carousel.tsx +149 -0
  95. package/templates/ui/checkbox.tsx +33 -0
  96. package/templates/ui/code-block.tsx +36 -0
  97. package/templates/ui/collapsible.tsx +48 -0
  98. package/templates/ui/combobox.tsx +295 -0
  99. package/templates/ui/command.tsx +148 -0
  100. package/templates/ui/context-menu.tsx +212 -0
  101. package/templates/ui/dialog.tsx +138 -0
  102. package/templates/ui/drawer.tsx +134 -0
  103. package/templates/ui/dropdown-menu.tsx +254 -0
  104. package/templates/ui/form.tsx +122 -0
  105. package/templates/ui/hover-card.tsx +44 -0
  106. package/templates/ui/input-group.tsx +148 -0
  107. package/templates/ui/input-otp.tsx +153 -0
  108. package/templates/ui/input.tsx +20 -0
  109. package/templates/ui/label.tsx +17 -0
  110. package/templates/ui/layout.tsx +252 -0
  111. package/templates/ui/list-item.tsx +50 -0
  112. package/templates/ui/menubar.tsx +225 -0
  113. package/templates/ui/navigation-menu.tsx +117 -0
  114. package/templates/ui/pagination.tsx +110 -0
  115. package/templates/ui/popover.tsx +77 -0
  116. package/templates/ui/progress.tsx +37 -0
  117. package/templates/ui/radio-group.tsx +41 -0
  118. package/templates/ui/receipt-card.tsx +70 -0
  119. package/templates/ui/resizable.tsx +140 -0
  120. package/templates/ui/scroll-area.tsx +64 -0
  121. package/templates/ui/select.tsx +186 -0
  122. package/templates/ui/separator.tsx +21 -0
  123. package/templates/ui/sheet.tsx +134 -0
  124. package/templates/ui/sidebar.tsx +222 -0
  125. package/templates/ui/skeleton.tsx +35 -0
  126. package/templates/ui/slider.tsx +60 -0
  127. package/templates/ui/switch.tsx +33 -0
  128. package/templates/ui/table.tsx +114 -0
  129. package/templates/ui/tabs.tsx +79 -0
  130. package/templates/ui/textarea.tsx +18 -0
  131. package/templates/ui/toast.tsx +139 -0
  132. package/templates/ui/toggle-group.tsx +68 -0
  133. package/templates/ui/toggle.tsx +47 -0
  134. package/templates/ui/tooltip.tsx +53 -0
  135. package/templates/ui/tree-view.tsx +76 -0
@@ -0,0 +1,254 @@
1
+ 'use client'
2
+
3
+ import { Menu as MenuPrimitive } from '@base-ui/react/menu'
4
+ import { CheckIcon, ChevronRightIcon } from 'lucide-react'
5
+ import type * as React from 'react'
6
+ import { cn } from '@/lib/utils'
7
+
8
+ function DropdownMenu({ ...props }: MenuPrimitive.Root.Props) {
9
+ return <MenuPrimitive.Root data-slot="dropdown-menu" {...props} />
10
+ }
11
+
12
+ function DropdownMenuPortal({ ...props }: MenuPrimitive.Portal.Props) {
13
+ return <MenuPrimitive.Portal data-slot="dropdown-menu-portal" {...props} />
14
+ }
15
+
16
+ function DropdownMenuTrigger({ ...props }: MenuPrimitive.Trigger.Props) {
17
+ return <MenuPrimitive.Trigger data-slot="dropdown-menu-trigger" {...props} />
18
+ }
19
+
20
+ function DropdownMenuContent({
21
+ align = 'start',
22
+ alignOffset = 0,
23
+ side = 'bottom',
24
+ sideOffset = 6,
25
+ className,
26
+ ...props
27
+ }: MenuPrimitive.Popup.Props &
28
+ Pick<MenuPrimitive.Positioner.Props, 'align' | 'alignOffset' | 'side' | 'sideOffset'>) {
29
+ return (
30
+ <MenuPrimitive.Portal>
31
+ <MenuPrimitive.Positioner
32
+ className="isolate z-50 outline-none"
33
+ align={align}
34
+ alignOffset={alignOffset}
35
+ side={side}
36
+ sideOffset={sideOffset}
37
+ >
38
+ <MenuPrimitive.Popup
39
+ data-slot="dropdown-menu-content"
40
+ className={cn(
41
+ 'z-50 max-h-(--available-height) w-(--anchor-width) min-w-32 origin-(--transform-origin) overflow-x-hidden overflow-y-auto rounded-[var(--radius)] border-[length:var(--border-width)] border-foreground bg-popover text-popover-foreground shadow-none duration-100 outline-none data-[side=bottom]:slide-in-from-top-2 data-[side=inline-end]:slide-in-from-left-2 data-[side=inline-start]:slide-in-from-right-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:overflow-hidden data-closed:fade-out-0 data-closed:zoom-out-95',
42
+ className,
43
+ )}
44
+ {...props}
45
+ />
46
+ </MenuPrimitive.Positioner>
47
+ </MenuPrimitive.Portal>
48
+ )
49
+ }
50
+
51
+ function DropdownMenuGroup({ ...props }: MenuPrimitive.Group.Props) {
52
+ return <MenuPrimitive.Group data-slot="dropdown-menu-group" {...props} />
53
+ }
54
+
55
+ function DropdownMenuLabel({
56
+ className,
57
+ inset,
58
+ ...props
59
+ }: MenuPrimitive.GroupLabel.Props & {
60
+ inset?: boolean
61
+ }) {
62
+ return (
63
+ <MenuPrimitive.GroupLabel
64
+ data-slot="dropdown-menu-label"
65
+ data-inset={inset}
66
+ className={cn('px-2 py-2 text-xs text-muted-foreground data-inset:pl-7', className)}
67
+ {...props}
68
+ />
69
+ )
70
+ }
71
+
72
+ function DropdownMenuItem({
73
+ className,
74
+ inset,
75
+ variant = 'default',
76
+ ...props
77
+ }: MenuPrimitive.Item.Props & {
78
+ inset?: boolean
79
+ variant?: 'default' | 'destructive'
80
+ }) {
81
+ return (
82
+ <MenuPrimitive.Item
83
+ data-slot="dropdown-menu-item"
84
+ data-inset={inset}
85
+ data-variant={variant}
86
+ className={cn(
87
+ "group/dropdown-menu-item relative flex cursor-default items-center gap-2 rounded-[var(--radius)] px-2 py-2 text-xs outline-hidden select-none focus:bg-accent focus:text-accent-foreground not-data-[variant=destructive]: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 data-[variant=destructive]:*:[svg]:text-destructive",
88
+ className,
89
+ )}
90
+ {...props}
91
+ />
92
+ )
93
+ }
94
+
95
+ function DropdownMenuSub({ ...props }: MenuPrimitive.SubmenuRoot.Props) {
96
+ return <MenuPrimitive.SubmenuRoot data-slot="dropdown-menu-sub" {...props} />
97
+ }
98
+
99
+ function DropdownMenuSubTrigger({
100
+ className,
101
+ inset,
102
+ children,
103
+ ...props
104
+ }: MenuPrimitive.SubmenuTrigger.Props & {
105
+ inset?: boolean
106
+ }) {
107
+ return (
108
+ <MenuPrimitive.SubmenuTrigger
109
+ data-slot="dropdown-menu-sub-trigger"
110
+ data-inset={inset}
111
+ className={cn(
112
+ "flex cursor-default items-center gap-2 rounded-[var(--radius)] px-2 py-2 text-xs outline-hidden select-none focus:bg-accent focus:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground data-inset:pl-7 data-popup-open:bg-accent data-popup-open:text-accent-foreground data-open:bg-accent data-open:text-accent-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
113
+ className,
114
+ )}
115
+ {...props}
116
+ >
117
+ {children}
118
+ <ChevronRightIcon className="ml-auto" />
119
+ </MenuPrimitive.SubmenuTrigger>
120
+ )
121
+ }
122
+
123
+ function DropdownMenuSubContent({
124
+ align = 'start',
125
+ alignOffset = -3,
126
+ side = 'right',
127
+ sideOffset = 0,
128
+ className,
129
+ ...props
130
+ }: React.ComponentProps<typeof DropdownMenuContent>) {
131
+ return (
132
+ <DropdownMenuContent
133
+ data-slot="dropdown-menu-sub-content"
134
+ className={cn(
135
+ 'w-auto min-w-[96px] rounded-[var(--radius)] border-[length:var(--border-width)] bg-popover text-popover-foreground 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',
136
+ className,
137
+ )}
138
+ align={align}
139
+ alignOffset={alignOffset}
140
+ side={side}
141
+ sideOffset={sideOffset}
142
+ {...props}
143
+ />
144
+ )
145
+ }
146
+
147
+ function DropdownMenuCheckboxItem({
148
+ className,
149
+ children,
150
+ checked,
151
+ inset,
152
+ ...props
153
+ }: MenuPrimitive.CheckboxItem.Props & {
154
+ inset?: boolean
155
+ }) {
156
+ return (
157
+ <MenuPrimitive.CheckboxItem
158
+ data-slot="dropdown-menu-checkbox-item"
159
+ data-inset={inset}
160
+ className={cn(
161
+ "relative flex cursor-default items-center gap-2 rounded-[var(--radius)] py-2 pr-8 pl-2 text-xs outline-hidden select-none focus:bg-accent focus:text-accent-foreground 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",
162
+ className,
163
+ )}
164
+ checked={checked}
165
+ {...props}
166
+ >
167
+ <span
168
+ className="pointer-events-none absolute right-2 flex items-center justify-center"
169
+ data-slot="dropdown-menu-checkbox-item-indicator"
170
+ >
171
+ <MenuPrimitive.CheckboxItemIndicator>
172
+ <CheckIcon />
173
+ </MenuPrimitive.CheckboxItemIndicator>
174
+ </span>
175
+ {children}
176
+ </MenuPrimitive.CheckboxItem>
177
+ )
178
+ }
179
+
180
+ function DropdownMenuRadioGroup({ ...props }: MenuPrimitive.RadioGroup.Props) {
181
+ return <MenuPrimitive.RadioGroup data-slot="dropdown-menu-radio-group" {...props} />
182
+ }
183
+
184
+ function DropdownMenuRadioItem({
185
+ className,
186
+ children,
187
+ inset,
188
+ ...props
189
+ }: MenuPrimitive.RadioItem.Props & {
190
+ inset?: boolean
191
+ }) {
192
+ return (
193
+ <MenuPrimitive.RadioItem
194
+ data-slot="dropdown-menu-radio-item"
195
+ data-inset={inset}
196
+ className={cn(
197
+ "relative flex cursor-default items-center gap-2 rounded-[var(--radius)] py-2 pr-8 pl-2 text-xs outline-hidden select-none focus:bg-accent focus:text-accent-foreground 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",
198
+ className,
199
+ )}
200
+ {...props}
201
+ >
202
+ <span
203
+ className="pointer-events-none absolute right-2 flex items-center justify-center"
204
+ data-slot="dropdown-menu-radio-item-indicator"
205
+ >
206
+ <MenuPrimitive.RadioItemIndicator>
207
+ <CheckIcon />
208
+ </MenuPrimitive.RadioItemIndicator>
209
+ </span>
210
+ {children}
211
+ </MenuPrimitive.RadioItem>
212
+ )
213
+ }
214
+
215
+ function DropdownMenuSeparator({ className, ...props }: MenuPrimitive.Separator.Props) {
216
+ return (
217
+ <MenuPrimitive.Separator
218
+ data-slot="dropdown-menu-separator"
219
+ className={cn('-mx-1 h-[length:var(--border-width)] bg-border', className)}
220
+ {...props}
221
+ />
222
+ )
223
+ }
224
+
225
+ function DropdownMenuShortcut({ className, ...props }: React.ComponentProps<'span'>) {
226
+ return (
227
+ <span
228
+ data-slot="dropdown-menu-shortcut"
229
+ className={cn(
230
+ 'ml-auto text-xs tracking-widest text-muted-foreground group-focus/dropdown-menu-item:text-accent-foreground',
231
+ className,
232
+ )}
233
+ {...props}
234
+ />
235
+ )
236
+ }
237
+
238
+ export {
239
+ DropdownMenu,
240
+ DropdownMenuPortal,
241
+ DropdownMenuTrigger,
242
+ DropdownMenuContent,
243
+ DropdownMenuGroup,
244
+ DropdownMenuLabel,
245
+ DropdownMenuItem,
246
+ DropdownMenuCheckboxItem,
247
+ DropdownMenuRadioGroup,
248
+ DropdownMenuRadioItem,
249
+ DropdownMenuSeparator,
250
+ DropdownMenuShortcut,
251
+ DropdownMenuSub,
252
+ DropdownMenuSubTrigger,
253
+ DropdownMenuSubContent,
254
+ }
@@ -0,0 +1,122 @@
1
+ 'use client'
2
+
3
+ import * as React from 'react'
4
+ import { cn } from '@/lib/utils'
5
+
6
+ // Lightweight form context — no react-hook-form dependency.
7
+ // Pass your own errors/touched state in or wire to your form library.
8
+
9
+ interface FormFieldContextValue {
10
+ id: string
11
+ name: string
12
+ error?: string
13
+ required?: boolean
14
+ }
15
+
16
+ const FormFieldContext = React.createContext<FormFieldContextValue>({
17
+ id: '',
18
+ name: '',
19
+ })
20
+
21
+ function useFormField() {
22
+ return React.useContext(FormFieldContext)
23
+ }
24
+
25
+ function Form({ className, ...props }: React.ComponentProps<'form'>) {
26
+ return (
27
+ <form
28
+ data-slot="form"
29
+ className={cn('space-y-4', className)}
30
+ {...props}
31
+ />
32
+ )
33
+ }
34
+
35
+ interface FormFieldProps {
36
+ name: string
37
+ error?: string
38
+ required?: boolean
39
+ children: React.ReactNode
40
+ className?: string
41
+ }
42
+
43
+ function FormField({ name, error, required, children, className }: FormFieldProps) {
44
+ const id = React.useId()
45
+ return (
46
+ <FormFieldContext.Provider value={{ id, name, error, required }}>
47
+ <div data-slot="form-field" className={cn('flex flex-col gap-1', className)}>
48
+ {children}
49
+ </div>
50
+ </FormFieldContext.Provider>
51
+ )
52
+ }
53
+
54
+ function FormLabel({ className, children, ...props }: React.ComponentProps<'label'>) {
55
+ const { id, required, error } = useFormField()
56
+ return (
57
+ <label
58
+ data-slot="form-label"
59
+ htmlFor={id}
60
+ className={cn(
61
+ 'text-xs font-medium uppercase tracking-wider',
62
+ error && 'text-destructive',
63
+ className,
64
+ )}
65
+ {...props}
66
+ >
67
+ {children}
68
+ {required && <span className="ml-0.5 text-destructive">*</span>}
69
+ </label>
70
+ )
71
+ }
72
+
73
+ function FormControl({ className, ...props }: React.ComponentProps<'div'>) {
74
+ const { id, error } = useFormField()
75
+ return (
76
+ <div
77
+ data-slot="form-control"
78
+ id={id}
79
+ aria-invalid={!!error}
80
+ className={cn('', className)}
81
+ {...props}
82
+ />
83
+ )
84
+ }
85
+
86
+ function FormDescription({ className, ...props }: React.ComponentProps<'p'>) {
87
+ return (
88
+ <p
89
+ data-slot="form-description"
90
+ className={cn('text-xs/relaxed text-muted-foreground', className)}
91
+ {...props}
92
+ />
93
+ )
94
+ }
95
+
96
+ function FormMessage({ className, children, ...props }: React.ComponentProps<'p'>) {
97
+ const { error } = useFormField()
98
+ const message = children ?? error
99
+ if (!message) return null
100
+ return (
101
+ <p
102
+ data-slot="form-message"
103
+ role="alert"
104
+ className={cn('text-xs text-destructive', className)}
105
+ {...props}
106
+ >
107
+ {message}
108
+ </p>
109
+ )
110
+ }
111
+
112
+ function FormItem({ className, ...props }: React.ComponentProps<'div'>) {
113
+ return (
114
+ <div
115
+ data-slot="form-item"
116
+ className={cn('flex flex-col gap-1', className)}
117
+ {...props}
118
+ />
119
+ )
120
+ }
121
+
122
+ export { Form, FormField, FormLabel, FormControl, FormDescription, FormMessage, FormItem, useFormField }
@@ -0,0 +1,44 @@
1
+ 'use client'
2
+
3
+ import { PreviewCard as PreviewCardPrimitive } from '@base-ui/react/preview-card'
4
+ import type * as React from 'react'
5
+ import { cn } from '@/lib/utils'
6
+
7
+ function HoverCard({ ...props }: PreviewCardPrimitive.Root.Props) {
8
+ return <PreviewCardPrimitive.Root data-slot="hover-card" {...props} />
9
+ }
10
+
11
+ function HoverCardTrigger({ ...props }: PreviewCardPrimitive.Trigger.Props) {
12
+ return <PreviewCardPrimitive.Trigger data-slot="hover-card-trigger" {...props} />
13
+ }
14
+
15
+ function HoverCardContent({
16
+ className,
17
+ side = 'bottom',
18
+ sideOffset = 6,
19
+ align = 'center',
20
+ ...props
21
+ }: PreviewCardPrimitive.Popup.Props &
22
+ Pick<PreviewCardPrimitive.Positioner.Props, 'side' | 'sideOffset' | 'align'>) {
23
+ return (
24
+ <PreviewCardPrimitive.Portal>
25
+ <PreviewCardPrimitive.Positioner
26
+ side={side}
27
+ sideOffset={sideOffset}
28
+ align={align}
29
+ className="isolate z-50"
30
+ >
31
+ <PreviewCardPrimitive.Popup
32
+ data-slot="hover-card-content"
33
+ className={cn(
34
+ 'z-50 w-64 origin-(--transform-origin) rounded-[var(--radius)] border-[length:var(--border-width)] border-dashed border-foreground bg-popover p-3 text-xs/relaxed text-popover-foreground shadow-none 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',
35
+ className,
36
+ )}
37
+ {...props}
38
+ />
39
+ </PreviewCardPrimitive.Positioner>
40
+ </PreviewCardPrimitive.Portal>
41
+ )
42
+ }
43
+
44
+ export { HoverCard, HoverCardTrigger, HoverCardContent }
@@ -0,0 +1,148 @@
1
+ 'use client'
2
+
3
+ import * as React from 'react'
4
+ import { cva, type VariantProps } from 'class-variance-authority'
5
+
6
+ import { cn } from '@/lib/utils'
7
+ import { Button } from '@/components/ui/button'
8
+ import { Input } from '@/components/ui/input'
9
+ import { Textarea } from '@/components/ui/textarea'
10
+
11
+ function InputGroup({ className, ...props }: React.ComponentProps<'div'>) {
12
+ return (
13
+ <div
14
+ data-slot="input-group"
15
+ role="group"
16
+ className={cn(
17
+ 'group/input-group relative flex h-8 w-full min-w-0 items-center rounded-[var(--radius)] border-[length:var(--border-width)] border-input outline-none in-data-[slot=combobox-content]:focus-within:border-inherit in-data-[slot=combobox-content]:focus-within:ring-0 has-disabled:bg-input/50 has-disabled:opacity-50 has-[[data-slot=input-group-control]:focus-visible]:border-ring has-[[data-slot=input-group-control]:focus-visible]:ring-1 has-[[data-slot=input-group-control]:focus-visible]:ring-ring/50 has-[[data-slot][aria-invalid=true]]:border-destructive has-[[data-slot][aria-invalid=true]]:ring-1 has-[[data-slot][aria-invalid=true]]:ring-destructive/20 has-[>[data-align=block-end]]:h-auto has-[>[data-align=block-end]]:flex-col has-[>[data-align=block-start]]:h-auto has-[>[data-align=block-start]]:flex-col has-[>textarea]:h-auto dark:bg-input/30 dark:has-disabled:bg-input/80 dark:has-[[data-slot][aria-invalid=true]]:ring-destructive/40 has-[>[data-align=block-end]]:[&>input]:pt-3 has-[>[data-align=block-start]]:[&>input]:pb-3 has-[>[data-align=inline-end]]:[&>input]:pr-1.5 has-[>[data-align=inline-start]]:[&>input]:pl-1.5',
18
+ className,
19
+ )}
20
+ {...props}
21
+ />
22
+ )
23
+ }
24
+
25
+ const inputGroupAddonVariants = cva(
26
+ "flex h-auto cursor-text items-center justify-center gap-2 py-1.5 text-xs font-medium text-muted-foreground select-none group-data-[disabled=true]/input-group:opacity-50 [&>kbd]:rounded-[var(--radius)] [&>svg:not([class*='size-'])]:size-4",
27
+ {
28
+ variants: {
29
+ align: {
30
+ 'inline-start':
31
+ 'order-first pl-2 has-[>button]:ml-[-0.3rem] has-[>kbd]:ml-[-0.15rem]',
32
+ 'inline-end':
33
+ 'order-last pr-2 has-[>button]:mr-[-0.3rem] has-[>kbd]:mr-[-0.15rem]',
34
+ 'block-start':
35
+ 'order-first w-full justify-start px-2.5 pt-2 group-has-[>input]/input-group:pt-2 [.border-b]:pb-2',
36
+ 'block-end':
37
+ 'order-last w-full justify-start px-2.5 pb-2 group-has-[>input]/input-group:pb-2 [.border-t]:pt-2',
38
+ },
39
+ },
40
+ defaultVariants: {
41
+ align: 'inline-start',
42
+ },
43
+ },
44
+ )
45
+
46
+ function InputGroupAddon({
47
+ className,
48
+ align = 'inline-start',
49
+ ...props
50
+ }: React.ComponentProps<'div'> & VariantProps<typeof inputGroupAddonVariants>) {
51
+ return (
52
+ <div
53
+ role="group"
54
+ data-slot="input-group-addon"
55
+ data-align={align}
56
+ className={cn(inputGroupAddonVariants({ align }), className)}
57
+ onClick={(e) => {
58
+ if ((e.target as HTMLElement).closest('button')) {
59
+ return
60
+ }
61
+ e.currentTarget.parentElement?.querySelector('input')?.focus()
62
+ }}
63
+ {...props}
64
+ />
65
+ )
66
+ }
67
+
68
+ const inputGroupButtonVariants = cva('flex items-center gap-2 text-xs shadow-none', {
69
+ variants: {
70
+ size: {
71
+ xs: "h-6 gap-1 rounded-[var(--radius)] px-1.5 [&>svg:not([class*='size-'])]:size-3.5",
72
+ sm: '',
73
+ 'icon-xs': 'size-6 rounded-[var(--radius)] p-0 has-[>svg]:p-0',
74
+ 'icon-sm': 'size-8 p-0 has-[>svg]:p-0',
75
+ },
76
+ },
77
+ defaultVariants: {
78
+ size: 'xs',
79
+ },
80
+ })
81
+
82
+ function InputGroupButton({
83
+ className,
84
+ type = 'button',
85
+ variant = 'ghost',
86
+ size = 'xs',
87
+ ...props
88
+ }: Omit<React.ComponentProps<typeof Button>, 'size' | 'type'> &
89
+ VariantProps<typeof inputGroupButtonVariants> & {
90
+ type?: 'button' | 'submit' | 'reset'
91
+ }) {
92
+ return (
93
+ <Button
94
+ type={type}
95
+ data-size={size}
96
+ variant={variant}
97
+ className={cn(inputGroupButtonVariants({ size }), className)}
98
+ {...props}
99
+ />
100
+ )
101
+ }
102
+
103
+ function InputGroupText({ className, ...props }: React.ComponentProps<'span'>) {
104
+ return (
105
+ <span
106
+ className={cn(
107
+ "flex items-center gap-2 text-xs text-muted-foreground [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4",
108
+ className,
109
+ )}
110
+ {...props}
111
+ />
112
+ )
113
+ }
114
+
115
+ function InputGroupInput({ className, ...props }: React.ComponentProps<'input'>) {
116
+ return (
117
+ <Input
118
+ data-slot="input-group-control"
119
+ className={cn(
120
+ 'flex-1 rounded-[var(--radius)] border-0 bg-transparent shadow-none ring-0 focus-visible:ring-0 disabled:bg-transparent aria-invalid:ring-0 dark:bg-transparent dark:disabled:bg-transparent',
121
+ className,
122
+ )}
123
+ {...props}
124
+ />
125
+ )
126
+ }
127
+
128
+ function InputGroupTextarea({ className, ...props }: React.ComponentProps<'textarea'>) {
129
+ return (
130
+ <Textarea
131
+ data-slot="input-group-control"
132
+ className={cn(
133
+ 'flex-1 resize-none rounded-[var(--radius)] border-0 bg-transparent py-2 shadow-none ring-0 focus-visible:ring-0 disabled:bg-transparent aria-invalid:ring-0 dark:bg-transparent dark:disabled:bg-transparent',
134
+ className,
135
+ )}
136
+ {...props}
137
+ />
138
+ )
139
+ }
140
+
141
+ export {
142
+ InputGroup,
143
+ InputGroupAddon,
144
+ InputGroupButton,
145
+ InputGroupText,
146
+ InputGroupInput,
147
+ InputGroupTextarea,
148
+ }