svelte-multiselect 10.1.0 → 10.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.
- package/dist/MultiSelect.svelte +11 -8
- package/dist/MultiSelect.svelte.d.ts +1 -1
- package/package.json +24 -24
- package/readme.md +7 -9
package/dist/MultiSelect.svelte
CHANGED
|
@@ -26,7 +26,7 @@ export let filterFunc = (opt, searchText) => {
|
|
|
26
26
|
return true;
|
|
27
27
|
return `${get_label(opt)}`.toLowerCase().includes(searchText.toLowerCase());
|
|
28
28
|
};
|
|
29
|
-
export let
|
|
29
|
+
export let closeDropdownOnSelect = `desktop`;
|
|
30
30
|
export let form_input = null;
|
|
31
31
|
export let highlightMatches = true;
|
|
32
32
|
export let id = null;
|
|
@@ -186,10 +186,13 @@ function add(option, event) {
|
|
|
186
186
|
selected = selected.sort(sortSelected);
|
|
187
187
|
}
|
|
188
188
|
}
|
|
189
|
-
|
|
189
|
+
const reached_max_select = selected.length === maxSelect;
|
|
190
|
+
const dropdown_should_close = closeDropdownOnSelect === true ||
|
|
191
|
+
(closeDropdownOnSelect === `desktop` && window_width < breakpoint);
|
|
192
|
+
if (reached_max_select || dropdown_should_close) {
|
|
190
193
|
close_dropdown(event);
|
|
191
|
-
|
|
192
|
-
|
|
194
|
+
}
|
|
195
|
+
else if (!dropdown_should_close) {
|
|
193
196
|
input?.focus();
|
|
194
197
|
}
|
|
195
198
|
dispatch(`add`, { option });
|
|
@@ -302,10 +305,10 @@ async function handle_keydown(event) {
|
|
|
302
305
|
}
|
|
303
306
|
}
|
|
304
307
|
function remove_all() {
|
|
305
|
-
selected = [];
|
|
306
|
-
searchText = ``;
|
|
307
308
|
dispatch(`removeAll`, { options: selected });
|
|
308
309
|
dispatch(`change`, { options: selected, type: `removeAll` });
|
|
310
|
+
selected = [];
|
|
311
|
+
searchText = ``;
|
|
309
312
|
}
|
|
310
313
|
$: is_selected = (label) => selected.map(get_label).includes(label);
|
|
311
314
|
const if_enter_or_space = (handler) => (event) => {
|
|
@@ -615,9 +618,9 @@ function highlight_matching_options(event) {
|
|
|
615
618
|
{#if searchText}
|
|
616
619
|
{@const text_input_is_duplicate = selected.map(get_label).includes(searchText)}
|
|
617
620
|
{@const is_dupe = !duplicates && text_input_is_duplicate && `dupe`}
|
|
618
|
-
{@const can_create = allowUserOptions && createOptionMsg && `create`}
|
|
621
|
+
{@const can_create = Boolean(allowUserOptions && createOptionMsg) && `create`}
|
|
619
622
|
{@const no_match =
|
|
620
|
-
matchingOptions?.length == 0 && noMatchingOptionsMsg && `no-match`}
|
|
623
|
+
Boolean(matchingOptions?.length == 0 && noMatchingOptionsMsg) && `no-match`}
|
|
621
624
|
{@const msgType = is_dupe || can_create || no_match}
|
|
622
625
|
{#if msgType}
|
|
623
626
|
{@const msg = {
|
|
@@ -17,7 +17,7 @@ declare class __sveltets_Render<Option extends T> {
|
|
|
17
17
|
duplicates?: boolean | undefined;
|
|
18
18
|
key?: ((opt: T) => unknown) | undefined;
|
|
19
19
|
filterFunc?: ((opt: Option, searchText: string) => boolean) | undefined;
|
|
20
|
-
|
|
20
|
+
closeDropdownOnSelect?: boolean | "desktop" | undefined;
|
|
21
21
|
form_input?: HTMLInputElement | null | undefined;
|
|
22
22
|
highlightMatches?: boolean | undefined;
|
|
23
23
|
id?: string | null | undefined;
|
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": "10.
|
|
8
|
+
"version": "10.2.0",
|
|
9
9
|
"type": "module",
|
|
10
10
|
"svelte": "./dist/index.js",
|
|
11
11
|
"bugs": "https://github.com/janosh/svelte-multiselect/issues",
|
|
@@ -23,37 +23,37 @@
|
|
|
23
23
|
"update-coverage": "vitest tests/unit --run --coverage && npx istanbul-badges-readme"
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
|
-
"svelte": "^4.0
|
|
26
|
+
"svelte": "^4.2.0"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
29
|
"@iconify/svelte": "^3.1.4",
|
|
30
|
-
"@playwright/test": "^1.
|
|
31
|
-
"@sveltejs/adapter-static": "^2.0.
|
|
32
|
-
"@sveltejs/kit": "^1.
|
|
33
|
-
"@sveltejs/package": "2.2.
|
|
34
|
-
"@sveltejs/vite-plugin-svelte": "2.4.
|
|
35
|
-
"@typescript-eslint/eslint-plugin": "^6.
|
|
36
|
-
"@typescript-eslint/parser": "^6.
|
|
37
|
-
"@vitest/coverage-v8": "^0.
|
|
38
|
-
"eslint": "^8.
|
|
39
|
-
"eslint-plugin-svelte": "^2.
|
|
40
|
-
"hastscript": "^
|
|
30
|
+
"@playwright/test": "^1.37.1",
|
|
31
|
+
"@sveltejs/adapter-static": "^2.0.3",
|
|
32
|
+
"@sveltejs/kit": "^1.24.1",
|
|
33
|
+
"@sveltejs/package": "2.2.2",
|
|
34
|
+
"@sveltejs/vite-plugin-svelte": "2.4.5",
|
|
35
|
+
"@typescript-eslint/eslint-plugin": "^6.7.0",
|
|
36
|
+
"@typescript-eslint/parser": "^6.7.0",
|
|
37
|
+
"@vitest/coverage-v8": "^0.34.4",
|
|
38
|
+
"eslint": "^8.49.0",
|
|
39
|
+
"eslint-plugin-svelte": "^2.33.1",
|
|
40
|
+
"hastscript": "^8.0.0",
|
|
41
41
|
"highlight.js": "^11.8.0",
|
|
42
42
|
"jsdom": "^22.1.0",
|
|
43
43
|
"mdsvex": "^0.11.0",
|
|
44
|
-
"mdsvexamples": "^0.
|
|
45
|
-
"prettier": "^
|
|
46
|
-
"prettier-plugin-svelte": "^
|
|
47
|
-
"rehype-autolink-headings": "^
|
|
48
|
-
"rehype-slug": "^
|
|
49
|
-
"svelte-check": "^3.
|
|
44
|
+
"mdsvexamples": "^0.4.1",
|
|
45
|
+
"prettier": "^3.0.3",
|
|
46
|
+
"prettier-plugin-svelte": "^3.0.3",
|
|
47
|
+
"rehype-autolink-headings": "^7.0.0",
|
|
48
|
+
"rehype-slug": "^6.0.0",
|
|
49
|
+
"svelte-check": "^3.5.1",
|
|
50
50
|
"svelte-preprocess": "^5.0.4",
|
|
51
|
-
"svelte-toc": "^0.5.
|
|
51
|
+
"svelte-toc": "^0.5.6",
|
|
52
52
|
"svelte-zoo": "^0.4.9",
|
|
53
|
-
"svelte2tsx": "^0.6.
|
|
54
|
-
"typescript": "5.
|
|
55
|
-
"vite": "^4.4.
|
|
56
|
-
"vitest": "^0.
|
|
53
|
+
"svelte2tsx": "^0.6.21",
|
|
54
|
+
"typescript": "5.2.2",
|
|
55
|
+
"vite": "^4.4.9",
|
|
56
|
+
"vitest": "^0.34.4"
|
|
57
57
|
},
|
|
58
58
|
"keywords": [
|
|
59
59
|
"svelte",
|
package/readme.md
CHANGED
|
@@ -194,10 +194,10 @@ Full list of props/bindable variables for this component. The `Option` type you
|
|
|
194
194
|
Customize how dropdown options are filtered when user enters search string into `<MultiSelect />`. Defaults to:
|
|
195
195
|
|
|
196
196
|
1. ```ts
|
|
197
|
-
|
|
197
|
+
closeDropdownOnSelect: boolean | 'desktop' = `desktop`
|
|
198
198
|
```
|
|
199
199
|
|
|
200
|
-
One of `true`, `false` or `'desktop'`. Whether to
|
|
200
|
+
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.
|
|
201
201
|
|
|
202
202
|
1. ```ts
|
|
203
203
|
form_input: HTMLInputElement | null = null
|
|
@@ -397,13 +397,11 @@ Full list of props/bindable variables for this component. The `Option` type you
|
|
|
397
397
|
1. `slot="disabled-icon"`: Custom icon to display inside the input when in `disabled` state. Receives no props. Use an empty `<span slot="disabled-icon" />` or `div` to remove the default disabled icon.
|
|
398
398
|
1. `slot="expand-icon"`: 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.
|
|
399
399
|
1. `slot="remove-icon"`: 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.
|
|
400
|
-
1. `slot="user-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).
|
|
401
|
-
- `
|
|
402
|
-
- `
|
|
403
|
-
- `
|
|
404
|
-
|
|
405
|
-
- `msg: string`: `duplicateOptionMsg` if user input is a duplicate else `createOptionMsg`.
|
|
406
|
-
1. `slot='after-input'`: ForPlaced after the search input. For arbitrary content like icons or temporary messages. Receives props `selected`, `disabled`, `invalid`, `id`, `placeholder`, `open`, `required`.
|
|
400
|
+
1. `slot="user-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:
|
|
401
|
+
- `searchText`: The text user typed into search input.
|
|
402
|
+
- `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.
|
|
403
|
+
- `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 slot replaces the default UI for displaying these messages so the slot needs to render them instead (unless purposely not showing a message).
|
|
404
|
+
1. `slot='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.
|
|
407
405
|
|
|
408
406
|
Example using several slots:
|
|
409
407
|
|