mirror of
https://github.com/carbon-design-system/carbon-components-svelte.git
synced 2025-09-18 11:36:36 +00:00
fix(multiselect): Svelte 5 compatibility
Refactor the MultiSelect component to remove circular dependencies which would cause infinite loops in Svelte 5 (#1986).
This commit is contained in:
parent
ac38e9d353
commit
f5de892268
1 changed files with 23 additions and 25 deletions
|
@ -168,7 +168,7 @@
|
||||||
*/
|
*/
|
||||||
export let highlightedId = null;
|
export let highlightedId = null;
|
||||||
|
|
||||||
import { afterUpdate, createEventDispatcher, setContext } from "svelte";
|
import { afterUpdate, createEventDispatcher, setContext, tick } from "svelte";
|
||||||
import WarningFilled from "../icons/WarningFilled.svelte";
|
import WarningFilled from "../icons/WarningFilled.svelte";
|
||||||
import WarningAltFilled from "../icons/WarningAltFilled.svelte";
|
import WarningAltFilled from "../icons/WarningAltFilled.svelte";
|
||||||
import Checkbox from "../Checkbox/Checkbox.svelte";
|
import Checkbox from "../Checkbox/Checkbox.svelte";
|
||||||
|
@ -237,7 +237,7 @@
|
||||||
afterUpdate(() => {
|
afterUpdate(() => {
|
||||||
if (checked.length !== prevChecked.length) {
|
if (checked.length !== prevChecked.length) {
|
||||||
if (selectionFeedback === "top") {
|
if (selectionFeedback === "top") {
|
||||||
sortedItems = sort();
|
items = sort();
|
||||||
}
|
}
|
||||||
prevChecked = checked;
|
prevChecked = checked;
|
||||||
selectedIds = checked.map(({ id }) => id);
|
selectedIds = checked.map(({ id }) => id);
|
||||||
|
@ -247,33 +247,29 @@
|
||||||
unselected: unchecked,
|
unselected: unchecked,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
if (!open) {
|
$: if (!open) {
|
||||||
if (!initialSorted || selectionFeedback !== "fixed") {
|
if (!initialSorted || selectionFeedback !== "fixed") {
|
||||||
sortedItems = sort();
|
tick().then(() => {
|
||||||
|
items = sort();
|
||||||
initialSorted = true;
|
initialSorted = true;
|
||||||
}
|
});
|
||||||
|
|
||||||
highlightedIndex = -1;
|
|
||||||
value = "";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
items = sortedItems;
|
highlightedIndex = -1;
|
||||||
});
|
value = "";
|
||||||
|
}
|
||||||
|
|
||||||
$: menuId = `menu-${id}`;
|
$: menuId = `menu-${id}`;
|
||||||
$: inline = type === "inline";
|
$: inline = type === "inline";
|
||||||
$: ariaLabel = $$props["aria-label"] || "Choose an item";
|
$: ariaLabel = $$props["aria-label"] || "Choose an item";
|
||||||
$: sortedItems = items.map((item) => ({
|
$: checked = items.filter(({ checked }) => checked);
|
||||||
...item,
|
$: unchecked = items.filter(({ checked }) => !checked);
|
||||||
checked: selectedIds.includes(item.id),
|
$: filteredItems = items.filter((item) => filterItem(item, value));
|
||||||
}));
|
|
||||||
$: checked = sortedItems.filter(({ checked }) => checked);
|
|
||||||
$: unchecked = sortedItems.filter(({ checked }) => !checked);
|
|
||||||
$: filteredItems = sortedItems.filter((item) => filterItem(item, value));
|
|
||||||
$: highlightedId =
|
$: highlightedId =
|
||||||
highlightedIndex > -1
|
highlightedIndex > -1
|
||||||
? (filterable ? filteredItems : sortedItems)[highlightedIndex]?.id ?? null
|
? (filterable ? filteredItems : items)[highlightedIndex]?.id ?? null
|
||||||
: null;
|
: null;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -366,7 +362,7 @@
|
||||||
change(-1);
|
change(-1);
|
||||||
} else if (key === 'Enter') {
|
} else if (key === 'Enter') {
|
||||||
if (highlightedIndex > -1) {
|
if (highlightedIndex > -1) {
|
||||||
sortedItems = sortedItems.map((item, i) => {
|
items = items.map((item, i) => {
|
||||||
if (i !== highlightedIndex) return item;
|
if (i !== highlightedIndex) return item;
|
||||||
return { ...item, checked: !item.checked };
|
return { ...item, checked: !item.checked };
|
||||||
});
|
});
|
||||||
|
@ -394,7 +390,7 @@
|
||||||
on:clear
|
on:clear
|
||||||
on:clear="{() => {
|
on:clear="{() => {
|
||||||
selectedIds = [];
|
selectedIds = [];
|
||||||
sortedItems = sortedItems.map((item) => ({
|
items = items.map((item) => ({
|
||||||
...item,
|
...item,
|
||||||
checked: false,
|
checked: false,
|
||||||
}));
|
}));
|
||||||
|
@ -424,10 +420,10 @@
|
||||||
on:keydown|stopPropagation="{({ key }) => {
|
on:keydown|stopPropagation="{({ key }) => {
|
||||||
if (key === 'Enter') {
|
if (key === 'Enter') {
|
||||||
if (highlightedId) {
|
if (highlightedId) {
|
||||||
const filteredItemIndex = sortedItems.findIndex(
|
const filteredItemIndex = items.findIndex(
|
||||||
(item) => item.id === highlightedId
|
(item) => item.id === highlightedId
|
||||||
);
|
);
|
||||||
sortedItems = sortedItems.map((item, i) => {
|
items = items.map((item, i) => {
|
||||||
if (i !== filteredItemIndex) return item;
|
if (i !== filteredItemIndex) return item;
|
||||||
return { ...item, checked: !item.checked };
|
return { ...item, checked: !item.checked };
|
||||||
});
|
});
|
||||||
|
@ -489,7 +485,7 @@
|
||||||
id="{id}"
|
id="{id}"
|
||||||
aria-multiselectable="true"
|
aria-multiselectable="true"
|
||||||
>
|
>
|
||||||
{#each filterable ? filteredItems : sortedItems as item, i (item.id)}
|
{#each filterable ? filteredItems : items as item, i (item.id)}
|
||||||
<ListBoxMenuItem
|
<ListBoxMenuItem
|
||||||
id="{item.id}"
|
id="{item.id}"
|
||||||
role="option"
|
role="option"
|
||||||
|
@ -503,9 +499,11 @@
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
sortedItems = sortedItems.map((_) =>
|
|
||||||
|
items = items.map((_) =>
|
||||||
_.id === item.id ? { ..._, checked: !_.checked } : _
|
_.id === item.id ? { ..._, checked: !_.checked } : _
|
||||||
);
|
);
|
||||||
|
|
||||||
fieldRef.focus();
|
fieldRef.focus();
|
||||||
}}"
|
}}"
|
||||||
on:mouseenter="{() => {
|
on:mouseenter="{() => {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue