svelte-select-5 6.2.3 → 6.2.4
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/Select.svelte +60 -47
- package/no-styles/Select.svelte +60 -47
- package/package.json +1 -1
package/Select.svelte
CHANGED
|
@@ -166,20 +166,6 @@
|
|
|
166
166
|
requiredSlot: requiredSlotSnippet = undefined,
|
|
167
167
|
} = $props();
|
|
168
168
|
|
|
169
|
-
// Prop validation (runs once on init)
|
|
170
|
-
if (typeof itemId !== 'string') {
|
|
171
|
-
console.warn('[svelte-select-5] itemId must be a string, using "value"');
|
|
172
|
-
itemId = 'value';
|
|
173
|
-
}
|
|
174
|
-
if (typeof label !== 'string') {
|
|
175
|
-
console.warn('[svelte-select-5] label must be a string, using "label"');
|
|
176
|
-
label = 'label';
|
|
177
|
-
}
|
|
178
|
-
if (loadOptions !== undefined && typeof loadOptions !== 'function') {
|
|
179
|
-
console.warn('[svelte-select-5] loadOptions must be a function');
|
|
180
|
-
loadOptions = undefined;
|
|
181
|
-
}
|
|
182
|
-
|
|
183
169
|
// Internal state
|
|
184
170
|
let timeout;
|
|
185
171
|
let activeValue = $state(undefined);
|
|
@@ -196,6 +182,31 @@
|
|
|
196
182
|
let loadRequestVersion = 0;
|
|
197
183
|
let isScrollingTimer;
|
|
198
184
|
|
|
185
|
+
// Validated props using $derived to avoid state_referenced_locally warning
|
|
186
|
+
const _itemId = $derived.by(() => {
|
|
187
|
+
if (typeof itemId !== 'string') {
|
|
188
|
+
console.warn('[svelte-select-5] itemId must be a string, using "value"');
|
|
189
|
+
return 'value';
|
|
190
|
+
}
|
|
191
|
+
return itemId;
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
const _label = $derived.by(() => {
|
|
195
|
+
if (typeof label !== 'string') {
|
|
196
|
+
console.warn('[svelte-select-5] label must be a string, using "label"');
|
|
197
|
+
return 'label';
|
|
198
|
+
}
|
|
199
|
+
return label;
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
const _loadOptions = $derived.by(() => {
|
|
203
|
+
if (loadOptions !== undefined && typeof loadOptions !== 'function') {
|
|
204
|
+
console.warn('[svelte-select-5] loadOptions must be a function');
|
|
205
|
+
return undefined;
|
|
206
|
+
}
|
|
207
|
+
return loadOptions;
|
|
208
|
+
});
|
|
209
|
+
|
|
199
210
|
// Floating UI config - using closure for listOffset to capture current value
|
|
200
211
|
let _floatingConfig = {
|
|
201
212
|
strategy: 'absolute',
|
|
@@ -221,9 +232,9 @@
|
|
|
221
232
|
// Helper functions
|
|
222
233
|
function setValue() {
|
|
223
234
|
if (typeof value === 'string') {
|
|
224
|
-
let item = (items || []).find((item) => item[
|
|
235
|
+
let item = (items || []).find((item) => item[_itemId] === value);
|
|
225
236
|
value = item || {
|
|
226
|
-
[
|
|
237
|
+
[_itemId]: value,
|
|
227
238
|
label: value,
|
|
228
239
|
};
|
|
229
240
|
} else if (multiple && Array.isArray(value) && value.length > 0) {
|
|
@@ -314,7 +325,7 @@
|
|
|
314
325
|
return;
|
|
315
326
|
}
|
|
316
327
|
|
|
317
|
-
if (!prev_value || value[
|
|
328
|
+
if (!prev_value || value[_itemId] !== prev_value[_itemId]) {
|
|
318
329
|
oninput?.(value);
|
|
319
330
|
}
|
|
320
331
|
}
|
|
@@ -331,7 +342,7 @@
|
|
|
331
342
|
|
|
332
343
|
function setValueIndexAsHoverIndex() {
|
|
333
344
|
const valueIndex = filteredItems.findIndex((i) => {
|
|
334
|
-
return i[
|
|
345
|
+
return i[_itemId] === value[_itemId];
|
|
335
346
|
});
|
|
336
347
|
|
|
337
348
|
checkHoverSelectable(valueIndex, true);
|
|
@@ -349,9 +360,9 @@
|
|
|
349
360
|
}
|
|
350
361
|
|
|
351
362
|
function setupFilterText() {
|
|
352
|
-
if (!
|
|
363
|
+
if (!_loadOptions && filterText.length === 0) return;
|
|
353
364
|
|
|
354
|
-
if (
|
|
365
|
+
if (_loadOptions) {
|
|
355
366
|
debounce(async function () {
|
|
356
367
|
const currentVersion = ++loadRequestVersion;
|
|
357
368
|
loading = true;
|
|
@@ -361,7 +372,7 @@
|
|
|
361
372
|
if (event === 'error') onerror?.(data);
|
|
362
373
|
if (event === 'loaded') onloaded?.(data);
|
|
363
374
|
},
|
|
364
|
-
loadOptions,
|
|
375
|
+
loadOptions: _loadOptions,
|
|
365
376
|
convertStringItemsToObjects,
|
|
366
377
|
filterText,
|
|
367
378
|
});
|
|
@@ -394,9 +405,9 @@
|
|
|
394
405
|
function computeJustValue() {
|
|
395
406
|
if (!value) return multiple ? null : undefined;
|
|
396
407
|
if (multiple) {
|
|
397
|
-
return value.map((item) => item?.[
|
|
408
|
+
return value.map((item) => item?.[_itemId]).filter(id => id !== undefined);
|
|
398
409
|
}
|
|
399
|
-
const id = value[
|
|
410
|
+
const id = value[_itemId];
|
|
400
411
|
return id !== undefined ? id : undefined;
|
|
401
412
|
}
|
|
402
413
|
|
|
@@ -408,7 +419,7 @@
|
|
|
408
419
|
let noDuplicates = true;
|
|
409
420
|
|
|
410
421
|
for (const val of value) {
|
|
411
|
-
const id = val[
|
|
422
|
+
const id = val[_itemId];
|
|
412
423
|
if (seen.has(id)) {
|
|
413
424
|
noDuplicates = false;
|
|
414
425
|
} else {
|
|
@@ -422,13 +433,13 @@
|
|
|
422
433
|
}
|
|
423
434
|
|
|
424
435
|
function findItem(selection) {
|
|
425
|
-
let matchTo = selection ? selection[
|
|
426
|
-
return items.find((item) => item[
|
|
436
|
+
let matchTo = selection ? selection[_itemId] : value[_itemId];
|
|
437
|
+
return items.find((item) => item[_itemId] === matchTo);
|
|
427
438
|
}
|
|
428
439
|
|
|
429
440
|
function updateValueDisplay(items) {
|
|
430
441
|
if (!items || items.length === 0 || items.some((item) => typeof item !== 'object')) return;
|
|
431
|
-
if (!value || (multiple ? value.some((selection) => !selection || !selection[
|
|
442
|
+
if (!value || (multiple ? value.some((selection) => !selection || !selection[_itemId]) : !value[_itemId])) return;
|
|
432
443
|
|
|
433
444
|
if (Array.isArray(value)) {
|
|
434
445
|
// Check if any value needs updating - compare properties, not references
|
|
@@ -437,7 +448,7 @@
|
|
|
437
448
|
const newValue = value.map((selection) => {
|
|
438
449
|
const found = findItem(selection);
|
|
439
450
|
// Only update if found item has different properties (not just different reference)
|
|
440
|
-
if (found && found[
|
|
451
|
+
if (found && found[_itemId] === selection[_itemId]) {
|
|
441
452
|
// Same itemId - check if other properties differ using shallow comparison
|
|
442
453
|
if (!shallowEqual(found, selection)) {
|
|
443
454
|
needsUpdate = true;
|
|
@@ -452,7 +463,7 @@
|
|
|
452
463
|
} else {
|
|
453
464
|
const found = findItem();
|
|
454
465
|
// Only update if found item has different properties
|
|
455
|
-
if (found && found[
|
|
466
|
+
if (found && found[_itemId] === value[_itemId]) {
|
|
456
467
|
if (!shallowEqual(found, value)) {
|
|
457
468
|
value = found;
|
|
458
469
|
}
|
|
@@ -489,7 +500,7 @@
|
|
|
489
500
|
if (filteredItems.length === 0) break;
|
|
490
501
|
const hoverItem = filteredItems[hoverItemIndex];
|
|
491
502
|
|
|
492
|
-
if (value && !multiple && value[
|
|
503
|
+
if (value && !multiple && value[_itemId] === hoverItem[_itemId]) {
|
|
493
504
|
closeList();
|
|
494
505
|
break;
|
|
495
506
|
} else {
|
|
@@ -524,7 +535,7 @@
|
|
|
524
535
|
if (listOpen && focused) {
|
|
525
536
|
if (
|
|
526
537
|
filteredItems.length === 0 ||
|
|
527
|
-
(value && value[
|
|
538
|
+
(value && value[_itemId] === filteredItems[hoverItemIndex][_itemId])
|
|
528
539
|
)
|
|
529
540
|
return closeList();
|
|
530
541
|
|
|
@@ -615,9 +626,9 @@
|
|
|
615
626
|
let selected = undefined;
|
|
616
627
|
|
|
617
628
|
if (_multiple && value.length > 0) {
|
|
618
|
-
selected = value.map((v) => v[
|
|
629
|
+
selected = value.map((v) => v[_label]).join(', ');
|
|
619
630
|
} else {
|
|
620
|
-
selected = value[
|
|
631
|
+
selected = value[_label];
|
|
621
632
|
}
|
|
622
633
|
|
|
623
634
|
return ariaValues(selected);
|
|
@@ -628,7 +639,7 @@
|
|
|
628
639
|
let _item = filteredItems[hoverItemIndex];
|
|
629
640
|
if (listOpen && _item) {
|
|
630
641
|
let count = filteredItems ? filteredItems.length : 0;
|
|
631
|
-
return ariaListOpen(_item[
|
|
642
|
+
return ariaListOpen(_item[_label], count);
|
|
632
643
|
} else {
|
|
633
644
|
return ariaFocused();
|
|
634
645
|
}
|
|
@@ -660,7 +671,7 @@
|
|
|
660
671
|
function handleItemClick(args) {
|
|
661
672
|
const { item, i } = args;
|
|
662
673
|
if (item?.selectable === false) return;
|
|
663
|
-
if (value && !multiple && value[
|
|
674
|
+
if (value && !multiple && value[_itemId] === item[_itemId]) return closeList();
|
|
664
675
|
if (isItemSelectable(item)) {
|
|
665
676
|
hoverItemIndex = i;
|
|
666
677
|
handleSelect(item);
|
|
@@ -750,14 +761,14 @@
|
|
|
750
761
|
|
|
751
762
|
// Derived values - order matters! filteredItems must come before ariaContext
|
|
752
763
|
let filteredItems = $derived(filter({
|
|
753
|
-
loadOptions,
|
|
764
|
+
loadOptions: _loadOptions,
|
|
754
765
|
filterText,
|
|
755
766
|
items,
|
|
756
767
|
multiple,
|
|
757
768
|
value,
|
|
758
|
-
itemId,
|
|
769
|
+
itemId: _itemId,
|
|
759
770
|
groupBy,
|
|
760
|
-
label,
|
|
771
|
+
label: _label,
|
|
761
772
|
filterSelectedItems,
|
|
762
773
|
itemFilter,
|
|
763
774
|
convertStringItemsToObjects,
|
|
@@ -830,8 +841,10 @@
|
|
|
830
841
|
// This prevents loops when parent components create new array references on each render
|
|
831
842
|
$effect(() => {
|
|
832
843
|
if (items !== prevItemsRef) {
|
|
833
|
-
//
|
|
834
|
-
|
|
844
|
+
// Use $state.snapshot() to compare plain objects, avoiding proxy identity issues
|
|
845
|
+
const itemsSnapshot = items ? $state.snapshot(items) : items;
|
|
846
|
+
const prevSnapshot = prevItemsRef ? $state.snapshot(prevItemsRef) : prevItemsRef;
|
|
847
|
+
if (!arrayShallowEqual(itemsSnapshot, prevSnapshot)) {
|
|
835
848
|
updateValueDisplay(items);
|
|
836
849
|
}
|
|
837
850
|
prevItemsRef = items;
|
|
@@ -845,9 +858,9 @@
|
|
|
845
858
|
// Helper function to resolve justValue to value
|
|
846
859
|
function resolveJustValue(jv) {
|
|
847
860
|
if (multiple) {
|
|
848
|
-
value = jv ? items.filter(item => jv.includes(item[
|
|
861
|
+
value = jv ? items.filter(item => jv.includes(item[_itemId])) : null;
|
|
849
862
|
} else {
|
|
850
|
-
value = jv != null ? items.find(item => item[
|
|
863
|
+
value = jv != null ? items.find(item => item[_itemId] === jv) ?? null : null;
|
|
851
864
|
}
|
|
852
865
|
}
|
|
853
866
|
|
|
@@ -967,11 +980,11 @@
|
|
|
967
980
|
tabindex="-1"
|
|
968
981
|
role="none">
|
|
969
982
|
<div
|
|
970
|
-
use:activeScroll={{ scroll: isItemActive(item, value,
|
|
983
|
+
use:activeScroll={{ scroll: isItemActive(item, value, _itemId), listDom }}
|
|
971
984
|
use:hoverScroll={{ scroll: scrollToHoverItem === i, listDom }}
|
|
972
985
|
class="item"
|
|
973
986
|
class:list-group-title={item.groupHeader}
|
|
974
|
-
class:active={isItemActive(item, value,
|
|
987
|
+
class:active={isItemActive(item, value, _itemId)}
|
|
975
988
|
class:first={isItemFirst(i)}
|
|
976
989
|
class:hover={hoverItemIndex === i}
|
|
977
990
|
class:group-item={item.groupItem}
|
|
@@ -979,7 +992,7 @@
|
|
|
979
992
|
{#if itemSnippet}
|
|
980
993
|
{@render itemSnippet({ item, index: i })}
|
|
981
994
|
{:else}
|
|
982
|
-
{item?.[
|
|
995
|
+
{item?.[_label]}
|
|
983
996
|
{/if}
|
|
984
997
|
</div>
|
|
985
998
|
</div>
|
|
@@ -1025,7 +1038,7 @@
|
|
|
1025
1038
|
{#if selectionSnippet}
|
|
1026
1039
|
{@render selectionSnippet({ selection: item, index: i })}
|
|
1027
1040
|
{:else}
|
|
1028
|
-
{item[
|
|
1041
|
+
{item[_label]}
|
|
1029
1042
|
{/if}
|
|
1030
1043
|
</span>
|
|
1031
1044
|
|
|
@@ -1047,7 +1060,7 @@
|
|
|
1047
1060
|
{#if selectionSnippet}
|
|
1048
1061
|
{@render selectionSnippet({ selection: value })}
|
|
1049
1062
|
{:else}
|
|
1050
|
-
{value[
|
|
1063
|
+
{value[_label]}
|
|
1051
1064
|
{/if}
|
|
1052
1065
|
</div>
|
|
1053
1066
|
{/if}
|
package/no-styles/Select.svelte
CHANGED
|
@@ -166,20 +166,6 @@
|
|
|
166
166
|
requiredSlot: requiredSlotSnippet = undefined,
|
|
167
167
|
} = $props();
|
|
168
168
|
|
|
169
|
-
// Prop validation (runs once on init)
|
|
170
|
-
if (typeof itemId !== 'string') {
|
|
171
|
-
console.warn('[svelte-select-5] itemId must be a string, using "value"');
|
|
172
|
-
itemId = 'value';
|
|
173
|
-
}
|
|
174
|
-
if (typeof label !== 'string') {
|
|
175
|
-
console.warn('[svelte-select-5] label must be a string, using "label"');
|
|
176
|
-
label = 'label';
|
|
177
|
-
}
|
|
178
|
-
if (loadOptions !== undefined && typeof loadOptions !== 'function') {
|
|
179
|
-
console.warn('[svelte-select-5] loadOptions must be a function');
|
|
180
|
-
loadOptions = undefined;
|
|
181
|
-
}
|
|
182
|
-
|
|
183
169
|
// Internal state
|
|
184
170
|
let timeout;
|
|
185
171
|
let activeValue = $state(undefined);
|
|
@@ -196,6 +182,31 @@
|
|
|
196
182
|
let loadRequestVersion = 0;
|
|
197
183
|
let isScrollingTimer;
|
|
198
184
|
|
|
185
|
+
// Validated props using $derived to avoid state_referenced_locally warning
|
|
186
|
+
const _itemId = $derived.by(() => {
|
|
187
|
+
if (typeof itemId !== 'string') {
|
|
188
|
+
console.warn('[svelte-select-5] itemId must be a string, using "value"');
|
|
189
|
+
return 'value';
|
|
190
|
+
}
|
|
191
|
+
return itemId;
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
const _label = $derived.by(() => {
|
|
195
|
+
if (typeof label !== 'string') {
|
|
196
|
+
console.warn('[svelte-select-5] label must be a string, using "label"');
|
|
197
|
+
return 'label';
|
|
198
|
+
}
|
|
199
|
+
return label;
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
const _loadOptions = $derived.by(() => {
|
|
203
|
+
if (loadOptions !== undefined && typeof loadOptions !== 'function') {
|
|
204
|
+
console.warn('[svelte-select-5] loadOptions must be a function');
|
|
205
|
+
return undefined;
|
|
206
|
+
}
|
|
207
|
+
return loadOptions;
|
|
208
|
+
});
|
|
209
|
+
|
|
199
210
|
// Floating UI config - using closure for listOffset to capture current value
|
|
200
211
|
let _floatingConfig = {
|
|
201
212
|
strategy: 'absolute',
|
|
@@ -221,9 +232,9 @@
|
|
|
221
232
|
// Helper functions
|
|
222
233
|
function setValue() {
|
|
223
234
|
if (typeof value === 'string') {
|
|
224
|
-
let item = (items || []).find((item) => item[
|
|
235
|
+
let item = (items || []).find((item) => item[_itemId] === value);
|
|
225
236
|
value = item || {
|
|
226
|
-
[
|
|
237
|
+
[_itemId]: value,
|
|
227
238
|
label: value,
|
|
228
239
|
};
|
|
229
240
|
} else if (multiple && Array.isArray(value) && value.length > 0) {
|
|
@@ -314,7 +325,7 @@
|
|
|
314
325
|
return;
|
|
315
326
|
}
|
|
316
327
|
|
|
317
|
-
if (!prev_value || value[
|
|
328
|
+
if (!prev_value || value[_itemId] !== prev_value[_itemId]) {
|
|
318
329
|
oninput?.(value);
|
|
319
330
|
}
|
|
320
331
|
}
|
|
@@ -331,7 +342,7 @@
|
|
|
331
342
|
|
|
332
343
|
function setValueIndexAsHoverIndex() {
|
|
333
344
|
const valueIndex = filteredItems.findIndex((i) => {
|
|
334
|
-
return i[
|
|
345
|
+
return i[_itemId] === value[_itemId];
|
|
335
346
|
});
|
|
336
347
|
|
|
337
348
|
checkHoverSelectable(valueIndex, true);
|
|
@@ -349,9 +360,9 @@
|
|
|
349
360
|
}
|
|
350
361
|
|
|
351
362
|
function setupFilterText() {
|
|
352
|
-
if (!
|
|
363
|
+
if (!_loadOptions && filterText.length === 0) return;
|
|
353
364
|
|
|
354
|
-
if (
|
|
365
|
+
if (_loadOptions) {
|
|
355
366
|
debounce(async function () {
|
|
356
367
|
const currentVersion = ++loadRequestVersion;
|
|
357
368
|
loading = true;
|
|
@@ -361,7 +372,7 @@
|
|
|
361
372
|
if (event === 'error') onerror?.(data);
|
|
362
373
|
if (event === 'loaded') onloaded?.(data);
|
|
363
374
|
},
|
|
364
|
-
loadOptions,
|
|
375
|
+
loadOptions: _loadOptions,
|
|
365
376
|
convertStringItemsToObjects,
|
|
366
377
|
filterText,
|
|
367
378
|
});
|
|
@@ -394,9 +405,9 @@
|
|
|
394
405
|
function computeJustValue() {
|
|
395
406
|
if (!value) return multiple ? null : undefined;
|
|
396
407
|
if (multiple) {
|
|
397
|
-
return value.map((item) => item?.[
|
|
408
|
+
return value.map((item) => item?.[_itemId]).filter(id => id !== undefined);
|
|
398
409
|
}
|
|
399
|
-
const id = value[
|
|
410
|
+
const id = value[_itemId];
|
|
400
411
|
return id !== undefined ? id : undefined;
|
|
401
412
|
}
|
|
402
413
|
|
|
@@ -408,7 +419,7 @@
|
|
|
408
419
|
let noDuplicates = true;
|
|
409
420
|
|
|
410
421
|
for (const val of value) {
|
|
411
|
-
const id = val[
|
|
422
|
+
const id = val[_itemId];
|
|
412
423
|
if (seen.has(id)) {
|
|
413
424
|
noDuplicates = false;
|
|
414
425
|
} else {
|
|
@@ -422,13 +433,13 @@
|
|
|
422
433
|
}
|
|
423
434
|
|
|
424
435
|
function findItem(selection) {
|
|
425
|
-
let matchTo = selection ? selection[
|
|
426
|
-
return items.find((item) => item[
|
|
436
|
+
let matchTo = selection ? selection[_itemId] : value[_itemId];
|
|
437
|
+
return items.find((item) => item[_itemId] === matchTo);
|
|
427
438
|
}
|
|
428
439
|
|
|
429
440
|
function updateValueDisplay(items) {
|
|
430
441
|
if (!items || items.length === 0 || items.some((item) => typeof item !== 'object')) return;
|
|
431
|
-
if (!value || (multiple ? value.some((selection) => !selection || !selection[
|
|
442
|
+
if (!value || (multiple ? value.some((selection) => !selection || !selection[_itemId]) : !value[_itemId])) return;
|
|
432
443
|
|
|
433
444
|
if (Array.isArray(value)) {
|
|
434
445
|
// Check if any value needs updating - compare properties, not references
|
|
@@ -437,7 +448,7 @@
|
|
|
437
448
|
const newValue = value.map((selection) => {
|
|
438
449
|
const found = findItem(selection);
|
|
439
450
|
// Only update if found item has different properties (not just different reference)
|
|
440
|
-
if (found && found[
|
|
451
|
+
if (found && found[_itemId] === selection[_itemId]) {
|
|
441
452
|
// Same itemId - check if other properties differ using shallow comparison
|
|
442
453
|
if (!shallowEqual(found, selection)) {
|
|
443
454
|
needsUpdate = true;
|
|
@@ -452,7 +463,7 @@
|
|
|
452
463
|
} else {
|
|
453
464
|
const found = findItem();
|
|
454
465
|
// Only update if found item has different properties
|
|
455
|
-
if (found && found[
|
|
466
|
+
if (found && found[_itemId] === value[_itemId]) {
|
|
456
467
|
if (!shallowEqual(found, value)) {
|
|
457
468
|
value = found;
|
|
458
469
|
}
|
|
@@ -489,7 +500,7 @@
|
|
|
489
500
|
if (filteredItems.length === 0) break;
|
|
490
501
|
const hoverItem = filteredItems[hoverItemIndex];
|
|
491
502
|
|
|
492
|
-
if (value && !multiple && value[
|
|
503
|
+
if (value && !multiple && value[_itemId] === hoverItem[_itemId]) {
|
|
493
504
|
closeList();
|
|
494
505
|
break;
|
|
495
506
|
} else {
|
|
@@ -524,7 +535,7 @@
|
|
|
524
535
|
if (listOpen && focused) {
|
|
525
536
|
if (
|
|
526
537
|
filteredItems.length === 0 ||
|
|
527
|
-
(value && value[
|
|
538
|
+
(value && value[_itemId] === filteredItems[hoverItemIndex][_itemId])
|
|
528
539
|
)
|
|
529
540
|
return closeList();
|
|
530
541
|
|
|
@@ -615,9 +626,9 @@
|
|
|
615
626
|
let selected = undefined;
|
|
616
627
|
|
|
617
628
|
if (_multiple && value.length > 0) {
|
|
618
|
-
selected = value.map((v) => v[
|
|
629
|
+
selected = value.map((v) => v[_label]).join(', ');
|
|
619
630
|
} else {
|
|
620
|
-
selected = value[
|
|
631
|
+
selected = value[_label];
|
|
621
632
|
}
|
|
622
633
|
|
|
623
634
|
return ariaValues(selected);
|
|
@@ -628,7 +639,7 @@
|
|
|
628
639
|
let _item = filteredItems[hoverItemIndex];
|
|
629
640
|
if (listOpen && _item) {
|
|
630
641
|
let count = filteredItems ? filteredItems.length : 0;
|
|
631
|
-
return ariaListOpen(_item[
|
|
642
|
+
return ariaListOpen(_item[_label], count);
|
|
632
643
|
} else {
|
|
633
644
|
return ariaFocused();
|
|
634
645
|
}
|
|
@@ -660,7 +671,7 @@
|
|
|
660
671
|
function handleItemClick(args) {
|
|
661
672
|
const { item, i } = args;
|
|
662
673
|
if (item?.selectable === false) return;
|
|
663
|
-
if (value && !multiple && value[
|
|
674
|
+
if (value && !multiple && value[_itemId] === item[_itemId]) return closeList();
|
|
664
675
|
if (isItemSelectable(item)) {
|
|
665
676
|
hoverItemIndex = i;
|
|
666
677
|
handleSelect(item);
|
|
@@ -750,14 +761,14 @@
|
|
|
750
761
|
|
|
751
762
|
// Derived values - order matters! filteredItems must come before ariaContext
|
|
752
763
|
let filteredItems = $derived(filter({
|
|
753
|
-
loadOptions,
|
|
764
|
+
loadOptions: _loadOptions,
|
|
754
765
|
filterText,
|
|
755
766
|
items,
|
|
756
767
|
multiple,
|
|
757
768
|
value,
|
|
758
|
-
itemId,
|
|
769
|
+
itemId: _itemId,
|
|
759
770
|
groupBy,
|
|
760
|
-
label,
|
|
771
|
+
label: _label,
|
|
761
772
|
filterSelectedItems,
|
|
762
773
|
itemFilter,
|
|
763
774
|
convertStringItemsToObjects,
|
|
@@ -830,8 +841,10 @@
|
|
|
830
841
|
// This prevents loops when parent components create new array references on each render
|
|
831
842
|
$effect(() => {
|
|
832
843
|
if (items !== prevItemsRef) {
|
|
833
|
-
//
|
|
834
|
-
|
|
844
|
+
// Use $state.snapshot() to compare plain objects, avoiding proxy identity issues
|
|
845
|
+
const itemsSnapshot = items ? $state.snapshot(items) : items;
|
|
846
|
+
const prevSnapshot = prevItemsRef ? $state.snapshot(prevItemsRef) : prevItemsRef;
|
|
847
|
+
if (!arrayShallowEqual(itemsSnapshot, prevSnapshot)) {
|
|
835
848
|
updateValueDisplay(items);
|
|
836
849
|
}
|
|
837
850
|
prevItemsRef = items;
|
|
@@ -845,9 +858,9 @@
|
|
|
845
858
|
// Helper function to resolve justValue to value
|
|
846
859
|
function resolveJustValue(jv) {
|
|
847
860
|
if (multiple) {
|
|
848
|
-
value = jv ? items.filter(item => jv.includes(item[
|
|
861
|
+
value = jv ? items.filter(item => jv.includes(item[_itemId])) : null;
|
|
849
862
|
} else {
|
|
850
|
-
value = jv != null ? items.find(item => item[
|
|
863
|
+
value = jv != null ? items.find(item => item[_itemId] === jv) ?? null : null;
|
|
851
864
|
}
|
|
852
865
|
}
|
|
853
866
|
|
|
@@ -967,11 +980,11 @@
|
|
|
967
980
|
tabindex="-1"
|
|
968
981
|
role="none">
|
|
969
982
|
<div
|
|
970
|
-
use:activeScroll={{ scroll: isItemActive(item, value,
|
|
983
|
+
use:activeScroll={{ scroll: isItemActive(item, value, _itemId), listDom }}
|
|
971
984
|
use:hoverScroll={{ scroll: scrollToHoverItem === i, listDom }}
|
|
972
985
|
class="item"
|
|
973
986
|
class:list-group-title={item.groupHeader}
|
|
974
|
-
class:active={isItemActive(item, value,
|
|
987
|
+
class:active={isItemActive(item, value, _itemId)}
|
|
975
988
|
class:first={isItemFirst(i)}
|
|
976
989
|
class:hover={hoverItemIndex === i}
|
|
977
990
|
class:group-item={item.groupItem}
|
|
@@ -979,7 +992,7 @@
|
|
|
979
992
|
{#if itemSnippet}
|
|
980
993
|
{@render itemSnippet({ item, index: i })}
|
|
981
994
|
{:else}
|
|
982
|
-
{item?.[
|
|
995
|
+
{item?.[_label]}
|
|
983
996
|
{/if}
|
|
984
997
|
</div>
|
|
985
998
|
</div>
|
|
@@ -1025,7 +1038,7 @@
|
|
|
1025
1038
|
{#if selectionSnippet}
|
|
1026
1039
|
{@render selectionSnippet({ selection: item, index: i })}
|
|
1027
1040
|
{:else}
|
|
1028
|
-
{item[
|
|
1041
|
+
{item[_label]}
|
|
1029
1042
|
{/if}
|
|
1030
1043
|
</span>
|
|
1031
1044
|
|
|
@@ -1047,7 +1060,7 @@
|
|
|
1047
1060
|
{#if selectionSnippet}
|
|
1048
1061
|
{@render selectionSnippet({ selection: value })}
|
|
1049
1062
|
{:else}
|
|
1050
|
-
{value[
|
|
1063
|
+
{value[_label]}
|
|
1051
1064
|
{/if}
|
|
1052
1065
|
</div>
|
|
1053
1066
|
{/if}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "svelte-select-5",
|
|
3
|
-
"version": "6.2.
|
|
3
|
+
"version": "6.2.4",
|
|
4
4
|
"description": "A <Select> component for Svelte 5 apps (fork of svelte-select)",
|
|
5
5
|
"repository": "https://github.com/Dbone29/svelte-select-5.git",
|
|
6
6
|
"author": "Robert Balfré <rob.balfre@gmail.com> (https://github.com/rob-balfre)",
|