@marsio/vue-draggable 1.0.2 → 1.0.3
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/README.md +86 -46
- package/build/cjs/Draggable.js +57 -25
- package/build/cjs/DraggableCore.js +44 -21
- package/build/cjs/utils/domFns.js +221 -97
- package/build/cjs/utils/log.js +2 -3
- package/build/cjs/utils/positionFns.js +86 -68
- package/build/cjs/utils/shims.js +45 -6
- package/build/cjs/utils/types.js +10 -2
- package/build/web/vue-draggable.min.js +1 -2
- package/package.json +33 -11
- package/LICENSE +0 -21
- package/build/cjs/utils/test.js +0 -12
- package/build/web/vue-draggable.min.js.LICENSE.txt +0 -6
|
@@ -3,43 +3,47 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports.addClassName =
|
|
7
|
-
exports.addEvent = addEvent;
|
|
8
|
-
exports.addUserSelectStyles = addUserSelectStyles;
|
|
9
|
-
exports.createCSSTransform = createCSSTransform;
|
|
10
|
-
exports.createSVGTransform = createSVGTransform;
|
|
11
|
-
exports.getTouch = getTouch;
|
|
12
|
-
exports.getTouchIdentifier = getTouchIdentifier;
|
|
13
|
-
exports.getTranslation = getTranslation;
|
|
14
|
-
exports.innerHeight = innerHeight;
|
|
15
|
-
exports.innerWidth = innerWidth;
|
|
16
|
-
exports.matchesSelector = matchesSelector;
|
|
17
|
-
exports.matchesSelectorAndParentsTo = matchesSelectorAndParentsTo;
|
|
18
|
-
exports.offsetXYFromParent = offsetXYFromParent;
|
|
19
|
-
exports.outerHeight = outerHeight;
|
|
20
|
-
exports.outerWidth = outerWidth;
|
|
21
|
-
exports.removeClassName = removeClassName;
|
|
22
|
-
exports.removeEvent = removeEvent;
|
|
23
|
-
exports.removeUserSelectStyles = removeUserSelectStyles;
|
|
6
|
+
exports.removeUserSelectStyles = exports.removeEvent = exports.removeClassName = exports.outerWidth = exports.outerHeight = exports.offsetXYFromParent = exports.matchesSelectorAndParentsTo = exports.matchesSelector = exports.innerWidth = exports.innerHeight = exports.getTranslation = exports.getTouchIdentifier = exports.getTouch = exports.createSVGTransform = exports.createCSSTransform = exports.addUserSelectStyles = exports.addEvent = exports.addClassName = void 0;
|
|
24
7
|
var _getPrefix = _interopRequireWildcard(require("./getPrefix"));
|
|
25
8
|
var _shims = require("./shims");
|
|
26
9
|
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
|
27
|
-
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u &&
|
|
10
|
+
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
|
11
|
+
/**
|
|
12
|
+
* Provides utility functions for DOM manipulation and event handling.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Cached method name for matchesSelector.
|
|
17
|
+
*/
|
|
28
18
|
let matchesSelectorFunc = '';
|
|
29
|
-
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Checks if the element matches the given CSS selector.
|
|
22
|
+
*
|
|
23
|
+
* @param el - The element to check.
|
|
24
|
+
* @param selector - The CSS selector to match against.
|
|
25
|
+
* @returns True if the element matches the selector, false otherwise.
|
|
26
|
+
*/
|
|
27
|
+
const matchesSelector = (el, selector) => {
|
|
30
28
|
if (!matchesSelectorFunc) {
|
|
31
29
|
matchesSelectorFunc = (0, _shims.findInArray)(['matches', 'webkitMatchesSelector', 'mozMatchesSelector', 'msMatchesSelector', 'oMatchesSelector'], function (method) {
|
|
32
30
|
return (0, _shims.isFunction)(el[method]);
|
|
33
31
|
});
|
|
34
32
|
}
|
|
35
|
-
|
|
36
|
-
// Might not be found entirely (not an Element?) - in that case, bail
|
|
37
33
|
if (!(0, _shims.isFunction)(el[matchesSelectorFunc])) return false;
|
|
38
34
|
return el[matchesSelectorFunc](selector);
|
|
39
|
-
}
|
|
35
|
+
};
|
|
40
36
|
|
|
41
|
-
|
|
42
|
-
|
|
37
|
+
/**
|
|
38
|
+
* Checks if the element or any of its parents match the given CSS selector.
|
|
39
|
+
*
|
|
40
|
+
* @param el - The element to start the search from.
|
|
41
|
+
* @param selector - The CSS selector to match against.
|
|
42
|
+
* @param baseNode - The base node to stop the search at.
|
|
43
|
+
* @returns True if a match is found, false otherwise.
|
|
44
|
+
*/
|
|
45
|
+
exports.matchesSelector = matchesSelector;
|
|
46
|
+
const matchesSelectorAndParentsTo = (el, selector, baseNode) => {
|
|
43
47
|
let node = el;
|
|
44
48
|
do {
|
|
45
49
|
if (matchesSelector(node, selector)) return true;
|
|
@@ -47,8 +51,18 @@ function matchesSelectorAndParentsTo(el, selector, baseNode) {
|
|
|
47
51
|
node = node.parentNode;
|
|
48
52
|
} while (node);
|
|
49
53
|
return false;
|
|
50
|
-
}
|
|
51
|
-
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Adds an event listener to an element.
|
|
58
|
+
*
|
|
59
|
+
* @param el - The element to add the event listener to.
|
|
60
|
+
* @param event - The event type to listen for.
|
|
61
|
+
* @param handler - The function to call when the event occurs.
|
|
62
|
+
* @param inputOptions - Optional parameters for the event listener.
|
|
63
|
+
*/
|
|
64
|
+
exports.matchesSelectorAndParentsTo = matchesSelectorAndParentsTo;
|
|
65
|
+
const addEvent = (el, event, handler, inputOptions) => {
|
|
52
66
|
if (!el) return;
|
|
53
67
|
const options = {
|
|
54
68
|
capture: true,
|
|
@@ -61,8 +75,18 @@ function addEvent(el, event, handler, inputOptions) {
|
|
|
61
75
|
} else {
|
|
62
76
|
el[`on${event}`] = handler;
|
|
63
77
|
}
|
|
64
|
-
}
|
|
65
|
-
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Removes an event listener from an element.
|
|
82
|
+
*
|
|
83
|
+
* @param el - The element to remove the event listener from.
|
|
84
|
+
* @param event - The event type of the listener to remove.
|
|
85
|
+
* @param handler - The function that was called when the event occurred.
|
|
86
|
+
* @param inputOptions - Optional parameters for the event listener.
|
|
87
|
+
*/
|
|
88
|
+
exports.addEvent = addEvent;
|
|
89
|
+
const removeEvent = (el, event, handler, inputOptions) => {
|
|
66
90
|
if (!el) return;
|
|
67
91
|
const options = {
|
|
68
92
|
capture: true,
|
|
@@ -71,46 +95,82 @@ function removeEvent(el, event, handler, inputOptions) {
|
|
|
71
95
|
if (el.removeEventListener) {
|
|
72
96
|
el.removeEventListener(event, handler, options);
|
|
73
97
|
} else if (el.detachEvent) {
|
|
74
|
-
el.detachEvent('on' + event, handler);
|
|
98
|
+
el.detachEvent?.('on' + event, handler);
|
|
75
99
|
} else {
|
|
76
100
|
el[`on${event}`] = null;
|
|
77
101
|
}
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Calculates the outer height of an element, including padding and border.
|
|
106
|
+
*
|
|
107
|
+
* @param node - The element to calculate the outer height of.
|
|
108
|
+
* @returns The outer height of the element.
|
|
109
|
+
*/
|
|
110
|
+
exports.removeEvent = removeEvent;
|
|
111
|
+
const outerHeight = node => {
|
|
82
112
|
let height = node.clientHeight;
|
|
83
113
|
const computedStyle = node.ownerDocument.defaultView?.getComputedStyle(node);
|
|
84
114
|
height += (0, _shims.int)(computedStyle.borderTopWidth);
|
|
85
115
|
height += (0, _shims.int)(computedStyle.borderBottomWidth);
|
|
86
116
|
return height;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Calculates the outer width of an element, including padding and border.
|
|
121
|
+
*
|
|
122
|
+
* @param node - The element to calculate the outer width of.
|
|
123
|
+
* @returns The outer width of the element.
|
|
124
|
+
*/
|
|
125
|
+
exports.outerHeight = outerHeight;
|
|
126
|
+
const outerWidth = node => {
|
|
91
127
|
let width = node.clientWidth;
|
|
92
128
|
const computedStyle = node.ownerDocument?.defaultView?.getComputedStyle(node);
|
|
93
129
|
width += (0, _shims.int)(computedStyle.borderLeftWidth);
|
|
94
130
|
width += (0, _shims.int)(computedStyle.borderRightWidth);
|
|
95
131
|
return width;
|
|
96
|
-
}
|
|
97
|
-
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Calculates the inner height of an element, excluding padding.
|
|
136
|
+
*
|
|
137
|
+
* @param node - The element to calculate the inner height of.
|
|
138
|
+
* @returns The inner height of the element.
|
|
139
|
+
*/
|
|
140
|
+
exports.outerWidth = outerWidth;
|
|
141
|
+
const innerHeight = node => {
|
|
98
142
|
let height = node.clientHeight;
|
|
99
143
|
const computedStyle = node.ownerDocument?.defaultView?.getComputedStyle(node);
|
|
100
144
|
height -= (0, _shims.int)(computedStyle.paddingTop);
|
|
101
145
|
height -= (0, _shims.int)(computedStyle.paddingBottom);
|
|
102
146
|
return height;
|
|
103
|
-
}
|
|
104
|
-
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Calculates the inner width of an element, excluding padding.
|
|
151
|
+
*
|
|
152
|
+
* @param node - The element to calculate the inner width of.
|
|
153
|
+
* @returns The inner width of the element.
|
|
154
|
+
*/
|
|
155
|
+
exports.innerHeight = innerHeight;
|
|
156
|
+
const innerWidth = node => {
|
|
105
157
|
let width = node.clientWidth;
|
|
106
158
|
const computedStyle = node.ownerDocument?.defaultView?.getComputedStyle(node);
|
|
107
159
|
width -= (0, _shims.int)(computedStyle.paddingLeft);
|
|
108
160
|
width -= (0, _shims.int)(computedStyle.paddingRight);
|
|
109
161
|
return width;
|
|
110
|
-
}
|
|
162
|
+
};
|
|
111
163
|
|
|
112
|
-
|
|
113
|
-
|
|
164
|
+
/**
|
|
165
|
+
* Calculates the X and Y offset of an event from the parent element.
|
|
166
|
+
*
|
|
167
|
+
* @param evt - The event object.
|
|
168
|
+
* @param offsetParent - The parent element to calculate the offset from.
|
|
169
|
+
* @param scale - The scale factor to apply to the offset.
|
|
170
|
+
* @returns The X and Y offset from the parent element.
|
|
171
|
+
*/
|
|
172
|
+
exports.innerWidth = innerWidth;
|
|
173
|
+
const offsetXYFromParent = (evt, offsetParent, scale) => {
|
|
114
174
|
const isBody = offsetParent === offsetParent.ownerDocument.body;
|
|
115
175
|
const offsetParentRect = isBody ? {
|
|
116
176
|
left: 0,
|
|
@@ -122,18 +182,18 @@ function offsetXYFromParent(evt, offsetParent, scale) {
|
|
|
122
182
|
x,
|
|
123
183
|
y
|
|
124
184
|
};
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Generates a CSS transform string from a position and offset.
|
|
189
|
+
*
|
|
190
|
+
* @param controlPos - The position of the control.
|
|
191
|
+
* @param positionOffset - The offset to apply to the position.
|
|
192
|
+
* @param unitSuffix - The unit to use for the position values.
|
|
193
|
+
* @returns A CSS transform string.
|
|
194
|
+
*/
|
|
195
|
+
exports.offsetXYFromParent = offsetXYFromParent;
|
|
196
|
+
const getTranslation = (_ref, positionOffset, unitSuffix) => {
|
|
137
197
|
let {
|
|
138
198
|
x,
|
|
139
199
|
y
|
|
@@ -145,22 +205,100 @@ function getTranslation(_ref, positionOffset, unitSuffix) {
|
|
|
145
205
|
translation = `translate(${defaultX}, ${defaultY})` + translation;
|
|
146
206
|
}
|
|
147
207
|
return translation;
|
|
148
|
-
}
|
|
149
|
-
|
|
208
|
+
};
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* Creates a CSS transform property for a given position and offset.
|
|
212
|
+
*
|
|
213
|
+
* @param controlPos - The control position.
|
|
214
|
+
* @param positionOffset - The position offset.
|
|
215
|
+
* @returns An object with a single property for CSS transform.
|
|
216
|
+
*/
|
|
217
|
+
exports.getTranslation = getTranslation;
|
|
218
|
+
const createCSSTransform = (controlPos, positionOffset) => {
|
|
219
|
+
const translation = getTranslation(controlPos, positionOffset, 'px');
|
|
220
|
+
return {
|
|
221
|
+
[(0, _getPrefix.browserPrefixToKey)('transform', _getPrefix.default)]: translation
|
|
222
|
+
};
|
|
223
|
+
};
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* Creates an SVG transform attribute value for a given position and offset.
|
|
227
|
+
*
|
|
228
|
+
* @param controlPos - The control position.
|
|
229
|
+
* @param positionOffset - The position offset.
|
|
230
|
+
* @returns A string for the SVG transform attribute.
|
|
231
|
+
*/
|
|
232
|
+
exports.createCSSTransform = createCSSTransform;
|
|
233
|
+
const createSVGTransform = (controlPos, positionOffset) => {
|
|
234
|
+
const translation = getTranslation(controlPos, positionOffset, '');
|
|
235
|
+
return translation;
|
|
236
|
+
};
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* Retrieves the touch object with a specific identifier from an event.
|
|
240
|
+
*
|
|
241
|
+
* @param e - The event object.
|
|
242
|
+
* @param identifier - The identifier of the touch object to retrieve.
|
|
243
|
+
* @returns The touch object, or null if not found.
|
|
244
|
+
*/
|
|
245
|
+
exports.createSVGTransform = createSVGTransform;
|
|
246
|
+
const getTouch = (e, identifier) => {
|
|
150
247
|
return e.targetTouches && (0, _shims.findInArray)(e.targetTouches, t => identifier === t.identifier) || e.changedTouches && (0, _shims.findInArray)(e.changedTouches, t => identifier === t.identifier);
|
|
151
|
-
}
|
|
152
|
-
|
|
248
|
+
};
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* Retrieves the identifier of the first touch point from an event.
|
|
252
|
+
*
|
|
253
|
+
* @param e - The event object.
|
|
254
|
+
* @returns The identifier of the first touch point, or null if not available.
|
|
255
|
+
*/
|
|
256
|
+
exports.getTouch = getTouch;
|
|
257
|
+
const getTouchIdentifier = e => {
|
|
153
258
|
if (e.targetTouches && e.targetTouches[0]) return e.targetTouches[0].identifier;
|
|
154
259
|
if (e.changedTouches && e.changedTouches[0]) return e.changedTouches[0].identifier;
|
|
155
|
-
return;
|
|
156
|
-
}
|
|
260
|
+
return null;
|
|
261
|
+
};
|
|
157
262
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
263
|
+
/**
|
|
264
|
+
* Adds a class name to an element.
|
|
265
|
+
*
|
|
266
|
+
* @param el - The element to add the class name to.
|
|
267
|
+
* @param className - The class name to add.
|
|
268
|
+
*/
|
|
269
|
+
exports.getTouchIdentifier = getTouchIdentifier;
|
|
270
|
+
const addClassName = (el, className) => {
|
|
271
|
+
if (el.classList) {
|
|
272
|
+
el.classList.add(className);
|
|
273
|
+
} else {
|
|
274
|
+
if (!el.className.match(new RegExp(`(?:^|\\s)${className}(?!\\S)`))) {
|
|
275
|
+
el.className += ` ${className}`;
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
};
|
|
161
279
|
|
|
162
|
-
|
|
163
|
-
|
|
280
|
+
/**
|
|
281
|
+
* Removes a class name from an element.
|
|
282
|
+
*
|
|
283
|
+
* @param el - The element to remove the class name from.
|
|
284
|
+
* @param className - The class name to remove.
|
|
285
|
+
*/
|
|
286
|
+
exports.addClassName = addClassName;
|
|
287
|
+
const removeClassName = (el, className) => {
|
|
288
|
+
if (el.classList) {
|
|
289
|
+
el.classList.remove(className);
|
|
290
|
+
} else {
|
|
291
|
+
el.className = el.className.replace(new RegExp(`(?:^|\\s)${className}(?!\\S)`, 'g'), '');
|
|
292
|
+
}
|
|
293
|
+
};
|
|
294
|
+
|
|
295
|
+
/**
|
|
296
|
+
* Adds styles to prevent user selection during drag operations.
|
|
297
|
+
*
|
|
298
|
+
* @param doc - The document to add the styles to. Optional.
|
|
299
|
+
*/
|
|
300
|
+
exports.removeClassName = removeClassName;
|
|
301
|
+
const addUserSelectStyles = doc => {
|
|
164
302
|
if (!doc) return;
|
|
165
303
|
let styleEl = doc.getElementById('vue-draggable-style-el');
|
|
166
304
|
if (!styleEl) {
|
|
@@ -172,38 +310,24 @@ function addUserSelectStyles(doc) {
|
|
|
172
310
|
doc.getElementsByTagName('head')[0].appendChild(styleEl);
|
|
173
311
|
}
|
|
174
312
|
if (doc.body) addClassName(doc.body, 'vue-draggable-transparent-selection');
|
|
175
|
-
}
|
|
176
|
-
|
|
313
|
+
};
|
|
314
|
+
|
|
315
|
+
/**
|
|
316
|
+
* Removes styles added to prevent user selection during drag operations.
|
|
317
|
+
*
|
|
318
|
+
* @param doc - The document to remove the styles from. Optional.
|
|
319
|
+
*/
|
|
320
|
+
exports.addUserSelectStyles = addUserSelectStyles;
|
|
321
|
+
const removeUserSelectStyles = doc => {
|
|
177
322
|
if (!doc) return;
|
|
178
323
|
try {
|
|
179
324
|
if (doc.body) removeClassName(doc.body, 'vue-draggable-transparent-selection');
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
// Remove selection caused by scroll, unless it's a focused input
|
|
184
|
-
// (we use doc.defaultView in case we're in an iframe)
|
|
185
|
-
const selection = (doc.defaultView || window).getSelection();
|
|
186
|
-
if (selection && selection.type !== 'Caret') {
|
|
187
|
-
selection.removeAllRanges();
|
|
188
|
-
}
|
|
325
|
+
const selection = doc.getSelection();
|
|
326
|
+
if (selection && selection.type !== 'Caret') {
|
|
327
|
+
selection.removeAllRanges();
|
|
189
328
|
}
|
|
190
329
|
} catch (e) {
|
|
191
|
-
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
function addClassName(el, className) {
|
|
195
|
-
if (el.classList) {
|
|
196
|
-
el.classList.add(className);
|
|
197
|
-
} else {
|
|
198
|
-
if (!el.className.match(new RegExp(`(?:^|\\s)${className}(?!\\S)`))) {
|
|
199
|
-
el.className += ` ${className}`;
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
function removeClassName(el, className) {
|
|
204
|
-
if (el.classList) {
|
|
205
|
-
el.classList.remove(className);
|
|
206
|
-
} else {
|
|
207
|
-
el.className = el.className.replace(new RegExp(`(?:^|\\s)${className}(?!\\S)`, 'g'), '');
|
|
330
|
+
console.error(e);
|
|
208
331
|
}
|
|
209
|
-
}
|
|
332
|
+
};
|
|
333
|
+
exports.removeUserSelectStyles = removeUserSelectStyles;
|
package/build/cjs/utils/log.js
CHANGED
|
@@ -3,84 +3,115 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports.canDragX =
|
|
7
|
-
exports.canDragY = canDragY;
|
|
8
|
-
exports.createCoreData = createCoreData;
|
|
9
|
-
exports.createDraggableData = createDraggableData;
|
|
10
|
-
exports.getBoundPosition = getBoundPosition;
|
|
11
|
-
exports.getControlPosition = getControlPosition;
|
|
12
|
-
exports.snapToGrid = snapToGrid;
|
|
13
|
-
var _get = _interopRequireDefault(require("lodash/get"));
|
|
6
|
+
exports.snapToGrid = exports.getControlPosition = exports.getBoundPosition = exports.createDraggableData = exports.createCoreData = exports.canDragY = exports.canDragX = void 0;
|
|
14
7
|
var _domFns = require("./domFns");
|
|
15
8
|
var _shims = require("./shims");
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
9
|
+
// Quick clone for bounds. We're doing this because we don't want to mess with the original bounds object.
|
|
10
|
+
// It's a simple copy, nothing fancy.
|
|
11
|
+
const cloneBounds = bounds => {
|
|
12
|
+
return {
|
|
13
|
+
left: bounds.left,
|
|
14
|
+
top: bounds.top,
|
|
15
|
+
right: bounds.right,
|
|
16
|
+
bottom: bounds.bottom
|
|
17
|
+
};
|
|
18
|
+
};
|
|
20
19
|
|
|
21
|
-
|
|
20
|
+
// This one's a bit tricky. We're trying to find the actual DOM node for a draggable component.
|
|
21
|
+
// It's using some internal React stuff, so don't worry if it looks a bit weird.
|
|
22
|
+
const findDOMNode = draggable => {
|
|
23
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
24
|
+
return draggable.findDOMNode();
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
// Ever got annoyed by CSS values being strings? Yeah, me too. This function takes those strings and turns them into numbers.
|
|
28
|
+
// Also, it warns you if something's not right, which is pretty handy.
|
|
29
|
+
const parseStyleToInt = (style, property) => {
|
|
30
|
+
if (!(property in style)) {
|
|
31
|
+
console.warn(`Property "${String(property)}" does not exist on the provided style object.`);
|
|
32
|
+
return 0;
|
|
33
|
+
}
|
|
34
|
+
const value = style[property];
|
|
35
|
+
const parsed = parseInt(value, 10);
|
|
36
|
+
if (isNaN(parsed)) {
|
|
37
|
+
console.warn(`Value of property "${String(property)}" is not a valid number.`);
|
|
38
|
+
return 0;
|
|
39
|
+
}
|
|
40
|
+
return parsed;
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
// This is where the magic happens. We're making sure the draggable stays within its bounds.
|
|
44
|
+
// It's a bit of math and some conditionals. Nothing too scary, but it does the job.
|
|
45
|
+
const getBoundPosition = (draggable, x, y) => {
|
|
46
|
+
if (!draggable.props.bounds) return [x, y];
|
|
22
47
|
let bounds = draggable.props.bounds;
|
|
23
48
|
bounds = typeof bounds === 'string' ? bounds : cloneBounds(bounds);
|
|
24
49
|
const node = findDOMNode(draggable);
|
|
50
|
+
if (!node) return [x, y];
|
|
25
51
|
const {
|
|
26
52
|
ownerDocument
|
|
27
53
|
} = node;
|
|
28
|
-
const ownerWindow =
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
} else {
|
|
35
|
-
boundNode = ownerDocument.querySelector(bounds);
|
|
36
|
-
}
|
|
54
|
+
const ownerWindow = ownerDocument?.defaultView;
|
|
55
|
+
if (!ownerWindow) {
|
|
56
|
+
return [x, y];
|
|
57
|
+
}
|
|
58
|
+
if (typeof bounds === 'string') {
|
|
59
|
+
const boundNode = bounds === 'parent' ? node.parentNode : ownerDocument.querySelector(bounds);
|
|
37
60
|
if (!(boundNode instanceof ownerWindow.HTMLElement)) {
|
|
38
|
-
throw new Error(`Bounds selector ${bounds} could not find an element.`);
|
|
61
|
+
throw new Error(`Bounds selector "${bounds}" could not find an element.`);
|
|
39
62
|
}
|
|
40
63
|
const nodeStyle = ownerWindow.getComputedStyle(node);
|
|
41
64
|
const boundNodeStyle = ownerWindow.getComputedStyle(boundNode);
|
|
42
|
-
// Compute bounds. This is a pain with padding and offsets but this gets it exactly right.
|
|
43
65
|
bounds = {
|
|
44
|
-
left: -node.offsetLeft + (
|
|
45
|
-
top: -node.offsetTop + (
|
|
46
|
-
right: (0, _domFns.innerWidth)(boundNode) - (0, _domFns.outerWidth)(node) - node.offsetLeft + (
|
|
47
|
-
bottom: (0, _domFns.innerHeight)(boundNode) - (0, _domFns.outerHeight)(node) - node.offsetTop + (
|
|
66
|
+
left: -node.offsetLeft + parseStyleToInt(boundNodeStyle, 'paddingLeft') + parseStyleToInt(nodeStyle, 'marginLeft'),
|
|
67
|
+
top: -node.offsetTop + parseStyleToInt(boundNodeStyle, 'paddingTop') + parseStyleToInt(nodeStyle, 'marginTop'),
|
|
68
|
+
right: (0, _domFns.innerWidth)(boundNode) - (0, _domFns.outerWidth)(node) - node.offsetLeft + parseStyleToInt(boundNodeStyle, 'paddingRight') - parseStyleToInt(nodeStyle, 'marginRight'),
|
|
69
|
+
bottom: (0, _domFns.innerHeight)(boundNode) - (0, _domFns.outerHeight)(node) - node.offsetTop + parseStyleToInt(boundNodeStyle, 'paddingBottom') - parseStyleToInt(nodeStyle, 'marginBottom')
|
|
48
70
|
};
|
|
49
71
|
}
|
|
50
72
|
|
|
51
|
-
//
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
// But above left and top limits.
|
|
56
|
-
if ((0, _shims.isNum)(bounds.left)) x = Math.max(x, bounds.left);
|
|
57
|
-
if ((0, _shims.isNum)(bounds.top)) y = Math.max(y, bounds.top);
|
|
73
|
+
// Clamp x and y to be within the bounds.
|
|
74
|
+
x = Math.max(Math.min(x, bounds.right || 0), bounds.left || 0);
|
|
75
|
+
y = Math.max(Math.min(y, bounds.bottom || 0), bounds.top || 0);
|
|
58
76
|
return [x, y];
|
|
59
|
-
}
|
|
60
|
-
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
// Snapping to a grid is super useful for aligning stuff. This function just rounds the position to the nearest grid point.
|
|
80
|
+
exports.getBoundPosition = getBoundPosition;
|
|
81
|
+
const snapToGrid = (grid, pendingX, pendingY) => {
|
|
61
82
|
const x = Math.round(pendingX / grid[0]) * grid[0];
|
|
62
83
|
const y = Math.round(pendingY / grid[1]) * grid[1];
|
|
63
84
|
return [x, y];
|
|
64
|
-
}
|
|
65
|
-
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
// Can we drag along the x-axis? This checks the draggable's props to see what's allowed.
|
|
88
|
+
exports.snapToGrid = snapToGrid;
|
|
89
|
+
const canDragX = draggable => {
|
|
66
90
|
return draggable.props.axis === 'both' || draggable.props.axis === 'x';
|
|
67
|
-
}
|
|
68
|
-
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
// Same as canDragX, but for the y-axis. Gotta keep things flexible.
|
|
94
|
+
exports.canDragX = canDragX;
|
|
95
|
+
const canDragY = draggable => {
|
|
69
96
|
return draggable.props.axis === 'both' || draggable.props.axis === 'y';
|
|
70
|
-
}
|
|
97
|
+
};
|
|
71
98
|
|
|
72
|
-
//
|
|
73
|
-
|
|
99
|
+
// Getting the control position is a bit of DOM manipulation and event handling.
|
|
100
|
+
// It's a bit dense, but it's just calculating positions based on the event and the draggable's state.
|
|
101
|
+
exports.canDragY = canDragY;
|
|
102
|
+
const getControlPosition = (e, draggableCore, touchIdentifier) => {
|
|
74
103
|
const touchObj = typeof touchIdentifier === 'number' ? (0, _domFns.getTouch)(e, touchIdentifier) : null;
|
|
75
104
|
if (typeof touchIdentifier === 'number' && !touchObj) return null; // not the right touch
|
|
76
105
|
const node = findDOMNode(draggableCore);
|
|
77
106
|
// User can provide an offsetParent if desired.
|
|
78
107
|
const offsetParent = draggableCore.props.offsetParent || node.offsetParent || node.ownerDocument.body;
|
|
79
108
|
return (0, _domFns.offsetXYFromParent)(touchObj || e, offsetParent, draggableCore.props.scale);
|
|
80
|
-
}
|
|
109
|
+
};
|
|
81
110
|
|
|
82
|
-
//
|
|
83
|
-
|
|
111
|
+
// When you start dragging, or move the draggable, this function updates the state with the new position.
|
|
112
|
+
// It's a bit of a state management thing, keeping track of deltas and positions.
|
|
113
|
+
exports.getControlPosition = getControlPosition;
|
|
114
|
+
const createCoreData = (draggable, x, y) => {
|
|
84
115
|
const state = draggable.state;
|
|
85
116
|
const isStart = !(0, _shims.isNum)(state.lastX);
|
|
86
117
|
const node = findDOMNode(draggable);
|
|
@@ -96,6 +127,7 @@ function createCoreData(draggable, x, y) {
|
|
|
96
127
|
y
|
|
97
128
|
};
|
|
98
129
|
} else {
|
|
130
|
+
// Otherwise, calculate the delta.
|
|
99
131
|
return {
|
|
100
132
|
node,
|
|
101
133
|
deltaX: x - state.lastX,
|
|
@@ -106,10 +138,12 @@ function createCoreData(draggable, x, y) {
|
|
|
106
138
|
y
|
|
107
139
|
};
|
|
108
140
|
}
|
|
109
|
-
}
|
|
141
|
+
};
|
|
110
142
|
|
|
111
|
-
//
|
|
112
|
-
|
|
143
|
+
// This takes the core data and adjusts it based on the draggable's scale.
|
|
144
|
+
// It's for when you're scaling the draggable and need the position to reflect that.
|
|
145
|
+
exports.createCoreData = createCoreData;
|
|
146
|
+
const createDraggableData = (draggable, coreData) => {
|
|
113
147
|
const scale = draggable.props.scale;
|
|
114
148
|
return {
|
|
115
149
|
node: coreData.node,
|
|
@@ -120,21 +154,5 @@ function createDraggableData(draggable, coreData) {
|
|
|
120
154
|
lastX: draggable.state.x,
|
|
121
155
|
lastY: draggable.state.y
|
|
122
156
|
};
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
// A lot faster than stringify/parse
|
|
126
|
-
function cloneBounds(bounds) {
|
|
127
|
-
return {
|
|
128
|
-
left: bounds.left,
|
|
129
|
-
top: bounds.top,
|
|
130
|
-
right: bounds.right,
|
|
131
|
-
bottom: bounds.bottom
|
|
132
|
-
};
|
|
133
|
-
}
|
|
134
|
-
function findDOMNode(draggable) {
|
|
135
|
-
const node = draggable.findDOMNode();
|
|
136
|
-
if (!node) {
|
|
137
|
-
throw new Error('<DraggableCore>: Unmounted during event!');
|
|
138
|
-
}
|
|
139
|
-
return node;
|
|
140
|
-
}
|
|
157
|
+
};
|
|
158
|
+
exports.createDraggableData = createDraggableData;
|