Something went wrong. Try again.
A lexicon-driven AppView for ATProto.
Something went wrong. Try again.
9.2 kB · 312 lines
TSX
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313"use client"
import * as React from "react"import { Combobox as ComboboxPrimitive } from "@base-ui/react"import { CheckIcon, ChevronDownIcon, XIcon } from "lucide-react"
import { cn } from "@/lib/utils"import { Button } from "@/components/ui/button"import { InputGroup, InputGroupAddon, InputGroupButton, InputGroupInput,} from "@/components/ui/input-group"
const Combobox = ComboboxPrimitive.Root
function ComboboxValue({ ...props }: ComboboxPrimitive.Value.Props) { return <ComboboxPrimitive.Value data-slot="combobox-value" {...props} />}
function ComboboxTrigger({ className, children, ...props}: ComboboxPrimitive.Trigger.Props) { return ( <ComboboxPrimitive.Trigger data-slot="combobox-trigger" className={cn("[&_svg:not([class*='size-'])]:size-4", className)} {...props} > {children} <ChevronDownIcon data-slot="combobox-trigger-icon" className="text-muted-foreground pointer-events-none size-4" /> </ComboboxPrimitive.Trigger> )}
function ComboboxClear({ className, ...props }: ComboboxPrimitive.Clear.Props) { return ( <ComboboxPrimitive.Clear data-slot="combobox-clear" render={<InputGroupButton variant="ghost" size="icon-xs" />} className={cn(className)} {...props} > <XIcon className="pointer-events-none" /> </ComboboxPrimitive.Clear> )}
function ComboboxInput({ className, children, disabled = false, showTrigger = true, showClear = false, ...props}: ComboboxPrimitive.Input.Props & { showTrigger?: boolean showClear?: boolean}) { return ( <InputGroup className={cn("w-auto", className)}> <ComboboxPrimitive.Input render={<InputGroupInput disabled={disabled} />} {...props} /> {(showTrigger || showClear) && ( <InputGroupAddon align="inline-end"> {showTrigger && ( <InputGroupButton size="icon-xs" variant="ghost" asChild data-slot="input-group-button" className="group-has-data-[slot=combobox-clear]/input-group:hidden data-pressed:bg-transparent" disabled={disabled} > <ComboboxTrigger /> </InputGroupButton> )} {showClear && <ComboboxClear disabled={disabled} />} </InputGroupAddon> )} {children} </InputGroup> )}
function ComboboxContent({ className, side = "bottom", sideOffset = 6, align = "start", alignOffset = 0, anchor, ...props}: ComboboxPrimitive.Popup.Props & Pick< ComboboxPrimitive.Positioner.Props, "side" | "align" | "sideOffset" | "alignOffset" | "anchor" >) { const content = ( <ComboboxPrimitive.Positioner side={side} sideOffset={sideOffset} align={align} alignOffset={alignOffset} anchor={anchor} className="pointer-events-auto isolate z-50" > <ComboboxPrimitive.Popup data-slot="combobox-content" data-chips={!!anchor} className={cn( "bg-popover text-popover-foreground data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-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 ring-foreground/10 *:data-[slot=input-group]:bg-input/30 *:data-[slot=input-group]:border-input/30 group/combobox-content relative max-h-96 w-(--anchor-width) max-w-(--available-width) min-w-[calc(var(--anchor-width)+--spacing(7))] origin-(--transform-origin) overflow-hidden rounded-md shadow-md ring-1 duration-100 data-[chips=true]:min-w-(--anchor-width) *:data-[slot=input-group]:m-1 *:data-[slot=input-group]:mb-0 *:data-[slot=input-group]:h-8 *:data-[slot=input-group]:shadow-none", className )} {...props} /> </ComboboxPrimitive.Positioner> )
return <ComboboxPrimitive.Portal>{content}</ComboboxPrimitive.Portal>}
function ComboboxList({ className, ...props }: ComboboxPrimitive.List.Props) { return ( <ComboboxPrimitive.List data-slot="combobox-list" className={cn( "max-h-[min(calc(--spacing(96)---spacing(9)),calc(var(--available-height)---spacing(9)))] scroll-py-1 overflow-y-auto p-1 data-empty:p-0", className )} {...props} /> )}
function ComboboxItem({ className, children, ...props}: ComboboxPrimitive.Item.Props) { return ( <ComboboxPrimitive.Item data-slot="combobox-item" className={cn( "data-highlighted:bg-accent data-highlighted:text-accent-foreground relative flex w-full cursor-default items-center gap-2 rounded-sm py-1.5 pr-8 pl-2 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", className )} {...props} > {children} <ComboboxPrimitive.ItemIndicator data-slot="combobox-item-indicator" render={ <span className="pointer-events-none absolute right-2 flex size-4 items-center justify-center" /> } > <CheckIcon className="pointer-events-none size-4 pointer-coarse:size-5" /> </ComboboxPrimitive.ItemIndicator> </ComboboxPrimitive.Item> )}
function ComboboxGroup({ className, ...props }: ComboboxPrimitive.Group.Props) { return ( <ComboboxPrimitive.Group data-slot="combobox-group" className={cn(className)} {...props} /> )}
function ComboboxLabel({ className, ...props}: ComboboxPrimitive.GroupLabel.Props) { return ( <ComboboxPrimitive.GroupLabel data-slot="combobox-label" className={cn( "text-muted-foreground px-2 py-1.5 text-xs pointer-coarse:px-3 pointer-coarse:py-2 pointer-coarse:text-sm", className )} {...props} /> )}
function ComboboxCollection({ ...props }: ComboboxPrimitive.Collection.Props) { return ( <ComboboxPrimitive.Collection data-slot="combobox-collection" {...props} /> )}
function ComboboxEmpty({ className, ...props }: ComboboxPrimitive.Empty.Props) { return ( <ComboboxPrimitive.Empty data-slot="combobox-empty" className={cn( "text-muted-foreground hidden w-full justify-center py-2 text-center text-sm group-data-empty/combobox-content:flex", className )} {...props} /> )}
function ComboboxSeparator({ className, ...props}: ComboboxPrimitive.Separator.Props) { return ( <ComboboxPrimitive.Separator data-slot="combobox-separator" className={cn("bg-border -mx-1 my-1 h-px", className)} {...props} /> )}
function ComboboxChips({ className, ...props}: React.ComponentPropsWithRef<typeof ComboboxPrimitive.Chips> & ComboboxPrimitive.Chips.Props) { return ( <ComboboxPrimitive.Chips data-slot="combobox-chips" className={cn( "dark:bg-input/30 border-input focus-within:border-ring focus-within:ring-ring/50 has-aria-invalid:ring-destructive/20 dark:has-aria-invalid:ring-destructive/40 has-aria-invalid:border-destructive dark:has-aria-invalid:border-destructive/50 flex min-h-9 flex-wrap items-center gap-1.5 rounded-md border bg-transparent bg-clip-padding px-2.5 py-1.5 text-sm shadow-xs transition-[color,box-shadow] focus-within:ring-[3px] has-aria-invalid:ring-[3px] has-data-[slot=combobox-chip]:px-1.5", className )} {...props} /> )}
function ComboboxChip({ className, children, showRemove = true, ...props}: ComboboxPrimitive.Chip.Props & { showRemove?: boolean}) { return ( <ComboboxPrimitive.Chip data-slot="combobox-chip" className={cn( "bg-muted text-foreground flex h-[calc(--spacing(5.5))] w-fit items-center justify-center gap-1 rounded-sm px-1.5 text-xs font-medium whitespace-nowrap has-disabled:pointer-events-none has-disabled:cursor-not-allowed has-disabled:opacity-50 has-data-[slot=combobox-chip-remove]:pr-0", className )} {...props} > {children} {showRemove && ( <ComboboxPrimitive.ChipRemove render={<Button variant="ghost" size="icon-xs" />} className="-ml-1 opacity-50 hover:opacity-100" data-slot="combobox-chip-remove" > <XIcon className="pointer-events-none" /> </ComboboxPrimitive.ChipRemove> )} </ComboboxPrimitive.Chip> )}
function ComboboxChipsInput({ className, children, ...props}: ComboboxPrimitive.Input.Props) { return ( <ComboboxPrimitive.Input data-slot="combobox-chip-input" className={cn("min-w-16 flex-1 outline-none", className)} {...props} /> )}
function useComboboxAnchor() { return React.useRef<HTMLDivElement | null>(null)}
export { Combobox, ComboboxInput, ComboboxContent, ComboboxList, ComboboxItem, ComboboxGroup, ComboboxLabel, ComboboxCollection, ComboboxEmpty, ComboboxSeparator, ComboboxChips, ComboboxChip, ComboboxChipsInput, ComboboxTrigger, ComboboxValue, useComboboxAnchor,}