@sveltia/ui 0.15.16 → 0.17.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/package/components/alert/alert.svelte +22 -7
- package/package/components/alert/alert.svelte.d.ts +47 -31
- package/package/components/button/button-group.svelte +16 -6
- package/package/components/button/button-group.svelte.d.ts +38 -28
- package/package/components/button/button.svelte +41 -136
- package/package/components/button/button.svelte.d.ts +20 -162
- package/package/components/button/select-button-group.svelte +31 -37
- package/package/components/button/select-button-group.svelte.d.ts +91 -39
- package/package/components/button/select-button.svelte +19 -62
- package/package/components/button/select-button.svelte.d.ts +31 -65
- package/package/components/button/split-button.svelte +37 -47
- package/package/components/button/split-button.svelte.d.ts +54 -60
- package/package/components/calendar/calendar.svelte +80 -55
- package/package/components/calendar/calendar.svelte.d.ts +30 -26
- package/package/components/checkbox/checkbox-group.svelte +23 -20
- package/package/components/checkbox/checkbox-group.svelte.d.ts +64 -32
- package/package/components/checkbox/checkbox.svelte +57 -67
- package/package/components/checkbox/checkbox.svelte.d.ts +81 -53
- package/package/components/dialog/alert-dialog.svelte +9 -36
- package/package/components/dialog/alert-dialog.svelte.d.ts +20 -49
- package/package/components/dialog/confirmation-dialog.svelte +9 -41
- package/package/components/dialog/confirmation-dialog.svelte.d.ts +20 -51
- package/package/components/dialog/dialog.svelte +60 -105
- package/package/components/dialog/dialog.svelte.d.ts +19 -86
- package/package/components/dialog/prompt-dialog.svelte +32 -61
- package/package/components/dialog/prompt-dialog.svelte.d.ts +53 -65
- package/package/components/disclosure/disclosure.svelte +39 -34
- package/package/components/disclosure/disclosure.svelte.d.ts +88 -57
- package/package/components/divider/divider.svelte +18 -14
- package/package/components/divider/divider.svelte.d.ts +48 -26
- package/package/components/divider/spacer.svelte +13 -8
- package/package/components/divider/spacer.svelte.d.ts +37 -25
- package/package/components/drawer/drawer.svelte +63 -76
- package/package/components/drawer/drawer.svelte.d.ts +116 -70
- package/package/components/grid/grid-body.svelte +15 -10
- package/package/components/grid/grid-body.svelte.d.ts +45 -29
- package/package/components/grid/grid-cell.svelte +16 -6
- package/package/components/grid/grid-cell.svelte.d.ts +38 -28
- package/package/components/grid/grid-col-header.svelte +16 -6
- package/package/components/grid/grid-col-header.svelte.d.ts +38 -28
- package/package/components/grid/grid-foot.svelte +16 -6
- package/package/components/grid/grid-foot.svelte.d.ts +38 -28
- package/package/components/grid/grid-head.svelte +16 -6
- package/package/components/grid/grid-head.svelte.d.ts +38 -28
- package/package/components/grid/grid-row-header.svelte +16 -6
- package/package/components/grid/grid-row-header.svelte.d.ts +38 -28
- package/package/components/grid/grid-row.svelte +19 -23
- package/package/components/grid/grid-row.svelte.d.ts +63 -43
- package/package/components/grid/grid.svelte +26 -25
- package/package/components/grid/grid.svelte.d.ts +71 -37
- package/package/components/icon/icon.svelte +14 -9
- package/package/components/icon/icon.svelte.d.ts +37 -25
- package/package/components/listbox/listbox.svelte +46 -52
- package/package/components/listbox/listbox.svelte.d.ts +117 -45
- package/package/components/listbox/option-group.svelte +23 -19
- package/package/components/listbox/option-group.svelte.d.ts +64 -32
- package/package/components/listbox/option.svelte +44 -57
- package/package/components/listbox/option.svelte.d.ts +68 -74
- package/package/components/menu/menu-button.svelte +42 -63
- package/package/components/menu/menu-button.svelte.d.ts +35 -62
- package/package/components/menu/menu-item-checkbox.svelte +29 -41
- package/package/components/menu/menu-item-checkbox.svelte.d.ts +20 -49
- package/package/components/menu/menu-item-group.svelte +22 -19
- package/package/components/menu/menu-item-group.svelte.d.ts +56 -32
- package/package/components/menu/menu-item-radio.svelte +29 -41
- package/package/components/menu/menu-item-radio.svelte.d.ts +20 -49
- package/package/components/menu/menu-item.svelte +66 -75
- package/package/components/menu/menu-item.svelte.d.ts +19 -68
- package/package/components/menu/menu.svelte +25 -22
- package/package/components/menu/menu.svelte.d.ts +65 -35
- package/package/components/radio/radio-group.svelte +36 -42
- package/package/components/radio/radio-group.svelte.d.ts +100 -40
- package/package/components/radio/radio.svelte +45 -48
- package/package/components/radio/radio.svelte.d.ts +111 -47
- package/package/components/select/combobox.svelte +76 -101
- package/package/components/select/combobox.svelte.d.ts +19 -54
- package/package/components/select/select-tags.svelte +48 -59
- package/package/components/select/select-tags.svelte.d.ts +127 -45
- package/package/components/select/select.svelte +18 -37
- package/package/components/select/select.svelte.d.ts +20 -45
- package/package/components/slider/slider.svelte +71 -68
- package/package/components/slider/slider.svelte.d.ts +159 -47
- package/package/components/switch/switch.svelte +36 -46
- package/package/components/switch/switch.svelte.d.ts +98 -42
- package/package/components/table/table-body.svelte +15 -11
- package/package/components/table/table-body.svelte.d.ts +45 -29
- package/package/components/table/table-cell.svelte +16 -6
- package/package/components/table/table-cell.svelte.d.ts +38 -28
- package/package/components/table/table-col-header.svelte +16 -6
- package/package/components/table/table-col-header.svelte.d.ts +38 -28
- package/package/components/table/table-foot.svelte +16 -6
- package/package/components/table/table-foot.svelte.d.ts +38 -28
- package/package/components/table/table-head.svelte +16 -6
- package/package/components/table/table-head.svelte.d.ts +38 -28
- package/package/components/table/table-row-header.svelte +16 -6
- package/package/components/table/table-row-header.svelte.d.ts +38 -28
- package/package/components/table/table-row.svelte +16 -6
- package/package/components/table/table-row.svelte.d.ts +38 -28
- package/package/components/table/table.svelte +16 -6
- package/package/components/table/table.svelte.d.ts +38 -28
- package/package/components/tabs/tab-box.svelte +16 -9
- package/package/components/tabs/tab-box.svelte.d.ts +47 -27
- package/package/components/tabs/tab-list.svelte +36 -35
- package/package/components/tabs/tab-list.svelte.d.ts +80 -38
- package/package/components/tabs/tab-panel.svelte +16 -6
- package/package/components/tabs/tab-panel.svelte.d.ts +38 -28
- package/package/components/tabs/tab-panels.svelte +16 -6
- package/package/components/tabs/tab-panels.svelte.d.ts +38 -26
- package/package/components/tabs/tab.svelte +28 -25
- package/package/components/tabs/tab.svelte.d.ts +31 -55
- package/package/components/text-editor/lexical-root.svelte +38 -32
- package/package/components/text-editor/lexical-root.svelte.d.ts +91 -29
- package/package/components/text-editor/text-editor.svelte +63 -79
- package/package/components/text-editor/text-editor.svelte.d.ts +114 -36
- package/package/components/text-editor/toolbar/editor-toolbar.svelte +41 -24
- package/package/components/text-editor/toolbar/editor-toolbar.svelte.d.ts +49 -23
- package/package/components/text-editor/toolbar/format-text-button.svelte +15 -5
- package/package/components/text-editor/toolbar/format-text-button.svelte.d.ts +30 -22
- package/package/components/text-editor/toolbar/insert-link-button.svelte +18 -16
- package/package/components/text-editor/toolbar/insert-link-button.svelte.d.ts +20 -23
- package/package/components/text-editor/toolbar/toggle-block-menu-item.svelte +19 -7
- package/package/components/text-editor/toolbar/toggle-block-menu-item.svelte.d.ts +30 -22
- package/package/components/text-field/number-input.svelte +63 -81
- package/package/components/text-field/number-input.svelte.d.ts +62 -68
- package/package/components/text-field/password-input.svelte +38 -57
- package/package/components/text-field/password-input.svelte.d.ts +30 -58
- package/package/components/text-field/search-bar.svelte +45 -62
- package/package/components/text-field/search-bar.svelte.d.ts +42 -87
- package/package/components/text-field/text-area.svelte +38 -54
- package/package/components/text-field/text-area.svelte.d.ts +116 -50
- package/package/components/text-field/text-input.svelte +30 -86
- package/package/components/text-field/text-input.svelte.d.ts +20 -105
- package/package/components/toast/toast.svelte +36 -30
- package/package/components/toast/toast.svelte.d.ts +65 -33
- package/package/components/toolbar/toolbar.svelte +25 -25
- package/package/components/toolbar/toolbar.svelte.d.ts +72 -34
- package/package/components/util/app-shell.svelte +22 -10
- package/package/components/util/app-shell.svelte.d.ts +40 -34
- package/package/components/util/group.svelte +20 -15
- package/package/components/util/group.svelte.d.ts +55 -31
- package/package/components/util/modal.svelte +89 -105
- package/package/components/util/modal.svelte.d.ts +24 -82
- package/package/components/util/placeholder.svelte +21 -0
- package/package/components/util/placeholder.svelte.d.ts +34 -0
- package/package/components/util/popup.svelte +65 -62
- package/package/components/util/popup.svelte.d.ts +104 -82
- package/package/services/{group.js → group.svelte.js} +11 -12
- package/package/services/{popup.js → popup.svelte.js} +6 -5
- package/package/typedefs.d.ts +545 -0
- package/package/typedefs.js +202 -0
- package/package.json +16 -23
- package/package/components/util/portal.svelte +0 -36
- package/package/components/util/portal.svelte.d.ts +0 -32
- /package/package/services/{events.d.ts → events.svelte.d.ts} +0 -0
- /package/package/services/{events.js → events.svelte.js} +0 -0
- /package/package/services/{group.d.ts → group.svelte.d.ts} +0 -0
- /package/package/services/{popup.d.ts → popup.svelte.d.ts} +0 -0
|
@@ -7,9 +7,7 @@
|
|
|
7
7
|
-->
|
|
8
8
|
<script>
|
|
9
9
|
import { generateElementId } from '@sveltia/utils/element';
|
|
10
|
-
import { createEventDispatcher } from 'svelte';
|
|
11
10
|
import { _ } from 'svelte-i18n';
|
|
12
|
-
import { writable } from 'svelte/store';
|
|
13
11
|
import Button from '../button/button.svelte';
|
|
14
12
|
import Icon from '../icon/icon.svelte';
|
|
15
13
|
import Listbox from '../listbox/listbox.svelte';
|
|
@@ -18,78 +16,56 @@
|
|
|
18
16
|
import Popup from '../util/popup.svelte';
|
|
19
17
|
|
|
20
18
|
/**
|
|
21
|
-
*
|
|
22
|
-
*
|
|
19
|
+
* @type {import('../../typedefs').ComboboxProps & import('../../typedefs').TextInputProps &
|
|
20
|
+
* Record<string, any>}
|
|
23
21
|
*/
|
|
24
|
-
let
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Whether to mark the widget required. An alias of the `aria-required` attribute.
|
|
43
|
-
* @type {boolean}
|
|
44
|
-
*/
|
|
45
|
-
export let required = false;
|
|
46
|
-
/**
|
|
47
|
-
* Whether to mark the widget invalid. An alias of the `aria-invalid` attribute.
|
|
48
|
-
* @type {boolean}
|
|
49
|
-
*/
|
|
50
|
-
export let invalid = false;
|
|
51
|
-
/**
|
|
52
|
-
* Selected option’s value.
|
|
53
|
-
* @type {(string | number | undefined)}
|
|
54
|
-
*/
|
|
55
|
-
export let value = undefined;
|
|
56
|
-
/**
|
|
57
|
-
* Whether to make the `combobox` editable.
|
|
58
|
-
*/
|
|
59
|
-
export let editable = true;
|
|
60
|
-
/**
|
|
61
|
-
* Where to show the dropdown menu.
|
|
62
|
-
* @type {import('../../typedefs').PopupPosition}
|
|
63
|
-
*/
|
|
64
|
-
export let position = 'bottom-left';
|
|
22
|
+
let {
|
|
23
|
+
/* eslint-disable prefer-const */
|
|
24
|
+
value = $bindable(),
|
|
25
|
+
class: className,
|
|
26
|
+
hidden = false,
|
|
27
|
+
disabled = false,
|
|
28
|
+
readonly = false,
|
|
29
|
+
required = false,
|
|
30
|
+
invalid = false,
|
|
31
|
+
editable = true,
|
|
32
|
+
position = 'bottom-left',
|
|
33
|
+
children,
|
|
34
|
+
chevronIcon,
|
|
35
|
+
onChange,
|
|
36
|
+
...restProps
|
|
37
|
+
/* eslint-enable prefer-const */
|
|
38
|
+
} = $props();
|
|
65
39
|
|
|
66
|
-
const dispatch = createEventDispatcher();
|
|
67
40
|
const id = generateElementId('combobox');
|
|
68
41
|
const selectedSelector = '[role="option"][aria-selected="true"]';
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
/** @type {
|
|
72
|
-
let
|
|
73
|
-
/** @type {
|
|
74
|
-
let
|
|
75
|
-
|
|
42
|
+
let isPopupOpen = $state(false);
|
|
43
|
+
|
|
44
|
+
/** @type {HTMLElement | undefined} */
|
|
45
|
+
let comboboxElement = $state();
|
|
46
|
+
/** @type {HTMLInputElement | undefined} */
|
|
47
|
+
let inputElement = $state();
|
|
48
|
+
/** @type {HTMLElement | undefined} */
|
|
49
|
+
let popupContent = $state();
|
|
76
50
|
/** @type {string} */
|
|
77
|
-
let label = '';
|
|
51
|
+
let label = $state('');
|
|
78
52
|
/** @type {boolean} */
|
|
79
|
-
let showFilter = false;
|
|
53
|
+
let showFilter = $state(false);
|
|
80
54
|
/** @type {string} */
|
|
81
|
-
let searchTerms = '';
|
|
55
|
+
let searchTerms = $state('');
|
|
82
56
|
/** @type {boolean} */
|
|
83
|
-
let hasMatchingOptions = true;
|
|
57
|
+
let hasMatchingOptions = $state(true);
|
|
58
|
+
/** @type {HTMLElement} */
|
|
59
|
+
const anchor = $derived(/** @type {HTMLElement} */ (comboboxElement ?? inputElement));
|
|
84
60
|
|
|
85
61
|
/**
|
|
86
62
|
* Update the {@link label} and selected option when the {@link value} is changed.
|
|
87
63
|
*/
|
|
88
|
-
const
|
|
89
|
-
const selected =
|
|
64
|
+
const _onChange = () => {
|
|
65
|
+
const selected = popupContent?.querySelector(selectedSelector);
|
|
90
66
|
|
|
91
67
|
const target = /** @type {HTMLButtonElement} */ (
|
|
92
|
-
|
|
68
|
+
popupContent?.querySelector(`[role="option"][value="${value}"]`)
|
|
93
69
|
);
|
|
94
70
|
|
|
95
71
|
if (target) {
|
|
@@ -106,53 +82,48 @@
|
|
|
106
82
|
* Update the {@link value} whenever an option is selected.
|
|
107
83
|
* @param {HTMLButtonElement} target - Selected option.
|
|
108
84
|
*/
|
|
109
|
-
const
|
|
85
|
+
const _onSelect = (target) => {
|
|
110
86
|
// @todo support more types
|
|
87
|
+
// @ts-ignore
|
|
111
88
|
value = target.dataset.type === 'number' ? Number(target.value) : target.value;
|
|
112
|
-
|
|
113
|
-
|
|
89
|
+
_onChange();
|
|
90
|
+
onChange?.(new CustomEvent('Change', { detail: { target: inputElement, value } }));
|
|
114
91
|
};
|
|
115
92
|
|
|
116
|
-
|
|
117
|
-
if (
|
|
93
|
+
$effect(() => {
|
|
94
|
+
if (popupContent) {
|
|
118
95
|
globalThis.requestAnimationFrame(() => {
|
|
119
|
-
const selected =
|
|
96
|
+
const selected = popupContent?.querySelector(selectedSelector);
|
|
120
97
|
|
|
121
98
|
if (selected) {
|
|
122
|
-
|
|
99
|
+
_onSelect(/** @type {HTMLButtonElement} */ (selected));
|
|
123
100
|
}
|
|
124
101
|
});
|
|
125
102
|
}
|
|
126
|
-
}
|
|
103
|
+
});
|
|
127
104
|
|
|
128
|
-
|
|
105
|
+
$effect(() => {
|
|
129
106
|
void value;
|
|
130
|
-
|
|
131
|
-
}
|
|
107
|
+
_onChange();
|
|
108
|
+
});
|
|
132
109
|
</script>
|
|
133
110
|
|
|
134
|
-
<div
|
|
135
|
-
role="none"
|
|
136
|
-
class="sui combobox {className}"
|
|
137
|
-
class:editable
|
|
138
|
-
hidden={hidden || undefined}
|
|
139
|
-
{...$$restProps}
|
|
140
|
-
>
|
|
111
|
+
<div {...restProps} role="none" class="sui combobox {className}" class:editable {hidden}>
|
|
141
112
|
{#if !editable}
|
|
142
113
|
<div
|
|
114
|
+
bind:this={comboboxElement}
|
|
115
|
+
{...restProps}
|
|
143
116
|
role="combobox"
|
|
144
117
|
{id}
|
|
145
118
|
class:selected={value !== undefined}
|
|
146
119
|
tabindex={disabled ? -1 : 0}
|
|
147
120
|
aria-controls="{id}-popup"
|
|
148
|
-
aria-expanded={
|
|
121
|
+
aria-expanded={isPopupOpen}
|
|
149
122
|
aria-hidden={hidden}
|
|
150
123
|
aria-disabled={disabled}
|
|
151
124
|
aria-readonly={readonly}
|
|
152
125
|
aria-haspopup="listbox"
|
|
153
126
|
aria-activedescendant="selected-option"
|
|
154
|
-
{...$$restProps}
|
|
155
|
-
bind:this={comboboxElement}
|
|
156
127
|
>
|
|
157
128
|
<div role="none" class="label">
|
|
158
129
|
{value !== undefined ? label : $_('_sui.combobox.select_an_option')}
|
|
@@ -160,6 +131,8 @@
|
|
|
160
131
|
</div>
|
|
161
132
|
{:else}
|
|
162
133
|
<TextInput
|
|
134
|
+
{...restProps}
|
|
135
|
+
bind:element={inputElement}
|
|
163
136
|
role="combobox"
|
|
164
137
|
{id}
|
|
165
138
|
{value}
|
|
@@ -169,11 +142,9 @@
|
|
|
169
142
|
{required}
|
|
170
143
|
{invalid}
|
|
171
144
|
aria-controls="{id}-popup"
|
|
172
|
-
aria-expanded={
|
|
145
|
+
aria-expanded={isPopupOpen}
|
|
173
146
|
aria-haspopup="listbox"
|
|
174
147
|
aria-activedescendant="selected-option"
|
|
175
|
-
{...$$restProps}
|
|
176
|
-
bind:this={inputComponent}
|
|
177
148
|
/>
|
|
178
149
|
{/if}
|
|
179
150
|
<Button
|
|
@@ -182,33 +153,37 @@
|
|
|
182
153
|
{hidden}
|
|
183
154
|
{disabled}
|
|
184
155
|
tabindex={readonly || disabled ? -1 : 0}
|
|
185
|
-
aria-label={
|
|
156
|
+
aria-label={isPopupOpen ? $_('_sui.collapse') : $_('_sui.expand')}
|
|
186
157
|
aria-controls="{id}-popup"
|
|
187
|
-
aria-expanded={
|
|
188
|
-
|
|
158
|
+
aria-expanded={isPopupOpen}
|
|
159
|
+
onclick={(event) => {
|
|
189
160
|
event.preventDefault();
|
|
190
161
|
event.stopPropagation();
|
|
191
162
|
|
|
192
163
|
if (!disabled && !readonly) {
|
|
193
|
-
|
|
164
|
+
isPopupOpen = !isPopupOpen;
|
|
194
165
|
}
|
|
195
166
|
}}
|
|
196
167
|
>
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
168
|
+
{#snippet startIcon()}
|
|
169
|
+
{#if chevronIcon}
|
|
170
|
+
{@render chevronIcon()}
|
|
171
|
+
{:else}
|
|
172
|
+
<Icon name="expand_more" />
|
|
173
|
+
{/if}
|
|
174
|
+
{/snippet}
|
|
200
175
|
</Button>
|
|
201
176
|
</div>
|
|
202
177
|
<Popup
|
|
178
|
+
bind:content={popupContent}
|
|
203
179
|
id="{id}-popup"
|
|
204
180
|
class="combobox"
|
|
205
|
-
anchor
|
|
181
|
+
{anchor}
|
|
206
182
|
{position}
|
|
207
183
|
touchOptimized={true}
|
|
208
184
|
bind:open={isPopupOpen}
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
showFilter = (popupComponent?.content?.querySelectorAll('[role="option"]')?.length ?? 0) > 5;
|
|
185
|
+
onopen={() => {
|
|
186
|
+
showFilter = (popupContent?.querySelectorAll('[role="option"]')?.length ?? 0) > 5;
|
|
212
187
|
searchTerms = '';
|
|
213
188
|
}}
|
|
214
189
|
>
|
|
@@ -219,10 +194,10 @@
|
|
|
219
194
|
aria-label={$_('_sui.combobox.filter_options')}
|
|
220
195
|
aria-controls="{id}-listbox"
|
|
221
196
|
bind:value={searchTerms}
|
|
222
|
-
|
|
197
|
+
onkeydown={(event) => {
|
|
223
198
|
if (['ArrowUp', 'ArrowDown', 'Enter'].includes(event.key)) {
|
|
224
199
|
event.preventDefault();
|
|
225
|
-
|
|
200
|
+
popupContent
|
|
226
201
|
?.querySelector('.sui.listbox')
|
|
227
202
|
?.dispatchEvent(new KeyboardEvent('keydown', event));
|
|
228
203
|
}
|
|
@@ -233,16 +208,16 @@
|
|
|
233
208
|
id="{id}-listbox"
|
|
234
209
|
class="in-combobox"
|
|
235
210
|
{searchTerms}
|
|
236
|
-
|
|
211
|
+
onclick={(event) => {
|
|
237
212
|
if (/** @type {HTMLElement} */ (event.target).matches('[role="option"]')) {
|
|
238
|
-
|
|
213
|
+
_onSelect(/** @type {HTMLButtonElement} */ (event.target));
|
|
239
214
|
}
|
|
240
215
|
}}
|
|
241
|
-
|
|
216
|
+
onFilter={(event) => {
|
|
242
217
|
hasMatchingOptions = !!(/** @type {CustomEvent} */ (event).detail.matched);
|
|
243
218
|
}}
|
|
244
219
|
>
|
|
245
|
-
|
|
220
|
+
{@render children?.()}
|
|
246
221
|
</Listbox>
|
|
247
222
|
{#if !hasMatchingOptions}
|
|
248
223
|
<div role="alert" class="no-options">
|
|
@@ -1,63 +1,28 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
export default Combobox;
|
|
2
|
+
type Combobox = SvelteComponent<ComboboxProps & TextInputProps & Record<string, any>, {
|
|
3
|
+
[evt: string]: CustomEvent<any>;
|
|
4
|
+
}, {}> & {
|
|
5
|
+
$$bindings?: "value" | undefined;
|
|
6
|
+
};
|
|
4
7
|
/**
|
|
5
8
|
* A variant of the `<Select>` widget with an auto-complete text input field.
|
|
6
9
|
* @see https://w3c.github.io/aria/#combobox
|
|
7
10
|
* @see https://www.w3.org/WAI/ARIA/apg/patterns/combobox/
|
|
8
11
|
* @todo Add DOM API compatibility.
|
|
9
12
|
*/
|
|
10
|
-
|
|
11
|
-
[x: string]: any;
|
|
12
|
-
class?: string | undefined;
|
|
13
|
-
disabled?: boolean | undefined;
|
|
14
|
-
invalid?: boolean | undefined;
|
|
15
|
-
required?: boolean | undefined;
|
|
16
|
-
value?: (string | number | undefined);
|
|
17
|
-
position?: import("../../typedefs").PopupPosition | undefined;
|
|
18
|
-
hidden?: boolean | undefined;
|
|
19
|
-
readonly?: boolean | undefined;
|
|
20
|
-
editable?: boolean | undefined;
|
|
21
|
-
}, {
|
|
22
|
-
change: CustomEvent<any>;
|
|
23
|
-
} & {
|
|
13
|
+
declare const Combobox: $$__sveltets_2_IsomorphicComponent<import("../../typedefs").ComboboxProps & import("../../typedefs").TextInputProps & Record<string, any>, {
|
|
24
14
|
[evt: string]: CustomEvent<any>;
|
|
25
|
-
}, {
|
|
26
|
-
|
|
27
|
-
|
|
15
|
+
}, {}, {}, "value">;
|
|
16
|
+
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> {
|
|
17
|
+
new (options: import("svelte").ComponentConstructorOptions<Props>): import("svelte").SvelteComponent<Props, Events, Slots> & {
|
|
18
|
+
$$bindings?: Bindings;
|
|
19
|
+
} & Exports;
|
|
20
|
+
(internal: unknown, props: Props & {
|
|
21
|
+
$$events?: Events;
|
|
22
|
+
$$slots?: Slots;
|
|
23
|
+
}): Exports & {
|
|
24
|
+
$set?: any;
|
|
25
|
+
$on?: any;
|
|
28
26
|
};
|
|
29
|
-
|
|
30
|
-
}> {
|
|
27
|
+
z_$$bindings?: Bindings;
|
|
31
28
|
}
|
|
32
|
-
export type ComboboxProps = typeof __propDef.props;
|
|
33
|
-
export type ComboboxEvents = typeof __propDef.events;
|
|
34
|
-
export type ComboboxSlots = typeof __propDef.slots;
|
|
35
|
-
import { SvelteComponent } from "svelte";
|
|
36
|
-
declare const __propDef: {
|
|
37
|
-
props: {
|
|
38
|
-
[x: string]: any;
|
|
39
|
-
class?: string | undefined;
|
|
40
|
-
disabled?: boolean | undefined;
|
|
41
|
-
invalid?: boolean | undefined;
|
|
42
|
-
required?: boolean | undefined;
|
|
43
|
-
value?: (string | number | undefined);
|
|
44
|
-
position?: import("../../typedefs").PopupPosition | undefined;
|
|
45
|
-
hidden?: boolean | undefined;
|
|
46
|
-
readonly?: boolean | undefined;
|
|
47
|
-
editable?: boolean | undefined;
|
|
48
|
-
};
|
|
49
|
-
events: {
|
|
50
|
-
change: CustomEvent<any>;
|
|
51
|
-
} & {
|
|
52
|
-
[evt: string]: CustomEvent<any>;
|
|
53
|
-
};
|
|
54
|
-
slots: {
|
|
55
|
-
'chevron-icon': {
|
|
56
|
-
slot: string;
|
|
57
|
-
};
|
|
58
|
-
default: {};
|
|
59
|
-
};
|
|
60
|
-
exports?: undefined;
|
|
61
|
-
bindings?: undefined;
|
|
62
|
-
};
|
|
63
|
-
export {};
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
<script>
|
|
2
|
-
import { createEventDispatcher } from 'svelte';
|
|
3
2
|
import { _ } from 'svelte-i18n';
|
|
4
3
|
import Button from '../button/button.svelte';
|
|
5
4
|
import Icon from '../icon/icon.svelte';
|
|
@@ -7,66 +6,54 @@
|
|
|
7
6
|
import Select from './select.svelte';
|
|
8
7
|
|
|
9
8
|
/**
|
|
10
|
-
*
|
|
11
|
-
* @
|
|
9
|
+
* @typedef {object} Props
|
|
10
|
+
* @property {{ label: string, value: string, searchValue?: string }[]} options - Available
|
|
11
|
+
* options.
|
|
12
|
+
* @property {string[]} [values] - Selected option values.
|
|
13
|
+
* @property {number | undefined} [max] - Maximum number of selectable options.
|
|
14
|
+
* @property {string} [class] - The `class` attribute on the wrapper element.
|
|
15
|
+
* @property {boolean} [hidden] - Whether to hide the widget.
|
|
16
|
+
* @property {boolean} [disabled] - Whether to disable the widget. An alias of the `aria-disabled`
|
|
17
|
+
* attribute.
|
|
18
|
+
* @property {boolean} [readonly] - Whether to make the widget read-only. An alias of the
|
|
19
|
+
* `aria-readonly` attribute.
|
|
20
|
+
* @property {boolean} [required] - Whether to mark the widget required. An alias of the
|
|
21
|
+
* `aria-required` attribute.
|
|
22
|
+
* @property {boolean} [invalid] - Whether to mark the widget invalid. An alias of the
|
|
23
|
+
* `aria-invalid` attribute.
|
|
24
|
+
* @property {import('svelte').Snippet} [children] - Primary slot content.
|
|
25
|
+
* @property {(event: CustomEvent) => void} [onAddValue] - Custom `AddValue` event handler.
|
|
26
|
+
* @property {(event: CustomEvent) => void} [onRemoveValue] - Custom `RemoveValue` event handler.
|
|
12
27
|
*/
|
|
13
|
-
|
|
14
|
-
export { className as class };
|
|
15
|
-
/**
|
|
16
|
-
* Whether to hide the widget. An alias of the `aria-hidden` attribute.
|
|
17
|
-
* @type {boolean | undefined}
|
|
18
|
-
*/
|
|
19
|
-
export let hidden = undefined;
|
|
20
|
-
/**
|
|
21
|
-
* Whether to disable the widget. An alias of the `aria-disabled` attribute.
|
|
22
|
-
* @type {boolean}
|
|
23
|
-
*/
|
|
24
|
-
export let disabled = false;
|
|
25
|
-
/**
|
|
26
|
-
* Whether to make the widget read-only. An alias of the `aria-readonly` attribute.
|
|
27
|
-
* @type {boolean}
|
|
28
|
-
*/
|
|
29
|
-
export let readonly = false;
|
|
30
|
-
/**
|
|
31
|
-
* Whether to mark the widget required. An alias of the `aria-required` attribute.
|
|
32
|
-
* @type {boolean}
|
|
33
|
-
*/
|
|
34
|
-
export let required = false;
|
|
35
|
-
/**
|
|
36
|
-
* Whether to mark the widget invalid. An alias of the `aria-invalid` attribute.
|
|
37
|
-
* @type {boolean}
|
|
38
|
-
*/
|
|
39
|
-
export let invalid = false;
|
|
40
|
-
/**
|
|
41
|
-
* Available options.
|
|
42
|
-
* @type {{ label: string, value: string, searchValue?: string }[]}
|
|
43
|
-
*/
|
|
44
|
-
export let options;
|
|
45
|
-
/**
|
|
46
|
-
* Selected option values.
|
|
47
|
-
* @type {string[]}
|
|
48
|
-
*/
|
|
49
|
-
export let values = [];
|
|
28
|
+
|
|
50
29
|
/**
|
|
51
|
-
*
|
|
52
|
-
* @type {number | undefined}
|
|
30
|
+
* @type {Props & Record<string, any>}
|
|
53
31
|
*/
|
|
54
|
-
|
|
32
|
+
let {
|
|
33
|
+
/* eslint-disable prefer-const */
|
|
34
|
+
values = $bindable([]),
|
|
35
|
+
options,
|
|
36
|
+
max = undefined,
|
|
37
|
+
class: className,
|
|
38
|
+
hidden = false,
|
|
39
|
+
disabled = false,
|
|
40
|
+
readonly = false,
|
|
41
|
+
required = false,
|
|
42
|
+
invalid = false,
|
|
43
|
+
children,
|
|
44
|
+
onAddValue,
|
|
45
|
+
onRemoveValue,
|
|
46
|
+
...restProps
|
|
47
|
+
/* eslint-enable prefer-const */
|
|
48
|
+
} = $props();
|
|
55
49
|
|
|
56
50
|
/**
|
|
57
51
|
* @type {string | undefined}
|
|
58
52
|
*/
|
|
59
|
-
let selectedValue =
|
|
60
|
-
|
|
61
|
-
const dispatch = createEventDispatcher();
|
|
53
|
+
let selectedValue = $state();
|
|
62
54
|
</script>
|
|
63
55
|
|
|
64
|
-
<div
|
|
65
|
-
role="none"
|
|
66
|
-
class="sui select-tags {className}"
|
|
67
|
-
class:disabled={disabled || readonly}
|
|
68
|
-
hidden={hidden || undefined}
|
|
69
|
-
>
|
|
56
|
+
<div role="none" class="sui select-tags {className}" class:disabled={disabled || readonly} {hidden}>
|
|
70
57
|
{#each values as value}
|
|
71
58
|
{@const option = options.find((o) => o.value === value)}
|
|
72
59
|
{#if option}
|
|
@@ -77,28 +64,30 @@
|
|
|
77
64
|
size="small"
|
|
78
65
|
disabled={disabled || readonly}
|
|
79
66
|
aria-label={$_('remove_x', { values: { name: option.label } })}
|
|
80
|
-
|
|
67
|
+
onclick={() => {
|
|
81
68
|
values = values.filter((v) => v !== value);
|
|
82
|
-
|
|
69
|
+
onRemoveValue?.(new CustomEvent('RemoveValue', { detail: { value } }));
|
|
83
70
|
}}
|
|
84
71
|
>
|
|
85
|
-
|
|
72
|
+
{#snippet startIcon()}
|
|
73
|
+
<Icon name="close" />
|
|
74
|
+
{/snippet}
|
|
86
75
|
</Button>
|
|
87
76
|
</span>
|
|
88
77
|
{/if}
|
|
89
78
|
{/each}
|
|
90
79
|
{#if (typeof max !== 'number' || values.length < max) && values.length < options.length}
|
|
91
80
|
<Select
|
|
81
|
+
{...restProps}
|
|
82
|
+
bind:value={selectedValue}
|
|
92
83
|
disabled={disabled || readonly}
|
|
93
84
|
{readonly}
|
|
94
85
|
{required}
|
|
95
86
|
{invalid}
|
|
96
|
-
{
|
|
97
|
-
bind:value={selectedValue}
|
|
98
|
-
on:change={() => {
|
|
87
|
+
onChange={() => {
|
|
99
88
|
if (selectedValue) {
|
|
100
89
|
values = [...values, selectedValue];
|
|
101
|
-
|
|
90
|
+
onAddValue?.(new CustomEvent('AddValue', { detail: { value: selectedValue } }));
|
|
102
91
|
// Reset the combobox
|
|
103
92
|
selectedValue = undefined;
|
|
104
93
|
}
|