svelte-multiselect 11.0.0-rc.1 → 11.1.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/dist/CircleSpinner.svelte +3 -4
- package/dist/CircleSpinner.svelte.d.ts +7 -19
- package/dist/CmdPalette.svelte +19 -37
- package/dist/CmdPalette.svelte.d.ts +19 -32
- package/dist/MultiSelect.svelte +322 -288
- package/dist/MultiSelect.svelte.d.ts +16 -105
- package/dist/Wiggle.svelte +10 -19
- package/dist/Wiggle.svelte.d.ts +14 -26
- package/dist/icons/ChevronExpand.svelte +5 -1
- package/dist/icons/ChevronExpand.svelte.d.ts +4 -25
- package/dist/icons/Cross.svelte +6 -2
- package/dist/icons/Cross.svelte.d.ts +4 -25
- package/dist/icons/Disabled.svelte +5 -1
- package/dist/icons/Disabled.svelte.d.ts +4 -25
- package/dist/icons/Octocat.svelte +5 -1
- package/dist/icons/Octocat.svelte.d.ts +4 -25
- package/dist/index.d.ts +2 -1
- package/dist/index.js +9 -7
- package/dist/props.d.ts +143 -0
- package/dist/props.js +1 -0
- package/dist/types.d.ts +0 -40
- package/dist/utils.d.ts +22 -3
- package/dist/utils.js +60 -3
- package/package.json +34 -31
- package/readme.md +45 -66
package/dist/utils.js
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Get the label key from an option object or the option itself if it's a string or number
|
|
3
|
+
* @param opt Option
|
|
4
|
+
* @returns Label
|
|
5
|
+
*/
|
|
2
6
|
export const get_label = (opt) => {
|
|
3
7
|
if (opt instanceof Object) {
|
|
4
8
|
if (opt.label === undefined) {
|
|
@@ -8,8 +12,13 @@ export const get_label = (opt) => {
|
|
|
8
12
|
}
|
|
9
13
|
return `${opt}`;
|
|
10
14
|
};
|
|
11
|
-
|
|
12
|
-
|
|
15
|
+
/**
|
|
16
|
+
* This function is used extract CSS strings from a {selected, option} style object to be used in the style attribute of the option.
|
|
17
|
+
* If the style is a string, it will be returned as is
|
|
18
|
+
* @param option Option
|
|
19
|
+
* @param key
|
|
20
|
+
* @returns CSS string
|
|
21
|
+
*/
|
|
13
22
|
export function get_style(option, key = null) {
|
|
14
23
|
let css_str = ``;
|
|
15
24
|
if (![`selected`, `option`, null].includes(key)) {
|
|
@@ -32,3 +41,51 @@ export function get_style(option, key = null) {
|
|
|
32
41
|
css_str += `;`;
|
|
33
42
|
return css_str;
|
|
34
43
|
}
|
|
44
|
+
/**
|
|
45
|
+
* Highlights text nodes that matching the string query
|
|
46
|
+
* @param element Parent element
|
|
47
|
+
* @param query Search query
|
|
48
|
+
* @param noMatchingOptionsMsg Text for empty node
|
|
49
|
+
*/
|
|
50
|
+
export function highlight_matching_nodes(element, query, noMatchingOptionsMsg) {
|
|
51
|
+
if (typeof CSS == `undefined` || !CSS.highlights || !query)
|
|
52
|
+
return; // abort if CSS highlight API not supported
|
|
53
|
+
// clear previous ranges from HighlightRegistry
|
|
54
|
+
CSS.highlights.clear();
|
|
55
|
+
const tree_walker = document.createTreeWalker(element, NodeFilter.SHOW_TEXT, {
|
|
56
|
+
acceptNode: (node) => {
|
|
57
|
+
// don't highlight text in the "no matching options" message
|
|
58
|
+
if (node?.textContent === noMatchingOptionsMsg)
|
|
59
|
+
return NodeFilter.FILTER_REJECT;
|
|
60
|
+
return NodeFilter.FILTER_ACCEPT;
|
|
61
|
+
},
|
|
62
|
+
});
|
|
63
|
+
const text_nodes = [];
|
|
64
|
+
let current_node = tree_walker.nextNode();
|
|
65
|
+
while (current_node) {
|
|
66
|
+
text_nodes.push(current_node);
|
|
67
|
+
current_node = tree_walker.nextNode();
|
|
68
|
+
}
|
|
69
|
+
// iterate over all text nodes and find matches
|
|
70
|
+
const ranges = text_nodes.map((el) => {
|
|
71
|
+
const text = el.textContent?.toLowerCase();
|
|
72
|
+
const indices = [];
|
|
73
|
+
let start_pos = 0;
|
|
74
|
+
while (text && start_pos < text.length) {
|
|
75
|
+
const index = text.indexOf(query, start_pos);
|
|
76
|
+
if (index === -1)
|
|
77
|
+
break;
|
|
78
|
+
indices.push(index);
|
|
79
|
+
start_pos = index + query.length;
|
|
80
|
+
}
|
|
81
|
+
// create range object for each str found in the text node
|
|
82
|
+
return indices.map((index) => {
|
|
83
|
+
const range = new Range();
|
|
84
|
+
range.setStart(el, index);
|
|
85
|
+
range.setEnd(el, index + query.length);
|
|
86
|
+
return range;
|
|
87
|
+
});
|
|
88
|
+
});
|
|
89
|
+
// create Highlight object from ranges and add to registry
|
|
90
|
+
CSS.highlights.set(`sms-search-matches`, new Highlight(...ranges.flat()));
|
|
91
|
+
}
|
package/package.json
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
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.1.0",
|
|
9
9
|
"type": "module",
|
|
10
10
|
"svelte": "./dist/index.js",
|
|
11
11
|
"bugs": "https://github.com/janosh/svelte-multiselect/issues",
|
|
@@ -15,46 +15,49 @@
|
|
|
15
15
|
"preview": "vite preview",
|
|
16
16
|
"package": "svelte-package",
|
|
17
17
|
"serve": "vite build && vite preview",
|
|
18
|
-
"check": "svelte-check
|
|
19
|
-
"test": "vitest
|
|
18
|
+
"check": "svelte-check src",
|
|
19
|
+
"test": "vitest run && playwright test",
|
|
20
20
|
"test:unit": "vitest tests/unit/*.ts",
|
|
21
21
|
"test:e2e": "playwright test tests/*.test.ts",
|
|
22
22
|
"changelog": "npx auto-changelog --package --output changelog.md --hide-empty-releases --hide-credit --commit-limit false",
|
|
23
23
|
"update-coverage": "vitest tests/unit --run --coverage && npx istanbul-badges-readme"
|
|
24
24
|
},
|
|
25
|
-
"
|
|
26
|
-
"svelte": "
|
|
25
|
+
"peerDependencies": {
|
|
26
|
+
"svelte": "^5.8.0"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
|
-
"@iconify/svelte": "^
|
|
30
|
-
"@playwright/test": "^1.
|
|
31
|
-
"@
|
|
32
|
-
"@sveltejs/
|
|
33
|
-
"@sveltejs/
|
|
34
|
-
"@sveltejs/
|
|
35
|
-
"@
|
|
36
|
-
"
|
|
37
|
-
"
|
|
38
|
-
"
|
|
39
|
-
"
|
|
40
|
-
"
|
|
41
|
-
"
|
|
42
|
-
"
|
|
43
|
-
"
|
|
44
|
-
"
|
|
45
|
-
"
|
|
29
|
+
"@iconify/svelte": "^5.0.0",
|
|
30
|
+
"@playwright/test": "^1.52.0",
|
|
31
|
+
"@stylistic/eslint-plugin": "^4.2.0",
|
|
32
|
+
"@sveltejs/adapter-static": "^3.0.8",
|
|
33
|
+
"@sveltejs/kit": "^2.21.0",
|
|
34
|
+
"@sveltejs/package": "2.3.11",
|
|
35
|
+
"@sveltejs/vite-plugin-svelte": "^5.0.3",
|
|
36
|
+
"@types/node": "^22.15.18",
|
|
37
|
+
"@vitest/coverage-v8": "^3.1.3",
|
|
38
|
+
"eslint": "^9.26.0",
|
|
39
|
+
"eslint-plugin-svelte": "^3.6.0",
|
|
40
|
+
"globals": "^16.1.0",
|
|
41
|
+
"hastscript": "^9.0.1",
|
|
42
|
+
"highlight.js": "^11.11.1",
|
|
43
|
+
"jsdom": "^26.1.0",
|
|
44
|
+
"mdsvex": "^0.12.6",
|
|
45
|
+
"mdsvexamples": "^0.5.0",
|
|
46
|
+
"prettier": "^3.5.3",
|
|
47
|
+
"prettier-plugin-svelte": "^3.4.0",
|
|
46
48
|
"rehype-autolink-headings": "^7.1.0",
|
|
47
49
|
"rehype-slug": "^6.0.0",
|
|
48
|
-
"svelte
|
|
49
|
-
"svelte-
|
|
50
|
+
"svelte": "^5.30.1",
|
|
51
|
+
"svelte-check": "^4.2.1",
|
|
52
|
+
"svelte-multiselect": "11.0.0-rc.1",
|
|
50
53
|
"svelte-preprocess": "^6.0.3",
|
|
51
|
-
"svelte-toc": "^0.
|
|
52
|
-
"svelte-zoo": "^0.4.
|
|
53
|
-
"svelte2tsx": "^0.7.
|
|
54
|
-
"typescript": "5.
|
|
55
|
-
"typescript-eslint": "^8.
|
|
56
|
-
"vite": "^
|
|
57
|
-
"vitest": "^
|
|
54
|
+
"svelte-toc": "^0.6.0",
|
|
55
|
+
"svelte-zoo": "^0.4.18",
|
|
56
|
+
"svelte2tsx": "^0.7.39",
|
|
57
|
+
"typescript": "5.8.3",
|
|
58
|
+
"typescript-eslint": "^8.32.1",
|
|
59
|
+
"vite": "^6.3.5",
|
|
60
|
+
"vitest": "^3.1.3"
|
|
58
61
|
},
|
|
59
62
|
"keywords": [
|
|
60
63
|
"svelte",
|
package/readme.md
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
[](https://github.com/janosh/svelte-multiselect/actions/workflows/test.yml)
|
|
9
9
|
[](https://github.com/janosh/svelte-multiselect/actions/workflows/gh-pages.yml)
|
|
10
10
|
[](https://npmjs.com/package/svelte-multiselect)
|
|
11
|
-
[](https://github.com/sveltejs/svelte/blob/master/packages/svelte/CHANGELOG.md)
|
|
11
|
+
[](https://github.com/sveltejs/svelte/blob/master/packages/svelte/CHANGELOG.md)
|
|
12
12
|
[](https://svelte.dev/repl/a5a14b8f15d64cb083b567292480db05)
|
|
13
13
|
[](https://stackblitz.com/github/janosh/svelte-multiselect)
|
|
14
14
|
|
|
@@ -40,34 +40,6 @@
|
|
|
40
40
|
| ------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------ | -------------------------------------------------------------------------------- |
|
|
41
41
|
|  |  |  |
|
|
42
42
|
|
|
43
|
-
## 📜   Breaking changes
|
|
44
|
-
|
|
45
|
-
- **8.0.0** (2022-10-22)
|
|
46
|
-
- Props `selectedLabels` and `selectedValues` were removed. If you were using them, they were equivalent to assigning `bind:selected` to a local variable and then running `selectedLabels = selected.map(option => option.label)` and `selectedValues = selected.map(option => option.value)` if your options were objects with `label` and `value` keys. If they were simple strings/numbers, there was no point in using `selected{Labels,Values}` anyway. [PR 138](https://github.com/janosh/svelte-multiselect/pull/138)
|
|
47
|
-
- Prop `noOptionsMsg` was renamed to `noMatchingOptionsMsg`. [PR 133](https://github.com/janosh/svelte-multiselect/pull/133).
|
|
48
|
-
- **v8.3.0** (2023-01-25) `addOptionMsg` was renamed to `createOptionMsg` (no major since version since it's rarely used) [sha](https://github.com/janosh/svelte-multiselect/commits).
|
|
49
|
-
- **v9.0.0** (2023-06-01) Svelte bumped from v3 to v4. Also, not breaking but noteworthy: MultiSelect received a default slot that functions as both `"option"` and `"selected"`. If you previously had two identical slots for `"option"` and `"selected"`, you can now remove the `name` from one of them and drop the other:
|
|
50
|
-
|
|
51
|
-
```diff
|
|
52
|
-
<MultiSelect
|
|
53
|
-
{options}
|
|
54
|
-
+ let:option
|
|
55
|
-
>
|
|
56
|
-
- <SlotComponent let:option {option} slot="selected" />
|
|
57
|
-
- <SlotComponent let:option {option} slot="option" />
|
|
58
|
-
+ <SlotComponent {option} />
|
|
59
|
-
</MultiSelect>
|
|
60
|
-
```
|
|
61
|
-
|
|
62
|
-
- **v10.0.0** (2023-06-23) `duplicateFunc()` renamed to `key` in [#238](https://github.com/janosh/svelte-multiselect/pull/238). Signature changed:
|
|
63
|
-
|
|
64
|
-
```diff
|
|
65
|
-
- duplicateFunc: (op1: T, op2: T) => boolean = (op1, op2) => `${get_label(op1)}`.toLowerCase() === `${get_label(op2)}`.toLowerCase()
|
|
66
|
-
+ key: (opt: T) => unknown = (opt) => `${get_label(opt)}`.toLowerCase()
|
|
67
|
-
```
|
|
68
|
-
|
|
69
|
-
Rather than implementing custom equality in `duplicateFunc`, the `key` function is now expected to map options to a unique identifier. `key(op1) === key(op2)` should mean `op1` and `op2` are the same option. `key` can return any type but usually best to return primitives (`string`, `number`, ...) for Svelte keyed each blocks (see [#217](https://github.com/janosh/svelte-multiselect/pull/217)).
|
|
70
|
-
|
|
71
43
|
## 🔨   Installation
|
|
72
44
|
|
|
73
45
|
```sh
|
|
@@ -84,7 +56,7 @@ yarn add --dev svelte-multiselect
|
|
|
84
56
|
|
|
85
57
|
const ui_libs = [`Svelte`, `React`, `Vue`, `Angular`, `...`]
|
|
86
58
|
|
|
87
|
-
let selected = []
|
|
59
|
+
let selected = $state([])
|
|
88
60
|
</script>
|
|
89
61
|
|
|
90
62
|
Favorite Frontend Tools?
|
|
@@ -123,7 +95,7 @@ Full list of props/bindable variables for this component. The `Option` type you
|
|
|
123
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`.
|
|
124
96
|
|
|
125
97
|
1. ```ts
|
|
126
|
-
allowUserOptions: boolean |
|
|
98
|
+
allowUserOptions: boolean | `append` = false
|
|
127
99
|
```
|
|
128
100
|
|
|
129
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.
|
|
@@ -194,7 +166,7 @@ Full list of props/bindable variables for this component. The `Option` type you
|
|
|
194
166
|
Customize how dropdown options are filtered when user enters search string into `<MultiSelect />`. Defaults to:
|
|
195
167
|
|
|
196
168
|
1. ```ts
|
|
197
|
-
closeDropdownOnSelect: boolean |
|
|
169
|
+
closeDropdownOnSelect: boolean | `desktop` = `desktop`
|
|
198
170
|
```
|
|
199
171
|
|
|
200
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.
|
|
@@ -257,7 +229,7 @@ Full list of props/bindable variables for this component. The `Option` type you
|
|
|
257
229
|
loading: boolean = false
|
|
258
230
|
```
|
|
259
231
|
|
|
260
|
-
Whether the component should display a spinner to indicate it's in loading state. Use
|
|
232
|
+
Whether the component should display a spinner to indicate it's in loading state. Use `{#snippet spinner()} ... {/snippet}` to specify a custom spinner.
|
|
261
233
|
|
|
262
234
|
1. ```ts
|
|
263
235
|
matchingOptions: Option[] = []
|
|
@@ -334,7 +306,7 @@ Full list of props/bindable variables for this component. The `Option` type you
|
|
|
334
306
|
parseLabelsAsHtml: boolean = false
|
|
335
307
|
```
|
|
336
308
|
|
|
337
|
-
Whether option labels should be passed to [Svelte's `@html` directive](https://svelte.dev/tutorial/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).
|
|
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).
|
|
338
310
|
|
|
339
311
|
1. ```ts
|
|
340
312
|
pattern: string | null = null
|
|
@@ -423,35 +395,42 @@ Full list of props/bindable variables for this component. The `Option` type you
|
|
|
423
395
|
|
|
424
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!
|
|
425
397
|
|
|
426
|
-
## 🎰  
|
|
398
|
+
## 🎰   Snippets
|
|
427
399
|
|
|
428
|
-
`MultiSelect.svelte` accepts the following named
|
|
400
|
+
`MultiSelect.svelte` accepts the following named snippets:
|
|
429
401
|
|
|
430
|
-
1.
|
|
431
|
-
1.
|
|
432
|
-
1.
|
|
433
|
-
1.
|
|
434
|
-
1.
|
|
435
|
-
1.
|
|
436
|
-
1.
|
|
402
|
+
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.
|
|
403
|
+
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.
|
|
404
|
+
1. `#snippet spinner()`: Custom spinner component to display when in `loading` state. Receives no props.
|
|
405
|
+
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.
|
|
406
|
+
1. `#snippet expandIcon()`: Allows setting a custom icon to indicate to users that the Multiselect text input field is expandable into a dropdown list. Receives prop `open: boolean` which is true if the Multiselect dropdown is visible and false if it's hidden.
|
|
407
|
+
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.
|
|
408
|
+
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:
|
|
437
409
|
- `searchText`: The text user typed into search input.
|
|
438
410
|
- `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.
|
|
439
|
-
- `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
|
|
440
|
-
1. `
|
|
411
|
+
- `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).
|
|
412
|
+
1. `snippet='after-input'`: Placed after the search input. For arbitrary content like icons or temporary messages. Receives props `selected: Option[]`, `disabled: boolean`, `invalid: boolean`, `id: string | null`, `placeholder: string`, `open: boolean`, `required: boolean`. Can serve as a more dynamic, more customizable alternative to the `placeholder` prop.
|
|
441
413
|
|
|
442
|
-
Example using several
|
|
414
|
+
Example using several snippets:
|
|
443
415
|
|
|
444
416
|
```svelte
|
|
445
|
-
<MultiSelect options={[`Red`, `Green`, `Blue`, `Yellow`, `Purple`]}
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
417
|
+
<MultiSelect options={[`Red`, `Green`, `Blue`, `Yellow`, `Purple`]}>
|
|
418
|
+
{#snippet children({ idx, option })}
|
|
419
|
+
<span style="display: flex; align-items: center; gap: 6pt;">
|
|
420
|
+
<span
|
|
421
|
+
style:background={`${option}`}
|
|
422
|
+
style="border-radius: 50%; width: 1em; height: 1em;"
|
|
423
|
+
></span>
|
|
424
|
+
{idx + 1}
|
|
425
|
+
{option}
|
|
426
|
+
</span>
|
|
427
|
+
{/snippet}
|
|
428
|
+
{#snippet spinner()}
|
|
429
|
+
<CustomSpinner />
|
|
430
|
+
{/snippet}
|
|
431
|
+
{#snippet removeIcon()}
|
|
432
|
+
<strong>X</strong>
|
|
433
|
+
{/snippet}
|
|
455
434
|
</MultiSelect>
|
|
456
435
|
```
|
|
457
436
|
|
|
@@ -460,37 +439,37 @@ Example using several slots:
|
|
|
460
439
|
`MultiSelect.svelte` dispatches the following events:
|
|
461
440
|
|
|
462
441
|
1. ```ts
|
|
463
|
-
|
|
442
|
+
onadd={(event) => console.log(event.detail.option)}
|
|
464
443
|
```
|
|
465
444
|
|
|
466
445
|
Triggers when a new option is selected. The newly selected option is provided as `event.detail.option`.
|
|
467
446
|
|
|
468
447
|
1. ```ts
|
|
469
|
-
|
|
448
|
+
onremove={(event) => console.log(event.detail.option)}`
|
|
470
449
|
```
|
|
471
450
|
|
|
472
451
|
Triggers when a single selected option is removed. The removed option is provided as `event.detail.option`.
|
|
473
452
|
|
|
474
453
|
1. ```ts
|
|
475
|
-
|
|
454
|
+
onremoveAll={(event) => console.log(event.detail.options)}`
|
|
476
455
|
```
|
|
477
456
|
|
|
478
457
|
Triggers when all selected options are removed. The payload `event.detail.options` gives the options that were previously selected.
|
|
479
458
|
|
|
480
459
|
1. ```ts
|
|
481
|
-
|
|
460
|
+
onchange={(event) => console.log(`${event.detail.type}: '${event.detail.option}'`)}
|
|
482
461
|
```
|
|
483
462
|
|
|
484
463
|
Triggers when an option is either added (selected) or removed from selected, or all selected options are removed at once. `type` is one of `'add' | 'remove' | 'removeAll'` and payload will be `option: Option` or `options: Option[]`, respectively.
|
|
485
464
|
|
|
486
465
|
1. ```ts
|
|
487
|
-
|
|
466
|
+
onopen={(event) => console.log(`Multiselect dropdown was opened by ${event}`)}
|
|
488
467
|
```
|
|
489
468
|
|
|
490
469
|
Triggers when the dropdown list of options appears. Event is the DOM's `FocusEvent`,`KeyboardEvent` or `ClickEvent` that initiated this Svelte `dispatch` event.
|
|
491
470
|
|
|
492
471
|
1. ```ts
|
|
493
|
-
|
|
472
|
+
onclose={(event) => console.log(`Multiselect dropdown was closed by ${event}`)}
|
|
494
473
|
```
|
|
495
474
|
|
|
496
475
|
Triggers when the dropdown list of options disappears. Event is the DOM's `FocusEvent`, `KeyboardEvent` or `ClickEvent` that initiated this Svelte `dispatch` event.
|
|
@@ -499,7 +478,7 @@ For example, here's how you might annoy your users with an alert every time one
|
|
|
499
478
|
|
|
500
479
|
```svelte
|
|
501
480
|
<MultiSelect
|
|
502
|
-
|
|
481
|
+
onchange={(e) => {
|
|
503
482
|
if (e.detail.type === 'add') alert(`You added ${e.detail.option}`)
|
|
504
483
|
if (e.detail.type === 'remove') alert(`You removed ${e.detail.option}`)
|
|
505
484
|
if (e.detail.type === 'removeAll') alert(`You removed ${e.detail.options}`)
|
|
@@ -509,12 +488,12 @@ For example, here's how you might annoy your users with an alert every time one
|
|
|
509
488
|
|
|
510
489
|
> Note: Depending on the data passed to the component the `options(s)` payload will either be objects or simple strings/numbers.
|
|
511
490
|
|
|
512
|
-
The above list of events are [Svelte `dispatch` events](https://svelte.dev/tutorial/component-events). 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:
|
|
491
|
+
The above list of events are [Svelte `dispatch` events](https://svelte.dev/tutorial/svelte/component-events). 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:
|
|
513
492
|
|
|
514
493
|
```svelte
|
|
515
494
|
<MultiSelect
|
|
516
495
|
options={[1, 2, 3]}
|
|
517
|
-
|
|
496
|
+
onkeyup={(event) => console.log('key', event.target.value)}
|
|
518
497
|
/>
|
|
519
498
|
```
|
|
520
499
|
|
|
@@ -534,7 +513,7 @@ const options = [42, 69]
|
|
|
534
513
|
// type Option = number
|
|
535
514
|
```
|
|
536
515
|
|
|
537
|
-
The inferred type of `Option` is used to enforce type-safety on derived props like `selected` as well as
|
|
516
|
+
The inferred type of `Option` is used to enforce type-safety on derived props like `selected` as well as snippets. E.g. you'll get an error when trying to use a snippet that expects a string if your options are objects (see [this comment](https://github.com/janosh/svelte-multiselect/pull/189/files#r1058853697) for example screenshots).
|
|
538
517
|
|
|
539
518
|
You can also import [the types this component uses](https://github.com/janosh/svelte-multiselect/blob/main/src/lib/index.ts) for downstream applications:
|
|
540
519
|
|