svelte-multiselect 11.1.1 โ†’ 11.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/dist/CircleSpinner.svelte +2 -1
  2. package/dist/CmdPalette.svelte +13 -7
  3. package/dist/CmdPalette.svelte.d.ts +4 -5
  4. package/dist/CodeExample.svelte +80 -0
  5. package/dist/CodeExample.svelte.d.ts +22 -0
  6. package/dist/CopyButton.svelte +47 -0
  7. package/dist/CopyButton.svelte.d.ts +25 -0
  8. package/dist/FileDetails.svelte +53 -0
  9. package/dist/FileDetails.svelte.d.ts +21 -0
  10. package/dist/GitHubCorner.svelte +82 -0
  11. package/dist/GitHubCorner.svelte.d.ts +13 -0
  12. package/dist/Icon.svelte +23 -0
  13. package/dist/Icon.svelte.d.ts +8 -0
  14. package/dist/MultiSelect.svelte +129 -75
  15. package/dist/MultiSelect.svelte.d.ts +2 -3
  16. package/dist/PrevNext.svelte +100 -0
  17. package/dist/PrevNext.svelte.d.ts +48 -0
  18. package/dist/RadioButtons.svelte +67 -0
  19. package/dist/RadioButtons.svelte.d.ts +44 -0
  20. package/dist/Toggle.svelte +78 -0
  21. package/dist/Toggle.svelte.d.ts +16 -0
  22. package/dist/icons.d.ts +47 -0
  23. package/dist/icons.js +46 -0
  24. package/dist/index.d.ts +10 -3
  25. package/dist/index.js +10 -3
  26. package/dist/types.d.ts +141 -0
  27. package/dist/utils.d.ts +6 -22
  28. package/dist/utils.js +17 -25
  29. package/package.json +17 -35
  30. package/readme.md +287 -121
  31. package/dist/icons/ChevronExpand.svelte +0 -9
  32. package/dist/icons/ChevronExpand.svelte.d.ts +0 -4
  33. package/dist/icons/Cross.svelte +0 -10
  34. package/dist/icons/Cross.svelte.d.ts +0 -4
  35. package/dist/icons/Disabled.svelte +0 -10
  36. package/dist/icons/Disabled.svelte.d.ts +0 -4
  37. package/dist/icons/Octocat.svelte +0 -9
  38. package/dist/icons/Octocat.svelte.d.ts +0 -4
  39. package/dist/icons/index.d.ts +0 -4
  40. package/dist/icons/index.js +0 -4
  41. package/dist/props.d.ts +0 -143
  42. package/dist/props.js +0 -1
package/readme.md CHANGED
@@ -36,9 +36,9 @@
36
36
 
37
37
  ## ๐Ÿงช   Coverage
38
38
 
