@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
|
@@ -1,33 +1,49 @@
|
|
|
1
1
|
import {clamp} from '@oscarpalmer/atoms/number';
|
|
2
|
-
import {
|
|
2
|
+
import {findAncestor, getData} from '@oscarpalmer/toretto';
|
|
3
3
|
import {on} from '@oscarpalmer/toretto/event';
|
|
4
|
+
import {LISTBOX_KEYS} from '../internal/listbox/listbox.constants';
|
|
5
|
+
import {
|
|
6
|
+
applyListboxSelection,
|
|
7
|
+
filterListbox,
|
|
8
|
+
filterListboxOption,
|
|
9
|
+
filterListboxOptions,
|
|
10
|
+
toggleListboxOption,
|
|
11
|
+
} from '../internal/listbox/listbox.data';
|
|
12
|
+
import {updateListboxPreview} from '../internal/listbox/listbox.dom';
|
|
13
|
+
import {processListboxKeydown} from '../internal/listbox/listbox.event';
|
|
14
|
+
import type {OuiListboxPreview} from '../internal/listbox/listbox.model';
|
|
4
15
|
import {
|
|
5
16
|
COMBOBOX_ATTRIBUTE_SELECTION_ITEM,
|
|
6
|
-
|
|
7
|
-
COMBOBOX_KEYS_NAVIGATION,
|
|
8
|
-
COMBOBOX_KEYS_SELECTION,
|
|
9
|
-
COMBOBOX_SELECTOR_ANCHOR,
|
|
10
|
-
COMBOBOX_SELECTOR_OPTION,
|
|
11
|
-
COMBOBOX_SELECTOR_SELECTION_ITEM,
|
|
17
|
+
COMBOBOX_SELECTORS,
|
|
12
18
|
COMBOBOX_TAGNAME,
|
|
13
19
|
} from './constants.combobox';
|
|
14
20
|
import {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
} from './data.combobox';
|
|
20
|
-
import {updateComboboxPreview, updateComboboxTabindices} from './dom.combobox';
|
|
21
|
+
updateComboboxAutocomplete,
|
|
22
|
+
updateComboboxSelection,
|
|
23
|
+
updateComboboxTabindices,
|
|
24
|
+
} from './dom.combobox';
|
|
21
25
|
import type {OuiComboboxElement} from './index';
|
|
22
|
-
import {
|
|
23
|
-
import type {
|
|
26
|
+
import {hasTextSelection} from './misc.combobox';
|
|
27
|
+
import type {OuiComboboxState} from './models.combobox';
|
|
24
28
|
import {comboboxStates} from './state.combobox';
|
|
25
29
|
|
|
26
30
|
// #region Functions
|
|
27
31
|
|
|
28
|
-
export function
|
|
29
|
-
|
|
32
|
+
export function onComboboxActivation(state: OuiComboboxState): void {
|
|
33
|
+
state.floatable.show();
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function onComboboxApply(
|
|
37
|
+
state: OuiComboboxState,
|
|
38
|
+
option: HTMLElement | undefined,
|
|
39
|
+
_: string[],
|
|
40
|
+
added: boolean,
|
|
41
|
+
selected?: HTMLElement[],
|
|
42
|
+
): void {
|
|
43
|
+
updateComboboxSelection(state, option, added, selected);
|
|
44
|
+
}
|
|
30
45
|
|
|
46
|
+
export function onComboboxClickContent(event: PointerEvent, state: OuiComboboxState): void {
|
|
31
47
|
if (state == null) {
|
|
32
48
|
return;
|
|
33
49
|
}
|
|
@@ -36,25 +52,31 @@ export function onComboboxClickContent(event: PointerEvent, content: HTMLElement
|
|
|
36
52
|
return;
|
|
37
53
|
}
|
|
38
54
|
|
|
39
|
-
const option = findAncestor(event,
|
|
55
|
+
const option = findAncestor(event, COMBOBOX_SELECTORS.option);
|
|
40
56
|
|
|
41
57
|
if (!(option instanceof HTMLElement)) {
|
|
42
58
|
state.filter.element.focus();
|
|
43
59
|
} else if (state.readonly) {
|
|
44
|
-
|
|
60
|
+
onComboboxPreview('set', state, option);
|
|
45
61
|
} else {
|
|
46
|
-
|
|
62
|
+
toggleListboxOption(state, option);
|
|
47
63
|
}
|
|
48
64
|
}
|
|
49
65
|
|
|
50
|
-
|
|
51
|
-
const combobox = findAncestor(event, COMBOBOX_TAGNAME)
|
|
66
|
+
function onComboboxClickDocument(event: PointerEvent): void {
|
|
67
|
+
const combobox = findAncestor(event, COMBOBOX_TAGNAME);
|
|
52
68
|
const state = comboboxStates.map.get(combobox!);
|
|
53
69
|
|
|
54
70
|
if (combobox == null || state == null) {
|
|
55
71
|
return;
|
|
56
72
|
}
|
|
57
73
|
|
|
74
|
+
if (findAncestor(event, COMBOBOX_SELECTORS.content) != null) {
|
|
75
|
+
onComboboxClickContent(event, state);
|
|
76
|
+
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
|
|
58
80
|
const label = findAncestor(event, 'label');
|
|
59
81
|
|
|
60
82
|
if (label != null) {
|
|
@@ -81,13 +103,13 @@ export function onComboboxClickDocument(event: PointerEvent): void {
|
|
|
81
103
|
} else if (state.readonly) {
|
|
82
104
|
updateComboboxTabindices(state, option);
|
|
83
105
|
} else {
|
|
84
|
-
|
|
106
|
+
toggleListboxOption(state, option);
|
|
85
107
|
}
|
|
86
108
|
|
|
87
109
|
return;
|
|
88
110
|
}
|
|
89
111
|
|
|
90
|
-
const anchor = findAncestor(event,
|
|
112
|
+
const anchor = findAncestor(event, COMBOBOX_SELECTORS.anchor);
|
|
91
113
|
|
|
92
114
|
if (anchor != null && !state.disabled) {
|
|
93
115
|
state.floatable.show();
|
|
@@ -102,9 +124,9 @@ export function onComboboxEnter(state: OuiComboboxState): void {
|
|
|
102
124
|
}
|
|
103
125
|
|
|
104
126
|
if (hasTextSelection(state.anchor.element)) {
|
|
105
|
-
onComboboxSelection(state);
|
|
127
|
+
onComboboxSelection(state, true);
|
|
106
128
|
} else {
|
|
107
|
-
|
|
129
|
+
toggleListboxOption(state, state.active);
|
|
108
130
|
}
|
|
109
131
|
}
|
|
110
132
|
|
|
@@ -113,66 +135,48 @@ export function onComboboxEscape(state: OuiComboboxState): void {
|
|
|
113
135
|
}
|
|
114
136
|
|
|
115
137
|
export function onComboboxFilter(
|
|
116
|
-
|
|
138
|
+
preview: OuiListboxPreview,
|
|
117
139
|
state: OuiComboboxState,
|
|
118
|
-
|
|
140
|
+
update: boolean,
|
|
141
|
+
active?: HTMLElement,
|
|
119
142
|
emit?: boolean,
|
|
120
143
|
): void {
|
|
121
|
-
if (state.
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
state
|
|
144
|
+
if (state.autocomplete.none) {
|
|
145
|
+
applyListboxSelection({
|
|
146
|
+
state,
|
|
147
|
+
added: false,
|
|
148
|
+
emit: (emit ?? true) && update,
|
|
149
|
+
});
|
|
150
|
+
} else {
|
|
151
|
+
updateListboxPreview(preview, state, active);
|
|
129
152
|
}
|
|
153
|
+
}
|
|
130
154
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
let update: OuiComboboxPreview | undefined;
|
|
136
|
-
|
|
137
|
-
if (type.includes('delete')) {
|
|
138
|
-
update = 'none';
|
|
139
|
-
} else if (type.includes('insert')) {
|
|
140
|
-
update = 'typed';
|
|
141
|
-
}
|
|
155
|
+
export function onComboboxFocusout(event: FocusEvent): void {
|
|
156
|
+
setTimeout(() => {
|
|
157
|
+
const combobox = findAncestor(event, COMBOBOX_TAGNAME);
|
|
158
|
+
const state = comboboxStates.map.get(combobox!);
|
|
142
159
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
160
|
+
if (
|
|
161
|
+
combobox == null ||
|
|
162
|
+
state == null ||
|
|
163
|
+
state.disabled ||
|
|
164
|
+
state.readonly ||
|
|
165
|
+
state.type === 'select' ||
|
|
166
|
+
state.host === document.activeElement ||
|
|
167
|
+
state.host.contains(document.activeElement)
|
|
168
|
+
) {
|
|
169
|
+
return;
|
|
148
170
|
}
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
if (diff) {
|
|
152
|
-
state.filter.value = state.filter.element.value;
|
|
153
|
-
|
|
154
|
-
dispatch(state.host, 'input');
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
171
|
|
|
158
|
-
|
|
159
|
-
if (
|
|
160
|
-
state.disabled ||
|
|
161
|
-
state.readonly ||
|
|
162
|
-
state.type === 'select' ||
|
|
163
|
-
state.host === document.activeElement ||
|
|
164
|
-
state.host.contains(document.activeElement)
|
|
165
|
-
) {
|
|
166
|
-
return;
|
|
167
|
-
}
|
|
172
|
+
const option = filterListboxOption(state, state.filter.element.value, true);
|
|
168
173
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
selected: option == null ? [] : [option],
|
|
174
|
+
applyListboxSelection({
|
|
175
|
+
option,
|
|
176
|
+
state,
|
|
177
|
+
added: false,
|
|
178
|
+
selected: option == null ? [] : [option],
|
|
179
|
+
});
|
|
176
180
|
});
|
|
177
181
|
}
|
|
178
182
|
|
|
@@ -181,7 +185,7 @@ export function onComboboxInput(event: InputEvent): void {
|
|
|
181
185
|
const state = comboboxStates.map.get(combobox!);
|
|
182
186
|
|
|
183
187
|
if (combobox != null && state != null && event.target === state.filter.element) {
|
|
184
|
-
|
|
188
|
+
filterListbox(event.inputType, state);
|
|
185
189
|
}
|
|
186
190
|
}
|
|
187
191
|
|
|
@@ -193,84 +197,12 @@ export function onComboboxKeydown(event: KeyboardEvent): void {
|
|
|
193
197
|
return;
|
|
194
198
|
}
|
|
195
199
|
|
|
196
|
-
const item = findAncestor(event,
|
|
200
|
+
const item = findAncestor(event, COMBOBOX_SELECTORS.selectionItem);
|
|
197
201
|
|
|
198
202
|
if (item instanceof HTMLElement) {
|
|
199
203
|
onComboboxKeydownSelection(event, state, item);
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
onComboboxKeydownFilter(event, state);
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
function onComboboxKeydownFilter(event: KeyboardEvent, state: OuiComboboxState): void {
|
|
208
|
-
const ignore = state.disabled || state.readonly;
|
|
209
|
-
const isSelect = state.type === 'select';
|
|
210
|
-
|
|
211
|
-
let preventDefault = ignore;
|
|
212
|
-
|
|
213
|
-
switch (true) {
|
|
214
|
-
case event.key === ' ': {
|
|
215
|
-
if (!state.disabled) {
|
|
216
|
-
state.floatable.show();
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
break;
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
case event.key === 'Enter': {
|
|
223
|
-
preventDefault = state.floatable.open;
|
|
224
|
-
|
|
225
|
-
if (preventDefault) {
|
|
226
|
-
onComboboxEnter(state);
|
|
227
|
-
} else if (!ignore && state.type === 'select') {
|
|
228
|
-
state.floatable.show();
|
|
229
|
-
} else if (!ignore) {
|
|
230
|
-
state.internals.form?.requestSubmit();
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
break;
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
case event.key === 'Escape': {
|
|
237
|
-
preventDefault = false;
|
|
238
|
-
|
|
239
|
-
onComboboxEscape(state);
|
|
240
|
-
|
|
241
|
-
break;
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
case !isSelect && COMBOBOX_KEYS_SELECTION.has(event.key): {
|
|
245
|
-
if (!ignore && hasTextSelection(state.anchor.element)) {
|
|
246
|
-
onComboboxSelection(state);
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
break;
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
case COMBOBOX_KEYS_NAVIGATION.has(event.key): {
|
|
253
|
-
if (!state.disabled) {
|
|
254
|
-
onComboboxNavigation(event, state);
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
break;
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
default: {
|
|
261
|
-
preventDefault = false;
|
|
262
|
-
|
|
263
|
-
if (event.key === 'Tab') {
|
|
264
|
-
onComboboxTab(state);
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
break;
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
if (preventDefault) {
|
|
272
|
-
event.preventDefault();
|
|
273
|
-
event.stopPropagation();
|
|
204
|
+
} else {
|
|
205
|
+
processListboxKeydown(event, state);
|
|
274
206
|
}
|
|
275
207
|
}
|
|
276
208
|
|
|
@@ -279,7 +211,7 @@ export function onComboboxKeydownSelection(
|
|
|
279
211
|
state: OuiComboboxState,
|
|
280
212
|
item: HTMLElement,
|
|
281
213
|
): void {
|
|
282
|
-
if (
|
|
214
|
+
if (LISTBOX_KEYS.activation.has(event.key)) {
|
|
283
215
|
event.preventDefault();
|
|
284
216
|
|
|
285
217
|
onComboboxRemoveSelection(state, item);
|
|
@@ -338,67 +270,12 @@ export function onComboboxKeydownSelection(
|
|
|
338
270
|
}
|
|
339
271
|
}
|
|
340
272
|
|
|
341
|
-
export function
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
state.floatable.show();
|
|
348
|
-
}
|
|
349
|
-
|
|
350
|
-
const visible = getComboboxVisibleOptions(state);
|
|
351
|
-
|
|
352
|
-
if (visible.length === 0) {
|
|
353
|
-
return;
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
let next: HTMLElement | undefined;
|
|
357
|
-
|
|
358
|
-
if (skip || state.active == null) {
|
|
359
|
-
next = state.active ?? visible.at(event.key === 'ArrowDown' ? 0 : -1);
|
|
360
|
-
} else {
|
|
361
|
-
const current = visible.findIndex(option => option.id === state.active?.id);
|
|
362
|
-
|
|
363
|
-
let index: number | undefined;
|
|
364
|
-
|
|
365
|
-
switch (event.key) {
|
|
366
|
-
case 'ArrowDown':
|
|
367
|
-
case 'ArrowUp':
|
|
368
|
-
index = clamp(current + (event.key === 'ArrowDown' ? 1 : -1), 0, visible.length - 1, true);
|
|
369
|
-
break;
|
|
370
|
-
|
|
371
|
-
case 'End':
|
|
372
|
-
index = visible.length - 1;
|
|
373
|
-
break;
|
|
374
|
-
|
|
375
|
-
case 'Home':
|
|
376
|
-
index = 0;
|
|
377
|
-
break;
|
|
378
|
-
|
|
379
|
-
case 'PageDown':
|
|
380
|
-
case 'PageUp':
|
|
381
|
-
index = clamp(current + (event.key === 'PageDown' ? 10 : -10), 0, visible.length - 1);
|
|
382
|
-
break;
|
|
383
|
-
|
|
384
|
-
default:
|
|
385
|
-
break;
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
if (index != null) {
|
|
389
|
-
next = visible[index];
|
|
390
|
-
}
|
|
391
|
-
}
|
|
392
|
-
|
|
393
|
-
let preview: OuiComboboxPreview;
|
|
394
|
-
|
|
395
|
-
if (state.type === 'autocomplete' && (state.autocomplete.both || state.autocomplete.inline)) {
|
|
396
|
-
preview = 'set';
|
|
397
|
-
} else {
|
|
398
|
-
preview = 'none';
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
updateComboboxPreview(preview, state, next ?? state.active ?? visible[0]);
|
|
273
|
+
export function onComboboxPreview(
|
|
274
|
+
preview: OuiListboxPreview,
|
|
275
|
+
state: OuiComboboxState,
|
|
276
|
+
active?: HTMLElement,
|
|
277
|
+
): void {
|
|
278
|
+
updateComboboxAutocomplete(preview, state, active);
|
|
402
279
|
}
|
|
403
280
|
|
|
404
281
|
export function onComboboxRemoveSelection(state: OuiComboboxState, item: HTMLElement): void {
|
|
@@ -411,15 +288,27 @@ export function onComboboxRemoveSelection(state: OuiComboboxState, item: HTMLEle
|
|
|
411
288
|
);
|
|
412
289
|
|
|
413
290
|
if (option != null) {
|
|
414
|
-
|
|
291
|
+
toggleListboxOption(state, option);
|
|
415
292
|
}
|
|
416
293
|
}
|
|
417
294
|
|
|
418
|
-
export function
|
|
295
|
+
export function onComboboxNavigation(
|
|
296
|
+
preview: OuiListboxPreview,
|
|
297
|
+
state: OuiComboboxState,
|
|
298
|
+
active?: HTMLElement,
|
|
299
|
+
): void {
|
|
300
|
+
updateListboxPreview(preview, state, active);
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
export function onComboboxSelection(state: OuiComboboxState, hasSelection?: boolean): void {
|
|
304
|
+
if (!(hasSelection ?? hasTextSelection(state.anchor.element))) {
|
|
305
|
+
return;
|
|
306
|
+
}
|
|
307
|
+
|
|
419
308
|
state.filter.value =
|
|
420
309
|
state.anchor.element === state.filter.element ? state.filter.element.value : '';
|
|
421
310
|
|
|
422
|
-
|
|
311
|
+
toggleListboxOption(state, filterListboxOptions(state) ?? state.active);
|
|
423
312
|
}
|
|
424
313
|
|
|
425
314
|
export function onComboboxTab(state: OuiComboboxState): void {
|
|
@@ -437,12 +326,34 @@ export function onComboboxTab(state: OuiComboboxState): void {
|
|
|
437
326
|
});
|
|
438
327
|
}
|
|
439
328
|
|
|
329
|
+
export function onComboboxToggle(state: OuiComboboxState): void {
|
|
330
|
+
if (!state.multiple) {
|
|
331
|
+
state.floatable.hide();
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
export function preventComboboxActivation(state: OuiComboboxState): boolean {
|
|
336
|
+
return state.floatable.open;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
export function skipComboboxNavigation(state: OuiComboboxState): boolean {
|
|
340
|
+
if (state.floatable.open) {
|
|
341
|
+
return false;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
state.floatable.show();
|
|
345
|
+
|
|
346
|
+
return true;
|
|
347
|
+
}
|
|
348
|
+
|
|
440
349
|
// #endregion
|
|
441
350
|
|
|
442
351
|
// #region Initialization
|
|
443
352
|
|
|
444
353
|
on(document, 'click', onComboboxClickDocument);
|
|
445
354
|
|
|
355
|
+
on(document, 'focusout', onComboboxFocusout);
|
|
356
|
+
|
|
446
357
|
on(document, 'input', onComboboxInput, {
|
|
447
358
|
passive: false,
|
|
448
359
|
});
|
package/src/js/combobox/index.ts
CHANGED
|
@@ -1,12 +1,24 @@
|
|
|
1
1
|
import {parse} from '@oscarpalmer/atoms/string';
|
|
2
2
|
import {getAttribute} from '@oscarpalmer/toretto/attribute';
|
|
3
|
+
import {setListboxValue, setListboxValues} from '../internal/listbox/listbox.data';
|
|
4
|
+
import {
|
|
5
|
+
setListboxDisabled,
|
|
6
|
+
setListboxFilter,
|
|
7
|
+
setListboxLimit,
|
|
8
|
+
setListboxReadonly,
|
|
9
|
+
setListboxRequired,
|
|
10
|
+
} from '../internal/listbox/listbox.misc';
|
|
11
|
+
import type {OuiListboxLocalizations, OuiListboxType} from '../internal/listbox/listbox.model';
|
|
12
|
+
import {attachListbox, detachListbox} from '../internal/listbox/listbox.state';
|
|
13
|
+
import {updateLocalizations} from '../l10n';
|
|
3
14
|
import {COMBOBOX_TAGNAME} from './constants.combobox';
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
15
|
+
import type {OuiComboboxState} from './models.combobox';
|
|
16
|
+
import {
|
|
17
|
+
comboboxStates,
|
|
18
|
+
createComboboxState,
|
|
19
|
+
onAttachCombobox,
|
|
20
|
+
onDetachCombobox,
|
|
21
|
+
} from './state.combobox';
|
|
10
22
|
|
|
11
23
|
// #region Types
|
|
12
24
|
|
|
@@ -39,7 +51,7 @@ export class OuiComboboxElement extends HTMLElement {
|
|
|
39
51
|
*/
|
|
40
52
|
set disabled(value: boolean) {
|
|
41
53
|
if (typeof value === 'boolean' && value !== this.disabled) {
|
|
42
|
-
|
|
54
|
+
setListboxDisabled(this.#state, value);
|
|
43
55
|
}
|
|
44
56
|
}
|
|
45
57
|
|
|
@@ -54,7 +66,7 @@ export class OuiComboboxElement extends HTMLElement {
|
|
|
54
66
|
* Set the filter value
|
|
55
67
|
*/
|
|
56
68
|
set filter(value: string) {
|
|
57
|
-
|
|
69
|
+
setListboxFilter(this.#state, value);
|
|
58
70
|
}
|
|
59
71
|
|
|
60
72
|
/**
|
|
@@ -68,7 +80,7 @@ export class OuiComboboxElement extends HTMLElement {
|
|
|
68
80
|
* Set the maximum number of selected options
|
|
69
81
|
*/
|
|
70
82
|
set max(value: number) {
|
|
71
|
-
|
|
83
|
+
setListboxLimit('max', this.#state, value);
|
|
72
84
|
}
|
|
73
85
|
|
|
74
86
|
/**
|
|
@@ -82,7 +94,7 @@ export class OuiComboboxElement extends HTMLElement {
|
|
|
82
94
|
* Set the minimum number of selected options
|
|
83
95
|
*/
|
|
84
96
|
set min(value: number) {
|
|
85
|
-
|
|
97
|
+
setListboxLimit('min', this.#state, value);
|
|
86
98
|
}
|
|
87
99
|
|
|
88
100
|
/**
|
|
@@ -111,7 +123,7 @@ export class OuiComboboxElement extends HTMLElement {
|
|
|
111
123
|
*/
|
|
112
124
|
set readonly(value: boolean) {
|
|
113
125
|
if (typeof value === 'boolean' && value !== this.readonly) {
|
|
114
|
-
|
|
126
|
+
setListboxReadonly(this.#state, value);
|
|
115
127
|
}
|
|
116
128
|
}
|
|
117
129
|
|
|
@@ -127,7 +139,7 @@ export class OuiComboboxElement extends HTMLElement {
|
|
|
127
139
|
*/
|
|
128
140
|
set required(value: boolean) {
|
|
129
141
|
if (typeof value === 'boolean' && value !== this.required) {
|
|
130
|
-
|
|
142
|
+
setListboxRequired(this.#state, value);
|
|
131
143
|
}
|
|
132
144
|
}
|
|
133
145
|
|
|
@@ -141,7 +153,7 @@ export class OuiComboboxElement extends HTMLElement {
|
|
|
141
153
|
/**
|
|
142
154
|
* Type of combobox
|
|
143
155
|
*/
|
|
144
|
-
get type():
|
|
156
|
+
get type(): OuiListboxType {
|
|
145
157
|
return this.#state.type;
|
|
146
158
|
}
|
|
147
159
|
|
|
@@ -156,7 +168,7 @@ export class OuiComboboxElement extends HTMLElement {
|
|
|
156
168
|
* Set the value
|
|
157
169
|
*/
|
|
158
170
|
set value(value: unknown) {
|
|
159
|
-
|
|
171
|
+
setListboxValue(this.#state, value);
|
|
160
172
|
}
|
|
161
173
|
|
|
162
174
|
/**
|
|
@@ -169,8 +181,8 @@ export class OuiComboboxElement extends HTMLElement {
|
|
|
169
181
|
/**
|
|
170
182
|
* Set the values
|
|
171
183
|
*/
|
|
172
|
-
set values(
|
|
173
|
-
|
|
184
|
+
set values(values: unknown[]) {
|
|
185
|
+
setListboxValues(this.#state, values);
|
|
174
186
|
}
|
|
175
187
|
|
|
176
188
|
constructor() {
|
|
@@ -191,7 +203,7 @@ export class OuiComboboxElement extends HTMLElement {
|
|
|
191
203
|
|
|
192
204
|
case 'max':
|
|
193
205
|
case 'min':
|
|
194
|
-
|
|
206
|
+
setListboxLimit(name, this.#state, value);
|
|
195
207
|
break;
|
|
196
208
|
|
|
197
209
|
case 'value':
|
|
@@ -207,20 +219,20 @@ export class OuiComboboxElement extends HTMLElement {
|
|
|
207
219
|
* Clear all selected options
|
|
208
220
|
*/
|
|
209
221
|
clear(): void {
|
|
210
|
-
|
|
222
|
+
setListboxValues(this.#state, []);
|
|
211
223
|
}
|
|
212
224
|
|
|
213
225
|
connectedCallback(): void {
|
|
214
226
|
if (this.#state == null) {
|
|
215
227
|
this.#initialize();
|
|
216
228
|
} else {
|
|
217
|
-
|
|
229
|
+
attachListbox(this.#state, comboboxStates, onAttachCombobox);
|
|
218
230
|
}
|
|
219
231
|
}
|
|
220
232
|
|
|
221
233
|
disconnectedCallback(): void {
|
|
222
234
|
if (this.#state != null) {
|
|
223
|
-
|
|
235
|
+
detachListbox(this.#state, comboboxStates, onDetachCombobox);
|
|
224
236
|
}
|
|
225
237
|
}
|
|
226
238
|
|
|
@@ -229,7 +241,7 @@ export class OuiComboboxElement extends HTMLElement {
|
|
|
229
241
|
}
|
|
230
242
|
|
|
231
243
|
formResetCallback(): void {
|
|
232
|
-
|
|
244
|
+
setListboxValues(this.#state, this.#state.values.initial);
|
|
233
245
|
}
|
|
234
246
|
|
|
235
247
|
formStateRestoreCallback(state: string | File | FormData, reason: unknown): void {
|
|
@@ -246,7 +258,7 @@ export class OuiComboboxElement extends HTMLElement {
|
|
|
246
258
|
if (this.#state == null) {
|
|
247
259
|
this.#restored = parsed;
|
|
248
260
|
} else {
|
|
249
|
-
|
|
261
|
+
setListboxValues(this.#state, parsed);
|
|
250
262
|
}
|
|
251
263
|
}
|
|
252
264
|
|
|
@@ -256,26 +268,27 @@ export class OuiComboboxElement extends HTMLElement {
|
|
|
256
268
|
* @param language Language code
|
|
257
269
|
* @param localizations Localizations for language
|
|
258
270
|
*/
|
|
259
|
-
setLocalizations(language: string, localizations: Partial<
|
|
271
|
+
setLocalizations(language: string, localizations: Partial<OuiListboxLocalizations>): void;
|
|
260
272
|
|
|
261
273
|
/**
|
|
262
274
|
* Set combobox localizations for one or more languages
|
|
263
275
|
*
|
|
264
276
|
* @param localizations Localizations for one or more languages
|
|
265
277
|
*/
|
|
266
|
-
setLocalizations(localizations: Record<string, Partial<
|
|
278
|
+
setLocalizations(localizations: Record<string, Partial<OuiListboxLocalizations>>): void;
|
|
267
279
|
|
|
268
280
|
setLocalizations(
|
|
269
|
-
first: string | Record<string, Partial<
|
|
270
|
-
second?: Partial<
|
|
281
|
+
first: string | Record<string, Partial<OuiListboxLocalizations>>,
|
|
282
|
+
second?: Partial<OuiListboxLocalizations>,
|
|
271
283
|
): void {
|
|
272
|
-
|
|
284
|
+
updateLocalizations(
|
|
285
|
+
this.#state.localizations.global,
|
|
273
286
|
typeof first === 'string'
|
|
274
287
|
? {
|
|
275
288
|
[first]: second!,
|
|
276
289
|
}
|
|
277
290
|
: first,
|
|
278
|
-
this.#state.localizations,
|
|
291
|
+
this.#state.localizations.component,
|
|
279
292
|
);
|
|
280
293
|
}
|
|
281
294
|
|
|
@@ -285,7 +298,7 @@ export class OuiComboboxElement extends HTMLElement {
|
|
|
285
298
|
this.#state = createComboboxState(this, this.#internals);
|
|
286
299
|
|
|
287
300
|
if (this.#restored != null) {
|
|
288
|
-
|
|
301
|
+
setListboxValues(this.#state, this.#restored);
|
|
289
302
|
|
|
290
303
|
this.#restored = undefined;
|
|
291
304
|
}
|
|
@@ -302,6 +315,6 @@ customElements.define(COMBOBOX_TAGNAME, OuiComboboxElement);
|
|
|
302
315
|
|
|
303
316
|
// #region Exports
|
|
304
317
|
|
|
305
|
-
export {setComboboxLocalizations} from './
|
|
318
|
+
export {setComboboxLocalizations} from './misc.combobox';
|
|
306
319
|
|
|
307
320
|
// #endregion
|