From f5de892268b1aaaa4f6875c814b6f18dcd5c6583 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Malinowski?=
Date: Sat, 9 Nov 2024 14:53:33 +0100
Subject: [PATCH] fix(multiselect): Svelte 5 compatibility
Refactor the MultiSelect component to remove circular dependencies which
would cause infinite loops in Svelte 5 (#1986).
---
src/MultiSelect/MultiSelect.svelte | 48 ++++++++++++++----------------
1 file changed, 23 insertions(+), 25 deletions(-)
diff --git a/src/MultiSelect/MultiSelect.svelte b/src/MultiSelect/MultiSelect.svelte
index 032dde90..057757b6 100644
--- a/src/MultiSelect/MultiSelect.svelte
+++ b/src/MultiSelect/MultiSelect.svelte
@@ -168,7 +168,7 @@
*/
export let highlightedId = null;
- import { afterUpdate, createEventDispatcher, setContext } from "svelte";
+ import { afterUpdate, createEventDispatcher, setContext, tick } from "svelte";
import WarningFilled from "../icons/WarningFilled.svelte";
import WarningAltFilled from "../icons/WarningAltFilled.svelte";
import Checkbox from "../Checkbox/Checkbox.svelte";
@@ -237,7 +237,7 @@
afterUpdate(() => {
if (checked.length !== prevChecked.length) {
if (selectionFeedback === "top") {
- sortedItems = sort();
+ items = sort();
}
prevChecked = checked;
selectedIds = checked.map(({ id }) => id);
@@ -247,33 +247,29 @@
unselected: unchecked,
});
}
+ });
- if (!open) {
- if (!initialSorted || selectionFeedback !== "fixed") {
- sortedItems = sort();
+ $: if (!open) {
+ if (!initialSorted || selectionFeedback !== "fixed") {
+ tick().then(() => {
+ items = sort();
initialSorted = true;
- }
-
- highlightedIndex = -1;
- value = "";
+ });
}
- items = sortedItems;
- });
+ highlightedIndex = -1;
+ value = "";
+ }
$: menuId = `menu-${id}`;
$: inline = type === "inline";
$: ariaLabel = $$props["aria-label"] || "Choose an item";
- $: sortedItems = items.map((item) => ({
- ...item,
- checked: selectedIds.includes(item.id),
- }));
- $: checked = sortedItems.filter(({ checked }) => checked);
- $: unchecked = sortedItems.filter(({ checked }) => !checked);
- $: filteredItems = sortedItems.filter((item) => filterItem(item, value));
+ $: checked = items.filter(({ checked }) => checked);
+ $: unchecked = items.filter(({ checked }) => !checked);
+ $: filteredItems = items.filter((item) => filterItem(item, value));
$: highlightedId =
highlightedIndex > -1
- ? (filterable ? filteredItems : sortedItems)[highlightedIndex]?.id ?? null
+ ? (filterable ? filteredItems : items)[highlightedIndex]?.id ?? null
: null;
@@ -366,7 +362,7 @@
change(-1);
} else if (key === 'Enter') {
if (highlightedIndex > -1) {
- sortedItems = sortedItems.map((item, i) => {
+ items = items.map((item, i) => {
if (i !== highlightedIndex) return item;
return { ...item, checked: !item.checked };
});
@@ -394,7 +390,7 @@
on:clear
on:clear="{() => {
selectedIds = [];
- sortedItems = sortedItems.map((item) => ({
+ items = items.map((item) => ({
...item,
checked: false,
}));
@@ -424,10 +420,10 @@
on:keydown|stopPropagation="{({ key }) => {
if (key === 'Enter') {
if (highlightedId) {
- const filteredItemIndex = sortedItems.findIndex(
+ const filteredItemIndex = items.findIndex(
(item) => item.id === highlightedId
);
- sortedItems = sortedItems.map((item, i) => {
+ items = items.map((item, i) => {
if (i !== filteredItemIndex) return item;
return { ...item, checked: !item.checked };
});
@@ -489,7 +485,7 @@
id="{id}"
aria-multiselectable="true"
>
- {#each filterable ? filteredItems : sortedItems as item, i (item.id)}
+ {#each filterable ? filteredItems : items as item, i (item.id)}