Find Similar Packages for svelte-select
1 Year
svelte-selectSimilar Packages:
Package Weekly Downloads Trend
Stat Detail
Package
Downloads
Stars
Size
Issues
Publish
License
svelte-select44,850-117 kB-a year agoISC
README for svelte-select
Svelte Select

Svelte Select

A select/autocomplete/typeahead Svelte component.

Demos

💥 Examples of every prop, event, slot and more 💥

✨ REPL: Simple ✨

💃 REPL: Show me everything 🕺

Installation

npm install svelte-select

Upgrading to v5

See migration guide if upgrading from v4 to v5.

Rollup and low/no-build setups

List position and floating is powered by floating-ui, see their package-entry-points docs if you encounter build errors.

Props

| Prop | Type | Default | Description | | ---------------------- | --------- | --------------- | -------------------------------------------------------------- | | items | any[] | [] | Array of items available to display / filter | | value | any | null | Selected value(s) | | justValue | any | null | READ-ONLY Selected value(s) excluding container object | | itemId | string | value | Override default identifier | | label | string | label | Override default label | | id | string | null | id attr for input field | | filterText | string | '' | Text to filter items by | | placeholder | string | Please select | Placeholder text | | hideEmptyState | boolean | false | When no items hide list | | listOpen | boolean | false | Open/close list | | class | string | '' | container classes | | containerStyles | string | '' | Add inline styles to container | | clearable | boolean | true | Enable clearing of value(s) | | disabled | boolean | false | Disable select | | multiple | boolean | false | Enable multi-select | | searchable | boolean | true | If false search/filtering is disabled | | groupHeaderSelectable | boolean | false | Enable selectable group headers | | focused | boolean | false | Controls input focus | | listAutoWidth | boolean | true | If false will ignore width of select | | showChevron | boolean | false | Show chevron | | inputAttributes | object | {} | Pass in HTML attributes to Select's input | | placeholderAlwaysShow | boolean | false | When multiple placeholder text will always show | | loading | boolean | false | Shows loading-icon. loadOptions will override this | | listOffset | number | 5 | px space between select and list | | debounceWait | number | 300 | milliseconds debounce wait | | floatingConfig | object | {} | Floating UI Config | | hasError | boolean | false | If true sets error class and styles | | name | string | null | Name attribute of hidden input, helpful for form actions | | required | boolean | false | If Select is within a <form> will restrict form submission | | multiFullItemClearable | boolean | false | When multiple selected items will clear on click | | closeListOnChange | boolean | true | After on:change list will close | | clearFilterTextOnBlur | boolean | true | If false, filterText value is preserved on:blur |

Named slots

<Select>
  <div slot="prepend" />
  <div slot="selection" let:selection let:index /> <!-- index only available when multiple -->
  <div slot="clear-icon" />  
  <div slot="multi-clear-icon" />  
  <div slot="loading-icon" />  
  <div slot="chevron-icon" /> 
  <div slot="list-prepend" />  
  <div slot="list" let:filteredItems />  
  <div slot="list-append" />  
  <div slot="item" let:item let:index />  
  <div slot="input-hidden" let:value />
  <div slot="required" let:value />
  <!-- Remember you can also use `svelte:fragment` to avoid a container DOM element. -->
  <svelte:fragment slot="empty" />  
</Select>

Events

| Event Name | Callback | Description | | ---------- | ----------------- | -------------------------------------------------------------------------- | | change | { detail } | fires when the user selects an option | | input | { detail } | fires when the value has been changed | | focus | { detail } | fires when select > input on:focus | | blur | { detail } | fires when select > input on:blur | | clear | { detail } | fires when clear is invoked or item is removed (by user) from multi select | | loaded | { options } | fires when loadOptions resolves | | error | { type, details } | fires when error is caught | | filter | { detail } | fires when listOpen: true and items are filtered | | hoverItem | { detail } | fires when hoverItemIndex changes |

Items

items can be simple arrays or collections.

<script>
  import Select from 'svelte-select';

  let simple = ['one', 'two', 'three'];

  let collection = [
    { value: 1, label: 'one' },
    { value: 2, label: 'two' },
    { value: 3, label: 'three' },
  ];
</script>

<Select items={simple} />

<Select items={collection} />

They can also be grouped and include non-selectable items.

<script>
  import Select from 'svelte-select';

  const items = [
    {value: 'chocolate', label: 'Chocolate', group: 'Sweet'},
    {value: 'pizza', label: 'Pizza', group: 'Savory'},
    {value: 'cake', label: 'Cake', group: 'Sweet', selectable: false},
    {value: 'chips', label: 'Chips', group: 'Savory'},
    {value: 'ice-cream', label: 'Ice Cream', group: 'Sweet'}
  ];

  const groupBy = (item) => item.group;
</script>

<Select {items} {groupBy} />

You can also use custom collections.

<script>
  import Select from 'svelte-select';

  const itemId = 'id';
  const label = 'title';

  const items = [
    {id: 0, title: 'Foo'},
    {id: 1, title: 'Bar'},
  ];
</script>

<Select {itemId} {label} {items} />

Async Items

To 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.

<script>
  import Select from 'svelte-select';

  import { someApiCall } from './services';

  async function examplePromise(filterText) {
    // Put your async code here...
    // For example call an API using filterText as your search params
    // When your API responds resolve your Promise
    let res = await someApiCall(filterText);
    return res;
  }
</script>

<Select loadOptions={examplePromise} />

Advanced List Positioning / Floating

svelte-select uses floating-ui to control the list floating. See their docs and pass in your config via the floatingConfig prop.

<script>
  import Select from 'svelte-select';

  let floatingConfig = {
    strategy: 'fixed'
  }
</script>

<Select {floatingConfig} />

Exposed methods

These internal functions are exposed to override if needed. Look through the test file (test/src/index.js) for examples.

export let itemFilter = (label, filterText, option) => label.toLowerCase().includes(filterText.toLowerCase());
export let groupBy = undefined;
export let groupFilter = groups => groups;
export let createGroupHeaderItem = groupValue => {
  return {
    value: groupValue,
    label: groupValue
  };
};
export function handleClear() {
  value = undefined;
  listOpen = false;
  dispatch("clear", value);
  handleFocus();
}
export let loadOptions = undefined; // if used must return a Promise that updates 'items'
/* Return an object with { cancelled: true } to keep the loading state as active. */
export const getFilteredItems = () => {
  return filteredItems;
};
export let debounce = (fn, wait = 1) => {
  clearTimeout(timeout);
  timeout = setTimeout(fn, wait);
};

Override core functionality at your own risk! See (get-items.js & filter.js)

    // core replaceable methods...
    <Select 
      filter={...}
      getItems={...}
    />

A11y (Accessibility)

Override these methods to change the aria-context and aria-selection text.

export let ariaValues = (values) => {
  return `Option ${values}, selected.`;
}

export let ariaListOpen = (label, count) => {
  return `You are currently focused on option ${label}. There are ${count} results available.`;
}

export let ariaFocused = () => {
  return `Select is focused, type to refine list, press down to open the menu.`;
}

CSS custom properties (variables)

You can style a component by overriding the available CSS custom properties.

<script>
  import Select from 'svelte-select';
</script>

<Select --border-radius= "10px" --placeholder-color="blue" />

You can also use the inputStyles prop to write in any override styles needed for the input.

<script>
  import Select from 'svelte-select';

  const items = ['One', 'Two', 'Three'];
</script>

<Select {items} inputStyles="box-sizing: border-box;"></Select>

🧪 Experimental: Replace styles (Tailwind, Bootstrap, Bulma etc)

If 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.

License

LIL