import * as React from "react"; import { Combobox as ComboboxPrimitive } from "@base-ui/react"; import { cva } from "class-variance-authority"; import { outlineControlSurfaceClassName } from "../../lib/control-outline"; import { cn } from "../../lib/utils"; import { Button } from "../primitives"; import { PrimitiveArrowIcon } from "../primitives"; import { InputGroup, InputGroupAddon, InputGroupInput, } from "../primitives"; import { ScrollFade } from "../primitives"; import { XIcon, CheckIcon, MagnifyingGlassIcon } from "@phosphor-icons/react"; const Combobox = ComboboxPrimitive.Root; type ComboboxFieldSize = "sm" | "default" | "lg" | "xl"; const comboboxHoverBorderClassName = "[&:not(:focus-within):hover]:!border-[color:color-mix(in_oklab,var(--border)_20%,transparent)]"; const comboboxButtonNoHoverBackgroundClassName = "hover:bg-transparent active:bg-transparent data-pressed:bg-transparent"; const comboboxActiveInputBorderClassName = [ comboboxHoverBorderClassName, "has-[[data-slot=input-group-button][aria-expanded=true]]:border-[color:color-mix(in_oklab,var(--border)_30%,transparent)]", "has-[[data-slot=input-group-button][data-state=open]]:border-[color:color-mix(in_oklab,var(--border)_30%,transparent)]", "has-[[data-slot=input-group-button][data-popup-open]]:border-[color:color-mix(in_oklab,var(--border)_30%,transparent)]", "has-[[data-slot=input-group-button][data-open]]:border-[color:color-mix(in_oklab,var(--border)_30%,transparent)]", "has-[[data-slot=combobox-trigger][aria-expanded=true]]:border-[color:color-mix(in_oklab,var(--border)_30%,transparent)]", "has-[[data-slot=combobox-trigger][data-state=open]]:border-[color:color-mix(in_oklab,var(--border)_30%,transparent)]", "has-[[data-slot=combobox-trigger][data-popup-open]]:border-[color:color-mix(in_oklab,var(--border)_30%,transparent)]", "has-[[data-slot=combobox-trigger][data-open]]:border-[color:color-mix(in_oklab,var(--border)_30%,transparent)]", ].join(" "); const comboboxPopupSurfaceBaseClassName = "floating-popup-surface group/combobox-content relative overflow-hidden rounded-lg border p-1 popup-text-xs-plus text-[color:var(--popover-foreground)] [&>[data-slot=combobox-search]]:-mx-1 [&>[data-slot=combobox-search]]:-mt-1 [&>[data-slot=combobox-search]]:mb-0 [&>[data-slot=combobox-search]]:border-b [&>[data-slot=combobox-search]]:border-[color:color-mix(in_oklab,var(--border)_5%,transparent)] [&>[data-slot=combobox-search]]:pr-1 [&>[data-slot=combobox-search]]:pl-0 [&>[data-slot=combobox-search]]:pt-1 [&>[data-slot=combobox-search]]:pb-1 [&>[data-slot=combobox-search]>[data-slot=input-group]]:m-0 [&>[data-slot=combobox-search]>[data-slot=input-group]]:rounded-none [&>[data-slot=combobox-search]>[data-slot=input-group]]:border-none [&>[data-slot=combobox-search]>[data-slot=input-group]]:bg-transparent [&>[data-slot=combobox-search]>[data-slot=input-group]]:shadow-none"; const comboboxPopupSurfaceClassName = cn( comboboxPopupSurfaceBaseClassName, "max-h-(--available-height) w-[min(var(--anchor-width),calc(var(--spacing)*64))] max-w-[min(var(--available-width),calc(var(--spacing)*64))] min-w-[min(calc(var(--anchor-width)+calc(var(--spacing)*7)),calc(var(--spacing)*64))] origin-(--transform-origin) duration-100 data-[chips=true]:min-w-[min(var(--anchor-width),calc(var(--spacing)*64))] 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:fade-out-0 data-closed:zoom-out-95", ); const ComboboxChipsSizeContext = React.createContext("default"); const useComboboxChipsSize = (): ComboboxFieldSize => React.useContext(ComboboxChipsSizeContext); const getComboboxInputButtonSize = ( size: ComboboxFieldSize, ): "icon-xxs" | "icon-xs" => size === "sm" || size === "default" ? "icon-xxs" : "icon-xs"; const getComboboxPopupTypographyClassName = ( size: ComboboxFieldSize, ): string => size === "default" ? "text-[13px] leading-[1.125rem]" : size === "lg" || size === "xl" ? "text-sm/relaxed" : "text-xs/relaxed"; const ComboboxValue = (props: ComboboxPrimitive.Value.Props) => ( ); function ComboboxTrigger({ className, children, size = "default", ...props }: ComboboxPrimitive.Trigger.Props & { size?: ComboboxFieldSize; }) { const isLargeFieldSize = size === "lg" || size === "xl"; return ( {children} ); } function ComboboxClear({ className, size = "default", ...props }: ComboboxPrimitive.Clear.Props & { size?: ComboboxFieldSize; }) { const buttonSize = getComboboxInputButtonSize(size); return ( } className={cn(className)} {...props} > ); } function ComboboxInput({ className, children, disabled = false, size = "default", showTrigger = true, showClear = false, ...props }: Omit & { size?: ComboboxFieldSize; showTrigger?: boolean; showClear?: boolean; }) { const shouldRenderTrigger = showTrigger && !showClear; const isPopupSearch = !showTrigger && !showClear; const isLargeFieldSize = size === "lg" || size === "xl"; const buttonSize = getComboboxInputButtonSize(size); const typographyClassName = getComboboxPopupTypographyClassName(size); const inputGroup = ( {isPopupSearch && ( )} } {...props} /> {shouldRenderTrigger && (