svelte-multiselect 8.4.0 → 8.6.0
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 +26 -9
- package/dist/CmdPalette.svelte.d.ts +12 -1
- package/dist/MultiSelect.svelte +92 -50
- package/dist/MultiSelect.svelte.d.ts +1 -0
- package/dist/index.d.ts +3 -0
- package/package.json +17 -17
- package/readme.md +19 -8
package/dist/CmdPalette.svelte
CHANGED
|
@@ -1,12 +1,18 @@
|
|
|
1
|
-
<script
|
|
1
|
+
<script>/* eslint-disable no-undef */ // TODO: remove when fixed
|
|
2
|
+
// https://github.com/sveltejs/eslint-plugin-svelte3/issues/201
|
|
3
|
+
import { tick } from 'svelte';
|
|
2
4
|
import { fade } from 'svelte/transition';
|
|
3
5
|
import Select from '.';
|
|
4
6
|
export let actions;
|
|
5
7
|
export let trigger = `k`;
|
|
6
8
|
export let fade_duration = 200; // in ms
|
|
7
|
-
let
|
|
8
|
-
|
|
9
|
-
let
|
|
9
|
+
export let style = ``; // for dialog
|
|
10
|
+
// for span in option slot, has no effect when passing slot="option"
|
|
11
|
+
export let span_style = ``;
|
|
12
|
+
export let open = false;
|
|
13
|
+
export let dialog;
|
|
14
|
+
export let input;
|
|
15
|
+
export let placeholder = `Filter actions...`;
|
|
10
16
|
async function toggle(event) {
|
|
11
17
|
if (event.key === trigger && event.metaKey && !open) {
|
|
12
18
|
// open on cmd+trigger
|
|
@@ -24,7 +30,7 @@ function close_if_outside(event) {
|
|
|
24
30
|
open = false;
|
|
25
31
|
}
|
|
26
32
|
}
|
|
27
|
-
function
|
|
33
|
+
function run_and_close(event) {
|
|
28
34
|
event.detail.option.action();
|
|
29
35
|
open = false;
|
|
30
36
|
}
|
|
@@ -33,14 +39,25 @@ function move(event) {
|
|
|
33
39
|
<svelte:window on:keydown={toggle} on:click={close_if_outside} />
|
|
34
40
|
|
|
35
41
|
{#if open}
|
|
36
|
-
<dialog
|
|
42
|
+
<dialog
|
|
43
|
+
class:open
|
|
44
|
+
bind:this={dialog}
|
|
45
|
+
transition:fade={{ duration: fade_duration }}
|
|
46
|
+
{style}
|
|
47
|
+
>
|
|
37
48
|
<Select
|
|
38
49
|
options={actions}
|
|
39
50
|
bind:input
|
|
40
|
-
placeholder
|
|
41
|
-
on:add={
|
|
51
|
+
{placeholder}
|
|
52
|
+
on:add={run_and_close}
|
|
42
53
|
on:keydown={toggle}
|
|
43
|
-
|
|
54
|
+
{...$$props}
|
|
55
|
+
>
|
|
56
|
+
<!-- wait for https://github.com/sveltejs/svelte/pull/8304 -->
|
|
57
|
+
<slot slot="option" name="option" let:option>
|
|
58
|
+
<span style={span_style}>{option.label}</span>
|
|
59
|
+
</slot>
|
|
60
|
+
</Select>
|
|
44
61
|
</dialog>
|
|
45
62
|
{/if}
|
|
46
63
|
|
|
@@ -1,17 +1,28 @@
|
|
|
1
1
|
import { SvelteComponentTyped } from "svelte";
|
|
2
2
|
declare const __propDef: {
|
|
3
3
|
props: {
|
|
4
|
+
[x: string]: any;
|
|
4
5
|
actions: {
|
|
5
6
|
label: string;
|
|
6
7
|
action: () => void;
|
|
7
8
|
}[];
|
|
8
9
|
trigger?: string | undefined;
|
|
9
10
|
fade_duration?: number | undefined;
|
|
11
|
+
style?: string | undefined;
|
|
12
|
+
span_style?: string | undefined;
|
|
13
|
+
open?: boolean | undefined;
|
|
14
|
+
dialog: HTMLDialogElement;
|
|
15
|
+
input: HTMLInputElement;
|
|
16
|
+
placeholder?: string | undefined;
|
|
10
17
|
};
|
|
11
18
|
events: {
|
|
12
19
|
[evt: string]: CustomEvent<any>;
|
|
13
20
|
};
|
|
14
|
-
slots: {
|
|
21
|
+
slots: {
|
|
22
|
+
option: {
|
|
23
|
+
slot: string;
|
|
24
|
+
};
|
|
25
|
+
};
|
|
15
26
|
};
|
|
16
27
|
export type CmdPaletteProps = typeof __propDef.props;
|
|
17
28
|
export type CmdPaletteEvents = typeof __propDef.events;
|
package/dist/MultiSelect.svelte
CHANGED
|
@@ -25,6 +25,7 @@ export let filterFunc = (op, searchText) => {
|
|
|
25
25
|
};
|
|
26
26
|
export let focusInputOnSelect = `desktop`;
|
|
27
27
|
export let form_input = null;
|
|
28
|
+
export let highlightMatches = true;
|
|
28
29
|
export let id = null;
|
|
29
30
|
export let input = null;
|
|
30
31
|
export let inputClass = ``;
|
|
@@ -128,7 +129,7 @@ function add(label, event) {
|
|
|
128
129
|
// custom option twice in append mode
|
|
129
130
|
[true, `append`].includes(allowUserOptions) &&
|
|
130
131
|
searchText.length > 0) {
|
|
131
|
-
// user entered text but no options match, so if allowUserOptions=true | 'append', we create
|
|
132
|
+
// user entered text but no options match, so if allowUserOptions = true | 'append', we create
|
|
132
133
|
// a new option from the user-entered text
|
|
133
134
|
if (typeof options[0] === `object`) {
|
|
134
135
|
// if 1st option is an object, we create new option as object to keep type homogeneity
|
|
@@ -140,8 +141,10 @@ function add(label, event) {
|
|
|
140
141
|
// create new option as number if it parses to a number and 1st option is also number or missing
|
|
141
142
|
option = Number(searchText);
|
|
142
143
|
}
|
|
143
|
-
else
|
|
144
|
+
else {
|
|
144
145
|
option = searchText; // else create custom option as string
|
|
146
|
+
}
|
|
147
|
+
dispatch(`create`, { option });
|
|
145
148
|
}
|
|
146
149
|
if (allowUserOptions === `append`)
|
|
147
150
|
options = [...options, option];
|
|
@@ -199,10 +202,10 @@ function remove(label) {
|
|
|
199
202
|
return console.error(`Multiselect can't remove selected option ${label}, not found in selected list`);
|
|
200
203
|
}
|
|
201
204
|
selected = selected.filter((op) => get_label(op) !== label); // remove option from selected list
|
|
202
|
-
dispatch(`remove`, { option });
|
|
203
|
-
dispatch(`change`, { option, type: `remove` });
|
|
204
205
|
invalid = false; // reset error status whenever items are removed
|
|
205
206
|
form_input?.setCustomValidity(``);
|
|
207
|
+
dispatch(`remove`, { option });
|
|
208
|
+
dispatch(`change`, { option, type: `remove` });
|
|
206
209
|
}
|
|
207
210
|
function open_dropdown(event) {
|
|
208
211
|
if (disabled)
|
|
@@ -287,10 +290,10 @@ async function handle_keydown(event) {
|
|
|
287
290
|
}
|
|
288
291
|
}
|
|
289
292
|
function remove_all() {
|
|
290
|
-
dispatch(`removeAll`, { options: selected });
|
|
291
|
-
dispatch(`change`, { options: selected, type: `removeAll` });
|
|
292
293
|
selected = [];
|
|
293
294
|
searchText = ``;
|
|
295
|
+
dispatch(`removeAll`, { options: selected });
|
|
296
|
+
dispatch(`change`, { options: selected, type: `removeAll` });
|
|
294
297
|
}
|
|
295
298
|
$: is_selected = (label) => selected.map(get_label).includes(label);
|
|
296
299
|
const if_enter_or_space = (handler) => (event) => {
|
|
@@ -331,6 +334,47 @@ const dragstart = (idx) => (event) => {
|
|
|
331
334
|
event.dataTransfer.dropEffect = `move`;
|
|
332
335
|
event.dataTransfer.setData(`text/plain`, `${idx}`);
|
|
333
336
|
};
|
|
337
|
+
let ul_options;
|
|
338
|
+
function highlight_matching_options(event) {
|
|
339
|
+
if (!highlightMatches || typeof CSS == `undefined` || !CSS.highlights)
|
|
340
|
+
return; // don't try if CSS highlight API not supported
|
|
341
|
+
// clear previous ranges from HighlightRegistry
|
|
342
|
+
CSS.highlights.clear();
|
|
343
|
+
// get input's search query
|
|
344
|
+
const query = event?.target?.value.trim().toLowerCase();
|
|
345
|
+
if (!query)
|
|
346
|
+
return;
|
|
347
|
+
const tree_walker = document.createTreeWalker(ul_options, NodeFilter.SHOW_TEXT);
|
|
348
|
+
const text_nodes = [];
|
|
349
|
+
let current_node = tree_walker.nextNode();
|
|
350
|
+
while (current_node) {
|
|
351
|
+
text_nodes.push(current_node);
|
|
352
|
+
current_node = tree_walker.nextNode();
|
|
353
|
+
}
|
|
354
|
+
// iterate over all text nodes and find matches
|
|
355
|
+
const ranges = text_nodes.map((el) => {
|
|
356
|
+
const text = el.textContent.toLowerCase();
|
|
357
|
+
const indices = [];
|
|
358
|
+
let start_pos = 0;
|
|
359
|
+
while (start_pos < text.length) {
|
|
360
|
+
const index = text.indexOf(query, start_pos);
|
|
361
|
+
if (index === -1)
|
|
362
|
+
break;
|
|
363
|
+
indices.push(index);
|
|
364
|
+
start_pos = index + query.length;
|
|
365
|
+
}
|
|
366
|
+
// create range object for each str found in the text node
|
|
367
|
+
return indices.map((index) => {
|
|
368
|
+
const range = new Range();
|
|
369
|
+
range.setStart(el, index);
|
|
370
|
+
range.setEnd(el, index + query.length);
|
|
371
|
+
return range;
|
|
372
|
+
});
|
|
373
|
+
});
|
|
374
|
+
// create Highlight object from ranges and add to registry
|
|
375
|
+
// eslint-disable-next-line no-undef
|
|
376
|
+
CSS.highlights.set(`search-results`, new Highlight(...ranges.flat()));
|
|
377
|
+
}
|
|
334
378
|
</script>
|
|
335
379
|
|
|
336
380
|
<svelte:window
|
|
@@ -344,13 +388,10 @@ const dragstart = (idx) => (event) => {
|
|
|
344
388
|
class:disabled
|
|
345
389
|
class:single={maxSelect === 1}
|
|
346
390
|
class:open
|
|
347
|
-
aria-expanded={open}
|
|
348
|
-
aria-multiselectable={maxSelect === null || maxSelect > 1}
|
|
349
391
|
class:invalid
|
|
350
392
|
class="multiselect {outerDivClass}"
|
|
351
393
|
on:mouseup|stopPropagation={open_dropdown}
|
|
352
394
|
title={disabled ? disabledInputTitle : null}
|
|
353
|
-
aria-disabled={disabled ? `true` : null}
|
|
354
395
|
data-id={id}
|
|
355
396
|
>
|
|
356
397
|
<!-- bind:value={selected} prevents form submission if required prop is true and no options are selected -->
|
|
@@ -379,11 +420,10 @@ const dragstart = (idx) => (event) => {
|
|
|
379
420
|
<slot name="expand-icon" {open}>
|
|
380
421
|
<ExpandIcon width="15px" style="min-width: 1em; padding: 0 1pt; cursor: pointer;" />
|
|
381
422
|
</slot>
|
|
382
|
-
<ul class="selected {ulSelectedClass}">
|
|
423
|
+
<ul class="selected {ulSelectedClass}" aria-label="selected options">
|
|
383
424
|
{#each selected as option, idx (get_label(option))}
|
|
384
425
|
<li
|
|
385
426
|
class={liSelectedClass}
|
|
386
|
-
aria-selected="true"
|
|
387
427
|
animate:flip={{ duration: 100 }}
|
|
388
428
|
draggable={selectedOptionsDraggable && !disabled && selected.length > 1}
|
|
389
429
|
on:dragstart={dragstart(idx)}
|
|
@@ -397,8 +437,7 @@ const dragstart = (idx) => (event) => {
|
|
|
397
437
|
{#if parseLabelsAsHtml}
|
|
398
438
|
{@html get_label(option)}
|
|
399
439
|
{:else}
|
|
400
|
-
{get_label(option)}
|
|
401
|
-
{/if}
|
|
440
|
+
{get_label(option)}{/if}
|
|
402
441
|
</slot>
|
|
403
442
|
{#if !disabled && (minSelect === null || selected.length > minSelect)}
|
|
404
443
|
<button
|
|
@@ -415,38 +454,37 @@ const dragstart = (idx) => (event) => {
|
|
|
415
454
|
{/if}
|
|
416
455
|
</li>
|
|
417
456
|
{/each}
|
|
418
|
-
<
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
</li>
|
|
457
|
+
<input
|
|
458
|
+
class={inputClass}
|
|
459
|
+
bind:this={input}
|
|
460
|
+
bind:value={searchText}
|
|
461
|
+
on:mouseup|self|stopPropagation={open_dropdown}
|
|
462
|
+
on:keydown|stopPropagation={handle_keydown}
|
|
463
|
+
on:focus
|
|
464
|
+
on:focus={open_dropdown}
|
|
465
|
+
on:input={highlight_matching_options}
|
|
466
|
+
{id}
|
|
467
|
+
{disabled}
|
|
468
|
+
{autocomplete}
|
|
469
|
+
{inputmode}
|
|
470
|
+
{pattern}
|
|
471
|
+
placeholder={selected.length == 0 ? placeholder : null}
|
|
472
|
+
aria-invalid={invalid ? `true` : null}
|
|
473
|
+
ondrop="return false"
|
|
474
|
+
on:blur
|
|
475
|
+
on:change
|
|
476
|
+
on:click
|
|
477
|
+
on:keydown
|
|
478
|
+
on:keyup
|
|
479
|
+
on:mousedown
|
|
480
|
+
on:mouseenter
|
|
481
|
+
on:mouseleave
|
|
482
|
+
on:touchcancel
|
|
483
|
+
on:touchend
|
|
484
|
+
on:touchmove
|
|
485
|
+
on:touchstart
|
|
486
|
+
/>
|
|
487
|
+
<!-- the above on:* lines forward potentially useful DOM events -->
|
|
450
488
|
</ul>
|
|
451
489
|
{#if loading}
|
|
452
490
|
<slot name="spinner">
|
|
@@ -482,7 +520,7 @@ const dragstart = (idx) => (event) => {
|
|
|
482
520
|
|
|
483
521
|
<!-- only render options dropdown if options or searchText is not empty needed to avoid briefly flashing empty dropdown -->
|
|
484
522
|
{#if (searchText && noMatchingOptionsMsg) || options?.length > 0}
|
|
485
|
-
<ul class:hidden={!open} class="options {ulOptionsClass}">
|
|
523
|
+
<ul class:hidden={!open} class="options {ulOptionsClass}" bind:this={ul_options}>
|
|
486
524
|
{#each matchingOptions as option, idx}
|
|
487
525
|
{@const {
|
|
488
526
|
label,
|
|
@@ -512,7 +550,6 @@ const dragstart = (idx) => (event) => {
|
|
|
512
550
|
}}
|
|
513
551
|
on:mouseout={() => (activeIndex = null)}
|
|
514
552
|
on:blur={() => (activeIndex = null)}
|
|
515
|
-
aria-selected="false"
|
|
516
553
|
>
|
|
517
554
|
<slot name="option" {option} {idx}>
|
|
518
555
|
{#if parseLabelsAsHtml}
|
|
@@ -533,7 +570,6 @@ const dragstart = (idx) => (event) => {
|
|
|
533
570
|
on:focus={() => (add_option_msg_is_active = true)}
|
|
534
571
|
on:mouseout={() => (add_option_msg_is_active = false)}
|
|
535
572
|
on:blur={() => (add_option_msg_is_active = false)}
|
|
536
|
-
aria-selected="false"
|
|
537
573
|
>
|
|
538
574
|
{!duplicates && selected.some((option) => duplicateFunc(option, searchText))
|
|
539
575
|
? duplicateOptionMsg
|
|
@@ -627,7 +663,7 @@ const dragstart = (idx) => (event) => {
|
|
|
627
663
|
margin: auto 0; /* CSS reset */
|
|
628
664
|
padding: 0; /* CSS reset */
|
|
629
665
|
}
|
|
630
|
-
:where(div.multiselect > ul.selected >
|
|
666
|
+
:where(div.multiselect > ul.selected > input) {
|
|
631
667
|
border: none;
|
|
632
668
|
outline: none;
|
|
633
669
|
background: none;
|
|
@@ -640,7 +676,7 @@ const dragstart = (idx) => (event) => {
|
|
|
640
676
|
border-radius: 0; /* reset ul.selected > li */
|
|
641
677
|
}
|
|
642
678
|
/* don't wrap ::placeholder rules in :where() as it seems to be overpowered by browser defaults i.t.o. specificity */
|
|
643
|
-
div.multiselect > ul.selected >
|
|
679
|
+
div.multiselect > ul.selected > input::placeholder {
|
|
644
680
|
padding-left: 5pt;
|
|
645
681
|
color: var(--sms-placeholder-color);
|
|
646
682
|
opacity: var(--sms-placeholder-opacity);
|
|
@@ -705,4 +741,10 @@ const dragstart = (idx) => (event) => {
|
|
|
705
741
|
:where(span.max-select-msg) {
|
|
706
742
|
padding: 0 3pt;
|
|
707
743
|
}
|
|
744
|
+
::highlight(search-results) {
|
|
745
|
+
color: var(--sms-highlight-color, orange);
|
|
746
|
+
background: var(--sms-highlight-bg);
|
|
747
|
+
text-decoration: var(--sms-highlight-text-decoration);
|
|
748
|
+
text-decoration-color: var(--sms-highlight-text-decoration-color);
|
|
749
|
+
}
|
|
708
750
|
</style>
|
|
@@ -19,6 +19,7 @@ declare class __sveltets_Render<Option extends GenericOption> {
|
|
|
19
19
|
filterFunc?: ((op: Option, searchText: string) => boolean) | undefined;
|
|
20
20
|
focusInputOnSelect?: boolean | "desktop" | undefined;
|
|
21
21
|
form_input?: HTMLInputElement | null | undefined;
|
|
22
|
+
highlightMatches?: boolean | undefined;
|
|
22
23
|
id?: string | null | undefined;
|
|
23
24
|
input?: HTMLInputElement | null | undefined;
|
|
24
25
|
inputClass?: string | undefined;
|
package/dist/index.d.ts
CHANGED
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.
|
|
8
|
+
"version": "8.6.0",
|
|
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.57.0"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
29
|
"@iconify/svelte": "^3.1.0",
|
|
30
|
-
"@playwright/test": "^1.31.
|
|
30
|
+
"@playwright/test": "^1.31.2",
|
|
31
31
|
"@sveltejs/adapter-static": "^2.0.1",
|
|
32
|
-
"@sveltejs/kit": "^1.
|
|
32
|
+
"@sveltejs/kit": "^1.12.0",
|
|
33
33
|
"@sveltejs/package": "2.0.2",
|
|
34
34
|
"@sveltejs/vite-plugin-svelte": "^2.0.3",
|
|
35
|
-
"@typescript-eslint/eslint-plugin": "^5.
|
|
36
|
-
"@typescript-eslint/parser": "^5.
|
|
37
|
-
"@vitest/coverage-c8": "^0.29.
|
|
38
|
-
"eslint": "^8.
|
|
35
|
+
"@typescript-eslint/eslint-plugin": "^5.55.0",
|
|
36
|
+
"@typescript-eslint/parser": "^5.55.0",
|
|
37
|
+
"@vitest/coverage-c8": "^0.29.3",
|
|
38
|
+
"eslint": "^8.36.0",
|
|
39
39
|
"eslint-plugin-svelte3": "^4.0.0",
|
|
40
40
|
"hastscript": "^7.2.0",
|
|
41
41
|
"highlight.js": "^11.7.0",
|
|
42
|
-
"jsdom": "^21.1.
|
|
42
|
+
"jsdom": "^21.1.1",
|
|
43
43
|
"mdsvex": "^0.10.6",
|
|
44
44
|
"mdsvexamples": "^0.3.3",
|
|
45
45
|
"prettier": "^2.8.4",
|
|
46
46
|
"prettier-plugin-svelte": "^2.9.0",
|
|
47
47
|
"rehype-autolink-headings": "^6.1.1",
|
|
48
48
|
"rehype-slug": "^5.1.0",
|
|
49
|
-
"svelte-check": "^3.
|
|
50
|
-
"svelte-preprocess": "^5.0.
|
|
51
|
-
"svelte-toc": "^0.5.
|
|
52
|
-
"svelte-zoo": "^0.3
|
|
53
|
-
"svelte2tsx": "^0.6.
|
|
54
|
-
"typescript": "
|
|
55
|
-
"vite": "^4.
|
|
56
|
-
"vitest": "^0.29.
|
|
49
|
+
"svelte-check": "^3.1.4",
|
|
50
|
+
"svelte-preprocess": "^5.0.3",
|
|
51
|
+
"svelte-toc": "^0.5.4",
|
|
52
|
+
"svelte-zoo": "^0.4.3",
|
|
53
|
+
"svelte2tsx": "^0.6.10",
|
|
54
|
+
"typescript": "5.0.2",
|
|
55
|
+
"vite": "^4.2.0",
|
|
56
|
+
"vitest": "^0.29.3"
|
|
57
57
|
},
|
|
58
58
|
"keywords": [
|
|
59
59
|
"svelte",
|
package/readme.md
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
[](https://github.com/janosh/svelte-multiselect/actions/workflows/test.yml)
|
|
9
9
|
[](https://github.com/janosh/svelte-multiselect/actions/workflows/gh-pages.yml)
|
|
10
10
|
[](https://npmjs.com/package/svelte-multiselect)
|
|
11
|
-
[](https://github.com/sveltejs/svelte/blob/master/CHANGELOG.md)
|
|
12
12
|
[](https://svelte.dev/repl/a5a14b8f15d64cb083b567292480db05)
|
|
13
13
|
[](https://stackblitz.com/github/janosh/svelte-multiselect)
|
|
14
14
|
|
|
@@ -185,6 +185,12 @@ Full list of props/bindable variables for this component. The `Option` type you
|
|
|
185
185
|
|
|
186
186
|
Handle to the `<input>` DOM node that's responsible for form validity checks and passing selected options to form submission handlers. Only available after component mounts (`null` before then).
|
|
187
187
|
|
|
188
|
+
1. ```ts
|
|
189
|
+
highlightMatches: boolean = true
|
|
190
|
+
```
|
|
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-results)` below for available CSS variables.
|
|
193
|
+
|
|
188
194
|
1. ```ts
|
|
189
195
|
id: string | null = null
|
|
190
196
|
```
|
|
@@ -500,6 +506,12 @@ There are 3 ways to style this component. To understand which options do what, i
|
|
|
500
506
|
|
|
501
507
|
If you only want to make small adjustments, you can pass the following CSS variables directly to the component as props or define them in a `:global()` CSS context. See [`app.css`](https://github.com/janosh/svelte-multiselect/blob/main/src/app.css) for how these variables are set on the demo site of this component.
|
|
502
508
|
|
|
509
|
+
Minimal example that changes the background color of the options dropdown:
|
|
510
|
+
|
|
511
|
+
```svelte
|
|
512
|
+
<MultiSelect --sms-options-bg="white" />
|
|
513
|
+
```
|
|
514
|
+
|
|
503
515
|
- `div.multiselect`
|
|
504
516
|
- `border: var(--sms-border, 1pt solid lightgray)`: Change this to e.g. to `1px solid red` to indicate this form field is in an invalid state.
|
|
505
517
|
- `border-radius: var(--sms-border-radius, 3pt)`
|
|
@@ -547,12 +559,11 @@ If you only want to make small adjustments, you can pass the following CSS varia
|
|
|
547
559
|
- `div.multiselect > ul.options > li.disabled`
|
|
548
560
|
- `background: var(--sms-li-disabled-bg, #f5f5f6)`: Background of disabled options in the dropdown list.
|
|
549
561
|
- `color: var(--sms-li-disabled-text, #b8b8b8)`: Text color of disabled option in the dropdown list.
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
```
|
|
562
|
+
- `::highlight(search-results)`: applies to search results in dropdown list that match the current search query if `highlightMatches=true`
|
|
563
|
+
- `color: var(--sms-highlight-color, orange)`
|
|
564
|
+
- `background: var(--sms-highlight-bg)`
|
|
565
|
+
- `text-decoration: var(--sms-highlight-text-decoration)`
|
|
566
|
+
- `text-decoration-color: var(--sms-highlight-text-decoration-color)`
|
|
556
567
|
|
|
557
568
|
### With CSS frameworks
|
|
558
569
|
|
|
@@ -611,7 +622,7 @@ Odd as it may seem, you get the most fine-grained control over the styling of ev
|
|
|
611
622
|
:global(div.multiselect > ul.selected > li button, button.remove-all) {
|
|
612
623
|
/* buttons to remove a single or all selected options at once */
|
|
613
624
|
}
|
|
614
|
-
:global(div.multiselect >
|
|
625
|
+
:global(div.multiselect > input[autocomplete]) {
|
|
615
626
|
/* input inside the top-level wrapper div */
|
|
616
627
|
}
|
|
617
628
|
:global(div.multiselect > ul.options) {
|