@marsio/vue-draggable 1.0.2
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/LICENSE +21 -0
- package/README.md +320 -0
- package/build/cjs/Draggable.js +278 -0
- package/build/cjs/DraggableCore.js +310 -0
- package/build/cjs/cjs.js +9 -0
- package/build/cjs/utils/domFns.js +209 -0
- package/build/cjs/utils/getPrefix.js +48 -0
- package/build/cjs/utils/log.js +9 -0
- package/build/cjs/utils/positionFns.js +140 -0
- package/build/cjs/utils/shims.js +39 -0
- package/build/cjs/utils/test.js +12 -0
- package/build/cjs/utils/types.js +21 -0
- package/build/web/vue-draggable.min.js +2 -0
- package/build/web/vue-draggable.min.js.LICENSE.txt +6 -0
- package/package.json +71 -0
- package/typings/index.d.ts +36 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
(MIT License)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2023 Marshall. All rights reserved.
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a
|
|
6
|
+
copy of this software and associated documentation files (the "Software"),
|
|
7
|
+
to deal in the Software without restriction, including without limitation
|
|
8
|
+
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
9
|
+
and/or sell copies of the Software, and to permit persons to whom the
|
|
10
|
+
Software is furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
|
13
|
+
all copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
20
|
+
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
21
|
+
DEALINGS IN THE SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
# Vue-Draggable
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
<p align="center">
|
|
6
|
+
<img src="https://user-images.githubusercontent.com/6365230/95649276-f3a02480-0b06-11eb-8504-e0614a780ba4.gif" />
|
|
7
|
+
</p>
|
|
8
|
+
|
|
9
|
+
A simple component for making elements draggable.
|
|
10
|
+
|
|
11
|
+
```js
|
|
12
|
+
<Draggable>
|
|
13
|
+
<div>I can now be moved around!</div>
|
|
14
|
+
</Draggable>
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
#### Technical Documentation
|
|
18
|
+
|
|
19
|
+
- [Installing](#installing)
|
|
20
|
+
- [Exports](#exports)
|
|
21
|
+
- [Draggable](#draggable)
|
|
22
|
+
- [Draggable Usage](#draggable-usage)
|
|
23
|
+
- [Draggable API](#draggable-api)
|
|
24
|
+
- [Controlled vs. Uncontrolled](#controlled-vs-uncontrolled)
|
|
25
|
+
- [DraggableCore](#draggablecore)
|
|
26
|
+
- [DraggableCore API](#draggablecore-api)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
### Installing
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
$ npm install @marsio/vue-draggable
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
If you aren't using browserify/webpack, a
|
|
37
|
+
[UMD version of vue-draggable](dist/vue-draggable.js) is available. It is updated per-release only.
|
|
38
|
+
This bundle is also what is loaded when installing from npm. It expects external Vue3.
|
|
39
|
+
|
|
40
|
+
If you want a UMD version of the latest `master` revision, you can generate it yourself from master by cloning this
|
|
41
|
+
repository and running `$ make`. This will create umd dist files in the `build/` folder.
|
|
42
|
+
|
|
43
|
+
### Exports
|
|
44
|
+
|
|
45
|
+
The default export is `<Draggable>`. At the `.DraggableCore` property is [`<DraggableCore>`](#draggablecore).
|
|
46
|
+
Here's how to use it:
|
|
47
|
+
|
|
48
|
+
```js
|
|
49
|
+
// ES6
|
|
50
|
+
import Draggable from '@marsio/vue-draggable'; // The default
|
|
51
|
+
import {DraggableCore} from '@marsio/vue-draggable'; // <DraggableCore>
|
|
52
|
+
import Draggable, {DraggableCore} from '@marsio/vue-draggable'; // Both at the same time
|
|
53
|
+
|
|
54
|
+
// CommonJS
|
|
55
|
+
let Draggable = require('@marsio/vue-draggable');
|
|
56
|
+
let DraggableCore = Draggable.DraggableCore;
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## `<Draggable>`
|
|
60
|
+
|
|
61
|
+
A `<Draggable>` element wraps an existing element and extends it with new event handlers and styles.
|
|
62
|
+
It does not create a wrapper element in the DOM.
|
|
63
|
+
|
|
64
|
+
Draggable items are moved using CSS Transforms. This allows items to be dragged regardless of their current
|
|
65
|
+
positioning (relative, absolute, or static). Elements can also be moved between drags without incident.
|
|
66
|
+
|
|
67
|
+
If the item you are dragging already has a CSS Transform applied, it will be overwritten by `<Draggable>`. Use
|
|
68
|
+
an intermediate wrapper (`<Draggable><span>...</span></Draggable>`) in this case.
|
|
69
|
+
|
|
70
|
+
### Draggable Usage
|
|
71
|
+
|
|
72
|
+
```js
|
|
73
|
+
<template>
|
|
74
|
+
<div>
|
|
75
|
+
<h1>Vue Draggable</h1>
|
|
76
|
+
<Draggable>
|
|
77
|
+
<div class="box">I can be dragged anywhere</div>
|
|
78
|
+
</Draggable>
|
|
79
|
+
</div>
|
|
80
|
+
</template>
|
|
81
|
+
<script>
|
|
82
|
+
import Draggable from '@marsio/vue-draggable'
|
|
83
|
+
export default {
|
|
84
|
+
components: {
|
|
85
|
+
Draggable
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
</script>
|
|
89
|
+
<style>
|
|
90
|
+
html, body {
|
|
91
|
+
height: 100%;
|
|
92
|
+
}
|
|
93
|
+
.vue-draggable, .cursor {
|
|
94
|
+
cursor: move;
|
|
95
|
+
}
|
|
96
|
+
.box {
|
|
97
|
+
background: #fff;
|
|
98
|
+
border: 1px solid #999;
|
|
99
|
+
border-radius: 3px;
|
|
100
|
+
width: 180px;
|
|
101
|
+
height: 180px;
|
|
102
|
+
margin: 10px;
|
|
103
|
+
padding: 10px;
|
|
104
|
+
float: left;
|
|
105
|
+
}
|
|
106
|
+
</style>
|
|
107
|
+
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### Draggable API
|
|
111
|
+
|
|
112
|
+
The `<Draggable/>` component transparently adds draggability to its children.
|
|
113
|
+
|
|
114
|
+
**Note**: Only a single child is allowed or an Error will be thrown.
|
|
115
|
+
|
|
116
|
+
For the `<Draggable/>` component to correctly attach itself to its child, the child element must provide support
|
|
117
|
+
for the following props:
|
|
118
|
+
- `style` is used to give the transform css to the child.
|
|
119
|
+
- `class` is used to apply the proper classes to the object being dragged.
|
|
120
|
+
- `onMousedown`, `onMouseup`, `onTouchstart`, and `onTouchend` are used to keep track of dragging state.
|
|
121
|
+
|
|
122
|
+
#### `<Draggable>` Props:
|
|
123
|
+
|
|
124
|
+
```js
|
|
125
|
+
type DraggableEventHandler = (e: Event, data: DraggableData) => void | false;
|
|
126
|
+
type DraggableData = {
|
|
127
|
+
node: HTMLElement,
|
|
128
|
+
x: number, y: number,
|
|
129
|
+
deltaX: number, deltaY: number,
|
|
130
|
+
lastX: number, lastY: number
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
/*
|
|
134
|
+
* Props:
|
|
135
|
+
*/
|
|
136
|
+
{
|
|
137
|
+
// If set to `true`, will allow dragging on non left-button clicks.
|
|
138
|
+
allowAnyClick: boolean,
|
|
139
|
+
|
|
140
|
+
// Determines which axis the draggable can move. This only affects
|
|
141
|
+
// flushing to the DOM. Callbacks will still include all values.
|
|
142
|
+
// Accepted values:
|
|
143
|
+
// - `both` allows movement horizontally and vertically (default).
|
|
144
|
+
// - `x` limits movement to horizontal axis.
|
|
145
|
+
// - `y` limits movement to vertical axis.
|
|
146
|
+
// - 'none' stops all movement.
|
|
147
|
+
axis: string,
|
|
148
|
+
|
|
149
|
+
// Specifies movement boundaries. Accepted values:
|
|
150
|
+
// - `parent` restricts movement within the node's offsetParent
|
|
151
|
+
// (nearest node with position relative or absolute), or
|
|
152
|
+
// - a selector, restricts movement within the targeted node
|
|
153
|
+
// - An object with `left, top, right, and bottom` properties.
|
|
154
|
+
// These indicate how far in each direction the draggable
|
|
155
|
+
// can be moved.
|
|
156
|
+
bounds: {left?: number, top?: number, right?: number, bottom?: number} | string,
|
|
157
|
+
|
|
158
|
+
// Specifies a selector to be used to prevent drag initialization. The string is passed to
|
|
159
|
+
// Element.matches, so it's possible to use multiple selectors like `.first, .second`.
|
|
160
|
+
// Example: '.body'
|
|
161
|
+
cancel: string,
|
|
162
|
+
|
|
163
|
+
// Class names for draggable UI.
|
|
164
|
+
// Default to 'vue-draggable', 'vue-draggable-dragging', and 'vue-draggable-dragged'
|
|
165
|
+
defaultClassName: string,
|
|
166
|
+
defaultClassNameDragging: string,
|
|
167
|
+
defaultClassNameDragged: string,
|
|
168
|
+
|
|
169
|
+
// Specifies the `x` and `y` that the dragged item should start at.
|
|
170
|
+
// This is generally not necessary to use (you can use absolute or relative
|
|
171
|
+
// positioning of the child directly), but can be helpful for uniformity in
|
|
172
|
+
// your callbacks and with css transforms.
|
|
173
|
+
defaultPosition: {x: number, y: number},
|
|
174
|
+
|
|
175
|
+
// If true, will not call any drag handlers.
|
|
176
|
+
disabled: boolean,
|
|
177
|
+
|
|
178
|
+
// Specifies the x and y that dragging should snap to.
|
|
179
|
+
grid: [number, number],
|
|
180
|
+
|
|
181
|
+
// Specifies a selector to be used as the handle that initiates drag.
|
|
182
|
+
// Example: '.handle'
|
|
183
|
+
handle: string,
|
|
184
|
+
|
|
185
|
+
// If desired, you can provide your own offsetParent for drag calculations.
|
|
186
|
+
// By default, we use the Draggable's offsetParent. This can be useful for elements
|
|
187
|
+
// with odd display types or floats.
|
|
188
|
+
offsetParent: HTMLElement,
|
|
189
|
+
|
|
190
|
+
// Called whenever the user mouses down. Called regardless of handle or
|
|
191
|
+
// disabled status.
|
|
192
|
+
onMousedown: (e: MouseEvent) => void,
|
|
193
|
+
|
|
194
|
+
// Called when dragging starts. If `false` is returned any handler,
|
|
195
|
+
// the action will cancel.
|
|
196
|
+
startFn: DraggableEventHandler,
|
|
197
|
+
|
|
198
|
+
// Called while dragging.
|
|
199
|
+
dragFn: DraggableEventHandler,
|
|
200
|
+
|
|
201
|
+
// Called when dragging stops.
|
|
202
|
+
stopFn: DraggableEventHandler,
|
|
203
|
+
|
|
204
|
+
// import { defineComponent, ref } from 'vue';
|
|
205
|
+
// import Draggable from 'vue-draggable'
|
|
206
|
+
|
|
207
|
+
// const Component1 = defineComponent({
|
|
208
|
+
// props: {
|
|
209
|
+
// title: String
|
|
210
|
+
// },
|
|
211
|
+
// setup(props) {
|
|
212
|
+
// return { title };
|
|
213
|
+
// }
|
|
214
|
+
// });
|
|
215
|
+
|
|
216
|
+
// export default defineComponent({
|
|
217
|
+
// setup(props) {
|
|
218
|
+
// const nodeRef = ref(null)
|
|
219
|
+
// return () => (
|
|
220
|
+
// <DraggableCore dragFn={onDrag} nodeRef={nodeRef}>
|
|
221
|
+
// <Component1 ref={nodeRef} />
|
|
222
|
+
// </DraggableCore>
|
|
223
|
+
// )
|
|
224
|
+
// }
|
|
225
|
+
// });
|
|
226
|
+
// `nodeRef` is also available on <DraggableCore>.
|
|
227
|
+
nodeRef: Ref<HTMLElement | null>,
|
|
228
|
+
|
|
229
|
+
// if you need to have direct control of the element.
|
|
230
|
+
position: {x: number, y: number}
|
|
231
|
+
|
|
232
|
+
// A position offset to start with. Useful for giving an initial position
|
|
233
|
+
// to the element. Differs from `defaultPosition` in that it does not
|
|
234
|
+
// affect the position returned in draggable callbacks, and in that it
|
|
235
|
+
// accepts strings, like `{x: '10%', y: '10%'}`.
|
|
236
|
+
positionOffset: {x: number | string, y: number | string},
|
|
237
|
+
|
|
238
|
+
// Specifies the scale of the canvas your are dragging this element on. This allows
|
|
239
|
+
// you to, for example, get the correct drag deltas while you are zoomed in or out via
|
|
240
|
+
// a transform or matrix in the parent of this element.
|
|
241
|
+
scale: number
|
|
242
|
+
}
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
Note that sending `class`, `style`, or `transform` as properties will error - set them on the child element
|
|
246
|
+
directly.
|
|
247
|
+
|
|
248
|
+
|
|
249
|
+
## Controlled vs. Uncontrolled
|
|
250
|
+
|
|
251
|
+
`<Draggable>` is a 'batteries-included' component that manages its own state. If you want to completely
|
|
252
|
+
control the lifecycle of the component, use `<DraggableCore>`.
|
|
253
|
+
|
|
254
|
+
For some users, they may want the nice state management that `<Draggable>` provides, but occasionally want
|
|
255
|
+
to programmatically reposition their components.
|
|
256
|
+
|
|
257
|
+
If the prop `position: {x: number, y: number}` is defined, the `<Draggable>` will ignore its internal state and use
|
|
258
|
+
the provided position instead. Alternatively, you can seed the position using `defaultPosition`. Technically, since
|
|
259
|
+
`<Draggable>` works only on position deltas, you could also seed the initial position using CSS `top/left`.
|
|
260
|
+
|
|
261
|
+
We then expect you to use at least an `dragFn` or `stopFn` handler to synchronize state.
|
|
262
|
+
|
|
263
|
+
To disable dragging while controlled, send the prop `disabled={true}` - at this point the `<Draggable>` will operate
|
|
264
|
+
like a completely static component.
|
|
265
|
+
|
|
266
|
+
## `<DraggableCore>`
|
|
267
|
+
|
|
268
|
+
For users that require absolute control, a `<DraggableCore>` element is available. This is useful as an abstraction
|
|
269
|
+
over touch and mouse events, but with full control. `<DraggableCore>` has no internal state.
|
|
270
|
+
|
|
271
|
+
`<DraggableCore>` is a useful building block for other libraries that simply want to abstract browser-specific
|
|
272
|
+
quirks and receive callbacks when a user attempts to move an element. It does not set styles or transforms
|
|
273
|
+
on itself and thus must have callbacks attached to be useful.
|
|
274
|
+
|
|
275
|
+
### DraggableCore API
|
|
276
|
+
|
|
277
|
+
`<DraggableCore>` takes a limited subset of options:
|
|
278
|
+
|
|
279
|
+
```js
|
|
280
|
+
{
|
|
281
|
+
allowAnyClick: boolean,
|
|
282
|
+
cancel: string,
|
|
283
|
+
disabled: boolean,
|
|
284
|
+
enableUserSelectHack: boolean,
|
|
285
|
+
offsetParent: HTMLElement,
|
|
286
|
+
grid: [number, number],
|
|
287
|
+
handle: string,
|
|
288
|
+
startFn: DraggableEventHandler,
|
|
289
|
+
dragFn: DraggableEventHandler,
|
|
290
|
+
stopFn: DraggableEventHandler,
|
|
291
|
+
onMousedown: (e: MouseEvent) => void,
|
|
292
|
+
scale: number
|
|
293
|
+
}
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
Note that there is no start position. `<DraggableCore>` simply calls `drag` handlers with the below parameters,
|
|
297
|
+
indicating its position (as inferred from the underlying MouseEvent) and deltas. It is up to the parent
|
|
298
|
+
to set actual positions on `<DraggableCore>`.
|
|
299
|
+
|
|
300
|
+
Drag callbacks (`startFn`, `dragFn`, `stopFn`) are called with the [same arguments as `<Draggable>`](#draggable-api).
|
|
301
|
+
|
|
302
|
+
----
|
|
303
|
+
|
|
304
|
+
### Contributing
|
|
305
|
+
|
|
306
|
+
- Fork the project
|
|
307
|
+
- Run the project in development mode: `$ npm run dev`
|
|
308
|
+
- Make changes.
|
|
309
|
+
- Update README with appropriate docs.
|
|
310
|
+
- Commit and PR
|
|
311
|
+
|
|
312
|
+
### Release checklist
|
|
313
|
+
|
|
314
|
+
- Update CHANGELOG
|
|
315
|
+
- `make release-patch`
|
|
316
|
+
- `make publish`
|
|
317
|
+
|
|
318
|
+
### License
|
|
319
|
+
|
|
320
|
+
MIT
|
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
Object.defineProperty(exports, "DraggableCore", {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
get: function () {
|
|
9
|
+
return _DraggableCore.default;
|
|
10
|
+
}
|
|
11
|
+
});
|
|
12
|
+
exports.draggableProps = exports.default = void 0;
|
|
13
|
+
var _vue = require("vue");
|
|
14
|
+
var _get = _interopRequireDefault(require("lodash/get"));
|
|
15
|
+
var _vueTypes = _interopRequireDefault(require("vue-types"));
|
|
16
|
+
var _clsx = _interopRequireDefault(require("clsx"));
|
|
17
|
+
var _domFns = require("./utils/domFns");
|
|
18
|
+
var _positionFns = require("./utils/positionFns");
|
|
19
|
+
var _shims = require("./utils/shims");
|
|
20
|
+
var _DraggableCore = _interopRequireWildcard(require("./DraggableCore"));
|
|
21
|
+
var _log = _interopRequireDefault(require("./utils/log"));
|
|
22
|
+
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); }
|
|
23
|
+
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 && Object.prototype.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; }
|
|
24
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
25
|
+
function _isSlot(s) {
|
|
26
|
+
return typeof s === 'function' || Object.prototype.toString.call(s) === '[object Object]' && !(0, _vue.isVNode)(s);
|
|
27
|
+
}
|
|
28
|
+
const draggableProps = exports.draggableProps = {
|
|
29
|
+
..._DraggableCore.draggableCoreProps,
|
|
30
|
+
axis: _vueTypes.default.oneOf(['both', 'x', 'y', 'none']).def('both'),
|
|
31
|
+
bounds: _vueTypes.default.oneOfType([_vueTypes.default.shape({
|
|
32
|
+
left: _vueTypes.default.number,
|
|
33
|
+
right: _vueTypes.default.number,
|
|
34
|
+
top: _vueTypes.default.number,
|
|
35
|
+
bottom: _vueTypes.default.number
|
|
36
|
+
}), _vueTypes.default.string, _vueTypes.default.oneOf([false])]).def(false),
|
|
37
|
+
defaultClassName: _vueTypes.default.string.def('vue-draggable'),
|
|
38
|
+
defaultClassNameDragging: _vueTypes.default.string.def('vue-draggable-dragging'),
|
|
39
|
+
defaultClassNameDragged: _vueTypes.default.string.def('vue-draggable-dragged'),
|
|
40
|
+
defaultPosition: _vueTypes.default.shape({
|
|
41
|
+
x: _vueTypes.default.number,
|
|
42
|
+
y: _vueTypes.default.number
|
|
43
|
+
}).def({
|
|
44
|
+
x: 0,
|
|
45
|
+
y: 0
|
|
46
|
+
}),
|
|
47
|
+
positionOffset: _vueTypes.default.shape({
|
|
48
|
+
x: _vueTypes.default.oneOfType([_vueTypes.default.number, _vueTypes.default.string]),
|
|
49
|
+
y: _vueTypes.default.oneOfType([_vueTypes.default.number, _vueTypes.default.string])
|
|
50
|
+
}),
|
|
51
|
+
position: _vueTypes.default.shape({
|
|
52
|
+
x: _vueTypes.default.number,
|
|
53
|
+
y: _vueTypes.default.number
|
|
54
|
+
}).def(null)
|
|
55
|
+
};
|
|
56
|
+
const componentName = 'Draggable';
|
|
57
|
+
const Draggable = exports.default = (0, _vue.defineComponent)({
|
|
58
|
+
compatConfig: {
|
|
59
|
+
MODE: 3
|
|
60
|
+
},
|
|
61
|
+
name: componentName,
|
|
62
|
+
inheritAttrs: false,
|
|
63
|
+
props: {
|
|
64
|
+
...draggableProps,
|
|
65
|
+
style: (0, _shims.dontSetMe)('style', componentName),
|
|
66
|
+
class: (0, _shims.dontSetMe)('class', componentName),
|
|
67
|
+
transform: (0, _shims.dontSetMe)('transform', componentName)
|
|
68
|
+
},
|
|
69
|
+
setup(props, _ref) {
|
|
70
|
+
let {
|
|
71
|
+
slots
|
|
72
|
+
} = _ref;
|
|
73
|
+
const rootElement = (0, _vue.ref)(null);
|
|
74
|
+
if (props.position && !(props.dragFn || props.stopFn)) {
|
|
75
|
+
// eslint-disable-next-line no-console
|
|
76
|
+
console.warn('A `position` was applied to this <Draggable>, without drag handlers. This will make this ' + 'component effectively undraggable. Please attach `onDrag` or `onStop` handlers so you can adjust the ' + '`position` of this element.');
|
|
77
|
+
}
|
|
78
|
+
const state = (0, _vue.reactive)({
|
|
79
|
+
// Whether or not we are currently dragging.
|
|
80
|
+
dragging: false,
|
|
81
|
+
// Whether or not we have been dragged before.
|
|
82
|
+
dragged: false,
|
|
83
|
+
// Current transform x and y.
|
|
84
|
+
x: props.position ? props.position.x : props.defaultPosition.x,
|
|
85
|
+
y: props.position ? props.position.y : props.defaultPosition.y,
|
|
86
|
+
prevPropsPosition: {
|
|
87
|
+
...props.position
|
|
88
|
+
},
|
|
89
|
+
// Used for compensating for out-of-bounds drags
|
|
90
|
+
slackX: 0,
|
|
91
|
+
slackY: 0,
|
|
92
|
+
// Can only determine if SVG after mounting
|
|
93
|
+
isElementSVG: false
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
// const position = ref(props.position);
|
|
97
|
+
// const prevPropsPosition = ref(null);
|
|
98
|
+
|
|
99
|
+
const findDOMNode = () => {
|
|
100
|
+
return (0, _get.default)(props, 'nodeRef.value') || rootElement.value;
|
|
101
|
+
};
|
|
102
|
+
(0, _vue.onMounted)(() => {
|
|
103
|
+
if (typeof window.SVGElement !== 'undefined' && findDOMNode() instanceof window.SVGElement) {
|
|
104
|
+
state.isElementSVG = true;
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
(0, _vue.onUnmounted)(() => {
|
|
108
|
+
state.dragging = false;
|
|
109
|
+
});
|
|
110
|
+
const onDragStart = (e, coreData) => {
|
|
111
|
+
(0, _log.default)('Draggable: onDragStart: %j', coreData);
|
|
112
|
+
|
|
113
|
+
// Short-circuit if user's callback killed it.
|
|
114
|
+
const shouldStart = props.startFn(e, (0, _positionFns.createDraggableData)({
|
|
115
|
+
props,
|
|
116
|
+
state
|
|
117
|
+
}, coreData));
|
|
118
|
+
// Kills start event on core as well, so move handlers are never bound.
|
|
119
|
+
if (shouldStart === false) return false;
|
|
120
|
+
state.dragging = true;
|
|
121
|
+
state.dragged = true;
|
|
122
|
+
};
|
|
123
|
+
const onDrag = (e, coreData) => {
|
|
124
|
+
if (!state.dragging) return false;
|
|
125
|
+
(0, _log.default)('Draggable: onDrag: %j', coreData);
|
|
126
|
+
const uiData = (0, _positionFns.createDraggableData)({
|
|
127
|
+
props,
|
|
128
|
+
state
|
|
129
|
+
}, coreData);
|
|
130
|
+
const newState = {
|
|
131
|
+
x: uiData.x,
|
|
132
|
+
y: uiData.y,
|
|
133
|
+
slackX: 0,
|
|
134
|
+
slackY: 0
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
// Keep within bounds.
|
|
138
|
+
if (props.bounds) {
|
|
139
|
+
// Save original x and y.
|
|
140
|
+
const {
|
|
141
|
+
x,
|
|
142
|
+
y
|
|
143
|
+
} = newState;
|
|
144
|
+
|
|
145
|
+
// Add slack to the values used to calculate bound position. This will ensure that if
|
|
146
|
+
// completely removed.
|
|
147
|
+
newState.x += state.slackX;
|
|
148
|
+
newState.y += state.slackY;
|
|
149
|
+
|
|
150
|
+
// Get bound position. This will ceil/floor the x and y within the boundaries.
|
|
151
|
+
const [newStateX, newStateY] = (0, _positionFns.getBoundPosition)({
|
|
152
|
+
props,
|
|
153
|
+
findDOMNode
|
|
154
|
+
}, newState.x, newState.y);
|
|
155
|
+
newState.x = newStateX;
|
|
156
|
+
newState.y = newStateY;
|
|
157
|
+
|
|
158
|
+
// Recalculate slack by noting how much was shaved by the boundPosition handler.
|
|
159
|
+
newState.slackX = state.slackX + (x - newState.x);
|
|
160
|
+
newState.slackY = state.slackY + (y - newState.y);
|
|
161
|
+
|
|
162
|
+
// Update the event we fire to reflect what really happened after bounds took effect.
|
|
163
|
+
uiData.x = newState.x;
|
|
164
|
+
uiData.y = newState.y;
|
|
165
|
+
uiData.deltaX = newState.x - state.x;
|
|
166
|
+
uiData.deltaY = newState.y - state.y;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// Short-circuit if user's callback killed it.
|
|
170
|
+
const shouldUpdate = props.dragFn(e, uiData);
|
|
171
|
+
if (shouldUpdate === false) return false;
|
|
172
|
+
Object.keys(newState).forEach(key => {
|
|
173
|
+
state[key] = newState[key];
|
|
174
|
+
});
|
|
175
|
+
};
|
|
176
|
+
const onDragStop = (e, coreData) => {
|
|
177
|
+
if (!state.dragging) return false;
|
|
178
|
+
|
|
179
|
+
// Short-circuit if user's callback killed it.
|
|
180
|
+
const shouldContinue = props.stopFn(e, (0, _positionFns.createDraggableData)({
|
|
181
|
+
props,
|
|
182
|
+
state
|
|
183
|
+
}, coreData));
|
|
184
|
+
if (shouldContinue === false) return false;
|
|
185
|
+
(0, _log.default)('Draggable: onDragStop: %j', coreData);
|
|
186
|
+
const newState = {
|
|
187
|
+
dragging: false,
|
|
188
|
+
slackX: 0,
|
|
189
|
+
slackY: 0
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
// If this is a controlled component, the result of this operation will be to
|
|
193
|
+
// revert back to the old position. We expect a handler on `onDragStop`, at the least.
|
|
194
|
+
const controlled = Boolean(props.position);
|
|
195
|
+
if (controlled) {
|
|
196
|
+
const {
|
|
197
|
+
x,
|
|
198
|
+
y
|
|
199
|
+
} = props.position;
|
|
200
|
+
newState.x = x;
|
|
201
|
+
newState.y = y;
|
|
202
|
+
}
|
|
203
|
+
Object.keys(newState).forEach(key => {
|
|
204
|
+
state[key] = newState[key];
|
|
205
|
+
});
|
|
206
|
+
};
|
|
207
|
+
return () => {
|
|
208
|
+
const {
|
|
209
|
+
axis,
|
|
210
|
+
bounds,
|
|
211
|
+
// children,
|
|
212
|
+
defaultPosition,
|
|
213
|
+
defaultClassName,
|
|
214
|
+
defaultClassNameDragging,
|
|
215
|
+
defaultClassNameDragged,
|
|
216
|
+
position,
|
|
217
|
+
positionOffset,
|
|
218
|
+
scale,
|
|
219
|
+
...draggableCoreProps
|
|
220
|
+
} = props;
|
|
221
|
+
let style = {};
|
|
222
|
+
let svgTransform = null;
|
|
223
|
+
const controlled = Boolean(position);
|
|
224
|
+
const draggable = !controlled || state.dragging;
|
|
225
|
+
const validPosition = position || defaultPosition;
|
|
226
|
+
const transformOpts = {
|
|
227
|
+
// Set left if horizontal drag is enabled
|
|
228
|
+
x: (0, _positionFns.canDragX)({
|
|
229
|
+
props
|
|
230
|
+
}) && draggable ? state.x : validPosition.x,
|
|
231
|
+
// Set top if vertical drag is enabled
|
|
232
|
+
y: (0, _positionFns.canDragY)({
|
|
233
|
+
props
|
|
234
|
+
}) && draggable ? state.y : validPosition.y
|
|
235
|
+
};
|
|
236
|
+
|
|
237
|
+
// If this element was SVG, we use the `transform` attribute.
|
|
238
|
+
if (state.isElementSVG) {
|
|
239
|
+
svgTransform = (0, _domFns.createSVGTransform)(transformOpts, positionOffset);
|
|
240
|
+
} else {
|
|
241
|
+
// Add a CSS transform to move the element around. This allows us to move the element around
|
|
242
|
+
// without worrying about whether or not it is relatively or absolutely positioned.
|
|
243
|
+
// If the item you are dragging already has a transform set, wrap it in a <span> so <Draggable>
|
|
244
|
+
// has a clean slate.
|
|
245
|
+
style = (0, _domFns.createCSSTransform)(transformOpts, positionOffset);
|
|
246
|
+
}
|
|
247
|
+
const slotContent = (0, _vue.renderSlot)(slots, 'default');
|
|
248
|
+
let children = slotContent.children;
|
|
249
|
+
if (!Array.isArray(children)) {
|
|
250
|
+
children = []; // 如果不是数组,则使用空数组
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
// Mark with class while dragging
|
|
254
|
+
const className = (0, _clsx.default)(defaultClassName, {
|
|
255
|
+
[defaultClassNameDragging]: state.dragging,
|
|
256
|
+
[defaultClassNameDragged]: state.dragged
|
|
257
|
+
});
|
|
258
|
+
const clonedChildren = children.flatMap(child => {
|
|
259
|
+
return (0, _vue.isVNode)(child) ? (0, _vue.cloneVNode)(child, {
|
|
260
|
+
class: className,
|
|
261
|
+
style: style,
|
|
262
|
+
transform: svgTransform
|
|
263
|
+
}) : child;
|
|
264
|
+
});
|
|
265
|
+
const coreProps = {
|
|
266
|
+
...draggableCoreProps,
|
|
267
|
+
startFn: onDragStart,
|
|
268
|
+
dragFn: onDrag,
|
|
269
|
+
stopFn: onDragStop
|
|
270
|
+
};
|
|
271
|
+
return (0, _vue.createVNode)(_DraggableCore.default, (0, _vue.mergeProps)({
|
|
272
|
+
"ref": rootElement
|
|
273
|
+
}, coreProps), _isSlot(clonedChildren) ? clonedChildren : {
|
|
274
|
+
default: () => [clonedChildren]
|
|
275
|
+
});
|
|
276
|
+
};
|
|
277
|
+
}
|
|
278
|
+
});
|