svelte-multiselect 8.6.1 โ 9.0.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/CmdPalette.svelte +10 -14
- package/dist/CmdPalette.svelte.d.ts +3 -4
- package/dist/MultiSelect.svelte +44 -19
- package/dist/MultiSelect.svelte.d.ts +14 -8
- package/dist/index.d.ts +1 -51
- package/dist/index.js +1 -0
- package/dist/types.d.ts +51 -0
- package/dist/types.js +1 -0
- package/package.json +16 -16
- package/readme.md +25 -18
package/dist/CmdPalette.svelte
CHANGED
|
@@ -2,26 +2,26 @@
|
|
|
2
2
|
// https://github.com/sveltejs/eslint-plugin-svelte3/issues/201
|
|
3
3
|
import { tick } from 'svelte';
|
|
4
4
|
import { fade } from 'svelte/transition';
|
|
5
|
-
import Select from '.';
|
|
5
|
+
import Select from './MultiSelect.svelte';
|
|
6
6
|
export let actions;
|
|
7
|
-
export let
|
|
7
|
+
export let triggers = [`k`];
|
|
8
|
+
export let close_keys = [`Escape`];
|
|
8
9
|
export let fade_duration = 200; // in ms
|
|
9
10
|
export let style = ``; // for dialog
|
|
10
|
-
// for span in option slot, has no effect when passing slot
|
|
11
|
+
// for span in option slot, has no effect when passing a slot
|
|
11
12
|
export let span_style = ``;
|
|
12
13
|
export let open = false;
|
|
13
14
|
export let dialog = null;
|
|
14
15
|
export let input = null;
|
|
15
16
|
export let placeholder = `Filter actions...`;
|
|
16
17
|
async function toggle(event) {
|
|
17
|
-
if (event.key
|
|
18
|
+
if (triggers.includes(event.key) && event.metaKey && !open) {
|
|
18
19
|
// open on cmd+trigger
|
|
19
20
|
open = true;
|
|
20
21
|
await tick(); // wait for dialog to open and input to be mounted
|
|
21
22
|
input?.focus();
|
|
22
23
|
}
|
|
23
|
-
else if (event.key
|
|
24
|
-
// close on escape
|
|
24
|
+
else if (close_keys.includes(event.key) && open) {
|
|
25
25
|
open = false;
|
|
26
26
|
}
|
|
27
27
|
}
|
|
@@ -39,22 +39,18 @@ function run_and_close(event) {
|
|
|
39
39
|
<svelte:window on:keydown={toggle} on:click={close_if_outside} />
|
|
40
40
|
|
|
41
41
|
{#if open}
|
|
42
|
-
<dialog
|
|
43
|
-
class:open
|
|
44
|
-
bind:this={dialog}
|
|
45
|
-
transition:fade={{ duration: fade_duration }}
|
|
46
|
-
{style}
|
|
47
|
-
>
|
|
42
|
+
<dialog open bind:this={dialog} transition:fade={{ duration: fade_duration }} {style}>
|
|
48
43
|
<Select
|
|
49
44
|
options={actions}
|
|
50
45
|
bind:input
|
|
51
46
|
{placeholder}
|
|
52
47
|
on:add={run_and_close}
|
|
53
48
|
on:keydown={toggle}
|
|
54
|
-
{...$$
|
|
49
|
+
{...$$restProps}
|
|
50
|
+
let:option
|
|
55
51
|
>
|
|
56
52
|
<!-- wait for https://github.com/sveltejs/svelte/pull/8304 -->
|
|
57
|
-
<slot
|
|
53
|
+
<slot>
|
|
58
54
|
<span style={span_style}>{option.label}</span>
|
|
59
55
|
</slot>
|
|
60
56
|
</Select>
|
|
@@ -6,7 +6,8 @@ declare const __propDef: {
|
|
|
6
6
|
label: string;
|
|
7
7
|
action: () => void;
|
|
8
8
|
}[];
|
|
9
|
-
|
|
9
|
+
triggers?: string[] | undefined;
|
|
10
|
+
close_keys?: string[] | undefined;
|
|
10
11
|
fade_duration?: number | undefined;
|
|
11
12
|
style?: string | undefined;
|
|
12
13
|
span_style?: string | undefined;
|
|
@@ -19,9 +20,7 @@ declare const __propDef: {
|
|
|
19
20
|
[evt: string]: CustomEvent<any>;
|
|
20
21
|
};
|
|
21
22
|
slots: {
|
|
22
|
-
|
|
23
|
-
slot: string;
|
|
24
|
-
};
|
|
23
|
+
default: {};
|
|
25
24
|
};
|
|
26
25
|
};
|
|
27
26
|
export type CmdPaletteProps = typeof __propDef.props;
|
package/dist/MultiSelect.svelte
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<script>import { createEventDispatcher, tick } from 'svelte';
|
|
2
2
|
import { flip } from 'svelte/animate';
|
|
3
|
-
import
|
|
3
|
+
import CircleSpinner from './CircleSpinner.svelte';
|
|
4
|
+
import Wiggle from './Wiggle.svelte';
|
|
4
5
|
import { CrossIcon, DisabledIcon, ExpandIcon } from './icons';
|
|
5
6
|
export let activeIndex = null;
|
|
6
7
|
export let activeOption = null;
|
|
@@ -63,7 +64,7 @@ export let ulOptionsClass = ``;
|
|
|
63
64
|
export let ulSelectedClass = ``;
|
|
64
65
|
export let value = null;
|
|
65
66
|
// get the label key from an option object or the option itself if it's a string or number
|
|
66
|
-
const get_label = (op) => {
|
|
67
|
+
export const get_label = (op) => {
|
|
67
68
|
if (op instanceof Object) {
|
|
68
69
|
if (op.label === undefined) {
|
|
69
70
|
console.error(`MultiSelect option ${JSON.stringify(op)} is an object but has no label key`);
|
|
@@ -103,8 +104,8 @@ if (sortSelected && selectedOptionsDraggable) {
|
|
|
103
104
|
console.warn(`MultiSelect's sortSelected and selectedOptionsDraggable should not be combined as any ` +
|
|
104
105
|
`user re-orderings of selected options will be undone by sortSelected on component re-renders.`);
|
|
105
106
|
}
|
|
106
|
-
if (allowUserOptions && !createOptionMsg) {
|
|
107
|
-
console.error(`MultiSelect
|
|
107
|
+
if (allowUserOptions && !createOptionMsg && createOptionMsg !== null) {
|
|
108
|
+
console.error(`MultiSelect has allowUserOptions=${allowUserOptions} but createOptionMsg=${createOptionMsg} is falsy. ` +
|
|
108
109
|
`This prevents the "Add option" <span> from showing up, resulting in a confusing user experience.`);
|
|
109
110
|
}
|
|
110
111
|
const dispatch = createEventDispatcher();
|
|
@@ -190,20 +191,22 @@ function add(option, event) {
|
|
|
190
191
|
}
|
|
191
192
|
}
|
|
192
193
|
// remove an option from selected list
|
|
193
|
-
function remove(
|
|
194
|
+
function remove(to_remove) {
|
|
194
195
|
if (selected.length === 0)
|
|
195
196
|
return;
|
|
196
|
-
|
|
197
|
+
const idx = selected.findIndex((op) => JSON.stringify(op) === JSON.stringify(to_remove));
|
|
198
|
+
let [option] = selected.splice(idx, 1); // remove option from selected list
|
|
197
199
|
if (option === undefined && allowUserOptions) {
|
|
198
200
|
// if option with label could not be found but allowUserOptions is truthy,
|
|
199
201
|
// assume it was created by user and create corresponding option object
|
|
200
202
|
// on the fly for use as event payload
|
|
201
|
-
|
|
203
|
+
const other_ops_type = typeof options[0];
|
|
204
|
+
option = (other_ops_type ? { label: to_remove } : to_remove);
|
|
202
205
|
}
|
|
203
206
|
if (option === undefined) {
|
|
204
|
-
return console.error(`Multiselect can't remove selected option ${
|
|
207
|
+
return console.error(`Multiselect can't remove selected option ${JSON.stringify(to_remove)}, not found in selected list`);
|
|
205
208
|
}
|
|
206
|
-
selected = selected
|
|
209
|
+
selected = [...selected]; // trigger Svelte rerender
|
|
207
210
|
invalid = false; // reset error status whenever items are removed
|
|
208
211
|
form_input?.setCustomValidity(``);
|
|
209
212
|
dispatch(`remove`, { option });
|
|
@@ -336,6 +339,7 @@ const dragstart = (idx) => (event) => {
|
|
|
336
339
|
event.dataTransfer.setData(`text/plain`, `${idx}`);
|
|
337
340
|
};
|
|
338
341
|
let ul_options;
|
|
342
|
+
// highlight text matching user-entered search text in available options
|
|
339
343
|
function highlight_matching_options(event) {
|
|
340
344
|
if (!highlightMatches || typeof CSS == `undefined` || !CSS.highlights)
|
|
341
345
|
return; // don't try if CSS highlight API not supported
|
|
@@ -401,6 +405,8 @@ function highlight_matching_options(event) {
|
|
|
401
405
|
on:mouseup|stopPropagation={open_dropdown}
|
|
402
406
|
title={disabled ? disabledInputTitle : null}
|
|
403
407
|
data-id={id}
|
|
408
|
+
role="searchbox"
|
|
409
|
+
tabindex="-1"
|
|
404
410
|
>
|
|
405
411
|
<!-- bind:value={selected} prevents form submission if required prop is true and no options are selected -->
|
|
406
412
|
<input
|
|
@@ -432,6 +438,8 @@ function highlight_matching_options(event) {
|
|
|
432
438
|
{#each selected as option, idx (option)}
|
|
433
439
|
<li
|
|
434
440
|
class={liSelectedClass}
|
|
441
|
+
role="option"
|
|
442
|
+
aria-selected="true"
|
|
435
443
|
animate:flip={{ duration: 100 }}
|
|
436
444
|
draggable={selectedOptionsDraggable && !disabled && selected.length > 1}
|
|
437
445
|
on:dragstart={dragstart(idx)}
|
|
@@ -442,10 +450,13 @@ function highlight_matching_options(event) {
|
|
|
442
450
|
>
|
|
443
451
|
<!-- on:dragover|preventDefault needed for the drop to succeed https://stackoverflow.com/a/31085796 -->
|
|
444
452
|
<slot name="selected" {option} {idx}>
|
|
445
|
-
{
|
|
446
|
-
{
|
|
447
|
-
|
|
448
|
-
{
|
|
453
|
+
<slot {option} {idx}>
|
|
454
|
+
{#if parseLabelsAsHtml}
|
|
455
|
+
{@html get_label(option)}
|
|
456
|
+
{:else}
|
|
457
|
+
{get_label(option)}
|
|
458
|
+
{/if}
|
|
459
|
+
</slot>
|
|
449
460
|
</slot>
|
|
450
461
|
{#if !disabled && (minSelect === null || selected.length > minSelect)}
|
|
451
462
|
<button
|
|
@@ -528,7 +539,15 @@ function highlight_matching_options(event) {
|
|
|
528
539
|
|
|
529
540
|
<!-- only render options dropdown if options or searchText is not empty needed to avoid briefly flashing empty dropdown -->
|
|
530
541
|
{#if (searchText && noMatchingOptionsMsg) || options?.length > 0}
|
|
531
|
-
<ul
|
|
542
|
+
<ul
|
|
543
|
+
class:hidden={!open}
|
|
544
|
+
class="options {ulOptionsClass}"
|
|
545
|
+
role="listbox"
|
|
546
|
+
aria-multiselectable={maxSelect === null || maxSelect > 1}
|
|
547
|
+
aria-expanded={open}
|
|
548
|
+
aria-disabled={disabled ? `true` : null}
|
|
549
|
+
bind:this={ul_options}
|
|
550
|
+
>
|
|
532
551
|
{#each matchingOptions as option, idx}
|
|
533
552
|
{@const {
|
|
534
553
|
label,
|
|
@@ -558,13 +577,17 @@ function highlight_matching_options(event) {
|
|
|
558
577
|
}}
|
|
559
578
|
on:mouseout={() => (activeIndex = null)}
|
|
560
579
|
on:blur={() => (activeIndex = null)}
|
|
580
|
+
role="option"
|
|
581
|
+
aria-selected="false"
|
|
561
582
|
>
|
|
562
583
|
<slot name="option" {option} {idx}>
|
|
563
|
-
{
|
|
564
|
-
{
|
|
565
|
-
|
|
566
|
-
{
|
|
567
|
-
|
|
584
|
+
<slot {option} {idx}>
|
|
585
|
+
{#if parseLabelsAsHtml}
|
|
586
|
+
{@html get_label(option)}
|
|
587
|
+
{:else}
|
|
588
|
+
{get_label(option)}
|
|
589
|
+
{/if}
|
|
590
|
+
</slot>
|
|
568
591
|
</slot>
|
|
569
592
|
</li>
|
|
570
593
|
{:else}
|
|
@@ -583,6 +606,8 @@ function highlight_matching_options(event) {
|
|
|
583
606
|
on:focus={() => (option_msg_is_active = true)}
|
|
584
607
|
on:mouseout={() => (option_msg_is_active = false)}
|
|
585
608
|
on:blur={() => (option_msg_is_active = false)}
|
|
609
|
+
role="option"
|
|
610
|
+
aria-selected="false"
|
|
586
611
|
class="user-msg"
|
|
587
612
|
>
|
|
588
613
|
{msg}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { SvelteComponentTyped } from "svelte";
|
|
2
|
-
import type { Option as
|
|
3
|
-
declare class __sveltets_Render<Option extends
|
|
2
|
+
import type { MultiSelectEvents, Option as T } from './types';
|
|
3
|
+
declare class __sveltets_Render<Option extends T> {
|
|
4
4
|
props(): {
|
|
5
5
|
activeIndex?: number | null | undefined;
|
|
6
6
|
activeOption?: Option | null | undefined;
|
|
7
|
-
createOptionMsg?: string | undefined;
|
|
7
|
+
createOptionMsg?: string | null | undefined;
|
|
8
8
|
allowUserOptions?: boolean | "append" | undefined;
|
|
9
9
|
allowEmpty?: boolean | undefined;
|
|
10
10
|
autocomplete?: string | undefined;
|
|
@@ -13,7 +13,7 @@ declare class __sveltets_Render<Option extends GenericOption> {
|
|
|
13
13
|
defaultDisabledTitle?: string | undefined;
|
|
14
14
|
disabled?: boolean | undefined;
|
|
15
15
|
disabledInputTitle?: string | undefined;
|
|
16
|
-
duplicateFunc?: ((op1:
|
|
16
|
+
duplicateFunc?: ((op1: T, op2: T) => boolean) | undefined;
|
|
17
17
|
duplicateOptionMsg?: string | undefined;
|
|
18
18
|
duplicates?: boolean | undefined;
|
|
19
19
|
filterFunc?: ((op: Option, searchText: string) => boolean) | undefined;
|
|
@@ -54,6 +54,7 @@ declare class __sveltets_Render<Option extends GenericOption> {
|
|
|
54
54
|
ulOptionsClass?: string | undefined;
|
|
55
55
|
ulSelectedClass?: string | undefined;
|
|
56
56
|
value?: Option | Option[] | null | undefined;
|
|
57
|
+
get_label?: ((op: T) => string | number) | undefined;
|
|
57
58
|
};
|
|
58
59
|
events(): MultiSelectEvents;
|
|
59
60
|
slots(): {
|
|
@@ -64,6 +65,10 @@ declare class __sveltets_Render<Option extends GenericOption> {
|
|
|
64
65
|
option: Option;
|
|
65
66
|
idx: any;
|
|
66
67
|
};
|
|
68
|
+
default: {
|
|
69
|
+
option: Option;
|
|
70
|
+
idx: any;
|
|
71
|
+
};
|
|
67
72
|
'remove-icon': {};
|
|
68
73
|
spinner: {};
|
|
69
74
|
'disabled-icon': {};
|
|
@@ -73,9 +78,10 @@ declare class __sveltets_Render<Option extends GenericOption> {
|
|
|
73
78
|
};
|
|
74
79
|
};
|
|
75
80
|
}
|
|
76
|
-
export type MultiSelectProps<Option extends
|
|
77
|
-
export type MultiSelectEvents<Option extends
|
|
78
|
-
export type MultiSelectSlots<Option extends
|
|
79
|
-
export default class MultiSelect<Option extends
|
|
81
|
+
export type MultiSelectProps<Option extends T> = ReturnType<__sveltets_Render<Option>['props']>;
|
|
82
|
+
export type MultiSelectEvents<Option extends T> = ReturnType<__sveltets_Render<Option>['events']>;
|
|
83
|
+
export type MultiSelectSlots<Option extends T> = ReturnType<__sveltets_Render<Option>['slots']>;
|
|
84
|
+
export default class MultiSelect<Option extends T> extends SvelteComponentTyped<MultiSelectProps<Option>, MultiSelectEvents<Option>, MultiSelectSlots<Option>> {
|
|
85
|
+
get get_label(): (op: T) => string | number;
|
|
80
86
|
}
|
|
81
87
|
export {};
|
package/dist/index.d.ts
CHANGED
|
@@ -2,55 +2,5 @@ export { default as CircleSpinner } from './CircleSpinner.svelte';
|
|
|
2
2
|
export { default as CmdPalette } from './CmdPalette.svelte';
|
|
3
3
|
export { default as MultiSelect, default } from './MultiSelect.svelte';
|
|
4
4
|
export { default as Wiggle } from './Wiggle.svelte';
|
|
5
|
-
export
|
|
6
|
-
export type ObjectOption = {
|
|
7
|
-
label: string | number;
|
|
8
|
-
value?: unknown;
|
|
9
|
-
title?: string;
|
|
10
|
-
disabled?: boolean;
|
|
11
|
-
preselected?: boolean;
|
|
12
|
-
disabledTitle?: string;
|
|
13
|
-
selectedTitle?: string;
|
|
14
|
-
[key: string]: unknown;
|
|
15
|
-
};
|
|
16
|
-
export type DispatchEvents<T = Option> = {
|
|
17
|
-
add: {
|
|
18
|
-
option: T;
|
|
19
|
-
};
|
|
20
|
-
create: {
|
|
21
|
-
option: T;
|
|
22
|
-
};
|
|
23
|
-
remove: {
|
|
24
|
-
option: T;
|
|
25
|
-
};
|
|
26
|
-
removeAll: {
|
|
27
|
-
options: T[];
|
|
28
|
-
};
|
|
29
|
-
change: {
|
|
30
|
-
option?: T;
|
|
31
|
-
options?: T[];
|
|
32
|
-
type: 'add' | 'remove' | 'removeAll';
|
|
33
|
-
};
|
|
34
|
-
open: {
|
|
35
|
-
event: Event;
|
|
36
|
-
};
|
|
37
|
-
close: {
|
|
38
|
-
event: Event;
|
|
39
|
-
};
|
|
40
|
-
};
|
|
41
|
-
export type MultiSelectEvents = {
|
|
42
|
-
[key in keyof DispatchEvents]: CustomEvent<DispatchEvents[key]>;
|
|
43
|
-
} & {
|
|
44
|
-
blur: FocusEvent;
|
|
45
|
-
click: MouseEvent;
|
|
46
|
-
focus: FocusEvent;
|
|
47
|
-
keydown: KeyboardEvent;
|
|
48
|
-
keyup: KeyboardEvent;
|
|
49
|
-
mouseenter: MouseEvent;
|
|
50
|
-
mouseleave: MouseEvent;
|
|
51
|
-
touchcancel: TouchEvent;
|
|
52
|
-
touchend: TouchEvent;
|
|
53
|
-
touchmove: TouchEvent;
|
|
54
|
-
touchstart: TouchEvent;
|
|
55
|
-
};
|
|
5
|
+
export * from './types';
|
|
56
6
|
export declare function scroll_into_view_if_needed_polyfill(centerIfNeeded?: boolean): IntersectionObserver;
|
package/dist/index.js
CHANGED
|
@@ -2,6 +2,7 @@ export { default as CircleSpinner } from './CircleSpinner.svelte';
|
|
|
2
2
|
export { default as CmdPalette } from './CmdPalette.svelte';
|
|
3
3
|
export { default as MultiSelect, default } from './MultiSelect.svelte';
|
|
4
4
|
export { default as Wiggle } from './Wiggle.svelte';
|
|
5
|
+
export * from './types';
|
|
5
6
|
// Firefox lacks support for scrollIntoViewIfNeeded (https://caniuse.com/scrollintoviewifneeded).
|
|
6
7
|
// See https://github.com/janosh/svelte-multiselect/issues/87
|
|
7
8
|
// Polyfill copied from
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
export type Option = string | number | ObjectOption;
|
|
2
|
+
export type ObjectOption = {
|
|
3
|
+
label: string | number;
|
|
4
|
+
value?: unknown;
|
|
5
|
+
title?: string;
|
|
6
|
+
disabled?: boolean;
|
|
7
|
+
preselected?: boolean;
|
|
8
|
+
disabledTitle?: string;
|
|
9
|
+
selectedTitle?: string;
|
|
10
|
+
[key: string]: unknown;
|
|
11
|
+
};
|
|
12
|
+
export type DispatchEvents<T = Option> = {
|
|
13
|
+
add: {
|
|
14
|
+
option: T;
|
|
15
|
+
};
|
|
16
|
+
create: {
|
|
17
|
+
option: T;
|
|
18
|
+
};
|
|
19
|
+
remove: {
|
|
20
|
+
option: T;
|
|
21
|
+
};
|
|
22
|
+
removeAll: {
|
|
23
|
+
options: T[];
|
|
24
|
+
};
|
|
25
|
+
change: {
|
|
26
|
+
option?: T;
|
|
27
|
+
options?: T[];
|
|
28
|
+
type: 'add' | 'remove' | 'removeAll';
|
|
29
|
+
};
|
|
30
|
+
open: {
|
|
31
|
+
event: Event;
|
|
32
|
+
};
|
|
33
|
+
close: {
|
|
34
|
+
event: Event;
|
|
35
|
+
};
|
|
36
|
+
};
|
|
37
|
+
export type MultiSelectEvents = {
|
|
38
|
+
[key in keyof DispatchEvents]: CustomEvent<DispatchEvents[key]>;
|
|
39
|
+
} & {
|
|
40
|
+
blur: FocusEvent;
|
|
41
|
+
click: MouseEvent;
|
|
42
|
+
focus: FocusEvent;
|
|
43
|
+
keydown: KeyboardEvent;
|
|
44
|
+
keyup: KeyboardEvent;
|
|
45
|
+
mouseenter: MouseEvent;
|
|
46
|
+
mouseleave: MouseEvent;
|
|
47
|
+
touchcancel: TouchEvent;
|
|
48
|
+
touchend: TouchEvent;
|
|
49
|
+
touchmove: TouchEvent;
|
|
50
|
+
touchstart: TouchEvent;
|
|
51
|
+
};
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
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": "
|
|
8
|
+
"version": "9.0.0",
|
|
9
9
|
"type": "module",
|
|
10
10
|
"svelte": "./dist/index.js",
|
|
11
11
|
"bugs": "https://github.com/janosh/svelte-multiselect/issues",
|
|
@@ -19,41 +19,41 @@
|
|
|
19
19
|
"test": "vitest --run --coverage tests/unit/*.ts && playwright test tests/*.test.ts",
|
|
20
20
|
"test:unit": "vitest tests/unit/*.ts",
|
|
21
21
|
"test:e2e": "playwright test tests/*.test.ts",
|
|
22
|
-
"changelog": "npx auto-changelog --package --output changelog.md --
|
|
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
25
|
"dependencies": {
|
|
26
|
-
"svelte": "^
|
|
26
|
+
"svelte": "^4.0.0-next.0"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
29
|
"@iconify/svelte": "^3.1.3",
|
|
30
|
-
"@playwright/test": "^1.
|
|
30
|
+
"@playwright/test": "^1.34.3",
|
|
31
31
|
"@sveltejs/adapter-static": "^2.0.2",
|
|
32
|
-
"@sveltejs/kit": "^1.
|
|
32
|
+
"@sveltejs/kit": "^1.19.0",
|
|
33
33
|
"@sveltejs/package": "2.0.2",
|
|
34
|
-
"@sveltejs/vite-plugin-svelte": "
|
|
35
|
-
"@typescript-eslint/eslint-plugin": "^5.59.
|
|
36
|
-
"@typescript-eslint/parser": "^5.59.
|
|
37
|
-
"@vitest/coverage-c8": "^0.
|
|
38
|
-
"eslint": "^8.
|
|
34
|
+
"@sveltejs/vite-plugin-svelte": "1.0.0-next.29",
|
|
35
|
+
"@typescript-eslint/eslint-plugin": "^5.59.7",
|
|
36
|
+
"@typescript-eslint/parser": "^5.59.7",
|
|
37
|
+
"@vitest/coverage-c8": "^0.31.1",
|
|
38
|
+
"eslint": "^8.41.0",
|
|
39
39
|
"eslint-plugin-svelte3": "^4.0.0",
|
|
40
40
|
"hastscript": "^7.2.0",
|
|
41
41
|
"highlight.js": "^11.8.0",
|
|
42
|
-
"jsdom": "^
|
|
42
|
+
"jsdom": "^22.0.0",
|
|
43
43
|
"mdsvex": "^0.10.6",
|
|
44
44
|
"mdsvexamples": "^0.3.3",
|
|
45
45
|
"prettier": "^2.8.8",
|
|
46
46
|
"prettier-plugin-svelte": "^2.10.0",
|
|
47
47
|
"rehype-autolink-headings": "^6.1.1",
|
|
48
48
|
"rehype-slug": "^5.1.0",
|
|
49
|
-
"svelte-check": "^3.2
|
|
49
|
+
"svelte-check": "^3.4.2",
|
|
50
50
|
"svelte-preprocess": "^5.0.3",
|
|
51
51
|
"svelte-toc": "^0.5.5",
|
|
52
|
-
"svelte-zoo": "^0.4.
|
|
53
|
-
"svelte2tsx": "^0.6.
|
|
52
|
+
"svelte-zoo": "^0.4.6",
|
|
53
|
+
"svelte2tsx": "^0.6.15",
|
|
54
54
|
"typescript": "5.0.4",
|
|
55
|
-
"vite": "^4.3.
|
|
56
|
-
"vitest": "^0.
|
|
55
|
+
"vite": "^4.3.9",
|
|
56
|
+
"vitest": "^0.31.1"
|
|
57
57
|
},
|
|
58
58
|
"keywords": [
|
|
59
59
|
"svelte",
|
package/readme.md
CHANGED
|
@@ -36,22 +36,34 @@
|
|
|
36
36
|
|
|
37
37
|
## ๐งช   Coverage
|
|
38
38
|
|
|
39
|
-
| Statements | Branches
|
|
40
|
-
| ------------------------------------------------------------------------------------------ |
|
|
41
|
-
|  |  |  |
|
|
42
42
|
|
|
43
43
|
## ๐   Breaking changes
|
|
44
44
|
|
|
45
|
-
- **8.0.0
|
|
45
|
+
- **8.0.0** (2022-10-22)
|
|
46
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
47
|
- Prop `noOptionsMsg` was renamed to `noMatchingOptionsMsg`. [PR 133](https://github.com/janosh/svelte-multiselect/pull/133).
|
|
48
|
-
- **v8.3.0
|
|
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
|
+
```
|
|
49
61
|
|
|
50
62
|
## ๐จ   Installation
|
|
51
63
|
|
|
52
64
|
```sh
|
|
53
65
|
npm install --dev svelte-multiselect
|
|
54
|
-
pnpm add
|
|
66
|
+
pnpm add -D svelte-multiselect
|
|
55
67
|
yarn add --dev svelte-multiselect
|
|
56
68
|
```
|
|
57
69
|
|
|
@@ -90,10 +102,10 @@ Full list of props/bindable variables for this component. The `Option` type you
|
|
|
90
102
|
Currently active option, i.e. the one the user currently hovers or navigated to with arrow keys.
|
|
91
103
|
|
|
92
104
|
1. ```ts
|
|
93
|
-
createOptionMsg: string = `Create this option...`
|
|
105
|
+
createOptionMsg: string | null = `Create this option...`
|
|
94
106
|
```
|
|
95
107
|
|
|
96
|
-
|
|
108
|
+
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.
|
|
97
109
|
|
|
98
110
|
1. ```ts
|
|
99
111
|
allowEmpty: boolean = false
|
|
@@ -146,7 +158,7 @@ Full list of props/bindable variables for this component. The `Option` type you
|
|
|
146
158
|
|
|
147
159
|
<!-- prettier-ignore -->
|
|
148
160
|
1. ```ts
|
|
149
|
-
duplicateFunc: (op1:
|
|
161
|
+
duplicateFunc: (op1: T, op2: T) => boolean = (op1, op2) =>
|
|
150
162
|
`${get_label(op1)}`.toLowerCase() === `${get_label(op2)}`.toLowerCase()
|
|
151
163
|
```
|
|
152
164
|
|
|
@@ -189,7 +201,7 @@ Full list of props/bindable variables for this component. The `Option` type you
|
|
|
189
201
|
highlightMatches: boolean = true
|
|
190
202
|
```
|
|
191
203
|
|
|
192
|
-
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 and [styling options](https://developer.mozilla.org/docs/Web/CSS/::highlight). See `::highlight(sms-search-matches)` below for available CSS variables.
|
|
204
|
+
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.
|
|
193
205
|
|
|
194
206
|
1. ```ts
|
|
195
207
|
id: string | null = null
|
|
@@ -375,14 +387,9 @@ Full list of props/bindable variables for this component. The `Option` type you
|
|
|
375
387
|
Example:
|
|
376
388
|
|
|
377
389
|
```svelte
|
|
378
|
-
<MultiSelect options={[`Red`, `Green`, `Blue`, `Yellow`, `Purple`]}>
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
{option.label}
|
|
382
|
-
<span style:background={option.label} style=" width: 1em; height: 1em;" />
|
|
383
|
-
</span>
|
|
384
|
-
|
|
385
|
-
<span let:idx let:option slot="selected">
|
|
390
|
+
<MultiSelect options={[`Red`, `Green`, `Blue`, `Yellow`, `Purple`]} let:idx let:option>
|
|
391
|
+
<!-- default slot overrides rendering of both dropdown-listed and selected options -->
|
|
392
|
+
<span>
|
|
386
393
|
{idx + 1}
|
|
387
394
|
{option.label}
|
|
388
395
|
<span style:background={option.label} style=" width: 1em; height: 1em;" />
|