svelte-typeahead 2.4.1 → 4.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "svelte-typeahead",
3
- "version": "2.4.1",
3
+ "version": "4.2.0",
4
4
  "license": "MIT",
5
5
  "description": "Accessible, fuzzy search typeahead component",
6
6
  "author": "Eric Liu (https://github.com/metonym)",
@@ -14,17 +14,17 @@
14
14
  "predeploy": "rollup -c",
15
15
  "deploy": "npx gh-pages -d dist",
16
16
  "prepack": "BUNDLE=true rollup -c",
17
- "test": "svelte-check"
17
+ "test": "svelte-check --workspace test"
18
18
  },
19
19
  "dependencies": {
20
20
  "fuzzy": "0.1.3",
21
- "svelte-search": "^1.0.0"
21
+ "svelte-search": "^1.1.0"
22
22
  },
23
23
  "devDependencies": {
24
- "@rollup/plugin-commonjs": "^17.1.0",
25
- "svelte": "^3.35.0",
26
- "svelte-check": "^1.2.5",
27
- "svelte-readme": "^3.0.0"
24
+ "@rollup/plugin-commonjs": "^21.0.1",
25
+ "svelte": "^3.44.0",
26
+ "svelte-check": "^2.2.6",
27
+ "svelte-readme": "^3.4.1"
28
28
  },
29
29
  "repository": {
30
30
  "type": "git",
@@ -1,25 +1,21 @@
1
1
  <script>
2
2
  /**
3
- * @typedef {string | number | Record<string, any>} Item
4
- * @typedef {{ original: Item; index: number; score: number; string: string; }} FuzzyResult
5
- * @event {{ searched: string; selected: Item; selectedIndex: number; original: Item; originalIndex: number; }} select
6
- * @event {any} clear
7
- * @slot {{ result: FuzzyResult; index: number }}
3
+ * @template TItem = string | number | Record<string, any>
8
4
  */
9
5
 
10
6
  export let id = "typeahead-" + Math.random().toString(36);
11
7
  export let value = "";
12
8
 
13
- /** @type {Item[]} */
9
+ /** @type {TItem[]} */
14
10
  export let data = [];
15
11
 
16
- /** @type {(item: Item) => Item} */
12
+ /** @type {(item: TItem) => any} */
17
13
  export let extract = (item) => item;
18
14
 
19
- /** @type {(item: Item) => Item} */
15
+ /** @type {(item: TItem) => boolean} */
20
16
  export let disable = (item) => false;
21
17
 
22
- /** @type {(item: Item) => Item} */
18
+ /** @type {(item: TItem) => boolean} */
23
19
  export let filter = (item) => false;
24
20
 
25
21
  /** Set to `false` to prevent the first result from being selected */
@@ -31,7 +27,7 @@
31
27
  */
32
28
  export let inputAfterSelect = "update";
33
29
 
34
- /** @type {FuzzyResult[]} */
30
+ /** @type {{ original: TItem; index: number; score: number; string: string; }[]} */
35
31
  export let results = [];
36
32
 
37
33
  /** Set to `true` to re-focus the input after selecting a result */
@@ -60,7 +56,7 @@
60
56
  selectedIndex = 0;
61
57
  }
62
58
 
