svelte-multiselect 11.5.1 → 11.6.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/types.d.ts CHANGED
@@ -62,6 +62,30 @@ export interface MultiSelectEvents<T extends Option = Option> {
62
62
  onexpandAll?: (data: {
63
63
  groups: string[];
64
64
  }) => unknown;
65
+ onsearch?: (data: {
66
+ searchText: string;
67
+ matchingCount: number;
68
+ }) => unknown;
69
+ onmaxreached?: (data: {
70
+ selected: T[];
71
+ maxSelect: number;
72
+ attemptedOption: T;
73
+ }) => unknown;
74
+ onduplicate?: (data: {
75
+ option: T;
76
+ }) => unknown;
77
+ onactivate?: (data: {
78
+ option: T | null;
79
+ index: number | null;
80
+ }) => unknown;
81
+ onundo?: (data: {
82
+ previous: T[];
83
+ current: T[];
84
+ }) => unknown;
85
+ onredo?: (data: {
86
+ previous: T[];
87
+ current: T[];
88
+ }) => unknown;
65
89
  }
66
90
  export interface LoadOptionsParams {
67
91
  search: string;
@@ -206,11 +230,32 @@ export interface MultiSelectProps<T extends Option = Option> extends MultiSelect
206
230
  collapseAllGroups?: () => void;
207
231
  expandAllGroups?: () => void;
208
232
  shortcuts?: Partial<KeyboardShortcuts>;
233
+ history?: boolean | number;
234
+ undo?: () => boolean;
235
+ redo?: () => boolean;
236
+ canUndo?: boolean;
237
+ canRedo?: boolean;
209
238
  }
210
239
  export interface KeyboardShortcuts {
211
240
  select_all?: string | null;
212
241
  clear_all?: string | null;
213
242
  open?: string | null;
214
243
  close?: string | null;
244
+ undo?: string | null;
245
+ redo?: string | null;
246
+ }
247
+ export interface NavRouteObject {
248
+ href: string;
249
+ label?: string;
250
+ children?: string[];
251
+ disabled?: boolean | string;
252
+ separator?: boolean;
253
+ align?: `left` | `right`;
254
+ external?: boolean;
255
+ tooltip?: string;
256
+ class?: string;
257
+ style?: string;
258
+ [key: string]: unknown;
215
259
  }
260
+ export type NavRoute = string | [string, string] | [string, string[]] | NavRouteObject;
216
261
  export {};
package/dist/utils.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import type { Option } from './types';
2
+ export declare function get_uuid(): string;
2
3
  export declare const is_object: (val: unknown) => val is Record<string, unknown>;
