@oscarpalmer/oui 0.26.1 → 0.28.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/floatable.css +9 -2
- package/dist/css/message.css +1 -0
- package/dist/css/reset.css +1 -0
- package/dist/js/dialog.d.mts +4 -0
- package/dist/js/dialog.mjs +33 -1
- package/dist/js/draggable-zszaW1qS.d.mts +155 -0
- package/dist/js/floatable/floatable.embedded.d.mts +2 -0
- package/dist/js/floatable/{embedded.mjs → floatable.embedded.mjs} +16 -11
- package/dist/js/floatable/floatable.standalone.d.mts +2 -0
- package/dist/js/floatable/floatable.standalone.mjs +2 -0
- package/dist/js/{embedded-CSOh5njI.d.mts → floatable.embedded-YxGwzgbE.d.mts} +5 -2
- package/dist/js/focus-trap/focus-trap.embedded.d.mts +2 -0
- package/dist/js/focus-trap/{embedded.mjs → focus-trap.embedded.mjs} +17 -15
- package/dist/js/focus-trap/focus-trap.standalone.d.mts +2 -0
- package/dist/js/focus-trap/focus-trap.standalone.mjs +2 -0
- package/dist/js/{embedded-CHK82Uh5.d.mts → focus-trap.embedded-DR8NpZfr.d.mts} +18 -18
- package/dist/js/index.d.mts +5 -3
- package/dist/js/index.mjs +11 -7
- package/dist/js/internal/draggable.d.mts +2 -2
- package/dist/js/internal/draggable.mjs +147 -95
- package/dist/js/movable/movable.embedded.d.mts +2 -0
- package/dist/js/movable/movable.embedded.mjs +184 -0
- package/dist/js/movable/movable.standalone.d.mts +2 -0
- package/dist/js/movable/movable.standalone.mjs +2 -0
- package/dist/js/popover.d.mts +2 -2
- package/dist/js/popover.mjs +4 -3
- package/dist/js/resizable/resizable.embedded.d.mts +2 -0
- package/dist/js/resizable/resizable.embedded.mjs +186 -0
- package/dist/js/resizable/resizable.standalone.d.mts +2 -0
- package/dist/js/resizable/resizable.standalone.mjs +2 -0
- package/dist/js/resizable.embedded-CXrUVPzR.d.mts +35 -0
- package/dist/js/sortable/sortable.embedded.d.mts +2 -0
- package/dist/js/{sortable.mjs → sortable/sortable.embedded.mjs} +88 -63
- package/dist/js/sortable/sortable.standalone.d.mts +2 -0
- package/dist/js/sortable/sortable.standalone.mjs +2 -0
- package/dist/js/splitter.mjs +6 -6
- package/dist/js/toolbar.mjs +6 -6
- package/dist/js/tooltip.d.mts +2 -2
- package/dist/js/tooltip.mjs +36 -33
- package/package.json +15 -11
- package/src/css/floatable.scss +9 -2
- package/src/css/form.scss +6 -6
- package/src/css/message.scss +1 -0
- package/src/css/reset.scss +1 -0
- package/src/js/dialog.ts +61 -1
- package/src/js/floatable/{embedded.ts → floatable.embedded.ts} +18 -10
- package/src/js/floatable/floatable.standalone.ts +6 -0
- package/src/js/focus-trap/{embedded.ts → focus-trap.embedded.ts} +20 -17
- package/src/js/focus-trap/focus-trap.standalone.ts +1 -0
- package/src/js/index.ts +5 -4
- package/src/js/internal/draggable.ts +310 -169
- package/src/js/movable/movable.embedded.ts +328 -0
- package/src/js/movable/movable.standalone.ts +2 -0
- package/src/js/popover.ts +3 -2
- package/src/js/resizable/resizable.embedded.ts +383 -0
- package/src/js/resizable/resizable.standalone.ts +5 -0
- package/src/js/{sortable.ts → sortable/sortable.embedded.ts} +170 -103
- package/src/js/sortable/sortable.standalone.ts +2 -0
- package/src/js/splitter.ts +1 -1
- package/src/js/tooltip.ts +49 -43
- package/dist/js/floatable/embedded.d.mts +0 -2
- package/dist/js/floatable/standalone.d.mts +0 -2
- package/dist/js/floatable/standalone.mjs +0 -2
- package/dist/js/focus-trap/embedded.d.mts +0 -2
- package/dist/js/focus-trap/standalone.d.mts +0 -2
- package/dist/js/focus-trap/standalone.mjs +0 -6
- package/dist/js/movable-dNqBctx3.d.mts +0 -101
- package/dist/js/movable.d.mts +0 -2
- package/dist/js/movable.mjs +0 -152
- package/dist/js/sortable.d.mts +0 -2
- package/src/js/floatable/standalone.ts +0 -1
- package/src/js/focus-trap/standalone.ts +0 -6
- package/src/js/movable.ts +0 -260
|
@@ -2,154 +2,230 @@ import type {EventPosition, PlainObject} from '@oscarpalmer/atoms/models';
|
|
|
2
2
|
import {clamp} from '@oscarpalmer/atoms/number';
|
|
3
3
|
import {getPosition, on} from '@oscarpalmer/toretto/event';
|
|
4
4
|
import {findAncestor} from '@oscarpalmer/toretto/find';
|
|
5
|
-
import {toggleStyles} from '@oscarpalmer/toretto/style';
|
|
5
|
+
import {toggleStyles, type StyleToggler} from '@oscarpalmer/toretto/style';
|
|
6
6
|
import supportsTouch from '@oscarpalmer/toretto/touch';
|
|
7
|
-
import type {OuiMovable} from '../movable';
|
|
8
|
-
import type {OuiSortable} from '../sortable';
|
|
7
|
+
import type {OuiMovable} from '../movable/movable.embedded';
|
|
8
|
+
import type {OuiSortable} from '../sortable/sortable.embedded';
|
|
9
|
+
import {isHTMLOrSVGElement} from '@oscarpalmer/toretto/is';
|
|
9
10
|
|
|
10
11
|
// #region Types
|
|
11
12
|
|
|
12
|
-
type
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
export type CreateOuiDraggableOptions = {
|
|
14
|
+
/**
|
|
15
|
+
* Container to hold the draggable element and restrict its movement within. Can be `body`, `document`, `window`, a _CSS_ selector, or an element. _(If not provided, the draggable element will not have any constraints)_
|
|
16
|
+
*/
|
|
17
|
+
container?: string | HTMLElement;
|
|
18
|
+
/**
|
|
19
|
+
* Direction in which the element can be dragged. _(If not provided, the element can be dragged in any direction)_
|
|
20
|
+
*/
|
|
21
|
+
direction?: OuiDraggableDirection;
|
|
22
|
+
};
|
|
16
23
|
|
|
17
|
-
|
|
24
|
+
type OuiDraggableDirection = 'horizontal' | 'vertical' | 'x' | 'y';
|
|
18
25
|
|
|
19
|
-
|
|
26
|
+
export abstract class OuiDraggable<ExtraState extends PlainObject = PlainObject> {
|
|
27
|
+
#destroyed = false;
|
|
20
28
|
|
|
21
|
-
|
|
29
|
+
#name: keyof OuiDraggableStates;
|
|
22
30
|
|
|
23
|
-
|
|
31
|
+
readonly #state: OuiDraggableState & ExtraState;
|
|
24
32
|
|
|
25
|
-
|
|
33
|
+
get element(): HTMLElement {
|
|
34
|
+
return this.#state.element;
|
|
35
|
+
}
|
|
26
36
|
|
|
27
37
|
constructor(
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
38
|
+
name: keyof OuiDraggableStates,
|
|
39
|
+
event: string,
|
|
40
|
+
attribute: string,
|
|
41
|
+
element: HTMLElement,
|
|
42
|
+
options: OuiDraggableOptions<ExtraState>,
|
|
43
|
+
extras: ExtraState,
|
|
31
44
|
) {
|
|
32
|
-
|
|
33
|
-
|
|
45
|
+
this.#name = name;
|
|
46
|
+
|
|
47
|
+
this.#state = {
|
|
48
|
+
...extras,
|
|
49
|
+
attribute,
|
|
50
|
+
element,
|
|
51
|
+
event,
|
|
52
|
+
options,
|
|
53
|
+
horizontal: true,
|
|
54
|
+
vertical: true,
|
|
55
|
+
styling: toggleStyles(element, styles),
|
|
56
|
+
} as OuiDraggableState & ExtraState;
|
|
57
|
+
|
|
58
|
+
const item = {
|
|
59
|
+
instance: this,
|
|
60
|
+
state: this.#state,
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
setContainer(item);
|
|
64
|
+
setDirection(item);
|
|
65
|
+
|
|
66
|
+
element.setAttribute(attribute, '');
|
|
67
|
+
|
|
68
|
+
let states = globals.states.get(element);
|
|
69
|
+
|
|
70
|
+
states ??= {};
|
|
71
|
+
|
|
72
|
+
states[this.#name] = this.#state;
|
|
73
|
+
|
|
74
|
+
globals.states.set(element, states);
|
|
34
75
|
}
|
|
35
76
|
|
|
36
77
|
destroy(): void {
|
|
37
|
-
|
|
78
|
+
if (this.#destroyed) {
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
this.#destroyed = true;
|
|
38
83
|
|
|
39
|
-
this
|
|
40
|
-
this.element = undefined!;
|
|
41
|
-
this.options = undefined!;
|
|
84
|
+
destroyInstance(this, this.#state);
|
|
42
85
|
}
|
|
43
86
|
}
|
|
44
87
|
|
|
45
|
-
type
|
|
88
|
+
type OuiDragBegin<State extends PlainObject = PlainObject> = (
|
|
46
89
|
event: MouseEvent | TouchEvent,
|
|
47
|
-
|
|
48
|
-
|
|
90
|
+
globals: OuiDraggableGlobals,
|
|
91
|
+
item: OuiDraggableItem<State>,
|
|
49
92
|
element: HTMLElement,
|
|
50
93
|
handle: HTMLElement,
|
|
51
94
|
position: EventPosition,
|
|
52
95
|
) => void;
|
|
53
96
|
|
|
54
|
-
type
|
|
97
|
+
type OuiDragCancel<State extends PlainObject = PlainObject> = (
|
|
98
|
+
globals: OuiDraggableGlobals,
|
|
99
|
+
item: OuiDraggableItem<State>,
|
|
100
|
+
) => void;
|
|
55
101
|
|
|
56
|
-
type
|
|
102
|
+
type OuiDragEnd<State extends PlainObject = PlainObject> = (
|
|
57
103
|
event: MouseEvent | TouchEvent,
|
|
58
|
-
|
|
59
|
-
|
|
104
|
+
globals: OuiDraggableGlobals,
|
|
105
|
+
item: OuiDraggableItem<State>,
|
|
60
106
|
reset: () => void,
|
|
61
107
|
) => void;
|
|
62
108
|
|
|
63
|
-
type
|
|
109
|
+
type OuiDragMove<State extends PlainObject = PlainObject> = (
|
|
64
110
|
event: MouseEvent | TouchEvent,
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
position:
|
|
111
|
+
globals: OuiDraggableGlobals,
|
|
112
|
+
item: OuiDraggableItem<State>,
|
|
113
|
+
position: OuiDragMovePosition,
|
|
68
114
|
) => PlainObject | undefined;
|
|
69
115
|
|
|
70
|
-
export type
|
|
116
|
+
export type OuiDragMovePosition = {
|
|
71
117
|
calculated: EventPosition;
|
|
72
118
|
original: EventPosition;
|
|
73
119
|
};
|
|
74
120
|
|
|
75
|
-
export type
|
|
76
|
-
Property extends keyof
|
|
77
|
-
Instance extends
|
|
121
|
+
export type OuiDraggableBound<
|
|
122
|
+
Property extends keyof OuiDraggableInstances = keyof OuiDraggableInstances,
|
|
123
|
+
Instance extends OuiDraggableInstances[Property] = OuiDraggableInstances[Property],
|
|
78
124
|
> = {
|
|
79
|
-
constructor: new (element: HTMLElement) => Instance;
|
|
125
|
+
constructor: new (element: HTMLElement, options?: CreateOuiDraggableOptions) => Instance;
|
|
80
126
|
property: Property;
|
|
81
127
|
};
|
|
82
128
|
|
|
83
|
-
type
|
|
129
|
+
export type OuiDraggableGlobals = {
|
|
130
|
+
container?: DOMRect;
|
|
131
|
+
element?: OuiDraggableGlobalsElement;
|
|
132
|
+
instances: WeakMap<HTMLElement, OuiDraggableInstances>;
|
|
133
|
+
offset?: EventPosition;
|
|
134
|
+
original?: EventPosition;
|
|
135
|
+
states: WeakMap<HTMLElement, OuiDraggableStates>;
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
type OuiDraggableGlobalsElement = {
|
|
139
|
+
node: HTMLElement;
|
|
140
|
+
rectangle: DOMRect;
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
type OuiDraggableInstances = {
|
|
84
144
|
movable?: OuiMovable;
|
|
85
145
|
sortable?: OuiSortable;
|
|
86
146
|
};
|
|
87
147
|
|
|
88
|
-
type
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
148
|
+
export type OuiDraggableItem<ExtraState extends PlainObject = PlainObject> = {
|
|
149
|
+
instance: OuiDraggable<ExtraState>;
|
|
150
|
+
state: OuiDraggableState & ExtraState;
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
type OuiDraggableOptions<ExtraState extends PlainObject = PlainObject> = {
|
|
154
|
+
container: OuiDraggableOptionsContainer<ExtraState>;
|
|
155
|
+
direction: OuiDraggableOptionsDirection<ExtraState>;
|
|
156
|
+
drag: OuiDraggableOptionsDrag<ExtraState>;
|
|
157
|
+
input?: CreateOuiDraggableOptions;
|
|
158
|
+
position: OuiDraggableOptionsPosition<ExtraState>;
|
|
159
|
+
getDragged(): HTMLElement;
|
|
160
|
+
getOrigin(): HTMLElement | undefined;
|
|
93
161
|
};
|
|
94
162
|
|
|
95
|
-
type
|
|
163
|
+
type OuiDraggableOptionsContainer<ExtraState extends PlainObject = PlainObject> = {
|
|
96
164
|
attribute: string;
|
|
97
165
|
map: Map<HTMLElement, Set<OuiDraggable>>;
|
|
98
|
-
onDestroy?:
|
|
99
|
-
onInitialize?:
|
|
166
|
+
onDestroy?: OuiDraggableOptionsContainerOnDestroy<ExtraState>;
|
|
167
|
+
onInitialize?: OuiDraggableOptionsContainerOnInitialize;
|
|
100
168
|
};
|
|
101
169
|
|
|
102
|
-
type
|
|
103
|
-
|
|
170
|
+
type OuiDraggableOptionsContainerOnDestroy<ExtraState extends PlainObject = PlainObject> = (
|
|
171
|
+
item: OuiDraggableItem<ExtraState>,
|
|
104
172
|
container: HTMLElement,
|
|
105
173
|
empty: boolean,
|
|
106
174
|
) => void;
|
|
107
175
|
|
|
108
|
-
type
|
|
176
|
+
type OuiDraggableOptionsContainerOnInitialize<ExtraState extends PlainObject = PlainObject> = (
|
|
177
|
+
item: OuiDraggableItem<ExtraState>,
|
|
178
|
+
) => void;
|
|
109
179
|
|
|
110
|
-
type
|
|
180
|
+
type OuiDraggableOptionsDirection<ExtraState extends PlainObject = PlainObject> = {
|
|
111
181
|
attribute: string;
|
|
112
|
-
onAfter?:
|
|
182
|
+
onAfter?: OuiDraggableOptionsDirectionOnAfter<ExtraState>;
|
|
113
183
|
};
|
|
114
184
|
|
|
115
|
-
type
|
|
185
|
+
type OuiDraggableOptionsDirectionOnAfter<ExtraState extends PlainObject = PlainObject> = (
|
|
186
|
+
item: OuiDraggableItem<ExtraState>,
|
|
187
|
+
) => void;
|
|
116
188
|
|
|
117
|
-
type
|
|
118
|
-
onBegin:
|
|
119
|
-
onCancel:
|
|
120
|
-
onEnd:
|
|
121
|
-
onMove:
|
|
189
|
+
type OuiDraggableOptionsDrag<ExtraState extends PlainObject = PlainObject> = {
|
|
190
|
+
onBegin: OuiDragBegin<ExtraState>;
|
|
191
|
+
onCancel: OuiDragCancel<ExtraState>;
|
|
192
|
+
onEnd: OuiDragEnd<ExtraState>;
|
|
193
|
+
onMove: OuiDragMove<ExtraState>;
|
|
122
194
|
};
|
|
123
195
|
|
|
124
|
-
type
|
|
125
|
-
getOffset:
|
|
126
|
-
getOriginal:
|
|
196
|
+
type OuiDraggableOptionsPosition<ExtraState extends PlainObject = PlainObject> = {
|
|
197
|
+
getOffset: OuiDraggableOptionsPositionGetOffset<ExtraState>;
|
|
198
|
+
getOriginal: OuiDraggableOptionsPositionGetOriginal<ExtraState>;
|
|
127
199
|
};
|
|
128
200
|
|
|
129
|
-
type
|
|
130
|
-
|
|
131
|
-
|
|
201
|
+
type OuiDraggableOptionsPositionGetOffset<ExtraState extends PlainObject = PlainObject> = (
|
|
202
|
+
globals: OuiDraggableGlobals,
|
|
203
|
+
item: OuiDraggableItem<ExtraState>,
|
|
132
204
|
element: HTMLElement,
|
|
133
205
|
position: EventPosition,
|
|
134
206
|
) => EventPosition;
|
|
135
207
|
|
|
136
|
-
type
|
|
137
|
-
|
|
138
|
-
|
|
208
|
+
type OuiDraggableOptionsPositionGetOriginal<ExtraState extends PlainObject = PlainObject> = (
|
|
209
|
+
globals: OuiDraggableGlobals,
|
|
210
|
+
item: OuiDraggableItem<ExtraState>,
|
|
139
211
|
position: EventPosition,
|
|
140
212
|
) => EventPosition;
|
|
141
213
|
|
|
142
|
-
export type
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
214
|
+
export type OuiDraggableState = {
|
|
215
|
+
attribute: string;
|
|
216
|
+
container?: HTMLElement;
|
|
217
|
+
element: HTMLElement;
|
|
218
|
+
event: string;
|
|
219
|
+
hasHandles?: boolean;
|
|
220
|
+
horizontal: boolean;
|
|
221
|
+
options: OuiDraggableOptions;
|
|
222
|
+
styling: StyleToggler;
|
|
223
|
+
vertical: boolean;
|
|
148
224
|
};
|
|
149
225
|
|
|
150
|
-
type
|
|
151
|
-
|
|
152
|
-
|
|
226
|
+
type OuiDraggableStates = {
|
|
227
|
+
movable?: OuiDraggableState;
|
|
228
|
+
sortable?: OuiDraggableState;
|
|
153
229
|
};
|
|
154
230
|
|
|
155
231
|
// #endregion
|
|
@@ -157,18 +233,43 @@ type DraggableStateElement = {
|
|
|
157
233
|
// #region Functions
|
|
158
234
|
|
|
159
235
|
export function addDraggable<
|
|
160
|
-
Property extends keyof
|
|
161
|
-
Instance extends
|
|
162
|
-
>(
|
|
163
|
-
|
|
236
|
+
Property extends keyof OuiDraggableInstances,
|
|
237
|
+
Instance extends OuiDraggableInstances[Property],
|
|
238
|
+
>(
|
|
239
|
+
this: OuiDraggableBound<Property, Instance>,
|
|
240
|
+
element: HTMLElement,
|
|
241
|
+
options?: CreateOuiDraggableOptions,
|
|
242
|
+
): Instance {
|
|
243
|
+
let instances = globals.instances.get(element);
|
|
164
244
|
|
|
165
245
|
if (instances == null) {
|
|
166
246
|
instances = {};
|
|
167
247
|
|
|
168
|
-
|
|
248
|
+
globals.instances.set(element, instances);
|
|
169
249
|
}
|
|
170
250
|
|
|
171
|
-
instances[this.property] ??= new this.constructor(element);
|
|
251
|
+
instances[this.property] ??= new this.constructor(element, options);
|
|
252
|
+
|
|
253
|
+
return instances[this.property] as Instance;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
function destroyInstance(instance: OuiDraggable, state: OuiDraggableState): void {
|
|
257
|
+
unsetContainer({
|
|
258
|
+
instance,
|
|
259
|
+
state,
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
state.element.removeAttribute(state.attribute);
|
|
263
|
+
state.styling.remove();
|
|
264
|
+
|
|
265
|
+
state.container = undefined;
|
|
266
|
+
state.element = undefined as never;
|
|
267
|
+
state.options = undefined as never;
|
|
268
|
+
state.styling = undefined as never;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
export function getDraggableStates(element: HTMLElement): OuiDraggableStates | undefined {
|
|
272
|
+
return globals.states.get(element);
|
|
172
273
|
}
|
|
173
274
|
|
|
174
275
|
function getHandle(event: Event, isMovable: boolean): HTMLElement | null {
|
|
@@ -178,23 +279,31 @@ function getHandle(event: Event, isMovable: boolean): HTMLElement | null {
|
|
|
178
279
|
) as HTMLElement;
|
|
179
280
|
}
|
|
180
281
|
|
|
181
|
-
function getNextPosition(
|
|
182
|
-
let x =
|
|
183
|
-
let y =
|
|
282
|
+
function getNextPosition(item: OuiDraggableItem, position: EventPosition): EventPosition {
|
|
283
|
+
let x = globals.original?.x ?? 0;
|
|
284
|
+
let y = globals.original?.y ?? 0;
|
|
184
285
|
|
|
185
|
-
if (
|
|
186
|
-
x = position.x - (
|
|
286
|
+
if (item.state.horizontal) {
|
|
287
|
+
x = position.x - (globals.offset?.x ?? 0);
|
|
187
288
|
|
|
188
|
-
if (
|
|
189
|
-
x = clamp(
|
|
289
|
+
if (globals.container != null && globals.element != null) {
|
|
290
|
+
x = clamp(
|
|
291
|
+
x,
|
|
292
|
+
globals.container.left,
|
|
293
|
+
globals.container.right - globals.element.rectangle.width,
|
|
294
|
+
);
|
|
190
295
|
}
|
|
191
296
|
}
|
|
192
297
|
|
|
193
|
-
if (
|
|
194
|
-
y = position.y - (
|
|
298
|
+
if (item.state.vertical) {
|
|
299
|
+
y = position.y - (globals.offset?.y ?? 0);
|
|
195
300
|
|
|
196
|
-
if (
|
|
197
|
-
y = clamp(
|
|
301
|
+
if (globals.container != null && globals.element != null) {
|
|
302
|
+
y = clamp(
|
|
303
|
+
y,
|
|
304
|
+
globals.container.top,
|
|
305
|
+
globals.container.bottom - globals.element.rectangle.height,
|
|
306
|
+
);
|
|
198
307
|
}
|
|
199
308
|
}
|
|
200
309
|
|
|
@@ -206,14 +315,12 @@ function onKeydown(event: KeyboardEvent): void {
|
|
|
206
315
|
return;
|
|
207
316
|
}
|
|
208
317
|
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
current.options.drag.onCancel?.(state, current);
|
|
318
|
+
current.state.options.drag.onCancel?.(globals, current);
|
|
212
319
|
|
|
213
|
-
current.element.dispatchEvent(
|
|
214
|
-
new CustomEvent(`${current.
|
|
320
|
+
current.state.element.dispatchEvent(
|
|
321
|
+
new CustomEvent(`${current.state.event}:cancel`, {
|
|
215
322
|
detail: {
|
|
216
|
-
element:
|
|
323
|
+
element: current.state.options.getOrigin(),
|
|
217
324
|
},
|
|
218
325
|
}),
|
|
219
326
|
);
|
|
@@ -235,17 +342,22 @@ function onPointerdown(event: MouseEvent | TouchEvent): void {
|
|
|
235
342
|
}
|
|
236
343
|
|
|
237
344
|
const container = findAncestor(event, SELECTOR)! as HTMLElement;
|
|
238
|
-
const instances = state.instances.get(container!);
|
|
239
345
|
|
|
240
|
-
|
|
346
|
+
const instances = globals.instances.get(container!);
|
|
347
|
+
const states = globals.states.get(container);
|
|
348
|
+
|
|
349
|
+
if (instances == null || states == null) {
|
|
241
350
|
return;
|
|
242
351
|
}
|
|
243
352
|
|
|
244
353
|
const isMovable = container.hasAttribute(ATTRIBUTE_MOVABLE);
|
|
245
354
|
|
|
246
|
-
const
|
|
355
|
+
const item: OuiDraggableItem = {
|
|
356
|
+
instance: (isMovable ? instances.movable : instances.sortable) as OuiDraggable,
|
|
357
|
+
state: (isMovable ? states.movable : states.sortable) as OuiDraggableState,
|
|
358
|
+
};
|
|
247
359
|
|
|
248
|
-
if (instance == null) {
|
|
360
|
+
if (item.instance == null || item.state == null) {
|
|
249
361
|
return;
|
|
250
362
|
}
|
|
251
363
|
|
|
@@ -265,9 +377,9 @@ function onPointerdown(event: MouseEvent | TouchEvent): void {
|
|
|
265
377
|
|
|
266
378
|
let handle: HTMLElement | null = element;
|
|
267
379
|
|
|
268
|
-
|
|
380
|
+
item.state.hasHandles ??= element.querySelector(SELECTOR_SORTABLE_HANDLE) != null;
|
|
269
381
|
|
|
270
|
-
if (
|
|
382
|
+
if (item.state.hasHandles) {
|
|
271
383
|
handle = getHandle(event, isMovable);
|
|
272
384
|
}
|
|
273
385
|
|
|
@@ -275,50 +387,51 @@ function onPointerdown(event: MouseEvent | TouchEvent): void {
|
|
|
275
387
|
return;
|
|
276
388
|
}
|
|
277
389
|
|
|
278
|
-
const
|
|
279
|
-
|
|
390
|
+
const dragged = item.state.options.getDragged();
|
|
280
391
|
const rectangle = dragged.getBoundingClientRect();
|
|
281
392
|
|
|
282
393
|
const position = getPosition(event) ?? {x: 0, y: 0};
|
|
283
394
|
|
|
284
|
-
current =
|
|
395
|
+
current = item;
|
|
285
396
|
|
|
286
|
-
|
|
397
|
+
globals.container = item.state.container?.getBoundingClientRect();
|
|
287
398
|
|
|
288
|
-
|
|
399
|
+
globals.element = {
|
|
289
400
|
rectangle,
|
|
290
401
|
node: dragged,
|
|
291
402
|
};
|
|
292
403
|
|
|
293
|
-
|
|
294
|
-
|
|
404
|
+
globals.offset = item.state.options.position.getOffset(globals, item, element, position);
|
|
405
|
+
globals.original = item.state.options.position.getOriginal(globals, item, position);
|
|
295
406
|
|
|
296
|
-
const begin = new CustomEvent(`${
|
|
407
|
+
const begin = new CustomEvent(`${item.state.event}:begin`, {
|
|
297
408
|
detail: {
|
|
298
409
|
element,
|
|
299
|
-
position: {...
|
|
410
|
+
position: {...globals.original},
|
|
300
411
|
},
|
|
301
412
|
cancelable: true,
|
|
302
413
|
});
|
|
303
414
|
|
|
304
|
-
|
|
415
|
+
item.state.element.dispatchEvent(begin);
|
|
305
416
|
|
|
306
417
|
setTimeout(() => {
|
|
307
418
|
if (begin.defaultPrevented) {
|
|
308
|
-
|
|
419
|
+
item.state.options.drag.onCancel?.(globals, item);
|
|
309
420
|
|
|
310
421
|
reset();
|
|
311
422
|
|
|
312
423
|
return;
|
|
313
424
|
}
|
|
314
425
|
|
|
315
|
-
const next = getNextPosition(
|
|
426
|
+
const next = getNextPosition(item, position);
|
|
316
427
|
|
|
317
428
|
dragged.style.position = 'fixed';
|
|
318
429
|
dragged.style.inset = `${next.y}px auto auto ${next.x}px`;
|
|
430
|
+
dragged.style.transform = 'translate3d(0, 0, 0)';
|
|
319
431
|
|
|
320
|
-
|
|
432
|
+
item.state.options.drag.onBegin?.(event, globals, item, element, handle, next);
|
|
321
433
|
|
|
434
|
+
item.state.styling.set();
|
|
322
435
|
styleToggler.set();
|
|
323
436
|
});
|
|
324
437
|
}
|
|
@@ -336,29 +449,29 @@ function onPointermove(event: MouseEvent | TouchEvent): void {
|
|
|
336
449
|
|
|
337
450
|
const next = getNextPosition(current, position);
|
|
338
451
|
|
|
339
|
-
if (
|
|
340
|
-
|
|
452
|
+
if (globals.element != null) {
|
|
453
|
+
globals.element.node.style.inset = `${next.y}px auto auto ${next.x}px`;
|
|
341
454
|
}
|
|
342
455
|
|
|
343
|
-
const detail = current.options.drag.onMove(event,
|
|
456
|
+
const detail = current.state.options.drag.onMove(event, globals, current, {
|
|
344
457
|
calculated: next,
|
|
345
458
|
original: position,
|
|
346
459
|
});
|
|
347
460
|
|
|
348
|
-
current.element.dispatchEvent(
|
|
349
|
-
new CustomEvent(`${current.
|
|
461
|
+
current.state.element.dispatchEvent(
|
|
462
|
+
new CustomEvent(`${current.state.event}:move`, {
|
|
350
463
|
detail,
|
|
351
464
|
}),
|
|
352
465
|
);
|
|
353
466
|
}
|
|
354
467
|
|
|
355
468
|
function onPointerup(event: MouseEvent | TouchEvent): void {
|
|
356
|
-
current?.options.drag.onEnd?.(event,
|
|
469
|
+
current?.state.options.drag.onEnd?.(event, globals, current, reset);
|
|
357
470
|
}
|
|
358
471
|
|
|
359
472
|
export function removeDraggable<
|
|
360
|
-
Property extends keyof
|
|
361
|
-
Instance extends
|
|
473
|
+
Property extends keyof OuiDraggableInstances,
|
|
474
|
+
Instance extends OuiDraggableInstances[Property],
|
|
362
475
|
>(
|
|
363
476
|
this: {
|
|
364
477
|
constructor: new (element: HTMLElement) => Instance;
|
|
@@ -368,92 +481,117 @@ export function removeDraggable<
|
|
|
368
481
|
): void {
|
|
369
482
|
const {property} = this;
|
|
370
483
|
|
|
371
|
-
|
|
484
|
+
removeInstance(globals.instances, property, element);
|
|
485
|
+
removeInstance(globals.states, property, element);
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
function removeInstance(
|
|
489
|
+
map: WeakMap<HTMLElement, OuiDraggableInstances | OuiDraggableStates>,
|
|
490
|
+
name: keyof OuiDraggableInstances | keyof OuiDraggableStates,
|
|
491
|
+
element: HTMLElement,
|
|
492
|
+
): void {
|
|
493
|
+
const instances = map.get(element);
|
|
372
494
|
|
|
373
|
-
if (instances == null || instances[
|
|
495
|
+
if (instances == null || instances[name] == null) {
|
|
374
496
|
return;
|
|
375
497
|
}
|
|
376
498
|
|
|
377
|
-
instances[
|
|
499
|
+
if (typeof (instances[name] as OuiDraggable).destroy === 'function') {
|
|
500
|
+
(instances[name] as OuiDraggable).destroy();
|
|
501
|
+
}
|
|
378
502
|
|
|
379
|
-
instances[
|
|
503
|
+
instances[name] = undefined;
|
|
380
504
|
|
|
381
|
-
if (instances[properties[
|
|
382
|
-
|
|
505
|
+
if (instances[properties[name]] == null) {
|
|
506
|
+
map.delete(element);
|
|
383
507
|
}
|
|
384
508
|
}
|
|
385
509
|
|
|
386
510
|
function reset(): void {
|
|
387
|
-
current
|
|
511
|
+
current?.state.styling.remove();
|
|
512
|
+
styleToggler.remove();
|
|
388
513
|
|
|
389
|
-
|
|
390
|
-
state.element = undefined;
|
|
391
|
-
state.offset = undefined;
|
|
392
|
-
state.original = undefined;
|
|
514
|
+
current = undefined;
|
|
393
515
|
|
|
394
|
-
|
|
516
|
+
globals.container = undefined;
|
|
517
|
+
globals.element = undefined;
|
|
518
|
+
globals.offset = undefined;
|
|
519
|
+
globals.original = undefined;
|
|
395
520
|
}
|
|
396
521
|
|
|
397
|
-
function setContainer(
|
|
398
|
-
const
|
|
522
|
+
function setContainer(item: OuiDraggableItem): void {
|
|
523
|
+
const {container} = item.state.options.input ?? {};
|
|
524
|
+
|
|
525
|
+
if (isHTMLOrSVGElement(container)) {
|
|
526
|
+
setContainerElement(item, container);
|
|
527
|
+
|
|
528
|
+
return;
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
const selector =
|
|
532
|
+
container ?? item.instance.element.getAttribute(item.state.options.container.attribute);
|
|
399
533
|
|
|
400
534
|
if (typeof selector !== 'string') {
|
|
401
535
|
return;
|
|
402
536
|
}
|
|
403
537
|
|
|
404
|
-
|
|
405
|
-
?
|
|
538
|
+
const element = containers.has(selector)
|
|
539
|
+
? item.state.element.ownerDocument.body
|
|
406
540
|
: (document.querySelector(selector) ?? undefined);
|
|
407
541
|
|
|
408
|
-
if (
|
|
409
|
-
|
|
542
|
+
if (isHTMLOrSVGElement(element)) {
|
|
543
|
+
setContainerElement(item, element);
|
|
410
544
|
}
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
function setContainerElement(item: OuiDraggableItem, element: HTMLElement): void {
|
|
548
|
+
item.state.container = element;
|
|
411
549
|
|
|
412
|
-
const set = options.container.map.get(
|
|
550
|
+
const set = item.state.options.container.map.get(element);
|
|
413
551
|
|
|
414
552
|
if (set == null) {
|
|
415
|
-
options.container.map.set(
|
|
553
|
+
item.state.options.container.map.set(element, new Set([item.instance]));
|
|
416
554
|
} else {
|
|
417
|
-
set.add(
|
|
555
|
+
set.add(item.instance);
|
|
418
556
|
}
|
|
419
557
|
|
|
420
|
-
options.container.onInitialize?.(
|
|
558
|
+
item.state.options.container.onInitialize?.(item);
|
|
421
559
|
}
|
|
422
560
|
|
|
423
|
-
function setDirection(
|
|
424
|
-
const direction =
|
|
561
|
+
function setDirection(item: OuiDraggableItem): void {
|
|
562
|
+
const direction = item.state.element.getAttribute(item.state.options.direction.attribute);
|
|
425
563
|
|
|
426
|
-
if (horizontals.has(direction as
|
|
427
|
-
|
|
428
|
-
} else if (verticals.has(direction as
|
|
429
|
-
|
|
564
|
+
if (horizontals.has(direction as OuiDraggableDirection)) {
|
|
565
|
+
item.state.vertical = false;
|
|
566
|
+
} else if (verticals.has(direction as OuiDraggableDirection)) {
|
|
567
|
+
item.state.horizontal = false;
|
|
430
568
|
}
|
|
431
569
|
|
|
432
|
-
options.direction.onAfter?.(
|
|
570
|
+
item.state.options.direction.onAfter?.(item);
|
|
433
571
|
}
|
|
434
572
|
|
|
435
|
-
function unsetContainer(
|
|
436
|
-
const {container} =
|
|
573
|
+
function unsetContainer(item: OuiDraggableItem): void {
|
|
574
|
+
const {container} = item.state;
|
|
437
575
|
|
|
438
576
|
if (container == null) {
|
|
439
577
|
return;
|
|
440
578
|
}
|
|
441
579
|
|
|
442
|
-
const set = options.container.map.get(container);
|
|
580
|
+
const set = item.state.options.container.map.get(container);
|
|
443
581
|
|
|
444
582
|
let empty = false;
|
|
445
583
|
|
|
446
584
|
if (set != null) {
|
|
447
|
-
set.delete(
|
|
585
|
+
set.delete(item.instance);
|
|
448
586
|
|
|
449
587
|
if (set.size === 0) {
|
|
450
588
|
empty = true;
|
|
451
589
|
|
|
452
|
-
options.container.map.delete(container);
|
|
590
|
+
item.state.options.container.map.delete(container);
|
|
453
591
|
}
|
|
454
592
|
}
|
|
455
593
|
|
|
456
|
-
options.container.onDestroy?.(
|
|
594
|
+
item.state.options.container.onDestroy?.(item, container, empty);
|
|
457
595
|
}
|
|
458
596
|
|
|
459
597
|
// #endregion
|
|
@@ -474,32 +612,35 @@ const SELECTOR_SORTABLE_HANDLE = `[${ATTRIBUTE_SORTABLE}-handle]`;
|
|
|
474
612
|
|
|
475
613
|
const SELECTOR_SORTABLE_ITEM = `[${ATTRIBUTE_SORTABLE}] > *`;
|
|
476
614
|
|
|
477
|
-
const
|
|
615
|
+
const containers = new Set<string>(['body', 'document', 'window']);
|
|
478
616
|
|
|
479
|
-
const horizontals = new Set<
|
|
617
|
+
const horizontals = new Set<OuiDraggableDirection>(['horizontal', 'x']);
|
|
480
618
|
|
|
481
|
-
const properties: Record<keyof
|
|
619
|
+
const properties: Record<keyof OuiDraggableInstances, keyof OuiDraggableInstances> = {
|
|
482
620
|
movable: 'sortable',
|
|
483
621
|
sortable: 'movable',
|
|
484
622
|
};
|
|
485
623
|
|
|
486
|
-
const
|
|
624
|
+
const globals: OuiDraggableGlobals = {
|
|
487
625
|
container: undefined,
|
|
488
626
|
element: undefined,
|
|
489
627
|
instances: new WeakMap(),
|
|
490
628
|
offset: undefined,
|
|
491
629
|
original: undefined,
|
|
630
|
+
states: new WeakMap(),
|
|
492
631
|
};
|
|
493
632
|
|
|
494
|
-
const
|
|
633
|
+
const styles = {
|
|
495
634
|
touchAction: 'none',
|
|
496
635
|
userSelect: 'none',
|
|
497
636
|
webkitUserSelect: 'none',
|
|
498
|
-
}
|
|
637
|
+
};
|
|
638
|
+
|
|
639
|
+
const styleToggler = toggleStyles(document.body, styles);
|
|
499
640
|
|
|
500
|
-
const verticals = new Set<
|
|
641
|
+
const verticals = new Set<OuiDraggableDirection>(['vertical', 'y']);
|
|
501
642
|
|
|
502
|
-
let current:
|
|
643
|
+
let current: OuiDraggableItem | undefined;
|
|
503
644
|
|
|
504
645
|
// #endregion
|
|
505
646
|
|
|
@@ -509,7 +650,7 @@ on(document, 'keydown', onKeydown);
|
|
|
509
650
|
on(document, 'mousedown', onPointerdown);
|
|
510
651
|
on(document, 'pointermove', onPointermove);
|
|
511
652
|
on(document, 'pointerup', onPointerup);
|
|
512
|
-
on(document, 'touchcancel', onPointerup
|
|
653
|
+
on(document, 'touchcancel', onPointerup);
|
|
513
654
|
on(document, 'touchstart', onPointerdown, {passive: false});
|
|
514
655
|
|
|
515
656
|
// #endregion
|