{"name":"base","type":"registry:block","dependencies":["@radix-ui/react-alert-dialog","@radix-ui/react-checkbox","@radix-ui/react-dialog","@radix-ui/react-label","@radix-ui/react-popover","@radix-ui/react-select","@radix-ui/react-slot","cmdk","next-themes","sonner","zod"],"devDependencies":["knip"],"registryDependencies":["alert-dialog","button","checkbox","command","dialog","input","label","popover","select","sonner","textarea"],"files":[{"path":"./components/ui/base/action-button.tsx","content":"'use client'\n\nimport { cn } from '@/lib/utils'\nimport { type VariantProps } from 'class-variance-authority'\nimport { Loader2 } from 'lucide-react'\nimport { useFormStatus } from 'react-dom'\nimport { Button, buttonVariants } from '../button'\n\nexport type ActionButtonProps = React.ComponentProps<'button'> &\n\tVariantProps<typeof buttonVariants> & {\n\t\tasChild?: boolean\n\t\tloading?: boolean\n\t}\n\nexport function ActionButton({ children, className, disabled, loading, ...props }: ActionButtonProps) {\n\tconst { pending } = useFormStatus()\n\n\treturn (\n\t\t<Button className={cn('relative', className)} disabled={disabled || loading || pending} type='submit' {...props}>\n\t\t\t<span className={cn('flex items-center gap-2', { invisible: loading || pending })}>{children}</span>\n\t\t\t{(loading || pending) && (\n\t\t\t\t<div className='absolute m-auto'>\n\t\t\t\t\t<Loader2 className='size-5 animate-spin' />\n\t\t\t\t</div>\n\t\t\t)}\n\t\t</Button>\n\t)\n}\n","type":"registry:ui"},{"path":"./components/ui/base/confirm.tsx","content":"'use client'\n\nimport { ReactNode, useActionState, useEffect, useState } from 'react'\nimport {\n\tAlertDialog,\n\tAlertDialogCancel,\n\tAlertDialogContent,\n\tAlertDialogDescription,\n\tAlertDialogFooter,\n\tAlertDialogHeader,\n\tAlertDialogTitle,\n\tAlertDialogTrigger,\n} from '../alert-dialog'\nimport { ActionButton } from './action-button'\n\ninterface ConfirmProps {\n\taction: () => Promise<unknown>\n\tchildren: ReactNode\n\tdesc: string\n\ttitle: string\n\tvariant?: 'default' | 'destructive'\n}\n\nexport function Confirm({ action: _action, children, desc, title, variant = 'default' }: ConfirmProps) {\n\tconst [open, setOpen] = useState(false)\n\tconst [state, action] = useActionState(_action, null)\n\n\tuseEffect(() => {\n\t\tif (state === undefined) setOpen(false)\n\t}, [state])\n\n\treturn (\n\t\t<AlertDialog open={open} onOpenChange={setOpen}>\n\t\t\t<AlertDialogTrigger asChild>{children}</AlertDialogTrigger>\n\t\t\t<AlertDialogContent>\n\t\t\t\t<AlertDialogHeader>\n\t\t\t\t\t<AlertDialogTitle>{title}</AlertDialogTitle>\n\t\t\t\t\t<AlertDialogDescription>{desc}</AlertDialogDescription>\n\t\t\t\t</AlertDialogHeader>\n\t\t\t\t<AlertDialogFooter>\n\t\t\t\t\t<AlertDialogCancel className='cursor-pointer'>Cancel</AlertDialogCancel>\n\t\t\t\t\t<form action={action}>\n\t\t\t\t\t\t<ActionButton variant={variant}>Continue</ActionButton>\n\t\t\t\t\t</form>\n\t\t\t\t</AlertDialogFooter>\n\t\t\t</AlertDialogContent>\n\t\t</AlertDialog>\n\t)\n}\n\nexport function ConfirmDelete({ action, children }: { action: () => Promise<unknown>; children: ReactNode }) {\n\treturn (\n\t\t<Confirm\n\t\t\taction={action}\n\t\t\ttitle='Are you absolutely sure?'\n\t\t\tdesc='This action cannot be undone. This will permanently delete this item and remove the data from our servers.'\n\t\t\tvariant='destructive'>\n\t\t\t{children}\n\t\t</Confirm>\n\t)\n}\n","type":"registry:ui"},{"path":"./components/ui/base/form-checkbox.tsx","content":"import { cn } from '@/lib/utils'\nimport { ZodSchema } from 'zod'\nimport { FormBaseProps } from '.'\nimport { Checkbox } from '../checkbox'\nimport { FormState } from '../form/utils'\nimport { Label } from '../label'\nimport { FormError } from './form-error'\n\nexport function FormCheckbox<T extends FormState<ZodSchema>>({\n\tclassName,\n\tlabel,\n\tstate,\n\t// TODO: Check on value change for this component\n\t...props\n}: FormBaseProps<React.ComponentProps<typeof Checkbox>, T>) {\n\treturn (\n\t\t<div className={cn('grid gap-2', className)}>\n\t\t\t<div className='flex items-center gap-2'>\n\t\t\t\t<Checkbox id={props.name} name={props.name} {...props} />\n\t\t\t\t<Label htmlFor={props.name}>{label}</Label>\n\t\t\t</div>\n\t\t\t<FormError value={props.name ? state?.fieldErrors[props.name] : undefined} />\n\t\t</div>\n\t)\n}\n","type":"registry:ui"},{"path":"./components/ui/base/form-error.tsx","content":"'use client'\n\nimport { cn } from '@/lib/utils'\nimport { useEffect } from 'react'\nimport { useFormStatus } from 'react-dom'\nimport { toast } from 'sonner'\n\nexport function FormError({ hidden = false, value }: { hidden?: boolean; value: string[] | undefined }) {\n\tconst { pending } = useFormStatus()\n\n\tuseEffect(() => {\n\t\tif (!hidden) return\n\t\tif (value?.length && value.length > 0) toast.error(`FATAL: ${value[0]}`)\n\t}, [hidden, value])\n\n\tif (hidden || !value || !value.length) return null\n\treturn <div className={cn('text-sm text-destructive', { hidden: pending })}>{value[0]}</div>\n}\n","type":"registry:ui"},{"path":"./components/ui/base/form-input.tsx","content":"import { cn } from '@/lib/utils'\nimport { ZodSchema } from 'zod'\nimport { FormBaseProps } from '.'\nimport { FormState } from '../form/utils'\nimport { Input } from '../input'\nimport { Label } from '../label'\nimport { FormError } from './form-error'\n\nexport function FormInput<T extends FormState<ZodSchema>>({\n\tclassName,\n\tdesc,\n\tlabel,\n\tstate,\n\tonValueChange,\n\t...props\n}: FormBaseProps<React.ComponentProps<'input'>, T>) {\n\treturn (\n\t\t<div className={cn('grid gap-2 h-fit', className)}>\n\t\t\t{label && <Label htmlFor={props.name}>{label}</Label>}\n\t\t\t{desc && <p className='text-xs text-muted-foreground -mt-1'>{desc}</p>}\n\t\t\t<Input id={props.name} name={props.name} onChange={(e) => onValueChange?.(e.target.value)} {...props} />\n\t\t\t<FormError value={props.name ? state?.fieldErrors[props.name] : undefined} />\n\t\t</div>\n\t)\n}\n","type":"registry:ui"},{"path":"./components/ui/base/form-select.tsx","content":"'use client'\n\nimport { cn } from '@/lib/utils'\nimport { SelectProps } from '@radix-ui/react-select'\nimport { useMemo } from 'react'\nimport { ZodSchema } from 'zod'\nimport { FormBaseProps } from '.'\nimport { FormState } from '../form/utils'\nimport { Label } from '../label'\nimport { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '../select'\nimport { FormError } from './form-error'\n\nexport function FormSelect<T extends FormState<ZodSchema>>({\n\tclassName,\n\tdesc,\n\tlabel,\n\toptions: _options,\n\tstate,\n\t...props\n}: FormBaseProps<SelectProps, T> & { options: ({ label: React.ReactNode; value: string } | string)[] }) {\n\tconst options = useMemo(() => _options.map((o) => (typeof o === 'string' ? o : { label: o.label, value: o.value })), [_options])\n\n\treturn (\n\t\t<div className={cn('grid gap-2 h-fit', className)}>\n\t\t\t{label && <Label htmlFor={props.name}>{label}</Label>}\n\t\t\t{desc && <p className='text-xs text-muted-foreground -mt-1'>{desc}</p>}\n\t\t\t<Select {...props}>\n\t\t\t\t<SelectTrigger className='w-full'>\n\t\t\t\t\t<SelectValue placeholder='Select an option' />\n\t\t\t\t</SelectTrigger>\n\t\t\t\t<SelectContent>\n\t\t\t\t\t{options.map((option) => (\n\t\t\t\t\t\t<SelectItem\n\t\t\t\t\t\t\tkey={typeof option === 'string' ? option : option.value}\n\t\t\t\t\t\t\tvalue={typeof option === 'string' ? option : option.value}>\n\t\t\t\t\t\t\t{typeof option === 'string' ? option : option.label}\n\t\t\t\t\t\t</SelectItem>\n\t\t\t\t\t))}\n\t\t\t\t</SelectContent>\n\t\t\t</Select>\n\t\t\t<FormError value={props.name ? state?.fieldErrors[props.name] : undefined} />\n\t\t</div>\n\t)\n}\n","type":"registry:ui"},{"path":"./components/ui/base/form-textarea.tsx","content":"import { cn } from '@/lib/utils'\nimport { ZodSchema } from 'zod'\nimport { FormBaseProps } from '.'\nimport { FormState } from '../form/utils'\nimport { Label } from '../label'\nimport { Textarea } from '../textarea'\nimport { FormError } from './form-error'\n\nexport function FormTextarea<T extends FormState<ZodSchema>>({\n\tclassName,\n\tdesc,\n\tlabel,\n\tstate,\n\tonValueChange,\n\t...props\n}: FormBaseProps<React.ComponentProps<'textarea'>, T>) {\n\treturn (\n\t\t<div className={cn('grid gap-2 h-fit', className)}>\n\t\t\t{label && <Label htmlFor={props.name}>{label}</Label>}\n\t\t\t{desc && <p className='text-xs text-muted-foreground -mt-1'>{desc}</p>}\n\t\t\t<Textarea id={props.name} name={props.name} onChange={(e) => onValueChange?.(e.target.value)} {...props} />\n\t\t\t<FormError value={props.name ? state?.fieldErrors[props.name] : undefined} />\n\t\t</div>\n\t)\n}\n","type":"registry:ui"},{"path":"./components/ui/base/global-toaster.tsx","content":"'use client'\n\nimport { usePathname, useRouter, useSearchParams } from 'next/navigation'\nimport { useEffect } from 'react'\nimport { toast } from 'sonner'\nimport { Toaster } from '../sonner'\n\nexport function GlobalToaster() {\n\tconst pathname = usePathname()\n\tconst router = useRouter()\n\tconst searchParams = useSearchParams()\n\n\tuseEffect(() => {\n\t\tconst message = searchParams.get('message')\n\t\tconst error = searchParams.get('error')\n\t\tconst success = searchParams.get('success')\n\n\t\tif (!message && !error && !success) return\n\t\tconst toastType = message ? toast : success ? toast.success : toast.error\n\t\ttoastType(message ? message : success ? success : error)\n\n\t\tconst newSearchParams = new URLSearchParams(searchParams.toString())\n\t\tconst paramsToRemove = ['message', 'error', 'success']\n\t\tparamsToRemove.forEach((param) => newSearchParams.delete(param))\n\t\tconst redirectPath = `${pathname}?${newSearchParams.toString()}`\n\t\trouter.replace(redirectPath, { scroll: false })\n\t}, [pathname, router, searchParams])\n\n\treturn <Toaster position='top-center' richColors />\n}\n","type":"registry:ui"},{"path":"./components/ui/base/index.ts","content":"import { ZodSchema } from 'zod'\nimport { FormState } from '../form/utils'\n\nexport type FormBaseProps<T, U extends FormState<ZodSchema>> = Omit<T, 'className' | 'id' | 'name' | 'onChange'> & {\n\tclassName?: string\n\tdesc?: string\n\tlabel?: string\n\tname?: U['fields']\n\tstate?: U\n\tonValueChange?: (value: string) => void\n}\n","type":"registry:ui"},{"path":"./components/ui/form/index.ts","content":"import z from 'zod'\n\nexport function formDataToObject(formData: FormData): Record<string, any> {\n\tconst obj: Record<string, any> = {}\n\n\tfor (const [key, value] of Array.from(formData.entries())) {\n\t\tconst keys = key.split('.')\n\t\tlet current = obj\n\n\t\tfor (let i = 0; i < keys.length - 1; i++) {\n\t\t\tconst k = keys[i]\n\t\t\tif (!(k in current)) current[k] = {}\n\t\t\tcurrent = current[k]\n\t\t}\n\n\t\tcurrent[keys[keys.length - 1]] = value\n\t}\n\n\treturn obj\n}\n\nexport function zodErrorToFieldErrors(error: z.ZodError): Record<string, string[]> {\n\tconst fieldErrors: Record<string, string[]> = {}\n\n\tfor (const issue of error.issues) {\n\t\tconst fieldName = issue.path.join('.')\n\t\tfieldErrors[fieldName] ??= []\n\t\tfieldErrors[fieldName].push(issue.message)\n\t}\n\n\treturn fieldErrors\n}\n","type":"registry:ui"},{"path":"./components/ui/form/use-form.tsx","content":"'use client'\n\nimport { useActionState, useCallback, useEffect, useState } from 'react'\nimport { toast } from 'sonner'\nimport z, { ZodSchema } from 'zod'\nimport { formDataToObject, zodErrorToFieldErrors } from '.'\nimport { Action, FormOptions, StateFromAction } from './utils'\n\nexport function useForm<A extends Action<ZodSchema, any>>(action: A, opts: FormOptions<A>) {\n\tconst [serverState, serverAction] = useActionState(action as any, undefined)\n\tconst [state, setState] = useState<StateFromAction<A>>()\n\n\tuseEffect(() => {\n\t\tsetState(serverState as any)\n\t}, [serverState])\n\n\tuseEffect(() => {\n\t\tif (state?.successMessage) toast.success(state.successMessage)\n\t}, [state])\n\n\tuseEffect(() => {\n\t\tif (state?.success) {\n\t\t\topts.setOpen?.(false)\n\t\t\topts.onSuccess?.(state)\n\t\t}\n\t}, [opts, state])\n\n\tconst handleSubmit = useCallback(\n\t\t(formData: FormData) => {\n\t\t\tif (opts.schema) {\n\t\t\t\tconst parsed = (opts.schema as z.ZodSchema).safeParse(formDataToObject(formData))\n\t\t\t\tif (!parsed.success) {\n\t\t\t\t\tconst fieldErrors = zodErrorToFieldErrors(parsed.error)\n\t\t\t\t\treturn setState({ success: false, successMessage: null, fieldErrors, step: state?.step ?? null } as any)\n\t\t\t\t}\n\t\t\t}\n\t\t\tif ('defaults' in opts && opts.defaults) formData.set('__defaults', JSON.stringify(opts.defaults))\n\t\t\t;(serverAction as any)(formData)\n\t\t},\n\t\t[opts, serverAction, state?.step],\n\t)\n\n\treturn [state, handleSubmit] as const\n}\n","type":"registry:ui"},{"path":"./components/ui/form/utils.ts","content":"import z, { ZodSchema } from 'zod'\nimport { formDataToObject, zodErrorToFieldErrors } from '.'\n\ntype DotPrefix<T extends string, P extends string> = `${P}.${T}`\ntype DotPaths<T> = {\n\t[K in keyof T & string]: NonNullable<T[K]> extends Record<string, any> ? DotPrefix<DotPaths<NonNullable<T[K]>>, K> | K : K\n}[keyof T & string]\n\ntype FieldErrors<T> = {\n\t[K in DotPaths<T>]?: string[]\n}\n\nexport type FormState<T extends ZodSchema> = {\n\tsuccess: boolean\n\tsuccessMessage: string | null\n\tglobalError: string | null\n\tfieldErrors: FieldErrors<z.infer<T>>\n\tfields: DotPaths<z.infer<T>>\n\tstep: number | null\n}\n\ntype AnyZod = z.ZodTypeAny\nexport type Action<T extends AnyZod, U extends AnyZod | null> = ((_: any, formData: FormData) => Promise<FormState<T>>) & {\n\t__types?: { schema: T; defaultSchema: U; fields: DotPaths<z.infer<T>>[] } // phantom only\n}\n\ntype HandlerNoDefaults<T extends AnyZod> = (data: z.infer<T>, ctx: { formData: FormData }) => Promise<Partial<FormState<T>> | void>\ntype HandlerWithDefaults<T extends AnyZod, U extends AnyZod> = (\n\tdata: z.infer<T>,\n\tctx: { defaults: z.infer<U>; formData: FormData },\n) => Promise<Partial<FormState<T>> | void>\n\ntype ActionSchema<A> = A extends { __types?: { schema: infer S } } ? S : never\ntype ActionDefaultSchema<A> = A extends { __types?: { defaultSchema: infer D } } ? D : undefined\n\nexport type FormOptions<A extends Action<ZodSchema, any>> =\n\tActionDefaultSchema<A> extends z.ZodTypeAny\n\t\t? {\n\t\t\t\tschema?: ActionSchema<A>\n\t\t\t\tdefaults: z.infer<NonNullable<ActionDefaultSchema<A>>>\n\t\t\t\tsetOpen?: (open: boolean) => void\n\t\t\t\tonSuccess?: (state: StateFromAction<A>) => void\n\t\t\t}\n\t\t: {\n\t\t\t\tschema?: ActionSchema<A>\n\t\t\t\tdefaults?: undefined\n\t\t\t\tsetOpen?: (open: boolean) => void\n\t\t\t\tonSuccess?: (state: StateFromAction<A>) => void\n\t\t\t}\n\nexport type StateFromAction<A extends (...args: any) => Promise<any>> = Awaited<ReturnType<A>>\n\nfunction makeAction<T extends AnyZod, U extends AnyZod | null>(\n\tschema: T,\n\tdefaultSchema: U,\n\tprotectedAction: boolean,\n\tonValid: (data: unknown, ctx: any) => Promise<Partial<FormState<any>> | void>,\n): Action<T, U> {\n\tconst fn = (async (_: unknown, formData: FormData) => {\n\t\tconst parsed = schema.safeParse(formDataToObject(formData))\n\t\tif (!parsed.success) {\n\t\t\tconst fieldErrors = zodErrorToFieldErrors(parsed.error)\n\t\t\treturn { success: false, successMessage: null, globalError: null, fieldErrors, step: null }\n\t\t}\n\n\t\tlet defaults\n\t\tif (defaultSchema) {\n\t\t\tconst raw = formData.get('__defaults')\n\t\t\tdefaults = defaultSchema.safeParse(raw ? JSON.parse(String(raw)) : undefined)\n\t\t\tif (!defaults.success)\n\t\t\t\treturn { success: false, successMessage: null, globalError: 'Error with default values', fieldErrors: {}, step: null }\n\t\t}\n\n\t\tconst result = await onValid(parsed.data, { defaults: defaults?.data, formData })\n\n\t\tif (result?.globalError || result?.fieldErrors)\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\tsuccessMessage: null,\n\t\t\t\tglobalError: result.globalError,\n\t\t\t\tfieldErrors: result.fieldErrors,\n\t\t\t\tstep: result.step,\n\t\t\t}\n\t\treturn {\n\t\t\tsuccess: true,\n\t\t\tsuccessMessage: result?.successMessage ?? null,\n\t\t\tglobalError: null,\n\t\t\tfieldErrors: {},\n\t\t\tstep: result?.step ?? null,\n\t\t}\n\t}) as Action<T, U>\n\n\treturn fn\n}\n\nexport function _action<T extends AnyZod>(schema: T): { handle: (onValid: HandlerNoDefaults<T>) => Action<T, null> }\nexport function _action<T extends AnyZod, U extends AnyZod>(\n\tschema: T,\n\tdefaultSchema: U,\n): { handle: (onValid: HandlerWithDefaults<T, U>) => Action<T, U> }\nexport function _action<T extends AnyZod, U extends AnyZod | undefined>(schema: T, defaultSchema?: U) {\n\treturn {\n\t\thandle(onValid: any) {\n\t\t\treturn makeAction(schema, (defaultSchema ?? null) as U extends AnyZod ? U : null, true, onValid)\n\t\t},\n\t}\n}\n","type":"registry:ui"},{"path":"./components/ui/input-group.tsx","content":"\"use client\"\n\nimport * as React from \"react\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"@/lib/utils\"\nimport { Button } from \"@/components/ui/button\"\nimport { Input } from \"@/components/ui/input\"\nimport { Textarea } from \"@/components/ui/textarea\"\n\nfunction InputGroup({ className, ...props }: React.ComponentProps<\"div\">) {\n  return (\n    <div\n      data-slot=\"input-group\"\n      role=\"group\"\n      className={cn(\n        \"group/input-group relative flex h-8 w-full min-w-0 items-center rounded-lg border border-input transition-colors 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-3 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-3 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\",\n        className\n      )}\n      {...props}\n    />\n  )\n}\n\nconst inputGroupAddonVariants = cva(\n  \"flex h-auto cursor-text items-center justify-center gap-2 py-1.5 text-sm font-medium text-muted-foreground select-none group-data-[disabled=true]/input-group:opacity-50 [&>kbd]:rounded-[calc(var(--radius)-5px)] [&>svg:not([class*='size-'])]:size-4\",\n  {\n    variants: {\n      align: {\n        \"inline-start\":\n          \"order-first pl-2 has-[>button]:ml-[-0.3rem] has-[>kbd]:ml-[-0.15rem]\",\n        \"inline-end\":\n          \"order-last pr-2 has-[>button]:mr-[-0.3rem] has-[>kbd]:mr-[-0.15rem]\",\n        \"block-start\":\n          \"order-first w-full justify-start px-2.5 pt-2 group-has-[>input]/input-group:pt-2 [.border-b]:pb-2\",\n        \"block-end\":\n          \"order-last w-full justify-start px-2.5 pb-2 group-has-[>input]/input-group:pb-2 [.border-t]:pt-2\",\n      },\n    },\n    defaultVariants: {\n      align: \"inline-start\",\n    },\n  }\n)\n\nfunction InputGroupAddon({\n  className,\n  align = \"inline-start\",\n  ...props\n}: React.ComponentProps<\"div\"> & VariantProps<typeof inputGroupAddonVariants>) {\n  return (\n    <div\n      role=\"group\"\n      data-slot=\"input-group-addon\"\n      data-align={align}\n      className={cn(inputGroupAddonVariants({ align }), className)}\n      onClick={(e) => {\n        if ((e.target as HTMLElement).closest(\"button\")) {\n          return\n        }\n        e.currentTarget.parentElement?.querySelector(\"input\")?.focus()\n      }}\n      {...props}\n    />\n  )\n}\n\nconst inputGroupButtonVariants = cva(\n  \"flex items-center gap-2 text-sm shadow-none\",\n  {\n    variants: {\n      size: {\n        xs: \"h-6 gap-1 rounded-[calc(var(--radius)-3px)] px-1.5 [&>svg:not([class*='size-'])]:size-3.5\",\n        sm: \"\",\n        \"icon-xs\":\n          \"size-6 rounded-[calc(var(--radius)-3px)] p-0 has-[>svg]:p-0\",\n        \"icon-sm\": \"size-8 p-0 has-[>svg]:p-0\",\n      },\n    },\n    defaultVariants: {\n      size: \"xs\",\n    },\n  }\n)\n\nfunction InputGroupButton({\n  className,\n  type = \"button\",\n  variant = \"ghost\",\n  size = \"xs\",\n  ...props\n}: Omit<React.ComponentProps<typeof Button>, \"size\"> &\n  VariantProps<typeof inputGroupButtonVariants>) {\n  return (\n    <Button\n      type={type}\n      data-size={size}\n      variant={variant}\n      className={cn(inputGroupButtonVariants({ size }), className)}\n      {...props}\n    />\n  )\n}\n\nfunction InputGroupText({ className, ...props }: React.ComponentProps<\"span\">) {\n  return (\n    <span\n      className={cn(\n        \"flex items-center gap-2 text-sm text-muted-foreground [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4\",\n        className\n      )}\n      {...props}\n    />\n  )\n}\n\nfunction InputGroupInput({\n  className,\n  ...props\n}: React.ComponentProps<\"input\">) {\n  return (\n    <Input\n      data-slot=\"input-group-control\"\n      className={cn(\n        \"flex-1 rounded-none 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\",\n        className\n      )}\n      {...props}\n    />\n  )\n}\n\nfunction InputGroupTextarea({\n  className,\n  ...props\n}: React.ComponentProps<\"textarea\">) {\n  return (\n    <Textarea\n      data-slot=\"input-group-control\"\n      className={cn(\n        \"flex-1 resize-none rounded-none 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\",\n        className\n      )}\n      {...props}\n    />\n  )\n}\n\nexport {\n  InputGroup,\n  InputGroupAddon,\n  InputGroupButton,\n  InputGroupText,\n  InputGroupInput,\n  InputGroupTextarea,\n}\n","type":"registry:ui"},{"path":"./knip.json","content":"{\n\t\"$schema\": \"https://unpkg.com/knip@5/schema.json\"\n}\n","type":"registry:example","target":"~/knip.json"}],"tailwind":{},"cssVars":{},"meta":{}}