63
- if (prevResults !== resultsId) {
59
+ if (prevResults !== resultsId && !$$slots["no-results"]) {
64
60
  hideDropdown = results.length === 0;
65
61
  }
66
62
 
@@ -102,12 +98,7 @@
102
98
 
103
99
  <svelte:window
104
100
  on:click={({ target }) => {
105
- if (
106
- !hideDropdown &&
107
- results.length > 0 &&
108
- comboboxRef &&
109
- !comboboxRef.contains(target)
110
- ) {
101
+ if (!hideDropdown && comboboxRef && !comboboxRef.contains(target)) {
111
102
  hideDropdown = true;
112
103
  }
113
104
  }}
@@ -125,12 +116,17 @@
125
116
  >
126
117
  <Search
127
118
  {id}
119
+ removeFormAriaAttributes={true}
128
120
  {...$$restProps}
129
121
  bind:ref={searchRef}
130
122
  aria-autocomplete="list"
131
123
  aria-controls="{id}-listbox"
132
124
  aria-labelledby="{id}-label"
133
- aria-activedescendant=""
125
+ aria-activedescendant={selectedIndex >= 0 &&
126
+ !hideDropdown &&
127
+ results.length > 0
128
+ ? `${id}-result-${selectedIndex}`
129
+ : null}
134
130
  bind:value
135
131
  on:type
136
132
  on:input
@@ -146,6 +142,8 @@
146
142
  on:blur
147
143
  on:keydown
148
144
  on:keydown={(e) => {
145
+ if (results.length === 0) return;
146
+
149
147
  switch (e.key) {
150
148
  case "Enter":
151
149
  select();
@@ -173,13 +171,13 @@
173
171
  }
174
172
  }}
175
173
  />
176
- {#if !hideDropdown && results.length > 0}
177
- <ul
178
- class:svelte-typeahead-list={true}
179
- role="listbox"
180
- aria-labelledby="{id}-label"
181
- id="{id}-listbox"
182
- >
174
+ <ul
175
+ class:svelte-typeahead-list={true}
176
+ role="listbox"
177
+ aria-labelledby="{id}-label"
178
+ id="{id}-listbox"
179
+ >
180
+ {#if !hideDropdown && results.length > 0}
183
181
  {#each results as result, i}
184
182
  <li
185
183
  role="option"
@@ -194,13 +192,18 @@
194
192
  }
195
193
  }}
196
194
  >
197
- <slot {result} index={i}>
195
+ <slot {result} index={i} {value}>
198
196
  {@html result.string}
199
197
  </slot>
200
198
  </li>
201
199
  {/each}
202
- </ul>
203
- {/if}
200
+ {/if}
201
+ {#if $$slots["no-results"] && !hideDropdown && value.length > 0 && results.length === 0}
202
+ <div class:no-results={true}>
203
+ <slot name="no-results" {value} />
204
+ </div>
205
+ {/if}
206
+ </ul>
204
207
  </div>
205
208
 
206
209
  <style>
@@ -220,8 +223,12 @@
220
223
  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
221
224
  }
222
225
 
223
- li {
226
+ li,
227
+ .no-results {
224
228
  padding: 0.25rem 1rem;
229
+ }
230
+
231
+ li {
225
232
  cursor: pointer;
226
233
  }
227
234
 
@@ -2,16 +2,7 @@
2
2
  import { SvelteComponentTyped } from "svelte";
3
3
  import { SearchProps } from "svelte-search/types/Search";
4
4
 
5
- export type Item = string | number | Record<string, any>;
6
-
7
- export interface FuzzyResult {
8
- original: Item;
9
- index: number;
10
- score: number;
11
- string: string;
12
- }
13
-
14
- export interface TypeaheadProps extends SearchProps {
5
+ export interface TypeaheadProps<TItem> extends SearchProps {
15
6
  /**
16
7
  * @default "typeahead-" + Math.random().toString(36)
17
8
  */
@@ -25,22 +16,22 @@ export interface TypeaheadProps extends SearchProps {
25
16
  /**
26
17
  * @default []
27
18
  */
28
- data?: Item[];
19
+ data?: TItem[];
29
20
 
30
21
  /**
31
22
  * @default (item) => item
32
23
  */
33
- extract?: (item: Item) => Item;
24
+ extract?: (item: TItem) => any;
34
25
 
35
26
  /**
36
27
  * @default (item) => false
37
28
  */
38
- disable?: (item: Item) => boolean;
29
+ disable?: (item: TItem) => boolean;
39
30
 
40
31
  /**
41
32
  * @default (item) => false
42
33
  */
43
- filter?: (item: Item) => boolean;
34
+ filter?: (item: TItem) => boolean;
44
35
 
45
36
  /**
46
37
  * Set to `false` to prevent the first result from being selected
@@ -57,7 +48,12 @@ export interface TypeaheadProps extends SearchProps {
57
48
  /**
58
49
  * @default []
59
50
  */
60
- results?: FuzzyResult[];
51
+ results?: {
52
+ original: TItem;
53
+ index: number;
54
+ score: number;
55
+ string: string;
56
+ }[];
61
57
 
62
58
  /**
63
59
  * Set to `true` to re-focus the input after selecting a result
@@ -72,14 +68,16 @@ export interface TypeaheadProps extends SearchProps {
72
68
  limit?: number;
73
69
  }
74
70
 
75
- export default class Typeahead extends SvelteComponentTyped<
76
- TypeaheadProps,
71
+ export default class Typeahead<
72
+ TItem = string | number | Record<string, any>
73
+ > extends SvelteComponentTyped<
74
+ TypeaheadProps<TItem>,
77
75
  {
78
76
  select: CustomEvent<{
79
77
  searched: string;
80
- selected: Item;
78
+ selected: TItem;
81
79
  selectedIndex: number;
82
- original: Item;
80
+ original: TItem;
83
81
  originalIndex: number;
84
82
  }>;
85
83
  type: CustomEvent<string>;
@@ -92,8 +90,17 @@ export default class Typeahead extends SvelteComponentTyped<
92
90
  },
93
91
  {
94
92
  default: {
95
- result: FuzzyResult;
93
+ result: {
94
+ original: TItem;
95
+ index: number;
96
+ score: number;
97
+ string: string;
98
+ };
96
99
  index: number;
100
+ value: string;
101
+ };
102
+ "no-results": {
103
+ value: string;
97
104
  };
98
105
  }
99
106
  > {}
package/types/index.d.ts CHANGED
@@ -1 +1 @@
1
- export { default as default } from "./Typeahead";
1
+ export { default as default } from "./Typeahead.svelte";