@oscarpalmer/oui 0.33.0 → 0.35.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/js/combobox/constants.combobox.d.mts +2 -0
- package/dist/js/combobox/constants.combobox.mjs +46 -0
- package/dist/js/combobox/data.combobox.d.mts +18 -0
- package/dist/js/combobox/data.combobox.mjs +2 -0
- package/dist/js/combobox/dom.combobox.d.mts +110 -0
- package/dist/js/combobox/dom.combobox.mjs +2 -0
- package/dist/js/combobox/event.combobox.d.mts +17 -0
- package/dist/js/combobox/event.combobox.mjs +2 -0
- package/dist/js/combobox/form.combobox.d.mts +6 -0
- package/dist/js/combobox/form.combobox.mjs +2 -0
- package/dist/js/combobox/index.d.mts +2 -0
- package/dist/js/combobox/index.mjs +195 -0
- package/dist/js/combobox/misc.combobox.d.mts +2 -0
- package/dist/js/combobox/misc.combobox.mjs +2 -0
- package/dist/js/combobox/models.combobox.d.mts +2 -0
- package/dist/js/combobox/models.combobox.mjs +1 -0
- package/dist/js/combobox/state.combobox.d.mts +13 -0
- package/dist/js/combobox/state.combobox.mjs +2 -0
- package/dist/js/constants.combobox-h_kyDegw.d.mts +248 -0
- package/dist/js/data.combobox-B8HMkDOh.mjs +1030 -0
- package/dist/js/dialog.mjs +3 -2
- package/dist/js/floatable/floatable.embedded.mjs +4 -4
- package/dist/js/focus-trap/focus-trap.embedded.mjs +3 -3
- package/dist/js/index.d.mts +14 -643
- package/dist/js/index.mjs +19 -4875
- package/dist/js/internal/draggable.mjs +6 -6
- package/dist/js/internal/navigable.mjs +3 -3
- package/dist/js/l10n.d.mts +20 -0
- package/dist/js/l10n.mjs +80 -0
- package/dist/js/menu.d.mts +1 -1
- package/dist/js/menu.mjs +3 -2
- package/dist/js/movable/movable.embedded.mjs +3 -3
- package/dist/js/popover.mjs +1 -1
- package/dist/js/resizable/resizable.embedded.mjs +7 -7
- package/dist/js/sortable/sortable.embedded.mjs +7 -6
- package/dist/js/splitter.mjs +7 -13
- package/dist/js/toolbar.d.mts +1 -1
- package/dist/js/tooltip.mjs +3 -3
- package/package.json +4 -4
- package/src/js/combobox/constants.combobox.ts +62 -0
- package/src/js/combobox/data.combobox.ts +236 -0
- package/src/js/combobox/dom.combobox.ts +825 -0
- package/src/js/combobox/event.combobox.ts +454 -0
- package/src/js/combobox/form.combobox.ts +116 -0
- package/src/js/combobox/index.ts +313 -0
- package/src/js/combobox/misc.combobox.ts +188 -0
- package/src/js/combobox/models.combobox.ts +94 -0
- package/src/js/combobox/state.combobox.ts +247 -0
- package/src/js/index.ts +1 -1
- package/src/js/internal/draggable.ts +3 -3
- package/src/js/l10n.ts +192 -0
- package/src/js/movable/movable.embedded.ts +2 -2
- package/src/js/resizable/resizable.embedded.ts +3 -3
- package/src/js/sortable/sortable.embedded.ts +2 -2
- package/src/js/splitter.ts +2 -2
- package/dist/js/combobox.d.mts +0 -91
- package/dist/js/combobox.mjs +0 -797
- package/src/js/combobox.ts +0 -2410
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
import {setAria} from '@oscarpalmer/toretto/aria';
|
|
2
|
+
import {getAttribute, setAttribute} from '@oscarpalmer/toretto/attribute';
|
|
3
|
+
import {getData} from '@oscarpalmer/toretto/data';
|
|
4
|
+
import {on} from '@oscarpalmer/toretto/event';
|
|
5
|
+
import {createEmbeddedFloatable} from '../floatable/floatable.embedded';
|
|
6
|
+
import {getLocalizations} from '../l10n';
|
|
7
|
+
import {
|
|
8
|
+
COMBOBOX_MESSAGE_LABEL,
|
|
9
|
+
COMBOBOX_MESSAGE_SELECT,
|
|
10
|
+
COMBOBOX_TYPES,
|
|
11
|
+
} from './constants.combobox';
|
|
12
|
+
import {filterComboboxOptions} from './data.combobox';
|
|
13
|
+
import {
|
|
14
|
+
createComboboxAnchor,
|
|
15
|
+
createComboboxContent,
|
|
16
|
+
setComboboxDisabled,
|
|
17
|
+
setComboboxReadonly,
|
|
18
|
+
setComboboxRequired,
|
|
19
|
+
updateComboboxMessage,
|
|
20
|
+
updateComboboxPreview,
|
|
21
|
+
updateComboboxSelectionItems,
|
|
22
|
+
} from './dom.combobox';
|
|
23
|
+
import {onComboboxClickContent, onComboboxFocusout} from './event.combobox';
|
|
24
|
+
import {updateComboboxForm} from './form.combobox';
|
|
25
|
+
import type {OuiComboboxElement} from './index';
|
|
26
|
+
import {
|
|
27
|
+
generateComboboxIds,
|
|
28
|
+
getComboboxAttributeValue,
|
|
29
|
+
getComboboxAutoComplete,
|
|
30
|
+
getComboboxBooleanAria,
|
|
31
|
+
getComboboxId,
|
|
32
|
+
getComboboxVisibleOptions,
|
|
33
|
+
setComboboxLimit,
|
|
34
|
+
} from './misc.combobox';
|
|
35
|
+
import type {OuiComboboxLocalizations, OuiComboboxState} from './models.combobox';
|
|
36
|
+
|
|
37
|
+
// #region Functions
|
|
38
|
+
|
|
39
|
+
export function attachCombobox(state: OuiComboboxState): void {
|
|
40
|
+
const {anchor, content, filter, label, listeners, select} = state;
|
|
41
|
+
|
|
42
|
+
label.element.htmlFor = filter.element.id;
|
|
43
|
+
label.element.id = `${state.id}_label`;
|
|
44
|
+
|
|
45
|
+
select.hidden = true;
|
|
46
|
+
|
|
47
|
+
select.insertAdjacentElement('afterend', anchor.container ?? anchor.element);
|
|
48
|
+
(anchor.container ?? anchor.element).insertAdjacentElement('afterend', content);
|
|
49
|
+
|
|
50
|
+
select.remove();
|
|
51
|
+
|
|
52
|
+
state.floatable = createEmbeddedFloatable(anchor.container ?? anchor.element, content, {
|
|
53
|
+
position: 'below-start',
|
|
54
|
+
reusable: false,
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
state.floatable.update();
|
|
58
|
+
|
|
59
|
+
listeners.push(
|
|
60
|
+
on(state.host, 'focusout', () => {
|
|
61
|
+
setTimeout(() => {
|
|
62
|
+
onComboboxFocusout(state);
|
|
63
|
+
});
|
|
64
|
+
}),
|
|
65
|
+
on(content, 'click', event => {
|
|
66
|
+
onComboboxClickContent(event, content);
|
|
67
|
+
}),
|
|
68
|
+
on(content, 'toggle', () => {
|
|
69
|
+
setAria(anchor.element, 'expanded', state.floatable.open);
|
|
70
|
+
|
|
71
|
+
setAria(
|
|
72
|
+
filter.element,
|
|
73
|
+
'activedescendant',
|
|
74
|
+
state.floatable.open ? state.active?.id : undefined,
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
if (state.floatable.open) {
|
|
78
|
+
filter.element.focus();
|
|
79
|
+
}
|
|
80
|
+
}),
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
comboboxStates.map.set(state.host, state);
|
|
84
|
+
comboboxStates.map.set(state.content, state);
|
|
85
|
+
comboboxStates.set.add(state);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export function createComboboxState(
|
|
89
|
+
element: OuiComboboxElement,
|
|
90
|
+
internals: ElementInternals,
|
|
91
|
+
): OuiComboboxState {
|
|
92
|
+
const select = element.querySelector('select');
|
|
93
|
+
|
|
94
|
+
if (select == null || select.id === '') {
|
|
95
|
+
throw new Error(COMBOBOX_MESSAGE_SELECT);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const label = element.querySelector(`label[for="${select.id}"]`) as HTMLLabelElement;
|
|
99
|
+
|
|
100
|
+
if (label == null) {
|
|
101
|
+
throw new Error(COMBOBOX_MESSAGE_LABEL);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
element.id = select.id;
|
|
105
|
+
|
|
106
|
+
setAttribute(element, 'name', select.name === '' ? select.id : select.name);
|
|
107
|
+
|
|
108
|
+
const disabled = getComboboxBooleanAria(element, 'disabled') || select.disabled;
|
|
109
|
+
const multiple = element.multiple || select.multiple;
|
|
110
|
+
const readonly = getComboboxBooleanAria(element, 'readonly');
|
|
111
|
+
const required = getComboboxBooleanAria(element, 'required') || select.required;
|
|
112
|
+
|
|
113
|
+
const id = getComboboxId();
|
|
114
|
+
const type = multiple
|
|
115
|
+
? 'select'
|
|
116
|
+
: getComboboxAttributeValue(element, 'type', COMBOBOX_TYPES, 'select');
|
|
117
|
+
|
|
118
|
+
const autocomplete = getComboboxAutoComplete(element, type === 'select');
|
|
119
|
+
|
|
120
|
+
const labelId = label.id;
|
|
121
|
+
|
|
122
|
+
label.htmlFor = id;
|
|
123
|
+
label.id = `${id}_label`;
|
|
124
|
+
|
|
125
|
+
generateComboboxIds(id, select);
|
|
126
|
+
|
|
127
|
+
const anchor = createComboboxAnchor({autocomplete, id, label, multiple, select, type});
|
|
128
|
+
const content = createComboboxContent({autocomplete, id, label, multiple, select, type});
|
|
129
|
+
|
|
130
|
+
const values =
|
|
131
|
+
content.list.selected.length === 0
|
|
132
|
+
? ['']
|
|
133
|
+
: content.list.selected.map(option => getData(option, 'value', false) ?? '');
|
|
134
|
+
|
|
135
|
+
const state: OuiComboboxState = {
|
|
136
|
+
autocomplete,
|
|
137
|
+
disabled,
|
|
138
|
+
id,
|
|
139
|
+
internals,
|
|
140
|
+
multiple,
|
|
141
|
+
readonly,
|
|
142
|
+
required,
|
|
143
|
+
select,
|
|
144
|
+
type,
|
|
145
|
+
anchor: {
|
|
146
|
+
container: anchor.container,
|
|
147
|
+
element: anchor.element,
|
|
148
|
+
},
|
|
149
|
+
active: content.list.selected[0],
|
|
150
|
+
content: content.element,
|
|
151
|
+
filter: {
|
|
152
|
+
element: content.filter?.element ?? (anchor.element as HTMLInputElement),
|
|
153
|
+
value: '',
|
|
154
|
+
},
|
|
155
|
+
floatable: undefined as never,
|
|
156
|
+
groups: content.list.groups,
|
|
157
|
+
host: element,
|
|
158
|
+
label: {
|
|
159
|
+
element: label,
|
|
160
|
+
id: labelId,
|
|
161
|
+
},
|
|
162
|
+
listeners: [],
|
|
163
|
+
localizations: {},
|
|
164
|
+
message: content.message,
|
|
165
|
+
name: element.name,
|
|
166
|
+
options: {
|
|
167
|
+
all: content.list.options,
|
|
168
|
+
selected: content.list.selected,
|
|
169
|
+
},
|
|
170
|
+
selection: anchor.selection,
|
|
171
|
+
values: {
|
|
172
|
+
current: values.slice(),
|
|
173
|
+
initial: values.slice(),
|
|
174
|
+
},
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
attachCombobox(state);
|
|
178
|
+
|
|
179
|
+
setComboboxDisabled(state, disabled);
|
|
180
|
+
setComboboxLimit('max', state, getAttribute(element, 'max'));
|
|
181
|
+
setComboboxLimit('min', state, getAttribute(element, 'min'));
|
|
182
|
+
setComboboxReadonly(state, readonly);
|
|
183
|
+
setComboboxRequired(state, required);
|
|
184
|
+
|
|
185
|
+
filterComboboxOptions(state);
|
|
186
|
+
|
|
187
|
+
if (content.list.selected.length > 0) {
|
|
188
|
+
updateComboboxPreview('set', state, content.list.selected[0]);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
updateComboboxForm(state, state.values.current, false);
|
|
192
|
+
updateComboboxMessage(state, getComboboxVisibleOptions(state).length);
|
|
193
|
+
updateComboboxSelectionItems(state);
|
|
194
|
+
|
|
195
|
+
return state;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
export function detachCombobox(state: OuiComboboxState): void {
|
|
199
|
+
const {content, floatable, host, label, select} = state;
|
|
200
|
+
|
|
201
|
+
const listeners = state.listeners.splice(0);
|
|
202
|
+
const {length} = listeners;
|
|
203
|
+
|
|
204
|
+
for (let index = 0; index < length; index += 1) {
|
|
205
|
+
listeners[index]();
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
floatable.destroy();
|
|
209
|
+
|
|
210
|
+
const anchor = state.anchor.container ?? state.anchor.element;
|
|
211
|
+
|
|
212
|
+
anchor.insertAdjacentElement('beforebegin', select);
|
|
213
|
+
|
|
214
|
+
anchor.remove();
|
|
215
|
+
content.remove();
|
|
216
|
+
|
|
217
|
+
label.element.htmlFor = select.id;
|
|
218
|
+
label.element.id = state.label.id;
|
|
219
|
+
|
|
220
|
+
select.hidden = false;
|
|
221
|
+
|
|
222
|
+
comboboxStates.map.delete(host);
|
|
223
|
+
comboboxStates.map.delete(content);
|
|
224
|
+
comboboxStates.set.delete(state);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
// #endregion
|
|
228
|
+
|
|
229
|
+
// #region Variables
|
|
230
|
+
|
|
231
|
+
export const comboboxLocalizations = getLocalizations<OuiComboboxLocalizations>({
|
|
232
|
+
empty: 'No results found',
|
|
233
|
+
input: 'Please enter a value',
|
|
234
|
+
invalid: 'Please select an option from the list',
|
|
235
|
+
max: max => `Please select fewer options (maximum is ${max})`,
|
|
236
|
+
min: min => `Please select more options (minimum is ${min})`,
|
|
237
|
+
remove: label => `Remove ${label}`,
|
|
238
|
+
results: amount => `${amount} results available`,
|
|
239
|
+
selected: amount => `${amount} selected`,
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
export const comboboxStates = {
|
|
243
|
+
map: new WeakMap<HTMLElement, OuiComboboxState>(),
|
|
244
|
+
set: new Set<OuiComboboxState>(),
|
|
245
|
+
};
|
|
246
|
+
|
|
247
|
+
// #endregion
|
package/src/js/index.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type {EventPosition, PlainObject} from '@oscarpalmer/atoms/models';
|
|
2
2
|
import {clamp} from '@oscarpalmer/atoms/number';
|
|
3
3
|
import {getAttribute, setAttribute} from '@oscarpalmer/toretto/attribute';
|
|
4
|
-
import {dispatch,
|
|
4
|
+
import {dispatch, getEventPosition, on} from '@oscarpalmer/toretto/event';
|
|
5
5
|
import {findAncestor} from '@oscarpalmer/toretto/find';
|
|
6
6
|
import {isHTMLOrSVGElement} from '@oscarpalmer/toretto/is';
|
|
7
7
|
import {setStyle, setStyles, toggleStyles, type StyleToggler} from '@oscarpalmer/toretto/style';
|
|
@@ -392,7 +392,7 @@ function onPointerdown(event: MouseEvent | TouchEvent): void {
|
|
|
392
392
|
const dragged = item.state.options.getDragged();
|
|
393
393
|
const rectangle = dragged.getBoundingClientRect();
|
|
394
394
|
|
|
395
|
-
const position =
|
|
395
|
+
const position = getEventPosition(event) ?? {x: 0, y: 0};
|
|
396
396
|
|
|
397
397
|
current = item;
|
|
398
398
|
|
|
@@ -442,7 +442,7 @@ function onPointermove(event: MouseEvent | TouchEvent): void {
|
|
|
442
442
|
return;
|
|
443
443
|
}
|
|
444
444
|
|
|
445
|
-
const position =
|
|
445
|
+
const position = getEventPosition(event);
|
|
446
446
|
|
|
447
447
|
if (position == null) {
|
|
448
448
|
return;
|
package/src/js/l10n.ts
ADDED
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import type {GenericCallback} from '@oscarpalmer/atoms/models';
|
|
2
|
+
import {getString} from '@oscarpalmer/atoms/string';
|
|
3
|
+
|
|
4
|
+
// #region Types
|
|
5
|
+
|
|
6
|
+
type LocalizationParameters<Localization> = Localization extends GenericCallback
|
|
7
|
+
? Parameters<Localization>
|
|
8
|
+
: never;
|
|
9
|
+
|
|
10
|
+
type OuiLocalizationValues = Record<string, string | GenericCallback>;
|
|
11
|
+
|
|
12
|
+
export class OuiLocalizations<Localizations extends OuiLocalizationValues> {
|
|
13
|
+
readonly defaults: Localizations;
|
|
14
|
+
|
|
15
|
+
readonly keys: Set<keyof Localizations>;
|
|
16
|
+
|
|
17
|
+
readonly values: Record<string, Partial<Localizations>> = {};
|
|
18
|
+
|
|
19
|
+
constructor(defaults: Localizations) {
|
|
20
|
+
this.defaults = defaults;
|
|
21
|
+
this.keys = new Set(Object.keys(defaults) as Array<keyof Localizations>);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
get<Key extends keyof Localizations>(
|
|
25
|
+
element: Element,
|
|
26
|
+
key: Key,
|
|
27
|
+
localizations: Record<string, Partial<Localizations>>,
|
|
28
|
+
): string | GenericCallback {
|
|
29
|
+
return getLocalization(this, element, key, localizations);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
set(language: string, localizations: Partial<Localizations>): void;
|
|
33
|
+
|
|
34
|
+
set(localizations: Record<string, Partial<Localizations>>): void;
|
|
35
|
+
|
|
36
|
+
set(
|
|
37
|
+
first: string | Record<string, Partial<Localizations>>,
|
|
38
|
+
second?: Partial<Localizations>,
|
|
39
|
+
): void {
|
|
40
|
+
updateLocalizations(
|
|
41
|
+
this,
|
|
42
|
+
typeof first === 'string'
|
|
43
|
+
? {
|
|
44
|
+
[first]: second!,
|
|
45
|
+
}
|
|
46
|
+
: first,
|
|
47
|
+
this.values,
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// #endregion
|
|
53
|
+
|
|
54
|
+
// #region Functions
|
|
55
|
+
|
|
56
|
+
export function getLanguage(element: Element): string {
|
|
57
|
+
return (
|
|
58
|
+
element.closest('[lang]')?.getAttribute('lang') ?? document.documentElement.lang
|
|
59
|
+
).toLowerCase();
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export function getLocalization<
|
|
63
|
+
Localizations extends OuiLocalizationValues,
|
|
64
|
+
Key extends keyof Localizations,
|
|
65
|
+
>(
|
|
66
|
+
localizations: OuiLocalizations<Localizations>,
|
|
67
|
+
element: Element,
|
|
68
|
+
key: Key,
|
|
69
|
+
value: Record<string, Partial<Localizations>>,
|
|
70
|
+
): Localizations[Key] | GenericCallback {
|
|
71
|
+
const language = getLanguage(element);
|
|
72
|
+
|
|
73
|
+
const values = [value, localizations.values];
|
|
74
|
+
const {length} = values;
|
|
75
|
+
|
|
76
|
+
let localization: Localizations[Key] | undefined;
|
|
77
|
+
let shortLanguage: string | undefined;
|
|
78
|
+
|
|
79
|
+
for (let index = 0; index < length; index += 1) {
|
|
80
|
+
const value = values[index];
|
|
81
|
+
|
|
82
|
+
localization = value?.[language]?.[key];
|
|
83
|
+
|
|
84
|
+
if (localization != null) {
|
|
85
|
+
break;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
shortLanguage ??= language.split('-')[0];
|
|
89
|
+
|
|
90
|
+
if (shortLanguage === language) {
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
localization = value?.[shortLanguage]?.[key];
|
|
95
|
+
|
|
96
|
+
if (localization != null) {
|
|
97
|
+
break;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
return localization ?? localizations.defaults[key];
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export function getLocalizations<Localizations extends OuiLocalizationValues>(
|
|
105
|
+
defaults: Localizations,
|
|
106
|
+
): OuiLocalizations<Localizations> {
|
|
107
|
+
return new OuiLocalizations(defaults);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export function localize<
|
|
111
|
+
Localizations extends OuiLocalizationValues,
|
|
112
|
+
Key extends keyof Localizations,
|
|
113
|
+
Localization extends Localizations[Key],
|
|
114
|
+
>(
|
|
115
|
+
localization: Localization,
|
|
116
|
+
data: Record<string, unknown>,
|
|
117
|
+
parameters: LocalizationParameters<Localization>,
|
|
118
|
+
): string {
|
|
119
|
+
if (typeof localization === 'function') {
|
|
120
|
+
return localization(...parameters);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const keys = Object.keys(data);
|
|
124
|
+
const {length} = keys;
|
|
125
|
+
|
|
126
|
+
let localized = localization as string;
|
|
127
|
+
|
|
128
|
+
for (let index = 0; index < length; index += 1) {
|
|
129
|
+
const key = keys[index];
|
|
130
|
+
const value = data[key];
|
|
131
|
+
|
|
132
|
+
localized = localized.replaceAll(`{${key}}`, getString(value));
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
return localized;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
export function updateLocalizations<Localizations extends OuiLocalizationValues>(
|
|
139
|
+
instance: OuiLocalizations<Localizations>,
|
|
140
|
+
values: Record<string, Partial<Localizations>>,
|
|
141
|
+
destination?: Record<string, Partial<Localizations>>,
|
|
142
|
+
onAfter?: () => void,
|
|
143
|
+
): void {
|
|
144
|
+
if (typeof values !== 'object' || values == null) {
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
const localizations = destination ?? instance.values;
|
|
149
|
+
|
|
150
|
+
const languages = Object.keys(values);
|
|
151
|
+
const languagesLength = languages.length;
|
|
152
|
+
|
|
153
|
+
let updated = false;
|
|
154
|
+
|
|
155
|
+
for (let languagesIndex = 0; languagesIndex < languagesLength; languagesIndex += 1) {
|
|
156
|
+
const language = languages[languagesIndex];
|
|
157
|
+
const languageValue = values[language];
|
|
158
|
+
|
|
159
|
+
if (typeof languageValue !== 'object' || languageValue == null) {
|
|
160
|
+
continue;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
const normalizedLanguage = language.toLowerCase();
|
|
164
|
+
|
|
165
|
+
localizations[normalizedLanguage] ??= {};
|
|
166
|
+
|
|
167
|
+
const keys = Object.keys(languageValue);
|
|
168
|
+
const keysLength = keys.length;
|
|
169
|
+
|
|
170
|
+
for (let keysIndex = 0; keysIndex < keysLength; keysIndex += 1) {
|
|
171
|
+
const key = keys[keysIndex];
|
|
172
|
+
const keyValue = languageValue[key];
|
|
173
|
+
|
|
174
|
+
const normalizedKey = key.toLowerCase() as keyof Localizations;
|
|
175
|
+
|
|
176
|
+
if (
|
|
177
|
+
instance.keys.has(normalizedKey) &&
|
|
178
|
+
(typeof keyValue === 'string' || typeof keyValue === 'function')
|
|
179
|
+
) {
|
|
180
|
+
updated = true;
|
|
181
|
+
|
|
182
|
+
localizations[normalizedLanguage][normalizedKey] = keyValue as never;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
if (updated && typeof onAfter === 'function') {
|
|
188
|
+
onAfter();
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// #endregion
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type {EventPosition, PlainObject} from '@oscarpalmer/atoms/models';
|
|
2
2
|
import {setAttribute} from '@oscarpalmer/toretto/attribute';
|
|
3
|
-
import {dispatch,
|
|
3
|
+
import {dispatch, getEventPosition, on} from '@oscarpalmer/toretto/event';
|
|
4
4
|
import {isHTMLOrSVGElement} from '@oscarpalmer/toretto/is';
|
|
5
5
|
import {getStyles, setStyle, setStyles} from '@oscarpalmer/toretto/style';
|
|
6
6
|
import {attributable} from '../internal/attributable';
|
|
@@ -202,7 +202,7 @@ function onEnd(
|
|
|
202
202
|
const dispatched = dispatch(state.element, 'movable:end', {
|
|
203
203
|
detail: {
|
|
204
204
|
from: {...globals.original},
|
|
205
|
-
to:
|
|
205
|
+
to: getEventPosition(event),
|
|
206
206
|
},
|
|
207
207
|
});
|
|
208
208
|
|
|
@@ -2,7 +2,7 @@ import {isPlainObject} from '@oscarpalmer/atoms/is';
|
|
|
2
2
|
import type {EventPosition} from '@oscarpalmer/atoms/models';
|
|
3
3
|
import {getNumber} from '@oscarpalmer/atoms/number';
|
|
4
4
|
import {getAttribute, setAttribute} from '@oscarpalmer/toretto/attribute';
|
|
5
|
-
import {dispatch,
|
|
5
|
+
import {dispatch, getEventPosition, on} from '@oscarpalmer/toretto/event';
|
|
6
6
|
import {findAncestor} from '@oscarpalmer/toretto/find';
|
|
7
7
|
import {isHTMLOrSVGElement} from '@oscarpalmer/toretto/is';
|
|
8
8
|
import {setStyles, toggleStyles, type StyleToggler} from '@oscarpalmer/toretto/style';
|
|
@@ -279,7 +279,7 @@ function onPointerdown(event: MouseEvent | TouchEvent): void {
|
|
|
279
279
|
const handle = findAncestor(event, SELECTOR_HANDLE);
|
|
280
280
|
const element = handle && findAncestor(handle, SELECTOR);
|
|
281
281
|
const stored = element && items.get(element as HTMLElement);
|
|
282
|
-
const position =
|
|
282
|
+
const position = getEventPosition(event);
|
|
283
283
|
|
|
284
284
|
if (stored == null || position == null) {
|
|
285
285
|
return;
|
|
@@ -309,7 +309,7 @@ function onPointermove(event: MouseEvent | TouchEvent): void {
|
|
|
309
309
|
return;
|
|
310
310
|
}
|
|
311
311
|
|
|
312
|
-
const {x, y} =
|
|
312
|
+
const {x, y} = getEventPosition(event) ?? {};
|
|
313
313
|
|
|
314
314
|
if (x == null || y == null) {
|
|
315
315
|
return;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type {EventPosition, PlainObject} from '@oscarpalmer/atoms/models';
|
|
2
2
|
import {getAttribute, setAttribute, setAttributes} from '@oscarpalmer/toretto/attribute';
|
|
3
3
|
import {createElement} from '@oscarpalmer/toretto/create';
|
|
4
|
-
import {dispatch,
|
|
4
|
+
import {dispatch, getEventPosition} from '@oscarpalmer/toretto/event';
|
|
5
5
|
import {findAncestor, getElementFromPosition} from '@oscarpalmer/toretto/find';
|
|
6
6
|
import {isHTMLOrSVGElement} from '@oscarpalmer/toretto/is';
|
|
7
7
|
import {setStyle} from '@oscarpalmer/toretto/style';
|
|
@@ -214,7 +214,7 @@ function onEnd(
|
|
|
214
214
|
): void {
|
|
215
215
|
const {origin} = item.state;
|
|
216
216
|
|
|
217
|
-
const position =
|
|
217
|
+
const position = getEventPosition(event) ?? {x: 0, y: 0};
|
|
218
218
|
|
|
219
219
|
const target = getElementFromPosition(position)[0];
|
|
220
220
|
|
package/src/js/splitter.ts
CHANGED
|
@@ -3,7 +3,7 @@ import {round} from '@oscarpalmer/atoms/math';
|
|
|
3
3
|
import {clamp} from '@oscarpalmer/atoms/number';
|
|
4
4
|
import {setAria} from '@oscarpalmer/toretto/aria';
|
|
5
5
|
import {getAttribute, setAttribute} from '@oscarpalmer/toretto/attribute';
|
|
6
|
-
import {
|
|
6
|
+
import {getEventPosition, on} from '@oscarpalmer/toretto/event';
|
|
7
7
|
import {findAncestor} from '@oscarpalmer/toretto/find';
|
|
8
8
|
import {setStyle, toggleStyles} from '@oscarpalmer/toretto/style';
|
|
9
9
|
import supportsTouch from '@oscarpalmer/toretto/touch';
|
|
@@ -464,7 +464,7 @@ function onPointermove(event: MouseEvent): void {
|
|
|
464
464
|
return;
|
|
465
465
|
}
|
|
466
466
|
|
|
467
|
-
const position =
|
|
467
|
+
const position = getEventPosition(event);
|
|
468
468
|
|
|
469
469
|
if (position != null) {
|
|
470
470
|
splitter.values.now.current = getSize(
|
package/dist/js/combobox.d.mts
DELETED
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
//#region src/js/combobox.d.ts
|
|
2
|
-
declare global {
|
|
3
|
-
interface HTMLElementTagNameMap {
|
|
4
|
-
[TAGNAME]: OuiComboboxElement;
|
|
5
|
-
}
|
|
6
|
-
}
|
|
7
|
-
declare class OuiComboboxElement extends HTMLElement {
|
|
8
|
-
#private;
|
|
9
|
-
static formAssociated: boolean;
|
|
10
|
-
static observedAttributes: string[];
|
|
11
|
-
/**
|
|
12
|
-
* Is the combobox disabled?
|
|
13
|
-
*/
|
|
14
|
-
get disabled(): boolean;
|
|
15
|
-
/**
|
|
16
|
-
* Should the combobox be disabled?
|
|
17
|
-
*/
|
|
18
|
-
set disabled(value: boolean);
|
|
19
|
-
/**
|
|
20
|
-
* Maximum number of selected options
|
|
21
|
-
*/
|
|
22
|
-
get max(): number | undefined;
|
|
23
|
-
/**
|
|
24
|
-
* Set the maximum number of selected options
|
|
25
|
-
*/
|
|
26
|
-
set max(value: number);
|
|
27
|
-
/**
|
|
28
|
-
* Minimum number of selected options
|
|
29
|
-
*/
|
|
30
|
-
get min(): number | undefined;
|
|
31
|
-
/**
|
|
32
|
-
* Set the minimum number of selected options
|
|
33
|
-
*/
|
|
34
|
-
set min(value: number);
|
|
35
|
-
/**
|
|
36
|
-
* Does the combobox allow multiple values?
|
|
37
|
-
*/
|
|
38
|
-
get multiple(): boolean;
|
|
39
|
-
/**
|
|
40
|
-
* Name of the combobox
|
|
41
|
-
*/
|
|
42
|
-
get name(): string;
|
|
43
|
-
/**
|
|
44
|
-
* Is the combobox readonly?
|
|
45
|
-
*/
|
|
46
|
-
get readonly(): boolean;
|
|
47
|
-
/**
|
|
48
|
-
* Should the combobox be readonly?
|
|
49
|
-
*/
|
|
50
|
-
set readonly(value: boolean);
|
|
51
|
-
/**
|
|
52
|
-
* Is the combobox required?
|
|
53
|
-
*/
|
|
54
|
-
get required(): boolean;
|
|
55
|
-
/**
|
|
56
|
-
* Should the combobox be required?
|
|
57
|
-
*/
|
|
58
|
-
set required(value: boolean);
|
|
59
|
-
/**
|
|
60
|
-
* Selected options
|
|
61
|
-
*/
|
|
62
|
-
get selected(): HTMLElement[];
|
|
63
|
-
/**
|
|
64
|
-
* Type of combobox
|
|
65
|
-
*/
|
|
66
|
-
get type(): OuiComboboxType;
|
|
67
|
-
/**
|
|
68
|
-
* Current value
|
|
69
|
-
*/
|
|
70
|
-
get value(): string;
|
|
71
|
-
/**
|
|
72
|
-
* Set the value
|
|
73
|
-
*/
|
|
74
|
-
set value(value: unknown);
|
|
75
|
-
/**
|
|
76
|
-
* Current values
|
|
77
|
-
*/
|
|
78
|
-
get values(): string[];
|
|
79
|
-
/**
|
|
80
|
-
* Set the values
|
|
81
|
-
*/
|
|
82
|
-
set values(value: unknown[]);
|
|
83
|
-
constructor();
|
|
84
|
-
attributeChangedCallback(name: string, _: string | null, value: string | null): void;
|
|
85
|
-
clear(): void;
|
|
86
|
-
formResetCallback(): void;
|
|
87
|
-
}
|
|
88
|
-
type OuiComboboxType = 'autocomplete' | 'select';
|
|
89
|
-
declare const TAGNAME = "oui-combobox";
|
|
90
|
-
//#endregion
|
|
91
|
-
export { OuiComboboxElement };
|