{"id":13493107,"url":"https://github.com/rob-balfre/svelte-select","last_synced_at":"2025-05-14T07:08:20.380Z","repository":{"id":37664735,"uuid":"161249703","full_name":"rob-balfre/svelte-select","owner":"rob-balfre","description":"Svelte Select. A select component for Svelte","archived":false,"fork":false,"pushed_at":"2024-10-20T20:42:55.000Z","size":2162,"stargazers_count":1317,"open_issues_count":101,"forks_count":191,"subscribers_count":16,"default_branch":"master","last_synced_at":"2025-05-09T22:34:00.033Z","etag":null,"topics":["autocomplete","select","svelte","sveltejs","typeahead"],"latest_commit_sha":null,"homepage":"https://svelte-select-examples.vercel.app","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rob-balfre.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","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":"2018-12-10T23:24:07.000Z","updated_at":"2025-05-09T11:07:03.000Z","dependencies_parsed_at":"2024-04-28T21:38:05.898Z","dependency_job_id":"870ebfbc-7bbd-4fbf-8751-a0eb9f142f91","html_url":"https://github.com/rob-balfre/svelte-select","commit_stats":{"total_commits":874,"total_committers":58,"mean_commits":"15.068965517241379","dds":0.2723112128146453,"last_synced_commit":"b87d8ab3b77bb36ea21d7b51040134bac5c32f7e"},"previous_names":[],"tags_count":171,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rob-balfre%2Fsvelte-select","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rob-balfre%2Fsvelte-select/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rob-balfre%2Fsvelte-select/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rob-balfre%2Fsvelte-select/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rob-balfre","download_url":"https://codeload.github.com/rob-balfre/svelte-select/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253609625,"owners_count":21935558,"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":["autocomplete","select","svelte","sveltejs","typeahead"],"created_at":"2024-07-31T19:01:12.304Z","updated_at":"2025-05-14T07:08:20.352Z","avatar_url":"https://github.com/rob-balfre.png","language":"JavaScript","funding_links":[],"categories":["JavaScript","components and libraries"],"sub_categories":["inputs and widgets"],"readme":"\u003cdiv align=\"center\"\u003e\n  \u003cimg src=\"https://raw.githubusercontent.com/rob-balfre/svelte-select/master/svelte-select.png\" alt=\"Svelte Select\" width=\"150\" /\u003e\n  \u003ch1\u003eSvelte Select\u003c/h1\u003e\n\u003c/div\u003e\n\n\u003cdiv align=\"center\"\u003e\n  \u003ca href=\"https://npmjs.org/package/svelte-select\"\u003e\n    \u003cimg src=\"https://badgen.now.sh/npm/v/svelte-select\" alt=\"version\" /\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://npmjs.org/package/svelte-select\"\u003e\n    \u003cimg src=\"https://badgen.now.sh/npm/dm/svelte-select\" alt=\"downloads\" /\u003e\n  \u003c/a\u003e\n\u003c/div\u003e\n\u003cdiv align=\"center\"\u003eA select/autocomplete/typeahead Svelte component.\u003c/div\u003e\n\n## Demos\n\n[💥 Examples of every prop, event, slot and more 💥](https://svelte-select-examples.vercel.app)\n\n[✨ REPL: Simple ✨](https://svelte.dev/repl/c3bbe052fdfc4e87a46ccd9091ee002b)\n\n[💃 REPL: Show me everything 🕺](https://svelte.dev/repl/3df87e32340e4e9e85bf371becae2af0)\n\n## Installation\n\n```bash\nnpm install svelte-select\n```\n\n## Svelte 5\nI'm not currently using Svelte 5 in my day job or personal projects so might be a while before I tackle porting / upgrading to Svelte 5. Looking forward to it though, just need to find the time!\n\n\n## Upgrading Svelte Select\nSee [migration guide](/MIGRATION_GUIDE.md) if upgrading\n\n\n## Rollup and low/no-build setups\n\nList position and floating is powered by `floating-ui`, see their [package-entry-points](https://github.com/floating-ui/floating-ui#package-entry-points) docs if you encounter build errors.\n\n\n\n## Props\n\n| Prop                   | Type      | Default         | Description                                                    |\n| ---------------------- | --------- | --------------- | -------------------------------------------------------------- |\n| items                  | `any[]`   | `[]`            | Array of items available to display / filter                   |\n| value                  | `any`     | `null`          | Selected value(s)                                              |\n| justValue              | `any`     | `null`          | **READ-ONLY** Selected value(s) excluding container object     |\n| itemId                 | `string`  | `value`         | Override default identifier                                    |\n| label                  | `string`  | `label`         | Override default label                                         |\n| id                     | `string`  | `null`          | id attr for input field                                        |\n| filterText             | `string`  | `''`            | Text to filter `items` by                                      |\n| placeholder            | `string`  | `Please select` | Placeholder text                                               |\n| hideEmptyState         | `boolean` | `false`         | When no items hide list                                        |\n| listOpen               | `boolean` | `false`         | Open/close list                                                |\n| class                  | `string`  | `''`            | container classes                                              |\n| containerStyles        | `string`  | `''`            | Add inline styles to container                                 |\n| clearable              | `boolean` | `true`          | Enable clearing of value(s)                                    |\n| disabled               | `boolean` | `false`         | Disable select                                                 |\n| multiple               | `boolean` | `false`         | Enable multi-select                                            |\n| searchable             | `boolean` | `true`          | If `false` search/filtering is disabled                        |\n| groupHeaderSelectable  | `boolean` | `false`         | Enable selectable group headers                                |\n| focused                | `boolean` | `false`         | Controls input focus                                           |\n| listAutoWidth          | `boolean` | `true`          | If `false` will ignore width of select                         |\n| showChevron            | `boolean` | `false`         | Show chevron                                                   |\n| inputAttributes        | `object`  | `{}`            | Pass in HTML attributes to Select's input                      |\n| placeholderAlwaysShow  | `boolean` | `false`         | When `multiple` placeholder text will always show              |\n| loading                | `boolean` | `false`         | Shows `loading-icon`. `loadOptions` will override this         |\n| listOffset             | `number`  | `5`             | `px` space between select and list                             |\n| debounceWait           | `number`  | `300`           | `milliseconds` debounce wait                                   |\n| floatingConfig         | `object`  | `{}`            | [Floating UI Config](https://floating-ui.com/)                 |\n| hasError               | `boolean` | `false`         | If `true` sets error class and styles                          |\n| name                   | `string`  | `null`          | Name attribute of hidden input, helpful for form actions       |\n| required               | `boolean` | `false`         | If `Select` is within a `\u003cform\u003e` will restrict form submission |\n| multiFullItemClearable | `boolean` | `false`         | When `multiple` selected items will clear on click             |\n| closeListOnChange      | `boolean` | `true`          | After `on:change` list will close                              |\n| clearFilterTextOnBlur  | `boolean` | `true`          | If `false`, `filterText` value is preserved on:blur            |\n\n\n## Named slots\n\n```svelte\n\u003cSelect\u003e\n  \u003cdiv slot=\"prepend\" /\u003e\n  \u003cdiv slot=\"selection\" let:selection let:index /\u003e \u003c!-- index only available when multiple --\u003e\n  \u003cdiv slot=\"clear-icon\" /\u003e  \n  \u003cdiv slot=\"multi-clear-icon\" /\u003e  \n  \u003cdiv slot=\"loading-icon\" /\u003e  \n  \u003cdiv slot=\"chevron-icon\" /\u003e \n  \u003cdiv slot=\"list-prepend\" /\u003e  \n  \u003cdiv slot=\"list\" let:filteredItems /\u003e  \n  \u003cdiv slot=\"list-append\" /\u003e  \n  \u003cdiv slot=\"item\" let:item let:index /\u003e  \n  \u003cdiv slot=\"input-hidden\" let:value /\u003e\n  \u003cdiv slot=\"required\" let:value /\u003e\n  \u003c!-- Remember you can also use `svelte:fragment` to avoid a container DOM element. --\u003e\n  \u003csvelte:fragment slot=\"empty\" /\u003e  \n\u003c/Select\u003e\n```\n\n\n## Events\n\n| Event Name | Callback          | Description                                                                |\n| ---------- | ----------------- | -------------------------------------------------------------------------- |\n| change     | { detail }        | fires when the user selects an option                                      |\n| input      | { detail }        | fires when the value has been changed                                      |\n| focus      | { detail }        | fires when select \u003e input on:focus                                         |\n| blur       | { detail }        | fires when select \u003e input on:blur                                          |\n| clear      | { detail }        | fires when clear is invoked or item is removed (by user) from multi select |\n| loaded     | { options }       | fires when `loadOptions` resolves                                          |\n| error      | { type, details } | fires when error is caught                                                 |\n| filter     | { detail }        | fires when `listOpen: true` and items are filtered                         |\n| hoverItem  | { detail }        | fires when hoverItemIndex changes                                          |\n\n\n### Items\n\n`items` can be simple arrays or collections.\n\n```html\n\u003cscript\u003e\n  import Select from 'svelte-select';\n\n  let simple = ['one', 'two', 'three'];\n\n  let collection = [\n    { value: 1, label: 'one' },\n    { value: 2, label: 'two' },\n    { value: 3, label: 'three' },\n  ];\n\u003c/script\u003e\n\n\u003cSelect items={simple} /\u003e\n\n\u003cSelect items={collection} /\u003e\n```\n\nThey can also be grouped and include non-selectable items.\n\n```html\n\u003cscript\u003e\n  import Select from 'svelte-select';\n\n  const items = [\n    {value: 'chocolate', label: 'Chocolate', group: 'Sweet'},\n    {value: 'pizza', label: 'Pizza', group: 'Savory'},\n    {value: 'cake', label: 'Cake', group: 'Sweet', selectable: false},\n    {value: 'chips', label: 'Chips', group: 'Savory'},\n    {value: 'ice-cream', label: 'Ice Cream', group: 'Sweet'}\n  ];\n\n  const groupBy = (item) =\u003e item.group;\n\u003c/script\u003e\n\n\u003cSelect {items} {groupBy} /\u003e\n```\n\nYou can also use custom collections.\n\n```html\n\u003cscript\u003e\n  import Select from 'svelte-select';\n\n  const itemId = 'id';\n  const label = 'title';\n\n  const items = [\n    {id: 0, title: 'Foo'},\n    {id: 1, title: 'Bar'},\n  ];\n\u003c/script\u003e\n\n\u003cSelect {itemId} {label} {items} /\u003e\n```\n\n### Async Items\n\nTo load items asynchronously then `loadOptions` is the simplest solution. Supply a function that returns a `Promise` that resolves with a list of items. `loadOptions` has debounce baked in and fires each time `filterText` is updated.\n\n```html\n\u003cscript\u003e\n  import Select from 'svelte-select';\n\n  import { someApiCall } from './services';\n\n  async function examplePromise(filterText) {\n    // Put your async code here...\n    // For example call an API using filterText as your search params\n    // When your API responds resolve your Promise\n    let res = await someApiCall(filterText);\n    return res;\n  }\n\u003c/script\u003e\n\n\u003cSelect loadOptions={examplePromise} /\u003e\n```\n\n\n### Advanced List Positioning / Floating \n\n`svelte-select` uses [floating-ui](https://floating-ui.com/) to control the list floating. See their docs and pass in your config via the `floatingConfig` prop.\n\n```html\n\u003cscript\u003e\n  import Select from 'svelte-select';\n\n  let floatingConfig = {\n    strategy: 'fixed'\n  }\n\u003c/script\u003e\n\n\u003cSelect {floatingConfig} /\u003e\n```\n\n### Exposed methods\nThese internal functions are exposed to override if needed. Look through the test file (test/src/index.js) for examples.\n\n```js\nexport let itemFilter = (label, filterText, option) =\u003e label.toLowerCase().includes(filterText.toLowerCase());\n```\n\n```js\nexport let groupBy = undefined;\n```\n\n```js\nexport let groupFilter = groups =\u003e groups;\n```\n\n```js\nexport let createGroupHeaderItem = groupValue =\u003e {\n  return {\n    value: groupValue,\n    label: groupValue\n  };\n};\n```\n\n```js\nexport function handleClear() {\n  value = undefined;\n  listOpen = false;\n  dispatch(\"clear\", value);\n  handleFocus();\n}\n```\n\n```js\nexport let loadOptions = undefined; // if used must return a Promise that updates 'items'\n/* Return an object with { cancelled: true } to keep the loading state as active. */\n```\n\n```js\nexport const getFilteredItems = () =\u003e {\n  return filteredItems;\n};\n```\n\n```js\nexport let debounce = (fn, wait = 1) =\u003e {\n  clearTimeout(timeout);\n  timeout = setTimeout(fn, wait);\n};\n```\n\nOverride core functionality at your own risk! See ([get-items.js](/src/lib/get-items.js) \u0026 [filter.js](/src/lib/filter.js))\n\n```js\n    // core replaceable methods...\n    \u003cSelect \n      filter={...}\n      getItems={...}\n    /\u003e\n```\n\n## A11y (Accessibility)\n\nOverride these methods to change the `aria-context` and `aria-selection` text.\n\n```js\nexport let ariaValues = (values) =\u003e {\n  return `Option ${values}, selected.`;\n}\n\nexport let ariaListOpen = (label, count) =\u003e {\n  return `You are currently focused on option ${label}. There are ${count} results available.`;\n}\n\nexport let ariaFocused = () =\u003e {\n  return `Select is focused, type to refine list, press down to open the menu.`;\n}\n```\n\n## CSS custom properties (variables)\n\nYou can style a component by overriding [the available CSS custom properties](/docs/theming_variables.md).\n\n```html\n\u003cscript\u003e\n  import Select from 'svelte-select';\n\u003c/script\u003e\n\n\u003cSelect --border-radius= \"10px\" --placeholder-color=\"blue\" /\u003e\n```\n\nYou can also use the `inputStyles` prop to write in any override styles needed for the input.\n\n```html\n\u003cscript\u003e\n  import Select from 'svelte-select';\n\n  const items = ['One', 'Two', 'Three'];\n\u003c/script\u003e\n\n\u003cSelect {items} inputStyles=\"box-sizing: border-box;\"\u003e\u003c/Select\u003e\n```\n\n### 🧪 Experimental: Replace styles (Tailwind, Bootstrap, Bulma etc)\nIf you'd like to supply your own styles use: `import Select from 'svelte-select/no-styles/Select.svelte'`. Then somewhere in your code or build pipeline add your own. There is a tailwind stylesheet via `import 'svelte-select/tailwind.css'`. It uses `@extend` so PostCSS is required.\n\n\n## License\n\n[LIL](LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frob-balfre%2Fsvelte-select","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frob-balfre%2Fsvelte-select","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frob-balfre%2Fsvelte-select/lists"}