mertani-web-toolkit 0.1.54 → 0.1.55
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.
|
@@ -57,6 +57,8 @@
|
|
|
57
57
|
emptyMessage?: string;
|
|
58
58
|
closeOnSelect?: boolean;
|
|
59
59
|
loadingSuggestions?: boolean;
|
|
60
|
+
/** Jika false, suggestions tidak difilter di client (untuk data dari API yang sudah difilter) */
|
|
61
|
+
filterSuggestionsClientSide?: boolean;
|
|
60
62
|
|
|
61
63
|
// Events
|
|
62
64
|
onSelectSuggestion?: (value: string, option: SuggestionOption) => void;
|
|
@@ -126,6 +128,7 @@
|
|
|
126
128
|
emptyMessage = 'Tidak ada hasil',
|
|
127
129
|
closeOnSelect = true,
|
|
128
130
|
loadingSuggestions = false,
|
|
131
|
+
filterSuggestionsClientSide = true,
|
|
129
132
|
|
|
130
133
|
// Events
|
|
131
134
|
onSelectSuggestion,
|
|
@@ -155,15 +158,15 @@
|
|
|
155
158
|
...props
|
|
156
159
|
}: Props = $props();
|
|
157
160
|
|
|
158
|
-
let inputValue = $
|
|
159
|
-
let errorMessage = $
|
|
160
|
-
let isFocused = $
|
|
161
|
-
let showList = $
|
|
162
|
-
let activeIndex = $
|
|
163
|
-
let wrapperEl: HTMLDivElement | null = $
|
|
164
|
-
let inputEl: HTMLInputElement | null = $
|
|
165
|
-
let searchByValue = $
|
|
166
|
-
let searchByOpen = $
|
|
161
|
+
let inputValue = $derived(value);
|
|
162
|
+
let errorMessage = $derived('');
|
|
163
|
+
let isFocused = $derived(false);
|
|
164
|
+
let showList = $derived(false);
|
|
165
|
+
let activeIndex = $derived(-1);
|
|
166
|
+
let wrapperEl: HTMLDivElement | null = $derived(null);
|
|
167
|
+
let inputEl: HTMLInputElement | null = $derived(null);
|
|
168
|
+
let searchByValue = $derived(searchBy);
|
|
169
|
+
let searchByOpen = $derived(false);
|
|
167
170
|
|
|
168
171
|
$effect(() => {
|
|
169
172
|
inputValue = value;
|
|
@@ -180,6 +183,11 @@
|
|
|
180
183
|
}
|
|
181
184
|
});
|
|
182
185
|
|
|
186
|
+
$effect(() => {
|
|
187
|
+
suggestions = suggestions;
|
|
188
|
+
activeIndex = -1;
|
|
189
|
+
});
|
|
190
|
+
|
|
183
191
|
const sizeConfig = $derived(() => {
|
|
184
192
|
switch (size) {
|
|
185
193
|
case 48:
|
|
@@ -309,12 +317,17 @@
|
|
|
309
317
|
return classes.join(' ');
|
|
310
318
|
});
|
|
311
319
|
|
|
312
|
-
function normalizeSuggestion(option: SuggestionOption) {
|
|
320
|
+
function normalizeSuggestion(option: SuggestionOption): {
|
|
321
|
+
label: string;
|
|
322
|
+
value: string;
|
|
323
|
+
raw: SuggestionOption;
|
|
324
|
+
} {
|
|
313
325
|
if (typeof option === 'string') {
|
|
314
326
|
return { label: option, value: option, raw: option };
|
|
315
327
|
}
|
|
316
|
-
const val = option.value ?? option.label;
|
|
317
|
-
|
|
328
|
+
const val = String(option.value ?? option.id ?? option.label ?? '');
|
|
329
|
+
const lbl = String(option.label ?? option.value ?? option.id ?? '');
|
|
330
|
+
return { label: lbl, value: val, raw: option };
|
|
318
331
|
}
|
|
319
332
|
|
|
320
333
|
const filteredSuggestions = $derived(() => {
|
|
@@ -325,9 +338,10 @@
|
|
|
325
338
|
return [];
|
|
326
339
|
}
|
|
327
340
|
|
|
328
|
-
const result =
|
|
329
|
-
|
|
330
|
-
|
|
341
|
+
const result =
|
|
342
|
+
filterSuggestionsClientSide && query
|
|
343
|
+
? normalized.filter((item) => item.label.toLowerCase().includes(query))
|
|
344
|
+
: normalized;
|
|
331
345
|
return result.slice(0, maxSuggestions);
|
|
332
346
|
});
|
|
333
347
|
|
|
@@ -388,12 +402,6 @@
|
|
|
388
402
|
oninput?.(e);
|
|
389
403
|
}
|
|
390
404
|
|
|
391
|
-
function handleSearchByChange(e: Event) {
|
|
392
|
-
const target = e.target as HTMLSelectElement;
|
|
393
|
-
searchByValue = target.value;
|
|
394
|
-
searchBy = target.value;
|
|
395
|
-
}
|
|
396
|
-
|
|
397
405
|
function selectSearchBy(option: SearchByOption) {
|
|
398
406
|
searchByValue = option.value;
|
|
399
407
|
searchBy = option.value;
|
|
@@ -469,12 +477,15 @@
|
|
|
469
477
|
}
|
|
470
478
|
|
|
471
479
|
$effect(() => {
|
|
472
|
-
if (showList) {
|
|
473
|
-
setTimeout(() => document.addEventListener('click', handleClickOutside), 10);
|
|
474
|
-
} else {
|
|
480
|
+
if (!showList) {
|
|
475
481
|
document.removeEventListener('click', handleClickOutside);
|
|
482
|
+
return;
|
|
476
483
|
}
|
|
477
|
-
|
|
484
|
+
const tid = setTimeout(() => document.addEventListener('click', handleClickOutside), 10);
|
|
485
|
+
return () => {
|
|
486
|
+
clearTimeout(tid);
|
|
487
|
+
document.removeEventListener('click', handleClickOutside);
|
|
488
|
+
};
|
|
478
489
|
});
|
|
479
490
|
</script>
|
|
480
491
|
|
|
@@ -42,6 +42,8 @@ interface Props extends HTMLInputAttributes {
|
|
|
42
42
|
emptyMessage?: string;
|
|
43
43
|
closeOnSelect?: boolean;
|
|
44
44
|
loadingSuggestions?: boolean;
|
|
45
|
+
/** Jika false, suggestions tidak difilter di client (untuk data dari API yang sudah difilter) */
|
|
46
|
+
filterSuggestionsClientSide?: boolean;
|
|
45
47
|
onSelectSuggestion?: (value: string, option: SuggestionOption) => void;
|
|
46
48
|
onclick?: (event: MouseEvent) => void;
|
|
47
49
|
oninput?: (event: Event) => void;
|