{"id":23937491,"url":"https://github.com/rudrodip/asyncr","last_synced_at":"2025-04-05T00:05:37.545Z","repository":{"id":269643548,"uuid":"907988994","full_name":"rudrodip/asyncr","owner":"rudrodip","description":"Async Select component built with React \u0026 ShadCN UI","archived":false,"fork":false,"pushed_at":"2025-01-19T03:58:50.000Z","size":302,"stargazers_count":196,"open_issues_count":3,"forks_count":7,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-02T06:38:23.795Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://async.rdsx.dev","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rudrodip.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-12-24T19:45:54.000Z","updated_at":"2025-03-31T17:26:14.000Z","dependencies_parsed_at":"2024-12-25T05:30:30.430Z","dependency_job_id":"d5bb56f2-a075-47f1-90ef-c23216d906bf","html_url":"https://github.com/rudrodip/asyncr","commit_stats":null,"previous_names":["rudrodip/asyncr"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rudrodip%2Fasyncr","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rudrodip%2Fasyncr/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rudrodip%2Fasyncr/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rudrodip%2Fasyncr/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rudrodip","download_url":"https://codeload.github.com/rudrodip/asyncr/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247266562,"owners_count":20910836,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-01-06T02:01:59.793Z","updated_at":"2025-04-05T00:05:37.527Z","avatar_url":"https://github.com/rudrodip.png","language":"TypeScript","funding_links":[],"categories":["TypeScript","Components \u0026 Libraries"],"sub_categories":[],"readme":"# Async Select Component\n\nA modern, accessible, and customizable async select component for React applications. Built with TypeScript and shadcn/ui components.\n\n![Async Select](./public/og.png)\n\n## Installation\n\nThe Async Select Component is built through the composition of `\u003cPopover /\u003e` and the `\u003cCommand /\u003e` components from [shadcn/ui](https://ui.shadcn.com/docs).\n\nSee installation instructions for the [Popover](https://ui.shadcn.com/docs/components/popover#installation) and the [Command](https://ui.shadcn.com/docs/components/command#installation) components.\n\n## Basic Usage\n\n```tsx\nimport { AsyncSelect } from \"@/components/async-select\";\n\nfunction MyComponent() {\n  const [value, setValue] = useState(\"\");\n\n  return (\n    \u003cAsyncSelect\u003cDataType\u003e\n      fetcher={fetchData}\n      renderOption={(item) =\u003e \u003cdiv\u003e{item.name}\u003c/div\u003e}\n      getOptionValue={(item) =\u003e item.id}\n      getDisplayValue={(item) =\u003e item.name}\n      label=\"Select\"\n      value={value}\n      onChange={setValue}\n    /\u003e\n  );\n}\n```\n\n## Props\n\n### Required Props\n\n| Prop | Type | Description |\n|------|------|-------------|\n| `fetcher` | `(query?: string) =\u003e Promise\u003cT[]\u003e` | Async function to fetch options |\n| `renderOption` | `(option: T) =\u003e React.ReactNode` | Function to render each option in the dropdown |\n| `getOptionValue` | `(option: T) =\u003e string` | Function to get unique value from option |\n| `getDisplayValue` | `(option: T) =\u003e React.ReactNode` | Function to render selected value |\n| `value` | `string` | Currently selected value |\n| `onChange` | `(value: string) =\u003e void` | Callback when selection changes |\n| `label` | `string` | Label for the select field |\n\n### Optional Props\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `preload` | `boolean` | `false` | Enable preloading all options |\n| `filterFn` | `(option: T, query: string) =\u003e boolean` | - | Custom filter function for preload mode |\n| `notFound` | `React.ReactNode` | - | Custom not found message/component |\n| `loadingSkeleton` | `React.ReactNode` | - | Custom loading state component |\n| `placeholder` | `string` | \"Select...\" | Placeholder text |\n| `disabled` | `boolean` | `false` | Disable the select |\n| `width` | `string \\| number` | \"200px\" | Custom width |\n| `className` | `string` | - | Custom class for popover |\n| `triggerClassName` | `string` | - | Custom class for trigger button |\n| `noResultsMessage` | `string` | - | Custom no results message |\n| `clearable` | `boolean` | `true` | Allow clearing selection |\n\n## Examples\n\n### Async Mode\n\n```tsx\n\u003cAsyncSelect\u003cUser\u003e\n  fetcher={searchUsers}\n  renderOption={(user) =\u003e (\n    \u003cdiv className=\"flex items-center gap-2\"\u003e\n      \u003cImage\n        src={user.avatar}\n        alt={user.name}\n        width={24}\n        height={24}\n        className=\"rounded-full\"\n      /\u003e\n      \u003cdiv className=\"flex flex-col\"\u003e\n        \u003cdiv className=\"font-medium\"\u003e{user.name}\u003c/div\u003e\n        \u003cdiv className=\"text-xs text-muted-foreground\"\u003e{user.role}\u003c/div\u003e\n      \u003c/div\u003e\n    \u003c/div\u003e\n  )}\n  getOptionValue={(user) =\u003e user.id}\n  getDisplayValue={(user) =\u003e (\n    \u003cdiv className=\"flex items-center gap-2\"\u003e\n      \u003cImage\n        src={user.avatar}\n        alt={user.name}\n        width={24}\n        height={24}\n        className=\"rounded-full\"\n      /\u003e\n      \u003cdiv className=\"flex flex-col\"\u003e\n        \u003cdiv className=\"font-medium\"\u003e{user.name}\u003c/div\u003e\n        \u003cdiv className=\"text-xs text-muted-foreground\"\u003e{user.role}\u003c/div\u003e\n      \u003c/div\u003e\n    \u003c/div\u003e\n  )}\n  notFound={\u003cdiv className=\"py-6 text-center text-sm\"\u003eNo users found\u003c/div\u003e}\n  label=\"User\"\n  placeholder=\"Search users...\"\n  value={selectedUser}\n  onChange={setSelectedUser}\n  width=\"375px\"\n/\u003e\n```\n\n### Preload Mode\n\n```tsx\n\u003cAsyncSelect\u003cUser\u003e\n  fetcher={searchAllUsers}\n  preload\n  filterFn={(user, query) =\u003e user.name.toLowerCase().includes(query.toLowerCase())}\n  renderOption={(user) =\u003e (\n    \u003cdiv className=\"flex items-center gap-2\"\u003e\n      \u003cImage\n        src={user.avatar}\n        alt={user.name}\n        width={24}\n        height={24}\n        className=\"rounded-full\"\n      /\u003e\n      \u003cdiv className=\"flex flex-col\"\u003e\n        \u003cdiv className=\"font-medium\"\u003e{user.name}\u003c/div\u003e\n        \u003cdiv className=\"text-xs text-muted-foreground\"\u003e{user.role}\u003c/div\u003e\n      \u003c/div\u003e\n    \u003c/div\u003e\n  )}\n  getOptionValue={(user) =\u003e user.id}\n  getDisplayValue={(user) =\u003e user.name}\n  label=\"User\"\n  value={selectedUser}\n  onChange={setSelectedUser}\n/\u003e\n```\n\n## TypeScript Interface\n\n```tsx\ninterface AsyncSelectProps\u003cT\u003e {\n  fetcher: (query?: string) =\u003e Promise\u003cT[]\u003e;\n  preload?: boolean;\n  filterFn?: (option: T, query: string) =\u003e boolean;\n  renderOption: (option: T) =\u003e React.ReactNode;\n  getOptionValue: (option: T) =\u003e string;\n  getDisplayValue: (option: T) =\u003e React.ReactNode;\n  notFound?: React.ReactNode;\n  loadingSkeleton?: React.ReactNode;\n  value: string;\n  onChange: (value: string) =\u003e void;\n  label: string;\n  placeholder?: string;\n  disabled?: boolean;\n  width?: string | number;\n  className?: string;\n  triggerClassName?: string;\n  noResultsMessage?: string;\n  clearable?: boolean;\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frudrodip%2Fasyncr","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frudrodip%2Fasyncr","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frudrodip%2Fasyncr/lists"}