svelte-multiselect 8.6.0 → 8.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/CmdPalette.svelte +2 -2
- package/dist/CmdPalette.svelte.d.ts +2 -2
- package/dist/MultiSelect.svelte +59 -47
- package/dist/MultiSelect.svelte.d.ts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +7 -7
- package/package.json +21 -21
- package/readme.md +11 -7
package/dist/CmdPalette.svelte
CHANGED
|
@@ -10,8 +10,8 @@ export let style = ``; // for dialog
|
|
|
10
10
|
// for span in option slot, has no effect when passing slot="option"
|
|
11
11
|
export let span_style = ``;
|
|
12
12
|
export let open = false;
|
|
13
|
-
export let dialog;
|
|
14
|
-
export let input;
|
|
13
|
+
export let dialog = null;
|
|
14
|
+
export let input = null;
|
|
15
15
|
export let placeholder = `Filter actions...`;
|
|
16
16
|
async function toggle(event) {
|
|
17
17
|
if (event.key === trigger && event.metaKey && !open) {
|
|
@@ -11,8 +11,8 @@ declare const __propDef: {
|
|
|
11
11
|
style?: string | undefined;
|
|
12
12
|
span_style?: string | undefined;
|
|
13
13
|
open?: boolean | undefined;
|
|
14
|
-
dialog
|
|
15
|
-
input
|
|
14
|
+
dialog?: HTMLDialogElement | null | undefined;
|
|
15
|
+
input?: HTMLInputElement | null | undefined;
|
|
16
16
|
placeholder?: string | undefined;
|
|
17
17
|
};
|
|
18
18
|
events: {
|
package/dist/MultiSelect.svelte
CHANGED
|
@@ -100,13 +100,18 @@ if (parseLabelsAsHtml && allowUserOptions) {
|
|
|
100
100
|
console.warn(`Don't combine parseLabelsAsHtml and allowUserOptions. It's susceptible to XSS attacks!`);
|
|
101
101
|
}
|
|
102
102
|
if (sortSelected && selectedOptionsDraggable) {
|
|
103
|
-
console.warn(`MultiSelect's sortSelected and selectedOptionsDraggable should not be combined as any
|
|
103
|
+
console.warn(`MultiSelect's sortSelected and selectedOptionsDraggable should not be combined as any ` +
|
|
104
|
+
`user re-orderings of selected options will be undone by sortSelected on component re-renders.`);
|
|
105
|
+
}
|
|
106
|
+
if (allowUserOptions && !createOptionMsg) {
|
|
107
|
+
console.error(`MultiSelect's allowUserOptions=${allowUserOptions} but createOptionMsg=${createOptionMsg} is falsy. ` +
|
|
108
|
+
`This prevents the "Add option" <span> from showing up, resulting in a confusing user experience.`);
|
|
104
109
|
}
|
|
105
110
|
const dispatch = createEventDispatcher();
|
|
106
|
-
let
|
|
111
|
+
let option_msg_is_active = false; // controls active state of <li>{createOptionMsg}</li>
|
|
107
112
|
let window_width;
|
|
108
113
|
// options matching the current search text
|
|
109
|
-
$: matchingOptions = options.filter((op) => filterFunc(op, searchText) && !selected.
|
|
114
|
+
$: matchingOptions = options.filter((op) => filterFunc(op, searchText) && !selected.includes(op) // remove already selected options from dropdown list
|
|
110
115
|
);
|
|
111
116
|
// raise if matchingOptions[activeIndex] does not yield a value
|
|
112
117
|
if (activeIndex !== null && !matchingOptions[activeIndex]) {
|
|
@@ -115,17 +120,17 @@ if (activeIndex !== null && !matchingOptions[activeIndex]) {
|
|
|
115
120
|
// update activeOption when activeIndex changes
|
|
116
121
|
$: activeOption = matchingOptions[activeIndex ?? -1] ?? null;
|
|
117
122
|
// add an option to selected list
|
|
118
|
-
function add(
|
|
123
|
+
function add(option, event) {
|
|
119
124
|
if (maxSelect && maxSelect > 1 && selected.length >= maxSelect)
|
|
120
125
|
wiggle = true;
|
|
121
|
-
if (!isNaN(Number(
|
|
122
|
-
|
|
123
|
-
|
|
126
|
+
if (!isNaN(Number(option)) && typeof selected.map(get_label)[0] === `number`) {
|
|
127
|
+
option = Number(option); // convert to number if possible
|
|
128
|
+
}
|
|
129
|
+
const is_duplicate = selected.some((op) => duplicateFunc(op, option));
|
|
124
130
|
if ((maxSelect === null || maxSelect === 1 || selected.length < maxSelect) &&
|
|
125
131
|
(duplicates || !is_duplicate)) {
|
|
126
|
-
// first check if we find option in the options list
|
|
127
|
-
|
|
128
|
-
if (!option && // this has the side-effect of not allowing to user to add the same
|
|
132
|
+
if (!options.includes(option) && // first check if we find option in the options list
|
|
133
|
+
// this has the side-effect of not allowing to user to add the same
|
|
129
134
|
// custom option twice in append mode
|
|
130
135
|
[true, `append`].includes(allowUserOptions) &&
|
|
131
136
|
searchText.length > 0) {
|
|
@@ -149,13 +154,10 @@ function add(label, event) {
|
|
|
149
154
|
if (allowUserOptions === `append`)
|
|
150
155
|
options = [...options, option];
|
|
151
156
|
}
|
|
152
|
-
if (option === undefined) {
|
|
153
|
-
throw `Run time error, option with label ${label} not found in options list`;
|
|
154
|
-
}
|
|
155
157
|
if (resetFilterOnAdd)
|
|
156
158
|
searchText = ``; // reset search string on selection
|
|
157
159
|
if ([``, undefined, null].includes(option)) {
|
|
158
|
-
console.error(`MultiSelect: encountered
|
|
160
|
+
console.error(`MultiSelect: encountered falsy option ${option}`);
|
|
159
161
|
return;
|
|
160
162
|
}
|
|
161
163
|
if (maxSelect === 1) {
|
|
@@ -234,8 +236,7 @@ async function handle_keydown(event) {
|
|
|
234
236
|
else if (event.key === `Enter`) {
|
|
235
237
|
event.preventDefault(); // prevent enter key from triggering form submission
|
|
236
238
|
if (activeOption) {
|
|
237
|
-
|
|
238
|
-
selected.map(get_label).includes(label) ? remove(label) : add(label, event);
|
|
239
|
+
selected.includes(activeOption) ? remove(activeOption) : add(activeOption, event);
|
|
239
240
|
searchText = ``;
|
|
240
241
|
}
|
|
241
242
|
else if (allowUserOptions && searchText.length > 0) {
|
|
@@ -257,7 +258,7 @@ async function handle_keydown(event) {
|
|
|
257
258
|
else if (allowUserOptions && !matchingOptions.length && searchText.length > 0) {
|
|
258
259
|
// if allowUserOptions is truthy and user entered text but no options match, we make
|
|
259
260
|
// <li>{addUserMsg}</li> active on keydown (or toggle it if already active)
|
|
260
|
-
|
|
261
|
+
option_msg_is_active = !option_msg_is_active;
|
|
261
262
|
return;
|
|
262
263
|
}
|
|
263
264
|
else if (activeIndex === null) {
|
|
@@ -282,7 +283,7 @@ async function handle_keydown(event) {
|
|
|
282
283
|
}
|
|
283
284
|
// on backspace key: remove last selected option
|
|
284
285
|
else if (event.key === `Backspace` && selected.length > 0 && !searchText) {
|
|
285
|
-
remove(selected.
|
|
286
|
+
remove(selected.at(-1));
|
|
286
287
|
}
|
|
287
288
|
// make first matching option active on any keypress (if none of the above special cases match)
|
|
288
289
|
else if (matchingOptions.length > 0) {
|
|
@@ -344,7 +345,14 @@ function highlight_matching_options(event) {
|
|
|
344
345
|
const query = event?.target?.value.trim().toLowerCase();
|
|
345
346
|
if (!query)
|
|
346
347
|
return;
|
|
347
|
-
const tree_walker = document.createTreeWalker(ul_options, NodeFilter.SHOW_TEXT
|
|
348
|
+
const tree_walker = document.createTreeWalker(ul_options, NodeFilter.SHOW_TEXT, {
|
|
349
|
+
acceptNode: (node) => {
|
|
350
|
+
// don't highlight text in the "no matching options" message
|
|
351
|
+
if (node?.textContent === noMatchingOptionsMsg)
|
|
352
|
+
return NodeFilter.FILTER_REJECT;
|
|
353
|
+
return NodeFilter.FILTER_ACCEPT;
|
|
354
|
+
},
|
|
355
|
+
});
|
|
348
356
|
const text_nodes = [];
|
|
349
357
|
let current_node = tree_walker.nextNode();
|
|
350
358
|
while (current_node) {
|
|
@@ -353,10 +361,10 @@ function highlight_matching_options(event) {
|
|
|
353
361
|
}
|
|
354
362
|
// iterate over all text nodes and find matches
|
|
355
363
|
const ranges = text_nodes.map((el) => {
|
|
356
|
-
const text = el.textContent
|
|
364
|
+
const text = el.textContent?.toLowerCase();
|
|
357
365
|
const indices = [];
|
|
358
366
|
let start_pos = 0;
|
|
359
|
-
while (start_pos < text.length) {
|
|
367
|
+
while (text && start_pos < text.length) {
|
|
360
368
|
const index = text.indexOf(query, start_pos);
|
|
361
369
|
if (index === -1)
|
|
362
370
|
break;
|
|
@@ -373,7 +381,7 @@ function highlight_matching_options(event) {
|
|
|
373
381
|
});
|
|
374
382
|
// create Highlight object from ranges and add to registry
|
|
375
383
|
// eslint-disable-next-line no-undef
|
|
376
|
-
CSS.highlights.set(`search-
|
|
384
|
+
CSS.highlights.set(`sms-search-matches`, new Highlight(...ranges.flat()));
|
|
377
385
|
}
|
|
378
386
|
</script>
|
|
379
387
|
|
|
@@ -398,7 +406,7 @@ function highlight_matching_options(event) {
|
|
|
398
406
|
<input
|
|
399
407
|
{name}
|
|
400
408
|
required={Boolean(required)}
|
|
401
|
-
value={selected.length >= required ? JSON.stringify(selected) : null}
|
|
409
|
+
value={selected.length >= Number(required) ? JSON.stringify(selected) : null}
|
|
402
410
|
tabindex="-1"
|
|
403
411
|
aria-hidden="true"
|
|
404
412
|
aria-label="ignore this, used only to prevent form submission if select is required but empty"
|
|
@@ -407,9 +415,9 @@ function highlight_matching_options(event) {
|
|
|
407
415
|
on:invalid={() => {
|
|
408
416
|
invalid = true
|
|
409
417
|
let msg
|
|
410
|
-
if (maxSelect && maxSelect > 1 && required > 1) {
|
|
418
|
+
if (maxSelect && maxSelect > 1 && Number(required) > 1) {
|
|
411
419
|
msg = `Please select between ${required} and ${maxSelect} options`
|
|
412
|
-
} else if (required > 1) {
|
|
420
|
+
} else if (Number(required) > 1) {
|
|
413
421
|
msg = `Please select at least ${required} options`
|
|
414
422
|
} else {
|
|
415
423
|
msg = `Please select an option`
|
|
@@ -421,7 +429,7 @@ function highlight_matching_options(event) {
|
|
|
421
429
|
<ExpandIcon width="15px" style="min-width: 1em; padding: 0 1pt; cursor: pointer;" />
|
|
422
430
|
</slot>
|
|
423
431
|
<ul class="selected {ulSelectedClass}" aria-label="selected options">
|
|
424
|
-
{#each selected as option, idx (
|
|
432
|
+
{#each selected as option, idx (option)}
|
|
425
433
|
<li
|
|
426
434
|
class={liSelectedClass}
|
|
427
435
|
animate:flip={{ duration: 100 }}
|
|
@@ -441,8 +449,8 @@ function highlight_matching_options(event) {
|
|
|
441
449
|
</slot>
|
|
442
450
|
{#if !disabled && (minSelect === null || selected.length > minSelect)}
|
|
443
451
|
<button
|
|
444
|
-
on:mouseup|stopPropagation={() => remove(
|
|
445
|
-
on:keydown={if_enter_or_space(() => remove(
|
|
452
|
+
on:mouseup|stopPropagation={() => remove(option)}
|
|
453
|
+
on:keydown={if_enter_or_space(() => remove(option))}
|
|
446
454
|
type="button"
|
|
447
455
|
title="{removeBtnTitle} {get_label(option)}"
|
|
448
456
|
class="remove"
|
|
@@ -533,7 +541,7 @@ function highlight_matching_options(event) {
|
|
|
533
541
|
<li
|
|
534
542
|
on:mousedown|stopPropagation
|
|
535
543
|
on:mouseup|stopPropagation={(event) => {
|
|
536
|
-
if (!disabled) add(
|
|
544
|
+
if (!disabled) add(option, event)
|
|
537
545
|
}}
|
|
538
546
|
title={disabled
|
|
539
547
|
? disabledTitle
|
|
@@ -560,24 +568,30 @@ function highlight_matching_options(event) {
|
|
|
560
568
|
</slot>
|
|
561
569
|
</li>
|
|
562
570
|
{:else}
|
|
563
|
-
{
|
|
571
|
+
{@const search_is_duplicate = selected.some((option) =>
|
|
572
|
+
duplicateFunc(option, searchText)
|
|
573
|
+
)}
|
|
574
|
+
{@const msg =
|
|
575
|
+
!duplicates && search_is_duplicate ? duplicateOptionMsg : createOptionMsg}
|
|
576
|
+
{#if allowUserOptions && searchText && msg}
|
|
564
577
|
<li
|
|
565
578
|
on:mousedown|stopPropagation
|
|
566
579
|
on:mouseup|stopPropagation={(event) => add(searchText, event)}
|
|
567
580
|
title={createOptionMsg}
|
|
568
|
-
class:active={
|
|
569
|
-
on:mouseover={() => (
|
|
570
|
-
on:focus={() => (
|
|
571
|
-
on:mouseout={() => (
|
|
572
|
-
on:blur={() => (
|
|
581
|
+
class:active={option_msg_is_active}
|
|
582
|
+
on:mouseover={() => (option_msg_is_active = true)}
|
|
583
|
+
on:focus={() => (option_msg_is_active = true)}
|
|
584
|
+
on:mouseout={() => (option_msg_is_active = false)}
|
|
585
|
+
on:blur={() => (option_msg_is_active = false)}
|
|
586
|
+
class="user-msg"
|
|
573
587
|
>
|
|
574
|
-
{
|
|
575
|
-
? duplicateOptionMsg
|
|
576
|
-
: createOptionMsg}
|
|
588
|
+
{msg}
|
|
577
589
|
</li>
|
|
578
|
-
{:else}
|
|
579
|
-
|
|
590
|
+
{:else if noMatchingOptionsMsg}
|
|
591
|
+
<!-- use span to not have cursor: pointer -->
|
|
592
|
+
<span class="user-msg">{noMatchingOptionsMsg}</span>
|
|
580
593
|
{/if}
|
|
594
|
+
<!-- Show nothing if all messages are empty -->
|
|
581
595
|
{/each}
|
|
582
596
|
</ul>
|
|
583
597
|
{/if}
|
|
@@ -721,8 +735,9 @@ function highlight_matching_options(event) {
|
|
|
721
735
|
cursor: pointer;
|
|
722
736
|
scroll-margin: var(--sms-options-scroll-margin, 100px);
|
|
723
737
|
}
|
|
724
|
-
|
|
725
|
-
|
|
738
|
+
:where(div.multiselect > ul.options .user-msg) {
|
|
739
|
+
/* block needed so vertical padding applies to span */
|
|
740
|
+
display: block;
|
|
726
741
|
padding: 3pt 2ex;
|
|
727
742
|
}
|
|
728
743
|
:where(div.multiselect > ul.options > li.selected) {
|
|
@@ -741,10 +756,7 @@ function highlight_matching_options(event) {
|
|
|
741
756
|
:where(span.max-select-msg) {
|
|
742
757
|
padding: 0 3pt;
|
|
743
758
|
}
|
|
744
|
-
::highlight(search-
|
|
745
|
-
color:
|
|
746
|
-
background: var(--sms-highlight-bg);
|
|
747
|
-
text-decoration: var(--sms-highlight-text-decoration);
|
|
748
|
-
text-decoration-color: var(--sms-highlight-text-decoration-color);
|
|
759
|
+
::highlight(sms-search-matches) {
|
|
760
|
+
color: mediumaquamarine;
|
|
749
761
|
}
|
|
750
762
|
</style>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { SvelteComponentTyped } from "svelte";
|
|
2
|
-
import type {
|
|
2
|
+
import type { Option as GenericOption, MultiSelectEvents } from './';
|
|
3
3
|
declare class __sveltets_Render<Option extends GenericOption> {
|
|
4
4
|
props(): {
|
|
5
5
|
activeIndex?: number | null | undefined;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { default as CircleSpinner } from './CircleSpinner.svelte';
|
|
2
2
|
export { default as CmdPalette } from './CmdPalette.svelte';
|
|
3
|
-
export { default
|
|
3
|
+
export { default as MultiSelect, default } from './MultiSelect.svelte';
|
|
4
4
|
export { default as Wiggle } from './Wiggle.svelte';
|
|
5
5
|
export type Option = string | number | ObjectOption;
|
|
6
6
|
export type ObjectOption = {
|
package/dist/index.js
CHANGED
|
@@ -1,26 +1,26 @@
|
|
|
1
1
|
export { default as CircleSpinner } from './CircleSpinner.svelte';
|
|
2
2
|
export { default as CmdPalette } from './CmdPalette.svelte';
|
|
3
|
-
export { default
|
|
3
|
+
export { default as MultiSelect, default } from './MultiSelect.svelte';
|
|
4
4
|
export { default as Wiggle } from './Wiggle.svelte';
|
|
5
|
-
// Firefox lacks support for scrollIntoViewIfNeeded
|
|
6
|
-
// https://github.com/janosh/svelte-multiselect/issues/87
|
|
7
|
-
//
|
|
5
|
+
// Firefox lacks support for scrollIntoViewIfNeeded (https://caniuse.com/scrollintoviewifneeded).
|
|
6
|
+
// See https://github.com/janosh/svelte-multiselect/issues/87
|
|
7
|
+
// Polyfill copied from
|
|
8
8
|
// https://github.com/nuxodin/lazyfill/blob/a8e63/polyfills/Element/prototype/scrollIntoViewIfNeeded.js
|
|
9
9
|
// exported for testing
|
|
10
10
|
export function scroll_into_view_if_needed_polyfill(centerIfNeeded = true) {
|
|
11
|
-
const
|
|
11
|
+
const elem = this;
|
|
12
12
|
const observer = new IntersectionObserver(function ([entry]) {
|
|
13
13
|
const ratio = entry.intersectionRatio;
|
|
14
14
|
if (ratio < 1) {
|
|
15
15
|
const place = ratio <= 0 && centerIfNeeded ? `center` : `nearest`;
|
|
16
|
-
|
|
16
|
+
elem.scrollIntoView({
|
|
17
17
|
block: place,
|
|
18
18
|
inline: place,
|
|
19
19
|
});
|
|
20
20
|
}
|
|
21
21
|
this.disconnect();
|
|
22
22
|
});
|
|
23
|
-
observer.observe(
|
|
23
|
+
observer.observe(elem);
|
|
24
24
|
return observer; // return for testing
|
|
25
25
|
}
|
|
26
26
|
if (typeof Element !== `undefined` &&
|
package/package.json
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"homepage": "https://janosh.github.io/svelte-multiselect",
|
|
6
6
|
"repository": "https://github.com/janosh/svelte-multiselect",
|
|
7
7
|
"license": "MIT",
|
|
8
|
-
"version": "8.6.
|
|
8
|
+
"version": "8.6.1",
|
|
9
9
|
"type": "module",
|
|
10
10
|
"svelte": "./dist/index.js",
|
|
11
11
|
"bugs": "https://github.com/janosh/svelte-multiselect/issues",
|
|
@@ -23,37 +23,37 @@
|
|
|
23
23
|
"update-coverage": "vitest tests/unit --run --coverage && npx istanbul-badges-readme"
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
|
-
"svelte": "^3.
|
|
26
|
+
"svelte": "^3.58.0"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
|
-
"@iconify/svelte": "^3.1.
|
|
30
|
-
"@playwright/test": "^1.
|
|
31
|
-
"@sveltejs/adapter-static": "^2.0.
|
|
32
|
-
"@sveltejs/kit": "^1.
|
|
29
|
+
"@iconify/svelte": "^3.1.3",
|
|
30
|
+
"@playwright/test": "^1.33.0",
|
|
31
|
+
"@sveltejs/adapter-static": "^2.0.2",
|
|
32
|
+
"@sveltejs/kit": "^1.15.9",
|
|
33
33
|
"@sveltejs/package": "2.0.2",
|
|
34
|
-
"@sveltejs/vite-plugin-svelte": "^2.
|
|
35
|
-
"@typescript-eslint/eslint-plugin": "^5.
|
|
36
|
-
"@typescript-eslint/parser": "^5.
|
|
37
|
-
"@vitest/coverage-c8": "^0.
|
|
38
|
-
"eslint": "^8.
|
|
34
|
+
"@sveltejs/vite-plugin-svelte": "^2.1.1",
|
|
35
|
+
"@typescript-eslint/eslint-plugin": "^5.59.1",
|
|
36
|
+
"@typescript-eslint/parser": "^5.59.1",
|
|
37
|
+
"@vitest/coverage-c8": "^0.30.1",
|
|
38
|
+
"eslint": "^8.39.0",
|
|
39
39
|
"eslint-plugin-svelte3": "^4.0.0",
|
|
40
40
|
"hastscript": "^7.2.0",
|
|
41
|
-
"highlight.js": "^11.
|
|
41
|
+
"highlight.js": "^11.8.0",
|
|
42
42
|
"jsdom": "^21.1.1",
|
|
43
43
|
"mdsvex": "^0.10.6",
|
|
44
44
|
"mdsvexamples": "^0.3.3",
|
|
45
|
-
"prettier": "^2.8.
|
|
46
|
-
"prettier-plugin-svelte": "^2.
|
|
45
|
+
"prettier": "^2.8.8",
|
|
46
|
+
"prettier-plugin-svelte": "^2.10.0",
|
|
47
47
|
"rehype-autolink-headings": "^6.1.1",
|
|
48
48
|
"rehype-slug": "^5.1.0",
|
|
49
|
-
"svelte-check": "^3.
|
|
49
|
+
"svelte-check": "^3.2.0",
|
|
50
50
|
"svelte-preprocess": "^5.0.3",
|
|
51
|
-
"svelte-toc": "^0.5.
|
|
52
|
-
"svelte-zoo": "^0.4.
|
|
53
|
-
"svelte2tsx": "^0.6.
|
|
54
|
-
"typescript": "5.0.
|
|
55
|
-
"vite": "^4.
|
|
56
|
-
"vitest": "^0.
|
|
51
|
+
"svelte-toc": "^0.5.5",
|
|
52
|
+
"svelte-zoo": "^0.4.5",
|
|
53
|
+
"svelte2tsx": "^0.6.11",
|
|
54
|
+
"typescript": "5.0.4",
|
|
55
|
+
"vite": "^4.3.3",
|
|
56
|
+
"vitest": "^0.30.1"
|
|
57
57
|
},
|
|
58
58
|
"keywords": [
|
|
59
59
|
"svelte",
|
package/readme.md
CHANGED
|
@@ -189,7 +189,7 @@ Full list of props/bindable variables for this component. The `Option` type you
|
|
|
189
189
|
highlightMatches: boolean = true
|
|
190
190
|
```
|
|
191
191
|
|
|
192
|
-
Whether to highlight text in the dropdown options that matches the current user-entered search query. Uses the [CSS Custom Highlight API](https://developer.mozilla.org/docs/Web/API/CSS_Custom_Highlight_API) with limited browser support and [styling options](https://developer.mozilla.org/docs/Web/CSS/::highlight). See `::highlight(search-
|
|
192
|
+
Whether to highlight text in the dropdown options that matches the current user-entered search query. Uses the [CSS Custom Highlight API](https://developer.mozilla.org/docs/Web/API/CSS_Custom_Highlight_API) with limited browser support and [styling options](https://developer.mozilla.org/docs/Web/CSS/::highlight). See `::highlight(sms-search-matches)` below for available CSS variables.
|
|
193
193
|
|
|
194
194
|
1. ```ts
|
|
195
195
|
id: string | null = null
|
|
@@ -526,7 +526,7 @@ Minimal example that changes the background color of the options dropdown:
|
|
|
526
526
|
- `div.multiselect.open`
|
|
527
527
|
- `z-index: var(--sms-open-z-index, 4)`: Increase this if needed to ensure the dropdown list is displayed atop all other page elements.
|
|
528
528
|
- `div.multiselect:focus-within`
|
|
529
|
-
- `border: var(--sms-focus-border, 1pt solid var(--sms-active-color, cornflowerblue))`: Border when component has focus. Defaults to `--sms-active-color`
|
|
529
|
+
- `border: var(--sms-focus-border, 1pt solid var(--sms-active-color, cornflowerblue))`: Border when component has focus. Defaults to `--sms-active-color` which in turn defaults to `cornflowerblue`.
|
|
530
530
|
- `div.multiselect.disabled`
|
|
531
531
|
- `background: var(--sms-disabled-bg, lightgray)`: Background when in disabled state.
|
|
532
532
|
- `div.multiselect input::placeholder`
|
|
@@ -559,11 +559,15 @@ Minimal example that changes the background color of the options dropdown:
|
|
|
559
559
|
- `div.multiselect > ul.options > li.disabled`
|
|
560
560
|
- `background: var(--sms-li-disabled-bg, #f5f5f6)`: Background of disabled options in the dropdown list.
|
|
561
561
|
- `color: var(--sms-li-disabled-text, #b8b8b8)`: Text color of disabled option in the dropdown list.
|
|
562
|
-
- `::highlight(search-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
562
|
+
- `::highlight(sms-search-matches)`: applies to search results in dropdown list that match the current search query if `highlightMatches=true`. These styles [cannot be set via CSS variables](https://stackoverflow.com/a/56799215). Instead, use a new rule set. For example:
|
|
563
|
+
|
|
564
|
+
```css
|
|
565
|
+
::highlight(sms-search-matches) {
|
|
566
|
+
color: orange;
|
|
567
|
+
background: rgba(0, 0, 0, 0.15);
|
|
568
|
+
text-decoration: underline;
|
|
569
|
+
}
|
|
570
|
+
```
|
|
567
571
|
|
|
568
572
|
### With CSS frameworks
|
|
569
573
|
|