{
  "name": "combobox-debounced-demo",
  "type": "registry:example",
  "dependencies": [
    "lucide-react"
  ],
  "registryDependencies": [
    "combobox"
  ],
  "files": [
    {
      "path": "examples/combobox-debounced-demo.tsx",
      "type": "registry:example",
      "content": "\"use client\";\n\nimport { ChevronDown } from \"lucide-react\";\nimport * as React from \"react\";\n\nimport {\n  Combobox,\n  ComboboxAnchor,\n  ComboboxContent,\n  ComboboxEmpty,\n  ComboboxInput,\n  ComboboxItem,\n  ComboboxLabel,\n  ComboboxLoading,\n  ComboboxTrigger,\n} from \"@/registry/bases/radix/ui/combobox\";\n\nconst tricks = [\n  { label: \"Kickflip\", value: \"kickflip\" },\n  { label: \"Heelflip\", value: \"heelflip\" },\n  { label: \"Tre Flip\", value: \"tre-flip\" },\n  { label: \"FS 540\", value: \"fs-540\" },\n  { label: \"Casper flip 360 flip\", value: \"casper-flip-360-flip\" },\n  { label: \"Kickflip Backflip\", value: \"kickflip-backflip\" },\n  { label: \"360 Varial McTwist\", value: \"360-varial-mc-twist\" },\n  { label: \"The 900\", value: \"the-900\" },\n];\n\nexport default function ComboboxDebouncedDemo() {\n  const [value, setValue] = React.useState(\"\");\n  const [search, setSearch] = React.useState(\"\");\n  const [isLoading, setIsLoading] = React.useState(false);\n  const [progress, setProgress] = React.useState(0);\n  const [filteredItems, setFilteredItems] = React.useState(tricks);\n\n  // Debounce search with loading simulation\n  const debouncedSearch = React.useCallback(\n    debounce(async (searchTerm: string) => {\n      setIsLoading(true);\n      setProgress(0);\n\n      // Simulate a more realistic progress pattern\n      const progressSteps = [15, 35, 65, 85, 95] as const;\n      let currentStepIndex = 0;\n\n      const interval = setInterval(() => {\n        if (currentStepIndex < progressSteps.length) {\n          setProgress(progressSteps[currentStepIndex] ?? 0);\n          currentStepIndex++;\n        }\n      }, 150);\n\n      // Simulate API delay with variable timing\n      const delay = Math.random() * 300 + 400; // Random delay between 400-700ms\n      await new Promise((resolve) => setTimeout(resolve, delay));\n\n      const results = tricks.filter((trick) =>\n        trick.label.toLowerCase().includes(searchTerm.toLowerCase()),\n      );\n\n      setFilteredItems(results);\n      setProgress(100);\n      setIsLoading(false);\n      clearInterval(interval);\n    }, 300),\n    [],\n  );\n\n  const onInputValueChange = React.useCallback(\n    (value: string) => {\n      setSearch(value);\n      debouncedSearch(value);\n    },\n    [debouncedSearch],\n  );\n\n  return (\n    <Combobox\n      value={value}\n      onValueChange={setValue}\n      inputValue={search}\n      onInputValueChange={onInputValueChange}\n      manualFiltering\n    >\n      <ComboboxLabel>Trick</ComboboxLabel>\n      <ComboboxAnchor>\n        <ComboboxInput placeholder=\"Search trick...\" />\n        <ComboboxTrigger>\n          <ChevronDown className=\"h-4 w-4\" />\n        </ComboboxTrigger>\n      </ComboboxAnchor>\n      <ComboboxContent>\n        {isLoading ? (\n          <ComboboxLoading value={progress} label=\"Searching tricks...\" />\n        ) : null}\n        <ComboboxEmpty keepVisible={!isLoading && filteredItems.length === 0}>\n          No trick found.\n        </ComboboxEmpty>\n        {!isLoading &&\n          filteredItems.map((trick) => (\n            <ComboboxItem key={trick.value} value={trick.value} outset>\n              {trick.label}\n            </ComboboxItem>\n          ))}\n      </ComboboxContent>\n    </Combobox>\n  );\n}\n\nfunction debounce<TFunction extends (...args: never[]) => unknown>(\n  func: TFunction,\n  wait: number,\n): (...args: Parameters<TFunction>) => void {\n  let timeoutId: ReturnType<typeof setTimeout>;\n\n  return function (this: unknown, ...args: Parameters<TFunction>): void {\n    clearTimeout(timeoutId);\n    timeoutId = setTimeout(() => {\n      func.apply(this, args);\n    }, wait);\n  };\n}\n",
      "target": ""
    }
  ]
}