39
- | Statements | Branches | Lines |
40
- | ------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------ | -------------------------------------------------------------------------------- |
41
- | ![Statements](https://img.shields.io/badge/statements-97.94%25-brightgreen.svg?style=flat) | ![Branches](https://img.shields.io/badge/branches-79.39%25-red.svg?style=flat) | ![Lines](https://img.shields.io/badge/lines-97.94%25-brightgreen.svg?style=flat) |
39
+ | Statements | Branches | Lines |
40
+ | ------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- |
41
+ | ![Statements](https://img.shields.io/badge/statements-92.81%25-brightgreen.svg?style=flat) | ![Branches](https://img.shields.io/badge/branches-81.57%25-yellow.svg?style=flat) | ![Lines](https://img.shields.io/badge/lines-92.81%25-brightgreen.svg?style=flat) |
42
42
 
43
43
  ## ๐Ÿ”จ   Installation
44
44
 
@@ -66,334 +66,493 @@ Favorite Frontend Tools?
66
66
  <MultiSelect bind:selected options={ui_libs} />
67
67
  ```
68
68
 
69
+ ## ๐Ÿง  &thinsp; Mental Model
70
+
71
+ | Prop | Purpose | Value |
72
+ | --------------- | ------------------------------------------------------ | ----------------------------------------------------------------------------------- |
73
+ | `options` | What users can choose from | Array of strings, numbers, or objects with `label` property |
74
+ | `bind:selected` | Which options users have chosen | Always an array: `[]`, `['Apple']` or `['Apple', 'Banana']` |
75
+ | `bind:value` | Single-select convenience for the user-selected option | Single item: `'Apple'` (or `null`) if `maxSelect={1}`, otherwise same as `selected` |
76
+
77
+ ### Common Patterns
78
+
79
+ ```svelte
80
+ <!-- Multi-select -->
81
+ <MultiSelect bind:selected options={['A', 'B', 'C']} />
82
+
83
+ <!-- Single-select -->
84
+ <MultiSelect bind:value options={colors} maxSelect={1} />
85
+
86
+ <!-- Object options (need 'label' property, can have arbitrary other keys, some like `value`, `disabled`, `preselected`, `style` have special meaning, see type ObjectOption) -->
87
+ <MultiSelect
88
+ bind:selected
89
+ options={[
90
+ { label: 'Red', value: '#ff0000' },
91
+ { label: 'Blue', value: '#0000ff' },
92
+ ]}
93
+ />
94
+ ```
95
+
96
+ ### Troubleshooting
97
+
98
+ - **Object options not working?** โ†’ Add `label` property
99
+ - **Dropdown not showing?** โ†’ Check you have `options` and not `disabled={true}`
100
+ - **Want single item not array?** โ†’ Use `bind:value` with `maxSelect={1}`
101
+ - **Types confusing?** โ†’ Component auto-infers type of `selected` and `value` from your `options` array
102
+
69
103
  ## ๐Ÿ”ฃ &thinsp; Props
70
104
 
71
- Full list of props/bindable variables for this component. The `Option` type you see below is defined in [`src/lib/index.ts`](https://github.com/janosh/svelte-multiselect/blob/main/src/lib/index.ts) and can be imported as `import { type Option } from 'svelte-multiselect'`.
105
+ Complete reference of all props. Props are organized by importance - **Essential Props** are what you'll use most often.
106
+
107
+ > **๐Ÿ’ก Tip:** The `Option` type is automatically inferred from your `options` array, or you can import it: `import { type Option } from 'svelte-multiselect'`
108
+
109
+ ### Essential Props
110
+
111
+ These are the core props you'll use in most cases:
112
+
113
+ 1. ```ts
114
+ options: Option[] // REQUIRED
115
+ ```
116
+
117
+ **The only required prop.** Array of strings, numbers, or objects that users can select from. Objects must have a `label` property that will be displayed in the dropdown.
118
+
119
+ ```svelte
120
+ <!-- Simple options -->
121
+ <MultiSelect options={['Red', 'Green', 'Blue']} />
122
+
123
+ <!-- Object options -->
124
+ <MultiSelect
125
+ options={[
126
+ { label: 'Red', value: '#ff0000', hex: true },
127
+ { label: 'Green', value: '#00ff00', hex: true },
128
+ ]}
129
+ />
130
+ ```
72
131
 
73
132
  1. ```ts
74
- activeIndex: number | null = null
133
+ selected: Option[] = [] // bindable
75
134
  ```
76
135
 
77
- Zero-based index of currently active option in the array of currently matching options, i.e. if the user typed a search string into the input and only a subset of options match, this index refers to the array position of the matching subset of options
136
+ **Your main state variable.** Array of currently selected options. Use `bind:selected` for two-way binding.
137
+
138
+ ```svelte
139
+ <script>
140
+ let selected = $state(['Red']) // Pre-select Red
141
+ </script>
142
+ <MultiSelect bind:selected options={colors} />
143
+ ```
78
144
 
79
145
  1. ```ts
80
- activeOption: Option | null = null
146
+ value: Option | Option[] | null = null // bindable
81
147
  ```
82
148
 
83
- Currently active option, i.e. the one the user currently hovers or navigated to with arrow keys.
149
+ **Alternative to `selected`.** When `maxSelect={1}`, `value` is the single selected item (not an array). Otherwise, `value` equals `selected`.
150
+
151
+ ```svelte
152
+ <!-- Single-select: value = 'Red' (not ['Red']) -->
153
+ <MultiSelect bind:value options={colors} maxSelect={1} />
154
+
155
+ <!-- Multi-select: value = ['Red', 'Blue'] (same as selected) -->
156
+ <MultiSelect bind:value options={colors} />
157
+ ```
84
158
 
85
159
  1. ```ts
86
- createOptionMsg: string | null = `Create this option...`
160
+ maxSelect: number | null = null
87
161
  ```
88
162
 
89
- The message shown to users when `allowUserOptions` is truthy and they entered text that doesn't match any existing options to suggest creating a new option from the entered text. Emits `console.error` if `allowUserOptions` is `true` or `'append'` and `createOptionMsg=''` to since users might be unaware they can create new option. The error can be silenced by setting `createOptionMsg=null` indicating developer intent is to e.g. use MultiSelect as a tagging component where a user message might be unwanted.
163
+ **Controls selection behavior.** `null` = unlimited, `1` = single select, `2+` = limited multi-select.
164
+
165
+ ```svelte
166
+ <!-- Unlimited selection -->
167
+ <MultiSelect options={colors} />
168
+
169
+ <!-- Single selection -->
170
+ <MultiSelect options={colors} maxSelect={1} />
171
+
172
+ <!-- Max 3 selections -->
173
+ <MultiSelect options={colors} maxSelect={3} />
174
+ ```
90
175
 
91
176
  1. ```ts
92
- allowEmpty: boolean = false
177
+ placeholder: string | null = null
178
+ ```
179
+
180
+ Text shown when no options are selected.
181
+
182
+ 1. ```ts
183
+ disabled: boolean = false
184
+ ```
185
+
186
+ Disables the component. Users can't interact with it, but it's still rendered.
187
+
188
+ 1. ```ts
189
+ required: boolean | number = false
190
+ ```
191
+
192
+ For form validation. `true` means at least 1 option required, numbers specify exact minimum.
193
+
194
+ ### Commonly Used Props
195
+
196
+ 1. ```ts
197
+ searchText: string = `` // bindable
198
+ ```
199
+
200
+ The text user entered to filter options. Bindable for external control.
201
+
202
+ 1. ```ts
203
+ open: boolean = false // bindable
93
204
  ```
94
205
 
95
- Whether to `console.error` if dropdown list of options is empty. `allowEmpty={false}` will suppress errors. `allowEmpty={true}` will report a console error if component is not `disabled`, not in `loading` state and doesn't `allowUserOptions`.
206
+ Whether the dropdown is visible. Bindable for external control.
96
207
 
97
208
  1. ```ts
98
209
  allowUserOptions: boolean | `append` = false
99
210
  ```
100
211
 
101
- Whether users can enter values that are not in the dropdown list. `true` means add user-defined options to the selected list only, `'append'` means add to both options and selected.
102
- If `allowUserOptions` is `true` or `'append'` then the type `object | number | string` of entered value is determined by `typeof options[0]` (i.e. the first option in the dropdown list) to keep type homogeneity.
212
+ Whether users can create new options by typing. `true` = add to selected only, `'append'` = add to both options and selected.
103
213
 
104
214
  1. ```ts
105
- autocomplete: string = `off`
215
+ allowEmpty: boolean = false
106
216
  ```
107
217
 
108
- Applied to the `<input>`. Specifies if browser is permitted to auto-fill this form field. Should usually be one of `'on'` or `'off'` but see [MDN docs](https://developer.mozilla.org/docs/Web/HTML/Attributes/autocomplete) for other admissible values.
218
+ Whether to allow the component to exist with no options. If `false`, shows console error when no options provided (unless `loading`, `disabled`, or `allowUserOptions` is `true`).
109
219
 
110
220
  1. ```ts
111
- autoScroll: boolean = true
221
+ loading: boolean = false
112
222
  ```
113
223
 
114
- `false` disables keeping the active dropdown items in view when going up/down the list of options with arrow keys.
224
+ Shows a loading spinner. Useful when fetching options asynchronously.
115
225
 
116
226
  1. ```ts
117
- breakpoint: number = 800
227
+ invalid: boolean = false // bindable
118
228
  ```
119
229
 
120
- Screens wider than `breakpoint` in pixels will be considered `'desktop'`, everything narrower as `'mobile'`.
230
+ Marks the component as invalid (adds CSS class). Automatically set during form validation.
231
+
232
+ ### Advanced Props
121
233
 
122
234
  1. ```ts
123
- defaultDisabledTitle: string = `This option is disabled`
235
+ activeIndex: number | null = null // bindable
124
236
  ```
125
237
 
126
- Title text to display when user hovers over a disabled option. Each option can override this through its `disabledTitle` attribute.
238
+ Zero-based index of currently active option in the filtered list.
127
239
 
128
240
  1. ```ts
129
- disabled: boolean = false
241
+ activeOption: Option | null = null // bindable
130
242
  ```
131
243
 
132
- Disable the component. It will still be rendered but users won't be able to interact with it.
244
+ Currently active option (hovered or navigated to with arrow keys).
133
245
 
134
246
  1. ```ts
135
- disabledInputTitle: string = `This input is disabled`
247
+ createOptionMsg: string | null = `Create this option...`
136
248
  ```
137
249
 
138
- Tooltip text to display on hover when the component is in `disabled` state.
250
+ Message shown when `allowUserOptions` is enabled and user can create a new option.
139
251
 
140
252
  1. ```ts
141
253
  duplicates: boolean = false
142
254
  ```
143
255
 
144
- Whether to allow users to select duplicate options. Applies only to the selected item list, not the options dropdown. Keeping that free of duplicates is left to developer. The selected item list can have duplicates if `allowUserOptions` is truthy, `duplicates` is `true` and users create the same option multiple times. Use `duplicateOptionMsg` to customize the message shown to user if `duplicates` is `false` and users attempt this and `key` to customize when a pair of options is considered equal.
256
+ Whether to allow selecting the same option multiple times.
145
257
 
258
+ <!-- deno-fmt-ignore -->
146
259
  1. ```ts
147
- duplicateOptionMsg: string = `This option is already selected`
260
+ filterFunc: (opt: Option, searchText: string) => boolean
148
261
  ```
149
262
 
150
- Text to display to users when `allowUserOptions` is truthy and they try to create a new option that's already selected.
263
+ Custom function to filter options based on search text. Default filters by label.
151
264
 
152
- <!-- prettier-ignore -->
265
+ <!-- deno-fmt-ignore -->
153
266
  1. ```ts
154
- key: (opt: T) => unknown = (opt) => `${get_label(opt)}`.toLowerCase()
267
+ key: (opt: Option) => unknown
155
268
  ```
156
269
 
157
- A function that maps options to a value by which equality of options is determined. Defaults to mapping options to their lower-cased label. E.g. by default ``const opt1 = { label: `foo`, id: 1 }`` and ``const opt2 = { label: `foo`, id: 2 }`` are considered equal. If you want to consider them different, you can set `key` to e.g. `key={(opt) => opt.id}` or ``key={(opt) => `${opt.label}-${opt.id}}`` or even `key={JSON.stringify}`.
270
+ Function to determine option equality. Default compares by lowercased label.
158
271
 
159
272
  1. ```ts
160
- filterFunc = (opt: Option, searchText: string): boolean => {
161
- if (!searchText) return true
162
- return `${get_label(opt)}`.toLowerCase().includes(searchText.toLowerCase())
163
- }
273
+ closeDropdownOnSelect: boolean | 'if-mobile' | 'retain-focus' = 'if-mobile'
164
274
  ```
165
275
 
166
- Customize how dropdown options are filtered when user enters search string into `<MultiSelect />`. Defaults to:
276
+ Whether to close dropdown after selection. `'if-mobile'` closes dropdown on mobile devices only (responsive). `'retain-focus'` closes dropdown but keeps input focused for rapid typing to create custom options from text input (see `allowUserOptions`).
167
277
 
168
278
  1. ```ts
169
- closeDropdownOnSelect: boolean | `desktop` = `desktop`
279
+ resetFilterOnAdd: boolean = true
170
280
  ```
171
281
 
172
- One of `true`, `false` or `'desktop'`. Whether to close the dropdown list after selecting a dropdown item. If `true`, component will loose focus and `dropdown` is closed. `'desktop'` means `false` if current window width is larger than the current value of `breakpoint` prop (default is 800, meaning screen width in pixels). This is to align with the default behavior of many mobile browsers like Safari which close dropdowns after selecting an option while desktop browsers facilitate multi-selection by leaving dropdowns open.
282
+ Whether to clear search text when an option is selected.
173
283
 
174
284
  1. ```ts
175
- form_input: HTMLInputElement | null = null
285
+ sortSelected: boolean | ((a: Option, b: Option) => number) = false
176
286
  ```
177
287
 
178
- Handle to the `<input>` DOM node that's responsible for form validity checks and passing selected options to form submission handlers. Only available after component mounts (`null` before then).
288
+ Whether/how to sort selected options. `true` uses default sort, function enables custom sorting.
179
289
 
180
290
  1. ```ts
181
- highlightMatches: boolean = true
291
+ portal: { target_node?: HTMLElement; active?: boolean } = {}
182
292
  ```
183
293
 
184
- Whether to highlight text in the dropdown options that matches the current user-entered search query. Uses the [CSS Custom Highlight API](https://developer.mozilla.org/docs/Web/API/CSS_Custom_Highlight_API) with [limited browser support](https://caniuse.com/mdn-api_css_highlights) (70% as of May 2023) and [styling options](https://developer.mozilla.org/docs/Web/CSS/::highlight). See `::highlight(sms-search-matches)` below for available CSS variables.
294
+ Configuration for portal rendering. When `active: true`, the dropdown is rendered at document.body level with fixed positioning. Useful for avoiding z-index and overflow issues.
295
+
296
+ ### Form & Accessibility Props
185
297
 
186
298
  1. ```ts
187
299
  id: string | null = null
188
300
  ```
189
301
 
190
- Applied to the `<input>` element for associating HTML form `<label>`s with this component for accessibility. Also, clicking a `<label>` with same `for` attribute as `id` will focus this component.
302
+ Applied to the `<input>` for associating with `<label>` elements.
303
+
304
+ 1. ```ts
305
+ name: string | null = null
306
+ ```
307
+
308
+ Form field name for form submission.
191
309
 
192
310
  1. ```ts
193
- input: HTMLInputElement | null = null
311
+ autocomplete: string = 'off'
194
312
  ```
195
313
 
196
- Handle to the `<input>` DOM node. Only available after component mounts (`null` before then).
314
+ Browser autocomplete behavior. Usually `'on'` or `'off'`.
197
315
 
198
316
  1. ```ts
199
317
  inputmode: string | null = null
200
318
  ```
201
319
 
202
- The `inputmode` attribute hints at the type of data the user may enter. Values like `'numeric' | 'tel' | 'email'` allow mobile browsers to display an appropriate virtual on-screen keyboard. See [MDN](https://developer.mozilla.org/docs/Web/HTML/Global_attributes/inputmode) for details. If you want to suppress the on-screen keyboard to leave full-screen real estate for the dropdown list of options, set `inputmode="none"`.
320
+ Hint for mobile keyboard type (`'numeric'`, `'tel'`, `'email'`, etc.). Set to `'none'` to hide keyboard.
203
321
 
204
322
  1. ```ts
205
- inputStyle: string | null = null
323
+ pattern: string | null = null
206
324
  ```
207
325
 
208
- One-off CSS rules applied to the `<input>` element.
326
+ Regex pattern for input validation.
327
+
328
+ ### UI & Behavior Props
209
329
 
210
330
  1. ```ts
211
- invalid: boolean = false
331
+ maxOptions: number | undefined = undefined
212
332
  ```
213
333
 
214
- If `required = true, 1, 2, ...` and user tries to submit form but `selected = []` is empty/`selected.length < required`, `invalid` is automatically set to `true` and CSS class `invalid` applied to the top-level `div.multiselect`. `invalid` class is removed as soon as any change to `selected` is registered. `invalid` can also be controlled externally by binding to it `<MultiSelect bind:invalid />` and setting it to `true` based on outside events or custom validation.
334
+ Limit number of options shown in dropdown. `undefined` = no limit.
215
335
 
216
336
  1. ```ts
217
- liOptionStyle: string | null = null
337
+ minSelect: number | null = null
218
338
  ```
219
339
 
220
- One-off CSS rules applied to the `<li>` elements that wrap the dropdown options.
340
+ Minimum selections required before remove buttons appear.
221
341
 
222
342
  1. ```ts
223
- liSelectedStyle: string | null = null
343
+ autoScroll: boolean = true
224
344
  ```
225
345
 
226
- One-off CSS rules applied to the `<li>` elements that wrap the selected options.
346
+ Whether to keep active option in view when navigating with arrow keys.
227
347
 
228
348
  1. ```ts
229
- loading: boolean = false
349
+ breakpoint: number = 800
230
350
  ```
231
351
 
232
- Whether the component should display a spinner to indicate it's in loading state. Use `{#snippet spinner()} ... {/snippet}` to specify a custom spinner.
352
+ Screen width (px) that separates 'mobile' from 'desktop' behavior.
233
353
 
234
354
  1. ```ts
235
- matchingOptions: Option[] = []
355
+ highlightMatches: boolean = true
236
356
  ```
237
357
 
238
- List of options currently displayed to the user. Same as `options` unless the user entered `searchText` in which case this array contains only those options for which `filterFunc = (op: Option, searchText: string) => boolean` returned `true`.
358
+ Whether to highlight matching text in dropdown options.
239
359
 
240
360
  1. ```ts
241
- maxOptions: number | undefined = undefined
361
+ parseLabelsAsHtml: boolean = false
242
362
  ```
243
363
 
244
- Positive integer to limit the number of options displayed in the dropdown. `undefined` and 0 mean no limit.
364
+ Whether to render option labels as HTML. **Warning:** Don't combine with `allowUserOptions` (XSS risk).
245
365
 
246
366
  1. ```ts
247
- maxSelect: number | null = null
367
+ selectedOptionsDraggable: boolean = !sortSelected
248
368
  ```
249
369
 
250
- Positive integer to limit the number of options users can pick. `null` means no limit. `maxSelect={1}` will change the type of `selected` to be a single `Option` (or `null`) (not a length-1 array). Likewise, the type of `selectedLabels` changes from `(string | number)[]` to `string | number | null` and `selectedValues` from `unknown[]` to `unknown | null`. `maxSelect={1}` will also give `div.multiselect` a class of `single`. I.e. you can target the selector `div.multiselect.single` to give single selects a different appearance from multi selects.
370
+ Whether selected options can be reordered by dragging.
371
+
372
+ ### Message Props
251
373
 
252
374
  1. ```ts
253
- maxSelectMsg: ((current: number, max: number) => string) | null = (
254
- current: number,
255
- max: number
256
- ) => (max > 1 ? `${current}/${max}` : ``)
375
+ noMatchingOptionsMsg: string = 'No matching options'
257
376
  ```
258
377
 
259
- Inform users how many of the maximum allowed options they have already selected. Set `maxSelectMsg={null}` to not show a message. Defaults to `null` when `maxSelect={1}` or `maxSelect={null}`. Else if `maxSelect > 1`, defaults to:
378
+ Message when search yields no results.
260
379
 
261
- ```ts
262
- maxSelectMsg = (current: number, max: number) => `${current}/${max}`
380
+ 1. ```ts
381
+ duplicateOptionMsg: string = 'This option is already selected'
263
382
  ```
264
383
 
265
- Use CSS selector `span.max-select-msg` (or prop `maxSelectMsgClass` if you're using a CSS framework like Tailwind) to customize appearance of the message container.
384
+ Message when user tries to create duplicate option.
266
385
 
267
386
  1. ```ts
268
- minSelect: number | null = null
387
+ defaultDisabledTitle: string = 'This option is disabled'
269
388
  ```
270
389
 
271
- Conditionally render the `x` button which removes a selected option depending on the number of selected options. Meaning all remove buttons disappear if `selected.length <= minSelect`. E.g. if 2 options are selected and `minSelect={3}`, users will not be able to remove any selections until they selected more than 3 options.
390
+ Tooltip for disabled options.
391
+
392
+ 1. ```ts
393
+ disabledInputTitle: string = 'This input is disabled'
394
+ ```
272
395
 
273
- Note: Prop `required={3}` should be used instead if you only care about the component state at form submission time. `minSelect={3}` should be used if you want to place constraints on component state at all times.
396
+ Tooltip when component is disabled.
274
397
 
275
398
  1. ```ts
276
- name: string | null = null
399
+ removeAllTitle: string = 'Remove all'
277
400
  ```
278
401
 
279
- Applied to the `<input>` element. Sets the key of this field in a submitted form data object. See [form example](https://janosh.github.io/svelte-multiselect/form).
402
+ Tooltip for remove-all button.
280
403
 
281
404
  1. ```ts
282
- noMatchingOptionsMsg: string = `No matching options`
405
+ removeBtnTitle: string = 'Remove'
283
406
  ```
284
407
 
285
- What message to show if no options match the user-entered search string.
408
+ Tooltip for individual remove buttons.
286
409
 
410
+ <!-- deno-fmt-ignore -->
287
411
  1. ```ts
288
- open: boolean = false
412
+ maxSelectMsg: ((current: number, max: number) => string) | null
289
413
  ```
290
414
 
291
- Whether the dropdown list is currently visible. Is two-way bindable, i.e. can be used for external control of when the options are visible.
415
+ Function to generate "X of Y selected" message. `null` = no message.
416
+
417
+ ### DOM Element References (bindable)
418
+
419
+ These give you access to DOM elements after the component mounts:
292
420
 
293
421
  1. ```ts
294
- options: Option[]
422
+ input: HTMLInputElement | null = null // bindable
295
423
  ```
296
424
 
297
- **The only required prop** (no default). Array of strings/numbers or `Option` objects to be listed in the dropdown. The only required key on objects is `label` which must also be unique. An object's `value` defaults to `label` if `undefined`. You can add arbitrary additional keys to your option objects. A few keys like `preselected` and `title` have special meaning though. See type `ObjectOption` in [`/src/lib/types.ts`](https://github.com/janosh/svelte-multiselect/blob/main/src/lib/types.ts) for all special keys and their purpose.
425
+ Handle to the main `<input>` DOM element.
298
426
 
299
427
  1. ```ts
300
- outerDiv: HTMLDivElement | null = null
428
+ form_input: HTMLInputElement | null = null // bindable
301
429
  ```
302
430
 
303
- Handle to outer `<div class="multiselect">` that wraps the whole component. Only available after component mounts (`null` before then).
431
+ Handle to the hidden form input used for validation.
304
432
 
305
433
  1. ```ts
306
- parseLabelsAsHtml: boolean = false
434
+ outerDiv: HTMLDivElement | null = null // bindable
307
435
  ```
308
436
 
309
- Whether option labels should be passed to [Svelte's `@html` directive](https://svelte.dev/tutorial/svelte/html-tags) or inserted into the DOM as plain text. `true` will raise an error if `allowUserOptions` is also truthy as it makes your site susceptible to [cross-site scripting (XSS) attacks](https://wikipedia.org/wiki/Cross-site_scripting).
437
+ Handle to the outer wrapper `<div>` element.
438
+
439
+ ### Styling Props
440
+
441
+ For custom styling with CSS frameworks or one-off styles:
310
442
 
311
443
  1. ```ts
312
- pattern: string | null = null
444
+ style: string | null = null
313
445
  ```
314
446
 
315
- The pattern attribute specifies a regular expression which the input's value must match. If a non-null value doesn't match the `pattern` regex, the read-only `patternMismatch` property will be `true`. See [MDN](https://developer.mozilla.org/docs/Web/HTML/Attributes/pattern) for details.
447
+ CSS rules for the outer wrapper div.
316
448
 
317
449
  1. ```ts
318
- placeholder: string | null = null
450
+ inputStyle: string | null = null
451
+ ```
452
+
453
+ CSS rules for the main input element.
454
+
455
+ 1. ```ts
456
+ ulSelectedStyle: string | null = null
319
457
  ```
320
458
 
321
- String shown in the text input when no option is selected.
459
+ CSS rules for the selected options list.
322
460
 
323
461
  1. ```ts
324
- removeAllTitle: string = `Remove all`
462
+ ulOptionsStyle: string | null = null
325
463
  ```
326
464
 
327
- Title text to display when user hovers over remove-all button.
465
+ CSS rules for the dropdown options list.
328
466
 
329
467
  1. ```ts
330
- removeBtnTitle: string = `Remove`
468
+ liSelectedStyle: string | null = null
331
469
  ```
332
470
 
333
- Title text to display when user hovers over button to remove selected option (which defaults to a cross icon).
471
+ CSS rules for selected option list items.
334
472
 
335
473
  1. ```ts
336
- required: boolean | number = false
474
+ liOptionStyle: string | null = null
337
475
  ```
338
476
 
339
- If `required = true, 1, 2, ...` forms can't be submitted without selecting given number of options. `true` means 1. `false` means even empty MultiSelect will pass form validity check. If user tries to submit a form containing MultiSelect with less than the required number of options, submission is aborted, MultiSelect scrolls into view and shows message "Please select at least `required` options".
477
+ CSS rules for dropdown option list items.
478
+
479
+ ### CSS Class Props
480
+
481
+ For use with CSS frameworks like Tailwind:
340
482
 
341
483
  1. ```ts
342
- resetFilterOnAdd: boolean = true
484
+ outerDivClass: string = ''
343
485
  ```
344
486
 
345
- Whether text entered into the input to filter options in the dropdown list is reset to empty string when user selects an option.
487
+ CSS class for outer wrapper div.
346
488
 
347
489
  1. ```ts
348
- searchText: string = ``
490
+ inputClass: string = ''
349
491
  ```
350
492
 
351
- Text the user-entered to filter down on the list of options. Binds both ways, i.e. can also be used to set the input text.
493
+ CSS class for main input element.
352
494
 
353
495
  1. ```ts
354
- selected: Option[] =
355
- options
356
- ?.filter((op) => (op as ObjectOption)?.preselected)
357
- .slice(0, maxSelect ?? undefined) ?? []
496
+ ulSelectedClass: string = ''
358
497
  ```
359
498
 
360
- Array of currently selected options. Supports 2-way binding `bind:selected={[1, 2, 3]}` to control component state externally. Can be passed as prop to set pre-selected options that will already be populated when component mounts before any user interaction.
499
+ CSS class for selected options list.
361
500
 
362
501
  1. ```ts
363
- sortSelected: boolean | ((op1: Option, op2: Option) => number) = false
502
+ ulOptionsClass: string = ''
364
503
  ```
365
504
 
366
- Default behavior is to render selected items in the order they were chosen. `sortSelected={true}` uses default JS array sorting. A compare function enables custom logic for sorting selected options. See the [`/sort-selected`](https://janosh.github.io/svelte-multiselect/sort-selected) example.
505
+ CSS class for dropdown options list.
367
506
 
368
507
  1. ```ts
369
- selectedOptionsDraggable: boolean = !sortSelected
508
+ liSelectedClass: string = ''
370
509
  ```
371
510
 
372
- Whether selected options are draggable so users can change their order.
511
+ CSS class for selected option items.
373
512
 
374
513
  1. ```ts
375
- style: string | null = null
514
+ liOptionClass: string = ''
376
515
  ```
377
516
 
378
- One-off CSS rules applied to the outer `<div class="multiselect">` that wraps the whole component for passing one-off CSS.
517
+ CSS class for dropdown option items.
379
518
 
380
519
  1. ```ts
381
- ulSelectedStyle: string | null = null
520
+ liActiveOptionClass: string = ''
382
521
  ```
383
522
 
384
- One-off CSS rules applied to the `<ul class="selected">` that wraps the list of selected options.
523
+ CSS class for the currently active dropdown option.
385
524
 
386
525
  1. ```ts
387
- ulOptionsStyle: string | null = null
526
+ liUserMsgClass: string = ''
527
+ ```
528
+
529
+ CSS class for user messages (no matches, create option, etc.).
530
+
531
+ 1. ```ts
532
+ liActiveUserMsgClass: string = ''
388
533
  ```
389
534
 
390
- One-off CSS rules applied to the `<ul class="options">` that wraps the list of selected options.
535
+ CSS class for active user messages.
391
536
 
392
537
  1. ```ts
393
- value: Option | Option[] | null = null
538
+ maxSelectMsgClass: string = ''
394
539
  ```
395
540
 
396
- If `maxSelect={1}`, `value` will be the single item in `selected` (or `null` if `selected` is empty). If `maxSelect != 1`, `maxSelect` and `selected` are equal. Warning: Setting `value` does not rendered state on initial mount, meaning `bind:value` will update local variable `value` whenever internal component state changes but passing a `value` when component first mounts won't be reflected in UI. This is because the source of truth for rendering is `bind:selected`. `selected` is reactive to `value` internally but only on reassignment from initial value. Suggestions for better solutions than [#249](https://github.com/janosh/svelte-multiselect/issues/249) welcome!
541
+ CSS class for the "X of Y selected" message.
542
+
543
+ ### Read-only Props (bindable)
544
+
545
+ These reflect internal component state:
546
+
547
+ 1. ```ts
548
+ matchingOptions: Option[] = [] // bindable
549
+ ```
550
+
551
+ Currently filtered options based on search text.
552
+
553
+ ### Bindable Props
554
+
555
+ `selected`, `value`, `searchText`, `open`, `activeIndex`, `activeOption`, `invalid`, `input`, `outerDiv`, `form_input`, `options`, `matchingOptions`
397
556
 
398
557
  ## ๐ŸŽฐ &thinsp; Snippets
399
558
 
@@ -416,10 +575,10 @@ Example using several snippets:
416
575
  ```svelte
417
576
  <MultiSelect options={[`Red`, `Green`, `Blue`, `Yellow`, `Purple`]}>
418
577
  {#snippet children({ idx, option })}
419
- <span style="display: flex; align-items: center; gap: 6pt;">
578
+ <span style="display: flex; align-items: center; gap: 6pt">
420
579
  <span
421
580
  style:background={`${option}`}
422
- style="border-radius: 50%; width: 1em; height: 1em;"
581
+ style="border-radius: 50%; width: 1em; height: 1em"
423
582
  ></span>
424
583
  {idx + 1}
425
584
  {option}
@@ -444,6 +603,12 @@ Example using several snippets:
444
603
 
445
604
  Triggers when a new option is selected. The newly selected option is provided as `event.detail.option`.
446
605
 
606
+ 1. ```ts
607
+ oncreate={(event) => console.log(event.detail.option)}
608
+ ```
609
+
610
+ Triggers when a user creates a new option (when `allowUserOptions` is enabled). The created option is provided as `event.detail.option`.
611
+
447
612
  1. ```ts
448
613
  onremove={(event) => console.log(event.detail.option)}`
449
614
  ```
@@ -519,10 +684,10 @@ You can also import [the types this component uses](https://github.com/janosh/sv
519
684
 
520
685
  ```ts
521
686
  import {
522
- Option,
523
- ObjectOption,
524
687
  DispatchEvents,
525
688
  MultiSelectEvents,
689
+ ObjectOption,
690
+ Option,
526
691
  } from 'svelte-multiselect'
527
692
  ```
528
693
 
@@ -584,6 +749,7 @@ Minimal example that changes the background color of the options dropdown:
584
749
  - `background: var(--sms-options-bg, white)`: Background of dropdown list.
585
750
  - `max-height: var(--sms-options-max-height, 50vh)`: Maximum height of options dropdown.
586
751
  - `overscroll-behavior: var(--sms-options-overscroll, none)`: Whether scroll events bubble to parent elements when reaching the top/bottom of the options dropdown. See [MDN](https://developer.mozilla.org/docs/Web/CSS/overscroll-behavior).
752
+ - `z-index: var(--sms-options-z-index, 3)`: Z-index for the dropdown options list.
587
753
  - `box-shadow: var(--sms-options-shadow, 0 0 14pt -8pt black)`: Box shadow of dropdown list.
588
754
  - `border: var(--sms-options-border)`
589
755
  - `border-width: var(--sms-options-border-width)`