svelte-multiselect 8.2.3 โ†’ 8.2.4

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.
@@ -14,6 +14,7 @@ export let defaultDisabledTitle = `This option is disabled`;
14
14
  export let disabled = false;
15
15
  export let disabledInputTitle = `This input is disabled`;
16
16
  // case-insensitive equality comparison after string coercion (looking only at the `label` key of object options)
17
+ // prettier-ignore
17
18
  export let duplicateFunc = (op1, op2) => `${get_label(op1)}`.toLowerCase() === `${get_label(op2)}`.toLowerCase();
18
19
  export let duplicateOptionMsg = `This option is already selected`;
19
20
  export let duplicates = false; // whether to allow duplicate options
@@ -53,7 +54,7 @@ export let required = false;
53
54
  export let resetFilterOnAdd = true;
54
55
  export let searchText = ``;
55
56
  export let selected = options
56
- ?.filter((op) => op?.preselected)
57
+ ?.filter((op) => op instanceof Object && op?.preselected)
57
58
  .slice(0, maxSelect ?? undefined) ?? [];
58
59
  export let sortSelected = false;
59
60
  export let selectedOptionsDraggable = !sortSelected;
@@ -123,7 +124,7 @@ function add(label, event) {
123
124
  // a new option from the user-entered text
124
125
  if (typeof options[0] === `object`) {
125
126
  // if 1st option is an object, we create new option as object to keep type homogeneity
126
- option = { label: searchText, value: searchText };
127
+ option = { label: searchText };
127
128
  }
128
129
  else {
129
130
  if ([`number`, `undefined`].includes(typeof options[0]) &&
@@ -147,7 +148,7 @@ function add(label, event) {
147
148
  return;
148
149
  }
149
150
  if (maxSelect === 1) {
150
- // for maxselect = 1 we always replace current option with new one
151
+ // for maxSelect = 1 we always replace current option with new one
151
152
  selected = [option];
152
153
  }
153
154
  else {
@@ -183,7 +184,7 @@ function remove(label) {
183
184
  selected = selected; // Svelte rerender after in-place splice
184
185
  const option = options.find((option) => get_label(option) === label) ??
185
186
  // if option with label could not be found but allowUserOptions is truthy,
186
- // assume it was created by user and create correspondidng option object
187
+ // assume it was created by user and create corresponding option object
187
188
  // on the fly for use as event payload
188
189
  (allowUserOptions && { label, value: label });
189
190
  if (!option) {
@@ -212,7 +213,7 @@ function close_dropdown(event) {
212
213
  }
213
214
  // handle all keyboard events this component receives
214
215
  async function handle_keydown(event) {
215
- // on escape or tab out of input: dismiss options dropdown and reset search text
216
+ // on escape or tab out of input: close options dropdown and reset search text
216
217
  if (event.key === `Escape` || event.key === `Tab`) {
217
218
  close_dropdown(event);
218
219
  searchText = ``;
@@ -375,9 +376,10 @@ const dragstart = (idx) => (event) => {
375
376
  on:dragstart={dragstart(idx)}
376
377
  on:drop|preventDefault={drop(idx)}
377
378
  on:dragenter={() => (drag_idx = idx)}
379
+ on:dragover|preventDefault
378
380
  class:active={drag_idx === idx}
379
- ondragover="return false"
380
381
  >
382
+ <!-- on:dragover|preventDefault needed for the drop to succeed https://stackoverflow.com/a/31085796 -->
381
383
  <slot name="selected" {option} {idx}>
382
384
  {#if parseLabelsAsHtml}
383
385
  {@html get_label(option)}
@@ -1,7 +1,7 @@
1
1
  import { SvelteComponentTyped } from "svelte";
2
- import type { MultiSelectEvents, Option } from './';
3
- declare const __propDef: {
4
- props: {
2
+ import type { MultiSelectEvents, Option as GenericOption } from './';
3
+ declare class __sveltets_Render<Option extends GenericOption> {
4
+ props(): {
5
5
  activeIndex?: number | null | undefined;
6
6
  activeOption?: Option | null | undefined;
7
7
  addOptionMsg?: string | undefined;
@@ -12,7 +12,7 @@ declare const __propDef: {
12
12
  defaultDisabledTitle?: string | undefined;
13
13
  disabled?: boolean | undefined;
14
14
  disabledInputTitle?: string | undefined;
15
- duplicateFunc?: ((op1: Option, op2: Option) => boolean) | undefined;
15
+ duplicateFunc?: ((op1: GenericOption, op2: GenericOption) => boolean) | undefined;
16
16
  duplicateOptionMsg?: string | undefined;
17
17
  duplicates?: boolean | undefined;
18
18
  filterFunc?: ((op: Option, searchText: string) => boolean) | undefined;
@@ -53,7 +53,8 @@ declare const __propDef: {
53
53
  ulSelectedClass?: string | undefined;
54
54
  value?: Option | Option[] | null | undefined;
55
55
  };
56
- slots: {
56
+ events(): MultiSelectEvents;
57
+ slots(): {
57
58
  'expand-icon': {
58
59
  open: boolean;
59
60
  };
@@ -69,11 +70,10 @@ declare const __propDef: {
69
70
  idx: any;
70
71
  };
71
72
  };
72
- events: MultiSelectEvents;
73
- };
74
- export type MultiSelectProps = typeof __propDef.props;
75
- export type MultiSelectEvents = typeof __propDef.events;
76
- export type MultiSelectSlots = typeof __propDef.slots;
77
- export default class MultiSelect extends SvelteComponentTyped<MultiSelectProps, MultiSelectEvents, MultiSelectSlots> {
73
+ }
74
+ export type MultiSelectProps<Option extends GenericOption> = ReturnType<__sveltets_Render<Option>['props']>;
75
+ export type MultiSelectEvents<Option extends GenericOption> = ReturnType<__sveltets_Render<Option>['events']>;
76
+ export type MultiSelectSlots<Option extends GenericOption> = ReturnType<__sveltets_Render<Option>['slots']>;
77
+ export default class MultiSelect<Option extends GenericOption> extends SvelteComponentTyped<MultiSelectProps<Option>, MultiSelectEvents<Option>, MultiSelectSlots<Option>> {
78
78
  }
79
79
  export {};
package/changelog.md CHANGED
@@ -2,6 +2,21 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file. Dates are displayed in UTC.
4
4
 
5
+ #### [v8.2.4](https://github.com/janosh/svelte-multiselect/compare/v8.2.3...v8.2.4)
6
+
7
+ > 8 January 2023
8
+
9
+ - Coverage badges [`#190`](https://github.com/janosh/svelte-multiselect/pull/190)
10
+ - feat: add type inference for the `options` prop [`#189`](https://github.com/janosh/svelte-multiselect/pull/189)
11
+ - feat: add type inference for the `options` prop (#189) [`#78`](https://github.com/janosh/svelte-multiselect/issues/78)
12
+ - merge ExampleCode.svelte with CollapsibleCode.svelte [`56ff99b`](https://github.com/janosh/svelte-multiselect/commit/56ff99bcc378c5582b303aa1c03302cdbceb3076)
13
+ - pnpm add -D svelte-zoo to outsource some site components and icons [`6ee64f3`](https://github.com/janosh/svelte-multiselect/commit/6ee64f376dfe166b993c94a36d376d1dce5f44f5)
14
+ - restore reactive searchText block in loading example [`846da66`](https://github.com/janosh/svelte-multiselect/commit/846da66af058ac1f448c8aaa513d12fb4c2ac4cc)
15
+ - fix bunch of TS errors, add playwright test for dragging selected options to reorder [`a483217`](https://github.com/janosh/svelte-multiselect/commit/a4832176f6fceb5346af2d4cd8ecc01a5626ab43)
16
+ - add update-coverage package.json script [`1094f08`](https://github.com/janosh/svelte-multiselect/commit/1094f08cec9d6fd2f54b058af05022ab35ec4ac9)
17
+ - add vite alias $root to clean up package.json, readme|contributing|changelog.md imports [`c19cbe4`](https://github.com/janosh/svelte-multiselect/commit/c19cbe4e38413bbcd04d4e35eddcd4cd88c67662)
18
+ - mv src/components src/site [`3683ed7`](https://github.com/janosh/svelte-multiselect/commit/3683ed70f19498070ffe9e95c0261c688fb2f7c7)
19
+
5
20
  <!-- auto-changelog-above -->
6
21
 
7
22
  #### [v8.2.3](https://github.com/janosh/svelte-multiselect/compare/v8.2.2...v8.2.3)
@@ -116,7 +131,7 @@ All notable changes to this project will be documented in this file. Dates are d
116
131
 
117
132
  - Fix single select with arrow and enter keys [`#128`](https://github.com/janosh/svelte-multiselect/pull/128)
118
133
  - Add SCSS preprocessing [`#126`](https://github.com/janosh/svelte-multiselect/pull/126)
119
- - [pre-commit.ci] pre-commit autoupdate [`#124`](https://github.com/janosh/svelte-multiselect/pull/124)
134
+ - pre-commit autoupdate [`#124`](https://github.com/janosh/svelte-multiselect/pull/124)
120
135
  - more unit tests [`1adbc99`](https://github.com/janosh/svelte-multiselect/commit/1adbc994b746b39c4ad081dc2573bf37f27c96c0)
121
136
  - test required but empty MultiSelect fails form validity check (i.e. causes unsubmittable form) and filled one passes it [`fd8b377`](https://github.com/janosh/svelte-multiselect/commit/fd8b37782cd508aacfc8125c6647cefe56144b80)
122
137
 
@@ -186,7 +201,7 @@ All notable changes to this project will be documented in this file. Dates are d
186
201
  - Convert E2E tests from`vitest` to `@playwright/test` [`#95`](https://github.com/janosh/svelte-multiselect/pull/95)
187
202
  - Allow empty Multiselect [`#94`](https://github.com/janosh/svelte-multiselect/pull/94)
188
203
  - Add new slot `'remove-icon'` [`#93`](https://github.com/janosh/svelte-multiselect/pull/93)
189
- - [pre-commit.ci] pre-commit autoupdate [`#92`](https://github.com/janosh/svelte-multiselect/pull/92)
204
+ - pre-commit autoupdate [`#92`](https://github.com/janosh/svelte-multiselect/pull/92)
190
205
 
191
206
  #### [v5.0.3](https://github.com/janosh/svelte-multiselect/compare/v5.0.2...v5.0.3)
192
207
 
@@ -224,7 +239,7 @@ All notable changes to this project will be documented in this file. Dates are d
224
239
 
225
240
  - Fix backspace deleting multiple selected options if identical labels [`#72`](https://github.com/janosh/svelte-multiselect/pull/72)
226
241
  - Several fixes for `allowUserOptions` [`#69`](https://github.com/janosh/svelte-multiselect/pull/69)
227
- - [pre-commit.ci] pre-commit autoupdate [`#70`](https://github.com/janosh/svelte-multiselect/pull/70)
242
+ - pre-commit autoupdate [`#70`](https://github.com/janosh/svelte-multiselect/pull/70)
228
243
 
229
244
  #### [v4.0.5](https://github.com/janosh/svelte-multiselect/compare/v4.0.4...v4.0.5)
230
245
 
@@ -347,7 +362,7 @@ All notable changes to this project will be documented in this file. Dates are d
347
362
  - favorite web framework show Confetti.svelte on:add Svelte [`8d109ee`](https://github.com/janosh/svelte-multiselect/commit/8d109ee5c7755e447fcb72419f3b7ecc19cac0b2)
348
363
  - bump svelte@3.45.0 to silence warning: MultiSelect has unused export property 'defaultDisabledTitle' (sveltejs/svelte#6964) [`f80a7a6`](https://github.com/janosh/svelte-multiselect/commit/f80a7a622310005407585298f2611597c0941990)
349
364
  - update readme + svelte-toc@0.2.0 [`40013ba`](https://github.com/janosh/svelte-multiselect/commit/40013badd61dd0fcade7ab295dabd26693e3cc51)
350
- - [pre-commit.ci] pre-commit autoupdate [`0d05864`](https://github.com/janosh/svelte-multiselect/commit/0d05864d19987460dd30d667eb22deb91a520668)
365
+ - pre-commit autoupdate [`0d05864`](https://github.com/janosh/svelte-multiselect/commit/0d05864d19987460dd30d667eb22deb91a520668)
351
366
  - iOS Safari prevent zoom into page on focus MultiSelect input [`44f17be`](https://github.com/janosh/svelte-multiselect/commit/44f17be53378e38f4a8748b815737d25cdebc85f)
352
367
 
353
368
  ### [v3.0.0](https://github.com/janosh/svelte-multiselect/compare/v2.0.0...v3.0.0)
@@ -398,7 +413,7 @@ All notable changes to this project will be documented in this file. Dates are d
398
413
 
399
414
  - Add new prop disabledOptions [`#9`](https://github.com/janosh/svelte-multiselect/pull/9)
400
415
  - add pre-commit hooks [`dfb6399`](https://github.com/janosh/svelte-multiselect/commit/dfb6399a77b705f8e5979eb887d345a5f52ff929)
401
- - [pre-commit.ci] pre-commit autoupdate [`b69425d`](https://github.com/janosh/svelte-multiselect/commit/b69425d18473122f1af889d2f48c60d02e43b99f)
416
+ - pre-commit autoupdate [`b69425d`](https://github.com/janosh/svelte-multiselect/commit/b69425d18473122f1af889d2f48c60d02e43b99f)
402
417
 
403
418
  #### [v1.1.11](https://github.com/janosh/svelte-multiselect/compare/v1.1.10...v1.1.11)
404
419
 
@@ -490,7 +505,7 @@ All notable changes to this project will be documented in this file. Dates are d
490
505
 
491
506
  - remove hidden input for storing currently selected options as JSON [`802a219`](https://github.com/janosh/svelte-multiselect/commit/802a2195a28986c219298d7d9e7ca47f2aaf7db6)
492
507
 
493
- #### v1.0.0
508
+ ### v1.0.0
494
509
 
495
510
  > 7 May 2021
496
511
 
@@ -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]: never;
5
+ [x: string]: any;
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]: never;
16
+ [x: string]: any;
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]: never;
5
+ [x: string]: any;
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]: never;
16
+ [x: string]: any;
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]: never;
5
+ [x: string]: any;
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]: never;
16
+ [x: string]: any;
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]: never;
5
+ [x: string]: any;
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]: never;
16
+ [x: string]: any;
17
17
  };
18
18
  events: {
19
19
  [evt: string]: CustomEvent<any>;
package/index.d.ts CHANGED
@@ -47,3 +47,4 @@ export type MultiSelectEvents = {
47
47
  touchmove: TouchEvent;
48
48
  touchstart: TouchEvent;
49
49
  };
50
+ export declare function scroll_into_view_if_needed_polyfill(centerIfNeeded?: boolean): IntersectionObserver;
package/index.js CHANGED
@@ -3,21 +3,25 @@ export { default } from './MultiSelect.svelte';
3
3
  // https://github.com/janosh/svelte-multiselect/issues/87
4
4
  // this polyfill was copied from
5
5
  // https://github.com/nuxodin/lazyfill/blob/a8e63/polyfills/Element/prototype/scrollIntoViewIfNeeded.js
6
+ // exported for testing
7
+ export function scroll_into_view_if_needed_polyfill(centerIfNeeded = true) {
8
+ const el = this;
9
+ const observer = new IntersectionObserver(function ([entry]) {
10
+ const ratio = entry.intersectionRatio;
11
+ if (ratio < 1) {
12
+ const place = ratio <= 0 && centerIfNeeded ? `center` : `nearest`;
13
+ el.scrollIntoView({
14
+ block: place,
15
+ inline: place,
16
+ });
17
+ }
18
+ this.disconnect();
19
+ });
20
+ observer.observe(this);
21
+ return observer; // return for testing
22
+ }
6
23
  if (typeof Element !== `undefined` &&
7
24
  !Element.prototype?.scrollIntoViewIfNeeded &&
8
25
  typeof IntersectionObserver !== `undefined`) {
9
- Element.prototype.scrollIntoViewIfNeeded = function (centerIfNeeded = true) {
10
- const el = this;
11
- new IntersectionObserver(function ([entry]) {
12
- const ratio = entry.intersectionRatio;
13
- if (ratio < 1) {
14
- const place = ratio <= 0 && centerIfNeeded ? `center` : `nearest`;
15
- el.scrollIntoView({
16
- block: place,
17
- inline: place,
18
- });
19
- }
20
- this.disconnect();
21
- }).observe(this);
22
- };
26
+ Element.prototype.scrollIntoViewIfNeeded = scroll_into_view_if_needed_polyfill;
23
27
  }
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.3",
8
+ "version": "8.2.4",
9
9
  "type": "module",
10
10
  "svelte": "index.js",
11
- "main": "index.js",
12
11
  "bugs": "https://github.com/janosh/svelte-multiselect/issues",
13
12
  "devDependencies": {
14
13
  "@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",
14
+ "@playwright/test": "^1.29.2",
15
+ "@sveltejs/adapter-static": "1.0.1",
16
+ "@sveltejs/kit": "1.0.7",
17
+ "@sveltejs/package": "1.0.2",
19
18
  "@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",
19
+ "@typescript-eslint/eslint-plugin": "^5.48.0",
20
+ "@typescript-eslint/parser": "^5.48.0",
21
+ "@vitest/coverage-c8": "^0.26.3",
22
+ "eslint": "^8.31.0",
24
23
  "eslint-plugin-svelte3": "^4.0.0",
25
- "hastscript": "^7.1.0",
24
+ "hastscript": "^7.2.0",
26
25
  "highlight.js": "^11.7.0",
27
- "jsdom": "^20.0.3",
26
+ "jsdom": "^21.0.0",
28
27
  "mdsvex": "^0.10.6",
29
28
  "mdsvexamples": "^0.3.3",
30
- "prettier": "^2.8.1",
29
+ "prettier": "^2.8.2",
31
30
  "prettier-plugin-svelte": "^2.9.0",
32
31
  "rehype-autolink-headings": "^6.1.1",
33
32
  "rehype-slug": "^5.1.0",
34
33
  "svelte": "^3.55.0",
35
- "svelte-check": "^2.10.2",
36
- "svelte-github-corner": "^0.1.0",
34
+ "svelte-check": "^3.0.1",
35
+ "svelte-github-corner": "^0.2.0",
37
36
  "svelte-preprocess": "^5.0.0",
38
- "svelte-toc": "^0.5.0",
39
- "svelte2tsx": "^0.5.22",
37
+ "svelte-toc": "^0.5.1",
38
+ "svelte-zoo": "^0.1.4",
39
+ "svelte2tsx": "^0.6.0",
40
40
  "tslib": "^2.4.1",
41
41
  "typescript": "^4.9.4",
42
- "vite": "^4.0.1",
43
- "vitest": "^0.25.8"
42
+ "vite": "^4.0.4",
43
+ "vitest": "^0.26.3"
44
44
  },
45
45
  "keywords": [
46
46
  "svelte",
package/readme.md CHANGED
@@ -21,7 +21,7 @@
21
21
 
22
22
  <slot name="examples" />
23
23
 
24
- ## ๐Ÿ’ก &nbsp; Features
24
+ ## ๐Ÿ’ก &thinsp; 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
@@ -34,7 +34,13 @@
34
34
 
35
35
  <slot name="nav" />
36
36
 
37
- ## ๐Ÿ“œ &nbsp; Breaking changes
37
+ ## ๐Ÿงช &thinsp; Coverage
38
+
39
+ | Statements | Branches | Lines |
40
+ | ------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------- |
41
+ | ![Statements](https://img.shields.io/badge/statements-92.95%25-brightgreen.svg?style=flat) | ![Branches](https://img.shields.io/badge/branches-100%25-brightgreen.svg?style=flat) | ![Lines](https://img.shields.io/badge/lines-92.95%25-brightgreen.svg?style=flat) |
42
+
43
+ ## ๐Ÿ“œ &thinsp; Breaking changes
38
44
 
39
45
  - **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
46
  - **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,15 +48,15 @@
42
48
  - 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
49
  - Prop `noOptionsMsg` was renamed to `noMatchingOptionsMsg`. [PR 133](https://github.com/janosh/svelte-multiselect/pull/133).
44
50
 
45
- ## ๐Ÿ”จ &nbsp; Installation
51
+ ## ๐Ÿ”จ &thinsp; Installation
46
52
 
47
53
  ```sh
48
- npm install -D svelte-multiselect
49
- pnpm add -D svelte-multiselect
50
- yarn add -D svelte-multiselect
54
+ npm install --dev svelte-multiselect
55
+ pnpm add --dev svelte-multiselect
56
+ yarn add --dev svelte-multiselect
51
57
  ```
52
58
 
53
- ## ๐Ÿ“™ &nbsp; Usage
59
+ ## ๐Ÿ“™ &thinsp; Usage
54
60
 
55
61
  ```svelte
56
62
  <script>
@@ -68,7 +74,7 @@ Favorite Frontend Tools?
68
74
  <MultiSelect bind:selected options={ui_libs} />
69
75
  ```
70
76
 
71
- ## ๐Ÿ”ฃ &nbsp; Props
77
+ ## ๐Ÿ”ฃ &thinsp; Props
72
78
 
73
79
  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
80
 
@@ -135,7 +141,7 @@ Full list of props/bindable variables for this component. The `Option` type you
135
141
 
136
142
  <!-- prettier-ignore -->
137
143
  1. ```ts
138
- duplicateFunc: (op1: Option, op2: Option) => boolean = (op1, op2) =>
144
+ duplicateFunc: (op1: GenericOption, op2: GenericOption) => boolean = (op1, op2) =>
139
145
  `${get_label(op1)}`.toLowerCase() === `${get_label(op2)}`.toLowerCase()
140
146
  ```
141
147
 
@@ -344,7 +350,7 @@ Full list of props/bindable variables for this component. The `Option` type you
344
350
 
345
351
  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
352
 
347
- ## ๐ŸŽฐ &nbsp; Slots
353
+ ## ๐ŸŽฐ &thinsp; Slots
348
354
 
349
355
  `MultiSelect.svelte` accepts the following named slots:
350
356
 
@@ -376,7 +382,7 @@ Example:
376
382
  </MultiSelect>
377
383
  ```
378
384
 
379
- ## ๐ŸŽฌ &nbsp; Events
385
+ ## ๐ŸŽฌ &thinsp; Events
380
386
 
381
387
  `MultiSelect.svelte` dispatches the following events:
382
388
 
@@ -439,25 +445,36 @@ The above list of events are [Svelte `dispatch` events](https://svelte.dev/tutor
439
445
  />
440
446
  ```
441
447
 
442
- ## ๐Ÿฆบ &nbsp; TypeScript
448
+ ## ๐Ÿฆบ &thinsp; TypeScript
443
449
 
444
- TypeScript users can import the types used for internal type safety:
450
+ The type of `options` is inferred automatically from the data you pass. E.g.
445
451
 
446
- ```svelte
447
- <script lang="ts">
448
- import MultiSelect from 'svelte-multiselect'
449
- import type { Option, ObjectOption } from 'svelte-multiselect'
450
-
451
- const myOptions: ObjectOption[] = [
452
- { label: 'foo', value: 42 },
453
- { label: 'bar', value: 69 },
454
- ]
455
- // an Option can be string | number | ObjectOption
456
- const myNumbers: Option[] = [42, 69]
457
- </script>
452
+ ```ts
453
+ const options = [
454
+ { label: `foo`, value: 42 }
455
+ { label: `bar`, value: 69 }
456
+ ]
457
+ // type Option = { label: string, value: number }
458
+ const options = [`foo`, `bar`]
459
+ // type Option = string
460
+ const options = [42, 69]
461
+ // type Option = number
462
+ ```
463
+
464
+ The inferred type of `Option` is used to enforce type-safety on derived props like `selected` as well as slot components. E.g. you'll get an error when trying to use a slot component 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).
465
+
466
+ You can also import [the types this component uses](https://github.com/janosh/svelte-multiselect/blob/main/src/lib/index.ts) for downstream applications:
467
+
468
+ ```ts
469
+ import {
470
+ Option,
471
+ ObjectOption,
472
+ DispatchEvents,
473
+ MultiSelectEvents,
474
+ } from 'svelte-multiselect'
458
475
  ```
459
476
 
460
- ## โœจ &nbsp; Styling
477
+ ## โœจ &thinsp; Styling
461
478
 
462
479
  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:
463
480
 
@@ -608,10 +625,10 @@ Odd as it may seem, you get the most fine-grained control over the styling of ev
608
625
  }
609
626
  ```
610
627
 
611
- ## ๐Ÿ†• &nbsp; Changelog
628
+ ## ๐Ÿ†• &thinsp; Changelog
612
629
 
613
630
  [View the changelog](changelog.md).
614
631
 
615
- ## ๐Ÿ™ &nbsp; Contributing
632
+ ## ๐Ÿ™ &thinsp; Contributing
616
633
 
617
634
  Here are some steps to [get you started](contributing.md) if you'd like to contribute to this project!