From a901b7cc302d15247804068a926da7cbaf70383a Mon Sep 17 00:00:00 2001
From: Braks <78412429+bcakmakoglu@users.noreply.github.com>
Date: Wed, 14 Jul 2021 17:51:56 +0200
Subject: [PATCH 001/216] Create LICENSE
---
LICENSE | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)
create mode 100644 LICENSE
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..36f2799
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2021 Braks
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
From 1915bad00af1e27679c0ef5ad36ac6e8033169f1 Mon Sep 17 00:00:00 2001
From: Braks <78412429+bcakmakoglu@users.noreply.github.com>
Date: Thu, 15 Jul 2021 01:06:54 +0200
Subject: [PATCH 002/216] refactor: instead of a computed property we'll wait
for the mounted hook and a certain noderef before calling
useDraggable/useDraggableCore update: README.md
---
README.md | 50 +++++++++++++-----------------
example/Foo.vue | 4 ++-
src/components/Draggable.tsx | 53 ++++++++++++++++++++------------
src/components/DraggableCore.tsx | 40 ++++++++++++++----------
src/hooks/useDraggable.ts | 28 ++++++++---------
src/hooks/useDraggableCore.ts | 1 +
6 files changed, 96 insertions(+), 80 deletions(-)
diff --git a/README.md b/README.md
index 133cf6b..be49bcf 100644
--- a/README.md
+++ b/README.md
@@ -10,28 +10,38 @@ Make your Vue components draggable.
Based on [React Draggable](https://www.npmjs.com/package/react-draggable#draggablecore).
Check the [Docs](https://revue-draggable-docs.vercel.app/) for an in-depth explanation.
+### Install
+```bash
+# install revue draggable
+$ yarn add @braks/revue-draggable
+
+# or
+$ npm i --save @braks/revue-draggable
+```
+
+If you plan to use Vue2, add the composition api to your dependencies.
+```bash
+# install revue flow
+$ yarn add @braks/revue-draggable @vue/composition-api
+
+# or
+$ npm i --save @braks/revue-draggable @vue/composition-api
+```
+
+
## Quickstart
The easiest way to make your elements draggable is by using the DraggableDirective
which will handle everything for you with no configuration necessary.
````vue {}[App.vue]
-
I use a directive to make myself draggable
+
I use a directive to make myself draggable
```
-For full control use DraggableCore instead.
-DraggableCore will simply abstract over touch and mouse events but provides no transformation.
-Without callbacks, it does not provide any meaningful functionality.
-Alternatively you can just use the useDraggable and useDraggableCore abstractions which will
-provide you with the necessary callbacks and reactive fields to make your element draggable.
+For full control use `` instead. DraggableCore will simply abstract over touch and mouse events but provides
+no transformation. Without callbacks, it does not provide any meaningful functionality. Alternatively you can just use
+the useDraggable and useDraggableCore abstractions which will provide you with the necessary callbacks and reactive
+fields to make your element draggable.
### Vue2
-The components cannot be used in Vue2 as they're written in Vue3 JSX, which sadly is not downward compatible.
-You can use the useDraggable and useDraggableCore hooks to add draggability to your elements.
+
+The components cannot be used in Vue2 as they're written in Vue3 JSX, which sadly is not downward compatible. You can
+use the useDraggable and useDraggableCore hooks to add draggability to your elements.
```vue
+
```
-## Plugin
-You can add Revue Draggable as a Plugin to your Vue app.
-
-```ts {}[main.ts]
-import { createApp } from 'vue';
-import { DraggablePlugin } from '@braks/revue-draggable';
-
-const app = createApp();
-app.use(DraggablePlugin);
-app.moun('#root');
-```
+Check [the example file](./example/App.vue) for more.
-## Development
-This project uses Vite for development and Rollup to create a distribution.
+## ๐งช Development
+This project uses [Vite](https://vitejs.dev/) for development and [Rollup](https://rollupjs.org/) to create a distribution.
```bash
# start (dev)
From 9cdc63707aaaf89449d3076a70f3f7a4aaf55ce7 Mon Sep 17 00:00:00 2001
From: Braks <78412429+bcakmakoglu@users.noreply.github.com>
Date: Thu, 15 Jul 2021 11:54:49 +0200
Subject: [PATCH 012/216] update: docs with more info in index.md
---
docs/content/en/draggable.md | 2 +-
docs/content/en/index.md | 167 +++++++++++++++++++++++++++++++----
2 files changed, 150 insertions(+), 19 deletions(-)
diff --git a/docs/content/en/draggable.md b/docs/content/en/draggable.md
index 6b994b2..7619f9f 100644
--- a/docs/content/en/draggable.md
+++ b/docs/content/en/draggable.md
@@ -12,7 +12,7 @@ Draggable items move using CSS Transforms.
This allows items to be dragged regardless of their current positioning (relative, absolute, or static).
Elements can also be moved between drags without incident.
-If the item you are dragging already has a CSS Transform applied, it will be overwritten by .
+If the item you are dragging already has a CSS Transform applied, it will be overwritten by ``.
Use an intermediate wrapper (`...`) in this case.
## Usage
diff --git a/docs/content/en/index.md b/docs/content/en/index.md
index 7cb0947..66e5e31 100644
--- a/docs/content/en/index.md
+++ b/docs/content/en/index.md
@@ -8,11 +8,12 @@ features:
- Add your own Callbacks, extend Events
- Use the Core for full control
- Built for composition
-- Usable in Vue3 as a component wrapper and composition hook
-- Usable in Vue2 with composition hook
+- Usable in Vue3 (component, directive, hooks)
+- Usable in Vue2 (directive, hooks)
---
Make your Vue components draggable.
+Based on [React Draggable](https://www.npmjs.com/package/react-draggable#draggablecore).
[Demo](https://revue-draggable.vercel.app/)
[Repo](https://github.com/bcakmakoglu/revue-draggable)
@@ -21,26 +22,156 @@ Make your Vue components draggable.
+## ๐ Setup
-## Installation
-Add `@braks/revue-draggable` dependency using yarn or npm to your project
+```bash
+# install revue draggable
+$ yarn add @braks/revue-draggable
-
-
+# or
+$ npm i --save @braks/revue-draggable
+```
- ```bash
- yarn add @braks/revue-draggable
- ```
+For Vue2 add the composition-api to your dependencies.
+```bash
+# install revue flow
+$ yarn add @braks/revue-draggable @vue/composition-api
-
-
+# or
+$ npm i --save @braks/revue-draggable @vue/composition-api
+```
- ```bash
- npm install @braks/revue-draggable
- ```
+For [Nuxt](https://nuxtjs.org/) make sure to include
+```ts {}[nuxt.config.ts]
+// nuxt.config.ts
+export default {
+ build: {
+ transpile: ['@braks/revue-draggable']
+ }
+}
+```
-
-
+### ๐ Registering Draggable
-## TypeScript
-The library comes with typings, which you can find in the index.d.ts file.
+```ts {}[main.ts]
+// Vue3
+import { createApp } from 'vue';
+import Draggable, { DraggablePlugin, DraggableDirective } from '@braks/revue-draggable';
+
+const app = createApp();
+
+// Use as Plugin (registers directives and components)
+app.use(DraggablePlugin);
+
+// or register only what you need
+app.directive('draggable', DraggableDirective)
+app.component('Draggable', Draggabl)
+
+app.moun('#root');
+```
+
+```ts {}[main.ts]
+// Vue2
+import Vue from 'vue';
+import { DraggablePlugin, DraggableDirective } from '@braks/revue-draggable';
+
+// Use as Plugin
+Vue.use(DraggablePlugin)
+
+// or
+Vue.directive('draggable', DraggableDirective)
+// Vue.component('Draggable, Draggable) components should not be registered in Vue2, as it won't work.
+```
+
+## ๐ฎ Quickstart
+
+The easiest way to make your elements draggable is by using the **DraggableDirective** which will handle everything for you
+with no configuration necessary.
+
+````vue {}[App.vue]
+
+
I use a directive to make myself draggable
+
+
+```
+
+For full control use `` instead. DraggableCore will simply abstract over touch and mouse events but provides
+no transformation. Without callbacks, it does not provide any meaningful functionality. Alternatively you can just use
+the useDraggable and useDraggableCore abstractions which will provide you with the necessary callbacks and reactive
+fields to make your element draggable.
+
+### Vue2
+
+The components cannot be used in Vue2 as they're written in Vue3 JSX, which sadly is not downward compatible. You can
+use the useDraggable and useDraggableCore hooks to add draggability to your elements.
+
+```vue
+
+
+
+ Drag me please!
+
+
+
+```
+
+## ๐งช Development
+This project uses [Vite](https://vitejs.dev/) for development and [Rollup](https://rollupjs.org/) to create a distribution.
+
+```bash
+# start (dev)
+$ yarn dev
+
+# build app
+$ yarn build
+
+# serve app from build
+$ yarn serve
+
+# build dist
+$ yarn build:dist
+```
From 65aeb05499d0a643864432834d6ed9f2842cb894 Mon Sep 17 00:00:00 2001
From: Braks <78412429+bcakmakoglu@users.noreply.github.com>
Date: Thu, 15 Jul 2021 12:31:56 +0200
Subject: [PATCH 013/216] feat: install plugin differently for vue2 / vue3 *
Check what vue version before exporting draggable component
---
src/components/Draggable.tsx | 18 +++++++++++++-----
src/components/DraggableCore.tsx | 13 ++++++++++---
src/plugin/index.ts | 11 +++++++++--
3 files changed, 32 insertions(+), 10 deletions(-)
diff --git a/src/components/Draggable.tsx b/src/components/Draggable.tsx
index 0a113c7..9f1c74e 100644
--- a/src/components/Draggable.tsx
+++ b/src/components/Draggable.tsx
@@ -4,10 +4,8 @@ import { DraggableProps, MouseTouchEvent } from '../utils/types';
import { isVNode } from '../utils/shims';
import useDraggable from '../hooks/useDraggable';
-const Undraggable: typeof Draggable = defineComponent({
- template: "
"
-});
-const DraggableCoreNext = defineComponent({
+const DraggableCore = defineComponent({
name: 'DraggableCore',
props: {
scale: {
@@ -60,12 +56,13 @@ const DraggableCoreNext = defineComponent({
default: undefined
},
nodeRef: {
- type: Object as PropType,
+ type: Object as PropType,
default: undefined
}
},
+ emits: ['start', 'move', 'stop'],
setup(props, { slots }) {
- const nodeRef = ref(props.nodeRef ?? null);
+ const nodeRef = ref(props.nodeRef ?? null);
const draggable = reactive({
onMouseDown: (e: MouseTouchEvent) => {},
onMouseUp: (e: MouseTouchEvent) => {},
@@ -108,10 +105,4 @@ const DraggableCoreNext = defineComponent({
}
});
-if (isVue3) {
- DraggableCore = DraggableCoreNext;
-} else {
- DraggableCore = Undraggable;
-}
-
export default DraggableCore;
diff --git a/src/directives/DraggableCoreDirective.ts b/src/directives/DraggableCoreDirective.ts
index 3bb4222..23033ba 100644
--- a/src/directives/DraggableCoreDirective.ts
+++ b/src/directives/DraggableCoreDirective.ts
@@ -1,12 +1,17 @@
-import { Directive, DirectiveHook, isVue3 } from 'vue-demi';
+import { Directive, DirectiveHook, getCurrentInstance, isVue3 } from 'vue-demi';
import { DraggableCoreProps, EventHandler } from '../utils/types';
import useDraggableCore from '../hooks/useDraggableCore';
const draggableCoreDirective: DirectiveHook = (el, binding) => {
+ const instance = getCurrentInstance();
const draggable = useDraggableCore({
...binding.value,
nodeRef: el
});
+ if (instance && instance.isUnmounted) {
+ draggable.onBeforeUnmount();
+ return;
+ }
el.onmousedown = draggable.onMouseDown as EventHandler;
el.onmouseup = draggable.onMouseUp as EventHandler;
el.ontouchend = draggable.onTouchEnd as EventHandler;
diff --git a/src/directives/DraggableDirective.ts b/src/directives/DraggableDirective.ts
index 7195b6d..65c8711 100644
--- a/src/directives/DraggableDirective.ts
+++ b/src/directives/DraggableDirective.ts
@@ -1,17 +1,25 @@
-import { Directive, DirectiveHook, isVue3 } from 'vue-demi';
-import { DraggableProps, EventHandler } from '../utils/types';
+import { Directive, DirectiveHook, getCurrentInstance, isVue3 } from 'vue-demi';
+import { DraggableProps, EventHandler, MouseTouchEvent } from '../utils/types';
import useDraggable from '../hooks/useDraggable';
const draggableDirective: DirectiveHook = (el, binding) => {
+ const instance = getCurrentInstance();
const draggable = useDraggable({
...binding.value,
nodeRef: el
});
- el.onmousedown = draggable.core.onMouseDown as EventHandler;
- el.onmouseup = draggable.core.onMouseUp as EventHandler;
- el.ontouchend = draggable.core.onTouchEnd as EventHandler;
- el.dispatchEvent(new CustomEvent('draggable', { detail: draggable }));
- draggable.onUpdated();
+ if (instance && instance.isUnmounted) {
+ draggable.onBeforeUnmount();
+ } else {
+ el.onmousedown = (e) => {
+ draggable.core.onMouseDown(e as MouseTouchEvent);
+ instance?.emit('mousedown', e);
+ };
+ el.onmouseup = draggable.core.onMouseUp as EventHandler;
+ el.ontouchend = draggable.core.onTouchEnd as EventHandler;
+ el.dispatchEvent(new CustomEvent('draggable', { detail: draggable }));
+ draggable.onUpdated();
+ }
};
const DraggableDirective: Directive = {
[isVue3 ? 'mounted' : 'inserted']: draggableDirective
diff --git a/src/hooks/useDraggable.ts b/src/hooks/useDraggable.ts
index d24b0c9..8fe212b 100644
--- a/src/hooks/useDraggable.ts
+++ b/src/hooks/useDraggable.ts
@@ -1,9 +1,16 @@
import log from '../utils/log';
-import { DraggableCoreProps, DraggableEventHandler, DraggableProps, UseDraggable } from '../utils/types';
+import {
+ DraggableCoreProps,
+ DraggableEvent,
+ DraggableEventHandler,
+ DraggableProps,
+ TransformedEvent,
+ UseDraggable
+} from '../utils/types';
import { canDragX, canDragY, createDraggableData, getBoundPosition } from '../utils/positionFns';
import { createCSSTransform, createSVGTransform } from '../utils/domFns';
import useDraggableCore from './useDraggableCore';
-import { onBeforeUnmount, onUpdated } from 'vue-demi';
+import { getCurrentInstance, onBeforeUnmount, onUpdated } from 'vue-demi';
const useDraggable = ({
nodeRef,
@@ -20,7 +27,8 @@ const useDraggable = ({
defaultPosition = { x: 0, y: 0 },
bounds,
...rest
-}: Partial): UseDraggable => {
+}: Partial): UseDraggable => {
+ const instance = getCurrentInstance();
if (!nodeRef) {
console.warn(
'You are trying to use without passing a valid node reference. This will cause errors down the line.'
@@ -57,6 +65,7 @@ const useDraggable = ({
scale: scale
})
);
+ instance?.emit('drag-start', { e, data: coreData } as DraggableEvent);
if (shouldStart === false) return false;
dragging = true;
@@ -107,6 +116,7 @@ const useDraggable = ({
}
const shouldUpdate = onDragProp(e, uiData);
+ instance?.emit('drag', { e, data: coreData } as DraggableEvent);
if (shouldUpdate === false) return false;
stateX = newState.x;
stateY = newState.y;
@@ -127,6 +137,7 @@ const useDraggable = ({
coreData
})
);
+ instance?.emit('drag-stop', { e, data: coreData } as DraggableEvent);
if (shouldContinue === false) return false;
log('Draggable: onDragStop: %j', coreData);
@@ -177,6 +188,11 @@ const useDraggable = ({
Object.keys(classes).forEach((cl) => {
classes[cl] ? nodeRef?.classList.toggle(cl, true) : nodeRef?.classList.toggle(cl, false);
});
+ instance?.emit('transformed', {
+ style: styles,
+ transform: svgTransform,
+ classes
+ } as TransformedEvent);
};
const lifeCycleHooks = {
diff --git a/src/hooks/useDraggableCore.ts b/src/hooks/useDraggableCore.ts
index 43a2640..1ebad9e 100644
--- a/src/hooks/useDraggableCore.ts
+++ b/src/hooks/useDraggableCore.ts
@@ -10,7 +10,7 @@ import {
import { createCoreData, getControlPosition, snapToGrid } from '../utils/positionFns';
import log from '../utils/log';
import { isFunction } from '../utils/shims';
-import { onBeforeUnmount } from 'vue-demi';
+import { getCurrentInstance, onBeforeUnmount } from 'vue-demi';
// Simple abstraction for dragging events names.
const eventsFor = {
@@ -53,6 +53,7 @@ const useDraggableCore = ({
let lastX = NaN;
let lastY = NaN;
let touchIdentifier: number | undefined = NaN;
+ const instance = getCurrentInstance();
const handleDragStart: EventHandler = (e) => {
if (isFunction(onMouseDownProp)) {
@@ -100,6 +101,7 @@ const useDraggableCore = ({
log('calling', onStart);
const shouldUpdate = onStart(e, coreEvent);
+ instance?.emit('start', { e, coreEvent });
if (shouldUpdate === false) return;
if (enableUserSelectHack) addUserSelectStyles(ownerDocument);
@@ -145,6 +147,7 @@ const useDraggableCore = ({
log('DraggableCore: handleDrag: %j', coreEvent);
const shouldUpdate = onDrag(e, coreEvent);
+ instance?.emit('move', { e, coreEvent });
if (shouldUpdate === false) {
try {
handleDragStop(new MouseEvent('mouseup') as MouseTouchEvent);
@@ -185,6 +188,7 @@ const useDraggableCore = ({
});
const shouldContinue = onStop(e, coreEvent);
+ instance?.emit('stop', { e, coreEvent });
if (shouldContinue === false) return false;
if (nodeRef) {
diff --git a/src/utils/types.ts b/src/utils/types.ts
index 2e9888c..13df43b 100644
--- a/src/utils/types.ts
+++ b/src/utils/types.ts
@@ -1,5 +1,3 @@
-import { VNode } from 'vue-demi';
-
export type DraggableEventHandler = (e: MouseEvent, data: DraggableData) => void | false;
export type DraggableData = {
@@ -42,7 +40,18 @@ export interface DraggableProps extends DraggableCoreProps {
position: ControlPosition;
}
-export type DraggableEvent = MouseEvent | TouchEvent;
+export type DraggableEvent = {
+ e: MouseTouchEvent;
+ data: DraggableData;
+};
+
+export type TransformedEvent = {
+ style: Record | false;
+ transform: string | false;
+ classes: {
+ [x: string]: boolean;
+ };
+};
export interface DraggableCoreProps {
allowAnyClick: boolean;
From 383339fabf445d7a4ebd1272fde98d5d027fa6c9 Mon Sep 17 00:00:00 2001
From: Braks <78412429+bcakmakoglu@users.noreply.github.com>
Date: Thu, 15 Jul 2021 16:21:06 +0200
Subject: [PATCH 016/216] update: docs with info on events
---
docs/content/en/draggable-core.md | 39 +++++++++++++++++++++-
docs/content/en/draggable.md | 54 +++++++++++++++++++++++++++++--
2 files changed, 90 insertions(+), 3 deletions(-)
diff --git a/docs/content/en/draggable-core.md b/docs/content/en/draggable-core.md
index 8d4bf31..4338137 100644
--- a/docs/content/en/draggable-core.md
+++ b/docs/content/en/draggable-core.md
@@ -15,6 +15,7 @@ It does not set styles or transforms on itself and thus must have callbacks atta
## API
### Types
+
```ts
type DraggableEventHandler = (e: MouseEvent, data: DraggableData) => void | false;
@@ -28,6 +29,11 @@ type DraggableData = {
lastY: number;
};
+type DraggableEvent = {
+ e: MouseTouchEvent;
+ data: DraggableData;
+};
+
interface DraggableCoreProps {
allowAnyClick: boolean;
cancel: string;
@@ -45,6 +51,7 @@ interface DraggableCoreProps {
```
### Props
+
```ts
export default {
scale: {
@@ -108,6 +115,28 @@ It is up to the parent to set actual positions on ``.
Drag callbacks (onStart, onDrag, onStop) are called with the [same arguments as ``](/draggable).
+### Events
+
+Instead of passing callback functions you can use typical vue event handlers.
+The drawback here is that `` allows you to return false from a callback to stop the update of the current event handler.
+You might have to handle this case yourself if that is an issue or just pass the function as a prop.
+
+```vue
+
+
+
Drag me!
+
+
+... the rest of your code
+
+```
+
+#### Emittable Events
+
+* `start` - Called after native `mousedown`. Emits `DraggableEvent`.
+* `move` - Called after native `mouseup`. Emits `DraggableEvent`.
+* `stop` - Called after native `touchend`. Emits `DraggableEvent`.
+
## useDraggableCore
Instead of using the wrapper component you can compose your own
@@ -133,7 +162,15 @@ It will bind the necessary events to the element but will not apply any transfor
```vue {}[App.vue]
-
I use a directive to make myself draggable
+
+ I use a directive to make myself draggable
+
-```
-
-For full control use `` instead. DraggableCore will simply abstract over touch and mouse events but provides
-no transformation. Without callbacks, it does not provide any meaningful functionality. Alternatively you can just use
-the useDraggable and useDraggableCore abstractions which will provide you with the necessary callbacks and reactive
-fields to make your element draggable.
-
-### Vue2
-
-The components cannot be used in Vue2 as they're written in Vue3 JSX, which sadly is not downward compatible. You can
-use the useDraggable and useDraggableCore hooks to add draggability to your elements.
-
-```vue
-
-
-
- Drag me please!
-
-
-
-```
-
-Check [the example file](./example/App.vue) for more.
+Check [the example file](./example/App.vue) for more in-detail examples like dropping elements, setting boundaries or syncing states.
## ๐งช Development
This project uses [Vite](https://vitejs.dev/) for development and [Rollup](https://rollupjs.org/) to create a distribution.
diff --git a/example/App.vue b/example/App.vue
index 8e18525..6e87688 100644
--- a/example/App.vue
+++ b/example/App.vue
@@ -4,156 +4,103 @@
+ I use rem instead of px for my transforms. I also
+ have absolute positioning.
+
+
+ I depend on a CSS hack to avoid double absolute positioning.
+
+
+ I'm a component slot
+
-
I use event handlers instead of callbacks passed as props
+
I use a custom made Draggable Component using composable hooks.
```
-
-## Directive
-Lastly, you have the option of just using the DraggableDirective directly on your element.
-The directive accepts `` props as a directive binding value.
-It will bind the necessary events to the element and will move it (i.e., apply transformation styles).
-````vue {}[App.vue]
-
-
- I use a directive to make myself draggable
-
-
-
-```
-
-For full control use `` instead. DraggableCore will simply abstract over touch and mouse events but provides
-no transformation. Without callbacks, it does not provide any meaningful functionality. Alternatively you can just use
-the useDraggable and useDraggableCore abstractions which will provide you with the necessary callbacks and reactive
-fields to make your element draggable.
-
-### Vue2
-
-The components cannot be used in Vue2 as they're written in Vue3 JSX, which sadly is not downward compatible. You can
-use the useDraggable and useDraggableCore hooks to add draggability to your elements.
-
-```vue
-
-
-
- Drag me please!
-
-
-
-```
+Check [the example file](./example/App.vue) for more in-detail examples like dropping elements, setting boundaries or syncing states.
## ๐งช Development
This project uses [Vite](https://vitejs.dev/) for development and [Rollup](https://rollupjs.org/) to create a distribution.
@@ -175,3 +113,10 @@ $ yarn serve
# build dist
$ yarn build:dist
```
+
+## ๐ต๐ปโโ๏ธ Tests
+Testing is done by Cypress.
+You can find the specs in the [cypress directory](/cypress);
+```bash
+$ yarn ci // starts test server and runs tests, make sure port 3000 is open
+```
diff --git a/example/Draggable.tsx b/example/Draggable.tsx
index ae827a3..2314fba 100644
--- a/example/Draggable.tsx
+++ b/example/Draggable.tsx
@@ -1,6 +1,6 @@
import { defineComponent, onMounted, PropType, ref } from 'vue-demi';
import DraggableCore from './DraggableCore';
-import { DraggableProps, useDraggable } from '../src';
+import { DraggableOptions, useDraggable } from '../src';
import { isVNode } from '../src/utils/shims';
const Draggable = defineComponent({
@@ -8,98 +8,98 @@ const Draggable = defineComponent({
components: { DraggableCore },
props: {
axis: {
- type: String as PropType,
+ type: String as PropType,
default: 'both'
},
bounds: {
- type: [Object, String, Boolean] as PropType,
+ type: [Object, String, Boolean] as PropType,
default: false
},
defaultClassName: {
- type: String as PropType,
+ type: String as PropType,
default: 'revue-draggable'
},
defaultClassNameDragging: {
- type: String as PropType,
+ type: String as PropType,
default: 'revue-draggable-dragging'
},
defaultClassNameDragged: {
- type: String as PropType,
+ type: String as PropType,
default: 'revue-draggable-dragged'
},
defaultPosition: {
- type: Object as PropType,
+ type: Object as PropType,
default: () => ({ x: 0, y: 0 })
},
scale: {
- type: Number as PropType,
+ type: Number as PropType,
default: 1
},
position: {
- type: Object as PropType,
+ type: Object as PropType,
default: undefined
},
positionOffset: {
- type: Object as PropType,
+ type: Object as PropType,
default: undefined
},
allowAnyClick: {
- type: Boolean as PropType,
+ type: Boolean as PropType,
default: true
},
disabled: {
- type: Boolean as PropType,
+ type: Boolean as PropType,
default: false
},
enableUserSelectHack: {
- type: Boolean as PropType,
+ type: Boolean as PropType,
default: true
},
onStart: {
- type: Function as PropType,
+ type: Function as PropType,
default: () => {}
},
onDrag: {
- type: Function as PropType,
+ type: Function as PropType,
default: () => {}
},
onStop: {
- type: Function as PropType,
+ type: Function as PropType,
default: () => {}
},
onMouseDown: {
- type: Function as PropType,
+ type: Function as PropType,
default: () => {}
},
cancel: {
- type: String as PropType,
+ type: String as PropType,
default: undefined
},
offsetParent: {
- type: Object as PropType,
+ type: Object as PropType,
default: () => {}
},
grid: {
- type: Array as unknown as PropType,
+ type: Array as unknown as PropType,
default: undefined
},
handle: {
- type: String as PropType,
+ type: String as PropType,
default: undefined
},
nodeRef: {
- type: Object as PropType,
+ type: Object as PropType,
default: undefined
}
},
emits: ['drag-start', 'drag-move', 'drag-stop', 'transformed', 'core-start', 'core-move', 'core-stop'],
setup(props, { slots }) {
- const nodeRef = ref(props.nodeRef ?? null);
+ const nodeRef = ref(props.nodeRef ?? null);
onMounted(() => {
const node = nodeRef.value && isVNode(nodeRef.value) ? (nodeRef.value as any).$el : nodeRef.value;
useDraggable({
- ...(props as DraggableProps),
+ ...(props as DraggableOptions),
nodeRef: node
});
});
diff --git a/example/DraggableCore.tsx b/example/DraggableCore.tsx
index 3d4f4e3..89752b5 100644
--- a/example/DraggableCore.tsx
+++ b/example/DraggableCore.tsx
@@ -1,71 +1,71 @@
import { defineComponent, onMounted, PropType, ref } from 'vue-demi';
-import { useDraggableCore, DraggableCoreProps } from '../src';
+import { useDraggableCore, DraggableCoreOptions } from '../src';
import { isVNode } from '../src/utils/shims';
const DraggableCore = defineComponent({
name: 'DraggableCore',
props: {
scale: {
- type: Number as PropType,
+ type: Number as PropType,
default: 1
},
allowAnyClick: {
- type: Boolean as PropType,
+ type: Boolean as PropType,
default: true
},
disabled: {
- type: Boolean as PropType,
+ type: Boolean as PropType,
default: false
},
enableUserSelectHack: {
- type: Boolean as PropType,
+ type: Boolean as PropType,
default: true
},
onStart: {
- type: Function as PropType,
+ type: Function as PropType,
default: () => {}
},
onDrag: {
- type: Function as PropType,
+ type: Function as PropType,
default: () => {}
},
onStop: {
- type: Function as PropType,
+ type: Function as PropType,
default: () => {}
},
onMouseDown: {
- type: Function as PropType,
+ type: Function as PropType,
default: () => {}
},
cancel: {
- type: String as PropType,
+ type: String as PropType,
default: undefined
},
offsetParent: {
- type: Object as PropType,
+ type: Object as PropType,
default: undefined
},
grid: {
- type: Array as unknown as PropType,
+ type: Array as unknown as PropType,
default: undefined
},
handle: {
- type: String as PropType,
+ type: String as PropType,
default: undefined
},
nodeRef: {
- type: Object as PropType,
+ type: Object as PropType,
default: undefined
}
},
emits: ['core-start', 'core-move', 'core-stop'],
setup(props, { slots }) {
- const nodeRef = ref(props.nodeRef ?? null);
+ const nodeRef = ref(props.nodeRef ?? null);
onMounted(() => {
const node = nodeRef.value && isVNode(nodeRef.value) ? (nodeRef.value as any).$el : nodeRef.value;
useDraggableCore({
- ...(props as DraggableCoreProps),
+ ...(props as DraggableCoreOptions),
nodeRef: node
});
});
diff --git a/src/directive/DraggableDirective.ts b/src/directive/DraggableDirective.ts
index 483dda7..8570a73 100644
--- a/src/directive/DraggableDirective.ts
+++ b/src/directive/DraggableDirective.ts
@@ -1,10 +1,10 @@
import { Directive, DirectiveHook, isVue3, VNode } from 'vue-demi';
-import { DraggableProps, UseDraggable } from '../utils/types';
+import { DraggableOptions, UseDraggable } from '../utils/types';
import useDraggable from '../hooks/useDraggable';
import useDraggableCore from '../hooks/useDraggableCore';
-const onMounted: DirectiveHook = (el, binding) => {
- const options: Partial = {
+const onMounted: DirectiveHook = (el, binding) => {
+ const options: Partial = {
...binding.value,
nodeRef: el as HTMLElement
};
@@ -19,7 +19,7 @@ const onMounted: DirectiveHook = (el,
}
};
-const onUpdated: DirectiveHook = (el, binding) => {
+const onUpdated: DirectiveHook = (el, binding) => {
// typehack as we store the draggable instance on the element, see the comment above
const element = el as any;
if (typeof element['revue-draggable'] !== 'undefined' && binding.value) {
@@ -28,14 +28,14 @@ const onUpdated: DirectiveHook = (el,
}
};
-const onUnmounted: DirectiveHook = (el) => {
+const onUnmounted: DirectiveHook = (el) => {
const element = el as any;
if (typeof element['revue-draggable'] !== 'undefined') {
delete element['revue-draggable'];
}
};
-const DraggableDirective: Directive = {
+const DraggableDirective: Directive = {
[isVue3 ? 'mounted' : 'inserted']: onMounted,
[isVue3 ? 'updated' : 'componentUpdated']: onUpdated,
[isVue3 ? 'unmounted' : 'unbind']: onUnmounted
diff --git a/src/hooks/useDraggable.ts b/src/hooks/useDraggable.ts
index b2a35ef..4d99820 100644
--- a/src/hooks/useDraggable.ts
+++ b/src/hooks/useDraggable.ts
@@ -2,10 +2,10 @@ import { getCurrentInstance, onBeforeUnmount, onUpdated } from 'vue-demi';
import { createEventHook } from '@vueuse/core';
import log from '../utils/log';
import {
- DraggableCoreProps,
+ DraggableCoreOptions,
DraggableEventHandler,
DraggableHook,
- DraggableProps,
+ DraggableOptions,
DraggableState,
TransformedData,
UseDraggable
@@ -40,7 +40,7 @@ const useDraggable = ({
bounds,
update,
...rest
-}: Partial): UseDraggable => {
+}: Partial): UseDraggable => {
if (!nodeRef) {
console.warn(
'You are trying to use without passing a valid node reference. This will cause errors down the line.'
@@ -213,9 +213,9 @@ const useDraggable = ({
};
const styles =
- !draggable.state.isElementSVG && createCSSTransform(transformOpts(), positionOffset as DraggableProps['positionOffset']);
+ !draggable.state.isElementSVG && createCSSTransform(transformOpts(), positionOffset as DraggableOptions['positionOffset']);
const svgTransform =
- draggable.state.isElementSVG && createSVGTransform(transformOpts(), positionOffset as DraggableProps['positionOffset']);
+ draggable.state.isElementSVG && createSVGTransform(transformOpts(), positionOffset as DraggableOptions['positionOffset']);
const classes = {
[defaultClassName]: true,
[defaultClassNameDragging]: draggable.state.dragging,
@@ -292,7 +292,7 @@ const useDraggable = ({
onDrag,
onStop: onDragStop,
...rest
- } as DraggableCoreProps);
+ } as DraggableCoreOptions);
onUpdateHook.on((state) => {
log('Draggable: State Updated %j', state);
diff --git a/src/hooks/useDraggableCore.ts b/src/hooks/useDraggableCore.ts
index 070ac08..8e04f78 100644
--- a/src/hooks/useDraggableCore.ts
+++ b/src/hooks/useDraggableCore.ts
@@ -1,7 +1,7 @@
import { getCurrentInstance, onBeforeUnmount } from 'vue-demi';
import { createEventHook } from '@vueuse/core';
import {
- DraggableCoreProps,
+ DraggableCoreOptions,
DraggableCoreState,
DraggableHook, DraggableState,
EventHandler,
@@ -61,7 +61,7 @@ const useDraggableCore = ({
onStop = () => {},
onDrag = () => {},
onMouseDown: onMouseDownProp = () => {}
-}: Partial): UseDraggableCore => {
+}: Partial): UseDraggableCore => {
if (!nodeRef) {
console.warn(
'You are trying to use without passing a valid node reference. This will cause errors down the line.'
diff --git a/src/utils/positionFns.ts b/src/utils/positionFns.ts
index 78680a2..a7f075b 100644
--- a/src/utils/positionFns.ts
+++ b/src/utils/positionFns.ts
@@ -1,6 +1,6 @@
import { isNum, int } from './shims';
import { getTouch, innerWidth, innerHeight, offsetXYFromParent, outerWidth, outerHeight } from './domFns';
-import { Bounds, ControlPosition, DraggableData, DraggableProps, MouseTouchEvent } from './types';
+import { Bounds, ControlPosition, DraggableData, DraggableOptions, MouseTouchEvent } from './types';
export function getBoundPosition({ bounds, x, y, node }: { bounds: any; x: number; y: number; node: any }): [number, number] {
// If no bounds, short-circuit and move on
@@ -58,11 +58,11 @@ export function snapToGrid(grid: [number, number], pendingX: number, pendingY: n
return [x, y];
}
-export function canDragX(axis: DraggableProps['axis']): boolean {
+export function canDragX(axis: DraggableOptions['axis']): boolean {
return axis === 'both' || axis === 'x';
}
-export function canDragY(axis: DraggableProps['axis']): boolean {
+export function canDragY(axis: DraggableOptions['axis']): boolean {
return axis === 'both' || axis === 'y';
}
diff --git a/src/utils/types.ts b/src/utils/types.ts
index 8fe536c..b158b3e 100644
--- a/src/utils/types.ts
+++ b/src/utils/types.ts
@@ -31,7 +31,7 @@ export interface DraggableBounds {
bottom?: number;
}
-export interface DraggableProps extends DraggableCoreProps {
+export interface DraggableOptions extends DraggableCoreOptions {
axis: 'both' | 'x' | 'y' | 'none';
bounds: DraggableBounds | string | false;
defaultClassName: string;
@@ -51,7 +51,7 @@ export type TransformedData = {
};
};
-export interface DraggableCoreProps {
+export interface DraggableCoreOptions {
allowAnyClick: boolean;
cancel: string;
disabled: boolean;
@@ -68,9 +68,9 @@ export interface DraggableCoreProps {
nodeRef: HTMLElement;
}
-export type DraggableCoreState = State & DraggableCoreProps;
+export type DraggableCoreState = State & DraggableCoreOptions;
-export type DraggableState = State & DraggableProps;
+export type DraggableState = State & DraggableOptions;
interface State {
dragging: boolean;
From 183a189bde12c7f0a06dc189d92d1888ec93bd8f Mon Sep 17 00:00:00 2001
From: Braks <78412429+bcakmakoglu@users.noreply.github.com>
Date: Mon, 19 Jul 2021 21:03:06 +0200
Subject: [PATCH 045/216] update: test & example
---
cypress/integration/1-tests/draggable.spec.js | 2 +-
example/App.vue | 30 +++++++++++++++++++
2 files changed, 31 insertions(+), 1 deletion(-)
diff --git a/cypress/integration/1-tests/draggable.spec.js b/cypress/integration/1-tests/draggable.spec.js
index 3ab7d93..ba11e07 100644
--- a/cypress/integration/1-tests/draggable.spec.js
+++ b/cypress/integration/1-tests/draggable.spec.js
@@ -8,7 +8,7 @@ describe('draggable', () => {
cy.get('#app').should('be.visible');
cy.get('#app')
.get('.box')
- .should('have.length.at.least', 26)
+ .should('have.length.at.least', 23)
.should('have.class', 'revue-draggable')
.each((el) => {
const originalPosition = el.position();
diff --git a/example/App.vue b/example/App.vue
index 6e87688..3b5e474 100644
--- a/example/App.vue
+++ b/example/App.vue
@@ -22,6 +22,9 @@
You must click my handle to drag me
+
+ I can only be moved within the confines of the body element.
+
+ I can detect drops from the next box.
+
+
+ I can be dropped onto another box.
+
+
+
+
+ I can only be moved within my offsetParent.
+ Both parent padding and child margin work properly.
+
+
+ I also can only be moved within my offsetParent.
+ Both parent padding and child margin work properly.
+
+
+
+
+ I already have an absolute position.
+
+
+ {{ "I have a default position of {x: 25, y: 25}, so I'm slightly offset." }}
+
+
+ {{ "I have a default position based on percents {x: '-10%', y: '-10%'}, so I'm slightly offset." }}
+
+
My position can be changed programmatically.
I have a drag handler to sync state.
From f24900135ef25c125644d5909a1962b87d0e4685 Mon Sep 17 00:00:00 2001
From: Braks <78412429+bcakmakoglu@users.noreply.github.com>
Date: Mon, 19 Jul 2021 21:07:27 +0200
Subject: [PATCH 046/216] v0.1.14-0
---
package.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/package.json b/package.json
index f524143..aaffbf6 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "@braks/revue-draggable",
- "version": "0.1.13",
+ "version": "0.1.14-0",
"private": false,
"repository": {
"type": "git",
From 6f0dddbe619ee35ca9bc2ca54a19333166e929dd Mon Sep 17 00:00:00 2001
From: Braks <78412429+bcakmakoglu@users.noreply.github.com>
Date: Tue, 20 Jul 2021 01:32:03 +0200
Subject: [PATCH 047/216] feat: Reimplemented components, though they will not
be without a wrapper so we can support Vue2 * Composable or directive usage
is preferred * Composables heavily updated with better unMounting and no
callbacks (instead use event hooks)
---
example/App.vue | 69 +++----
example/DraggableCore.tsx | 77 --------
.../components/Draggable.ts | 57 +++---
src/components/DraggableCore.ts | 65 +++++++
src/directive/DraggableDirective.ts | 52 ++++--
src/hooks/useDraggable.ts | 164 +++++++----------
src/hooks/useDraggableCore.ts | 173 +++++++-----------
src/utils/domFns.ts | 4 +-
src/utils/positionFns.ts | 9 +-
src/utils/shims.ts | 6 -
src/utils/types.ts | 34 ++--
11 files changed, 321 insertions(+), 389 deletions(-)
delete mode 100644 example/DraggableCore.tsx
rename example/Draggable.tsx => src/components/Draggable.ts (62%)
create mode 100644 src/components/DraggableCore.ts
diff --git a/example/App.vue b/example/App.vue
index 3b5e474..2c37650 100644
--- a/example/App.vue
+++ b/example/App.vue
@@ -4,33 +4,33 @@
My position can be changed programmatically.
I have a dragStop handler to sync state.
@@ -106,8 +107,8 @@
class="box rem-position-fix"
style="position: absolute; bottom: 6.25rem; right: 18rem"
v-draggable
- @drag-start="onStart"
- @drag-stop="onStop"
+ @start="onStart"
+ @stop="onStop"
>
I use rem instead of px for my transforms. I also
have absolute positioning.
@@ -115,10 +116,12 @@
I depend on a CSS hack to avoid double absolute positioning.
-
- I'm a component slot
-
-
+
+
+ I'm in a nested component
+
+
+
I use a custom made Draggable Component using composable hooks.
@@ -143,8 +145,7 @@
@move="onMove"
>
I use rem instead of px for my transforms. I
- also have absolute positioning.
- I depend on a CSS hack to avoid double absolute positioning.
+ also have absolute positioning. I depend on a CSS hack to avoid double absolute positioning.
+ I can only be moved within the confines of the body element.
+
+
+
+
Drag here
+
+
+
+ I have long scrollable content with a handle
+ {{ '\n' + Array(40).fill('x').join('\n') }}
-
- Can't drag here
-
Dragging here works
-
-
- I snap to a 25 x 25 grid
-
-
- I snap to a 50 x 50 grid
-
-
- I can detect drops from the next box.
-
-
- I can be dropped onto another box.
-
-
-
-
- I can only be moved within my offsetParent.
- Both parent padding and child margin work properly.
-
-
- I also can only be moved within my offsetParent.
- Both parent padding and child margin work properly.
-
+
+
+ Can't drag here
+
Dragging here works
+
+
+ I snap to a 25 x 25 grid
+
+
+ I snap to a 50 x 50 grid
+
+
+ I can detect drops from the next box.
+
+
+ I can be dropped onto another box.
+
+
+
+
+ I can only be moved within my offsetParent.
+ Both parent padding and child margin work properly.
+
+
+ I also can only be moved within my offsetParent.
+ Both parent padding and child margin work properly.
-
- I already have an absolute position.
-
-
- {{ "I have a default position of {x: 25, y: 25}, so I'm slightly offset." }}
-
-
- {{ "I have a default position based on percents {x: '-10%', y: '-10%'}, so I'm slightly offset." }}
+
+
+ I already have an absolute position.
+
+
+ {{ "I have a default position of {x: 25, y: 25}, so I'm slightly offset." }}
+
+
+ {{ "I have a default position based on percents {x: '-10%', y: '-10%'}, so I'm slightly offset." }}
+
+
+ My position can be changed programmatically.
+ I have a drag handler to sync state.
+
+
-
- My position can be changed programmatically.
- I have a drag handler to sync state.
-
-
-
-
-
-
+
+
-
- My position can be changed programmatically.
- I have a dragStop handler to sync state.
-
-
-
-
-
-
+
+
+ My position can be changed programmatically.
+ I have a dragStop handler to sync state.
+
+
-
- I use rem instead of px for my transforms. I
- also have absolute positioning. I depend on a CSS hack to avoid double absolute positioning.
+
+
-
-
- I'm in a nested component
-
-
-
-
3 Slots in a single Draggable Wrapper
-
3 Slots in a single Draggable Wrapper
-
3 Slots in a single Draggable Wrapper
-
+
+ I use rem instead of px for my transforms. I
+ also have absolute positioning. I depend on a CSS hack to avoid double absolute positioning.
+
+
+
+ I'm in a nested component
+
+
+
+
3 Slots in a single Draggable Wrapper
+
3 Slots in a single Draggable Wrapper
+
3 Slots in a single Draggable Wrapper
+
+ -->
-
+
"
:transform="translateTransformToRem(transform, 16)"
class="rem-position-fix"
style="position: absolute; bottom: 0; right: 22rem"
@@ -220,9 +440,19 @@
also have absolute positioning. I depend on a CSS hack to avoid double absolute positioning.
-
+
- I'm in a nested component!
+ I' m in a nested component!
@@ -231,6 +461,13 @@
+
+
+
+
+
+
+
+
+
I use rem instead of px for my transforms. I
also have absolute positioning. I depend on a CSS hack to avoid double absolute positioning.
+
+
+
+
+
+
+
+
+
-
-
3 Slots in a single Draggable Wrapper
-
3 Slots in a single Draggable Wrapper
-
3 Slots in a single Draggable Wrapper
-
"
- :transform="translateTransformToRem(transform, 16)"
class="rem-position-fix"
style="position: absolute; bottom: 0; right: 22rem"
@start="onStart"
@stop="onStop"
@move="onMove"
+ @transformed="translateTransformToRem(transform, 16)"
>
I use rem instead of px for my transforms. I
also have absolute positioning. I depend on a CSS hack to avoid double absolute positioning.
From 46b9bf41094223c6350af9589239d4f9e0711fee Mon Sep 17 00:00:00 2001
From: Braks <78412429+bcakmakoglu@users.noreply.github.com>
Date: Fri, 13 Aug 2021 17:16:27 +0200
Subject: [PATCH 139/216] update(core): Stateless core
* Remove onUpdateHook (redundant)
* Remove positions from core state
* Remove redundant typings from core state
* Add typings to draggable
BREAKING CHANGE: Core does not accept position options. It will stay "stateless" (in terms of positions) and will only accept updates on it's options, i.e. disabling position tracking, handle definitions etc.
---
src/components/Draggable.ts | 2 +-
src/hooks/useDraggable.ts | 20 +++-----------
src/hooks/useDraggableCore.ts | 52 ++++++++++++-----------------------
src/utils/types.ts | 10 +++----
4 files changed, 28 insertions(+), 56 deletions(-)
diff --git a/src/components/Draggable.ts b/src/components/Draggable.ts
index 25cd0f5..d666d9d 100644
--- a/src/components/Draggable.ts
+++ b/src/components/Draggable.ts
@@ -1,4 +1,4 @@
-import { h, defineComponent, PropType, Ref, onUpdated, isVue3 } from 'vue-demi';
+import { h, defineComponent, PropType, onUpdated, isVue3 } from 'vue-demi';
import { templateRef } from '@vueuse/core';
import { DraggableOptions } from '../utils/types';
import useDraggable from '../hooks/useDraggable';
diff --git a/src/hooks/useDraggable.ts b/src/hooks/useDraggable.ts
index 8a008d5..fe3bece 100644
--- a/src/hooks/useDraggable.ts
+++ b/src/hooks/useDraggable.ts
@@ -12,7 +12,6 @@ import {
import { canDragX, canDragY, createDraggableData, getBoundPosition } from '../utils/positionFns';
import { createCSSTransform, createSVGTransform } from '../utils/domFns';
import useDraggableCore from './useDraggableCore';
-import equal from 'fast-deep-equal/es6';
const useDraggable = (target: MaybeRef, options: Partial): UseDraggable => {
if (!target) {
@@ -58,34 +57,25 @@ const useDraggable = (target: MaybeRef, options: Partial)
let state: Ref;
if (isVue3) {
state = controlledRef(initState(options), {
- onBeforeChange(val, oldVal) {
- if (equal(val, oldVal)) {
- return;
- }
+ onBeforeChange(val) {
coreState.value = { ...coreState.value, ...val };
},
- onChanged(val) {
+ onChanged() {
onUpdated();
- onUpdateHook.trigger(val);
}
});
} else {
state = ref(initState(options)) as Ref;
- watch(state, (val, oldVal) => {
- if (equal(val, oldVal)) {
- return;
- }
+ watch(state, (val) => {
coreState.value = { ...coreState.value, ...val };
onUpdated();
- onUpdateHook.trigger(val);
});
}
const onDragStartHook = createEventHook(),
onDragHook = createEventHook(),
onDragStopHook = createEventHook(),
- onTransformedHook = createEventHook(),
- onUpdateHook = createEventHook>();
+ onTransformedHook = createEventHook();
const onDragStart: DraggableEventHandler = (e, data) => {
log('Draggable: onDragStart: %j', data);
@@ -103,7 +93,6 @@ const useDraggable = (target: MaybeRef, options: Partial)
get(state).dragging = true;
get(state).dragged = true;
- transform();
};
const onDrag: DraggableEventHandler = (e, data) => {
@@ -276,7 +265,6 @@ const useDraggable = (target: MaybeRef, options: Partial)
return {
state,
- onUpdated: onUpdateHook.on,
onDragStart: onDragStartHook.on,
onDrag: onDragHook.on,
onDragStop: onDragStopHook.on,
diff --git a/src/hooks/useDraggableCore.ts b/src/hooks/useDraggableCore.ts
index 18311a7..ae62551 100644
--- a/src/hooks/useDraggableCore.ts
+++ b/src/hooks/useDraggableCore.ts
@@ -18,7 +18,6 @@ import {
import { createCoreData, getControlPosition, snapToGrid } from '../utils/positionFns';
import log from '../utils/log';
import { addEvent } from '../utils/domFns';
-import equal from 'fast-deep-equal/es6';
// Simple abstraction for dragging events names.
const eventsFor = {
@@ -60,48 +59,34 @@ const useDraggableCore = (target: MaybeRef, options: Partial {},
move: () => {},
stop: () => {}
},
initialState
);
+ let [posX, posY] = [0, 0];
const node = computed(() => unrefElement(target));
let state: Ref;
if (isVue3) {
state = controlledRef(initState(options), {
- onBeforeChange(val, oldVal) {
- if (equal(val, oldVal)) {
- return;
- }
- },
- onChanged(val) {
+ onChanged() {
init();
- onUpdateHook.trigger(val);
}
});
} else {
state = ref(initState(options)) as Ref;
- watch(state, (val, oldVal) => {
- if (equal(val, oldVal)) {
- return;
- }
+ watch(state, () => {
init();
- onUpdateHook.trigger(val);
});
}
const onDragStartHook = createEventHook(),
onDragHook = createEventHook(),
- onDragStopHook = createEventHook(),
- onUpdateHook = createEventHook>();
+ onDragStopHook = createEventHook();
const handleDragStart: EventHandler = (e) => {
if (!get(state).allowAnyClick && e.button !== 0) return false;
@@ -138,8 +123,8 @@ const useDraggableCore = (target: MaybeRef, options: Partial, options: Partial, options: Partial, options: Partial, options: Partial, options: Partial = (e: T) => void | false;
@@ -39,6 +40,10 @@ export interface DraggableOptions extends DraggableCoreOptions {
defaultPosition: ControlPosition;
positionOffset?: PositionOffsetControlPosition;
position?: ControlPosition;
+ prevPropsPosition: { x: number; y: number };
+ isElementSVG: boolean;
+ x: number;
+ y: number;
}
export interface DraggableCoreOptions {
@@ -63,12 +68,8 @@ export type DraggableState = State & DraggableOptions;
interface State {
dragging: boolean;
dragged: boolean;
- x: number;
- y: number;
- prevPropsPosition: { x: number; y: number };
slackX: number;
slackY: number;
- isElementSVG: boolean;
touch?: number;
}
@@ -77,7 +78,6 @@ export interface UseDraggable {
onDrag: EventHookOn;
onDragStop: EventHookOn;
onTransformed: EventHookOn;
- onUpdated: EventHookOn>;
state: Ref>;
}
From 15e4d90e88101429f2c9162fdee68ec3546e8baf Mon Sep 17 00:00:00 2001
From: Braks <78412429+bcakmakoglu@users.noreply.github.com>
Date: Fri, 13 Aug 2021 17:17:23 +0200
Subject: [PATCH 140/216] update(docs): Draggable and Draggable Core
documentation
* Add correct types to docs
* Remove onUpdateHook from docs
---
docs/content/en/draggable-core.md | 30 +++++++++-----
docs/content/en/draggable.md | 67 +++++++++++++++++--------------
2 files changed, 56 insertions(+), 41 deletions(-)
diff --git a/docs/content/en/draggable-core.md b/docs/content/en/draggable-core.md
index 8bb697e..2ee91ad 100644
--- a/docs/content/en/draggable-core.md
+++ b/docs/content/en/draggable-core.md
@@ -31,19 +31,27 @@ type DraggableData = {
export interface DraggableCoreOptions {
allowAnyClick: boolean;
- cancel: string;
- disabled: boolean;
- update?: boolean;
enableUserSelectHack: boolean;
- offsetParent: HTMLElement;
- grid: [number, number];
+ disabled: boolean;
+ update: boolean;
+ offsetParent?: HTMLElement;
+ grid?: [number, number];
handle: string;
- onStart: DraggableEventHandler;
- onDrag: DraggableEventHandler;
- onStop: DraggableEventHandler;
- onMouseDown: (e: MouseEvent) => void;
+ cancel: string;
scale: number;
- nodeRef: HTMLElement;
+ start: DraggableEventHandler;
+ move: DraggableEventHandler;
+ stop: DraggableEventHandler;
+}
+
+type DraggableCoreState = State & DraggableCoreOptions;
+
+interface State {
+ dragging: boolean;
+ dragged: boolean;
+ slackX: number;
+ slackY: number;
+ touch?: number;
}
```
@@ -84,7 +92,7 @@ interface UseDraggable {
onDrag: EventHookOn;
onDragStop: EventHookOn;
onTransformed: EventHookOn;
- updateState: (state: Partial) => Partial | void;
+ state: Ref;
}
// useDraggableCore hooks
diff --git a/docs/content/en/draggable.md b/docs/content/en/draggable.md
index 4d6993d..9f1cf72 100644
--- a/docs/content/en/draggable.md
+++ b/docs/content/en/draggable.md
@@ -6,7 +6,7 @@ position: 2
---
A `` element wraps an existing element and extends it with new event handlers and styles.
You can either use a component wrapper, which creates an element in the DOM, a directive, which will not create
-an element or a composable and it's hooks (no element included either).
+an element or a composable, and it's hooks (no element included either).
Draggable items move using CSS Transforms.
This allows items to be dragged regardless of their current positioning (relative, absolute, or static).
@@ -75,8 +75,12 @@ interface DraggableOptions extends DraggableCoreOptions {
defaultClassNameDragging: string;
defaultClassNameDragged: string;
defaultPosition: ControlPosition;
- positionOffset: PositionOffsetControlPosition;
- position: ControlPosition;
+ positionOffset?: PositionOffsetControlPosition;
+ position?: ControlPosition;
+ prevPropsPosition: { x: number; y: number };
+ isElementSVG: boolean;
+ x: number;
+ y: number;
}
type TransformedData = {
@@ -87,35 +91,13 @@ type TransformedData = {
};
};
-interface DraggableCoreOptions {
- allowAnyClick: boolean;
- cancel: string;
- disabled: boolean;
- update?: boolean;
- enableUserSelectHack: boolean;
- offsetParent: HTMLElement;
- grid: [number, number];
- handle: string;
- onStart: DraggableEventHandler;
- onDrag: DraggableEventHandler;
- onStop: DraggableEventHandler;
- onMouseDown: (e: MouseEvent) => void;
- scale: number;
-}
-
-type DraggableCoreState = State & DraggableCoreOptions;
-
type DraggableState = State & DraggableOptions;
interface State {
dragging: boolean;
dragged: boolean;
- x: number;
- y: number;
- prevPropsPosition: { x: number; y: number };
slackX: number;
slackY: number;
- isElementSVG: boolean;
touch?: number;
}
@@ -124,11 +106,9 @@ interface UseDraggable {
onDrag: EventHookOn;
onDragStop: EventHookOn;
onTransformed: EventHookOn;
- updateState: (state: Partial) => Partial | void;
+ state: Ref;
}
-type UseDraggableCore = Omit;
-
interface DraggableEvent {
event: MouseEvent;
data: DraggableData;
@@ -152,6 +132,32 @@ interface DraggableEvent {
* `stop` - Called after native `mouseup` or `touchend` event and `stop` event of ``. Emits `DraggableEvent`.
* `transformed` - Called after the element has been transformed (i.e., styles to move it have been applied). Emits `TransformEvent`
+
+#### Scoped Slot
+
+A scoped slot is available containing the state of the Draggable component.
+Overwriting the state will trigger Draggable to transform and update it's internal state.
+
+```vue
+
+