@oscarpalmer/oui 0.34.0 → 0.36.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/css/combobox.css +1 -1
- package/dist/css/listbox.css +152 -0
- package/dist/js/combobox/constants.combobox.d.mts +2 -2
- package/dist/js/combobox/constants.combobox.mjs +40 -33
- package/dist/js/combobox/dom.combobox.d.mts +8 -91
- package/dist/js/combobox/dom.combobox.mjs +204 -2
- package/dist/js/combobox/event.combobox.d.mts +14 -8
- package/dist/js/combobox/event.combobox.mjs +2 -2
- package/dist/js/combobox/index.d.mts +1 -1
- package/dist/js/combobox/index.mjs +21 -18
- package/dist/js/combobox/misc.combobox.d.mts +2 -14
- package/dist/js/combobox/misc.combobox.mjs +2 -2
- package/dist/js/combobox/models.combobox.d.mts +44 -2
- package/dist/js/combobox/state.combobox.d.mts +9 -8
- package/dist/js/combobox/state.combobox.mjs +2 -2
- package/dist/js/constants.combobox-DmRAMC64.d.mts +26 -0
- package/dist/js/constants.listbox-DRsXUxd3.d.mts +14 -0
- package/dist/js/index-EfkUSals.d.mts +139 -0
- package/dist/js/index.d.mts +4 -2
- package/dist/js/index.mjs +4 -2
- package/dist/js/internal/attributable.mjs +4 -3
- package/dist/js/internal/listbox/listbox.constants.d.mts +11 -0
- package/dist/js/internal/listbox/listbox.constants.mjs +23 -0
- package/dist/js/internal/listbox/listbox.data.d.mts +20 -0
- package/dist/js/internal/listbox/listbox.data.mjs +2 -0
- package/dist/js/internal/listbox/listbox.dom.d.mts +66 -0
- package/dist/js/internal/listbox/listbox.dom.mjs +2 -0
- package/dist/js/internal/listbox/listbox.event.d.mts +5 -0
- package/dist/js/internal/listbox/listbox.event.mjs +63 -0
- package/dist/js/internal/listbox/listbox.form.d.mts +6 -0
- package/dist/js/internal/listbox/listbox.form.mjs +52 -0
- package/dist/js/internal/listbox/listbox.misc.d.mts +12 -0
- package/dist/js/internal/listbox/listbox.misc.mjs +2 -0
- package/dist/js/internal/listbox/listbox.model.d.mts +2 -0
- package/dist/js/internal/listbox/listbox.model.mjs +1 -0
- package/dist/js/internal/listbox/listbox.state.d.mts +7 -0
- package/dist/js/internal/listbox/listbox.state.mjs +40 -0
- package/dist/js/internal/misc.d.mts +6 -0
- package/dist/js/internal/misc.mjs +13 -0
- package/dist/js/l10n-Bn-7RcwR.d.mts +20 -0
- package/dist/js/l10n.d.mts +2 -0
- package/dist/js/l10n.mjs +80 -0
- package/dist/js/listbox/constants.listbox.d.mts +2 -0
- package/dist/js/listbox/constants.listbox.mjs +40 -0
- package/dist/js/listbox/event.listbox.d.mts +8 -0
- package/dist/js/listbox/event.listbox.mjs +2 -0
- package/dist/js/listbox/index.d.mts +116 -0
- package/dist/js/listbox/index.mjs +189 -0
- package/dist/js/listbox/misc.listbox.d.mts +2 -0
- package/dist/js/listbox/misc.listbox.mjs +2 -0
- package/dist/js/listbox/state.listbox.d.mts +11 -0
- package/dist/js/listbox/state.listbox.mjs +2 -0
- package/dist/js/listbox.data-BWd0PCy7.mjs +424 -0
- package/dist/js/listbox.model-CRReGOmu.d.mts +125 -0
- package/dist/js/misc.listbox-BI-XsTOf.mjs +197 -0
- package/dist/js/misc.listbox-gnoJhrTr.d.mts +20 -0
- package/dist/js/sortable/sortable.embedded.mjs +4 -2
- package/dist/js/state.combobox-4xq0FPCF.mjs +365 -0
- package/package.json +7 -3
- package/src/css/combobox.scss +1 -1
- package/src/css/listbox.scss +149 -0
- package/src/js/combobox/constants.combobox.ts +46 -25
- package/src/js/combobox/dom.combobox.ts +65 -452
- package/src/js/combobox/event.combobox.ts +129 -218
- package/src/js/combobox/index.ts +43 -30
- package/src/js/combobox/misc.combobox.ts +60 -94
- package/src/js/combobox/models.combobox.ts +7 -47
- package/src/js/combobox/state.combobox.ts +136 -125
- package/src/js/index.ts +1 -0
- package/src/js/internal/listbox/listbox.constants.ts +25 -0
- package/src/js/{combobox/data.combobox.ts → internal/listbox/listbox.data.ts} +94 -43
- package/src/js/internal/listbox/listbox.dom.ts +445 -0
- package/src/js/internal/listbox/listbox.event.ts +129 -0
- package/src/js/{combobox/form.combobox.ts → internal/listbox/listbox.form.ts} +33 -33
- package/src/js/internal/listbox/listbox.misc.ts +135 -0
- package/src/js/internal/listbox/listbox.model.ts +169 -0
- package/src/js/internal/listbox/listbox.state.ts +82 -0
- package/src/js/internal/misc.ts +27 -0
- package/src/js/l10n.ts +192 -0
- package/src/js/listbox/constants.listbox.ts +61 -0
- package/src/js/listbox/event.listbox.ts +106 -0
- package/src/js/listbox/index.ts +302 -0
- package/src/js/listbox/misc.listbox.ts +70 -0
- package/src/js/listbox/state.listbox.ts +196 -0
- package/dist/js/combobox/data.combobox.d.mts +0 -18
- package/dist/js/combobox/data.combobox.mjs +0 -2
- package/dist/js/combobox/form.combobox.d.mts +0 -6
- package/dist/js/combobox/form.combobox.mjs +0 -2
- package/dist/js/combobox/i18n.combobox.d.mts +0 -2
- package/dist/js/combobox/i18n.combobox.mjs +0 -2
- package/dist/js/constants.combobox-DqNUGBLS.d.mts +0 -243
- package/dist/js/data.combobox-8RwBv5ey.mjs +0 -1077
- package/src/js/combobox/i18n.combobox.ts +0 -179
|
@@ -2,32 +2,26 @@ import {setAria} from '@oscarpalmer/toretto/aria';
|
|
|
2
2
|
import {setAttribute} from '@oscarpalmer/toretto/attribute';
|
|
3
3
|
import {createElement} from '@oscarpalmer/toretto/create';
|
|
4
4
|
import {getData} from '@oscarpalmer/toretto/data';
|
|
5
|
+
import {
|
|
6
|
+
createListboxFilter,
|
|
7
|
+
createListboxInput,
|
|
8
|
+
createListboxList,
|
|
9
|
+
createListboxMessage,
|
|
10
|
+
createListboxValueLabel,
|
|
11
|
+
type CreateListboxContent,
|
|
12
|
+
type CreateListboxContentParameters,
|
|
13
|
+
} from '../internal/listbox/listbox.dom';
|
|
14
|
+
import type {OuiListboxPreview} from '../internal/listbox/listbox.model';
|
|
15
|
+
import {getLocalization, localize} from '../l10n';
|
|
5
16
|
import {
|
|
6
17
|
COMBOBOX_ATTRIBUTE_ANCHOR,
|
|
7
|
-
COMBOBOX_ATTRIBUTE_CONTENT,
|
|
8
|
-
COMBOBOX_ATTRIBUTE_FILTER,
|
|
9
|
-
COMBOBOX_ATTRIBUTE_FILTER_INPUT,
|
|
10
|
-
COMBOBOX_ATTRIBUTE_HEADER,
|
|
11
|
-
COMBOBOX_ATTRIBUTE_HIDDEN,
|
|
12
|
-
COMBOBOX_ATTRIBUTE_LIST,
|
|
13
|
-
COMBOBOX_ATTRIBUTE_MESSAGE,
|
|
14
|
-
COMBOBOX_ATTRIBUTE_OPTION,
|
|
15
|
-
COMBOBOX_ATTRIBUTE_OPTION_ACTIVE,
|
|
16
18
|
COMBOBOX_ATTRIBUTE_SELECTION,
|
|
17
19
|
COMBOBOX_ATTRIBUTE_SELECTION_ITEM,
|
|
18
|
-
comboboxScrollOptions,
|
|
19
20
|
} from './constants.combobox';
|
|
20
|
-
import {updateComboboxValidity} from './form.combobox';
|
|
21
|
-
import {getComboboxLocalization} from './i18n.combobox';
|
|
22
21
|
import type {
|
|
23
|
-
OuiComboboxAutoComplete,
|
|
24
|
-
OuiComboboxAutoCompleteType,
|
|
25
|
-
OuiComboboxGroup,
|
|
26
|
-
OuiComboboxPreview,
|
|
27
22
|
OuiComboboxSelection,
|
|
28
23
|
OuiComboboxSelectionItem,
|
|
29
24
|
OuiComboboxState,
|
|
30
|
-
OuiComboboxType,
|
|
31
25
|
} from './models.combobox';
|
|
32
26
|
|
|
33
27
|
// #region Types
|
|
@@ -38,88 +32,6 @@ type CreateAnchor = {
|
|
|
38
32
|
selection?: OuiComboboxSelection;
|
|
39
33
|
};
|
|
40
34
|
|
|
41
|
-
type CreatAnchorParameters = {
|
|
42
|
-
autocomplete: OuiComboboxAutoComplete;
|
|
43
|
-
id: string;
|
|
44
|
-
label: HTMLLabelElement;
|
|
45
|
-
multiple: boolean;
|
|
46
|
-
select: HTMLSelectElement;
|
|
47
|
-
type: OuiComboboxType;
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
type CreateContent = {
|
|
51
|
-
element: HTMLElement;
|
|
52
|
-
filter?: CreateFilter;
|
|
53
|
-
list: CreateList;
|
|
54
|
-
message: HTMLElement;
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
type CreateContentParameters = {
|
|
58
|
-
autocomplete: OuiComboboxAutoComplete;
|
|
59
|
-
id: string;
|
|
60
|
-
label: HTMLLabelElement;
|
|
61
|
-
multiple: boolean;
|
|
62
|
-
select: HTMLSelectElement;
|
|
63
|
-
type: OuiComboboxType;
|
|
64
|
-
};
|
|
65
|
-
|
|
66
|
-
type CreateFilter = {
|
|
67
|
-
container: HTMLElement;
|
|
68
|
-
element: HTMLInputElement;
|
|
69
|
-
};
|
|
70
|
-
|
|
71
|
-
type CreateFilterParameters = {
|
|
72
|
-
autocomplete: OuiComboboxAutoCompleteType;
|
|
73
|
-
id: string;
|
|
74
|
-
label: HTMLLabelElement;
|
|
75
|
-
type: OuiComboboxType;
|
|
76
|
-
};
|
|
77
|
-
|
|
78
|
-
type CreateGroupParameters = {
|
|
79
|
-
autocomplete: OuiComboboxAutoComplete;
|
|
80
|
-
group: HTMLOptGroupElement;
|
|
81
|
-
groupOptions: HTMLOptionElement[];
|
|
82
|
-
selected: HTMLElement[];
|
|
83
|
-
};
|
|
84
|
-
|
|
85
|
-
type CreateInputParameters = {
|
|
86
|
-
autocomplete: OuiComboboxAutoCompleteType;
|
|
87
|
-
id: string;
|
|
88
|
-
label: HTMLLabelElement;
|
|
89
|
-
type: OuiComboboxType;
|
|
90
|
-
value: string;
|
|
91
|
-
};
|
|
92
|
-
|
|
93
|
-
type CreateList = {
|
|
94
|
-
element: HTMLElement;
|
|
95
|
-
groups?: OuiComboboxGroup[];
|
|
96
|
-
options: HTMLElement[];
|
|
97
|
-
selected: HTMLElement[];
|
|
98
|
-
};
|
|
99
|
-
|
|
100
|
-
type CreateListParameters = {
|
|
101
|
-
autocomplete: OuiComboboxAutoComplete;
|
|
102
|
-
id: string;
|
|
103
|
-
label: HTMLLabelElement;
|
|
104
|
-
multiple: boolean;
|
|
105
|
-
select: HTMLSelectElement;
|
|
106
|
-
};
|
|
107
|
-
|
|
108
|
-
type CreateOptionParameters = {
|
|
109
|
-
autocomplete: OuiComboboxAutoComplete;
|
|
110
|
-
group?: string;
|
|
111
|
-
index: number;
|
|
112
|
-
option: HTMLOptionElement;
|
|
113
|
-
};
|
|
114
|
-
|
|
115
|
-
type CreateOptionsParameters = {
|
|
116
|
-
autocomplete: OuiComboboxAutoComplete;
|
|
117
|
-
group?: string;
|
|
118
|
-
list: HTMLElement;
|
|
119
|
-
options: HTMLOptionElement[];
|
|
120
|
-
selected: HTMLElement[];
|
|
121
|
-
};
|
|
122
|
-
|
|
123
35
|
type CreateSelectionItemsParameters = {
|
|
124
36
|
container: HTMLElement;
|
|
125
37
|
items: OuiComboboxSelectionItem[];
|
|
@@ -131,21 +43,15 @@ type CreateSelectionItemsParameters = {
|
|
|
131
43
|
|
|
132
44
|
// #region Functions
|
|
133
45
|
|
|
134
|
-
export function createComboboxAnchor(parameters:
|
|
135
|
-
const {
|
|
46
|
+
export function createComboboxAnchor(parameters: CreateListboxContentParameters): CreateAnchor {
|
|
47
|
+
const {select} = parameters;
|
|
136
48
|
|
|
137
49
|
let container: HTMLElement | undefined;
|
|
138
50
|
let element: HTMLElement;
|
|
139
51
|
let selection: OuiComboboxSelection | undefined;
|
|
140
52
|
|
|
141
53
|
if (parameters.type === 'autocomplete') {
|
|
142
|
-
element =
|
|
143
|
-
id,
|
|
144
|
-
label,
|
|
145
|
-
type,
|
|
146
|
-
autocomplete: autocomplete.value,
|
|
147
|
-
value: select.selectedOptions[0]?.textContent ?? '',
|
|
148
|
-
});
|
|
54
|
+
element = createListboxInput(parameters, select.selectedOptions[0]?.textContent ?? '');
|
|
149
55
|
} else {
|
|
150
56
|
({container, element, selection} = createComboboxButton(parameters));
|
|
151
57
|
}
|
|
@@ -155,7 +61,7 @@ export function createComboboxAnchor(parameters: CreatAnchorParameters): CreateA
|
|
|
155
61
|
return {container, element, selection};
|
|
156
62
|
}
|
|
157
63
|
|
|
158
|
-
export function createComboboxButton(parameters:
|
|
64
|
+
export function createComboboxButton(parameters: CreateListboxContentParameters): CreateAnchor {
|
|
159
65
|
const {id, label, multiple, select} = parameters;
|
|
160
66
|
|
|
161
67
|
const element = createElement('button', {
|
|
@@ -163,7 +69,7 @@ export function createComboboxButton(parameters: CreatAnchorParameters): CreateA
|
|
|
163
69
|
controls: `${id}_content`,
|
|
164
70
|
expanded: false,
|
|
165
71
|
haspopup: 'listbox',
|
|
166
|
-
labelledby: `${label.id} ${id}`,
|
|
72
|
+
labelledby: `${label.id} ${id}_value`, // Non-input anchor, so no implicit value label, so we need to explicitly reference the value label
|
|
167
73
|
},
|
|
168
74
|
property: {
|
|
169
75
|
textContent: multiple ? '' : (select.selectedOptions[0]?.textContent ?? ''),
|
|
@@ -182,15 +88,17 @@ export function createComboboxButton(parameters: CreatAnchorParameters): CreateA
|
|
|
182
88
|
return {container, element, selection};
|
|
183
89
|
}
|
|
184
90
|
|
|
185
|
-
export function createComboboxContent(
|
|
186
|
-
|
|
91
|
+
export function createComboboxContent(
|
|
92
|
+
parameters: CreateListboxContentParameters,
|
|
93
|
+
): CreateListboxContent {
|
|
94
|
+
const {id, label} = parameters;
|
|
187
95
|
|
|
188
96
|
const element = createElement('div', {
|
|
189
97
|
aria: {
|
|
190
98
|
labelledby: label.id,
|
|
191
99
|
},
|
|
192
100
|
attribute: {
|
|
193
|
-
[
|
|
101
|
+
[parameters.attributes.content]: '',
|
|
194
102
|
popover: '',
|
|
195
103
|
},
|
|
196
104
|
property: {
|
|
@@ -199,241 +107,18 @@ export function createComboboxContent(parameters: CreateContentParameters): Crea
|
|
|
199
107
|
},
|
|
200
108
|
});
|
|
201
109
|
|
|
202
|
-
const filter =
|
|
203
|
-
const list =
|
|
204
|
-
const message =
|
|
110
|
+
const filter = createListboxFilter(parameters);
|
|
111
|
+
const list = createListboxList(parameters);
|
|
112
|
+
const message = createListboxMessage(parameters.attributes.message);
|
|
113
|
+
const value = createListboxValueLabel(parameters.id);
|
|
205
114
|
|
|
206
115
|
if (filter != null) {
|
|
207
116
|
element.append(filter.container);
|
|
208
117
|
}
|
|
209
118
|
|
|
210
|
-
element.append(list.element, message);
|
|
211
|
-
|
|
212
|
-
return {element, filter, list, message};
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
export function createComboboxFilter(parameters: CreateFilterParameters): CreateFilter | undefined {
|
|
216
|
-
const {autocomplete, id, label, type} = parameters;
|
|
217
|
-
|
|
218
|
-
if (type === 'autocomplete') {
|
|
219
|
-
return;
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
const container = createElement('div', {
|
|
223
|
-
attribute: {
|
|
224
|
-
[COMBOBOX_ATTRIBUTE_FILTER]: '',
|
|
225
|
-
},
|
|
226
|
-
});
|
|
227
|
-
|
|
228
|
-
const element = createComboboxInput({autocomplete, id, label, type, value: ''});
|
|
229
|
-
|
|
230
|
-
setAttribute(element, COMBOBOX_ATTRIBUTE_FILTER_INPUT, '');
|
|
231
|
-
|
|
232
|
-
container.append(element);
|
|
233
|
-
|
|
234
|
-
return {container, element};
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
export function createComboboxGroup(parameters: CreateGroupParameters): OuiComboboxGroup {
|
|
238
|
-
const {autocomplete, group, groupOptions, selected} = parameters;
|
|
239
|
-
|
|
240
|
-
const element = createElement('li', {
|
|
241
|
-
aria: {
|
|
242
|
-
label: group.label,
|
|
243
|
-
},
|
|
244
|
-
property: {
|
|
245
|
-
role: 'group',
|
|
246
|
-
},
|
|
247
|
-
});
|
|
248
|
-
|
|
249
|
-
const list = createElement('ul', {
|
|
250
|
-
property: {
|
|
251
|
-
role: 'none',
|
|
252
|
-
},
|
|
253
|
-
});
|
|
254
|
-
|
|
255
|
-
const header = createComboboxHeader(group);
|
|
256
|
-
|
|
257
|
-
element.append(header, list);
|
|
258
|
-
|
|
259
|
-
return {
|
|
260
|
-
element,
|
|
261
|
-
header,
|
|
262
|
-
options: createComboboxOptions({
|
|
263
|
-
autocomplete,
|
|
264
|
-
list,
|
|
265
|
-
selected,
|
|
266
|
-
group: header.id,
|
|
267
|
-
options: groupOptions,
|
|
268
|
-
}),
|
|
269
|
-
};
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
export function createComboboxHeader(group: HTMLOptGroupElement): HTMLElement {
|
|
273
|
-
return createElement('div', {
|
|
274
|
-
aria: {
|
|
275
|
-
hidden: true,
|
|
276
|
-
},
|
|
277
|
-
attribute: {
|
|
278
|
-
[COMBOBOX_ATTRIBUTE_HEADER]: '',
|
|
279
|
-
},
|
|
280
|
-
property: {
|
|
281
|
-
id: group.id,
|
|
282
|
-
textContent: group.label,
|
|
283
|
-
},
|
|
284
|
-
});
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
export function createComboboxInput(parameters: CreateInputParameters): HTMLInputElement {
|
|
288
|
-
const {autocomplete, id, label, type, value} = parameters;
|
|
289
|
-
|
|
290
|
-
return createElement('input', {
|
|
291
|
-
aria: {
|
|
292
|
-
autocomplete: autocomplete,
|
|
293
|
-
controls: `${id}_list`,
|
|
294
|
-
expanded: type === 'select',
|
|
295
|
-
haspopup: 'listbox',
|
|
296
|
-
labelledby: label.id,
|
|
297
|
-
},
|
|
298
|
-
attribute: {
|
|
299
|
-
autocorrect: 'off',
|
|
300
|
-
autocomplete: 'off',
|
|
301
|
-
form: '',
|
|
302
|
-
spellcheck: 'false',
|
|
303
|
-
type: 'text',
|
|
304
|
-
},
|
|
305
|
-
property: {
|
|
306
|
-
id,
|
|
307
|
-
value,
|
|
308
|
-
role: 'combobox',
|
|
309
|
-
},
|
|
310
|
-
});
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
export function createComboboxList(parameters: CreateListParameters): CreateList {
|
|
314
|
-
const {autocomplete, id, label, multiple, select} = parameters;
|
|
315
|
-
|
|
316
|
-
const element = createElement('ul', {
|
|
317
|
-
aria: {
|
|
318
|
-
labelledby: label.id,
|
|
319
|
-
multiselectable: multiple,
|
|
320
|
-
},
|
|
321
|
-
attribute: {
|
|
322
|
-
[COMBOBOX_ATTRIBUTE_LIST]: '',
|
|
323
|
-
tabindex: -1,
|
|
324
|
-
},
|
|
325
|
-
property: {
|
|
326
|
-
id: `${id}_list`,
|
|
327
|
-
role: 'listbox',
|
|
328
|
-
},
|
|
329
|
-
});
|
|
330
|
-
|
|
331
|
-
const children = [...select.children];
|
|
332
|
-
const childrenLength = children.length;
|
|
333
|
-
|
|
334
|
-
const options: HTMLElement[] = [];
|
|
335
|
-
const selected: HTMLElement[] = [];
|
|
336
|
-
|
|
337
|
-
let groups: OuiComboboxGroup[] | undefined;
|
|
338
|
-
|
|
339
|
-
for (let childIndex = 0; childIndex < childrenLength; childIndex += 1) {
|
|
340
|
-
const child = children[childIndex];
|
|
341
|
-
|
|
342
|
-
if (child instanceof HTMLOptionElement) {
|
|
343
|
-
const option = createComboboxOption({
|
|
344
|
-
autocomplete,
|
|
345
|
-
index: childIndex,
|
|
346
|
-
option: child,
|
|
347
|
-
});
|
|
348
|
-
|
|
349
|
-
element.append(option);
|
|
350
|
-
options.push(option);
|
|
351
|
-
|
|
352
|
-
if (child.selected) {
|
|
353
|
-
selected.push(option);
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
continue;
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
if (!(child instanceof HTMLOptGroupElement)) {
|
|
360
|
-
continue;
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
const group = createComboboxGroup({
|
|
364
|
-
autocomplete,
|
|
365
|
-
selected,
|
|
366
|
-
group: child,
|
|
367
|
-
groupOptions: [...child.children] as HTMLOptionElement[],
|
|
368
|
-
});
|
|
369
|
-
|
|
370
|
-
groups ??= [];
|
|
371
|
-
|
|
372
|
-
element.append(group.element, ...group.options);
|
|
373
|
-
groups.push(group);
|
|
374
|
-
options.push(...group.options);
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
return {element, groups, options, selected};
|
|
378
|
-
}
|
|
379
|
-
|
|
380
|
-
export function createComboboxMessage(): HTMLElement {
|
|
381
|
-
return createElement('div', {
|
|
382
|
-
aria: {
|
|
383
|
-
live: 'polite',
|
|
384
|
-
},
|
|
385
|
-
attribute: {
|
|
386
|
-
[COMBOBOX_ATTRIBUTE_MESSAGE]: '',
|
|
387
|
-
},
|
|
388
|
-
property: {
|
|
389
|
-
hidden: true,
|
|
390
|
-
role: 'status',
|
|
391
|
-
},
|
|
392
|
-
});
|
|
393
|
-
}
|
|
394
|
-
|
|
395
|
-
export function createComboboxOption(parameters: CreateOptionParameters): HTMLElement {
|
|
396
|
-
const {autocomplete, group, option} = parameters;
|
|
119
|
+
element.append(list.element, message, value);
|
|
397
120
|
|
|
398
|
-
return
|
|
399
|
-
aria: {
|
|
400
|
-
selected: !autocomplete.none && option.selected,
|
|
401
|
-
},
|
|
402
|
-
attribute: {
|
|
403
|
-
[COMBOBOX_ATTRIBUTE_OPTION]: '',
|
|
404
|
-
},
|
|
405
|
-
data: {
|
|
406
|
-
group,
|
|
407
|
-
value: option.value,
|
|
408
|
-
},
|
|
409
|
-
property: {
|
|
410
|
-
id: option.id,
|
|
411
|
-
role: 'option',
|
|
412
|
-
textContent: option.textContent,
|
|
413
|
-
},
|
|
414
|
-
});
|
|
415
|
-
}
|
|
416
|
-
|
|
417
|
-
export function createComboboxOptions(parameters: CreateOptionsParameters): HTMLElement[] {
|
|
418
|
-
const {autocomplete, group, list, options, selected} = parameters;
|
|
419
|
-
|
|
420
|
-
const items: HTMLElement[] = [];
|
|
421
|
-
|
|
422
|
-
for (let index = 0; index < options.length; index += 1) {
|
|
423
|
-
const option = options[index];
|
|
424
|
-
|
|
425
|
-
const item = createComboboxOption({autocomplete, group, index, option});
|
|
426
|
-
|
|
427
|
-
items.push(item);
|
|
428
|
-
|
|
429
|
-
if (option.selected) {
|
|
430
|
-
selected.push(item);
|
|
431
|
-
}
|
|
432
|
-
|
|
433
|
-
list.append(item);
|
|
434
|
-
}
|
|
435
|
-
|
|
436
|
-
return items;
|
|
121
|
+
return {element, filter, list, message, value};
|
|
437
122
|
}
|
|
438
123
|
|
|
439
124
|
export function createComboboxSelection(
|
|
@@ -471,17 +156,31 @@ export function createComboboxSelectionItem(
|
|
|
471
156
|
option: HTMLElement,
|
|
472
157
|
state?: OuiComboboxState,
|
|
473
158
|
): OuiComboboxSelectionItem {
|
|
159
|
+
const optionLabel = option.textContent;
|
|
160
|
+
const optionValue = getData(option, 'value', false) ?? '';
|
|
161
|
+
|
|
474
162
|
const element = createElement('li');
|
|
475
163
|
|
|
476
164
|
const localization =
|
|
477
|
-
state == null
|
|
165
|
+
state == null
|
|
166
|
+
? option.textContent
|
|
167
|
+
: getLocalization(
|
|
168
|
+
state.localizations.global,
|
|
169
|
+
state.host,
|
|
170
|
+
'remove',
|
|
171
|
+
state.localizations.component,
|
|
172
|
+
);
|
|
478
173
|
|
|
479
174
|
const button = createElement('button', {
|
|
480
175
|
aria: {
|
|
481
|
-
label:
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
:
|
|
176
|
+
label: localize(
|
|
177
|
+
localization,
|
|
178
|
+
{
|
|
179
|
+
label: optionLabel,
|
|
180
|
+
value: optionValue,
|
|
181
|
+
},
|
|
182
|
+
[optionLabel, optionValue],
|
|
183
|
+
),
|
|
485
184
|
},
|
|
486
185
|
attribute: {
|
|
487
186
|
[COMBOBOX_ATTRIBUTE_SELECTION_ITEM]: '',
|
|
@@ -531,44 +230,6 @@ export function createComboboxSelectionItems(parameters: CreateSelectionItemsPar
|
|
|
531
230
|
}
|
|
532
231
|
}
|
|
533
232
|
|
|
534
|
-
export function setComboboxDisabled(state: OuiComboboxState, value: boolean): void {
|
|
535
|
-
state.filter.element.readOnly = state.readonly || value;
|
|
536
|
-
|
|
537
|
-
setProperties('disabled', state, value);
|
|
538
|
-
}
|
|
539
|
-
|
|
540
|
-
function setProperties(
|
|
541
|
-
key: 'disabled' | 'readonly' | 'required',
|
|
542
|
-
state: OuiComboboxState,
|
|
543
|
-
value: boolean,
|
|
544
|
-
): void {
|
|
545
|
-
state[key] = value;
|
|
546
|
-
|
|
547
|
-
const elements = [state.host, state.anchor.element, state.filter.element];
|
|
548
|
-
const {length} = elements;
|
|
549
|
-
|
|
550
|
-
for (let index = 0; index < length; index += 1) {
|
|
551
|
-
const element = elements[index];
|
|
552
|
-
|
|
553
|
-
setAria(
|
|
554
|
-
element,
|
|
555
|
-
key,
|
|
556
|
-
key !== 'readonly' || !(element instanceof HTMLButtonElement) ? value : undefined,
|
|
557
|
-
);
|
|
558
|
-
}
|
|
559
|
-
}
|
|
560
|
-
|
|
561
|
-
export function setComboboxReadonly(state: OuiComboboxState, value: boolean): void {
|
|
562
|
-
state.filter.element.readOnly = state.disabled || value;
|
|
563
|
-
|
|
564
|
-
setProperties('readonly', state, value);
|
|
565
|
-
}
|
|
566
|
-
|
|
567
|
-
export function setComboboxRequired(state: OuiComboboxState, value: boolean): void {
|
|
568
|
-
setProperties('required', state, value);
|
|
569
|
-
updateComboboxValidity(state);
|
|
570
|
-
}
|
|
571
|
-
|
|
572
233
|
export function updateComboboxTabindices(state: OuiComboboxState, active?: HTMLElement): void {
|
|
573
234
|
if (active == null || state.selection == null) {
|
|
574
235
|
return;
|
|
@@ -593,24 +254,8 @@ export function updateComboboxTabindices(state: OuiComboboxState, active?: HTMLE
|
|
|
593
254
|
next.button.focus();
|
|
594
255
|
}
|
|
595
256
|
|
|
596
|
-
export function updateComboboxAnchor(state: OuiComboboxState): void {
|
|
597
|
-
if (!state.multiple) {
|
|
598
|
-
return;
|
|
599
|
-
}
|
|
600
|
-
|
|
601
|
-
const localization = getComboboxLocalization('selected', state);
|
|
602
|
-
|
|
603
|
-
setAria(
|
|
604
|
-
state.anchor.element,
|
|
605
|
-
'label',
|
|
606
|
-
typeof localization === 'function'
|
|
607
|
-
? localization(state.options.selected.length)
|
|
608
|
-
: localization.replace('{amount}', state.options.selected.length.toString()),
|
|
609
|
-
);
|
|
610
|
-
}
|
|
611
|
-
|
|
612
257
|
export function updateComboboxAutocomplete(
|
|
613
|
-
preview:
|
|
258
|
+
preview: OuiListboxPreview,
|
|
614
259
|
state: OuiComboboxState,
|
|
615
260
|
active?: HTMLElement,
|
|
616
261
|
): void {
|
|
@@ -644,51 +289,6 @@ export function updateComboboxAutocomplete(
|
|
|
644
289
|
}
|
|
645
290
|
}
|
|
646
291
|
|
|
647
|
-
export function updateComboboxMessage(state: OuiComboboxState, visible: number): void {
|
|
648
|
-
setAttribute(state.message, COMBOBOX_ATTRIBUTE_HIDDEN, visible > 0 ? '' : undefined);
|
|
649
|
-
|
|
650
|
-
if (visible === 0) {
|
|
651
|
-
const localization = getComboboxLocalization('empty', state);
|
|
652
|
-
|
|
653
|
-
state.message.textContent = typeof localization === 'function' ? localization() : localization;
|
|
654
|
-
} else {
|
|
655
|
-
const localization = getComboboxLocalization('results', state);
|
|
656
|
-
|
|
657
|
-
state.message.textContent =
|
|
658
|
-
typeof localization === 'function'
|
|
659
|
-
? localization(visible)
|
|
660
|
-
: localization.replace('{amount}', visible.toString());
|
|
661
|
-
}
|
|
662
|
-
|
|
663
|
-
state.message.hidden = false;
|
|
664
|
-
}
|
|
665
|
-
|
|
666
|
-
export function updateComboboxPreview(
|
|
667
|
-
preview: OuiComboboxPreview,
|
|
668
|
-
state: OuiComboboxState,
|
|
669
|
-
active?: HTMLElement,
|
|
670
|
-
): void {
|
|
671
|
-
const {length} = state.options.all;
|
|
672
|
-
|
|
673
|
-
for (let index = 0; index < length; index += 1) {
|
|
674
|
-
const option = state.options.all[index];
|
|
675
|
-
|
|
676
|
-
setAttribute(option, COMBOBOX_ATTRIBUTE_OPTION_ACTIVE, option === active ? '' : undefined);
|
|
677
|
-
}
|
|
678
|
-
|
|
679
|
-
state.active = active;
|
|
680
|
-
|
|
681
|
-
setAria(state.filter.element, 'activedescendant', state.floatable.open ? active?.id : undefined);
|
|
682
|
-
|
|
683
|
-
if (state.floatable.open) {
|
|
684
|
-
active?.scrollIntoView(comboboxScrollOptions);
|
|
685
|
-
}
|
|
686
|
-
|
|
687
|
-
if (preview !== 'none') {
|
|
688
|
-
updateComboboxAutocomplete(preview, state, active);
|
|
689
|
-
}
|
|
690
|
-
}
|
|
691
|
-
|
|
692
292
|
export function updateComboboxSelection(
|
|
693
293
|
state: OuiComboboxState,
|
|
694
294
|
active: HTMLElement | undefined,
|
|
@@ -701,7 +301,7 @@ export function updateComboboxSelection(
|
|
|
701
301
|
|
|
702
302
|
let options = active == null ? [] : [active];
|
|
703
303
|
|
|
704
|
-
if (selected != null) {
|
|
304
|
+
if (added && selected != null) {
|
|
705
305
|
options = selected;
|
|
706
306
|
|
|
707
307
|
const {length} = state.selection.items;
|
|
@@ -766,7 +366,12 @@ export function updateComboboxSelectionItems(state: OuiComboboxState): void {
|
|
|
766
366
|
return;
|
|
767
367
|
}
|
|
768
368
|
|
|
769
|
-
const localization =
|
|
369
|
+
const localization = getLocalization(
|
|
370
|
+
state.localizations.global,
|
|
371
|
+
state.host,
|
|
372
|
+
'remove',
|
|
373
|
+
state.localizations.component,
|
|
374
|
+
);
|
|
770
375
|
|
|
771
376
|
const {length} = state.selection.items;
|
|
772
377
|
|
|
@@ -781,12 +386,20 @@ export function updateComboboxSelectionItems(state: OuiComboboxState): void {
|
|
|
781
386
|
continue;
|
|
782
387
|
}
|
|
783
388
|
|
|
389
|
+
const optionLabel = option.textContent;
|
|
390
|
+
const optionValue = getData(option, 'value', false) ?? '';
|
|
391
|
+
|
|
784
392
|
setAria(
|
|
785
393
|
item.button,
|
|
786
394
|
'label',
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
395
|
+
localize(
|
|
396
|
+
localization,
|
|
397
|
+
{
|
|
398
|
+
label: optionLabel,
|
|
399
|
+
value: optionValue,
|
|
400
|
+
},
|
|
401
|
+
[optionLabel, optionValue],
|
|
402
|
+
),
|
|
790
403
|
);
|
|
791
404
|
}
|
|
792
405
|
}
|