| 1 | "use client"; |
| 2 | |
| 3 | import * as React from |
| 4 | import { cva, type |
| 5 | import { cn } |
| 6 | |
| 7 | import { Button } |
| 8 | import { Input } |
| 9 | import { Textarea } |
| 10 | |
| 11 | function InputGroup({ className |
| 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-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", |
| 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-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", |
| 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. |
| 51 | return ( |
| 52 | <div |
| 53 | role="group" |
| 54 | data-slot="input-group-addon" |
| 55 | data-align={align} |
| 56 | className={cn(inputGroupAddonVariants |
| 57 | onClick={(e) |
| 58 | if ((e.target |
| 59 | return; |
| 60 | } |
| 61 | e.currentTarget.parentElement |
| 62 | }} |
| 63 | {...props} |
| 64 | /> |
| 65 | ); |
| 66 | } |
| 67 | |
| 68 | const inputGroupButtonVariants = cva |
| 69 | "flex items-center gap-2 text-sm shadow-none", |
| 70 | { |
| 71 | variants: { |
| 72 | size: { |
| 73 | xs: "h-6 gap-1 rounded-[calc(var(--radius)-3px)] px-1.5 [&>svg:not([class*='size-'])]:size-3.5", |
| 74 | sm: "", |
| 75 | "icon-xs": |
| 76 | "size-6 rounded-[calc(var(--radius)-3px)] p-0 has-[>svg]:p-0", |
| 77 | "icon-sm": "size-8 p-0 has-[>svg]:p-0", |
| 78 | }, |
| 79 | }, |
| 80 | defaultVariants: { |
| 81 | size: "xs", |
| 82 | }, |
| 83 | }, |
| 84 | ); |
| 85 | |
| 86 | function InputGroupButton({ |
| 87 | className, |
| 88 | type = "button" |
| 89 | variant = "ghost" |
| 90 | size = "xs" |
| 91 | ...props |
| 92 | }: Omit< |
| 93 | VariantProps<typeof |
| 94 | return ( |
| 95 | <Button |
| 96 | type={type} |
| 97 | data-size={size} |
| 98 | variant={variant} |
| 99 | className={cn(inputGroupButtonVariants |
| 100 | {...props} |
| 101 | /> |
| 102 | ); |
| 103 | } |
| 104 | |
| 105 | function InputGroupText({ className |
| 106 | return ( |
| 107 | <span |
| 108 | className={cn( |
| 109 | "flex items-center gap-2 text-sm text-muted-foreground [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4", |
| 110 | className, |
| 111 | )} |
| 112 | {...props} |
| 113 | /> |
| 114 | ); |
| 115 | } |
| 116 | |
| 117 | function InputGroupInput({ |
| 118 | className, |
| 119 | ...props |
| 120 | }: React. |
| 121 | return ( |
| 122 | <Input |
| 123 | data-slot="input-group-control" |
| 124 | className={cn( |
| 125 | "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", |
| 126 | className, |
| 127 | )} |
| 128 | {...props} |
| 129 | /> |
| 130 | ); |
| 131 | } |
| 132 | |
| 133 | function InputGroupTextarea({ |
| 134 | className, |
| 135 | ...props |
| 136 | }: React. |
| 137 | return ( |
| 138 | <Textarea |
| 139 | data-slot="input-group-control" |
| 140 | className={cn( |
| 141 | "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", |
| 142 | className, |
| 143 | )} |
| 144 | {...props} |
| 145 | /> |
| 146 | ); |
| 147 | } |
| 148 | |
| 149 | export { |
| 150 | InputGroup, |
| 151 | InputGroupAddon, |
| 152 | InputGroupButton, |
| 153 | InputGroupText, |
| 154 | InputGroupInput, |
| 155 | InputGroupTextarea, |
| 156 | }; |