3
4
  export declare const has_group: <T extends Option>(opt: T) => opt is T & {
4
5
  group: string;
package/dist/utils.js CHANGED
@@ -1,3 +1,14 @@
1
+ let uuid_counter = 0;
2
+ // Generates a UUID for component IDs. Uses native crypto.randomUUID when available.
3
+ // Fallback uses timestamp+counter - sufficient for DOM IDs (uniqueness, not security).
4
+ // Cryptographic randomness is unnecessary here since these IDs are only used for
5
+ // associating labels with inputs and ensuring unique DOM element identifiers.
6
+ export function get_uuid() {
7
+ if (globalThis.crypto?.randomUUID)
8
+ return globalThis.crypto.randomUUID();
9
+ const hex = (Date.now().toString(16) + (uuid_counter++).toString(16)).padStart(32, `0`);
10
+ return hex.replace(/(.{8})(.{4})(.{4})(.{4})(.{12})/, `$1-$2-$3-$4-$5`);
11
+ }
1
12
  // Type guard for checking if a value is a non-null object
2
13
  export const is_object = (val) => typeof val === `object` && val !== null;
3
14
  // Type guard for checking if an option has a group key
package/package.json CHANGED
@@ -5,7 +5,7 @@
5
5
  "homepage": "https://janosh.github.io/svelte-multiselect",
6
6
  "repository": "https://github.com/janosh/svelte-multiselect",
7
7
  "license": "MIT",
8
- "version": "11.5.1",
8
+ "version": "11.6.0",
9
9
  "type": "module",
10
10
  "scripts": {
11
11
  "dev": "vite dev",
@@ -13,40 +13,52 @@
13
13
  "preview": "vite preview",
14
14
  "test": "vitest --run && playwright test",
15
15
  "check": "svelte-check",
16
- "package": "svelte-package",
17
- "prepublishOnly": "svelte-package && test -d dist"
16
+ "package": "svelte-package && find dist -name '*.js' -o -name '*.d.ts' | xargs sed -i '' -E \"s/(\\.\\.?\\/[^'\\\"]*)\\.ts(['\\\"])/\\1.js\\2/g\"",
17
+ "prepublishOnly": "pnpm package"
18
18
  },
19
19
  "svelte": "./dist/index.js",
20
20
  "bugs": "https://github.com/janosh/svelte-multiselect/issues",
21
21
  "peerDependencies": {
22
- "svelte": "^5.35.6"
22
+ "@wooorm/starry-night": "^3.0.0",
23
+ "abstract-syntax-tree": "^2.0.0",
24
+ "svelte": "^5.48.0",
25
+ "svelte-preprocess": "^6.0.0"
26
+ },
27
+ "peerDependenciesMeta": {
28
+ "@wooorm/starry-night": {
29
+ "optional": true
30
+ },
31
+ "abstract-syntax-tree": {
32
+ "optional": true
33
+ },
34
+ "svelte-preprocess": {
35
+ "optional": true
36
+ }
23
37
  },
24
38
  "devDependencies": {
25
- "@playwright/test": "^1.57.0",
26
- "@stylistic/eslint-plugin": "^5.6.1",
39
+ "@playwright/test": "^1.58.0",
40
+ "@stylistic/eslint-plugin": "^5.7.1",
27
41
  "@sveltejs/adapter-static": "^3.0.10",
28
- "@sveltejs/kit": "^2.49.2",
42
+ "@sveltejs/kit": "^2.50.1",
29
43
  "@sveltejs/package": "2.5.7",
30
- "@sveltejs/vite-plugin-svelte": "^6.2.1",
31
- "@types/node": "^25.0.3",
32
- "@vitest/coverage-v8": "^4.0.16",
44
+ "@sveltejs/vite-plugin-svelte": "^6.2.4",
45
+ "@types/node": "^25.0.10",
46
+ "@vitest/coverage-v8": "^4.0.18",
47
+ "@wooorm/starry-night": "^3.9.0",
48
+ "abstract-syntax-tree": "^2.22.0",
33
49
  "eslint": "^9.39.2",
34
- "eslint-plugin-svelte": "^3.13.1",
35
- "happy-dom": "^20.0.11",
36
- "hastscript": "^9.0.1",
50
+ "eslint-plugin-svelte": "^3.14.0",
51
+ "happy-dom": "^20.3.7",
37
52
  "mdsvex": "^0.12.6",
38
- "mdsvexamples": "^0.5.0",
39
- "rehype-autolink-headings": "^7.1.0",
40
- "rehype-slug": "^6.0.0",
41
- "svelte": "^5.46.1",
53
+ "svelte": "^5.48.2",
42
54
  "svelte-check": "^4.3.5",
43
55
  "svelte-preprocess": "^6.0.3",
44
56
  "svelte-toc": "^0.6.2",
45
57
  "svelte2tsx": "^0.7.46",
46
58
  "typescript": "5.9.3",
47
- "typescript-eslint": "^8.51.0",
48
- "vite": "^7.3.0",
49
- "vitest": "^4.0.16"
59
+ "typescript-eslint": "^8.53.1",
60
+ "vite": "^7.3.1",
61
+ "vitest": "^4.0.18"
50
62
  },
51
63
  "keywords": [
52
64
  "svelte",
@@ -72,6 +84,18 @@
72
84
  "./attachments": {
73
85
  "types": "./dist/attachments.d.ts",
74
86
  "default": "./dist/attachments.js"
87
+ },
88
+ "./utils": {
89
+ "types": "./dist/utils.d.ts",
90
+ "default": "./dist/utils.js"
91
+ },
92
+ "./heading-anchors": {
93
+ "types": "./dist/heading-anchors.d.ts",
94
+ "default": "./dist/heading-anchors.js"
95
+ },
96
+ "./live-examples": {
97
+ "types": "./dist/live-examples/index.d.ts",
98
+ "default": "./dist/live-examples/index.js"
75
99
  }
76
100
  },
77
101
  "types": "./dist/index.d.ts",
package/readme.md CHANGED
@@ -802,6 +802,30 @@ Example using several snippets:
802
802
 
803
803
  Triggers when the dropdown list of options disappears. `event` is the DOM's `FocusEvent`, `KeyboardEvent` or `ClickEvent` that triggered the close.
804
804
 
805
+ 1. ```ts
806
+ onsearch={({ searchText, matchingCount }) => console.log(searchText, matchingCount)}
807
+ ```
808
+
809
+ Triggers (debounced, 150ms) when the search text changes. Useful for analytics or loading remote options. `searchText` is the current input value, `matchingCount` is the number of options that match.
810
+
811
+ 1. ```ts
812
+ onmaxreached={({ selected, maxSelect, attemptedOption }) => console.log(attemptedOption)}
813
+ ```
814
+
815
+ Triggers when a user tries to select more options than `maxSelect` allows. Useful for showing feedback. Does not fire for `maxSelect=1` (which uses replace behavior).
816
+
817
+ 1. ```ts
818
+ onduplicate={({ option }) => console.log(`Duplicate:`, option)}
819
+ ```
820
+
821
+ Triggers when a user tries to add an already-selected option (when `duplicates=false`). Useful for showing feedback to the user.
822
+
823
+ 1. ```ts
824
+ onactivate={({ option, index }) => console.log(`Active:`, option, index)}
825
+ ```
826
+
827
+ Triggers during keyboard navigation (ArrowUp/ArrowDown) through options. `option` is the newly active option, `index` is its position. Does not fire on mouse hover.
828
+
805
829
  For example, here's how you might annoy your users with an alert every time one or more options are added or removed:
806
830
 
807
831
  ```svelte
@@ -987,7 +1011,7 @@ This simplified version of the DOM structure of the component shows where these
987
1011
 
988
1012
  ### With global CSS
989
1013
 
990
- 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).
1014
+ 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).
991
1015
 
992
1016
  ```css
993
1017
  :global(div.multiselect) {