feat(multi-select): expose highlightedId and fix highlighting for filterable variant (#1153)

This commit is contained in:
Dominik G 2022-03-12 22:49:10 +01:00 committed by GitHub
commit 9215e3b106
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 39 additions and 23 deletions

View file

@ -2422,6 +2422,7 @@ export interface MultiSelectItem {
| Prop name | Kind | Reactive | Type | Default value | Description | | Prop name | Kind | Reactive | Type | Default value | Description |
| :---------------- | :--------------- | :------- | :--------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------- | | :---------------- | :--------------- | :------- | :--------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------- |
| highlightedId | <code>let</code> | Yes | <code>null &#124; MultiSelectItemId</code> | <code>null</code> | Id of the highlighted ListBoxMenuItem |
| selectionRef | <code>let</code> | Yes | <code>null &#124; HTMLDivElement</code> | <code>null</code> | Obtain a reference to the selection element | | selectionRef | <code>let</code> | Yes | <code>null &#124; HTMLDivElement</code> | <code>null</code> | Obtain a reference to the selection element |
| fieldRef | <code>let</code> | Yes | <code>null &#124; HTMLDivElement</code> | <code>null</code> | Obtain a reference to the field box element | | fieldRef | <code>let</code> | Yes | <code>null &#124; HTMLDivElement</code> | <code>null</code> | Obtain a reference to the field box element |
| multiSelectRef | <code>let</code> | Yes | <code>null &#124; HTMLDivElement</code> | <code>null</code> | Obtain a reference to the outer div element | | multiSelectRef | <code>let</code> | Yes | <code>null &#124; HTMLDivElement</code> | <code>null</code> | Obtain a reference to the outer div element |

View file

@ -6804,6 +6804,17 @@
"isFunctionDeclaration": false, "isFunctionDeclaration": false,
"constant": false, "constant": false,
"reactive": true "reactive": true
},
{
"name": "highlightedId",
"kind": "let",
"description": "Id of the highlighted ListBoxMenuItem",
"type": "null | MultiSelectItemId",
"value": "null",
"isFunction": false,
"isFunctionDeclaration": false,
"constant": false,
"reactive": true
} }
], ],
"slots": [], "slots": [],

View file

@ -156,6 +156,12 @@
*/ */
export let selectionRef = null; export let selectionRef = null;
/**
* Id of the highlighted ListBoxMenuItem
* @type {null | MultiSelectItemId}
*/
export let highlightedId = null;
import { afterUpdate, createEventDispatcher, setContext } from "svelte"; import { afterUpdate, createEventDispatcher, setContext } from "svelte";
import WarningFilled16 from "../icons/WarningFilled16.svelte"; import WarningFilled16 from "../icons/WarningFilled16.svelte";
import WarningAltFilled16 from "../icons/WarningAltFilled16.svelte"; import WarningAltFilled16 from "../icons/WarningAltFilled16.svelte";
@ -191,10 +197,10 @@
function change(direction) { function change(direction) {
let index = highlightedIndex + direction; let index = highlightedIndex + direction;
const length = filterable ? filteredItems.length : items.length;
if (index < 0) { if (index < 0) {
index = items.length - 1; index = length - 1;
} else if (index >= items.length) { } else if (index >= length) {
index = 0; index = 0;
} }
@ -245,9 +251,10 @@
$: checked = sortedItems.filter(({ checked }) => checked); $: checked = sortedItems.filter(({ checked }) => checked);
$: unchecked = sortedItems.filter(({ checked }) => !checked); $: unchecked = sortedItems.filter(({ checked }) => !checked);
$: filteredItems = sortedItems.filter((item) => filterItem(item, value)); $: filteredItems = sortedItems.filter((item) => filterItem(item, value));
$: highlightedId = sortedItems[highlightedIndex] $: highlightedId =
? sortedItems[highlightedIndex].id highlightedIndex > -1
: undefined; ? (filterable ? filteredItems : sortedItems)[highlightedIndex]?.id ?? null
: null;
$: value = inputValue; $: value = inputValue;
</script> </script>
@ -394,23 +401,14 @@
on:keydown on:keydown
on:keydown|stopPropagation="{({ key }) => { on:keydown|stopPropagation="{({ key }) => {
if (key === 'Enter') { if (key === 'Enter') {
if (highlightedIndex > -1) { if (highlightedId) {
if (filterable) { const filteredItemIndex = sortedItems.findIndex(
const filteredItemId = filteredItems[highlightedIndex].id; (item) => item.id === highlightedId
const filteredItemIndex = sortedItems );
.map((item) => item.id)
.indexOf(filteredItemId);
sortedItems = sortedItems.map((item, i) => { sortedItems = sortedItems.map((item, i) => {
if (i !== filteredItemIndex) return item; if (i !== filteredItemIndex) return item;
return { ...item, checked: !item.checked }; return { ...item, checked: !item.checked };
}); });
} else {
sortedItems = sortedItems.map((item, i) => {
if (i !== highlightedIndex) return item;
return { ...item, checked: !item.checked };
});
}
} }
} else if (key === 'Tab') { } else if (key === 'Tab') {
open = false; open = false;

View file

@ -217,6 +217,12 @@ export interface MultiSelectProps
* @default null * @default null
*/ */
selectionRef?: null | HTMLDivElement; selectionRef?: null | HTMLDivElement;
/**
* Id of the highlighted ListBoxMenuItem
* @default null
*/
highlightedId?: null | MultiSelectItemId;
} }
export default class MultiSelect extends SvelteComponentTyped< export default class MultiSelect extends SvelteComponentTyped<