mirror of
https://github.com/carbon-design-system/carbon-components-svelte.git
synced 2025-09-15 02:11:05 +00:00
feat(ComboBox): selectedIndex -> selectedId (#1016)
* feat(breaking): selectedIndex -> selectedId in ComboBox * docs: update ComboBox
This commit is contained in:
parent
e11a893bee
commit
cde8a79fa8
9 changed files with 91 additions and 102 deletions
|
@ -657,12 +657,12 @@ export interface ComboBoxItem {
|
||||||
### Props
|
### Props
|
||||||
|
|
||||||
| Prop name | Kind | Reactive | Type | Default value | Description |
|
| Prop name | Kind | Reactive | Type | Default value | Description |
|
||||||
| :--------------- | :-------------------- | :------- | :---------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------ |
|
| :--------------- | :-------------------- | :------- | :---------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------ |
|
||||||
| listRef | <code>let</code> | Yes | <code>null | HTMLDivElement</code> | <code>null</code> | Obtain a reference to the list HTML element |
|
| listRef | <code>let</code> | Yes | <code>null | HTMLDivElement</code> | <code>null</code> | Obtain a reference to the list HTML element |
|
||||||
| ref | <code>let</code> | Yes | <code>null | HTMLInputElement</code> | <code>null</code> | Obtain a reference to the input HTML element |
|
| ref | <code>let</code> | Yes | <code>null | HTMLInputElement</code> | <code>null</code> | Obtain a reference to the input HTML element |
|
||||||
| open | <code>let</code> | Yes | <code>boolean</code> | <code>false</code> | Set to `true` to open the combobox menu dropdown |
|
| open | <code>let</code> | Yes | <code>boolean</code> | <code>false</code> | Set to `true` to open the combobox menu dropdown |
|
||||||
| value | <code>let</code> | Yes | <code>string</code> | <code>""</code> | Specify the selected combobox value |
|
| value | <code>let</code> | Yes | <code>string</code> | <code>""</code> | Specify the selected combobox value |
|
||||||
| selectedIndex | <code>let</code> | Yes | <code>number</code> | <code>-1</code> | Set the selected item by value index |
|
| selectedId | <code>let</code> | Yes | <code>string</code> | -- | Set the selected item by value id |
|
||||||
| items | <code>let</code> | No | <code>ComboBoxItem[]</code> | <code>[]</code> | Set the combobox items |
|
| items | <code>let</code> | No | <code>ComboBoxItem[]</code> | <code>[]</code> | Set the combobox items |
|
||||||
| itemToString | <code>let</code> | No | <code>(item: ComboBoxItem) => string</code> | <code>(item) => item.text || item.id</code> | Override the display of a combobox item |
|
| itemToString | <code>let</code> | No | <code>(item: ComboBoxItem) => string</code> | <code>(item) => item.text || item.id</code> | Override the display of a combobox item |
|
||||||
| direction | <code>let</code> | No | <code>"bottom" | "top"</code> | <code>"bottom"</code> | Specify the direction of the combobox dropdown menu |
|
| direction | <code>let</code> | No | <code>"bottom" | "top"</code> | <code>"bottom"</code> | Specify the direction of the combobox dropdown menu |
|
||||||
|
@ -680,7 +680,7 @@ export interface ComboBoxItem {
|
||||||
| translateWithId | <code>let</code> | No | <code>(id: any) => string</code> | -- | Override the default translation ids |
|
| translateWithId | <code>let</code> | No | <code>(id: any) => string</code> | -- | Override the default translation ids |
|
||||||
| id | <code>let</code> | No | <code>string</code> | <code>"ccs-" + Math.random().toString(36)</code> | Set an id for the list box component |
|
| id | <code>let</code> | No | <code>string</code> | <code>"ccs-" + Math.random().toString(36)</code> | Set an id for the list box component |
|
||||||
| name | <code>let</code> | No | <code>string</code> | -- | Specify a name attribute for the input |
|
| name | <code>let</code> | No | <code>string</code> | -- | Specify a name attribute for the input |
|
||||||
| clear | <code>function</code> | No | <code>(options?: { focus?: boolean; }) => void</code> | <code>() => { prevSelectedIndex = undefined; selectedIndex = -1; highlightedIndex = -1; highlightedId = undefined; selectedId = undefined; selectedItem = undefined; open = false; inputValue = ""; if (options?.focus !== false) ref?.focus(); }</code> | Clear the combo box programmatically |
|
| clear | <code>function</code> | No | <code>(options?: { focus?: boolean; }) => void</code> | <code>() => { prevSelectedId = null; highlightedIndex = -1; highlightedId = undefined; selectedId = undefined; selectedItem = undefined; open = false; inputValue = ""; if (options?.focus !== false) ref?.focus(); }</code> | Clear the combo box programmatically |
|
||||||
|
|
||||||
### Slots
|
### Slots
|
||||||
|
|
||||||
|
@ -689,8 +689,8 @@ None.
|
||||||
### Events
|
### Events
|
||||||
|
|
||||||
| Event name | Type | Detail |
|
| Event name | Type | Detail |
|
||||||
| :--------- | :--------- | :------------------------------------------------------------------------------------- |
|
| :--------- | :--------- | :-------------------------------------------------------------- |
|
||||||
| select | dispatched | <code>{ selectedId: string; selectedIndex: number; selectedItem: ComboBoxItem }</code> |
|
| select | dispatched | <code>{ selectedId: string; selectedItem: ComboBoxItem }</code> |
|
||||||
| keydown | forwarded | -- |
|
| keydown | forwarded | -- |
|
||||||
| keyup | forwarded | -- |
|
| keyup | forwarded | -- |
|
||||||
| focus | forwarded | -- |
|
| focus | forwarded | -- |
|
||||||
|
|
|
@ -1395,11 +1395,10 @@
|
||||||
"reactive": false
|
"reactive": false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "selectedIndex",
|
"name": "selectedId",
|
||||||
"kind": "let",
|
"kind": "let",
|
||||||
"description": "Set the selected item by value index",
|
"description": "Set the selected item by value id",
|
||||||
"type": "number",
|
"type": "string",
|
||||||
"value": "-1",
|
|
||||||
"isFunction": false,
|
"isFunction": false,
|
||||||
"isFunctionDeclaration": false,
|
"isFunctionDeclaration": false,
|
||||||
"constant": false,
|
"constant": false,
|
||||||
|
@ -1616,7 +1615,7 @@
|
||||||
"kind": "function",
|
"kind": "function",
|
||||||
"description": "Clear the combo box programmatically",
|
"description": "Clear the combo box programmatically",
|
||||||
"type": "(options?: { focus?: boolean; }) => void",
|
"type": "(options?: { focus?: boolean; }) => void",
|
||||||
"value": "() => { prevSelectedIndex = undefined; selectedIndex = -1; highlightedIndex = -1; highlightedId = undefined; selectedId = undefined; selectedItem = undefined; open = false; inputValue = \"\"; if (options?.focus !== false) ref?.focus(); }",
|
"value": "() => { prevSelectedId = null; highlightedIndex = -1; highlightedId = undefined; selectedId = undefined; selectedItem = undefined; open = false; inputValue = \"\"; if (options?.focus !== false) ref?.focus(); }",
|
||||||
"isFunction": true,
|
"isFunction": true,
|
||||||
"isFunctionDeclaration": true,
|
"isFunctionDeclaration": true,
|
||||||
"constant": false,
|
"constant": false,
|
||||||
|
@ -1628,7 +1627,7 @@
|
||||||
{
|
{
|
||||||
"type": "dispatched",
|
"type": "dispatched",
|
||||||
"name": "select",
|
"name": "select",
|
||||||
"detail": "{ selectedId: string; selectedIndex: number; selectedItem: ComboBoxItem }"
|
"detail": "{ selectedId: string; selectedItem: ComboBoxItem }"
|
||||||
},
|
},
|
||||||
{ "type": "forwarded", "name": "keydown", "element": "input" },
|
{ "type": "forwarded", "name": "keydown", "element": "input" },
|
||||||
{ "type": "forwarded", "name": "keyup", "element": "input" },
|
{ "type": "forwarded", "name": "keyup", "element": "input" },
|
||||||
|
|
|
@ -12,10 +12,10 @@ items={[
|
||||||
{id: "2", text: "Fax"}
|
{id: "2", text: "Fax"}
|
||||||
]} />
|
]} />
|
||||||
|
|
||||||
### Selected index
|
### Selected id
|
||||||
|
|
||||||
<ComboBox titleText="Contact" placeholder="Select contact method"
|
<ComboBox titleText="Contact" placeholder="Select contact method"
|
||||||
selectedIndex={1}
|
selectedId="1"
|
||||||
items={[
|
items={[
|
||||||
{id: "0", text: "Slack"},
|
{id: "0", text: "Slack"},
|
||||||
{id: "1", text: "Email"},
|
{id: "1", text: "Email"},
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
<ComboBox
|
<ComboBox
|
||||||
titleText="Contact"
|
titleText="Contact"
|
||||||
placeholder="Select contact method"
|
placeholder="Select contact method"
|
||||||
selectedIndex="{1}"
|
selectedId="1"
|
||||||
bind:this="{ref}"
|
bind:this="{ref}"
|
||||||
items="{[
|
items="{[
|
||||||
{ id: '0', text: 'Slack' },
|
{ id: '0', text: 'Slack' },
|
||||||
|
|
|
@ -7,17 +7,18 @@
|
||||||
{ id: "2", text: "Fax" },
|
{ id: "2", text: "Fax" },
|
||||||
];
|
];
|
||||||
|
|
||||||
let comboBox1_selectedIndex = -1;
|
let comboBox1_selectedId = undefined;
|
||||||
let comboBox2_selectedIndex = -1;
|
let comboBox2_selectedId = undefined;
|
||||||
|
|
||||||
const formatSelected = (i) => (items[i] ? items[i].text : "N/A");
|
const formatSelected = (id) =>
|
||||||
|
items.find((item) => item.id === id)?.text ?? "N/A";
|
||||||
|
|
||||||
$: primary = formatSelected(comboBox1_selectedIndex);
|
$: primary = formatSelected(comboBox1_selectedId);
|
||||||
$: secondary = formatSelected(comboBox2_selectedIndex);
|
$: secondary = formatSelected(comboBox2_selectedId);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<ComboBox
|
<ComboBox
|
||||||
bind:selectedIndex="{comboBox1_selectedIndex}"
|
bind:selectedId="{comboBox1_selectedId}"
|
||||||
titleText="Primary contact"
|
titleText="Primary contact"
|
||||||
placeholder="Select primary contact method"
|
placeholder="Select primary contact method"
|
||||||
items="{items}"
|
items="{items}"
|
||||||
|
@ -26,7 +27,7 @@
|
||||||
<div>Primary: {primary}</div>
|
<div>Primary: {primary}</div>
|
||||||
|
|
||||||
<ComboBox
|
<ComboBox
|
||||||
bind:selectedIndex="{comboBox2_selectedIndex}"
|
bind:selectedId="{comboBox2_selectedId}"
|
||||||
titleText="Secondary contact"
|
titleText="Secondary contact"
|
||||||
placeholder="Select secondary contact method"
|
placeholder="Select secondary contact method"
|
||||||
items="{items}"
|
items="{items}"
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
<script>
|
<script>
|
||||||
import { ComboBox, Button } from "carbon-components-svelte";
|
import { ComboBox, Button } from "carbon-components-svelte";
|
||||||
let selectedIndex = 1;
|
let selectedId = "1";
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<ComboBox
|
<ComboBox
|
||||||
titleText="Contact"
|
titleText="Contact"
|
||||||
placeholder="Select contact method"
|
placeholder="Select contact method"
|
||||||
bind:selectedIndex
|
bind:selectedId
|
||||||
items="{[
|
items="{[
|
||||||
{ id: '0', text: 'Slack' },
|
{ id: '0', text: 'Slack' },
|
||||||
{ id: '1', text: 'Email' },
|
{ id: '1', text: 'Email' },
|
||||||
|
@ -14,5 +14,7 @@
|
||||||
]}"
|
]}"
|
||||||
/>
|
/>
|
||||||
<br />
|
<br />
|
||||||
<Button on:click="{() => (selectedIndex = -1)}">Set to -1 (unselected)</Button>
|
<Button on:click="{() => (selectedId = undefined)}"
|
||||||
<Button on:click="{() => (selectedIndex = 2)}">Set to 2 (Fax)</Button>
|
>Set to undefined (unselected)</Button
|
||||||
|
>
|
||||||
|
<Button on:click="{() => (selectedId = '2')}">Set to 2 (Fax)</Button>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<script>
|
<script>
|
||||||
/**
|
/**
|
||||||
* @typedef {{ id: string; text: string; }} ComboBoxItem
|
* @typedef {{ id: string; text: string; }} ComboBoxItem
|
||||||
* @event {{ selectedId: string; selectedIndex: number; selectedItem: ComboBoxItem }} select
|
* @event {{ selectedId: string; selectedItem: ComboBoxItem }} select
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -16,8 +16,11 @@
|
||||||
*/
|
*/
|
||||||
export let itemToString = (item) => item.text || item.id;
|
export let itemToString = (item) => item.text || item.id;
|
||||||
|
|
||||||
/** Set the selected item by value index */
|
/**
|
||||||
export let selectedIndex = -1;
|
* Set the selected item by value id
|
||||||
|
* @type {string}
|
||||||
|
*/
|
||||||
|
export let selectedId = undefined;
|
||||||
|
|
||||||
/** Specify the selected combobox value */
|
/** Specify the selected combobox value */
|
||||||
export let value = "";
|
export let value = "";
|
||||||
|
@ -107,10 +110,9 @@
|
||||||
|
|
||||||
const dispatch = createEventDispatcher();
|
const dispatch = createEventDispatcher();
|
||||||
|
|
||||||
let selectedId = undefined;
|
|
||||||
let selectedItem = undefined;
|
let selectedItem = undefined;
|
||||||
let inputValue = value;
|
let inputValue = value;
|
||||||
let prevSelectedIndex = undefined;
|
let prevSelectedId = null;
|
||||||
let highlightedIndex = -1;
|
let highlightedIndex = -1;
|
||||||
|
|
||||||
function change(dir) {
|
function change(dir) {
|
||||||
|
@ -129,8 +131,7 @@
|
||||||
* @type {(options?: { focus?: boolean; }) => void}
|
* @type {(options?: { focus?: boolean; }) => void}
|
||||||
*/
|
*/
|
||||||
export function clear(options = {}) {
|
export function clear(options = {}) {
|
||||||
prevSelectedIndex = undefined;
|
prevSelectedId = null;
|
||||||
selectedIndex = -1;
|
|
||||||
highlightedIndex = -1;
|
highlightedIndex = -1;
|
||||||
highlightedId = undefined;
|
highlightedId = undefined;
|
||||||
selectedId = undefined;
|
selectedId = undefined;
|
||||||
|
@ -149,34 +150,31 @@
|
||||||
filteredItems = [];
|
filteredItems = [];
|
||||||
if (!selectedItem) {
|
if (!selectedItem) {
|
||||||
selectedId = undefined;
|
selectedId = undefined;
|
||||||
selectedIndex = -1;
|
|
||||||
inputValue = "";
|
inputValue = "";
|
||||||
highlightedIndex = -1;
|
highlightedIndex = -1;
|
||||||
highlightedId = undefined;
|
highlightedId = undefined;
|
||||||
prevSelectedIndex = undefined;
|
|
||||||
} else {
|
} else {
|
||||||
// programmatically set selectedIndex
|
// programmatically set inputValue
|
||||||
inputValue = selectedItem.text;
|
inputValue = selectedItem.text;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
$: if (selectedIndex > -1) {
|
$: if (selectedId !== undefined) {
|
||||||
if (prevSelectedIndex !== selectedIndex) {
|
if (prevSelectedId !== selectedId) {
|
||||||
prevSelectedIndex = selectedIndex;
|
prevSelectedId = selectedId;
|
||||||
if (filteredItems?.length === 1 && open) {
|
if (filteredItems?.length === 1 && open) {
|
||||||
selectedId = filteredItems[0].id;
|
selectedId = filteredItems[0].id;
|
||||||
selectedItem = filteredItems[0];
|
selectedItem = filteredItems[0];
|
||||||
highlightedIndex = -1;
|
highlightedIndex = -1;
|
||||||
highlightedId = undefined;
|
highlightedId = undefined;
|
||||||
} else {
|
} else {
|
||||||
selectedId = items[selectedIndex].id;
|
selectedItem = items.find((item) => item.id === selectedId);
|
||||||
selectedItem = items[selectedIndex];
|
|
||||||
}
|
}
|
||||||
dispatch("select", { selectedId, selectedIndex, selectedItem });
|
dispatch("select", { selectedId, selectedItem });
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
prevSelectedIndex = selectedIndex;
|
prevSelectedId = selectedId;
|
||||||
selectedItem = undefined;
|
selectedItem = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -269,29 +267,25 @@
|
||||||
if (key === 'Enter') {
|
if (key === 'Enter') {
|
||||||
open = !open;
|
open = !open;
|
||||||
|
|
||||||
if (highlightedIndex > -1 && highlightedIndex !== selectedIndex) {
|
if (
|
||||||
selectedIndex = highlightedIndex;
|
highlightedIndex > -1 &&
|
||||||
|
filteredItems[highlightedIndex]?.id !== selectedId
|
||||||
|
) {
|
||||||
open = false;
|
open = false;
|
||||||
highlightedIndex = -1;
|
if (filteredItems[highlightedIndex]) {
|
||||||
if (filteredItems[selectedIndex]) {
|
inputValue = filteredItems[highlightedIndex].text;
|
||||||
inputValue = filteredItems[selectedIndex].text;
|
selectedItem = filteredItems[highlightedIndex];
|
||||||
selectedItem = filteredItems[selectedIndex];
|
selectedId = filteredItems[highlightedIndex].id;
|
||||||
selectedId = filteredItems[selectedIndex].id;
|
|
||||||
}
|
}
|
||||||
selectedIndex = items.findIndex((item) => item.id === selectedId);
|
|
||||||
} else {
|
} else {
|
||||||
selectedIndex = 0;
|
|
||||||
open = false;
|
open = false;
|
||||||
|
if (filteredItems[0]) {
|
||||||
|
inputValue = filteredItems[0].text;
|
||||||
|
selectedItem = filteredItems[0];
|
||||||
|
selectedId = filteredItems[0].id;
|
||||||
|
}
|
||||||
|
}
|
||||||
highlightedIndex = -1;
|
highlightedIndex = -1;
|
||||||
if (filteredItems[selectedIndex]) {
|
|
||||||
inputValue = filteredItems[selectedIndex].text;
|
|
||||||
selectedItem = filteredItems[selectedIndex];
|
|
||||||
selectedId = filteredItems[selectedIndex].id;
|
|
||||||
selectedIndex = items.findIndex(
|
|
||||||
(item) => item.id === selectedId
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (key === 'Tab') {
|
} else if (key === 'Tab') {
|
||||||
open = false;
|
open = false;
|
||||||
} else if (key === 'ArrowDown') {
|
} else if (key === 'ArrowDown') {
|
||||||
|
@ -354,12 +348,10 @@
|
||||||
{#each filteredItems as item, i (item.id)}
|
{#each filteredItems as item, i (item.id)}
|
||||||
<ListBoxMenuItem
|
<ListBoxMenuItem
|
||||||
id="{item.id}"
|
id="{item.id}"
|
||||||
active="{selectedIndex === i || selectedId === item.id}"
|
active="{selectedId === item.id}"
|
||||||
highlighted="{highlightedIndex === i || selectedIndex === i}"
|
highlighted="{highlightedIndex === i}"
|
||||||
on:click="{() => {
|
on:click="{() => {
|
||||||
selectedIndex = items
|
selectedId = item.id;
|
||||||
.map(({ id }) => id)
|
|
||||||
.indexOf(filteredItems[i].id);
|
|
||||||
open = false;
|
open = false;
|
||||||
|
|
||||||
if (filteredItems[i]) {
|
if (filteredItems[i]) {
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
<ComboBox
|
<ComboBox
|
||||||
titleText="Contact"
|
titleText="Contact"
|
||||||
placeholder="Select contact method"
|
placeholder="Select contact method"
|
||||||
selectedIndex="{1}"
|
selectedId="1"
|
||||||
items="{items}"
|
items="{items}"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|
11
types/ComboBox/ComboBox.svelte.d.ts
vendored
11
types/ComboBox/ComboBox.svelte.d.ts
vendored
|
@ -21,10 +21,9 @@ export interface ComboBoxProps
|
||||||
itemToString?: (item: ComboBoxItem) => string;
|
itemToString?: (item: ComboBoxItem) => string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the selected item by value index
|
* Set the selected item by value id
|
||||||
* @default -1
|
|
||||||
*/
|
*/
|
||||||
selectedIndex?: number;
|
selectedId?: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specify the selected combobox value
|
* Specify the selected combobox value
|
||||||
|
@ -141,11 +140,7 @@ export interface ComboBoxProps
|
||||||
export default class ComboBox extends SvelteComponentTyped<
|
export default class ComboBox extends SvelteComponentTyped<
|
||||||
ComboBoxProps,
|
ComboBoxProps,
|
||||||
{
|
{
|
||||||
select: CustomEvent<{
|
select: CustomEvent<{ selectedId: string; selectedItem: ComboBoxItem }>;
|
||||||
selectedId: string;
|
|
||||||
selectedIndex: number;
|
|
||||||
selectedItem: ComboBoxItem;
|
|
||||||
}>;
|
|
||||||
keydown: WindowEventMap["keydown"];
|
keydown: WindowEventMap["keydown"];
|
||||||
keyup: WindowEventMap["keyup"];
|
keyup: WindowEventMap["keyup"];
|
||||||
focus: WindowEventMap["focus"];
|
focus: WindowEventMap["focus"];
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue