@oscarpalmer/oui 0.29.1 → 0.31.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 +4 -4
- package/dist/css/combobox.css +165 -0
- package/dist/css/form.css +18 -14
- package/dist/js/combobox.d.mts +91 -0
- package/dist/js/combobox.mjs +797 -0
- package/dist/js/dialog.d.mts +4 -3
- package/dist/js/dialog.mjs +1 -1
- package/dist/js/{draggable-fIYXd8eO.d.mts → draggable-a6w0J1OD.d.mts} +1 -2
- package/dist/js/floatable/floatable.embedded.d.mts +1 -1
- package/dist/js/floatable/floatable.embedded.mjs +2 -2
- package/dist/js/floatable/floatable.standalone.d.mts +1 -1
- package/dist/js/{floatable.embedded-DUR8bQBK.d.mts → floatable.embedded-Bct4U5Dm.d.mts} +0 -1
- package/dist/js/focus-trap/focus-trap.embedded.mjs +13 -9
- package/dist/js/index.d.mts +9 -4
- package/dist/js/index.mjs +2 -1
- package/dist/js/internal/draggable.d.mts +1 -1
- package/dist/js/internal/draggable.mjs +22 -21
- package/dist/js/internal/navigable.d.mts +0 -1
- package/dist/js/internal/navigable.mjs +4 -3
- package/dist/js/menu.mjs +5 -2
- package/dist/js/movable/movable.embedded.d.mts +1 -1
- package/dist/js/movable/movable.embedded.mjs +7 -12
- package/dist/js/movable/movable.standalone.d.mts +1 -1
- package/dist/js/popover.d.mts +1 -2
- package/dist/js/popover.mjs +1 -1
- package/dist/js/resizable/resizable.embedded.d.mts +1 -1
- package/dist/js/resizable/resizable.embedded.mjs +41 -20
- package/dist/js/resizable/resizable.standalone.d.mts +1 -1
- package/dist/js/{resizable.embedded-CXrUVPzR.d.mts → resizable.embedded-3qoR0Bjm.d.mts} +0 -1
- package/dist/js/sortable/sortable.embedded.d.mts +1 -1
- package/dist/js/sortable/sortable.embedded.mjs +28 -37
- package/dist/js/sortable/sortable.standalone.d.mts +1 -1
- package/dist/js/splitter.d.mts +2 -2
- package/dist/js/splitter.mjs +11 -11
- package/dist/js/tooltip.d.mts +1 -2
- package/dist/js/tooltip.mjs +3 -3
- package/package.json +7 -3
- package/src/css/badge.scss +1 -18
- package/src/css/combobox.scss +137 -0
- package/src/css/form.scss +18 -80
- package/src/css/mixins.scss +86 -0
- package/src/js/combobox.ts +1479 -0
- package/src/js/focus-trap/focus-trap.embedded.ts +19 -11
- package/src/js/index.ts +1 -0
- package/src/js/internal/draggable.ts +33 -31
- package/src/js/internal/navigable.ts +5 -1
- package/src/js/menu.ts +5 -2
- package/src/js/movable/movable.embedded.ts +3 -8
- package/src/js/resizable/resizable.embedded.ts +57 -20
- package/src/js/sortable/sortable.embedded.ts +21 -26
- package/src/js/splitter.ts +37 -23
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {isPlainObject} from '@oscarpalmer/atoms/is';
|
|
2
2
|
import {clamp} from '@oscarpalmer/atoms/number';
|
|
3
3
|
import {setAttribute} from '@oscarpalmer/toretto/attribute';
|
|
4
|
-
import {on} from '@oscarpalmer/toretto/event';
|
|
4
|
+
import {dispatch, on} from '@oscarpalmer/toretto/event';
|
|
5
5
|
import {findAncestor} from '@oscarpalmer/toretto/find';
|
|
6
6
|
import {getFocusable} from '@oscarpalmer/toretto/focusable';
|
|
7
7
|
import {isHTMLOrSVGElement} from '@oscarpalmer/toretto/is';
|
|
@@ -289,19 +289,27 @@ function onTab(event: KeyboardEvent): void {
|
|
|
289
289
|
return;
|
|
290
290
|
}
|
|
291
291
|
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
292
|
+
const dispatched = dispatch(element, 'focus-trap');
|
|
293
|
+
|
|
294
|
+
setTimeout(() => {
|
|
295
|
+
if (dispatched.defaultPrevented) {
|
|
296
|
+
return;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
if (!instance.disabled) {
|
|
300
|
+
event.preventDefault();
|
|
301
|
+
}
|
|
295
302
|
|
|
296
|
-
|
|
303
|
+
const elements = getFocusable(element);
|
|
297
304
|
|
|
298
|
-
|
|
305
|
+
const index = elements.indexOf(event.target as HTMLElement);
|
|
299
306
|
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
307
|
+
if (index === -1 || elements.length === 0) {
|
|
308
|
+
tabToTrap(instance, elements, element);
|
|
309
|
+
} else {
|
|
310
|
+
tabToElement(instance, elements, index, event.shiftKey ? -1 : 1);
|
|
311
|
+
}
|
|
312
|
+
});
|
|
305
313
|
}
|
|
306
314
|
|
|
307
315
|
export function removeFocusTrap(element: HTMLElement): void {
|
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 {getPosition, on} from '@oscarpalmer/toretto/event';
|
|
4
|
+
import {dispatch, getPosition, 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';
|
|
@@ -27,8 +27,6 @@ type OuiDraggableDirection = 'horizontal' | 'vertical' | 'x' | 'y';
|
|
|
27
27
|
export abstract class OuiDraggable<ExtraState extends PlainObject = PlainObject> {
|
|
28
28
|
#destroyed = false;
|
|
29
29
|
|
|
30
|
-
#name: keyof OuiDraggableStates;
|
|
31
|
-
|
|
32
30
|
readonly #state: OuiDraggableState & ExtraState;
|
|
33
31
|
|
|
34
32
|
get element(): HTMLElement {
|
|
@@ -43,13 +41,12 @@ export abstract class OuiDraggable<ExtraState extends PlainObject = PlainObject>
|
|
|
43
41
|
options: OuiDraggableOptions<ExtraState>,
|
|
44
42
|
extras: ExtraState,
|
|
45
43
|
) {
|
|
46
|
-
this.#name = name;
|
|
47
|
-
|
|
48
44
|
this.#state = {
|
|
49
45
|
...extras,
|
|
50
46
|
attribute,
|
|
51
47
|
element,
|
|
52
48
|
event,
|
|
49
|
+
name,
|
|
53
50
|
options,
|
|
54
51
|
horizontal: true,
|
|
55
52
|
vertical: true,
|
|
@@ -70,7 +67,7 @@ export abstract class OuiDraggable<ExtraState extends PlainObject = PlainObject>
|
|
|
70
67
|
|
|
71
68
|
states ??= {};
|
|
72
69
|
|
|
73
|
-
states[this.#name] = this.#state;
|
|
70
|
+
states[this.#state.name] = this.#state;
|
|
74
71
|
|
|
75
72
|
globals.states.set(element, states);
|
|
76
73
|
}
|
|
@@ -216,9 +213,9 @@ export type OuiDraggableState = {
|
|
|
216
213
|
attribute: string;
|
|
217
214
|
container?: HTMLElement;
|
|
218
215
|
element: HTMLElement;
|
|
219
|
-
event: string;
|
|
220
216
|
hasHandles?: boolean;
|
|
221
217
|
horizontal: boolean;
|
|
218
|
+
name: keyof OuiDraggableStates;
|
|
222
219
|
options: OuiDraggableOptions;
|
|
223
220
|
styling: StyleToggler;
|
|
224
221
|
vertical: boolean;
|
|
@@ -254,6 +251,22 @@ export function addDraggable<
|
|
|
254
251
|
return instances[this.property] as Instance;
|
|
255
252
|
}
|
|
256
253
|
|
|
254
|
+
function cancelDrag(item?: OuiDraggableItem): void {
|
|
255
|
+
if (item == null) {
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
item.state.options.drag.onCancel?.(globals, item);
|
|
260
|
+
|
|
261
|
+
dispatch(item.state.element, `${item.state.name}:cancel`, {
|
|
262
|
+
detail: {
|
|
263
|
+
element: item.state.options.getOrigin(),
|
|
264
|
+
},
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
reset();
|
|
268
|
+
}
|
|
269
|
+
|
|
257
270
|
function destroyInstance(instance: OuiDraggable, state: OuiDraggableState): void {
|
|
258
271
|
unsetContainer({
|
|
259
272
|
instance,
|
|
@@ -312,21 +325,9 @@ function getNextPosition(item: OuiDraggableItem, position: EventPosition): Event
|
|
|
312
325
|
}
|
|
313
326
|
|
|
314
327
|
function onKeydown(event: KeyboardEvent): void {
|
|
315
|
-
if (current
|
|
316
|
-
|
|
328
|
+
if (current != null && event.key === KEY_ESCAPE) {
|
|
329
|
+
cancelDrag(current);
|
|
317
330
|
}
|
|
318
|
-
|
|
319
|
-
current.state.options.drag.onCancel?.(globals, current);
|
|
320
|
-
|
|
321
|
-
current.state.element.dispatchEvent(
|
|
322
|
-
new CustomEvent(`${current.state.event}:cancel`, {
|
|
323
|
-
detail: {
|
|
324
|
-
element: current.state.options.getOrigin(),
|
|
325
|
-
},
|
|
326
|
-
}),
|
|
327
|
-
);
|
|
328
|
-
|
|
329
|
-
reset();
|
|
330
331
|
}
|
|
331
332
|
|
|
332
333
|
function onPointerdown(event: MouseEvent | TouchEvent): void {
|
|
@@ -405,18 +406,15 @@ function onPointerdown(event: MouseEvent | TouchEvent): void {
|
|
|
405
406
|
globals.offset = item.state.options.position.getOffset(globals, item, element, position);
|
|
406
407
|
globals.original = item.state.options.position.getOriginal(globals, item, position);
|
|
407
408
|
|
|
408
|
-
const
|
|
409
|
+
const dispatched = dispatch(item.state.element, `${item.state.name}:begin`, {
|
|
409
410
|
detail: {
|
|
410
411
|
element,
|
|
411
412
|
position: {...globals.original},
|
|
412
413
|
},
|
|
413
|
-
cancelable: true,
|
|
414
414
|
});
|
|
415
415
|
|
|
416
|
-
item.state.element.dispatchEvent(begin);
|
|
417
|
-
|
|
418
416
|
setTimeout(() => {
|
|
419
|
-
if (
|
|
417
|
+
if (dispatched.defaultPrevented) {
|
|
420
418
|
item.state.options.drag.onCancel?.(globals, item);
|
|
421
419
|
|
|
422
420
|
reset();
|
|
@@ -461,11 +459,15 @@ function onPointermove(event: MouseEvent | TouchEvent): void {
|
|
|
461
459
|
original: position,
|
|
462
460
|
});
|
|
463
461
|
|
|
464
|
-
current.state.element.
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
)
|
|
462
|
+
const dispatched = dispatch(current.state.element, `${current.state.name}:move`, {
|
|
463
|
+
detail,
|
|
464
|
+
});
|
|
465
|
+
|
|
466
|
+
setTimeout(() => {
|
|
467
|
+
if (dispatched.defaultPrevented) {
|
|
468
|
+
cancelDrag(current);
|
|
469
|
+
}
|
|
470
|
+
});
|
|
469
471
|
}
|
|
470
472
|
|
|
471
473
|
function onPointerup(event: MouseEvent | TouchEvent): void {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {clamp} from '@oscarpalmer/atoms/number';
|
|
2
2
|
import {getAria, setRole} from '@oscarpalmer/toretto/aria';
|
|
3
|
-
import {on} from '@oscarpalmer/toretto/event';
|
|
3
|
+
import {dispatch, on} from '@oscarpalmer/toretto/event';
|
|
4
4
|
import {findAncestor} from '@oscarpalmer/toretto/find';
|
|
5
5
|
import {isHTMLOrSVGElement} from '@oscarpalmer/toretto/is';
|
|
6
6
|
import type {AriaRole, RemovableEventListener} from '@oscarpalmer/toretto/models';
|
|
@@ -212,6 +212,10 @@ export function updateNavigableFocus(
|
|
|
212
212
|
if (focus) {
|
|
213
213
|
navigable.active.element?.focus();
|
|
214
214
|
}
|
|
215
|
+
|
|
216
|
+
dispatch(navigable.active.element, 'navigable:change', {
|
|
217
|
+
detail: {...navigable.active},
|
|
218
|
+
});
|
|
215
219
|
}
|
|
216
220
|
|
|
217
221
|
// #endregion
|
package/src/js/menu.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import {setAria, setRole} from '@oscarpalmer/toretto/aria';
|
|
2
|
-
import {setAttribute} from '@oscarpalmer/toretto/attribute';
|
|
2
|
+
import {setAttribute, setAttributes} from '@oscarpalmer/toretto/attribute';
|
|
3
3
|
import {on} from '@oscarpalmer/toretto/event';
|
|
4
4
|
import {findAncestor} from '@oscarpalmer/toretto/find';
|
|
5
5
|
import {createEmbeddedFloatable, getOnBeforeToggleListener} from './floatable/floatable.embedded';
|
|
@@ -197,7 +197,10 @@ function initializeMenu(menu: OuiMenu): void {
|
|
|
197
197
|
haspopup: 'menu',
|
|
198
198
|
});
|
|
199
199
|
|
|
200
|
-
|
|
200
|
+
setAttributes(menu.content, {
|
|
201
|
+
popover: '',
|
|
202
|
+
tabindex: '-1'
|
|
203
|
+
});
|
|
201
204
|
|
|
202
205
|
setRole(menu.content, 'menu');
|
|
203
206
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type {EventPosition, PlainObject} from '@oscarpalmer/atoms/models';
|
|
2
2
|
import {setAttribute} from '@oscarpalmer/toretto/attribute';
|
|
3
|
-
import {getPosition, on} from '@oscarpalmer/toretto/event';
|
|
3
|
+
import {dispatch, getPosition, 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';
|
|
@@ -199,18 +199,15 @@ function onEnd(
|
|
|
199
199
|
setOffset(state, container);
|
|
200
200
|
}
|
|
201
201
|
|
|
202
|
-
const
|
|
202
|
+
const dispatched = dispatch(state.element, 'movable:end', {
|
|
203
203
|
detail: {
|
|
204
204
|
from: {...globals.original},
|
|
205
205
|
to: getPosition(event),
|
|
206
206
|
},
|
|
207
|
-
cancelable: true,
|
|
208
207
|
});
|
|
209
208
|
|
|
210
|
-
state.element.dispatchEvent(end);
|
|
211
|
-
|
|
212
209
|
setTimeout(() => {
|
|
213
|
-
if (
|
|
210
|
+
if (dispatched.defaultPrevented) {
|
|
214
211
|
onCancel(globals, item);
|
|
215
212
|
}
|
|
216
213
|
|
|
@@ -295,8 +292,6 @@ const ATTRIBUTE_MOVING = `${ATTRIBUTE_MOVABLE}-moving`;
|
|
|
295
292
|
|
|
296
293
|
const CONTAINERS = new Map<HTMLElement, Set<OuiMovable>>();
|
|
297
294
|
|
|
298
|
-
const EVENT_END = 'move:end';
|
|
299
|
-
|
|
300
295
|
const MESSAGE = 'The element must be an instance of HTMLElement or SVGElement';
|
|
301
296
|
|
|
302
297
|
const MOVED = new Set<OuiMovable>();
|
|
@@ -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 {getPosition, on} from '@oscarpalmer/toretto/event';
|
|
5
|
+
import {dispatch, getPosition, 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';
|
|
@@ -32,8 +32,6 @@ export class OuiResizable {
|
|
|
32
32
|
set(): void {
|
|
33
33
|
const [width, height] = getAndSetDimensions(this.#state.element, this.#state.options);
|
|
34
34
|
|
|
35
|
-
console.log('set', width, height);
|
|
36
|
-
|
|
37
35
|
this.#state.width = width;
|
|
38
36
|
this.#state.height = height;
|
|
39
37
|
}
|
|
@@ -91,6 +89,21 @@ function addResizable(
|
|
|
91
89
|
return item?.instance;
|
|
92
90
|
}
|
|
93
91
|
|
|
92
|
+
function cancelResize(item?: OuiResizableItem): void {
|
|
93
|
+
if (item == null) {
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
setStyles(item.state.element, {
|
|
98
|
+
height: `${item.state.height}px`,
|
|
99
|
+
width: `${item.state.width}px`,
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
resetResizable();
|
|
103
|
+
|
|
104
|
+
dispatch(item.state.element, 'resizable:cancel');
|
|
105
|
+
}
|
|
106
|
+
|
|
94
107
|
/**
|
|
95
108
|
* Creates _(or retrieves)_ a _OuiResizable_ instance for an element
|
|
96
109
|
*
|
|
@@ -245,16 +258,9 @@ function getXAndY(first: unknown, second?: unknown): [number, number] {
|
|
|
245
258
|
}
|
|
246
259
|
|
|
247
260
|
function onKeydown(event: KeyboardEvent): void {
|
|
248
|
-
if (current
|
|
249
|
-
|
|
261
|
+
if (current != null && event.key === 'Escape') {
|
|
262
|
+
cancelResize(current);
|
|
250
263
|
}
|
|
251
|
-
|
|
252
|
-
setStyles(current.state.element, {
|
|
253
|
-
height: `${current.state.height}px`,
|
|
254
|
-
width: `${current.state.width}px`,
|
|
255
|
-
});
|
|
256
|
-
|
|
257
|
-
resetResizable();
|
|
258
264
|
}
|
|
259
265
|
|
|
260
266
|
function onPointerdown(event: MouseEvent | TouchEvent): void {
|
|
@@ -283,11 +289,19 @@ function onPointerdown(event: MouseEvent | TouchEvent): void {
|
|
|
283
289
|
event.preventDefault();
|
|
284
290
|
}
|
|
285
291
|
|
|
286
|
-
|
|
287
|
-
start = position;
|
|
292
|
+
const dispatched = dispatch(element!, 'resizable:begin');
|
|
288
293
|
|
|
289
|
-
|
|
290
|
-
|
|
294
|
+
setTimeout(() => {
|
|
295
|
+
if (dispatched.defaultPrevented) {
|
|
296
|
+
return;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
current = stored;
|
|
300
|
+
start = position;
|
|
301
|
+
|
|
302
|
+
current.state.styles.set();
|
|
303
|
+
styleToggler.set();
|
|
304
|
+
});
|
|
291
305
|
}
|
|
292
306
|
|
|
293
307
|
function onPointermove(event: MouseEvent | TouchEvent): void {
|
|
@@ -305,6 +319,19 @@ function onPointermove(event: MouseEvent | TouchEvent): void {
|
|
|
305
319
|
const height = current.state.height + (y - (start?.y ?? 0));
|
|
306
320
|
|
|
307
321
|
getAndSetDimensions(current.state.element, current.state.options, {height, width});
|
|
322
|
+
|
|
323
|
+
const dispatched = dispatch(current.state.element, 'resizable:resize', {
|
|
324
|
+
detail: {
|
|
325
|
+
height,
|
|
326
|
+
width,
|
|
327
|
+
},
|
|
328
|
+
});
|
|
329
|
+
|
|
330
|
+
setTimeout(() => {
|
|
331
|
+
if (dispatched.defaultPrevented) {
|
|
332
|
+
cancelResize(current);
|
|
333
|
+
}
|
|
334
|
+
});
|
|
308
335
|
}
|
|
309
336
|
|
|
310
337
|
function onPointerup(): void {
|
|
@@ -312,12 +339,22 @@ function onPointerup(): void {
|
|
|
312
339
|
return;
|
|
313
340
|
}
|
|
314
341
|
|
|
315
|
-
const
|
|
342
|
+
const dispatched = dispatch(current.state.element, 'resizable:end');
|
|
316
343
|
|
|
317
|
-
|
|
318
|
-
|
|
344
|
+
setTimeout(() => {
|
|
345
|
+
if (current == null || dispatched.defaultPrevented) {
|
|
346
|
+
cancelResize(current);
|
|
319
347
|
|
|
320
|
-
|
|
348
|
+
return;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
const {height, width} = current.state.element.getBoundingClientRect();
|
|
352
|
+
|
|
353
|
+
current.state.height = height;
|
|
354
|
+
current.state.width = width;
|
|
355
|
+
|
|
356
|
+
resetResizable();
|
|
357
|
+
});
|
|
321
358
|
}
|
|
322
359
|
|
|
323
360
|
function removeResizable(element: HTMLElement): void {
|
|
@@ -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 {getPosition} from '@oscarpalmer/toretto/event';
|
|
4
|
+
import {dispatch, getPosition} 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';
|
|
@@ -80,7 +80,7 @@ type OuiSortableState = {
|
|
|
80
80
|
function afterEnd(
|
|
81
81
|
insert: 'append' | 'insert' | 'prepend' | undefined,
|
|
82
82
|
from: OuiDraggableItem<OuiSortableState>,
|
|
83
|
-
events: CustomEvent
|
|
83
|
+
events: [CustomEvent, CustomEvent | undefined],
|
|
84
84
|
elements: {origin?: HTMLElement; target: HTMLElement},
|
|
85
85
|
position: EventPosition | undefined,
|
|
86
86
|
valid: boolean,
|
|
@@ -91,7 +91,7 @@ function afterEnd(
|
|
|
91
91
|
|
|
92
92
|
resetPlaceholders();
|
|
93
93
|
|
|
94
|
-
if (!valid || events.some(event => event
|
|
94
|
+
if (!valid || events.some(event => event?.defaultPrevented)) {
|
|
95
95
|
return;
|
|
96
96
|
}
|
|
97
97
|
|
|
@@ -110,9 +110,9 @@ function afterEnd(
|
|
|
110
110
|
let insertion: 'afterend' | 'beforebegin';
|
|
111
111
|
|
|
112
112
|
if (position.y < top + height / 2) {
|
|
113
|
-
insertion =
|
|
113
|
+
insertion = 'beforebegin';
|
|
114
114
|
} else {
|
|
115
|
-
insertion =
|
|
115
|
+
insertion = 'afterend';
|
|
116
116
|
}
|
|
117
117
|
|
|
118
118
|
elements.target?.insertAdjacentElement(insertion, elements.origin!);
|
|
@@ -277,17 +277,23 @@ function onEnd(
|
|
|
277
277
|
cancelable: true,
|
|
278
278
|
};
|
|
279
279
|
|
|
280
|
-
const
|
|
281
|
-
const toEvent = new CustomEvent(EVENT_END, options);
|
|
280
|
+
const dispatchedFrom = dispatch(item.instance.element, 'sortable:end', options);
|
|
282
281
|
|
|
283
|
-
|
|
282
|
+
let dispatchedTo: CustomEvent | undefined;
|
|
284
283
|
|
|
285
|
-
if (item.instance !== toInstance) {
|
|
286
|
-
toInstance
|
|
284
|
+
if (item.instance !== toInstance && toInstance != null) {
|
|
285
|
+
dispatchedTo = dispatch(toInstance.element, 'sortable:end', options);
|
|
287
286
|
}
|
|
288
287
|
|
|
289
288
|
setTimeout(() => {
|
|
290
|
-
afterEnd(
|
|
289
|
+
afterEnd(
|
|
290
|
+
insert,
|
|
291
|
+
item,
|
|
292
|
+
[dispatchedFrom, dispatchedTo],
|
|
293
|
+
{origin, target: element},
|
|
294
|
+
position,
|
|
295
|
+
valid,
|
|
296
|
+
);
|
|
291
297
|
|
|
292
298
|
reset();
|
|
293
299
|
});
|
|
@@ -340,11 +346,11 @@ function onMove(
|
|
|
340
346
|
if (position.calculated.y < top + height / 2) {
|
|
341
347
|
place = 'before';
|
|
342
348
|
|
|
343
|
-
toElement.insertAdjacentElement(
|
|
349
|
+
toElement.insertAdjacentElement('beforebegin', placeholder);
|
|
344
350
|
} else {
|
|
345
351
|
place = 'after';
|
|
346
352
|
|
|
347
|
-
toElement.insertAdjacentElement(
|
|
353
|
+
toElement.insertAdjacentElement('afterend', placeholder);
|
|
348
354
|
}
|
|
349
355
|
|
|
350
356
|
setAttribute(placeholder, ATTRIBUTE_PLACEHOLDER_POSITION, place);
|
|
@@ -383,8 +389,7 @@ function setPlaceholder(
|
|
|
383
389
|
|
|
384
390
|
updatePlaceholder(item, element);
|
|
385
391
|
|
|
386
|
-
const
|
|
387
|
-
cancelable: true,
|
|
392
|
+
const dispatched = dispatch(item.instance.element, 'sortable:placeholder', {
|
|
388
393
|
detail: {
|
|
389
394
|
origin,
|
|
390
395
|
parent: item.state.element,
|
|
@@ -408,10 +413,8 @@ function setPlaceholder(
|
|
|
408
413
|
},
|
|
409
414
|
});
|
|
410
415
|
|
|
411
|
-
item.instance.element.dispatchEvent(event);
|
|
412
|
-
|
|
413
416
|
setTimeout(() => {
|
|
414
|
-
if (!
|
|
417
|
+
if (!dispatched.defaultPrevented && placeholder.drag.custom == null) {
|
|
415
418
|
placeholder.drag.default?.append(element.cloneNode(true));
|
|
416
419
|
}
|
|
417
420
|
|
|
@@ -492,14 +495,6 @@ const ATTRIBUTE_VERTICAL = `${ATTRIBUTE}-vertical`;
|
|
|
492
495
|
|
|
493
496
|
const CONTAINERS = new Map<HTMLElement, Set<OuiSortable>>();
|
|
494
497
|
|
|
495
|
-
const EVENT_END = 'sort:end';
|
|
496
|
-
|
|
497
|
-
const EVENT_PLACEHOLDER = 'sort:placeholder';
|
|
498
|
-
|
|
499
|
-
const INSERT_AFTER = 'afterend';
|
|
500
|
-
|
|
501
|
-
const INSERT_BEFORE = 'beforebegin';
|
|
502
|
-
|
|
503
498
|
const MESSAGE = 'The element must be an instance of HTMLElement or SVGElement';
|
|
504
499
|
|
|
505
500
|
const SELECTOR = `[${ATTRIBUTE}]`;
|
package/src/js/splitter.ts
CHANGED
|
@@ -5,14 +5,10 @@ import {setAria} from '@oscarpalmer/toretto/aria';
|
|
|
5
5
|
import {getAttribute, setAttribute} from '@oscarpalmer/toretto/attribute';
|
|
6
6
|
import {getPosition, on} from '@oscarpalmer/toretto/event';
|
|
7
7
|
import {findAncestor} from '@oscarpalmer/toretto/find';
|
|
8
|
-
import {setStyle,
|
|
8
|
+
import {setStyle, toggleStyles} from '@oscarpalmer/toretto/style';
|
|
9
9
|
import supportsTouch from '@oscarpalmer/toretto/touch';
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
interface HTMLElementTagNameMap {
|
|
13
|
-
[SELECTOR]: OuiSplitterElement;
|
|
14
|
-
}
|
|
15
|
-
}
|
|
11
|
+
// #region Special variables
|
|
16
12
|
|
|
17
13
|
const ATTRIBUTE_MAX = 'max';
|
|
18
14
|
|
|
@@ -22,6 +18,16 @@ const ATTRIBUTE_SIZE = 'size';
|
|
|
22
18
|
|
|
23
19
|
const ATTRIBUTE_TYPE = 'type';
|
|
24
20
|
|
|
21
|
+
// #endregion
|
|
22
|
+
|
|
23
|
+
// #region Types
|
|
24
|
+
|
|
25
|
+
declare global {
|
|
26
|
+
interface HTMLElementTagNameMap {
|
|
27
|
+
[TAGNAME]: OuiSplitterElement;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
25
31
|
class OuiSplitter {
|
|
26
32
|
element: OuiSplitterElement;
|
|
27
33
|
|
|
@@ -227,7 +233,9 @@ type OuiSplitterValuesNow = {
|
|
|
227
233
|
previous: number;
|
|
228
234
|
};
|
|
229
235
|
|
|
230
|
-
//
|
|
236
|
+
// #endregion
|
|
237
|
+
|
|
238
|
+
// #region Functions
|
|
231
239
|
|
|
232
240
|
function createHandle(): HTMLSpanElement {
|
|
233
241
|
const handle = document.createElement('span');
|
|
@@ -498,31 +506,33 @@ function setSize(splitter: OuiSplitter, size: number, previous?: boolean): void
|
|
|
498
506
|
setAriaValue(splitter);
|
|
499
507
|
}
|
|
500
508
|
|
|
501
|
-
//
|
|
509
|
+
// #endregion
|
|
502
510
|
|
|
503
|
-
|
|
511
|
+
// #region Variables
|
|
504
512
|
|
|
505
|
-
const
|
|
513
|
+
const TAGNAME = 'oui-splitter';
|
|
506
514
|
|
|
507
|
-
const
|
|
515
|
+
const ATTRIBUTE_ACTIVE = `${TAGNAME}-active`;
|
|
508
516
|
|
|
509
|
-
const
|
|
517
|
+
const ATTRIBUTE_HANDLE = `${TAGNAME}-handle`;
|
|
510
518
|
|
|
511
|
-
const
|
|
519
|
+
const ATTRIBUTE_HORIZONTAL = `${TAGNAME}-horizontal`;
|
|
512
520
|
|
|
513
|
-
const
|
|
521
|
+
const ATTRIBUTE_SEPARATOR = `${TAGNAME}-separator`;
|
|
514
522
|
|
|
515
|
-
const
|
|
523
|
+
const KEYS_ABSOLUTE = new Set(['End', 'Home']);
|
|
516
524
|
|
|
517
|
-
const
|
|
525
|
+
const KEYS_HORIZONTAL = new Set(['ArrowDown', 'ArrowUp']);
|
|
518
526
|
|
|
519
|
-
const
|
|
527
|
+
const KEYS_NEGATIVE = new Set(['ArrowLeft', 'ArrowUp']);
|
|
520
528
|
|
|
521
|
-
const
|
|
529
|
+
const KEYS_VERTICAL = new Set(['ArrowLeft', 'ArrowRight']);
|
|
522
530
|
|
|
523
|
-
const
|
|
531
|
+
const KEYS_ALL = new Set([...KEYS_ABSOLUTE, ...KEYS_HORIZONTAL, ...KEYS_VERTICAL]);
|
|
524
532
|
|
|
525
|
-
const
|
|
533
|
+
const MAPPED_ELEMENTS = new WeakMap<HTMLElement, OuiSplitter>();
|
|
534
|
+
|
|
535
|
+
const MESSAGE = `<${TAGNAME}> must have exactly two panels.`;
|
|
526
536
|
|
|
527
537
|
const METHODS_CONNECT = ['delete', 'set'] as const;
|
|
528
538
|
|
|
@@ -540,7 +550,7 @@ const RESIZE_OBSERVER: ResizeObserver = new ResizeObserver(onObservation);
|
|
|
540
550
|
|
|
541
551
|
const SELECTOR_HANDLE = `[${ATTRIBUTE_HANDLE}]`;
|
|
542
552
|
|
|
543
|
-
const STYLING_TOGGLER
|
|
553
|
+
const STYLING_TOGGLER = toggleStyles(document.body, {
|
|
544
554
|
touchAction: 'none',
|
|
545
555
|
userSelect: 'none',
|
|
546
556
|
webkitUserSelect: 'none',
|
|
@@ -554,9 +564,9 @@ let frame: DOMHighResTimeStamp | undefined;
|
|
|
554
564
|
|
|
555
565
|
let splitter: OuiSplitter | undefined;
|
|
556
566
|
|
|
557
|
-
//
|
|
567
|
+
// #endregion
|
|
558
568
|
|
|
559
|
-
|
|
569
|
+
// #region Initialization
|
|
560
570
|
|
|
561
571
|
on(document, 'keydown', onKeydown);
|
|
562
572
|
on(document, 'mousedown', onPointerdown);
|
|
@@ -564,3 +574,7 @@ on(document, 'pointermove', onPointermove);
|
|
|
564
574
|
on(document, 'pointerup', onPointerup);
|
|
565
575
|
on(document, 'touchcancel', onPointerup);
|
|
566
576
|
on(document, 'touchstart', onPointerdown, {passive: false});
|
|
577
|
+
|
|
578
|
+
customElements.define(TAGNAME, OuiSplitterElement);
|
|
579
|
+
|
|
580
|
+
// #endregion
|