@oscarpalmer/oui 0.17.0 → 0.19.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/badge.css +13 -13
- package/dist/css/button.css +9 -9
- package/dist/css/color.css +99 -99
- package/dist/css/content.css +10 -12
- package/dist/css/flex.css +39 -39
- package/dist/css/form.css +47 -60
- package/dist/css/message.css +10 -6
- package/dist/css/reset.css +178 -57
- package/dist/css/table.css +4 -4
- package/dist/css/tooltip.css +26 -1
- package/dist/js/attributable.full.js +36 -0
- package/dist/js/attributable.js +30 -45
- package/dist/js/floatable.full.js +398 -0
- package/dist/js/floatable.js +254 -169
- package/dist/js/focus-trap/embedded.full.js +408 -0
- package/dist/js/focus-trap/embedded.js +131 -131
- package/dist/js/focus-trap/standalone.full.js +447 -0
- package/dist/js/focus-trap/standalone.js +4 -4
- package/dist/js/index.js +3 -4
- package/dist/js/oui.full.js +1573 -0
- package/dist/js/popover.full.js +760 -0
- package/dist/js/popover.js +84 -163
- package/dist/js/splitter.full.js +769 -0
- package/dist/js/splitter.js +264 -246
- package/dist/js/tooltip.full.js +613 -0
- package/dist/js/tooltip.js +160 -151
- package/package.json +35 -63
- package/src/css/a11y.scss +1 -1
- package/src/css/badge.scss +23 -19
- package/src/css/button.scss +9 -9
- package/src/css/color.scss +99 -99
- package/src/css/content.scss +6 -9
- package/src/css/flex.scss +21 -20
- package/src/css/form.scss +47 -62
- package/src/css/message.scss +11 -12
- package/src/css/mixins.scss +16 -10
- package/src/css/popover.scss +2 -2
- package/src/css/reset.scss +181 -55
- package/src/css/splitter.scss +15 -13
- package/src/css/table.scss +11 -11
- package/src/css/tooltip.scss +31 -2
- package/src/js/attributable.ts +3 -10
- package/src/js/floatable.ts +370 -141
- package/src/js/focus-trap/embedded.ts +141 -74
- package/src/js/focus-trap/standalone.ts +4 -4
- package/src/js/index.ts +1 -0
- package/src/js/popover.ts +52 -122
- package/src/js/splitter.ts +248 -131
- package/src/js/tooltip.ts +143 -68
- package/types/floatable.d.ts +17 -10
- package/types/focus-trap/embedded.d.ts +18 -5
- package/types/index.d.ts +1 -0
- package/types/popover.d.ts +2 -0
- package/types/splitter.d.ts +13 -1
- package/types/tooltip.d.ts +2 -1
- package/dist/css/value.css +0 -1
- package/dist/js/attributable.cjs +0 -51
- package/dist/js/floatable.cjs +0 -176
- package/dist/js/focus-trap/embedded.cjs +0 -150
- package/dist/js/focus-trap/standalone.cjs +0 -8
- package/dist/js/index.cjs +0 -6
- package/dist/js/popover.cjs +0 -166
- package/dist/js/splitter.cjs +0 -272
- package/dist/js/tooltip.cjs +0 -166
- package/types/attributable.d.cts +0 -5
- package/types/floatable.d.cts +0 -20
- package/types/focus-trap/embedded.d.cts +0 -15
- package/types/focus-trap/standalone.d.cts +0 -3
- package/types/index.d.cts +0 -14
- package/types/popover.d.cts +0 -14
- package/types/splitter.d.cts +0 -10
- package/types/tooltip.d.cts +0 -3
package/src/js/splitter.ts
CHANGED
|
@@ -3,39 +3,93 @@ import {round} from '@oscarpalmer/atoms/math';
|
|
|
3
3
|
import {clamp} from '@oscarpalmer/atoms/number';
|
|
4
4
|
import {getPosition, on} from '@oscarpalmer/toretto/event';
|
|
5
5
|
import {findAncestor} from '@oscarpalmer/toretto/find';
|
|
6
|
+
import {type StyleToggler, toggleStyles} from '@oscarpalmer/toretto/style';
|
|
7
|
+
import supportsTouch from '@oscarpalmer/toretto/touch';
|
|
6
8
|
|
|
7
9
|
declare global {
|
|
10
|
+
// biome-ignore lint/nursery/useConsistentTypeDefinitions: Extending builtins to allow custom element type help
|
|
8
11
|
interface HTMLElementTagNameMap {
|
|
9
|
-
|
|
12
|
+
[SELECTOR]: OuiSplitterElement;
|
|
10
13
|
}
|
|
11
14
|
}
|
|
12
15
|
|
|
13
16
|
export class OuiSplitterElement extends HTMLElement {
|
|
14
|
-
|
|
17
|
+
static readonly observedAttributes = ['max', 'min', 'size', 'type'];
|
|
18
|
+
|
|
19
|
+
readonly #splitter: Splitter;
|
|
20
|
+
|
|
21
|
+
// Getters and setters
|
|
22
|
+
|
|
23
|
+
get max(): number {
|
|
24
|
+
return this.#splitter.values.max;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
set max(value: number) {
|
|
28
|
+
this.setAttribute('max', String(value));
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
get min(): number {
|
|
32
|
+
return this.#splitter.values.min;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
set min(value: number) {
|
|
36
|
+
this.setAttribute('min', String(value));
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
get size(): number {
|
|
40
|
+
return this.#splitter.values.now.current;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
set size(value: number) {
|
|
44
|
+
this.setAttribute('size', String(value));
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
get type(): string {
|
|
48
|
+
return this.getAttribute('type') ?? 'vertical';
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
set type(value: string) {
|
|
52
|
+
this.setAttribute('type', value);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Constructor
|
|
15
56
|
|
|
16
57
|
constructor() {
|
|
17
58
|
super();
|
|
18
59
|
|
|
19
|
-
const panels = [...this.children].filter(
|
|
20
|
-
child => child instanceof HTMLElement,
|
|
21
|
-
);
|
|
60
|
+
const panels = [...this.children].filter(child => child instanceof HTMLElement);
|
|
22
61
|
|
|
23
62
|
if (panels.length !== 2) {
|
|
24
|
-
throw new Error(
|
|
63
|
+
throw new Error(`${SELECTOR} must have exactly two panels.`);
|
|
25
64
|
}
|
|
26
65
|
|
|
27
66
|
this.#splitter = new Splitter(this, panels);
|
|
28
67
|
}
|
|
29
68
|
|
|
69
|
+
// Methods
|
|
70
|
+
|
|
30
71
|
connectedCallback(): void {
|
|
31
|
-
|
|
32
|
-
observer.observe(this);
|
|
33
|
-
}
|
|
72
|
+
this.#splitter.updateConnections(1);
|
|
34
73
|
}
|
|
35
74
|
|
|
36
75
|
disconnectedCallback(): void {
|
|
37
|
-
|
|
38
|
-
|
|
76
|
+
this.#splitter.updateConnections(0);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
attributeChangedCallback(name: string): void {
|
|
80
|
+
switch (name) {
|
|
81
|
+
case 'max':
|
|
82
|
+
case 'min':
|
|
83
|
+
case 'size':
|
|
84
|
+
this.#splitter.updateValues();
|
|
85
|
+
break;
|
|
86
|
+
|
|
87
|
+
case 'type':
|
|
88
|
+
this.#splitter.updateOrientation();
|
|
89
|
+
break;
|
|
90
|
+
|
|
91
|
+
default:
|
|
92
|
+
break;
|
|
39
93
|
}
|
|
40
94
|
}
|
|
41
95
|
}
|
|
@@ -43,20 +97,24 @@ export class OuiSplitterElement extends HTMLElement {
|
|
|
43
97
|
let index = 0;
|
|
44
98
|
|
|
45
99
|
class Splitter {
|
|
100
|
+
element: OuiSplitterElement;
|
|
101
|
+
|
|
46
102
|
handle: HTMLSpanElement;
|
|
47
103
|
|
|
104
|
+
panels: HTMLElement[];
|
|
105
|
+
|
|
48
106
|
rectangle: DOMRect;
|
|
49
107
|
|
|
50
108
|
separator: HTMLDivElement;
|
|
51
109
|
|
|
52
|
-
types
|
|
110
|
+
types!: Types;
|
|
53
111
|
|
|
54
112
|
values: Values;
|
|
55
113
|
|
|
56
|
-
constructor(
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
114
|
+
constructor(element: OuiSplitterElement, panels: HTMLElement[]) {
|
|
115
|
+
this.element = element;
|
|
116
|
+
this.panels = panels;
|
|
117
|
+
|
|
60
118
|
if (isNullableOrWhitespace(element.id)) {
|
|
61
119
|
element.id = `oui_splitter_${++index}`;
|
|
62
120
|
}
|
|
@@ -71,19 +129,47 @@ class Splitter {
|
|
|
71
129
|
|
|
72
130
|
panels[0].insertAdjacentElement('afterend', this.separator);
|
|
73
131
|
|
|
74
|
-
|
|
75
|
-
|
|
132
|
+
this.updateOrientation();
|
|
133
|
+
this.updateValues();
|
|
134
|
+
}
|
|
76
135
|
|
|
77
|
-
|
|
136
|
+
updateConnections(add: 0 | 1): void {
|
|
137
|
+
const method = METHODS_CONNECT[add];
|
|
78
138
|
|
|
139
|
+
MAPPED_ELEMENTS[method](this.element, this);
|
|
140
|
+
MAPPED_ELEMENTS[method](this.handle, this);
|
|
141
|
+
MAPPED_ELEMENTS[method](this.separator, this);
|
|
142
|
+
|
|
143
|
+
if (this.types.auto) {
|
|
144
|
+
RESIZE_OBSERVER[METHODS_OBSERVE[add]](this.element);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
updateOrientation(): void {
|
|
79
149
|
this.types = getTypes(this);
|
|
80
150
|
|
|
151
|
+
if (this.types.auto) {
|
|
152
|
+
RESIZE_OBSERVER.observe(this.element);
|
|
153
|
+
} else {
|
|
154
|
+
RESIZE_OBSERVER.unobserve(this.element);
|
|
155
|
+
}
|
|
156
|
+
|
|
81
157
|
if (this.types.horizontal) {
|
|
82
|
-
this.element.setAttribute(
|
|
158
|
+
this.element.setAttribute(ATTRIBUTE_HORIZONTAL, '');
|
|
159
|
+
} else {
|
|
160
|
+
this.element.removeAttribute(ATTRIBUTE_HORIZONTAL);
|
|
83
161
|
}
|
|
84
162
|
|
|
85
163
|
setAriaOrientation(this);
|
|
86
|
-
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
updateValues(): void {
|
|
167
|
+
this.values = getValues(this.element);
|
|
168
|
+
|
|
169
|
+
requestAnimationFrame(() => {
|
|
170
|
+
setSize(this, this.values.now.current);
|
|
171
|
+
setAriaValue(this);
|
|
172
|
+
});
|
|
87
173
|
}
|
|
88
174
|
}
|
|
89
175
|
|
|
@@ -109,7 +195,7 @@ function createHandle(): HTMLSpanElement {
|
|
|
109
195
|
const handle = document.createElement('span');
|
|
110
196
|
|
|
111
197
|
handle.setAttribute('aria-hidden', 'true');
|
|
112
|
-
handle.setAttribute(
|
|
198
|
+
handle.setAttribute(ATTRIBUTE_HANDLE, '');
|
|
113
199
|
|
|
114
200
|
return handle;
|
|
115
201
|
}
|
|
@@ -122,13 +208,13 @@ function createSeparator(splitter: Splitter): HTMLDivElement {
|
|
|
122
208
|
|
|
123
209
|
separator.setAttribute('aria-controls', splitter.element.id);
|
|
124
210
|
separator.setAttribute('aria-label', 'Resize panels');
|
|
125
|
-
separator.setAttribute(
|
|
211
|
+
separator.setAttribute(ATTRIBUTE_SEPARATOR, '');
|
|
126
212
|
|
|
127
213
|
return separator;
|
|
128
214
|
}
|
|
129
215
|
|
|
130
216
|
function getContained(min: number, value: number, max: number): number {
|
|
131
|
-
return round(clamp(value, min, max),
|
|
217
|
+
return round(clamp(value, min, max), VALUE_DECIMALS);
|
|
132
218
|
}
|
|
133
219
|
|
|
134
220
|
function getSize(splitter: Splitter, value: number): number {
|
|
@@ -154,9 +240,7 @@ function getTypes(splitter: Splitter, width?: number, height?: number): Types {
|
|
|
154
240
|
if (type === 'auto') {
|
|
155
241
|
return {
|
|
156
242
|
auto: true,
|
|
157
|
-
horizontal:
|
|
158
|
-
(height ?? splitter.rectangle.height) >
|
|
159
|
-
(width ?? splitter.rectangle.width),
|
|
243
|
+
horizontal: (height ?? splitter.rectangle.height) > (width ?? splitter.rectangle.width),
|
|
160
244
|
};
|
|
161
245
|
}
|
|
162
246
|
|
|
@@ -166,11 +250,7 @@ function getTypes(splitter: Splitter, width?: number, height?: number): Types {
|
|
|
166
250
|
};
|
|
167
251
|
}
|
|
168
252
|
|
|
169
|
-
function getValue(
|
|
170
|
-
element: HTMLElement,
|
|
171
|
-
name: string,
|
|
172
|
-
defaultValue: number,
|
|
173
|
-
): number {
|
|
253
|
+
function getValue(element: HTMLElement, name: string, defaultValue: number): number {
|
|
174
254
|
const value = element.getAttribute(name);
|
|
175
255
|
|
|
176
256
|
if (isNullableOrWhitespace(value)) {
|
|
@@ -183,24 +263,24 @@ function getValue(
|
|
|
183
263
|
return defaultValue;
|
|
184
264
|
}
|
|
185
265
|
|
|
186
|
-
|
|
266
|
+
if (parsed < 0) {
|
|
267
|
+
return defaultValue;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
return parsed > 1 ? parsed / NAVIGATION_MAXIMUM_TOTAL : parsed;
|
|
187
271
|
}
|
|
188
272
|
|
|
189
273
|
function getValues(element: OuiSplitterElement): Values {
|
|
190
274
|
const values: Values = {
|
|
191
|
-
max: getValue(element, 'max',
|
|
192
|
-
min: getValue(element, 'min',
|
|
275
|
+
max: getValue(element, 'max', NAVIGATION_MAXIMUM_PERCENTAGE),
|
|
276
|
+
min: getValue(element, 'min', NAVIGATION_MINIMUM_PERCENTAGE),
|
|
193
277
|
now: {
|
|
194
278
|
current: 0.5,
|
|
195
279
|
previous: 0.5,
|
|
196
280
|
},
|
|
197
281
|
};
|
|
198
282
|
|
|
199
|
-
const value = getContained(
|
|
200
|
-
values.min,
|
|
201
|
-
getValue(element, 'size', values.now.current),
|
|
202
|
-
values.max,
|
|
203
|
-
);
|
|
283
|
+
const value = getContained(values.min, getValue(element, 'size', values.now.current), values.max);
|
|
204
284
|
|
|
205
285
|
values.now.current = value;
|
|
206
286
|
values.now.previous = value;
|
|
@@ -209,23 +289,27 @@ function getValues(element: OuiSplitterElement): Values {
|
|
|
209
289
|
}
|
|
210
290
|
|
|
211
291
|
function onEnd(reset: boolean): void {
|
|
212
|
-
if (splitter
|
|
213
|
-
|
|
214
|
-
|
|
292
|
+
if (splitter == null) {
|
|
293
|
+
return;
|
|
294
|
+
}
|
|
215
295
|
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
296
|
+
splitter.handle.removeAttribute(ATTRIBUTE_ACTIVE);
|
|
297
|
+
splitter.separator.removeAttribute(ATTRIBUTE_ACTIVE);
|
|
298
|
+
|
|
299
|
+
if (reset) {
|
|
300
|
+
setSize(splitter, splitter.values.now.previous);
|
|
301
|
+
} else {
|
|
302
|
+
splitter.values.now.previous = splitter.values.now.current;
|
|
221
303
|
}
|
|
222
304
|
|
|
223
305
|
splitter = undefined;
|
|
306
|
+
|
|
307
|
+
STYLING_TOGGLER.remove();
|
|
224
308
|
}
|
|
225
309
|
|
|
226
310
|
function onKeydown(event: KeyboardEvent): void {
|
|
227
311
|
switch (true) {
|
|
228
|
-
case
|
|
312
|
+
case KEYS_ALL.has(event.key):
|
|
229
313
|
onNavigate(event);
|
|
230
314
|
break;
|
|
231
315
|
|
|
@@ -238,79 +322,37 @@ function onKeydown(event: KeyboardEvent): void {
|
|
|
238
322
|
}
|
|
239
323
|
}
|
|
240
324
|
|
|
241
|
-
function onMousedown(event: Event): void {
|
|
242
|
-
splitter = mapped.get(
|
|
243
|
-
findAncestor(
|
|
244
|
-
event.target as never,
|
|
245
|
-
'[oui-splitter-handle]',
|
|
246
|
-
) as HTMLSpanElement,
|
|
247
|
-
);
|
|
248
|
-
|
|
249
|
-
if (splitter == null) {
|
|
250
|
-
return;
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
splitter.handle.setAttribute('oui-splitter-active', '');
|
|
254
|
-
splitter.separator.setAttribute('oui-splitter-active', '');
|
|
255
|
-
|
|
256
|
-
splitter.rectangle = splitter.element.getBoundingClientRect();
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
function onMousemove(event: MouseEvent): void {
|
|
260
|
-
if (splitter == null) {
|
|
261
|
-
return;
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
const position = getPosition(event);
|
|
265
|
-
|
|
266
|
-
if (position != null) {
|
|
267
|
-
splitter.values.now.current = getSize(
|
|
268
|
-
splitter,
|
|
269
|
-
splitter.types.horizontal ? position.y : position.x,
|
|
270
|
-
);
|
|
271
|
-
|
|
272
|
-
setSize(splitter, splitter.values.now.current);
|
|
273
|
-
}
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
function onMouseup(): void {
|
|
277
|
-
if (splitter != null) {
|
|
278
|
-
onEnd(false);
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
|
|
282
325
|
function onNavigate(event: KeyboardEvent): void {
|
|
283
|
-
const splitter =
|
|
284
|
-
findAncestor(
|
|
285
|
-
event.target as never,
|
|
286
|
-
'[oui-splitter-handle]',
|
|
287
|
-
) as HTMLSpanElement,
|
|
326
|
+
const splitter = MAPPED_ELEMENTS.get(
|
|
327
|
+
findAncestor(event.target as never, '[oui-splitter-separator]') as HTMLSpanElement,
|
|
288
328
|
);
|
|
289
329
|
|
|
290
330
|
if (splitter == null) {
|
|
291
331
|
return;
|
|
292
332
|
}
|
|
293
333
|
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
true,
|
|
299
|
-
);
|
|
334
|
+
const {types, values} = splitter;
|
|
335
|
+
|
|
336
|
+
if (KEYS_ABSOLUTE.has(event.key)) {
|
|
337
|
+
setSize(splitter, event.key === 'End' ? values.max : values.min, true);
|
|
300
338
|
|
|
301
339
|
return;
|
|
302
340
|
}
|
|
303
341
|
|
|
304
342
|
if (
|
|
305
|
-
(
|
|
306
|
-
(
|
|
343
|
+
(types.horizontal && !KEYS_HORIZONTAL.has(event.key)) ||
|
|
344
|
+
!(types.horizontal || KEYS_VERTICAL.has(event.key))
|
|
307
345
|
) {
|
|
308
346
|
return;
|
|
309
347
|
}
|
|
310
348
|
|
|
311
|
-
const
|
|
349
|
+
const offset = KEYS_NEGATIVE.has(event.key) ? -1 : 1;
|
|
312
350
|
|
|
313
|
-
setSize(
|
|
351
|
+
setSize(
|
|
352
|
+
splitter,
|
|
353
|
+
getContained(values.min, values.now.current + offset * NAVIGATION_MODIFIER, values.max),
|
|
354
|
+
true,
|
|
355
|
+
);
|
|
314
356
|
}
|
|
315
357
|
|
|
316
358
|
function onObservation(entries: ResizeObserverEntry[]): void {
|
|
@@ -320,22 +362,18 @@ function onObservation(entries: ResizeObserverEntry[]): void {
|
|
|
320
362
|
|
|
321
363
|
frame = requestAnimationFrame(() => {
|
|
322
364
|
for (const entry of entries) {
|
|
323
|
-
const splitter =
|
|
365
|
+
const splitter = MAPPED_ELEMENTS.get(entry.target as HTMLElement);
|
|
324
366
|
|
|
325
367
|
if (splitter == null) {
|
|
326
368
|
return;
|
|
327
369
|
}
|
|
328
370
|
|
|
329
|
-
splitter.types = getTypes(
|
|
330
|
-
splitter,
|
|
331
|
-
entry.contentRect.width,
|
|
332
|
-
entry.contentRect.height,
|
|
333
|
-
);
|
|
371
|
+
splitter.types = getTypes(splitter, entry.contentRect.width, entry.contentRect.height);
|
|
334
372
|
|
|
335
373
|
if (splitter.types.horizontal) {
|
|
336
|
-
splitter.element.setAttribute(
|
|
374
|
+
splitter.element.setAttribute(ATTRIBUTE_HORIZONTAL, '');
|
|
337
375
|
} else {
|
|
338
|
-
splitter.element.removeAttribute(
|
|
376
|
+
splitter.element.removeAttribute(ATTRIBUTE_HORIZONTAL);
|
|
339
377
|
}
|
|
340
378
|
|
|
341
379
|
setAriaOrientation(splitter);
|
|
@@ -345,6 +383,57 @@ function onObservation(entries: ResizeObserverEntry[]): void {
|
|
|
345
383
|
});
|
|
346
384
|
}
|
|
347
385
|
|
|
386
|
+
function onPointerdown(event: Event): void {
|
|
387
|
+
if (
|
|
388
|
+
(event.type === 'mousedown' && supportsTouch.value) ||
|
|
389
|
+
(event.type === 'touchstart' && !supportsTouch.value)
|
|
390
|
+
) {
|
|
391
|
+
return;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
splitter = MAPPED_ELEMENTS.get(
|
|
395
|
+
findAncestor(event.target as never, SELECTOR_HANDLE) as HTMLSpanElement,
|
|
396
|
+
);
|
|
397
|
+
|
|
398
|
+
if (splitter == null) {
|
|
399
|
+
return;
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
if (supportsTouch.value) {
|
|
403
|
+
event.preventDefault();
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
splitter.handle.setAttribute(ATTRIBUTE_ACTIVE, '');
|
|
407
|
+
splitter.separator.setAttribute(ATTRIBUTE_ACTIVE, '');
|
|
408
|
+
|
|
409
|
+
splitter.rectangle = splitter.element.getBoundingClientRect();
|
|
410
|
+
|
|
411
|
+
STYLING_TOGGLER.set();
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
function onPointermove(event: MouseEvent): void {
|
|
415
|
+
if (splitter == null) {
|
|
416
|
+
return;
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
const position = getPosition(event);
|
|
420
|
+
|
|
421
|
+
if (position != null) {
|
|
422
|
+
splitter.values.now.current = getSize(
|
|
423
|
+
splitter,
|
|
424
|
+
splitter.types.horizontal ? position.y : position.x,
|
|
425
|
+
);
|
|
426
|
+
|
|
427
|
+
setSize(splitter, splitter.values.now.current);
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
function onPointerup(): void {
|
|
432
|
+
if (splitter != null) {
|
|
433
|
+
onEnd(false);
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
|
|
348
437
|
function setAriaOrientation(splitter: Splitter): void {
|
|
349
438
|
splitter.separator.setAttribute(
|
|
350
439
|
'aria-orientation',
|
|
@@ -356,10 +445,7 @@ function setAriaValue(splitter: Splitter): void {
|
|
|
356
445
|
splitter.separator.setAttribute('aria-valuemax', String(splitter.values.max));
|
|
357
446
|
splitter.separator.setAttribute('aria-valuemin', String(splitter.values.min));
|
|
358
447
|
|
|
359
|
-
splitter.separator.setAttribute(
|
|
360
|
-
'aria-valuenow',
|
|
361
|
-
String(splitter.values.now.current),
|
|
362
|
-
);
|
|
448
|
+
splitter.separator.setAttribute('aria-valuenow', String(splitter.values.now.current));
|
|
363
449
|
}
|
|
364
450
|
|
|
365
451
|
function setSize(splitter: Splitter, size: number, previous?: boolean): void {
|
|
@@ -376,19 +462,51 @@ function setSize(splitter: Splitter, size: number, previous?: boolean): void {
|
|
|
376
462
|
|
|
377
463
|
//
|
|
378
464
|
|
|
379
|
-
const
|
|
465
|
+
const SELECTOR = 'oui-splitter';
|
|
466
|
+
|
|
467
|
+
const ATTRIBUTE_ACTIVE = `${SELECTOR}-active`;
|
|
468
|
+
|
|
469
|
+
const ATTRIBUTE_HANDLE = `${SELECTOR}-handle`;
|
|
470
|
+
|
|
471
|
+
const ATTRIBUTE_HORIZONTAL = `${SELECTOR}-horizontal`;
|
|
472
|
+
|
|
473
|
+
const ATTRIBUTE_SEPARATOR = `${SELECTOR}-separator`;
|
|
474
|
+
|
|
475
|
+
const KEYS_ABSOLUTE: Set<string> = new Set(['End', 'Home']);
|
|
476
|
+
|
|
477
|
+
const KEYS_HORIZONTAL: Set<string> = new Set(['ArrowDown', 'ArrowUp']);
|
|
478
|
+
|
|
479
|
+
const KEYS_NEGATIVE: Set<string> = new Set(['ArrowLeft', 'ArrowUp']);
|
|
480
|
+
|
|
481
|
+
const KEYS_VERTICAL: Set<string> = new Set(['ArrowLeft', 'ArrowRight']);
|
|
380
482
|
|
|
381
|
-
const
|
|
483
|
+
const KEYS_ALL: Set<string> = new Set([...KEYS_ABSOLUTE, ...KEYS_HORIZONTAL, ...KEYS_VERTICAL]);
|
|
382
484
|
|
|
383
|
-
const
|
|
485
|
+
const MAPPED_ELEMENTS: WeakMap<HTMLElement, Splitter> = new WeakMap();
|
|
384
486
|
|
|
385
|
-
const
|
|
487
|
+
const METHODS_CONNECT = ['delete', 'set'] as const;
|
|
386
488
|
|
|
387
|
-
const
|
|
489
|
+
const METHODS_OBSERVE = ['unobserve', 'observe'] as const;
|
|
388
490
|
|
|
389
|
-
const
|
|
491
|
+
const NAVIGATION_MAXIMUM_PERCENTAGE = 0.9;
|
|
390
492
|
|
|
391
|
-
const
|
|
493
|
+
const NAVIGATION_MAXIMUM_TOTAL = 100;
|
|
494
|
+
|
|
495
|
+
const NAVIGATION_MINIMUM_PERCENTAGE = 0.1;
|
|
496
|
+
|
|
497
|
+
const NAVIGATION_MODIFIER = 0.05;
|
|
498
|
+
|
|
499
|
+
const RESIZE_OBSERVER: ResizeObserver = new ResizeObserver(onObservation);
|
|
500
|
+
|
|
501
|
+
const SELECTOR_HANDLE = `[${ATTRIBUTE_HANDLE}]`;
|
|
502
|
+
|
|
503
|
+
const STYLING_TOGGLER: StyleToggler = toggleStyles(document.body, {
|
|
504
|
+
touchAction: 'none',
|
|
505
|
+
userSelect: 'none',
|
|
506
|
+
webkitUserSelect: 'none',
|
|
507
|
+
});
|
|
508
|
+
|
|
509
|
+
const VALUE_DECIMALS = 6;
|
|
392
510
|
|
|
393
511
|
let frame: DOMHighResTimeStamp | undefined;
|
|
394
512
|
|
|
@@ -396,12 +514,11 @@ let splitter: Splitter | undefined;
|
|
|
396
514
|
|
|
397
515
|
//
|
|
398
516
|
|
|
399
|
-
customElements.define(
|
|
517
|
+
customElements.define(SELECTOR, OuiSplitterElement);
|
|
400
518
|
|
|
401
519
|
on(document, 'keydown', onKeydown);
|
|
402
|
-
|
|
403
|
-
on(document, '
|
|
404
|
-
|
|
405
|
-
on(document, '
|
|
406
|
-
|
|
407
|
-
on(document, 'mouseup', onMouseup);
|
|
520
|
+
on(document, 'mousedown', onPointerdown);
|
|
521
|
+
on(document, 'pointermove', onPointermove);
|
|
522
|
+
on(document, 'pointerup', onPointerup);
|
|
523
|
+
on(document, 'touchcancel', onPointerup, {passive: false});
|
|
524
|
+
on(document, 'touchstart', onPointerdown, {passive: false});
|