@openui-xio/ui 0.0.2

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 (59) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/LICENSE +661 -0
  3. package/README.md +9 -0
  4. package/components.json +20 -0
  5. package/package.json +74 -0
  6. package/postcss.config.mjs +6 -0
  7. package/src/components/.gitkeep +0 -0
  8. package/src/components/accordion.tsx +66 -0
  9. package/src/components/alert-dialog.tsx +157 -0
  10. package/src/components/alert.tsx +66 -0
  11. package/src/components/aspect-ratio.tsx +11 -0
  12. package/src/components/avatar.tsx +53 -0
  13. package/src/components/badge.tsx +46 -0
  14. package/src/components/breadcrumb.tsx +109 -0
  15. package/src/components/button.tsx +46 -0
  16. package/src/components/calendar.tsx +85 -0
  17. package/src/components/card.tsx +92 -0
  18. package/src/components/carousel.tsx +241 -0
  19. package/src/components/chart.tsx +353 -0
  20. package/src/components/checkbox.tsx +32 -0
  21. package/src/components/collapsible.tsx +33 -0
  22. package/src/components/command.tsx +177 -0
  23. package/src/components/context-menu.tsx +252 -0
  24. package/src/components/dialog.tsx +135 -0
  25. package/src/components/drawer.tsx +132 -0
  26. package/src/components/dropdown-menu.tsx +257 -0
  27. package/src/components/form.tsx +168 -0
  28. package/src/components/hover-card.tsx +44 -0
  29. package/src/components/input-otp.tsx +77 -0
  30. package/src/components/input.tsx +21 -0
  31. package/src/components/label.tsx +24 -0
  32. package/src/components/menubar.tsx +276 -0
  33. package/src/components/navigation-menu.tsx +168 -0
  34. package/src/components/pagination.tsx +126 -0
  35. package/src/components/popover.tsx +48 -0
  36. package/src/components/progress.tsx +31 -0
  37. package/src/components/radio-group.tsx +45 -0
  38. package/src/components/resizable.tsx +56 -0
  39. package/src/components/scroll-area.tsx +58 -0
  40. package/src/components/select.tsx +185 -0
  41. package/src/components/separator.tsx +28 -0
  42. package/src/components/sheet.tsx +139 -0
  43. package/src/components/sidebar.tsx +726 -0
  44. package/src/components/skeleton.tsx +13 -0
  45. package/src/components/slider.tsx +63 -0
  46. package/src/components/sonner.tsx +25 -0
  47. package/src/components/switch.tsx +31 -0
  48. package/src/components/table.tsx +116 -0
  49. package/src/components/tabs.tsx +66 -0
  50. package/src/components/textarea.tsx +18 -0
  51. package/src/components/toggle-group.tsx +73 -0
  52. package/src/components/toggle.tsx +47 -0
  53. package/src/components/tooltip.tsx +61 -0
  54. package/src/hooks/.gitkeep +0 -0
  55. package/src/hooks/use-mobile.ts +21 -0
  56. package/src/lib/utils.ts +6 -0
  57. package/src/styles/globals.css +161 -0
  58. package/tsconfig.json +11 -0
  59. package/tsconfig.lint.json +8 -0
