sveltacular 0.0.22 → 0.0.23
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.
|
@@ -13,24 +13,34 @@ export let disabled = false;
|
|
|
13
13
|
export let required = false;
|
|
14
14
|
export let searchable = false;
|
|
15
15
|
export let search = void 0;
|
|
16
|
+
const id = uniqueId();
|
|
17
|
+
const dispatch = createEventDispatcher();
|
|
16
18
|
const getText = () => items.find((item) => item.value == value)?.name || "";
|
|
19
|
+
let text = getText();
|
|
20
|
+
let open = false;
|
|
21
|
+
let highlightIndex = -1;
|
|
22
|
+
let filteredItems = [];
|
|
17
23
|
const onSelect = (e) => {
|
|
18
24
|
value = e.detail.value;
|
|
19
25
|
dispatch("change", value);
|
|
20
26
|
text = getText();
|
|
27
|
+
applyFilter();
|
|
21
28
|
open = false;
|
|
22
29
|
};
|
|
30
|
+
const focusOnInput = () => {
|
|
31
|
+
if (browser)
|
|
32
|
+
document.getElementById(id)?.focus();
|
|
33
|
+
};
|
|
23
34
|
const toggle = () => {
|
|
24
35
|
open = !open;
|
|
25
|
-
|
|
26
|
-
document.getElementById(id)?.focus();
|
|
36
|
+
focusOnInput();
|
|
27
37
|
};
|
|
28
38
|
const onInputKeyPress = (e) => {
|
|
29
39
|
if (e.key == "Escape") {
|
|
30
40
|
open = false;
|
|
31
41
|
return;
|
|
32
42
|
}
|
|
33
|
-
if (e.key == "Enter") {
|
|
43
|
+
if (e.key == "Enter" || e.key == "Tab") {
|
|
34
44
|
open = false;
|
|
35
45
|
if (highlightIndex > -1) {
|
|
36
46
|
onSelect(new CustomEvent("select", { detail: filteredItems[highlightIndex] }));
|
|
@@ -48,37 +58,39 @@ const onInputKeyPress = (e) => {
|
|
|
48
58
|
open = false;
|
|
49
59
|
return;
|
|
50
60
|
}
|
|
51
|
-
if (e.key.length == 1) {
|
|
61
|
+
if (e.key.length == 1 || e.key == "Backspace" || e.key == "Delete") {
|
|
52
62
|
open = true;
|
|
53
63
|
highlightIndex = 0;
|
|
54
64
|
triggerSearch();
|
|
55
65
|
}
|
|
56
66
|
};
|
|
57
67
|
const triggerSearch = debounce(async () => {
|
|
58
|
-
dispatch("search", searchText);
|
|
59
68
|
if (search) {
|
|
60
|
-
items = await search(
|
|
61
|
-
|
|
69
|
+
items = await search(text);
|
|
70
|
+
console.log(items);
|
|
62
71
|
}
|
|
72
|
+
updateText();
|
|
73
|
+
applyFilter();
|
|
74
|
+
open = true;
|
|
63
75
|
}, 300);
|
|
64
|
-
const
|
|
76
|
+
const applyFilter = () => {
|
|
77
|
+
const searchText = text.trim().toLowerCase();
|
|
78
|
+
filteredItems = searchText ? items.map((item, index) => ({ ...item, index })).filter((item) => item.name.toLowerCase().includes(searchText)) : items.map((item, index) => ({ ...item, index }));
|
|
79
|
+
};
|
|
80
|
+
const clear = () => {
|
|
81
|
+
text = "";
|
|
82
|
+
value = "";
|
|
83
|
+
triggerSearch();
|
|
84
|
+
focusOnInput();
|
|
85
|
+
};
|
|
65
86
|
const updateText = async () => {
|
|
66
87
|
if (browser) {
|
|
67
88
|
const textBox = document.getElementById(id);
|
|
68
89
|
if (document.activeElement != textBox)
|
|
69
90
|
text = getText();
|
|
91
|
+
open = true;
|
|
70
92
|
}
|
|
71
93
|
};
|
|
72
|
-
const id = uniqueId();
|
|
73
|
-
let text = getText();
|
|
74
|
-
let open = false;
|
|
75
|
-
let highlightIndex = -1;
|
|
76
|
-
$:
|
|
77
|
-
searchText = searchable ? text : "";
|
|
78
|
-
$:
|
|
79
|
-
filteredItems = searchText ? items.map((item, index) => ({ ...item, index })).filter((item) => item.name.toLowerCase().includes(searchText.toLowerCase())) : items.map((item, index) => ({ ...item, index }));
|
|
80
|
-
$:
|
|
81
|
-
items && updateText();
|
|
82
94
|
triggerSearch();
|
|
83
95
|
</script>
|
|
84
96
|
|
|
@@ -102,12 +114,13 @@ triggerSearch();
|
|
|
102
114
|
<button type="button" class="icon" on:click={toggle} on:keydown={toggle}>
|
|
103
115
|
<AngleUpIcon />
|
|
104
116
|
</button>
|
|
117
|
+
<button type="button" class="clear" on:click={clear} on:keydown={clear}> X </button>
|
|
105
118
|
<div class="dropdown">
|
|
106
119
|
<Menu
|
|
107
120
|
items={filteredItems}
|
|
108
121
|
{open}
|
|
109
122
|
closeAfterSelect={false}
|
|
110
|
-
{
|
|
123
|
+
searchText={text}
|
|
111
124
|
on:select={onSelect}
|
|
112
125
|
size="full"
|
|
113
126
|
bind:highlightIndex
|
|
@@ -134,7 +147,7 @@ div input {
|
|
|
134
147
|
user-select: none;
|
|
135
148
|
white-space: nowrap;
|
|
136
149
|
}
|
|
137
|
-
div button
|
|
150
|
+
div button {
|
|
138
151
|
border: 0;
|
|
139
152
|
appearance: none;
|
|
140
153
|
background: transparent;
|
|
@@ -142,14 +155,19 @@ div button.icon {
|
|
|
142
155
|
margin: 0;
|
|
143
156
|
position: absolute;
|
|
144
157
|
top: 0.65rem;
|
|
145
|
-
right: 1rem;
|
|
146
158
|
width: 1rem;
|
|
147
159
|
height: 1rem;
|
|
148
|
-
transition: transform 0.3s linear;
|
|
149
160
|
z-index: 2;
|
|
150
161
|
color: var(--form-input-fg, black);
|
|
162
|
+
}
|
|
163
|
+
div button.icon {
|
|
164
|
+
right: 1rem;
|
|
165
|
+
transition: transform 0.3s linear;
|
|
151
166
|
transform: rotate(180deg);
|
|
152
167
|
}
|
|
168
|
+
div button.clear {
|
|
169
|
+
right: 3rem;
|
|
170
|
+
}
|
|
153
171
|
div.open .icon {
|
|
154
172
|
transform: rotate(0deg);
|
|
155
173
|
}
|