mirror of
https://github.com/carbon-design-system/carbon-components-svelte.git
synced 2025-09-18 03:26:36 +00:00
Merge 9ac8e34241
into 338f651178
This commit is contained in:
commit
1e01f51387
4 changed files with 89 additions and 23 deletions
|
@ -1505,6 +1505,18 @@
|
|||
"constant": false,
|
||||
"reactive": true
|
||||
},
|
||||
{
|
||||
"name": "allowArbitraryValues",
|
||||
"kind": "let",
|
||||
"description": "Set to `true` to allow values that aren't included in `items`",
|
||||
"type": "boolean",
|
||||
"value": "false",
|
||||
"isFunction": false,
|
||||
"isFunctionDeclaration": false,
|
||||
"isRequired": false,
|
||||
"constant": false,
|
||||
"reactive": false
|
||||
},
|
||||
{
|
||||
"name": "direction",
|
||||
"kind": "let",
|
||||
|
|
|
@ -34,6 +34,19 @@ items={[
|
|||
{id: "2", text: "Fax"}
|
||||
]} />
|
||||
|
||||
## Arbitrary Values
|
||||
|
||||
Set `allowArbitraryValues` to `true` to allow the user to type in whatever value they want, even if it's not present in `items`.
|
||||
`selectedId` will be set to `undefined` when the value is arbitrary.
|
||||
|
||||
<ComboBox allowArbitraryValues titleText="Contact" placeholder="Select contact method"
|
||||
selectedId="1"
|
||||
items={[
|
||||
{id: "0", text: "Slack"},
|
||||
{id: "1", text: "Email"},
|
||||
{id: "2", text: "Fax"}
|
||||
]} />
|
||||
|
||||
## Reactive example
|
||||
|
||||
<FileSource src="/framed/ComboBox/ReactiveComboBox" />
|
||||
|
|
|
@ -120,6 +120,11 @@
|
|||
resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.19.9.tgz#b2da6219b603e3fa371a78f53f5361260d0c5585"
|
||||
integrity sha512-oxoQgglOP7RH6iasDrhY+R/3cHrfwIDvRlT4CGChflq6twk8iENeVvMJjmvBb94Ik1Z+93iGO27err7w6l54GQ==
|
||||
|
||||
"@ibm/telemetry-js@^1.2.1":
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@ibm/telemetry-js/-/telemetry-js-1.3.0.tgz#321f2ed4bbbc78d69dc1ee9cb6f83d2d2af9baef"
|
||||
integrity sha512-9gIkyF2B9RizWN6rsdQN76DN6D+/Xbr4HGTwm6EUujfXvEVtWbf4jzxDFwKvZkeTC2tjHpkUNJQKdivbMKt8yg==
|
||||
|
||||
"@jridgewell/gen-mapping@^0.3.0":
|
||||
version "0.3.3"
|
||||
resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz#7e02e6eb5df901aaedb08514203b096614024098"
|
||||
|
@ -399,8 +404,9 @@ bufferutil@^4.0.1:
|
|||
node-gyp-build "~3.7.0"
|
||||
|
||||
carbon-components-svelte@../:
|
||||
version "0.82.5"
|
||||
version "0.84.1"
|
||||
dependencies:
|
||||
"@ibm/telemetry-js" "^1.2.1"
|
||||
flatpickr "4.6.9"
|
||||
|
||||
carbon-icons-svelte@^12.4.1:
|
||||
|
|
|
@ -27,6 +27,12 @@
|
|||
/** Specify the selected combobox value */
|
||||
export let value = "";
|
||||
|
||||
/**
|
||||
* Allow values that aren't in `items`.
|
||||
* @type {boolean}
|
||||
*/
|
||||
export let allowArbitraryValues = false
|
||||
|
||||
/**
|
||||
* Specify the direction of the combobox dropdown menu
|
||||
* @type {"bottom" | "top"}
|
||||
|
@ -107,7 +113,7 @@
|
|||
*/
|
||||
export let listRef = null;
|
||||
|
||||
import { createEventDispatcher, afterUpdate, tick } from "svelte";
|
||||
import { createEventDispatcher, afterUpdate, tick, onMount } from "svelte";
|
||||
import Checkmark from "../icons/Checkmark.svelte";
|
||||
import WarningFilled from "../icons/WarningFilled.svelte";
|
||||
import WarningAltFilled from "../icons/WarningAltFilled.svelte";
|
||||
|
@ -165,6 +171,12 @@
|
|||
if (options?.focus !== false) ref?.focus();
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
if (selectedItem) {
|
||||
value = itemToString(selectedItem)
|
||||
}
|
||||
})
|
||||
|
||||
afterUpdate(() => {
|
||||
if (open) {
|
||||
ref.focus();
|
||||
|
@ -172,6 +184,7 @@
|
|||
} else {
|
||||
highlightedIndex = -1;
|
||||
filteredItems = [];
|
||||
if (!allowArbitraryValues) {
|
||||
if (!selectedItem) {
|
||||
selectedId = undefined;
|
||||
value = "";
|
||||
|
@ -182,6 +195,7 @@
|
|||
value = itemToString(selectedItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
$: if (selectedId !== undefined) {
|
||||
|
@ -202,6 +216,39 @@
|
|||
selectedItem = undefined;
|
||||
}
|
||||
|
||||
function searchForMatchingValue() {
|
||||
// searching typed value in text list with lowercase
|
||||
let matchedItem =
|
||||
filteredItems.find(
|
||||
(e) =>
|
||||
e.text.toLowerCase() === value?.toLowerCase() && !e.disabled
|
||||
);
|
||||
|
||||
if (!allowArbitraryValues) {
|
||||
// typed value has matched or fallback to first enabled item
|
||||
matchedItem = matchedItem ?? filteredItems.find((e) => !e.disabled);
|
||||
if (matchedItem) setMatchedItem(matchedItem)
|
||||
} else {
|
||||
// When allowing arbitrary values, we still want to select a value if the user types in one that exists.
|
||||
// But if it doesn't exist, we don't try to fallback to another value.
|
||||
if (matchedItem) {
|
||||
setMatchedItem(matchedItem)
|
||||
} else {
|
||||
open = false;
|
||||
selectedItem = undefined;
|
||||
selectedId = undefined;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** @param item {ComboBoxItem}*/
|
||||
function setMatchedItem(item) {
|
||||
open = false;
|
||||
selectedItem = item;
|
||||
value = itemToString(selectedItem);
|
||||
selectedId = selectedItem.id;
|
||||
}
|
||||
|
||||
$: ariaLabel = $$props["aria-label"] || "Choose an item";
|
||||
$: menuId = `menu-${id}`;
|
||||
$: comboId = `combo-${id}`;
|
||||
|
@ -305,19 +352,7 @@
|
|||
selectedId = filteredItems[highlightedIndex].id;
|
||||
}
|
||||
} else {
|
||||
// searching typed value in text list with lowercase
|
||||
const matchedItem =
|
||||
filteredItems.find(
|
||||
(e) =>
|
||||
e.text.toLowerCase() === value?.toLowerCase() && !e.disabled
|
||||
) ?? filteredItems.find((e) => !e.disabled);
|
||||
if (matchedItem) {
|
||||
// typed value has matched or fallback to first enabled item
|
||||
open = false;
|
||||
selectedItem = matchedItem;
|
||||
value = itemToString(selectedItem);
|
||||
selectedId = selectedItem.id;
|
||||
}
|
||||
searchForMatchingValue()
|
||||
}
|
||||
highlightedIndex = -1;
|
||||
} else if (key === 'Tab') {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue