|
1 | 1 | <script lang="ts"> |
2 | | - import { tick, type Snippet } from 'svelte' |
3 | 2 | import { fade } from 'svelte/transition' |
4 | | -
|
5 | 3 | import Select from './MultiSelect.svelte' |
6 | 4 | import type { MultiSelectProps } from './props' |
7 | 5 | import type { ObjectOption } from './types' |
|
22 | 20 | fade_duration?: number // in ms |
23 | 21 | style?: string // for dialog |
24 | 22 | // for span in option snippet, has no effect when specifying a custom option snippet |
25 | | - span_style?: string |
26 | 23 | open?: boolean |
27 | 24 | dialog?: HTMLDialogElement | null |
28 | 25 | input?: HTMLInputElement | null |
29 | 26 | placeholder?: string |
30 | | - children?: Snippet |
31 | 27 | } |
32 | 28 | let { |
33 | 29 | actions, |
34 | 30 | triggers = [`k`], |
35 | 31 | close_keys = [`Escape`], |
36 | 32 | fade_duration = 200, |
37 | 33 | style = ``, |
38 | | - span_style = ``, |
39 | 34 | open = $bindable(false), |
40 | 35 | dialog = $bindable(null), |
41 | 36 | input = $bindable(null), |
42 | 37 | placeholder = `Filter actions...`, |
43 | | - children, |
44 | 38 | ...rest |
45 | 39 | }: Props = $props() |
46 | 40 |
|
| 41 | + $effect(() => { |
| 42 | + if (open && input) input?.focus() // focus input when palette is opened |
| 43 | + }) |
| 44 | +
|
47 | 45 | async function toggle(event: KeyboardEvent) { |
48 | 46 | if (triggers.includes(event.key) && event.metaKey && !open) { |
49 | | - // open on cmd+trigger |
50 | 47 | open = true |
51 | | - await tick() // wait for dialog to open and input to be mounted |
52 | | - input?.focus() |
53 | 48 | } else if (close_keys.includes(event.key) && open) { |
54 | 49 | open = false |
55 | 50 | } |
|
65 | 60 | option.action(option.label) |
66 | 61 | open = false |
67 | 62 | } |
68 | | -
|
69 | | - const children_render = $derived(children) |
70 | 63 | </script> |
71 | 64 |
|
72 | 65 | <svelte:window onkeydown={toggle} onclick={close_if_outside} /> |
|
80 | 73 | onadd={trigger_action_and_close} |
81 | 74 | onkeydown={toggle} |
82 | 75 | {...rest} |
83 | | - > |
84 | | - {#snippet children({ option })} |
85 | | - <!-- wait for https://github.com/sveltejs/svelte/pull/8304 --> |
86 | | - {#if children_render} |
87 | | - {@render children_render()} |
88 | | - {:else} |
89 | | - <span style={span_style}>{option.label}</span> |
90 | | - {/if} |
91 | | - {/snippet} |
92 | | - </Select> |
| 76 | + --sms-bg="var(--sms-options-bg)" |
| 77 | + --sms-width="min(20em, 90vw)" |
| 78 | + --sms-max-width="none" |
| 79 | + --sms-placeholder-color="lightgray" |
| 80 | + --sms-options-margin="1px 0" |
| 81 | + --sms-options-border-radius="0 0 1ex 1ex" |
| 82 | + /> |
93 | 83 | </dialog> |
94 | 84 | {/if} |
95 | 85 |
|
96 | 86 | <style> |
97 | | - /* TODO maybe remove global */ |
98 | | - :where(:global(dialog)) { |
| 87 | + :where(dialog) { |
99 | 88 | position: fixed; |
100 | 89 | top: 30%; |
101 | 90 | border: none; |
|
106 | 95 | z-index: 10; |
107 | 96 | font-size: 2.4ex; |
108 | 97 | } |
109 | | - dialog :global(div.multiselect) { |
110 | | - --sms-bg: var(--sms-options-bg); |
111 | | - --sms-width: min(20em, 90vw); |
112 | | - --sms-max-width: none; |
113 | | - --sms-placeholder-color: lightgray; |
114 | | - --sms-options-margin: 1px 0; |
115 | | - --sms-options-border-radius: 0 0 1ex 1ex; |
116 | | - } |
117 | 98 | </style> |
0 commit comments