@ibobbyts/svelte-ui-utils 0.4.4 → 0.4.6
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/README.md +21 -8
- package/dist/dialog/Dialog.svelte +142 -69
- package/dist/dialog/Dialog.svelte.d.ts.map +1 -1
- package/dist/dropdown/Dropdown.svelte +111 -6
- package/dist/dropdown/Dropdown.svelte.d.ts +7 -1
- package/dist/dropdown/Dropdown.svelte.d.ts.map +1 -1
- package/dist/dropdown/index.d.ts +1 -1
- package/dist/dropdown/index.d.ts.map +1 -1
- package/dist/dropdown/types.d.ts +3 -0
- package/dist/dropdown/types.d.ts.map +1 -1
- package/dist/style.css +53 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -357,18 +357,23 @@ light and dark defaults and expose `--suu-sortable-table-row-*-light` and
|
|
|
357
357
|
/>
|
|
358
358
|
```
|
|
359
359
|
|
|
360
|
-
Dialog components are controlled by the consuming app. `Dialog`
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
`
|
|
360
|
+
Dialog components are controlled by the consuming app. `Dialog` renders a
|
|
361
|
+
native `<dialog>` element and opens it with the browser top layer, so dialogs
|
|
362
|
+
nest: with several dialogs open at once, Escape, Tab, and backdrop clicks only
|
|
363
|
+
affect the topmost dialog and parent dialogs stay open. `Dialog` calls
|
|
364
|
+
`onClose` from the close button, backdrop, or Escape key when dismissible; it
|
|
365
|
+
does not mutate `open` internally. Set `dimBackdrop={false}` to disable
|
|
366
|
+
background darkening, `blurBackdrop={true}` to blur content behind the dialog,
|
|
367
|
+
and `showCountdown={true}` with `countdownDurationMs` to show a toast-style top
|
|
365
368
|
countdown bar. The optional `padding` prop accepts a CSS padding shorthand and
|
|
366
369
|
applies it consistently to the dialog header, body, and footer. The default
|
|
367
370
|
section-specific spacing is preserved when `padding` is omitted, and the same
|
|
368
371
|
prop is available on all dialog wrapper components. Set `restoreFocusSelector`
|
|
369
|
-
when the opening control may be replaced while the dialog is open; after
|
|
370
|
-
`Dialog` focuses the latest matching element and otherwise falls back
|
|
371
|
-
original connected element. `ConfirmDialog`
|
|
372
|
+
when the opening control may be replaced while the dialog is open; after
|
|
373
|
+
closing, `Dialog` focuses the latest matching element and otherwise falls back
|
|
374
|
+
to the original connected element. `ConfirmDialog` renders its `message` once
|
|
375
|
+
in the dialog body and forwards this prop, along with the dismiss, backdrop,
|
|
376
|
+
countdown, and focus-restore lifecycle props, to `Dialog`.
|
|
372
377
|
|
|
373
378
|
## Dropdown
|
|
374
379
|
|
|
@@ -411,6 +416,14 @@ use `menuAlign="right"` to align their right edges instead. `fitContent` sizes
|
|
|
411
416
|
the menu to its longest option while keeping the selected edge aligned.
|
|
412
417
|
`DataTable` uses this same component for its page-size picker.
|
|
413
418
|
|
|
419
|
+
Set `search={true}` with `loadOptions` to load remote options as the user
|
|
420
|
+
types. The default `input_style="dropdown"` keeps the search field inside the
|
|
421
|
+
expanded menu. Set `input_style="input"` to render a directly editable input;
|
|
422
|
+
results appear while it is focused and hide on blur. In input style, the
|
|
423
|
+
optional `getItemLabel` callback controls the displayed label while `value`
|
|
424
|
+
and `onChange` continue to represent submitted option values. The input style
|
|
425
|
+
is ignored when `search` is disabled.
|
|
426
|
+
|
|
414
427
|
For keyboard typeahead, an option may provide `searchText` separately from its
|
|
415
428
|
display `label`. Typeahead matches the beginning of `searchText` or `label`,
|
|
416
429
|
while the label remains the only text shown in the trigger and menu:
|
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
<svelte:options runes={false} />
|
|
2
2
|
|
|
3
|
+
<script context="module" lang="ts">
|
|
4
|
+
// Mount order mirrors the native top layer: the last registered element is
|
|
5
|
+
// the topmost dialog, and only it reacts to Escape, Tab, and backdrop clicks.
|
|
6
|
+
const openDialogElements: HTMLDialogElement[] = [];
|
|
7
|
+
|
|
8
|
+
const focusableSelector =
|
|
9
|
+
'a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])';
|
|
10
|
+
</script>
|
|
11
|
+
|
|
3
12
|
<script lang="ts">
|
|
4
13
|
import { tick } from 'svelte';
|
|
5
14
|
import type { DialogSize } from './types.js';
|
|
@@ -26,29 +35,26 @@
|
|
|
26
35
|
export let restoreFocusSelector: string | undefined = undefined;
|
|
27
36
|
export let onClose: (() => void) | undefined = undefined;
|
|
28
37
|
|
|
29
|
-
let dialogElement:
|
|
38
|
+
let dialogElement: HTMLDialogElement | undefined;
|
|
30
39
|
let titleId = `suu-dialog-title-${Math.random().toString(36).slice(2)}`;
|
|
31
40
|
let descriptionId = `suu-dialog-description-${Math.random().toString(36).slice(2)}`;
|
|
32
41
|
let wasOpen = false;
|
|
33
42
|
let previouslyFocusedElement: HTMLElement | null = null;
|
|
34
43
|
let restoreFocusSelectorAtOpen: string | undefined;
|
|
35
44
|
|
|
45
|
+
// The dialog element is the full-viewport top layer surface; the visual
|
|
46
|
+
// backdrop and panel stay on their existing inner elements.
|
|
47
|
+
const dialogResetStyle =
|
|
48
|
+
'width: 100%; height: 100%; max-width: none; max-height: none; margin: 0; padding: 0; border: none; background: transparent;';
|
|
49
|
+
|
|
36
50
|
$: resolvedLabelledBy = labelledBy ?? (title ? titleId : undefined);
|
|
37
51
|
$: resolvedDescribedBy =
|
|
38
52
|
describedBy ?? (description ? descriptionId : undefined);
|
|
39
53
|
$: backdropStyle =
|
|
40
54
|
`--suu-dialog-backdrop-opacity: ${backdropOpacity}; --suu-dialog-backdrop-blur: ${backdropBlur};`;
|
|
41
|
-
$: dialogStyle = padding ? `--suu-dialog-padding: ${padding};` : '';
|
|
42
55
|
$: countdownStyle = `--suu-dialog-countdown-duration: ${Math.max(0, countdownDurationMs)}ms;`;
|
|
43
56
|
$: if (open && !wasOpen) {
|
|
44
57
|
wasOpen = true;
|
|
45
|
-
void focusDialog();
|
|
46
|
-
} else if (!open && wasOpen) {
|
|
47
|
-
wasOpen = false;
|
|
48
|
-
restoreFocus();
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
async function focusDialog() {
|
|
52
58
|
if (typeof document !== 'undefined') {
|
|
53
59
|
previouslyFocusedElement =
|
|
54
60
|
document.activeElement instanceof HTMLElement
|
|
@@ -56,7 +62,37 @@
|
|
|
56
62
|
: null;
|
|
57
63
|
restoreFocusSelectorAtOpen = restoreFocusSelector;
|
|
58
64
|
}
|
|
65
|
+
void focusDialog();
|
|
66
|
+
} else if (!open && wasOpen) {
|
|
67
|
+
wasOpen = false;
|
|
68
|
+
void restoreFocus();
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function presentDialog(element: HTMLDialogElement) {
|
|
72
|
+
if (!openDialogElements.includes(element)) {
|
|
73
|
+
openDialogElements.push(element);
|
|
74
|
+
}
|
|
75
|
+
if (typeof element.showModal === 'function') {
|
|
76
|
+
if (!element.open) {
|
|
77
|
+
element.showModal();
|
|
78
|
+
}
|
|
79
|
+
} else if (!element.hasAttribute('open')) {
|
|
80
|
+
// jsdom does not implement showModal; the attribute keeps the element
|
|
81
|
+
// rendered as an open dialog there.
|
|
82
|
+
element.setAttribute('open', '');
|
|
83
|
+
}
|
|
59
84
|
|
|
85
|
+
return {
|
|
86
|
+
destroy() {
|
|
87
|
+
const index = openDialogElements.indexOf(element);
|
|
88
|
+
if (index !== -1) {
|
|
89
|
+
openDialogElements.splice(index, 1);
|
|
90
|
+
}
|
|
91
|
+
},
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
async function focusDialog() {
|
|
60
96
|
await tick();
|
|
61
97
|
dialogElement?.focus();
|
|
62
98
|
}
|
|
@@ -99,78 +135,115 @@
|
|
|
99
135
|
requestClose();
|
|
100
136
|
}
|
|
101
137
|
|
|
102
|
-
function
|
|
103
|
-
|
|
104
|
-
|
|
138
|
+
function handleCancel(event: Event) {
|
|
139
|
+
// Prevent the browser's own Escape close so the open prop stays the only
|
|
140
|
+
// source of truth; only the topmost dialog receives this event natively.
|
|
141
|
+
event.preventDefault();
|
|
142
|
+
if (closeOnEscape) {
|
|
105
143
|
requestClose();
|
|
106
144
|
}
|
|
107
145
|
}
|
|
108
|
-
</script>
|
|
109
146
|
|
|
110
|
-
|
|
147
|
+
function handleKeydown(event: KeyboardEvent) {
|
|
148
|
+
if (event.key !== 'Tab' || !dialogElement) {
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
if (openDialogElements[openDialogElements.length - 1] !== dialogElement) {
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
event.preventDefault();
|
|
156
|
+
const focusables = Array.from(
|
|
157
|
+
dialogElement.querySelectorAll<HTMLElement>(focusableSelector),
|
|
158
|
+
);
|
|
159
|
+
if (focusables.length === 0) {
|
|
160
|
+
dialogElement.focus();
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
const activeElement =
|
|
165
|
+
document.activeElement instanceof HTMLElement
|
|
166
|
+
? document.activeElement
|
|
167
|
+
: undefined;
|
|
168
|
+
const currentIndex = activeElement
|
|
169
|
+
? focusables.indexOf(activeElement)
|
|
170
|
+
: -1;
|
|
171
|
+
const nextIndex = event.shiftKey
|
|
172
|
+
? currentIndex <= 0
|
|
173
|
+
? focusables.length - 1
|
|
174
|
+
: currentIndex - 1
|
|
175
|
+
: currentIndex === -1 || currentIndex === focusables.length - 1
|
|
176
|
+
? 0
|
|
177
|
+
: currentIndex + 1;
|
|
178
|
+
focusables[nextIndex].focus();
|
|
179
|
+
}
|
|
180
|
+
</script>
|
|
111
181
|
|
|
112
182
|
{#if open}
|
|
113
|
-
<
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
183
|
+
<dialog
|
|
184
|
+
bind:this={dialogElement}
|
|
185
|
+
class="suu-dialog-root"
|
|
186
|
+
style={dialogResetStyle}
|
|
187
|
+
aria-labelledby={resolvedLabelledBy}
|
|
188
|
+
aria-describedby={resolvedDescribedBy}
|
|
189
|
+
tabindex="-1"
|
|
190
|
+
use:presentDialog
|
|
191
|
+
on:cancel={handleCancel}
|
|
192
|
+
on:keydown={handleKeydown}
|
|
120
193
|
>
|
|
121
194
|
<div
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
aria-describedby={resolvedDescribedBy}
|
|
129
|
-
tabindex="-1"
|
|
195
|
+
class="suu-dialog-backdrop"
|
|
196
|
+
data-dimmed={dimBackdrop ? 'true' : 'false'}
|
|
197
|
+
data-blurred={blurBackdrop ? 'true' : 'false'}
|
|
198
|
+
style={backdropStyle}
|
|
199
|
+
role="presentation"
|
|
200
|
+
on:mousedown={handleBackdropMouseDown}
|
|
130
201
|
>
|
|
131
|
-
{
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
<
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
{
|
|
147
|
-
|
|
202
|
+
<div class={`suu-dialog suu-dialog--${size}`} style:--suu-dialog-padding={padding}>
|
|
203
|
+
{#if showCountdown && countdownDurationMs > 0}
|
|
204
|
+
<div
|
|
205
|
+
class="suu-dialog__countdown"
|
|
206
|
+
style={countdownStyle}
|
|
207
|
+
role="timer"
|
|
208
|
+
aria-label={countdownLabel}
|
|
209
|
+
></div>
|
|
210
|
+
{/if}
|
|
211
|
+
<header class="suu-dialog__header">
|
|
212
|
+
<div class="suu-dialog__heading">
|
|
213
|
+
{#if title}
|
|
214
|
+
<h2 class="suu-dialog__title" id={titleId}>{title}</h2>
|
|
215
|
+
{/if}
|
|
216
|
+
{#if description}
|
|
217
|
+
<p class="suu-dialog__description" id={descriptionId}>
|
|
218
|
+
{description}
|
|
219
|
+
</p>
|
|
220
|
+
{/if}
|
|
221
|
+
</div>
|
|
222
|
+
{#if showCloseButton && dismissible}
|
|
223
|
+
<button
|
|
224
|
+
type="button"
|
|
225
|
+
class="suu-dialog__close"
|
|
226
|
+
aria-label={closeLabel}
|
|
227
|
+
title={closeLabel}
|
|
228
|
+
on:click={requestClose}
|
|
229
|
+
>
|
|
230
|
+
<svg viewBox="0 0 20 20" aria-hidden="true">
|
|
231
|
+
<path d="m6 6 8 8M14 6l-8 8"></path>
|
|
232
|
+
</svg>
|
|
233
|
+
</button>
|
|
148
234
|
{/if}
|
|
235
|
+
</header>
|
|
236
|
+
|
|
237
|
+
<div class="suu-dialog__body">
|
|
238
|
+
<slot />
|
|
149
239
|
</div>
|
|
150
|
-
{#if showCloseButton && dismissible}
|
|
151
|
-
<button
|
|
152
|
-
type="button"
|
|
153
|
-
class="suu-dialog__close"
|
|
154
|
-
aria-label={closeLabel}
|
|
155
|
-
title={closeLabel}
|
|
156
|
-
on:click={requestClose}
|
|
157
|
-
>
|
|
158
|
-
<svg viewBox="0 0 20 20" aria-hidden="true">
|
|
159
|
-
<path d="m6 6 8 8M14 6l-8 8"></path>
|
|
160
|
-
</svg>
|
|
161
|
-
</button>
|
|
162
|
-
{/if}
|
|
163
|
-
</header>
|
|
164
240
|
|
|
165
|
-
|
|
166
|
-
|
|
241
|
+
{#if $$slots.footer}
|
|
242
|
+
<footer class="suu-dialog__footer">
|
|
243
|
+
<slot name="footer" />
|
|
244
|
+
</footer>
|
|
245
|
+
{/if}
|
|
167
246
|
</div>
|
|
168
|
-
|
|
169
|
-
{#if $$slots.footer}
|
|
170
|
-
<footer class="suu-dialog__footer">
|
|
171
|
-
<slot name="footer" />
|
|
172
|
-
</footer>
|
|
173
|
-
{/if}
|
|
174
247
|
</div>
|
|
175
|
-
</
|
|
248
|
+
</dialog>
|
|
176
249
|
{/if}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Dialog.svelte.d.ts","sourceRoot":"","sources":["../../src/lib/dialog/Dialog.svelte.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"Dialog.svelte.d.ts","sourceRoot":"","sources":["../../src/lib/dialog/Dialog.svelte.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AA2N7C,UAAU,kCAAkC,CAAC,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,GAAG,EAAE,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,GAAG,EAAE,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,GAAG,EAAE,OAAO,GAAG,EAAE,EAAE,QAAQ,GAAG,MAAM;IACpM,KAAK,OAAO,EAAE,OAAO,QAAQ,EAAE,2BAA2B,CAAC,KAAK,CAAC,GAAG,OAAO,QAAQ,EAAE,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,GAAG;QAAE,UAAU,CAAC,EAAE,QAAQ,CAAA;KAAE,GAAG,OAAO,CAAC;IACjK,CAAC,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,GAAG;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,KAAK,CAAA;KAAC,GAAG,OAAO,GAAG;QAAE,IAAI,CAAC,EAAE,GAAG,CAAC;QAAC,GAAG,CAAC,EAAE,GAAG,CAAA;KAAE,CAAC;IAC9G,YAAY,CAAC,EAAE,QAAQ,CAAC;CAC3B;AACD,KAAK,gCAAgC,CAAC,KAAK,EAAE,KAAK,IAAI,KAAK,GACvD,CAAC,KAAK,SAAS;IAAE,OAAO,EAAE,GAAG,CAAA;CAAE,GACzB,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,GACnC,GAAG,GACH;IAAE,QAAQ,CAAC,EAAE,GAAG,CAAA;CAAE,GAClB,EAAE,CAAC,CAAC;AAId,QAAA,MAAM,MAAM;;;;;WAfksB,UAAU;cAAY,MAAM,GAAG,SAAS;;;;;;;sBAAsP,MAAM,GAAG,MAAM;;;;;iBAAmL,MAAM,GAAG,SAAS;kBAAgB,MAAM,GAAG,SAAS;2BAAyB,MAAM,GAAG,SAAS;cAAY,CAAC,MAAM,IAAI,CAAC,GAAG,SAAS;;;;;;;;;cAehtC,CAAC;AAChF,KAAK,MAAM,GAAG,YAAY,CAAC,OAAO,MAAM,CAAC,CAAC;AAC5C,eAAe,MAAM,CAAC"}
|
|
@@ -9,6 +9,8 @@
|
|
|
9
9
|
import { getUiMessages, type UiLanguage } from '../i18n.js';
|
|
10
10
|
import type {
|
|
11
11
|
DropdownChangeHandler,
|
|
12
|
+
DropdownInputStyle,
|
|
13
|
+
DropdownItemLabelGetter,
|
|
12
14
|
DropdownLoadOptions,
|
|
13
15
|
DropdownLoadOptionsResult,
|
|
14
16
|
DropdownLoadStatus,
|
|
@@ -19,6 +21,7 @@
|
|
|
19
21
|
DropdownOptionGroup,
|
|
20
22
|
DropdownPlacement,
|
|
21
23
|
DropdownSelectionChangeHandler,
|
|
24
|
+
DropdownSearchChangeHandler,
|
|
22
25
|
DropdownSelection,
|
|
23
26
|
DropdownTriggerClickHandler,
|
|
24
27
|
DropdownValue
|
|
@@ -33,10 +36,13 @@
|
|
|
33
36
|
export let selectedOptions: DropdownOption[] = [];
|
|
34
37
|
export let groupsCollapsedByDefault: 'true' | 'false' | 'auto' = 'false';
|
|
35
38
|
export let search = false;
|
|
39
|
+
export let input_style: DropdownInputStyle = 'dropdown';
|
|
40
|
+
export let getItemLabel: DropdownItemLabelGetter = (option) => option.label;
|
|
36
41
|
export let loadOptions: DropdownLoadOptions | undefined = undefined;
|
|
37
42
|
export let searchDebounceMs = 300;
|
|
38
43
|
export let searchLimit = 10;
|
|
39
44
|
export let searchPlaceholder: string | undefined = undefined;
|
|
45
|
+
export let placeholder: string | undefined = undefined;
|
|
40
46
|
export let language: UiLanguage = 'en_us';
|
|
41
47
|
export let loadingText: string | undefined = undefined;
|
|
42
48
|
export let noResultsText: string | undefined = undefined;
|
|
@@ -55,6 +61,7 @@
|
|
|
55
61
|
export let className: string | undefined = undefined;
|
|
56
62
|
export let portal = false;
|
|
57
63
|
export let onChange: DropdownSelectionChangeHandler | undefined = undefined;
|
|
64
|
+
export let onSearchChange: DropdownSearchChangeHandler | undefined = undefined;
|
|
58
65
|
export let onTriggerClick: DropdownTriggerClickHandler | undefined = undefined;
|
|
59
66
|
|
|
60
67
|
const viewportMargin = 20;
|
|
@@ -82,6 +89,10 @@
|
|
|
82
89
|
// from a search response; once true, the user's manual toggles own the set.
|
|
83
90
|
let searchGroupsInitialized = false;
|
|
84
91
|
let searchQuery = '';
|
|
92
|
+
// 在受控 value 尚未响应 onChange 时保留用户当前输入,避免
|
|
93
|
+
// selectedText 的旧值在同一轮更新中覆盖输入框内容。
|
|
94
|
+
let inputDraft: string | undefined;
|
|
95
|
+
let preserveInputDraftOnClose = false;
|
|
85
96
|
let searchStatus: DropdownLoadStatus = 'idle';
|
|
86
97
|
let searchOptions: DropdownOption[] = [];
|
|
87
98
|
let searchOptionGroups: DropdownOptionGroup[] | undefined = undefined;
|
|
@@ -115,7 +126,11 @@
|
|
|
115
126
|
$: selectedOption = Array.isArray(value) ? undefined : resolvedOptions.find((option) => option.value === value);
|
|
116
127
|
$: selectedText = multiselect
|
|
117
128
|
? selectedLabelTexts(selectedValues).join(', ')
|
|
118
|
-
:
|
|
129
|
+
: displayLabelForValue(Array.isArray(value) ? '' : value);
|
|
130
|
+
$: inputMode = search && input_style === 'input';
|
|
131
|
+
$: inputDisplayValue = inputMode
|
|
132
|
+
? (inputDraft ?? (searchQuery || (multiselect ? '' : selectedText)))
|
|
133
|
+
: '';
|
|
119
134
|
$: if (!open) {
|
|
120
135
|
activeValue = initialActiveValue();
|
|
121
136
|
}
|
|
@@ -185,6 +200,12 @@
|
|
|
185
200
|
return option?.label ?? knownLabels.get(nextValue) ?? String(nextValue);
|
|
186
201
|
}
|
|
187
202
|
|
|
203
|
+
function displayLabelForValue(nextValue: DropdownValue): string {
|
|
204
|
+
const option = resolvedOptions.find((candidate) => candidate.value === nextValue) ??
|
|
205
|
+
selectedOptions.find((candidate) => candidate.value === nextValue);
|
|
206
|
+
return option ? getItemLabel(option) : labelForValue(nextValue);
|
|
207
|
+
}
|
|
208
|
+
|
|
188
209
|
// Multiselect trigger text only lists values whose label is known; values
|
|
189
210
|
// without one never render a raw fallback string into the trigger.
|
|
190
211
|
function selectedLabelTexts(nextValues: DropdownMultiValue): string[] {
|
|
@@ -194,7 +215,9 @@
|
|
|
194
215
|
resolvedOptions.find((candidate) => candidate.value === nextValue)?.label ??
|
|
195
216
|
knownLabels.get(nextValue);
|
|
196
217
|
if (label !== undefined) {
|
|
197
|
-
|
|
218
|
+
const option = resolvedOptions.find((candidate) => candidate.value === nextValue) ??
|
|
219
|
+
selectedOptions.find((candidate) => candidate.value === nextValue);
|
|
220
|
+
texts.push(option ? getItemLabel(option) : label);
|
|
198
221
|
}
|
|
199
222
|
}
|
|
200
223
|
return texts;
|
|
@@ -332,6 +355,10 @@
|
|
|
332
355
|
return;
|
|
333
356
|
}
|
|
334
357
|
|
|
358
|
+
if (inputMode) {
|
|
359
|
+
inputDraft = getItemLabel(option);
|
|
360
|
+
preserveInputDraftOnClose = true;
|
|
361
|
+
}
|
|
335
362
|
open = false;
|
|
336
363
|
clearTypeaheadBuffer();
|
|
337
364
|
void (onChange as DropdownChangeHandler | undefined)?.(option.value);
|
|
@@ -452,6 +479,11 @@
|
|
|
452
479
|
clearSearchTimer();
|
|
453
480
|
abortSearchController();
|
|
454
481
|
searchQuery = '';
|
|
482
|
+
if (preserveInputDraftOnClose) {
|
|
483
|
+
preserveInputDraftOnClose = false;
|
|
484
|
+
} else {
|
|
485
|
+
inputDraft = undefined;
|
|
486
|
+
}
|
|
455
487
|
searchOptions = [];
|
|
456
488
|
searchOptionGroups = undefined;
|
|
457
489
|
searchStatus = 'idle';
|
|
@@ -459,6 +491,7 @@
|
|
|
459
491
|
|
|
460
492
|
function beginSearchOnOpen() {
|
|
461
493
|
searchQuery = '';
|
|
494
|
+
inputDraft = undefined;
|
|
462
495
|
searchOptions = [];
|
|
463
496
|
searchOptionGroups = undefined;
|
|
464
497
|
collapsedGroupIndexes = new Set();
|
|
@@ -482,7 +515,7 @@
|
|
|
482
515
|
}
|
|
483
516
|
open = true;
|
|
484
517
|
activeValue = initialActiveValue();
|
|
485
|
-
if (search) {
|
|
518
|
+
if (search && !inputMode) {
|
|
486
519
|
void tick().then(() => {
|
|
487
520
|
searchInputElement?.focus();
|
|
488
521
|
});
|
|
@@ -573,6 +606,7 @@
|
|
|
573
606
|
openMenu();
|
|
574
607
|
}
|
|
575
608
|
searchQuery = wasOpen ? `${searchQuery}${normalizeTypeaheadKey(event.key)}` : normalizeTypeaheadKey(event.key);
|
|
609
|
+
void onSearchChange?.(searchQuery);
|
|
576
610
|
scheduleSearch(searchQuery);
|
|
577
611
|
return;
|
|
578
612
|
}
|
|
@@ -591,10 +625,31 @@
|
|
|
591
625
|
}
|
|
592
626
|
|
|
593
627
|
function handleSearchInput(event: Event) {
|
|
594
|
-
|
|
628
|
+
const nextQuery = (event.currentTarget as HTMLInputElement).value;
|
|
629
|
+
inputDraft = nextQuery;
|
|
630
|
+
if (inputMode && !multiselect && value !== '' && nextQuery !== selectedText) {
|
|
631
|
+
void (onChange as DropdownChangeHandler | undefined)?.('');
|
|
632
|
+
}
|
|
633
|
+
searchQuery = nextQuery;
|
|
634
|
+
if (inputMode) {
|
|
635
|
+
if (nextQuery.trim()) {
|
|
636
|
+
if (!open) {
|
|
637
|
+
updateResolvedPlacement();
|
|
638
|
+
open = true;
|
|
639
|
+
activeValue = initialActiveValue();
|
|
640
|
+
}
|
|
641
|
+
} else {
|
|
642
|
+
open = false;
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
void onSearchChange?.(searchQuery);
|
|
595
646
|
scheduleSearch(searchQuery);
|
|
596
647
|
}
|
|
597
648
|
|
|
649
|
+
function handleInputFocus() {
|
|
650
|
+
// 输入模式下聚焦只准备输入;用户输入有效搜索词后才展开结果。
|
|
651
|
+
}
|
|
652
|
+
|
|
598
653
|
function handleSearchKeydown(event: KeyboardEvent) {
|
|
599
654
|
if (event.key === 'Escape') {
|
|
600
655
|
event.preventDefault();
|
|
@@ -716,11 +771,19 @@
|
|
|
716
771
|
}
|
|
717
772
|
|
|
718
773
|
function portalMenu(node: HTMLDivElement, enabled: boolean) {
|
|
774
|
+
let resizeObserver: ResizeObserver | undefined;
|
|
719
775
|
if (enabled && typeof document !== 'undefined') {
|
|
720
776
|
document.body.appendChild(node);
|
|
777
|
+
if (typeof ResizeObserver !== 'undefined') {
|
|
778
|
+
resizeObserver = new ResizeObserver(() => {
|
|
779
|
+
if (open) void updateViewportPanelMaxHeight();
|
|
780
|
+
});
|
|
781
|
+
resizeObserver.observe(node);
|
|
782
|
+
}
|
|
721
783
|
}
|
|
722
784
|
return {
|
|
723
785
|
destroy() {
|
|
786
|
+
resizeObserver?.disconnect();
|
|
724
787
|
if (node.parentNode) {
|
|
725
788
|
node.parentNode.removeChild(node);
|
|
726
789
|
}
|
|
@@ -806,6 +869,47 @@
|
|
|
806
869
|
style:max-width={maxWidth}
|
|
807
870
|
on:focusout={handleFocusout}
|
|
808
871
|
>
|
|
872
|
+
{#if inputMode}
|
|
873
|
+
{#if multiselect && selectedValues.length > 0}
|
|
874
|
+
<div class="suu-dropdown__selected-items">
|
|
875
|
+
{#each selectedValues as selectedValue}
|
|
876
|
+
{@const selectedOption = resolvedOptions.find((option) => option.value === selectedValue) ?? selectedOptions.find((option) => option.value === selectedValue)}
|
|
877
|
+
{#if selectedOption}
|
|
878
|
+
<span class="suu-dropdown__selected-item">
|
|
879
|
+
<span>{getItemLabel(selectedOption)}</span>
|
|
880
|
+
<button
|
|
881
|
+
type="button"
|
|
882
|
+
class="suu-dropdown__selected-remove"
|
|
883
|
+
aria-label={`Remove ${getItemLabel(selectedOption)}`}
|
|
884
|
+
on:mousedown|preventDefault
|
|
885
|
+
on:click={() => selectOption(selectedOption)}
|
|
886
|
+
>×</button>
|
|
887
|
+
</span>
|
|
888
|
+
{/if}
|
|
889
|
+
{/each}
|
|
890
|
+
</div>
|
|
891
|
+
{/if}
|
|
892
|
+
<div class="suu-dropdown__input-field">
|
|
893
|
+
<input
|
|
894
|
+
bind:this={searchInputElement}
|
|
895
|
+
{id}
|
|
896
|
+
class="suu-dropdown__input"
|
|
897
|
+
type="text"
|
|
898
|
+
value={inputDisplayValue}
|
|
899
|
+
placeholder={searchPlaceholder ?? placeholder ?? ''}
|
|
900
|
+
aria-label={ariaLabel}
|
|
901
|
+
autocomplete="off"
|
|
902
|
+
role="combobox"
|
|
903
|
+
aria-expanded={open}
|
|
904
|
+
aria-autocomplete="list"
|
|
905
|
+
aria-controls={resolvedListboxId}
|
|
906
|
+
{disabled}
|
|
907
|
+
on:focus={handleInputFocus}
|
|
908
|
+
on:input={handleSearchInput}
|
|
909
|
+
on:keydown={handleSearchKeydown}
|
|
910
|
+
/>
|
|
911
|
+
</div>
|
|
912
|
+
{:else}
|
|
809
913
|
<button
|
|
810
914
|
bind:this={buttonElement}
|
|
811
915
|
{id}
|
|
@@ -819,9 +923,10 @@
|
|
|
819
923
|
on:click={handleTriggerClick}
|
|
820
924
|
on:keydown={handleKeydown}
|
|
821
925
|
>
|
|
822
|
-
<span class="suu-dropdown__label">{selectedText}</span>
|
|
926
|
+
<span class="suu-dropdown__label">{selectedText || placeholder || ''}</span>
|
|
823
927
|
<span class="suu-dropdown__chevron" aria-hidden="true"></span>
|
|
824
928
|
</button>
|
|
929
|
+
{/if}
|
|
825
930
|
|
|
826
931
|
{#if name !== undefined && !multiselect}
|
|
827
932
|
<input
|
|
@@ -853,7 +958,7 @@
|
|
|
853
958
|
style:--suu-dropdown-menu-width={portalMenuWidth}
|
|
854
959
|
style:--suu-dropdown-panel-max-height={viewportPanelMaxHeight}
|
|
855
960
|
>
|
|
856
|
-
{#if search}
|
|
961
|
+
{#if search && !inputMode}
|
|
857
962
|
<div class="suu-dropdown__search">
|
|
858
963
|
<svg class="suu-dropdown__search-icon" viewBox="0 0 24 24" aria-hidden="true">
|
|
859
964
|
<circle cx="11" cy="11" r="7"></circle>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type UiLanguage } from '../i18n.js';
|
|
2
|
-
import type { DropdownLoadOptions, DropdownMenuAlign, DropdownOption, DropdownOptionGroup, DropdownPlacement, DropdownSelectionChangeHandler, DropdownSelection, DropdownTriggerClickHandler } from './types.js';
|
|
2
|
+
import type { DropdownInputStyle, DropdownItemLabelGetter, DropdownLoadOptions, DropdownMenuAlign, DropdownOption, DropdownOptionGroup, DropdownPlacement, DropdownSelectionChangeHandler, DropdownSearchChangeHandler, DropdownSelection, DropdownTriggerClickHandler } from './types.js';
|
|
3
3
|
interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
|
|
4
4
|
new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
|
|
5
5
|
$$bindings?: Bindings;
|
|
@@ -22,10 +22,13 @@ declare const Dropdown: $$__sveltets_2_IsomorphicComponent<{
|
|
|
22
22
|
/** Labels for controlled values that are not present in the current search result. */ selectedOptions?: DropdownOption[];
|
|
23
23
|
groupsCollapsedByDefault?: "true" | "false" | "auto";
|
|
24
24
|
search?: boolean;
|
|
25
|
+
input_style?: DropdownInputStyle;
|
|
26
|
+
getItemLabel?: DropdownItemLabelGetter;
|
|
25
27
|
loadOptions?: DropdownLoadOptions | undefined;
|
|
26
28
|
searchDebounceMs?: number;
|
|
27
29
|
searchLimit?: number;
|
|
28
30
|
searchPlaceholder?: string | undefined;
|
|
31
|
+
placeholder?: string | undefined;
|
|
29
32
|
language?: UiLanguage;
|
|
30
33
|
loadingText?: string | undefined;
|
|
31
34
|
noResultsText?: string | undefined;
|
|
@@ -44,8 +47,11 @@ declare const Dropdown: $$__sveltets_2_IsomorphicComponent<{
|
|
|
44
47
|
className?: string | undefined;
|
|
45
48
|
portal?: boolean;
|
|
46
49
|
onChange?: DropdownSelectionChangeHandler | undefined;
|
|
50
|
+
onSearchChange?: DropdownSearchChangeHandler | undefined;
|
|
47
51
|
onTriggerClick?: DropdownTriggerClickHandler | undefined;
|
|
48
52
|
}, {
|
|
53
|
+
mousedown: MouseEvent;
|
|
54
|
+
} & {
|
|
49
55
|
[evt: string]: CustomEvent<any>;
|
|
50
56
|
}, {}, {}, string>;
|
|
51
57
|
type Dropdown = InstanceType<typeof Dropdown>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Dropdown.svelte.d.ts","sourceRoot":"","sources":["../../src/lib/dropdown/Dropdown.svelte.ts"],"names":[],"mappings":"AAOA,OAAO,EAAiB,KAAK,UAAU,EAAE,MAAM,YAAY,CAAC;AAC5D,OAAO,KAAK,EAER,mBAAmB,EAGnB,iBAAiB,EAGjB,cAAc,EACd,mBAAmB,EACnB,iBAAiB,EACjB,8BAA8B,EAC9B,iBAAiB,EACjB,2BAA2B,EAE5B,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"Dropdown.svelte.d.ts","sourceRoot":"","sources":["../../src/lib/dropdown/Dropdown.svelte.ts"],"names":[],"mappings":"AAOA,OAAO,EAAiB,KAAK,UAAU,EAAE,MAAM,YAAY,CAAC;AAC5D,OAAO,KAAK,EAER,kBAAkB,EAClB,uBAAuB,EACvB,mBAAmB,EAGnB,iBAAiB,EAGjB,cAAc,EACd,mBAAmB,EACnB,iBAAiB,EACjB,8BAA8B,EAC9B,2BAA2B,EAC3B,iBAAiB,EACjB,2BAA2B,EAE5B,MAAM,YAAY,CAAC;AA66BtB,UAAU,kCAAkC,CAAC,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,GAAG,EAAE,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,GAAG,EAAE,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,GAAG,EAAE,OAAO,GAAG,EAAE,EAAE,QAAQ,GAAG,MAAM;IACpM,KAAK,OAAO,EAAE,OAAO,QAAQ,EAAE,2BAA2B,CAAC,KAAK,CAAC,GAAG,OAAO,QAAQ,EAAE,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,GAAG;QAAE,UAAU,CAAC,EAAE,QAAQ,CAAA;KAAE,GAAG,OAAO,CAAC;IACjK,CAAC,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,GAAG;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,KAAK,CAAA;KAAC,GAAG,OAAO,GAAG;QAAE,IAAI,CAAC,EAAE,GAAG,CAAC;QAAC,GAAG,CAAC,EAAE,GAAG,CAAA;KAAE,CAAC;IAC9G,YAAY,CAAC,EAAE,QAAQ,CAAC;CAC3B;AAKD,QAAA,MAAM,QAAQ;SAX03B,MAAM,GAAG,SAAS;YAAU,iBAAiB;;cAA8C,cAAc,EAAE;mBAAiB,mBAAmB,EAAE,GAAG,SAAS;IACriC,sFAAsF,mBAAkB,cAAc,EAAE;+BAA6B,MAAM,GAAG,OAAO,GAAG,MAAM;;kBAAwC,kBAAkB;mBAAiB,uBAAuB;kBAAgB,mBAAmB,GAAG,SAAS;;;wBAAoG,MAAM,GAAG,SAAS;kBAAgB,MAAM,GAAG,SAAS;eAAa,UAAU;kBAAgB,MAAM,GAAG,SAAS;oBAAkB,MAAM,GAAG,SAAS;gBAAc,MAAM,GAAG,SAAS;gBAAc,MAAM,GAAG,SAAS;gBAAc,iBAAiB;gBAAc,iBAAiB;;;;WAAuG,MAAM,GAAG,SAAS;;YAAsC,MAAM,GAAG,SAAS;eAAa,MAAM,GAAG,SAAS;eAAa,MAAM,GAAG,SAAS;gBAAc,MAAM,GAAG,SAAS;;eAAqC,8BAA8B,GAAG,SAAS;qBAAmB,2BAA2B,GAAG,SAAS;qBAAmB,2BAA2B,GAAG,SAAS;;;;;kBAUviC,CAAC;AAC5E,KAAK,QAAQ,GAAG,YAAY,CAAC,OAAO,QAAQ,CAAC,CAAC;AAChD,eAAe,QAAQ,CAAC"}
|
package/dist/dropdown/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export { default as Dropdown } from './Dropdown.svelte';
|
|
2
2
|
export { default as DropdownMultiSelect } from './DropdownMultiSelect.svelte';
|
|
3
|
-
export type { DropdownChangeHandler, DropdownLoadContext, DropdownLoadOptions, DropdownLoadOptionsResult, DropdownLoadStatus, DropdownMenuAlign, DropdownMultiChangeHandler, DropdownMultiValue, DropdownOption, DropdownOptionGroup, DropdownPlacement, DropdownSelectionChangeHandler, DropdownSelection, DropdownTriggerClickHandler, DropdownValue } from './types.js';
|
|
3
|
+
export type { DropdownChangeHandler, DropdownInputStyle, DropdownItemLabelGetter, DropdownLoadContext, DropdownLoadOptions, DropdownLoadOptionsResult, DropdownLoadStatus, DropdownMenuAlign, DropdownMultiChangeHandler, DropdownMultiValue, DropdownOption, DropdownOptionGroup, DropdownPlacement, DropdownSelectionChangeHandler, DropdownSearchChangeHandler, DropdownSelection, DropdownTriggerClickHandler, DropdownValue } from './types.js';
|
|
4
4
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/lib/dropdown/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,OAAO,IAAI,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AAC9E,YAAY,EACV,qBAAqB,EACrB,mBAAmB,EACnB,mBAAmB,EACnB,yBAAyB,EACzB,kBAAkB,EAClB,iBAAiB,EACjB,0BAA0B,EAC1B,kBAAkB,EAClB,cAAc,EACd,mBAAmB,EACnB,iBAAiB,EACjB,8BAA8B,EAC9B,iBAAiB,EACjB,2BAA2B,EAC3B,aAAa,EACd,MAAM,YAAY,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/lib/dropdown/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,OAAO,IAAI,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AAC9E,YAAY,EACV,qBAAqB,EACrB,kBAAkB,EAClB,uBAAuB,EACvB,mBAAmB,EACnB,mBAAmB,EACnB,yBAAyB,EACzB,kBAAkB,EAClB,iBAAiB,EACjB,0BAA0B,EAC1B,kBAAkB,EAClB,cAAc,EACd,mBAAmB,EACnB,iBAAiB,EACjB,8BAA8B,EAC9B,2BAA2B,EAC3B,iBAAiB,EACjB,2BAA2B,EAC3B,aAAa,EACd,MAAM,YAAY,CAAC"}
|
package/dist/dropdown/types.d.ts
CHANGED
|
@@ -25,6 +25,9 @@ export type DropdownSelectionChangeHandler = {
|
|
|
25
25
|
bivarianceHack(value: DropdownSelection): void | Promise<void>;
|
|
26
26
|
}['bivarianceHack'];
|
|
27
27
|
export type DropdownTriggerClickHandler = (event: MouseEvent) => void;
|
|
28
|
+
export type DropdownSearchChangeHandler = (query: string) => void | Promise<void>;
|
|
29
|
+
export type DropdownInputStyle = 'dropdown' | 'input';
|
|
30
|
+
export type DropdownItemLabelGetter = (option: DropdownOption) => string;
|
|
28
31
|
export type DropdownLoadStatus = 'idle' | 'loading' | 'success' | 'error';
|
|
29
32
|
export interface DropdownLoadContext {
|
|
30
33
|
limit: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/lib/dropdown/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC;AAEnC,MAAM,MAAM,kBAAkB,GAAG,MAAM,EAAE,CAAC;AAE1C,MAAM,MAAM,iBAAiB,GAAG,aAAa,GAAG,kBAAkB,CAAC;AAEnE,MAAM,MAAM,iBAAiB,GAAG,MAAM,GAAG,IAAI,GAAG,MAAM,CAAC;AAEvD,MAAM,MAAM,iBAAiB,GAAG,MAAM,GAAG,OAAO,CAAC;AAEjD,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,mGAAmG;IACnG,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,aAAa,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,mBAAmB;IAClC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,cAAc,EAAE,CAAC;CAC3B;AAED,MAAM,MAAM,qBAAqB,GAAG,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAEnF,MAAM,MAAM,0BAA0B,GAAG,CAAC,KAAK,EAAE,kBAAkB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAE7F,MAAM,MAAM,8BAA8B,GAAG;IAC5C,cAAc,CAAC,KAAK,EAAE,iBAAiB,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC/D,CAAC,gBAAgB,CAAC,CAAC;AAEpB,MAAM,MAAM,2BAA2B,GAAG,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAC;AAEtE,MAAM,MAAM,kBAAkB,GAAG,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,CAAC;AAE1E,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,WAAW,CAAC;CACrB;AAED,MAAM,WAAW,yBAAyB;IACxC;;;OAGG;IACH,OAAO,CAAC,EAAE,cAAc,EAAE,CAAC;IAC3B,YAAY,CAAC,EAAE,mBAAmB,EAAE,CAAC;CACtC;AAED,MAAM,MAAM,mBAAmB,GAAG,CAChC,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,mBAAmB,KACzB,OAAO,CAAC,yBAAyB,CAAC,GAAG,yBAAyB,CAAC"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/lib/dropdown/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC;AAEnC,MAAM,MAAM,kBAAkB,GAAG,MAAM,EAAE,CAAC;AAE1C,MAAM,MAAM,iBAAiB,GAAG,aAAa,GAAG,kBAAkB,CAAC;AAEnE,MAAM,MAAM,iBAAiB,GAAG,MAAM,GAAG,IAAI,GAAG,MAAM,CAAC;AAEvD,MAAM,MAAM,iBAAiB,GAAG,MAAM,GAAG,OAAO,CAAC;AAEjD,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,mGAAmG;IACnG,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,aAAa,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,mBAAmB;IAClC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,cAAc,EAAE,CAAC;CAC3B;AAED,MAAM,MAAM,qBAAqB,GAAG,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAEnF,MAAM,MAAM,0BAA0B,GAAG,CAAC,KAAK,EAAE,kBAAkB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAE7F,MAAM,MAAM,8BAA8B,GAAG;IAC5C,cAAc,CAAC,KAAK,EAAE,iBAAiB,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC/D,CAAC,gBAAgB,CAAC,CAAC;AAEpB,MAAM,MAAM,2BAA2B,GAAG,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAC;AAEtE,MAAM,MAAM,2BAA2B,GAAG,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAElF,MAAM,MAAM,kBAAkB,GAAG,UAAU,GAAG,OAAO,CAAC;AACtD,MAAM,MAAM,uBAAuB,GAAG,CAAC,MAAM,EAAE,cAAc,KAAK,MAAM,CAAC;AAEzE,MAAM,MAAM,kBAAkB,GAAG,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,CAAC;AAE1E,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,WAAW,CAAC;CACrB;AAED,MAAM,WAAW,yBAAyB;IACxC;;;OAGG;IACH,OAAO,CAAC,EAAE,cAAc,EAAE,CAAC;IAC3B,YAAY,CAAC,EAAE,mBAAmB,EAAE,CAAC;CACtC;AAED,MAAM,MAAM,mBAAmB,GAAG,CAChC,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,mBAAmB,KACzB,OAAO,CAAC,yBAAyB,CAAC,GAAG,yBAAyB,CAAC"}
|
package/dist/style.css
CHANGED
|
@@ -1209,6 +1209,59 @@
|
|
|
1209
1209
|
opacity: 0.6;
|
|
1210
1210
|
}
|
|
1211
1211
|
|
|
1212
|
+
.suu-dropdown__input-field {
|
|
1213
|
+
position: relative;
|
|
1214
|
+
width: 100%;
|
|
1215
|
+
}
|
|
1216
|
+
|
|
1217
|
+
.suu-dropdown__input {
|
|
1218
|
+
width: 100%;
|
|
1219
|
+
min-height: 42px;
|
|
1220
|
+
box-sizing: border-box;
|
|
1221
|
+
border: 1px solid var(--suu-color-border);
|
|
1222
|
+
border-radius: var(--suu-radius);
|
|
1223
|
+
background: var(--suu-color-bg);
|
|
1224
|
+
color: var(--suu-color-text);
|
|
1225
|
+
padding: 9px 14px;
|
|
1226
|
+
font: inherit;
|
|
1227
|
+
}
|
|
1228
|
+
|
|
1229
|
+
.suu-dropdown__input:focus {
|
|
1230
|
+
border-color: var(--suu-color-accent);
|
|
1231
|
+
outline: 2px solid color-mix(in srgb, var(--suu-color-accent) 22%, transparent);
|
|
1232
|
+
outline-offset: 1px;
|
|
1233
|
+
}
|
|
1234
|
+
|
|
1235
|
+
.suu-dropdown__selected-items {
|
|
1236
|
+
display: flex;
|
|
1237
|
+
flex-wrap: wrap;
|
|
1238
|
+
gap: 6px;
|
|
1239
|
+
margin-bottom: 6px;
|
|
1240
|
+
}
|
|
1241
|
+
|
|
1242
|
+
.suu-dropdown__selected-item {
|
|
1243
|
+
display: inline-flex;
|
|
1244
|
+
align-items: center;
|
|
1245
|
+
gap: 4px;
|
|
1246
|
+
max-width: 100%;
|
|
1247
|
+
padding: 3px 6px 3px 9px;
|
|
1248
|
+
border: 1px solid color-mix(in srgb, var(--suu-color-accent) 34%, var(--suu-color-border));
|
|
1249
|
+
border-radius: var(--suu-radius-pill);
|
|
1250
|
+
background: color-mix(in srgb, var(--suu-color-accent) 9%, var(--suu-color-bg));
|
|
1251
|
+
color: var(--suu-color-text);
|
|
1252
|
+
font-size: 0.875rem;
|
|
1253
|
+
}
|
|
1254
|
+
|
|
1255
|
+
.suu-dropdown__selected-remove {
|
|
1256
|
+
border: 0;
|
|
1257
|
+
padding: 0 2px;
|
|
1258
|
+
background: transparent;
|
|
1259
|
+
color: var(--suu-color-muted);
|
|
1260
|
+
cursor: pointer;
|
|
1261
|
+
font: inherit;
|
|
1262
|
+
line-height: 1;
|
|
1263
|
+
}
|
|
1264
|
+
|
|
1212
1265
|
.suu-dropdown__chevron {
|
|
1213
1266
|
flex: 0 0 auto;
|
|
1214
1267
|
width: 0.58em;
|
package/package.json
CHANGED