svelte-multiselect 11.3.0 โ 11.5.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.
- package/package.json +23 -16
- package/readme.md +222 -45
- package/dist/CircleSpinner.svelte +0 -29
- package/dist/CircleSpinner.svelte.d.ts +0 -8
- package/dist/CmdPalette.svelte +0 -74
- package/dist/CmdPalette.svelte.d.ts +0 -66
- package/dist/CodeExample.svelte +0 -87
- package/dist/CodeExample.svelte.d.ts +0 -25
- package/dist/CopyButton.svelte +0 -73
- package/dist/CopyButton.svelte.d.ts +0 -25
- package/dist/FileDetails.svelte +0 -52
- package/dist/FileDetails.svelte.d.ts +0 -23
- package/dist/GitHubCorner.svelte +0 -82
- package/dist/GitHubCorner.svelte.d.ts +0 -13
- package/dist/Icon.svelte +0 -23
- package/dist/Icon.svelte.d.ts +0 -8
- package/dist/MultiSelect.svelte +0 -1017
- package/dist/MultiSelect.svelte.d.ts +0 -25
- package/dist/Nav.svelte +0 -447
- package/dist/Nav.svelte.d.ts +0 -42
- package/dist/PrevNext.svelte +0 -101
- package/dist/PrevNext.svelte.d.ts +0 -56
- package/dist/Toggle.svelte +0 -74
- package/dist/Toggle.svelte.d.ts +0 -11
- package/dist/Wiggle.svelte +0 -15
- package/dist/Wiggle.svelte.d.ts +0 -15
- package/dist/attachments.d.ts +0 -49
- package/dist/attachments.js +0 -489
- package/dist/icons.d.ts +0 -47
- package/dist/icons.js +0 -46
- package/dist/index.d.ts +0 -16
- package/dist/index.js +0 -42
- package/dist/types.d.ts +0 -142
- package/dist/types.js +0 -1
- package/dist/utils.d.ts +0 -4
- package/dist/utils.js +0 -59
package/package.json
CHANGED
|
@@ -5,39 +5,46 @@
|
|
|
5
5
|
"homepage": "https://janosh.github.io/svelte-multiselect",
|
|
6
6
|
"repository": "https://github.com/janosh/svelte-multiselect",
|
|
7
7
|
"license": "MIT",
|
|
8
|
-
"version": "11.
|
|
8
|
+
"version": "11.5.0",
|
|
9
9
|
"type": "module",
|
|
10
|
+
"scripts": {
|
|
11
|
+
"dev": "vite dev",
|
|
12
|
+
"build": "vite build",
|
|
13
|
+
"preview": "vite preview",
|
|
14
|
+
"test": "vitest --run && playwright test",
|
|
15
|
+
"check": "svelte-check"
|
|
16
|
+
},
|
|
10
17
|
"svelte": "./dist/index.js",
|
|
11
18
|
"bugs": "https://github.com/janosh/svelte-multiselect/issues",
|
|
12
19
|
"peerDependencies": {
|
|
13
20
|
"svelte": "^5.35.6"
|
|
14
21
|
},
|
|
15
22
|
"devDependencies": {
|
|
16
|
-
"@playwright/test": "^1.
|
|
17
|
-
"@stylistic/eslint-plugin": "^5.
|
|
23
|
+
"@playwright/test": "^1.57.0",
|
|
24
|
+
"@stylistic/eslint-plugin": "^5.6.1",
|
|
18
25
|
"@sveltejs/adapter-static": "^3.0.10",
|
|
19
|
-
"@sveltejs/kit": "^2.
|
|
20
|
-
"@sveltejs/package": "2.5.
|
|
26
|
+
"@sveltejs/kit": "^2.49.2",
|
|
27
|
+
"@sveltejs/package": "2.5.7",
|
|
21
28
|
"@sveltejs/vite-plugin-svelte": "^6.2.1",
|
|
22
|
-
"@types/node": "^
|
|
23
|
-
"@vitest/coverage-v8": "^4.0.
|
|
24
|
-
"eslint": "^9.39.
|
|
25
|
-
"eslint-plugin-svelte": "^3.13.
|
|
26
|
-
"happy-dom": "^20.0.
|
|
29
|
+
"@types/node": "^25.0.3",
|
|
30
|
+
"@vitest/coverage-v8": "^4.0.16",
|
|
31
|
+
"eslint": "^9.39.2",
|
|
32
|
+
"eslint-plugin-svelte": "^3.13.1",
|
|
33
|
+
"happy-dom": "^20.0.11",
|
|
27
34
|
"hastscript": "^9.0.1",
|
|
28
35
|
"mdsvex": "^0.12.6",
|
|
29
36
|
"mdsvexamples": "^0.5.0",
|
|
30
37
|
"rehype-autolink-headings": "^7.1.0",
|
|
31
38
|
"rehype-slug": "^6.0.0",
|
|
32
|
-
"svelte": "^5.
|
|
33
|
-
"svelte-check": "^4.3.
|
|
39
|
+
"svelte": "^5.46.1",
|
|
40
|
+
"svelte-check": "^4.3.5",
|
|
34
41
|
"svelte-preprocess": "^6.0.3",
|
|
35
42
|
"svelte-toc": "^0.6.2",
|
|
36
|
-
"svelte2tsx": "^0.7.
|
|
43
|
+
"svelte2tsx": "^0.7.46",
|
|
37
44
|
"typescript": "5.9.3",
|
|
38
|
-
"typescript-eslint": "^8.
|
|
39
|
-
"vite": "^7.
|
|
40
|
-
"vitest": "^4.0.
|
|
45
|
+
"typescript-eslint": "^8.51.0",
|
|
46
|
+
"vite": "^7.3.0",
|
|
47
|
+
"vitest": "^4.0.16"
|
|
41
48
|
},
|
|
42
49
|
"keywords": [
|
|
43
50
|
"svelte",
|
package/readme.md
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
[](https://github.com/janosh/svelte-multiselect/actions/workflows/gh-pages.yml)
|
|
10
10
|
[](https://npmjs.com/package/svelte-multiselect)
|
|
11
11
|
[](https://github.com/sveltejs/svelte/blob/master/packages/svelte/CHANGELOG.md)
|
|
12
|
-
[](https://svelte.dev/playground/a5a14b8f15d64cb083b567292480db05)
|
|
13
13
|
[](https://stackblitz.com/github/janosh/svelte-multiselect)
|
|
14
14
|
|
|
15
15
|
</h4>
|
|
@@ -34,9 +34,9 @@
|
|
|
34
34
|
|
|
35
35
|
## ๐งช   Coverage
|
|
36
36
|
|
|
37
|
-
| Statements
|
|
38
|
-
|
|
|
39
|
-
|  |  |  |
|
|
40
40
|
|
|
41
41
|
## ๐จ   Installation
|
|
42
42
|
|
|
@@ -172,10 +172,18 @@ These are the core props you'll use in most cases:
|
|
|
172
172
|
```
|
|
173
173
|
|
|
174
174
|
1. ```ts
|
|
175
|
-
placeholder: string | null = null
|
|
175
|
+
placeholder: string | { text: string; persistent?: boolean } | null = null
|
|
176
176
|
```
|
|
177
177
|
|
|
178
|
-
Text shown when no options are selected.
|
|
178
|
+
Text shown when no options are selected. Can be a simple string or an object with extended options:
|
|
179
|
+
|
|
180
|
+
```svelte
|
|
181
|
+
<!-- Simple string -->
|
|
182
|
+
<MultiSelect placeholder="Choose..." />
|
|
183
|
+
|
|
184
|
+
<!-- Object with persistent option (stays visible even when options selected) -->
|
|
185
|
+
<MultiSelect placeholder={{ text: 'Add items...', persistent: true }} />
|
|
186
|
+
```
|
|
179
187
|
|
|
180
188
|
1. ```ts
|
|
181
189
|
disabled: boolean = false
|
|
@@ -229,6 +237,41 @@ These are the core props you'll use in most cases:
|
|
|
229
237
|
|
|
230
238
|
### Advanced Props
|
|
231
239
|
|
|
240
|
+
1. ```ts
|
|
241
|
+
loadOptions: LoadOptionsFn | LoadOptionsConfig = undefined
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
**Dynamic loading for large datasets.** Enables lazy loading / infinite scroll instead of passing static `options`. Pass either a function or an object with config:
|
|
245
|
+
|
|
246
|
+
```svelte
|
|
247
|
+
<!-- Simple: just a function -->
|
|
248
|
+
<MultiSelect loadOptions={myFetchFn} />
|
|
249
|
+
|
|
250
|
+
<!-- With config -->
|
|
251
|
+
<MultiSelect loadOptions={{ fetch: myFetchFn, debounceMs: 500, batchSize: 20 }} />
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
The function receives `{ search, offset, limit }` and must return `{ options, hasMore }`:
|
|
255
|
+
|
|
256
|
+
```ts
|
|
257
|
+
async function load_options({ search, offset, limit }) {
|
|
258
|
+
const response = await fetch(`/api/items?q=${search}&skip=${offset}&take=${limit}`)
|
|
259
|
+
const { items, total } = await response.json()
|
|
260
|
+
return { options: items, hasMore: offset + limit < total }
|
|
261
|
+
}
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
Config options (when passing an object):
|
|
265
|
+
|
|
266
|
+
| Key | Type | Default | Description |
|
|
267
|
+
| ------------ | --------- | ------- | ------------------------------------------- |
|
|
268
|
+
| `fetch` | `fn` | โ | Async function to load options (required) |
|
|
269
|
+
| `debounceMs` | `number` | `300` | Debounce delay for search queries |
|
|
270
|
+
| `batchSize` | `number` | `50` | Number of options to load per batch |
|
|
271
|
+
| `onOpen` | `boolean` | `true` | Whether to load options when dropdown opens |
|
|
272
|
+
|
|
273
|
+
Features automatic state management, debounced search, infinite scroll pagination, and loading indicators. See the [infinite-scroll demo](https://janosh.github.io/svelte-multiselect/infinite-scroll) for live examples.
|
|
274
|
+
|
|
232
275
|
1. ```ts
|
|
233
276
|
activeIndex: number | null = null // bindable
|
|
234
277
|
```
|
|
@@ -268,10 +311,10 @@ These are the core props you'll use in most cases:
|
|
|
268
311
|
Function to determine option equality. Default compares by lowercased label.
|
|
269
312
|
|
|
270
313
|
1. ```ts
|
|
271
|
-
closeDropdownOnSelect: boolean | 'if-mobile' | 'retain-focus' =
|
|
314
|
+
closeDropdownOnSelect: boolean | 'if-mobile' | 'retain-focus' = false
|
|
272
315
|
```
|
|
273
316
|
|
|
274
|
-
Whether to close dropdown after selection. `'if-mobile'` closes
|
|
317
|
+
Whether to close dropdown after selection. `false` (default) keeps dropdown open for rapid multi-selection. `true` closes after each selection. `'if-mobile'` closes on mobile devices only (screen width below `breakpoint`). `'retain-focus'` closes dropdown but keeps input focused for rapid typing to create custom options from text input (see `allowUserOptions`).
|
|
275
318
|
|
|
276
319
|
1. ```ts
|
|
277
320
|
resetFilterOnAdd: boolean = true
|
|
@@ -291,6 +334,85 @@ These are the core props you'll use in most cases:
|
|
|
291
334
|
|
|
292
335
|
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.
|
|
293
336
|
|
|
337
|
+
### Grouping Props
|
|
338
|
+
|
|
339
|
+
Group related options together with visual headers. Add a `group` key to your option objects:
|
|
340
|
+
|
|
341
|
+
```svelte
|
|
342
|
+
<script>
|
|
343
|
+
const options = [
|
|
344
|
+
{ label: `JavaScript`, group: `Frontend` },
|
|
345
|
+
{ label: `TypeScript`, group: `Frontend` },
|
|
346
|
+
{ label: `Python`, group: `Backend` },
|
|
347
|
+
{ label: `Go`, group: `Backend` },
|
|
348
|
+
]
|
|
349
|
+
</script>
|
|
350
|
+
|
|
351
|
+
<MultiSelect {options} collapsibleGroups groupSelectAll />
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
See the [grouping demo](https://janosh.github.io/svelte-multiselect/grouping) for live examples.
|
|
355
|
+
|
|
356
|
+
1. ```ts
|
|
357
|
+
collapsibleGroups: boolean = false
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
Enable click-to-collapse groups. When `true`, users can click group headers to hide/show options in that group.
|
|
361
|
+
|
|
362
|
+
1. ```ts
|
|
363
|
+
collapsedGroups: Set<string> = new Set()
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
Bindable set of collapsed group names. Use `bind:collapsedGroups` to control which groups are collapsed externally or to persist collapse state.
|
|
367
|
+
|
|
368
|
+
1. ```ts
|
|
369
|
+
groupSelectAll: boolean = false
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
Add a "Select all" button to each group header, allowing users to select all options in a specific group at once.
|
|
373
|
+
|
|
374
|
+
1. ```ts
|
|
375
|
+
ungroupedPosition: 'first' | 'last' = 'first'
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
Where to render options that don't have a `group` key. `'first'` places them at the top, `'last'` at the bottom.
|
|
379
|
+
|
|
380
|
+
1. ```ts
|
|
381
|
+
groupSortOrder: 'none' | 'asc' | 'desc' | ((a: string, b: string) => number) = 'none'
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
Sort groups alphabetically (`'asc'` or `'desc'`) or with a custom comparator function. Default `'none'` preserves order of first occurrence.
|
|
385
|
+
|
|
386
|
+
1. ```ts
|
|
387
|
+
searchExpandsCollapsedGroups: boolean = false
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
When `true`, collapsed groups automatically expand when the search query matches options within them.
|
|
391
|
+
|
|
392
|
+
1. ```ts
|
|
393
|
+
liGroupHeaderClass: string = ''
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
CSS class applied to group header `<li>` elements.
|
|
397
|
+
|
|
398
|
+
1. ```ts
|
|
399
|
+
liGroupHeaderStyle: string | null = null
|
|
400
|
+
```
|
|
401
|
+
|
|
402
|
+
Inline style for group header elements.
|
|
403
|
+
|
|
404
|
+
1. ```ts
|
|
405
|
+
groupHeader: Snippet<[{ group: string; options: T[]; collapsed: boolean }]>
|
|
406
|
+
```
|
|
407
|
+
|
|
408
|
+
Custom snippet for rendering group headers. Receives the group name, array of options in that group, and whether the group is collapsed.
|
|
409
|
+
|
|
410
|
+
1. ```ts
|
|
411
|
+
ongroupToggle: (data: { group: string; collapsed: boolean }) => void
|
|
412
|
+
```
|
|
413
|
+
|
|
414
|
+
Callback fired when a group is collapsed or expanded. Receives the group name and its new collapsed state.
|
|
415
|
+
|
|
294
416
|
### Form & Accessibility Props
|
|
295
417
|
|
|
296
418
|
1. ```ts
|
|
@@ -349,12 +471,36 @@ These are the core props you'll use in most cases:
|
|
|
349
471
|
|
|
350
472
|
Screen width (px) that separates 'mobile' from 'desktop' behavior.
|
|
351
473
|
|
|
474
|
+
1. ```ts
|
|
475
|
+
fuzzy: boolean = true
|
|
476
|
+
```
|
|
477
|
+
|
|
478
|
+
Whether to use fuzzy matching for filtering options. When `true` (default), matches non-consecutive characters (e.g., "ga" matches "Grapes" and "Green Apple"). When `false`, uses substring matching only.
|
|
479
|
+
|
|
352
480
|
1. ```ts
|
|
353
481
|
highlightMatches: boolean = true
|
|
354
482
|
```
|
|
355
483
|
|
|
356
484
|
Whether to highlight matching text in dropdown options.
|
|
357
485
|
|
|
486
|
+
1. ```ts
|
|
487
|
+
keepSelectedInDropdown: false | 'plain' | 'checkboxes' = false
|
|
488
|
+
```
|
|
489
|
+
|
|
490
|
+
Controls whether selected options remain visible in dropdown. `false` (default) hides selected options. `'plain'` shows them with visual distinction. `'checkboxes'` prefixes each option with a checkbox.
|
|
491
|
+
|
|
492
|
+
1. ```ts
|
|
493
|
+
selectAllOption: boolean | string = false
|
|
494
|
+
```
|
|
495
|
+
|
|
496
|
+
Adds a "Select All" option at the top of the dropdown. `true` shows default label, or pass a custom string label.
|
|
497
|
+
|
|
498
|
+
1. ```ts
|
|
499
|
+
liSelectAllClass: string = ''
|
|
500
|
+
```
|
|
501
|
+
|
|
502
|
+
CSS class applied to the "Select All" `<li>` element.
|
|
503
|
+
|
|
358
504
|
1. ```ts
|
|
359
505
|
parseLabelsAsHtml: boolean = false
|
|
360
506
|
```
|
|
@@ -367,6 +513,12 @@ These are the core props you'll use in most cases:
|
|
|
367
513
|
|
|
368
514
|
Whether selected options can be reordered by dragging.
|
|
369
515
|
|
|
516
|
+
1. ```ts
|
|
517
|
+
selectedFlipParams: FlipParams = { duration: 100 }
|
|
518
|
+
```
|
|
519
|
+
|
|
520
|
+
Animation parameters for the [Svelte flip animation](https://svelte.dev/docs/svelte/svelte-animate) when reordering selected options via drag-and-drop. Set `{ duration: 0 }` to disable animation. Accepts `duration`, `delay`, and `easing` properties.
|
|
521
|
+
|
|
370
522
|
### Message Props
|
|
371
523
|
|
|
372
524
|
1. ```ts
|
|
@@ -558,15 +710,16 @@ These reflect internal component state:
|
|
|
558
710
|
|
|
559
711
|
1. `#snippet option({ option, idx })`: Customize rendering of dropdown options. Receives as props an `option` and the zero-indexed position (`idx`) it has in the dropdown.
|
|
560
712
|
1. `#snippet selectedItem({ option, idx })`: Customize rendering of selected items. Receives as props an `option` and the zero-indexed position (`idx`) it has in the list of selected items.
|
|
713
|
+
1. `#snippet children({ option, idx })`: Convenience snippet that applies to both dropdown options AND selected items. Use this when you want the same custom rendering for both. Takes precedence if `option` or `selectedItem` are not provided.
|
|
561
714
|
1. `#snippet spinner()`: Custom spinner component to display when in `loading` state. Receives no props.
|
|
562
715
|
1. `#snippet disabledIcon()`: Custom icon to display inside the input when in `disabled` state. Receives no props. Use an empty `{#snippet disabledIcon()}{/snippet}` to remove the default disabled icon.
|
|
563
|
-
1. `#snippet expandIcon()`: Allows setting a custom icon to indicate to users that the Multiselect text input field is expandable into a dropdown list.
|
|
716
|
+
1. `#snippet expandIcon({ open })`: Allows setting a custom icon to indicate to users that the Multiselect text input field is expandable into a dropdown list. `open` is `true` if the dropdown is visible and `false` if hidden.
|
|
564
717
|
1. `#snippet removeIcon()`: Custom icon to display as remove button. Will be used both by buttons to remove individual selected options and the 'remove all' button that clears all options at once. Receives no props.
|
|
565
718
|
1. `#snippet userMsg({ searchText, msgType, msg })`: Displayed like a dropdown item when the list is empty and user is allowed to create custom options based on text input (or if the user's text input clashes with an existing option). Receives props:
|
|
566
719
|
- `searchText`: The text user typed into search input.
|
|
567
720
|
- `msgType: false | 'create' | 'dupe' | 'no-match'`: `'dupe'` means user input is a duplicate of an existing option. `'create'` means user is allowed to convert their input into a new option not previously in the dropdown. `'no-match'` means user input doesn't match any dropdown items and users are not allowed to create new options. `false` means none of the above.
|
|
568
721
|
- `msg`: Will be `duplicateOptionMsg` or `createOptionMsg` (see [props](#๐ฃ-props)) based on whether user input is a duplicate or can be created as new option. Note this snippet replaces the default UI for displaying these messages so the snippet needs to render them instead (unless purposely not showing a message).
|
|
569
|
-
1.
|
|
722
|
+
1. `#snippet afterInput({ selected, disabled, invalid, id, placeholder, open, required })`: Placed after the search input. For arbitrary content like icons or temporary messages. Can serve as a more dynamic, more customizable alternative to the `placeholder` prop.
|
|
570
723
|
|
|
571
724
|
Example using several snippets:
|
|
572
725
|
|
|
@@ -593,65 +746,79 @@ Example using several snippets:
|
|
|
593
746
|
|
|
594
747
|
## ๐ฌ   Events
|
|
595
748
|
|
|
596
|
-
`MultiSelect.svelte`
|
|
749
|
+
`MultiSelect.svelte` provides the following event callback props:
|
|
750
|
+
|
|
751
|
+
1. ```ts
|
|
752
|
+
onadd={({ option }) => console.log(option)}
|
|
753
|
+
```
|
|
754
|
+
|
|
755
|
+
Triggers when a new option is selected. The newly selected option is provided as `option`.
|
|
597
756
|
|
|
598
757
|
1. ```ts
|
|
599
|
-
|
|
758
|
+
oncreate={({ option }) => console.log(option)}
|
|
600
759
|
```
|
|
601
760
|
|
|
602
|
-
Triggers when a new option is
|
|
761
|
+
Triggers when a user creates a new option (when `allowUserOptions` is enabled). The created option is provided as `option`.
|
|
603
762
|
|
|
604
763
|
1. ```ts
|
|
605
|
-
|
|
764
|
+
onremove={({ option }) => console.log(option)}
|
|
606
765
|
```
|
|
607
766
|
|
|
608
|
-
Triggers when a
|
|
767
|
+
Triggers when a single selected option is removed. The removed option is provided as `option`.
|
|
609
768
|
|
|
610
769
|
1. ```ts
|
|
611
|
-
|
|
770
|
+
onremoveAll={({ options }) => console.log(options)}
|
|
612
771
|
```
|
|
613
772
|
|
|
614
|
-
Triggers when
|
|
773
|
+
Triggers when all selected options are removed. The `options` payload gives the options that were removed (might not be all if `minSelect` is set).
|
|
615
774
|
|
|
616
775
|
1. ```ts
|
|
617
|
-
|
|
776
|
+
onselectAll={({ options }) => console.log(options)}
|
|
618
777
|
```
|
|
619
778
|
|
|
620
|
-
Triggers when
|
|
779
|
+
Triggers when the "Select All" option is clicked (requires `selectAllOption` to be enabled). The `options` payload contains the options that were added.
|
|
621
780
|
|
|
622
781
|
1. ```ts
|
|
623
|
-
|
|
782
|
+
onreorder={({ options }) => console.log(options)}
|
|
624
783
|
```
|
|
625
784
|
|
|
626
|
-
Triggers when
|
|
785
|
+
Triggers when selected options are reordered via drag-and-drop (enabled by default when `sortSelected` is false). The `options` payload is the newly ordered array of selected options.
|
|
627
786
|
|
|
628
787
|
1. ```ts
|
|
629
|
-
|
|
788
|
+
onchange={({ type, option, options }) => console.log(type, option ?? options)}
|
|
630
789
|
```
|
|
631
790
|
|
|
632
|
-
Triggers when
|
|
791
|
+
Triggers when an option is either added (selected) or removed from selected, all selected options are removed at once, or selected options are reordered via drag-and-drop. `type` is one of `'add' | 'remove' | 'removeAll' | 'selectAll' | 'reorder'` and payload will be `option: Option` or `options: Option[]`, respectively.
|
|
633
792
|
|
|
634
793
|
1. ```ts
|
|
635
|
-
|
|
794
|
+
onopen={({ event }) => console.log(`Dropdown opened by`, event)}
|
|
636
795
|
```
|
|
637
796
|
|
|
638
|
-
Triggers when the dropdown list of options
|
|
797
|
+
Triggers when the dropdown list of options appears. `event` is the DOM's `FocusEvent`, `KeyboardEvent` or `ClickEvent` that triggered the open.
|
|
798
|
+
|
|
799
|
+
1. ```ts
|
|
800
|
+
onclose={({ event }) => console.log(`Dropdown closed by`, event)}
|
|
801
|
+
```
|
|
802
|
+
|
|
803
|
+
Triggers when the dropdown list of options disappears. `event` is the DOM's `FocusEvent`, `KeyboardEvent` or `ClickEvent` that triggered the close.
|
|
639
804
|
|
|
640
805
|
For example, here's how you might annoy your users with an alert every time one or more options are added or removed:
|
|
641
806
|
|
|
642
807
|
```svelte
|
|
643
808
|
<MultiSelect
|
|
644
|
-
onchange={(
|
|
645
|
-
if (
|
|
646
|
-
if (
|
|
647
|
-
if (
|
|
809
|
+
onchange={({ type, option, options }) => {
|
|
810
|
+
if (type === 'add') alert(`You added ${option}`)
|
|
811
|
+
if (type === 'remove') alert(`You removed ${option}`)
|
|
812
|
+
if (type === 'removeAll') alert(`You removed ${options}`)
|
|
813
|
+
if (type === 'selectAll') alert(`You selected all: ${options}`)
|
|
814
|
+
if (type === 'reorder') alert(`New order: ${options}`)
|
|
648
815
|
}}
|
|
649
816
|
/>
|
|
650
817
|
```
|
|
651
818
|
|
|
652
|
-
> Note: Depending on the data passed to the component the `
|
|
819
|
+
> Note: Depending on the data passed to the component the `option(s)` payload will either be objects or simple strings/numbers.
|
|
653
820
|
|
|
654
|
-
|
|
821
|
+
This component also forwards many DOM events from the `<input>` node: `blur`, `change`, `click`, `keydown`, `keyup`, `mousedown`, `mouseenter`, `mouseleave`, `touchcancel`, `touchend`, `touchmove`, `touchstart`. Registering listeners for these events works the same:
|
|
655
822
|
|
|
656
823
|
```svelte
|
|
657
824
|
<MultiSelect
|
|
@@ -682,7 +849,12 @@ You can also import [the types this component uses](https://github.com/janosh/sv
|
|
|
682
849
|
|
|
683
850
|
```ts
|
|
684
851
|
import {
|
|
685
|
-
|
|
852
|
+
LoadOptions, // Dynamic option loading callback
|
|
853
|
+
LoadOptionsConfig,
|
|
854
|
+
LoadOptionsFn,
|
|
855
|
+
LoadOptionsParams,
|
|
856
|
+
LoadOptionsResult,
|
|
857
|
+
MultiSelectEvents,
|
|
686
858
|
MultiSelectEvents,
|
|
687
859
|
ObjectOption,
|
|
688
860
|
Option,
|
|
@@ -717,10 +889,10 @@ Minimal example that changes the background color of the options dropdown:
|
|
|
717
889
|
```
|
|
718
890
|
|
|
719
891
|
- `div.multiselect`
|
|
720
|
-
- `border: var(--sms-border, 1pt solid lightgray)`: Change this to e.g. to `1px solid red` to indicate this form field is in an invalid state.
|
|
892
|
+
- `border: var(--sms-border, 1pt solid light-dark(lightgray, #555))`: Change this to e.g. to `1px solid red` to indicate this form field is in an invalid state.
|
|
721
893
|
- `border-radius: var(--sms-border-radius, 3pt)`
|
|
722
894
|
- `padding: var(--sms-padding, 0 3pt)`
|
|
723
|
-
- `background: var(--sms-bg)`
|
|
895
|
+
- `background: var(--sms-bg, light-dark(white, #1a1a1a))`
|
|
724
896
|
- `color: var(--sms-text-color)`
|
|
725
897
|
- `min-height: var(--sms-min-height, 22pt)`
|
|
726
898
|
- `width: var(--sms-width)`
|
|
@@ -732,23 +904,23 @@ Minimal example that changes the background color of the options dropdown:
|
|
|
732
904
|
- `div.multiselect:focus-within`
|
|
733
905
|
- `border: var(--sms-focus-border, 1pt solid var(--sms-active-color, cornflowerblue))`: Border when component has focus. Defaults to `--sms-active-color` which in turn defaults to `cornflowerblue`.
|
|
734
906
|
- `div.multiselect.disabled`
|
|
735
|
-
- `background: var(--sms-disabled-bg, lightgray)`: Background when in disabled state.
|
|
907
|
+
- `background: var(--sms-disabled-bg, light-dark(lightgray, #444))`: Background when in disabled state.
|
|
736
908
|
- `div.multiselect input::placeholder`
|
|
737
909
|
- `color: var(--sms-placeholder-color)`
|
|
738
910
|
- `opacity: var(--sms-placeholder-opacity)`
|
|
739
911
|
- `div.multiselect > ul.selected > li`
|
|
740
|
-
- `background: var(--sms-selected-bg, rgba(0, 0, 0, 0.15))`: Background of selected options.
|
|
912
|
+
- `background: var(--sms-selected-bg, light-dark(rgba(0, 0, 0, 0.15), rgba(255, 255, 255, 0.15)))`: Background of selected options.
|
|
741
913
|
- `padding: var(--sms-selected-li-padding, 1pt 5pt)`: Height of selected options.
|
|
742
914
|
- `color: var(--sms-selected-text-color, var(--sms-text-color))`: Text color for selected options.
|
|
743
915
|
- `ul.selected > li button:hover, button.remove-all:hover, button:focus`
|
|
744
|
-
- `color: var(--sms-remove-btn-hover-color, lightskyblue)`: Color of the remove-icon buttons for removing all or individual selected options when in `:focus` or `:hover` state.
|
|
745
|
-
- `background: var(--sms-remove-btn-hover-bg, rgba(0, 0, 0, 0.2))`: Background for hovered remove buttons.
|
|
916
|
+
- `color: var(--sms-remove-btn-hover-color, light-dark(#0088cc, lightskyblue))`: Color of the remove-icon buttons for removing all or individual selected options when in `:focus` or `:hover` state.
|
|
917
|
+
- `background: var(--sms-remove-btn-hover-bg, light-dark(rgba(0, 0, 0, 0.2), rgba(255, 255, 255, 0.2)))`: Background for hovered remove buttons.
|
|
746
918
|
- `div.multiselect > ul.options`
|
|
747
|
-
- `background: var(--sms-options-bg,
|
|
919
|
+
- `background: var(--sms-options-bg, light-dark(#fafafa, #1a1a1a))`: Background of dropdown list.
|
|
748
920
|
- `max-height: var(--sms-options-max-height, 50vh)`: Maximum height of options dropdown.
|
|
749
921
|
- `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).
|
|
750
922
|
- `z-index: var(--sms-options-z-index, 3)`: Z-index for the dropdown options list.
|
|
751
|
-
- `box-shadow: var(--sms-options-shadow, 0 0 14pt -8pt black)`: Box shadow of dropdown list.
|
|
923
|
+
- `box-shadow: var(--sms-options-shadow, light-dark(0 0 14pt -8pt black, 0 0 14pt -4pt rgba(0, 0, 0, 0.8)))`: Box shadow of dropdown list.
|
|
752
924
|
- `border: var(--sms-options-border)`
|
|
753
925
|
- `border-width: var(--sms-options-border-width)`
|
|
754
926
|
- `border-radius: var(--sms-options-border-radius, 1ex)`
|
|
@@ -757,13 +929,13 @@ Minimal example that changes the background color of the options dropdown:
|
|
|
757
929
|
- `div.multiselect > ul.options > li`
|
|
758
930
|
- `scroll-margin: var(--sms-options-scroll-margin, 100px)`: Top/bottom margin to keep between dropdown list items and top/bottom screen edge when auto-scrolling list to keep items in view.
|
|
759
931
|
- `div.multiselect > ul.options > li.selected`
|
|
760
|
-
- `background: var(--sms-li-selected-bg)`: Background of selected list items in options pane.
|
|
761
|
-
- `
|
|
932
|
+
- `background: var(--sms-li-selected-plain-bg, light-dark(rgba(0, 123, 255, 0.1), rgba(100, 180, 255, 0.2)))`: Background of selected list items in options pane.
|
|
933
|
+
- `border-left: var(--sms-li-selected-plain-border, 3px solid var(--sms-active-color, cornflowerblue))`: Left border of selected list items in options pane.
|
|
762
934
|
- `div.multiselect > ul.options > li.active`
|
|
763
|
-
- `background: var(--sms-li-active-bg, var(--sms-active-color, rgba(0, 0, 0, 0.15)))`: Background of active options. Options in the dropdown list become active either by mouseover or by navigating to them with arrow keys. Selected options become active when `selectedOptionsDraggable=true` and an option is being dragged to a new position. Note the active option in that case is not the dragged option but the option under it whose place it will take on drag end.
|
|
935
|
+
- `background: var(--sms-li-active-bg, var(--sms-active-color, light-dark(rgba(0, 0, 0, 0.15), rgba(255, 255, 255, 0.15))))`: Background of active options. Options in the dropdown list become active either by mouseover or by navigating to them with arrow keys. Selected options become active when `selectedOptionsDraggable=true` and an option is being dragged to a new position. Note the active option in that case is not the dragged option but the option under it whose place it will take on drag end.
|
|
764
936
|
- `div.multiselect > ul.options > li.disabled`
|
|
765
|
-
- `background: var(--sms-li-disabled-bg, #f5f5f6)`: Background of disabled options in the dropdown list.
|
|
766
|
-
- `color: var(--sms-li-disabled-text, #b8b8b8)`: Text color of disabled option in the dropdown list.
|
|
937
|
+
- `background: var(--sms-li-disabled-bg, light-dark(#f5f5f6, #2a2a2a))`: Background of disabled options in the dropdown list.
|
|
938
|
+
- `color: var(--sms-li-disabled-text, light-dark(#b8b8b8, #666))`: Text color of disabled option in the dropdown list.
|
|
767
939
|
- `::highlight(sms-search-matches)`: applies to search results in dropdown list that match the current search query if `highlightMatches=true`. These styles [cannot be set via CSS variables](https://stackoverflow.com/a/56799215). Instead, use a new rule set. For example:
|
|
768
940
|
|
|
769
941
|
```css
|
|
@@ -784,6 +956,7 @@ The second method allows you to pass in custom classes to the important DOM elem
|
|
|
784
956
|
- `ulOptionsClass`: available options listed in the dropdown when component is in `open` state
|
|
785
957
|
- `liOptionClass`: list items selectable from dropdown list
|
|
786
958
|
- `liActiveOptionClass`: the currently active dropdown list item (i.e. hovered or navigated to with arrow keys)
|
|
959
|
+
- `liSelectAllClass`: the "Select All" option at the top of the dropdown (when `selectAllOption` is enabled)
|
|
787
960
|
- `liUserMsgClass`: user message (last child of dropdown list when no options match user input)
|
|
788
961
|
- `liActiveUserMsgClass`: user message when active (i.e. hovered or navigated to with arrow keys)
|
|
789
962
|
- `maxSelectMsgClass`: small span towards the right end of the input field displaying to the user how many of the allowed number of options they've already selected
|
|
@@ -799,6 +972,7 @@ This simplified version of the DOM structure of the component shows where these
|
|
|
799
972
|
</ul>
|
|
800
973
|
<span class="maxSelectMsgClass">2/5 selected</span>
|
|
801
974
|
<ul class="options {ulOptionsClass}">
|
|
975
|
+
<li class="select-all {liSelectAllClass}">Select all</li>
|
|
802
976
|
<li class={liOptionClass}>Option 1</li>
|
|
803
977
|
<li class="{liOptionClass} {liActiveOptionClass}">
|
|
804
978
|
Option 2 (currently active)
|
|
@@ -859,6 +1033,9 @@ Odd as it may seem, you get the most fine-grained control over the styling of ev
|
|
|
859
1033
|
:global(div.multiselect > ul.options > li.disabled) {
|
|
860
1034
|
/* options with disabled key set to true (see props above) */
|
|
861
1035
|
}
|
|
1036
|
+
:global(div.multiselect > ul.options > li.select-all) {
|
|
1037
|
+
/* the "Select All" option at the top of the dropdown */
|
|
1038
|
+
}
|
|
862
1039
|
```
|
|
863
1040
|
|
|
864
1041
|
## ๐   Changelog
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
<script lang="ts">"use strict";
|
|
2
|
-
let { color = `cornflowerblue`, duration = `1.5s`, size = `1em` } = $props();
|
|
3
|
-
</script>
|
|
4
|
-
|
|
5
|
-
<div
|
|
6
|
-
style="--duration: {duration}"
|
|
7
|
-
style:border-color="{color} transparent {color}
|
|
8
|
-
{color}"
|
|
9
|
-
style:width={size}
|
|
10
|
-
style:height={size}
|
|
11
|
-
>
|
|
12
|
-
</div>
|
|
13
|
-
|
|
14
|
-
<style>
|
|
15
|
-
div {
|
|
16
|
-
display: inline-block;
|
|
17
|
-
vertical-align: middle;
|
|
18
|
-
margin: 0 3pt;
|
|
19
|
-
border-width: calc(1em / 5);
|
|
20
|
-
border-style: solid;
|
|
21
|
-
border-radius: 50%;
|
|
22
|
-
animation: var(--duration) infinite rotate;
|
|
23
|
-
}
|
|
24
|
-
@keyframes rotate {
|
|
25
|
-
100% {
|
|
26
|
-
transform: rotate(360deg);
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
</style>
|
package/dist/CmdPalette.svelte
DELETED
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
<script
|
|
2
|
-
lang="ts"
|
|
3
|
-
generics="Action extends { label: string; action: (label: string) => void } & Record<string, unknown> = { label: string; action: (label: string) => void }"
|
|
4
|
-
>import { fade } from 'svelte/transition';
|
|
5
|
-
import MultiSelect from './MultiSelect.svelte';
|
|
6
|
-
let { actions, triggers = [`k`], close_keys = [`Escape`], fade_duration = 200, dialog_style = ``, open = $bindable(false), dialog = $bindable(null), input = $bindable(null), placeholder = `Filter actions...`, dialog_props, ...rest } = $props();
|
|
7
|
-
$effect(() => {
|
|
8
|
-
if (open && input && document.activeElement !== input)
|
|
9
|
-
input.focus();
|
|
10
|
-
});
|
|
11
|
-
async function toggle(event) {
|
|
12
|
-
const is_trigger = triggers.includes(event.key) &&
|
|
13
|
-
(event.metaKey || event.ctrlKey);
|
|
14
|
-
if (is_trigger && !open)
|
|
15
|
-
open = true;
|
|
16
|
-
else if (close_keys.includes(event.key) && open)
|
|
17
|
-
open = false;
|
|
18
|
-
}
|
|
19
|
-
function close_if_outside(event) {
|
|
20
|
-
const target = event.target;
|
|
21
|
-
if (!target || !(target instanceof HTMLElement))
|
|
22
|
-
return;
|
|
23
|
-
if (open && !dialog?.contains(target) && !target.closest(`ul.options`)) {
|
|
24
|
-
open = false;
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
function trigger_action_and_close({ option }) {
|
|
28
|
-
if (!option?.action)
|
|
29
|
-
return;
|
|
30
|
-
option.action(option.label);
|
|
31
|
-
open = false;
|
|
32
|
-
}
|
|
33
|
-
</script>
|
|
34
|
-
|
|
35
|
-
<svelte:window onkeydown={toggle} onclick={close_if_outside} />
|
|
36
|
-
|
|
37
|
-
{#if open}
|
|
38
|
-
<dialog
|
|
39
|
-
open
|
|
40
|
-
bind:this={dialog}
|
|
41
|
-
transition:fade={{ duration: fade_duration }}
|
|
42
|
-
style={dialog_style}
|
|
43
|
-
{...dialog_props}
|
|
44
|
-
>
|
|
45
|
-
<MultiSelect
|
|
46
|
-
options={actions}
|
|
47
|
-
bind:input
|
|
48
|
-
{placeholder}
|
|
49
|
-
onadd={trigger_action_and_close}
|
|
50
|
-
onkeydown={toggle}
|
|
51
|
-
{...rest}
|
|
52
|
-
--sms-bg="var(--sms-options-bg)"
|
|
53
|
-
--sms-width="min(20em, 90vw)"
|
|
54
|
-
--sms-max-width="none"
|
|
55
|
-
--sms-placeholder-color="lightgray"
|
|
56
|
-
--sms-options-margin="1px 0"
|
|
57
|
-
--sms-options-border-radius="0 0 1ex 1ex"
|
|
58
|
-
/>
|
|
59
|
-
</dialog>
|
|
60
|
-
{/if}
|
|
61
|
-
|
|
62
|
-
<style>
|
|
63
|
-
:where(dialog) {
|
|
64
|
-
position: fixed;
|
|
65
|
-
top: 30%;
|
|
66
|
-
border: none;
|
|
67
|
-
padding: 0;
|
|
68
|
-
background-color: transparent;
|
|
69
|
-
display: flex;
|
|
70
|
-
color: white;
|
|
71
|
-
z-index: 10;
|
|
72
|
-
font-size: 2.4ex;
|
|
73
|
-
}
|
|
74
|
-
</style>
|