svelte-multiselect 8.2.0 → 8.2.2

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.
@@ -55,8 +55,8 @@ export let searchText = ``;
55
55
  export let selected = options
56
56
  ?.filter((op) => op?.preselected)
57
57
  .slice(0, maxSelect ?? undefined) ?? [];
58
- export let selectedOptionsDraggable = true;
59
58
  export let sortSelected = false;
59
+ export let selectedOptionsDraggable = !sortSelected;
60
60
  export let ulOptionsClass = ``;
61
61
  export let ulSelectedClass = ``;
62
62
  export let value = null;
@@ -89,6 +89,9 @@ if (!Array.isArray(selected)) {
89
89
  if (maxSelect && typeof required === `number` && required > maxSelect) {
90
90
  console.error(`MultiSelect maxSelect=${maxSelect} < required=${required}, makes it impossible for users to submit a valid form`);
91
91
  }
92
+ if (sortSelected && selectedOptionsDraggable) {
93
+ console.warn(`MultiSelect's sortSelected and selectedOptionsDraggable should not be combined as any user re-orderings of selected options will be undone by sortSelected on component re-renders.`);
94
+ }
92
95
  const dispatch = createEventDispatcher();
93
96
  let add_option_msg_is_active = false; // controls active state of <li>{addOptionMsg}</li>
94
97
  let window_width;
@@ -238,7 +241,7 @@ async function handle_keydown(event) {
238
241
  activeIndex = 0;
239
242
  return;
240
243
  }
241
- else if (allowUserOptions && searchText.length > 0) {
244
+ else if (allowUserOptions && !matchingOptions.length && searchText.length > 0) {
242
245
  // if allowUserOptions is truthy and user entered text but no options match, we make
243
246
  // <li>{addUserMsg}</li> active on keydown (or toggle it if already active)
244
247
  add_option_msg_is_active = !add_option_msg_is_active;
@@ -248,7 +251,8 @@ async function handle_keydown(event) {
248
251
  // if no option is active and no options are matching, do nothing
249
252
  return;
250
253
  }
251
- // if none of the abvove special cases apply, we make next/prev option
254
+ event.preventDefault();
255
+ // if none of the above special cases apply, we make next/prev option
252
256
  // active with wrap around at both ends
253
257
  const increment = event.key === `ArrowUp` ? -1 : 1;
254
258
  activeIndex = (activeIndex + increment) % matchingOptions.length;
@@ -358,7 +362,9 @@ const dragstart = (idx) => (event) => {
358
362
  form_input?.setCustomValidity(msg)
359
363
  }}
360
364
  />
361
- <ExpandIcon width="15px" style="min-width: 1em; padding: 0 1pt;" />
365
+ <slot name="expand-icon" {open}>
366
+ <ExpandIcon width="15px" style="min-width: 1em; padding: 0 1pt; cursor: pointer;" />
367
+ </slot>
362
368
  <ul class="selected {ulSelectedClass}">
363
369
  {#each selected as option, idx (get_label(option))}
364
370
  <li
@@ -393,36 +399,35 @@ const dragstart = (idx) => (event) => {
393
399
  {/if}
394
400
  </li>
395
401
  {/each}
396
- <input
397
- class={inputClass}
398
- bind:this={input}
399
- {autocomplete}
400
- bind:value={searchText}
401
- on:mouseup|self|stopPropagation={open_dropdown}
402
- on:keydown|stopPropagation={handle_keydown}
403
- on:focus
404
- on:focus={open_dropdown}
405
- {id}
406
- {disabled}
407
- {inputmode}
408
- {pattern}
409
- placeholder={selected.length == 0 ? placeholder : null}
410
- aria-invalid={invalid ? `true` : null}
411
- on:blur
412
- on:change
413
- on:click
414
- on:keydown
415
- on:keyup
416
- on:mousedown
417
- on:mouseenter
418
- on:mouseleave
419
- on:touchcancel
420
- on:touchend
421
- on:touchmove
422
- on:touchstart
423
- style:min-width={open ? `3em` : `0`}
424
- />
425
402
  </ul>
403
+ <input
404
+ class={inputClass}
405
+ bind:this={input}
406
+ {autocomplete}
407
+ bind:value={searchText}
408
+ on:mouseup|self|stopPropagation={open_dropdown}
409
+ on:keydown|stopPropagation={handle_keydown}
410
+ on:focus
411
+ on:focus={open_dropdown}
412
+ {id}
413
+ {disabled}
414
+ {inputmode}
415
+ {pattern}
416
+ placeholder={selected.length == 0 ? placeholder : null}
417
+ aria-invalid={invalid ? `true` : null}
418
+ on:blur
419
+ on:change
420
+ on:click
421
+ on:keydown
422
+ on:keyup
423
+ on:mousedown
424
+ on:mouseenter
425
+ on:mouseleave
426
+ on:touchcancel
427
+ on:touchend
428
+ on:touchmove
429
+ on:touchstart
430
+ />
426
431
  <!-- the above on:* lines forward potentially useful DOM events -->
427
432
  {#if loading}
428
433
  <slot name="spinner">
@@ -534,7 +539,7 @@ const dragstart = (idx) => (event) => {
534
539
  border-radius: var(--sms-border-radius, 3pt);
535
540
  background: var(--sms-bg);
536
541
  width: var(--sms-width, 100%);
537
- max-width: var(--sms-max-width);
542
+ max-width: var(--sms-max-width, 800px);
538
543
  padding: var(--sms-padding, 0 3pt);
539
544
  color: var(--sms-text-color);
540
545
  font-size: var(--sms-font-size, inherit);
@@ -603,7 +608,7 @@ const dragstart = (idx) => (event) => {
603
608
  margin: auto 0; /* CSS reset */
604
609
  padding: 0; /* CSS reset */
605
610
  }
606
- :where(div.multiselect > ul.selected > input) {
611
+ :where(div.multiselect > ul.selected + input) {
607
612
  border: none;
608
613
  outline: none;
609
614
  background: none;
@@ -612,10 +617,14 @@ const dragstart = (idx) => (event) => {
612
617
  font-size: inherit;
613
618
  cursor: inherit; /* needed for disabled state */
614
619
  border-radius: 0; /* reset ul.selected > li */
615
- width: 100%;
616
- flex: 1;
620
+ width: 0;
621
+ visibility: hidden;
622
+ }
623
+ :where(div.multiselect:focus-within > ul.selected + input) {
624
+ visibility: visible;
625
+ width: 3em;
617
626
  }
618
- :where(div.multiselect > ul.selected > input::placeholder) {
627
+ :where(div.multiselect > ul.selected + input::placeholder) {
619
628
  padding-left: 5pt;
620
629
  color: var(--sms-placeholder-color);
621
630
  opacity: var(--sms-placeholder-opacity);
@@ -47,13 +47,16 @@ declare const __propDef: {
47
47
  resetFilterOnAdd?: boolean | undefined;
48
48
  searchText?: string | undefined;
49
49
  selected?: Option[] | undefined;
50
- selectedOptionsDraggable?: boolean | undefined;
51
50
  sortSelected?: boolean | ((op1: Option, op2: Option) => number) | undefined;
51
+ selectedOptionsDraggable?: boolean | undefined;
52
52
  ulOptionsClass?: string | undefined;
53
53
  ulSelectedClass?: string | undefined;
54
54
  value?: Option | Option[] | null | undefined;
55
55
  };
56
56
  slots: {
57
+ 'expand-icon': {
58
+ open: boolean;
59
+ };
57
60
  selected: {
58
61
  option: Option;
59
62
  idx: any;
@@ -66,7 +69,6 @@ declare const __propDef: {
66
69
  idx: any;
67
70
  };
68
71
  };
69
- getters: {};
70
72
  events: MultiSelectEvents;
71
73
  };
72
74
  export type MultiSelectProps = typeof __propDef.props;
package/changelog.md CHANGED
@@ -2,8 +2,30 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file. Dates are displayed in UTC.
4
4
 
5
+ <!-- auto-changelog-above -->
6
+
7
+ #### [v8.2.2](https://github.com/janosh/svelte-multiselect/compare/v8.2.1...v8.2.2)
8
+
9
+ > 18 December 2022
10
+
11
+ - Issue console warning if `sortSelected && selectedOptionsDraggable` [`#187`](https://github.com/janosh/svelte-multiselect/pull/187)
12
+ - Add new slot named 'expand-icon' [`#186`](https://github.com/janosh/svelte-multiselect/pull/186)
13
+
14
+ #### [v8.2.1](https://github.com/janosh/svelte-multiselect/compare/v8.2.0...v8.2.1)
15
+
16
+ > 10 December 2022
17
+
18
+ - Fix `allowUserOptions` preventing dropdown list navigation with up/down arrow keys [`#184`](https://github.com/janosh/svelte-multiselect/pull/184)
19
+ - Mdsvexamples [`#182`](https://github.com/janosh/svelte-multiselect/pull/182)
20
+ - Add changelog & contributing pages to site [`#181`](https://github.com/janosh/svelte-multiselect/pull/181)
21
+ - tweak contributing.md and css-classes example [`6f78033`](https://github.com/janosh/svelte-multiselect/commit/6f78033826beb34cd00bf3282c93ac5328905735)
22
+ - fix build error [`b896d36`](https://github.com/janosh/svelte-multiselect/commit/b896d3643a0988b0d0bed832ba46bcad0e2c4494)
23
+ - fix readme badge for gh-pages.yml status [`906b560`](https://github.com/janosh/svelte-multiselect/commit/906b56024a826ed45263197b1267015d88f0a660)
24
+
5
25
  #### [v8.2.0](https://github.com/janosh/svelte-multiselect/compare/v8.1.0...v8.2.0)
6
26
 
27
+ > 30 November 2022
28
+
7
29
  - Draggable selected options [`#178`](https://github.com/janosh/svelte-multiselect/pull/178)
8
30
  - Fix page navigation in GH pages, broken because served from non-apex domain [`#172`](https://github.com/janosh/svelte-multiselect/pull/172)
9
31
  - Publish docs to GitHub pages [`#170`](https://github.com/janosh/svelte-multiselect/pull/170)
@@ -11,11 +33,9 @@ All notable changes to this project will be documented in this file. Dates are d
11
33
  - add missing about field to bug-report issue template (closes #171) [`#171`](https://github.com/janosh/svelte-multiselect/issues/171)
12
34
  - add changelog.md [`236d238`](https://github.com/janosh/svelte-multiselect/commit/236d238c5fa1ce5f07cf08c09861da4d8446acb2)
13
35
  - fix prop form_input: set default value null to make it optional [`b150fe0`](https://github.com/janosh/svelte-multiselect/commit/b150fe0032ebde82a319b23bd5e6b573e0c31721)
14
- - set aliveStatusCodes: [200, 429] in .github/workflows/link-check-config.json [`b34c7bf`](https://github.com/janosh/svelte-multiselect/commit/b34c7bf99d4afa96dcd3c9c322ab4e94b1ef3a39)
36
+ - set `aliveStatusCodes: [200, 429]` in `.github/workflows/link-check-config.json` [`b34c7bf`](https://github.com/janosh/svelte-multiselect/commit/b34c7bf99d4afa96dcd3c9c322ab4e94b1ef3a39)
15
37
  - add changelog script to `package.json` [`c943617`](https://github.com/janosh/svelte-multiselect/commit/c9436171033e06e8098f4443ed40d48ddee35167)
16
38
 
17
- <!-- auto-changelog-above -->
18
-
19
39
  #### [v8.1.0](https://github.com/janosh/svelte-multiselect/compare/v8.0.4...v8.1.0)
20
40
 
21
41
  > 18 November 2022
@@ -41,7 +61,7 @@ All notable changes to this project will be documented in this file. Dates are d
41
61
  - Test uncovered lines [`#157`](https://github.com/janosh/svelte-multiselect/pull/157)
42
62
  - Don't `console.error` about missing `options` if `loading=true` [`#156`](https://github.com/janosh/svelte-multiselect/pull/156)
43
63
  - Measure `vitest` coverage with `c8` [`#155`](https://github.com/janosh/svelte-multiselect/pull/155)
44
- - increase --sms-min-height 19-&gt;22pt [`5d0e081`](https://github.com/janosh/svelte-multiselect/commit/5d0e0815d0b488ae23b439a3f085dd083138c326)
64
+ - increase --sms-min-height 19->`22pt [`5d0e081`](<https://github.com/janosh/svelte-multiselect/commit/5d0e0815d0b488ae23b439a3f085dd083138c326>)
45
65
 
46
66
  #### [v8.0.2](https://github.com/janosh/svelte-multiselect/compare/v8.0.1...v8.0.2)
47
67
 
@@ -67,7 +87,7 @@ All notable changes to this project will be documented in this file. Dates are d
67
87
  - Add new prop `value` [`#138`](https://github.com/janosh/svelte-multiselect/pull/138)
68
88
  - New prop resetFilterOnAdd [`#137`](https://github.com/janosh/svelte-multiselect/pull/137)
69
89
  - `yarn` to `pnpm` [`#134`](https://github.com/janosh/svelte-multiselect/pull/134)
70
- - Rename prop `noOptionsMsg`-&gt;`noMatchingOptionsMsg` [`#133`](https://github.com/janosh/svelte-multiselect/pull/133)
90
+ - Rename prop `noOptionsMsg -> noMatchingOptionsMsg` [`#133`](https://github.com/janosh/svelte-multiselect/pull/133)
71
91
  - remove props selectedLabels and selectedValues [`ef6598e`](https://github.com/janosh/svelte-multiselect/commit/ef6598e8b0dc1f2f8cb687074463cb73b2f9ebff)
72
92
 
73
93
  #### [v7.1.0](https://github.com/janosh/svelte-multiselect/compare/v7.0.2...v7.1.0)
@@ -173,7 +193,7 @@ All notable changes to this project will be documented in this file. Dates are d
173
193
 
174
194
  - Replace `li.scrollIntoViewIfNeeded()` with `li.scrollIntoView()` [`#88`](https://github.com/janosh/svelte-multiselect/pull/88)
175
195
  - Add new prop `parseLabelsAsHtml` [`#84`](https://github.com/janosh/svelte-multiselect/pull/84)
176
- - try fix flaky test 'multiselect &gt; can select and remove many options' [`2b0c453`](https://github.com/janosh/svelte-multiselect/commit/2b0c453c794c0b3b82e81c5b994c10bc305a98d6)
196
+ - try fix flaky test 'multiselect >`can select and remove many options' [`2b0c453`](<https://github.com/janosh/svelte-multiselect/commit/2b0c453c794c0b3b82e81c5b994c10bc305a98d6>)
177
197
  - bump netlify node to v18, update readme + deps [`586c724`](https://github.com/janosh/svelte-multiselect/commit/586c724d471aece2b5a3726bb5eb145e36073fe3)
178
198
  - remove plausible.js analytics [`cd4c9f6`](https://github.com/janosh/svelte-multiselect/commit/cd4c9f6e18e13959dfb4fcebe9acba7a875b83a2)
179
199
 
@@ -222,7 +242,7 @@ All notable changes to this project will be documented in this file. Dates are d
222
242
  - Add `aria-label` to hidden `.form-control` input [`#62`](https://github.com/janosh/svelte-multiselect/pull/62)
223
243
  - Add `aria-label` to hidden `.form-control` input (#62) [`#58`](https://github.com/janosh/svelte-multiselect/issues/58) [`#35`](https://github.com/janosh/svelte-multiselect/issues/35)
224
244
  - fix dropdown closing when clicking between list items (closes #61) [`#61`](https://github.com/janosh/svelte-multiselect/issues/61)
225
- - svelte.config.js add kit.prerender.default: true, mv src/{global,app}.d.ts [`4a84913`](https://github.com/janosh/svelte-multiselect/commit/4a8491380e08bad137ca7bdda9ee4ddd38abe3d6)
245
+ - `svelte.config.js` add `kit.prerender.default: true`, `mv src/{global,app}.d.ts` [`4a84913`](https://github.com/janosh/svelte-multiselect/commit/4a8491380e08bad137ca7bdda9ee4ddd38abe3d6)
226
246
 
227
247
  #### [v4.0.2](https://github.com/janosh/svelte-multiselect/compare/v4.0.1...v4.0.2)
228
248
 
@@ -261,7 +281,7 @@ All notable changes to this project will be documented in this file. Dates are d
261
281
 
262
282
  > 20 February 2022
263
283
 
264
- - by default, only show maxSelectMsg if maxSelect != null and &gt; 1 (closes #37) [`#37`](https://github.com/janosh/svelte-multiselect/issues/37)
284
+ - by default, only show maxSelectMsg if maxSelect != null and >`1 (closes #37) [`#37`](<https://github.com/janosh/svelte-multiselect/issues/37>)
265
285
  - add CSS var --sms-options-shadow defaults to subtle black shadow around dropdown list (0 0 14pt -8pt black) (closes #36) [`#36`](https://github.com/janosh/svelte-multiselect/issues/36)
266
286
  - add prop liActiveOptionClass = '' (closes #35) [`#35`](https://github.com/janosh/svelte-multiselect/issues/35)
267
287
  - turn searchText = and showOptions = false into bindable props (closes #33) [`#33`](https://github.com/janosh/svelte-multiselect/issues/33)
@@ -293,7 +313,7 @@ All notable changes to this project will be documented in this file. Dates are d
293
313
 
294
314
  > 3 February 2022
295
315
 
296
- - apply id prop to &lt;input&gt; instead of outer div (closes #25) [`#25`](https://github.com/janosh/svelte-multiselect/issues/25)
316
+ - apply id prop to `<input>` instead of outer div (closes #25) [`#25`](https://github.com/janosh/svelte-multiselect/issues/25)
297
317
  - add eslint commit hook + update deps [`6ad44b8`](https://github.com/janosh/svelte-multiselect/commit/6ad44b85057aef71eae19293de80f9d42f91f87b)
298
318
  - v.3.2.0 [`71ff2d1`](https://github.com/janosh/svelte-multiselect/commit/71ff2d192caccacbe41f83949c14d7d4ca87d590)
299
319
  - add readme badge to document minimum svelte version (for #24) [`7d9fe5a`](https://github.com/janosh/svelte-multiselect/commit/7d9fe5a977b56dab95069b64321f0718e0d61f08)
@@ -303,7 +323,7 @@ All notable changes to this project will be documented in this file. Dates are d
303
323
  > 25 January 2022
304
324
 
305
325
  - wiggle the maxSelect msg on hitting selection limit (closes #19) [`#19`](https://github.com/janosh/svelte-multiselect/issues/19)
306
- - readme better docs for CSS variables, rename slots {options,selected}Renderer -&gt; render{options,selected} [`c8ab724`](https://github.com/janosh/svelte-multiselect/commit/c8ab7241506cfe6b5930d098150a251e85c52afd)
326
+ - readme better docs for CSS variables, rename slots `{options,selected}Renderer -> render{options,selected}` [`c8ab724`](https://github.com/janosh/svelte-multiselect/commit/c8ab7241506cfe6b5930d098150a251e85c52afd)
307
327
 
308
328
  #### [v3.1.0](https://github.com/janosh/svelte-multiselect/compare/v3.0.1...v3.1.0)
309
329
 
@@ -344,7 +364,7 @@ All notable changes to this project will be documented in this file. Dates are d
344
364
 
345
365
  > 27 October 2021
346
366
 
347
- - set &lt;input&gt; width back to 1pt as it's only needed to tab into, focus and blur &lt;MultiSelect&gt; (closes #12) [`#12`](https://github.com/janosh/svelte-multiselect/issues/12)
367
+ - set `<input>` width back to 1pt as it's only needed to tab into, focus and blur `<MultiSelect>` (closes #12) [`#12`](https://github.com/janosh/svelte-multiselect/issues/12)
348
368
  - update readme [`45c7993`](https://github.com/janosh/svelte-multiselect/commit/45c7993398c986499d4c0729177620cbec719cb7)
349
369
 
350
370
  #### [v1.2.1](https://github.com/janosh/svelte-multiselect/compare/v1.2.0...v1.2.1)
@@ -2,7 +2,7 @@
2
2
  /** @typedef {typeof __propDef.events} ChevronExpandEvents */
3
3
  /** @typedef {typeof __propDef.slots} ChevronExpandSlots */
4
4
  export default class ChevronExpand extends SvelteComponentTyped<{
5
- [x: string]: any;
5
+ [x: string]: never;
6
6
  }, {
7
7
  [evt: string]: CustomEvent<any>;
8
8
  }, {}> {
@@ -13,7 +13,7 @@ export type ChevronExpandSlots = typeof __propDef.slots;
13
13
  import { SvelteComponentTyped } from "svelte";
14
14
  declare const __propDef: {
15
15
  props: {
16
- [x: string]: any;
16
+ [x: string]: never;
17
17
  };
18
18
  events: {
19
19
  [evt: string]: CustomEvent<any>;
@@ -2,7 +2,7 @@
2
2
  /** @typedef {typeof __propDef.events} CrossEvents */
3
3
  /** @typedef {typeof __propDef.slots} CrossSlots */
4
4
  export default class Cross extends SvelteComponentTyped<{
5
- [x: string]: any;
5
+ [x: string]: never;
6
6
  }, {
7
7
  [evt: string]: CustomEvent<any>;
8
8
  }, {}> {
@@ -13,7 +13,7 @@ export type CrossSlots = typeof __propDef.slots;
13
13
  import { SvelteComponentTyped } from "svelte";
14
14
  declare const __propDef: {
15
15
  props: {
16
- [x: string]: any;
16
+ [x: string]: never;
17
17
  };
18
18
  events: {
19
19
  [evt: string]: CustomEvent<any>;
@@ -2,7 +2,7 @@
2
2
  /** @typedef {typeof __propDef.events} DisabledEvents */
3
3
  /** @typedef {typeof __propDef.slots} DisabledSlots */
4
4
  export default class Disabled extends SvelteComponentTyped<{
5
- [x: string]: any;
5
+ [x: string]: never;
6
6
  }, {
7
7
  [evt: string]: CustomEvent<any>;
8
8
  }, {}> {
@@ -13,7 +13,7 @@ export type DisabledSlots = typeof __propDef.slots;
13
13
  import { SvelteComponentTyped } from "svelte";
14
14
  declare const __propDef: {
15
15
  props: {
16
- [x: string]: any;
16
+ [x: string]: never;
17
17
  };
18
18
  events: {
19
19
  [evt: string]: CustomEvent<any>;
@@ -2,7 +2,7 @@
2
2
  /** @typedef {typeof __propDef.events} OctocatEvents */
3
3
  /** @typedef {typeof __propDef.slots} OctocatSlots */
4
4
  export default class Octocat extends SvelteComponentTyped<{
5
- [x: string]: any;
5
+ [x: string]: never;
6
6
  }, {
7
7
  [evt: string]: CustomEvent<any>;
8
8
  }, {}> {
@@ -13,7 +13,7 @@ export type OctocatSlots = typeof __propDef.slots;
13
13
  import { SvelteComponentTyped } from "svelte";
14
14
  declare const __propDef: {
15
15
  props: {
16
- [x: string]: any;
16
+ [x: string]: never;
17
17
  };
18
18
  events: {
19
19
  [evt: string]: CustomEvent<any>;
package/package.json CHANGED
@@ -5,42 +5,42 @@
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.2.0",
8
+ "version": "8.2.2",
9
9
  "type": "module",
10
10
  "svelte": "index.js",
11
11
  "main": "index.js",
12
12
  "bugs": "https://github.com/janosh/svelte-multiselect/issues",
13
13
  "devDependencies": {
14
- "@iconify/svelte": "^3.0.0",
15
- "@playwright/test": "^1.28.0",
16
- "@sveltejs/adapter-static": "1.0.0-next.48",
17
- "@sveltejs/kit": "1.0.0-next.553",
18
- "@sveltejs/package": "1.0.0-next.6",
19
- "@sveltejs/vite-plugin-svelte": "^1.2.0",
20
- "@typescript-eslint/eslint-plugin": "^5.43.0",
21
- "@typescript-eslint/parser": "^5.43.0",
22
- "@vitest/coverage-c8": "^0.25.2",
23
- "eslint": "^8.28.0",
14
+ "@iconify/svelte": "^3.0.1",
15
+ "@playwright/test": "^1.29.0",
16
+ "@sveltejs/adapter-static": "1.0.0",
17
+ "@sveltejs/kit": "1.0.1",
18
+ "@sveltejs/package": "1.0.1",
19
+ "@sveltejs/vite-plugin-svelte": "^2.0.2",
20
+ "@typescript-eslint/eslint-plugin": "^5.46.1",
21
+ "@typescript-eslint/parser": "^5.46.1",
22
+ "@vitest/coverage-c8": "^0.25.8",
23
+ "eslint": "^8.30.0",
24
24
  "eslint-plugin-svelte3": "^4.0.0",
25
25
  "hastscript": "^7.1.0",
26
- "highlight.js": "^11.6.0",
27
- "jsdom": "^20.0.2",
26
+ "highlight.js": "^11.7.0",
27
+ "jsdom": "^20.0.3",
28
28
  "mdsvex": "^0.10.6",
29
- "mdsvexamples": "^0.3.2",
30
- "prettier": "^2.7.1",
31
- "prettier-plugin-svelte": "^2.8.1",
29
+ "mdsvexamples": "^0.3.3",
30
+ "prettier": "^2.8.1",
31
+ "prettier-plugin-svelte": "^2.9.0",
32
32
  "rehype-autolink-headings": "^6.1.1",
33
33
  "rehype-slug": "^5.1.0",
34
- "svelte": "^3.53.1",
35
- "svelte-check": "^2.9.2",
34
+ "svelte": "^3.55.0",
35
+ "svelte-check": "^2.10.2",
36
36
  "svelte-github-corner": "^0.1.0",
37
- "svelte-preprocess": "^4.10.7",
38
- "svelte-toc": "^0.4.1",
39
- "svelte2tsx": "^0.5.20",
37
+ "svelte-preprocess": "^5.0.0",
38
+ "svelte-toc": "^0.5.0",
39
+ "svelte2tsx": "^0.5.22",
40
40
  "tslib": "^2.4.1",
41
- "typescript": "^4.9.3",
42
- "vite": "^3.2.4",
43
- "vitest": "^0.25.2"
41
+ "typescript": "^4.9.4",
42
+ "vite": "^4.0.1",
43
+ "vitest": "^0.25.8"
44
44
  },
45
45
  "keywords": [
46
46
  "svelte",
package/readme.md CHANGED
@@ -6,7 +6,7 @@
6
6
  <h4 align="center">
7
7
 
8
8
  [![Tests](https://github.com/janosh/svelte-multiselect/actions/workflows/test.yml/badge.svg)](https://github.com/janosh/svelte-multiselect/actions/workflows/test.yml)
9
- [![Docs](https://github.com/janosh/svelte-multiselect/actions/workflows/docs.yml/badge.svg)](https://github.com/janosh/svelte-multiselect/actions/workflows/docs.yml)
9
+ [![GitHub Pages](https://github.com/janosh/svelte-multiselect/actions/workflows/gh-pages.yml/badge.svg)](https://github.com/janosh/svelte-multiselect/actions/workflows/gh-pages.yml)
10
10
  [![NPM version](https://img.shields.io/npm/v/svelte-multiselect?logo=NPM&color=purple)](https://npmjs.com/package/svelte-multiselect)
11
11
  [![Needs Svelte version](https://img.shields.io/npm/dependency-version/svelte-multiselect/dev/svelte?color=teal&logo=Svelte&label=Svelte)](https://github.com/sveltejs/svelte/blob/master/CHANGELOG.md)
12
12
  [![REPL](https://img.shields.io/badge/Svelte-REPL-blue?label=Try%20it!)](https://svelte.dev/repl/a5a14b8f15d64cb083b567292480db05)
@@ -21,7 +21,7 @@
21
21
 
22
22
  <slot name="examples" />
23
23
 
24
- ## Features
24
+ ## 💡 &nbsp; Features
25
25
 
26
26
  - **Bindable:** `bind:selected` gives you an array of the currently selected options. Thanks to Svelte's 2-way binding, it can also control the component state externally through assignment `selected = ['foo', 42]`.
27
27
  - **Keyboard friendly** for mouse-less form completion
@@ -30,11 +30,11 @@
30
30
  - **Searchable:** start typing to filter options
31
31
  - **Tagging:** selected options are listed as tags within the input
32
32
  - **Single / multiple select:** pass `maxSelect={1, 2, 3, ...}` prop to restrict the number of selectable options
33
- - **Configurable:** see [props](#props)
33
+ - **Configurable:** see props
34
34
 
35
35
  <slot name="nav" />
36
36
 
37
- ## Recent breaking changes
37
+ ## 📜 &nbsp; Breaking changes
38
38
 
39
39
  - **6.1.0**&nbsp; The `dispatch` events `focus` and `blur` were renamed to `open` and `close`, respectively. These actions refer to the dropdown list, i.e. `<MultiSelect on:open={(event) => console.log(event)}>` will trigger when the dropdown list opens. The focus and blur events are now regular DOM (not Svelte `dispatch`) events emitted by the `<input>` node. [PR 120](https://github.com/janosh/svelte-multiselect/pull/120).
40
40
  - **v7.0.0**&nbsp; `selected` (as well `selectedLabels` and `selectedValues`) used to be arrays always. Now, if `maxSelect=1`, they will no longer be a length-1 array but simply a single a option (label/value respectively) or `null` if no option is selected. [PR 123](https://github.com/janosh/svelte-multiselect/pull/123).
@@ -42,7 +42,7 @@
42
42
  - 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)
43
43
  - Prop `noOptionsMsg` was renamed to `noMatchingOptionsMsg`. [PR 133](https://github.com/janosh/svelte-multiselect/pull/133).
44
44
 
45
- ## Installation
45
+ ## 🔨 &nbsp; Installation
46
46
 
47
47
  ```sh
48
48
  npm install -D svelte-multiselect
@@ -50,9 +50,9 @@ pnpm add -D svelte-multiselect
50
50
  yarn add -D svelte-multiselect
51
51
  ```
52
52
 
53
- ## Usage
53
+ ## 📙 &nbsp; Usage
54
54
 
55
- ```html
55
+ ```svelte
56
56
  <script>
57
57
  import MultiSelect from 'svelte-multiselect'
58
58
 
@@ -61,14 +61,14 @@ yarn add -D svelte-multiselect
61
61
  let selected = []
62
62
  </script>
63
63
 
64
- Favorite Frontend tools?
64
+ Favorite Frontend Tools?
65
65
 
66
66
  <code>selected = {JSON.stringify(selected)}</code>
67
67
 
68
68
  <MultiSelect bind:selected options={ui_libs} />
69
69
  ```
70
70
 
71
- ## Props
71
+ ## 🔣 &nbsp; Props
72
72
 
73
73
  Full list of props/bindable variables for this component. The `Option` type you see below is defined in [`src/lib/index.ts`](https://github.com/janosh/svelte-multiselect/blob/main/src/lib/index.ts) and can be imported as `import { type Option } from 'svelte-multiselect'`.
74
74
 
@@ -327,16 +327,16 @@ Full list of props/bindable variables for this component. The `Option` type you
327
327
  Array of currently selected options. Supports 2-way binding `bind:selected={[1, 2, 3]}` to control component state externally. Can be passed as prop to set pre-selected options that will already be populated when component mounts before any user interaction.
328
328
 
329
329
  1. ```ts
330
- selectedOptionsDraggable: boolean = true
330
+ sortSelected: boolean | ((op1: Option, op2: Option) => number) = false
331
331
  ```
332
332
 
333
- Whether selected options are draggable so users can change their order.
333
+ Default behavior is to render selected items in the order they were chosen. `sortSelected={true}` uses default JS array sorting. A compare function enables custom logic for sorting selected options. See the [`/sort-selected`](https://janosh.github.io/svelte-multiselect/sort-selected) example.
334
334
 
335
335
  1. ```ts
336
- sortSelected: boolean | ((op1: Option, op2: Option) => number) = false
336
+ selectedOptionsDraggable: boolean = !sortSelected
337
337
  ```
338
338
 
339
- Default behavior is to render selected items in the order they were chosen. `sortSelected={true}` uses default JS array sorting. A compare function enables custom logic for sorting selected options. See the [`/sort-selected`](https://janosh.github.io/svelte-multiselect/sort-selected) example.
339
+ Whether selected options are draggable so users can change their order.
340
340
 
341
341
  1. ```ts
342
342
  value: Option | Option[] | null = null
@@ -344,19 +344,20 @@ Full list of props/bindable variables for this component. The `Option` type you
344
344
 
345
345
  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: `value` supports 1-way binding only, meaning `bind:value` will update `value` when internal component state changes but changing `value` externally will not update internal component state. This is because `value` is already reactive to `selected` and making `selected` reactive to `value` would be cyclic. Suggestions for better solutions that solve both [#86](https://github.com/janosh/svelte-multiselect/issues/86) and [#136](https://github.com/janosh/svelte-multiselect/issues/136) welcome!
346
346
 
347
- ## Slots
347
+ ## 🎰 &nbsp; Slots
348
348
 
349
- `MultiSelect.svelte` has 3 named slots:
349
+ `MultiSelect.svelte` accepts the following named slots:
350
350
 
351
- - `slot="option"`: Customize rendering of dropdown options. Receives as props an `option` and the zero-indexed position (`idx`) it has in the dropdown.
352
- - `slot="selected"`: Customize rendering of selected items. Receives as props an `option` and the zero-indexed position (`idx`) it has in the list of selected items.
353
- - `slot="spinner"`: Custom spinner component to display when in `loading` state. Receives no props.
354
- - `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.
355
- - `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.
351
+ 1. `slot="option"`: Customize rendering of dropdown options. Receives as props an `option` and the zero-indexed position (`idx`) it has in the dropdown.
352
+ 1. `slot="selected"`: Customize rendering of selected items. Receives as props an `option` and the zero-indexed position (`idx`) it has in the list of selected items.
353
+ 1. `slot="spinner"`: Custom spinner component to display when in `loading` state. Receives no props.
354
+ 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.
355
+ 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.
356
+ 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.
356
357
 
357
358
  Example:
358
359
 
359
- ```html
360
+ ```svelte
360
361
  <MultiSelect options={[`Red`, `Green`, `Blue`, `Yellow`, `Purple`]}>
361
362
  <span let:idx let:option slot="option">
362
363
  {idx + 1}
@@ -375,7 +376,7 @@ Example:
375
376
  </MultiSelect>
376
377
  ```
377
378
 
378
- ## Events
379
+ ## 🎬 &nbsp; Events
379
380
 
380
381
  `MultiSelect.svelte` dispatches the following events:
381
382
 
@@ -417,7 +418,7 @@ Example:
417
418
 
418
419
  For example, here's how you might annoy your users with an alert every time one or more options are added or removed:
419
420
 
420
- ```html
421
+ ```svelte
421
422
  <MultiSelect
422
423
  on:change={(e) => {
423
424
  if (e.detail.type === 'add') alert(`You added ${e.detail.option}`)
@@ -431,18 +432,18 @@ For example, here's how you might annoy your users with an alert every time one
431
432
 
432
433
  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:
433
434
 
434
- ```html
435
+ ```svelte
435
436
  <MultiSelect
436
437
  options={[1, 2, 3]}
437
438
  on:keyup={(event) => console.log('key', event.target.value)}
438
439
  />
439
440
  ```
440
441
 
441
- ## TypeScript
442
+ ## 🦺 &nbsp; TypeScript
442
443
 
443
444
  TypeScript users can import the types used for internal type safety:
444
445
 
445
- ```html
446
+ ```svelte
446
447
  <script lang="ts">
447
448
  import MultiSelect from 'svelte-multiselect'
448
449
  import type { Option, ObjectOption } from 'svelte-multiselect'
@@ -456,11 +457,11 @@ TypeScript users can import the types used for internal type safety:
456
457
  </script>
457
458
  ```
458
459
 
459
- ## Styling
460
+ ## ✨ &nbsp; Styling
460
461
 
461
462
  There are 3 ways to style this component. To understand which options do what, it helps to keep in mind this simplified DOM structure of the component:
462
463
 
463
- ```html
464
+ ```svelte
464
465
  <div class="multiselect">
465
466
  <ul class="selected">
466
467
  <li>Selected 1</li>
@@ -484,8 +485,8 @@ If you only want to make small adjustments, you can pass the following CSS varia
484
485
  - `background: var(--sms-bg)`
485
486
  - `color: var(--sms-text-color)`
486
487
  - `min-height: var(--sms-min-height, 22pt)`
487
- - `width: var(--sms-width)`
488
- - `max-width: var(--sms-max-width)`
488
+ - `width: var(--sms-width, 100%)`
489
+ - `max-width: var(--sms-max-width, 800px)`
489
490
  - `margin: var(--sms-margin)`
490
491
  - `font-size: var(--sms-font-size, inherit)`
491
492
  - `div.multiselect.open`
@@ -522,7 +523,7 @@ If you only want to make small adjustments, you can pass the following CSS varia
522
523
 
523
524
  For example, to change the background color of the options dropdown:
524
525
 
525
- ```html
526
+ ```svelte
526
527
  <MultiSelect --sms-options-bg="white" />
527
528
  ```
528
529
 
@@ -540,7 +541,7 @@ The second method allows you to pass in custom classes to the important DOM elem
540
541
 
541
542
  This simplified version of the DOM structure of the component shows where these classes are inserted:
542
543
 
543
- ```html
544
+ ```svelte
544
545
  <div class="multiselect {outerDivClass}">
545
546
  <input class={inputClass} />
546
547
  <ul class="selected {ulSelectedClass}">
@@ -559,7 +560,7 @@ This simplified version of the DOM structure of the component shows where these
559
560
 
560
561
  ### With global CSS
561
562
 
562
- Odd as it may seem, you get the most fine-grained control over the styling of every part of this component by using the following `:global()` CSS selectors. `ul.selected` is the list of currently selected options rendered inside the component's input whereas `ul.options` is the list of available options that slides out when the component is in its `open` state. See also [simplified DOM structure](#styling).
563
+ Odd as it may seem, you get the most fine-grained control over the styling of every part of this component by using the following `:global()` CSS selectors. `ul.selected` is the list of currently selected options rendered inside the component's input whereas `ul.options` is the list of available options that slides out when the component is in its `open` state. See also [simplified DOM structure](#--styling).
563
564
 
564
565
  ```css
565
566
  :global(div.multiselect) {
@@ -607,6 +608,10 @@ Odd as it may seem, you get the most fine-grained control over the styling of ev
607
608
  }
608
609
  ```
609
610
 
610
- ## Want to contribute to this project?
611
+ ## 🆕 &nbsp; Changelog
612
+
613
+ [View the changelog](changelog.md).
614
+
615
+ ## 🙏 &nbsp; Contributing
611
616
 
612
- [Here are some steps](https://github.com/janosh/svelte-multiselect/blob/main/contributing.md) to get you started!
617
+ Here are some steps to [get you started](contributing.md) if you'd like to contribute to this project!