ivt
Version:
Ivt Components Library
1 lines • 12.6 kB
Source Map (JSON)
{"version":3,"file":"combobox-D9iqP8Dp.mjs","sources":["../../src/components/ui/combobox/combobox.tsx"],"sourcesContent":["\"use client\";\n\nimport { Check, ChevronsUpDownIcon, XIcon } from \"lucide-react\";\nimport * as React from \"react\";\n\nimport { Button } from \"@/components/ui/button\";\nimport {\n\tCommand,\n\tCommandEmpty,\n\tCommandGroup,\n\tCommandInput,\n\tCommandItem,\n\tCommandList,\n} from \"@/components/ui/command\";\nimport { Popover, PopoverContent, PopoverTrigger } from \"@/components/ui/popover\";\nimport { cn } from \"@/lib/utils\";\nimport { removeSpecialCharacters } from \"@/utils/string\";\nimport { Separator } from \"../separator\";\nimport { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from \"../tooltip\";\n\ninterface ComboboxItem {\n\tvalue: string;\n\tlabel: string;\n}\n\ninterface ComboboxProps {\n\t/**\n\t * A lista de itens a serem exibidos no combobox.\n\t * Cada item deve ter 'value' e 'label'.\n\t */\n\titems: ComboboxItem[];\n\t/**\n\t * O valor atualmente selecionado no combobox.\n\t */\n\tvalue: string;\n\t/**\n\t * Função de callback para quando um item é selecionado.\n\t * Recebe o novo valor selecionado.\n\t */\n\tonValueChange: (newValue: string) => void;\n\t/**\n\t * Placeholder para o botão do combobox quando nenhum item está selecionado.\n\t * @default \"Select item...\"\n\t */\n\tplaceholder?: string;\n\t/**\n\t * Placeholder para o campo de busca dentro do combobox.\n\t * @default \"Search item...\"\n\t */\n\tsearchPlaceholder?: string;\n\t/**\n\t * Mensagem exibida quando nenhum item é encontrado na busca.\n\t * @default \"No item found.\"\n\t */\n\temptyMessage?: string;\n\t/**\n\t * Largura do combobox (e do popover).\n\t * @default \"w-[200px]\"\n\t */\n\twidthClassName?: string;\n\t/**\n\t * Classes CSS adicionais para o combobox principal.\n\t */\n\tclassName?: string;\n\t/**\n\t * Título do grupo de comandos.\n\t */\n\tgroupHeading?: string;\n\t/**\n * \n\tAtiva ou desativa a normalização da busca, removendo acentos e caracteres especiais.\n\tQuando **true** (padrão), a busca ignora diferenças de acentuação — útil para buscas mais flexíveis.\n\tQuando **false**, a busca será literal, sensível a acentuação.\n */\n\tnormalizeSearch?: boolean;\n\t/**\n\t * Desabilita a interação com o combobox.\n\t */\n\tdisabled?: boolean;\n\n\t/**\n\t * ID do combobox.\n\t */\n\tid?: string;\n\n\t/**\n\t * Se o combobox deve ter um botão de limpar seleção.\n\t */\n\tclearable?: boolean;\n}\n\nexport function Combobox({\n\tid,\n\titems,\n\tvalue,\n\tonValueChange,\n\tplaceholder = \"Selecione um item...\",\n\tsearchPlaceholder = \"Busque um item...\",\n\temptyMessage = \"Nenhum item encontrado.\",\n\twidthClassName = \"w-fit\",\n\tclassName,\n\tgroupHeading,\n\tnormalizeSearch = true,\n\tdisabled = false,\n\tclearable = true,\n}: ComboboxProps) {\n\tconst [open, setOpen] = React.useState(false);\n\tconst [search, setSearch] = React.useState(\"\");\n\n\tconst normalize = React.useCallback(\n\t\t(text: string) =>\n\t\t\tnormalizeSearch ? removeSpecialCharacters(text).toLowerCase() : text.toLowerCase(),\n\t\t[normalizeSearch],\n\t);\n\n\tconst filteredItems = React.useMemo(() => {\n\t\tconst normalizedSearch = normalize(search);\n\n\t\tconst result = items.filter((item) => {\n\t\t\tconst normalizedLabel = normalize(item.label);\n\t\t\tconst normalizedValue = normalize(item.value);\n\n\t\t\treturn (\n\t\t\t\tnormalizedLabel.includes(normalizedSearch) || normalizedValue.includes(normalizedSearch)\n\t\t\t);\n\t\t});\n\n\t\treturn result;\n\t}, [items, search, normalize]);\n\n\tconst selectedItem = React.useMemo(() => {\n\t\treturn items.find((item) => item.value === value);\n\t}, [items, value]);\n\n\tconst hasValue = !!selectedItem;\n\n\tconst handleSelect = (currentValue: string) => {\n\t\tonValueChange(currentValue === value ? \"\" : currentValue);\n\t\tsetTimeout(() => setSearch(\"\"), 150);\n\t\tsetOpen(false);\n\t};\n\n\tconst handleClear = (e: React.MouseEvent) => {\n\t\te.stopPropagation();\n\t\tonValueChange(\"\");\n\t};\n\n\treturn (\n\t\t<Popover open={open} onOpenChange={setOpen}>\n\t\t\t<PopoverTrigger asChild>\n\t\t\t\t<Button\n\t\t\t\t\tid={id}\n\t\t\t\t\tvariant=\"outline\"\n\t\t\t\t\trole=\"combobox\"\n\t\t\t\t\taria-expanded={open}\n\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\twidthClassName,\n\t\t\t\t\t\t\"flex h-auto min-h-9 items-center justify-between rounded-md border bg-inherit px-3 py-2 hover:bg-inherit [&_svg]:pointer-events-auto gap-0\",\n\t\t\t\t\t\tplaceholder && !value && \"text-muted-foreground hover:text-muted-foreground\",\n\t\t\t\t\t\tclassName,\n\t\t\t\t\t)}\n\t\t\t\t>\n\t\t\t\t\t<span\n\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\"min-w-0 flex-1 truncate text-muted-foreground text-left\",\n\t\t\t\t\t\t\thasValue && \"text-foreground\",\n\t\t\t\t\t\t)}\n\t\t\t\t\t>\n\t\t\t\t\t\t{hasValue ? selectedItem.label : placeholder}\n\t\t\t\t\t</span>\n\n\t\t\t\t\t<div className=\"flex items-center justify-between\">\n\t\t\t\t\t\t{clearable && hasValue && !disabled ? (\n\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t<TooltipProvider>\n\t\t\t\t\t\t\t\t\t<Tooltip>\n\t\t\t\t\t\t\t\t\t\t<TooltipTrigger asChild>\n\t\t\t\t\t\t\t\t\t\t\t{/* biome-ignore lint/a11y/useKeyWithClickEvents: clear button action */}\n\t\t\t\t\t\t\t\t\t\t\t{/* biome-ignore lint/a11y/noStaticElementInteractions: clear button action */}\n\t\t\t\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\t\t\t\tonClick={(event) => {\n\t\t\t\t\t\t\t\t\t\t\t\t\tevent.stopPropagation();\n\t\t\t\t\t\t\t\t\t\t\t\t\thandleClear(event);\n\t\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t\t\tclassName=\"cursor-pointer\"\n\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t<XIcon className=\"text-muted-foreground h-4\" />\n\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t</TooltipTrigger>\n\t\t\t\t\t\t\t\t\t\t<TooltipContent>\n\t\t\t\t\t\t\t\t\t\t\t<span className=\"text-xs\">Limpar seleção</span>\n\t\t\t\t\t\t\t\t\t\t</TooltipContent>\n\t\t\t\t\t\t\t\t\t</Tooltip>\n\t\t\t\t\t\t\t\t</TooltipProvider>\n\t\t\t\t\t\t\t\t<Separator orientation=\"vertical\" className=\"flex h-full min-h-6\" />\n\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t) : null}\n\t\t\t\t\t</div>\n\t\t\t\t\t<ChevronsUpDownIcon className=\"text-muted-foreground h-4 cursor-pointer\" />\n\t\t\t\t</Button>\n\t\t\t</PopoverTrigger>\n\n\t\t\t<PopoverContent\n\t\t\t\talign=\"start\"\n\t\t\t\tclassName={cn(widthClassName, \"p-0\")}\n\t\t\t\tonOpenAutoFocus={(e) => e.preventDefault()}\n\t\t\t>\n\t\t\t\t<Command shouldFilter={false}>\n\t\t\t\t\t<CommandInput placeholder={searchPlaceholder} value={search} onValueChange={setSearch} />\n\t\t\t\t\t<CommandList>\n\t\t\t\t\t\t{filteredItems.length === 0 ? (\n\t\t\t\t\t\t\t<CommandEmpty>{emptyMessage}</CommandEmpty>\n\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t<CommandGroup heading={groupHeading}>\n\t\t\t\t\t\t\t\t{filteredItems.map((item) => (\n\t\t\t\t\t\t\t\t\t<CommandItem\n\t\t\t\t\t\t\t\t\t\tkey={item.value}\n\t\t\t\t\t\t\t\t\t\tvalue={item.value}\n\t\t\t\t\t\t\t\t\t\tonSelect={() => handleSelect(item.value)}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t{item.label}\n\t\t\t\t\t\t\t\t\t\t<Check\n\t\t\t\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t\t\t\t\"ml-auto h-4 w-4\",\n\t\t\t\t\t\t\t\t\t\t\t\tvalue === item.value ? \"opacity-100\" : \"opacity-0\",\n\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t</CommandItem>\n\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t</CommandGroup>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</CommandList>\n\t\t\t\t</Command>\n\t\t\t</PopoverContent>\n\t\t</Popover>\n\t);\n}\n"],"names":["Combobox","id","items","value","onValueChange","placeholder","searchPlaceholder","emptyMessage","widthClassName","className","groupHeading","normalizeSearch","disabled","clearable","open","setOpen","React","useState","search","setSearch","normalize","useCallback","text","removeSpecialCharacters","toLowerCase","filteredItems","useMemo","normalizedSearch","result","filter","item","normalizedLabel","label","normalizedValue","includes","selectedItem","find","hasValue","handleSelect","currentValue","setTimeout","handleClear","e","stopPropagation","Popover","onOpenChange","PopoverTrigger","asChild","Button","variant","role","aria-expanded","cn","span","div","TooltipProvider","Tooltip","TooltipTrigger","onClick","event","XIcon","TooltipContent","Separator","orientation","ChevronsUpDownIcon","PopoverContent","align","onOpenAutoFocus","preventDefault","Command","shouldFilter","CommandInput","CommandList","length","CommandEmpty","CommandGroup","heading","map","CommandItem","key","onSelect","Check"],"mappings":"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"}