svelte-typeahead 5.0.1 → 5.0.3
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/README.md +2 -2
- package/package.json +1 -1
- package/src/Typeahead.svelte +34 -35
package/README.md
CHANGED
|
@@ -97,8 +97,8 @@ Use the default slot to render custom results.
|
|
|
97
97
|
Use the "no-results" slot to render a message if the search value does not yield results.
|
|
98
98
|
|
|
99
99
|
```svelte
|
|
100
|
-
<Typeahead value="abcd" {data} {extract}
|
|
101
|
-
<svelte:fragment slot="no-results">
|
|
100
|
+
<Typeahead value="abcd" {data} {extract}>
|
|
101
|
+
<svelte:fragment slot="no-results" let:value>
|
|
102
102
|
No results found for "{value}"
|
|
103
103
|
</svelte:fragment>
|
|
104
104
|
</Typeahead>
|
package/package.json
CHANGED
package/src/Typeahead.svelte
CHANGED
|
@@ -73,7 +73,7 @@
|
|
|
73
73
|
async function select() {
|
|
74
74
|
const result = results[selectedIndex];
|
|
75
75
|
|
|
76
|
-
if (result.disabled) return;
|
|
76
|
+
if (!result || result.disabled) return;
|
|
77
77
|
|
|
78
78
|
const selectedValue = extract(result.original);
|
|
79
79
|
const searchedValue = value;
|
|
@@ -97,46 +97,35 @@
|
|
|
97
97
|
|
|
98
98
|
/** @type {() => number} */
|
|
99
99
|
function getNextNonDisabledIndex() {
|
|
100
|
-
|
|
101
|
-
let disabled = results[index]?.disabled ?? false;
|
|
102
|
-
|
|
103
|
-
while (disabled) {
|
|
104
|
-
if (index === results.length) {
|
|
105
|
-
index = 0;
|
|
106
|
-
} else {
|
|
107
|
-
index += 1;
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
disabled = results[index]?.disabled ?? false;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
return index;
|
|
100
|
+
return results.findIndex((result) => !result.disabled);
|
|
114
101
|
}
|
|
115
102
|
|
|
116
103
|
/** @type {(direction: -1 | 1) => void} */
|
|
117
104
|
function change(direction) {
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
if (index < 0) index = results.length - 1;
|
|
123
|
-
|
|
124
|
-
let disabled = results[index].disabled;
|
|
125
|
-
|
|
126
|
-
while (disabled) {
|
|
127
|
-
if (index === results.length) {
|
|
128
|
-
index = 0;
|
|
129
|
-
} else {
|
|
130
|
-
index += direction;
|
|
131
|
-
}
|
|
105
|
+
const startingIndex = selectedIndex === -1 && direction === -1 ? 0 : selectedIndex;
|
|
106
|
+
|
|
107
|
+
for (let step = 1; step <= results.length; step += 1) {
|
|
108
|
+
const index = (startingIndex + step * direction + results.length) % results.length;
|
|
132
109
|
|
|
133
|
-
|
|
110
|
+
if (!results[index].disabled) {
|
|
111
|
+
selectedIndex = index;
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
134
114
|
}
|
|
135
115
|
|
|
136
|
-
selectedIndex =
|
|
116
|
+
selectedIndex = -1;
|
|
137
117
|
}
|
|
138
118
|
|
|
139
|
-
const open = () =>
|
|
119
|
+
const open = () => {
|
|
120
|
+
hideDropdown = false;
|
|
121
|
+
// Reset selected index when reopening menu
|
|
122
|
+
if (autoselect && results.length > 0) {
|
|
123
|
+
selectedIndex = getNextNonDisabledIndex();
|
|
124
|
+
} else {
|
|
125
|
+
selectedIndex = -1;
|
|
126
|
+
}
|
|
127
|
+
};
|
|
128
|
+
|
|
140
129
|
const close = () => {
|
|
141
130
|
hideDropdown = true;
|
|
142
131
|
isFocused = false;
|
|
@@ -212,7 +201,15 @@
|
|
|
212
201
|
}}
|
|
213
202
|
on:clear
|
|
214
203
|
on:clear={open}
|
|
215
|
-
on:blur
|
|
204
|
+
on:blur={(e) => {
|
|
205
|
+
// Check if focus is moving to an element within the combobox
|
|
206
|
+
const relatedTarget = e.relatedTarget;
|
|
207
|
+
if (relatedTarget && comboboxRef?.contains(relatedTarget)) {
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
// Close immediately for keyboard navigation (Tab, Shift+Tab)
|
|
211
|
+
close();
|
|
212
|
+
}}
|
|
216
213
|
on:keydown
|
|
217
214
|
on:keydown={(e) => {
|
|
218
215
|
if (results.length === 0) return;
|
|
@@ -253,8 +250,9 @@
|
|
|
253
250
|
class:selected={selectedIndex === index}
|
|
254
251
|
class:disabled={result.disabled}
|
|
255
252
|
aria-selected={selectedIndex === index}
|
|
256
|
-
on:
|
|
253
|
+
on:mousedown={(e) => {
|
|
257
254
|
if (result.disabled) return;
|
|
255
|
+
e.preventDefault(); // Prevent input from losing focus
|
|
258
256
|
selectedIndex = index;
|
|
259
257
|
select();
|
|
260
258
|
}}
|
|
@@ -283,11 +281,12 @@
|
|
|
283
281
|
background-color: #fff;
|
|
284
282
|
}
|
|
285
283
|
|
|
286
|
-
ul {
|
|
284
|
+
[data-svelte-typeahead] ul {
|
|
287
285
|
position: absolute;
|
|
288
286
|
top: 100%;
|
|
289
287
|
left: 0;
|
|
290
288
|
width: 100%;
|
|
289
|
+
max-width: none;
|
|
291
290
|
margin: 0;
|
|
292
291
|
padding: 0;
|
|
293
292
|
list-style: none;
|