-
Notifications
You must be signed in to change notification settings - Fork 1.1k
/
index.js
98 lines (83 loc) · 3.12 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
// eslint-disable-next-line import/no-unresolved
import {Draggable} from '@shopify/draggable';
function translateMirror(mirror, mirrorCoords, containerRect) {
if (mirrorCoords.top < containerRect.top || mirrorCoords.left < containerRect.left) {
return;
}
requestAnimationFrame(() => {
mirror.style.transform = `translate3d(${mirrorCoords.left}px, ${mirrorCoords.top}px, 0)`;
});
}
function calcOffset(offset) {
return offset * 2 * 0.5;
}
export default function DragEvents() {
const toggleClass = 'PillSwitch--isOn';
const containers = document.querySelectorAll('#DragEvents .PillSwitch');
if (containers.length === 0) {
return false;
}
const draggable = new Draggable(containers, {
draggable: '.PillSwitchControl',
delay: 0,
});
let isToggled = false;
let initialMousePosition;
let containerRect;
let dragRect;
let dragThreshold;
let headings;
let headingText;
// --- Draggable events --- //
draggable.on('drag:start', (evt) => {
initialMousePosition = {
x: evt.sensorEvent.clientX,
y: evt.sensorEvent.clientY,
};
});
draggable.on('mirror:created', (evt) => {
containerRect = evt.sourceContainer.getBoundingClientRect();
dragRect = evt.source.getBoundingClientRect();
const containerRectQuarter = containerRect.width / 4;
dragThreshold = isToggled ? containerRectQuarter * -1 : containerRectQuarter;
headings = {
source: evt.originalSource.querySelector('[data-switch-on]'),
mirror: evt.mirror.querySelector('[data-switch-on]'),
};
headingText = {
on: headings.source.dataset.switchOn,
off: headings.source.dataset.switchOff,
};
});
draggable.on('mirror:move', (evt) => {
// Required to help restrict the draggable element to the container
evt.cancel();
// We do not want to use `getBoundingClientRect` while dragging,
// as that would be very expensive.
// Instead, we look at the mouse position, which we can ballpark as being
// close to the center of the draggable element.
// We need to look at both the X and Y offset and determine which is the higher number.
// That way we can drag outside of the container and still have the
// draggable element move appropriately.
const offsetX = calcOffset(evt.sensorEvent.clientX - initialMousePosition.x);
const offsetY = calcOffset(initialMousePosition.y - evt.sensorEvent.clientY);
const offsetValue = offsetX > offsetY ? offsetX : offsetY;
const mirrorCoords = {
top: dragRect.top - offsetValue,
left: dragRect.left + offsetValue,
};
translateMirror(evt.mirror, mirrorCoords, containerRect);
if (isToggled && offsetValue < dragThreshold) {
evt.sourceContainer.classList.remove(toggleClass);
headings.source.textContent = headingText.off;
headings.mirror.textContent = headingText.off;
isToggled = false;
} else if (!isToggled && offsetValue > dragThreshold) {
evt.sourceContainer.classList.add(toggleClass);
headings.source.textContent = headingText.on;
headings.mirror.textContent = headingText.on;
isToggled = true;
}
});
return draggable;
}