@@ -0,0 +1,257 @@
1
+ 'use client';
2
+
3
+ import * as React from 'react';
4
+ import * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu';
5
+ import { CheckIcon, ChevronRightIcon, CircleIcon } from 'lucide-react';
6
+
7
+ import { cn } from '@openui-xio/ui/lib/utils';
8
+
9
+ function DropdownMenu({
10
+ ...props
11
+ }: React.ComponentProps<typeof DropdownMenuPrimitive.Root>) {
12
+ return <DropdownMenuPrimitive.Root data-slot="dropdown-menu" {...props} />;
13
+ }
14
+
15
+ function DropdownMenuPortal({
16
+ ...props
17
+ }: React.ComponentProps<typeof DropdownMenuPrimitive.Portal>) {
18
+ return (
19
+ <DropdownMenuPrimitive.Portal data-slot="dropdown-menu-portal" {...props} />
20
+ );
21
+ }
22
+
23
+ function DropdownMenuTrigger({
24
+ ...props
25
+ }: React.ComponentProps<typeof DropdownMenuPrimitive.Trigger>) {
26
+ return (
27
+ <DropdownMenuPrimitive.Trigger
28
+ data-slot="dropdown-menu-trigger"
29
+ {...props}
30
+ />
31
+ );
32
+ }
33
+
34
+ function DropdownMenuContent({
35
+ className,
36
+ sideOffset = 4,
37
+ ...props
38
+ }: React.ComponentProps<typeof DropdownMenuPrimitive.Content>) {
39
+ return (
40
+ <DropdownMenuPrimitive.Portal>
41
+ <DropdownMenuPrimitive.Content
42
+ data-slot="dropdown-menu-content"
43
+ sideOffset={sideOffset}
44
+ className={cn(
45
+ 'data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]: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 z-50 max-h-(--radix-dropdown-menu-content-available-height) min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-y-auto overflow-x-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md data-[state=closed]:animate-out data-[state=open]:animate-in',
46
+ className,
47
+ )}
48
+ {...props}
49
+ />
50
+ </DropdownMenuPrimitive.Portal>
51
+ );
52
+ }
53
+
54
+ function DropdownMenuGroup({
55
+ ...props
56
+ }: React.ComponentProps<typeof DropdownMenuPrimitive.Group>) {
57
+ return (
58
+ <DropdownMenuPrimitive.Group data-slot="dropdown-menu-group" {...props} />
59
+ );
60
+ }
61
+
62
+ function DropdownMenuItem({
63
+ className,
64
+ inset,
65
+ variant = 'default',
66
+ ...props
67
+ }: React.ComponentProps<typeof DropdownMenuPrimitive.Item> & {
68
+ inset?: boolean;
69
+ variant?: 'default' | 'destructive';
70
+ }) {
71
+ return (
72
+ <DropdownMenuPrimitive.Item
73
+ data-slot="dropdown-menu-item"
74
+ data-inset={inset}
75
+ data-variant={variant}
76
+ className={cn(
77
+ 'data-[variant=destructive]:*:[svg]:!text-destructive dark:data-[variant=destructive]:focus:bg-destructive/20"size-"])]:size-4 data-[variant=destructive]:focus:text-destructive"text-"])]:text-muted-foreground relative flex cursor-default select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden [&_svg:not([class*= [&_svg:not([class*= focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[inset]:pl-8 data-[variant=destructive]:text-destructive data-[disabled]:opacity-50 data-[variant=destructive]:focus:bg-destructive/10 [&_svg]:pointer-events-none [&_svg]:shrink-0',
78
+ className,
79
+ )}
80
+ {...props}
81
+ />
82
+ );
83
+ }
84
+
85
+ function DropdownMenuCheckboxItem({
86
+ className,
87
+ children,
88
+ checked,
89
+ ...props
90
+ }: React.ComponentProps<typeof DropdownMenuPrimitive.CheckboxItem>) {
91
+ return (
92
+ <DropdownMenuPrimitive.CheckboxItem
93
+ data-slot="dropdown-menu-checkbox-item"
94
+ className={cn(
95
+ 'data-[disabled]:opacity-50"size-"])]:size-4 relative flex cursor-default select-none items-center gap-2 rounded-sm py-1.5 pr-2 pl-8 text-sm outline-hidden [&_svg:not([class*= focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none [&_svg]:pointer-events-none [&_svg]:shrink-0',
96
+ className,
97
+ )}
98
+ checked={checked}
99
+ {...props}
100
+ >
101
+ <span className="pointer-events-none absolute left-2 flex size-3.5 items-center justify-center">
102
+ <DropdownMenuPrimitive.ItemIndicator>
103
+ <CheckIcon className="size-4" />
104
+ </DropdownMenuPrimitive.ItemIndicator>
105
+ </span>
106
+ {children}
107
+ </DropdownMenuPrimitive.CheckboxItem>
108
+ );
109
+ }
110
+
111
+ function DropdownMenuRadioGroup({
112
+ ...props
113
+ }: React.ComponentProps<typeof DropdownMenuPrimitive.RadioGroup>) {
114
+ return (
115
+ <DropdownMenuPrimitive.RadioGroup
116
+ data-slot="dropdown-menu-radio-group"
117
+ {...props}
118
+ />
119
+ );
120
+ }
121
+
122
+ function DropdownMenuRadioItem({
123
+ className,
124
+ children,
125
+ ...props
126
+ }: React.ComponentProps<typeof DropdownMenuPrimitive.RadioItem>) {
127
+ return (
128
+ <DropdownMenuPrimitive.RadioItem
129
+ data-slot="dropdown-menu-radio-item"
130
+ className={cn(
131
+ 'data-[disabled]:opacity-50"size-"])]:size-4 relative flex cursor-default select-none items-center gap-2 rounded-sm py-1.5 pr-2 pl-8 text-sm outline-hidden [&_svg:not([class*= focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none [&_svg]:pointer-events-none [&_svg]:shrink-0',
132
+ className,
133
+ )}
134
+ {...props}
135
+ >
136
+ <span className="pointer-events-none absolute left-2 flex size-3.5 items-center justify-center">
137
+ <DropdownMenuPrimitive.ItemIndicator>
138
+ <CircleIcon className="size-2 fill-current" />
139
+ </DropdownMenuPrimitive.ItemIndicator>
140
+ </span>
141
+ {children}
142
+ </DropdownMenuPrimitive.RadioItem>
143
+ );
144
+ }
145
+
146
+ function DropdownMenuLabel({
147
+ className,
148
+ inset,
149
+ ...props
150
+ }: React.ComponentProps<typeof DropdownMenuPrimitive.Label> & {
151
+ inset?: boolean;
152
+ }) {
153
+ return (
154
+ <DropdownMenuPrimitive.Label
155
+ data-slot="dropdown-menu-label"
156
+ data-inset={inset}
157
+ className={cn(
158
+ 'px-2 py-1.5 font-medium text-sm data-[inset]:pl-8',
159
+ className,
160
+ )}
161
+ {...props}
162
+ />
163
+ );
164
+ }
165
+
166
+ function DropdownMenuSeparator({
167
+ className,
168
+ ...props
169
+ }: React.ComponentProps<typeof DropdownMenuPrimitive.Separator>) {
170
+ return (
171
+ <DropdownMenuPrimitive.Separator
172
+ data-slot="dropdown-menu-separator"
173
+ className={cn('-mx-1 my-1 h-px bg-border', className)}
174
+ {...props}
175
+ />
176
+ );
177
+ }
178
+
179
+ function DropdownMenuShortcut({
180
+ className,
181
+ ...props
182
+ }: React.ComponentProps<'span'>) {
183
+ return (
184
+ <span
185
+ data-slot="dropdown-menu-shortcut"
186
+ className={cn(
187
+ 'ml-auto text-muted-foreground text-xs tracking-widest',
188
+ className,
189
+ )}
190
+ {...props}
191
+ />
192
+ );
193
+ }
194
+
195
+ function DropdownMenuSub({
196
+ ...props
197
+ }: React.ComponentProps<typeof DropdownMenuPrimitive.Sub>) {
198
+ return <DropdownMenuPrimitive.Sub data-slot="dropdown-menu-sub" {...props} />;
199
+ }
200
+
201
+ function DropdownMenuSubTrigger({
202
+ className,
203
+ inset,
204
+ children,
205
+ ...props
206
+ }: React.ComponentProps<typeof DropdownMenuPrimitive.SubTrigger> & {
207
+ inset?: boolean;
208
+ }) {
209
+ return (
210
+ <DropdownMenuPrimitive.SubTrigger
211
+ data-slot="dropdown-menu-sub-trigger"
212
+ data-inset={inset}
213
+ className={cn(
214
+ 'flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-hidden focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[inset]:pl-8 data-[state=open]:text-accent-foreground',
215
+ className,
216
+ )}
217
+ {...props}
218
+ >
219
+ {children}
220
+ <ChevronRightIcon className="ml-auto size-4" />
221
+ </DropdownMenuPrimitive.SubTrigger>
222
+ );
223
+ }
224
+
225
+ function DropdownMenuSubContent({
226
+ className,
227
+ ...props
228
+ }: React.ComponentProps<typeof DropdownMenuPrimitive.SubContent>) {
229
+ return (
230
+ <DropdownMenuPrimitive.SubContent
231
+ data-slot="dropdown-menu-sub-content"
232
+ className={cn(
233
+ 'data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]: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 z-50 min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-lg data-[state=closed]:animate-out data-[state=open]:animate-in',
234
+ className,
235
+ )}
236
+ {...props}
237
+ />
238
+ );
239
+ }
240
+
241
+ export {
242
+ DropdownMenu,
243
+ DropdownMenuPortal,
244
+ DropdownMenuTrigger,
245
+ DropdownMenuContent,
246
+ DropdownMenuGroup,
247
+ DropdownMenuLabel,
248
+ DropdownMenuItem,
249
+ DropdownMenuCheckboxItem,
250
+ DropdownMenuRadioGroup,
251
+ DropdownMenuRadioItem,
252
+ DropdownMenuSeparator,
253
+ DropdownMenuShortcut,
254
+ DropdownMenuSub,
255
+ DropdownMenuSubTrigger,
256
+ DropdownMenuSubContent,
257
+ };
@@ -0,0 +1,168 @@
1
+ 'use client';
2
+
3
+ import * as React from 'react';
4
+ import type * as LabelPrimitive from '@radix-ui/react-label';
5
+ import { Slot } from '@radix-ui/react-slot';
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 '@openui-xio/ui/lib/utils';
17
+ import { Label } from '@openui-xio/ui/components/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>) {
108
+ const { error, formItemId, formDescriptionId, formMessageId } =
109
+ useFormField();
110
+
111
+ return (
112
+ <Slot
113
+ data-slot="form-control"
114
+ id={formItemId}
115
+ aria-describedby={
116
+ !error
117
+ ? `${formDescriptionId}`
118
+ : `${formDescriptionId} ${formMessageId}`
119
+ }
120
+ aria-invalid={!!error}
121
+ {...props}
122
+ />
123
+ );
124
+ }
125
+
126
+ function FormDescription({ className, ...props }: React.ComponentProps<'p'>) {
127
+ const { formDescriptionId } = useFormField();
128
+
129
+ return (
130
+ <p
131
+ data-slot="form-description"
132
+ id={formDescriptionId}
133
+ className={cn('text-muted-foreground text-sm', className)}
134
+ {...props}
135
+ />
136
+ );
137
+ }
138
+
139
+ function FormMessage({ className, ...props }: React.ComponentProps<'p'>) {
140
+ const { error, formMessageId } = useFormField();
141
+ const body = error ? String(error?.message ?? '') : props.children;
142
+
143
+ if (!body) {
144
+ return null;
145
+ }
146
+
147
+ return (
148
+ <p
149
+ data-slot="form-message"
150
+ id={formMessageId}
151
+ className={cn('text-destructive text-sm', className)}
152
+ {...props}
153
+ >
154
+ {body}
155
+ </p>
156
+ );
157
+ }
158
+
159
+ export {
160
+ useFormField,
161
+ Form,
162
+ FormItem,
163
+ FormLabel,
164
+ FormControl,
165
+ FormDescription,
166
+ FormMessage,
167
+ FormField,
168
+ };
@@ -0,0 +1,44 @@
1
+ 'use client';
2
+
3
+ import * as React from 'react';
4
+ import * as HoverCardPrimitive from '@radix-ui/react-hover-card';
5
+
6
+ import { cn } from '@openui-xio/ui/lib/utils';
7
+
8
+ function HoverCard({
9
+ ...props
10
+ }: React.ComponentProps<typeof HoverCardPrimitive.Root>) {
11
+ return <HoverCardPrimitive.Root data-slot="hover-card" {...props} />;
12
+ }
13
+
14
+ function HoverCardTrigger({
15
+ ...props
16
+ }: React.ComponentProps<typeof HoverCardPrimitive.Trigger>) {
17
+ return (
18
+ <HoverCardPrimitive.Trigger data-slot="hover-card-trigger" {...props} />
19
+ );
20
+ }
21
+
22
+ function HoverCardContent({
23
+ className,
24
+ align = 'center',
25
+ sideOffset = 4,
26
+ ...props
27
+ }: React.ComponentProps<typeof HoverCardPrimitive.Content>) {
28
+ return (
29
+ <HoverCardPrimitive.Portal data-slot="hover-card-portal">
30
+ <HoverCardPrimitive.Content
31
+ data-slot="hover-card-content"
32
+ align={align}
33
+ sideOffset={sideOffset}
34
+ className={cn(
35
+ 'data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]: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 z-50 w-64 origin-(--radix-hover-card-content-transform-origin) rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-hidden data-[state=closed]:animate-out data-[state=open]:animate-in',
36
+ className,
37
+ )}
38
+ {...props}
39
+ />
40
+ </HoverCardPrimitive.Portal>
41
+ );
42
+ }
43
+
44
+ export { HoverCard, HoverCardTrigger, HoverCardContent };
@@ -0,0 +1,77 @@
1
+ 'use client';
2
+
3
+ import * as React from 'react';
4
+ import { OTPInput, OTPInputContext } from 'input-otp';
5
+ import { MinusIcon } from 'lucide-react';
6
+
7
+ import { cn } from '@openui-xio/ui/lib/utils';
8
+
9
+ function InputOTP({
10
+ className,
11
+ containerClassName,
12
+ ...props
13
+ }: React.ComponentProps<typeof OTPInput> & {
14
+ containerClassName?: string;
15
+ }) {
16
+ return (
17
+ <OTPInput
18
+ data-slot="input-otp"
19
+ containerClassName={cn(
20
+ 'flex items-center gap-2 has-disabled:opacity-50',
21
+ containerClassName,
22
+ )}
23
+ className={cn('disabled:cursor-not-allowed', className)}
24
+ {...props}
25
+ />
26
+ );
27
+ }
28
+
29
+ function InputOTPGroup({ className, ...props }: React.ComponentProps<'div'>) {
30
+ return (
31
+ <div
32
+ data-slot="input-otp-group"
33
+ className={cn('flex items-center', className)}
34
+ {...props}
35
+ />
36
+ );
37
+ }
38
+
39
+ function InputOTPSlot({
40
+ index,
41
+ className,
42
+ ...props
43
+ }: React.ComponentProps<'div'> & {
44
+ index: number;
45
+ }) {
46
+ const inputOTPContext = React.useContext(OTPInputContext);
47
+ const { char, hasFakeCaret, isActive } = inputOTPContext?.slots[index] ?? {};
48
+
49
+ return (
50
+ <div
51
+ data-slot="input-otp-slot"
52
+ data-active={isActive}
53
+ className={cn(
54
+ 'relative flex h-9 w-9 items-center justify-center border-input border-y border-r text-sm shadow-xs outline-none transition-all first:rounded-l-md first:border-l last:rounded-r-md aria-invalid:border-destructive data-[active=true]:z-10 data-[active=true]:border-ring data-[active=true]:ring-[3px] data-[active=true]:ring-ring/50 data-[active=true]:aria-invalid:border-destructive data-[active=true]:aria-invalid:ring-destructive/20 dark:bg-input/30 dark:data-[active=true]:aria-invalid:ring-destructive/40',
55
+ className,
56
+ )}
57
+ {...props}
58
+ >
59
+ {char}
60
+ {hasFakeCaret && (
61
+ <div className="pointer-events-none absolute inset-0 flex items-center justify-center">
62
+ <div className="h-4 w-px animate-caret-blink bg-foreground duration-1000" />
63
+ </div>
64
+ )}
65
+ </div>
66
+ );
67
+ }
68
+
69
+ function InputOTPSeparator({ ...props }: React.ComponentProps<'div'>) {
70
+ return (
71
+ <div data-slot="input-otp-separator" role="separator" {...props}>
72
+ <MinusIcon />
73
+ </div>
74
+ );
75
+ }
76
+
77
+ export { InputOTP, InputOTPGroup, InputOTPSlot, InputOTPSeparator };
@@ -0,0 +1,21 @@
1
+ import * as React from 'react';
2
+
3
+ import { cn } from '@openui-xio/ui/lib/utils';
4
+
5
+ function Input({ className, type, ...props }: React.ComponentProps<'input'>) {
6
+ return (
7
+ <input
8
+ type={type}
9
+ data-slot="input"
10
+ className={cn(
11
+ 'flex h-9 w-full min-w-0 rounded-md border border-input bg-transparent px-3 py-1 text-base shadow-xs outline-none transition-[color,box-shadow] selection:bg-primary selection:text-primary-foreground file:inline-flex file:h-7 file:border-0 file:bg-transparent file:font-medium file:text-foreground file:text-sm placeholder:text-muted-foreground disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm dark:bg-input/30',
12
+ 'focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50',
13
+ 'aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40',
14
+ className,
15
+ )}
16
+ {...props}
17
+ />
18
+ );
19
+ }
20
+
21
+ export { Input };
@@ -0,0 +1,24 @@
1
+ 'use client';
2
+
3
+ import * as React from 'react';
4
+ import * as LabelPrimitive from '@radix-ui/react-label';
5
+
6
+ import { cn } from '@openui-xio/ui/lib/utils';
7
+
8
+ function Label({
9
+ className,
10
+ ...props
11
+ }: React.ComponentProps<typeof LabelPrimitive.Root>) {
12
+ return (
13
+ <LabelPrimitive.Root
14
+ data-slot="label"
15
+ className={cn(
16
+ 'flex select-none items-center gap-2 font-medium text-sm leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-50 group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50',
17
+ className,
18
+ )}
19
+ {...props}
20
+ />
21
+ );
22
+ }
23
+
24
+ export { Label };