Home / Function/ FilterableInput() — supabase Function Reference

FilterableInput() — supabase Function Reference

Architecture documentation for the FilterableInput() function in ReportFilterPopover.tsx from the supabase codebase.

Entity Profile

Relationship Graph

Source Code

apps/studio/components/interfaces/Reports/ReportFilterPopover.tsx lines 25–121

const FilterableInput = ({
  value,
  onChange,
  onKeyDown,
  placeholder,
  availableOptions = [],
}: {
  value: string | number
  onChange: (value: string | number) => void
  onKeyDown: (event: KeyboardEvent<HTMLInputElement>) => void
  placeholder?: string
  type?: string
  availableOptions?: string[]
}) => {
  const [isOpen, setIsOpen] = useState(false)
  const [inputValue, setInputValue] = useState(String(value || ''))

  // Ensure we always have a valid array
  const safeOptions = Array.isArray(availableOptions) ? availableOptions : []

  useEffect(() => {
    setInputValue(String(value || ''))
  }, [value])

  const handleInputChange = (newValue: string) => {
    setInputValue(newValue)
    onChange(newValue)
  }

  const handleOptionSelect = (option: string) => {
    setInputValue(option)
    onChange(option)
    setIsOpen(false)
  }

  const handleKeyDown = (event: KeyboardEvent<HTMLInputElement>) => {
    if (event.key === 'Escape') {
      setIsOpen(false)
      return
    }

    // When dropdown is open, let Command component handle Enter for selection
    if (event.key === 'Enter' && isOpen) {
      // Don't call onKeyDown to prevent interference with Command's selection
      return
    }

    // When dropdown is closed, allow custom input
    if (event.key === 'Enter' && !isOpen) {
      return
    }

    onKeyDown(event)
  }

  return (
    <div className="relative flex-1">
      <Command_Shadcn_ className="relative overflow-visible bg-transparent">
        <CommandInput_Shadcn_
          placeholder={placeholder}
          value={inputValue}
          onValueChange={handleInputChange}
          onFocus={() => setIsOpen(true)}
          onKeyDown={handleKeyDown}
          className={cn('h-6 text-sm', defaultTheme.input.variants.standard, sizes.tiny)}
          wrapperClassName="!p-0 !border !border-control rounded-md"
          showSearchIcon={false}
        />
        <div
          className={cn(
            'absolute top-full left-0 right-0 z-50 mt-1 opacity-0 transition-opacity pointer-events-none',
            isOpen && safeOptions.length > 0 && 'opacity-100 pointer-events-auto'
          )}
        >
          <CommandList_Shadcn_ className="max-h-60 overflow-auto bg-surface-100 border border-border rounded-md shadow-lg">
            <CommandEmpty_Shadcn_ className="py-2 px-3 text-sm text-foreground-lighter">
              No matching options found. Press Enter to use "{inputValue}"
            </CommandEmpty_Shadcn_>
            <CommandGroup_Shadcn_>
              {safeOptions.map((option, index) => (
                <CommandItem_Shadcn_
                  key={`${option}-${index}`}
                  value={option}
                  onSelect={() => handleOptionSelect(option)}
                  className="px-3 py-2 text-sm cursor-pointer"
                >
                  {option}
                </CommandItem_Shadcn_>
              ))}
            </CommandGroup_Shadcn_>
          </CommandList_Shadcn_>
        </div>
      </Command_Shadcn_>
      {isOpen && <div className="fixed inset-0 z-40" onClick={() => setIsOpen(false)} />}
    </div>
  )
}

Subdomains

Analyze Your Own Codebase

Get architecture documentation, dependency graphs, and domain analysis for your codebase in minutes.

Try Supermodel Free