react-use-drag 0.3.1 → 0.3.5
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 +55 -5
- package/dist/index.cjs +17 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +17 -3
- package/dist/index.mjs.map +1 -1
- package/dist/useDrag.d.ts +25 -4
- package/package.json +11 -3
package/README.md
CHANGED
|
@@ -1,9 +1,21 @@
|
|
|
1
1
|
# React use drag [](https://www.npmjs.com/package/react-use-drag) 
|
|
2
2
|
|
|
3
|
-
Drag interactions made easier.
|
|
3
|
+
Drag interactions made easier. Lightweight, React hook-based, and powered by Pointer Events for seamless mouse and touch support.
|
|
4
|
+
|
|
5
|
+
Try interactive [CodeSandbox demo](https://codesandbox.io/p/sandbox/react-use-drag-trjpqp?file=%2Fsrc%2FApp.js).
|
|
4
6
|
|
|
5
7
|

|
|
6
8
|
|
|
9
|
+
## Table of Contents
|
|
10
|
+
|
|
11
|
+
- [Installation](#installation)
|
|
12
|
+
- [How to use](#how-to-use)
|
|
13
|
+
- [API Reference](#api-reference)
|
|
14
|
+
- [Options](#options)
|
|
15
|
+
- [Return Value](#return-value)
|
|
16
|
+
- [Features](#features)
|
|
17
|
+
- [License](#license)
|
|
18
|
+
|
|
7
19
|
## Installation
|
|
8
20
|
|
|
9
21
|
```bash
|
|
@@ -14,23 +26,28 @@ npm install react-use-drag
|
|
|
14
26
|
|
|
15
27
|
```jsx
|
|
16
28
|
import { useDrag } from 'react-use-drag'
|
|
29
|
+
import { useState, useCallback } from 'react'
|
|
17
30
|
|
|
18
31
|
const App = () => {
|
|
19
32
|
const [position, setPosition] = useState({ x: 0, y: 0 })
|
|
20
33
|
const [positionOffset, setPositionOffset] = useState({ x: 0, y: 0 })
|
|
34
|
+
|
|
21
35
|
const onRelativePositionChange = useCallback((x, y) => {
|
|
22
36
|
setPositionOffset({ x, y })
|
|
23
37
|
}, [])
|
|
38
|
+
|
|
24
39
|
const onStart = useCallback(() => {
|
|
25
40
|
console.log('Dragging has started')
|
|
26
41
|
}, [])
|
|
42
|
+
|
|
27
43
|
const onEnd = useCallback((x, y) => {
|
|
28
|
-
setPosition((
|
|
29
|
-
x:
|
|
30
|
-
y:
|
|
44
|
+
setPosition((pos) => ({
|
|
45
|
+
x: pos.x + x,
|
|
46
|
+
y: pos.y + y,
|
|
31
47
|
}))
|
|
32
48
|
setPositionOffset({ x: 0, y: 0 })
|
|
33
49
|
}, [])
|
|
50
|
+
|
|
34
51
|
const { elementProps, isMoving } = useDrag({
|
|
35
52
|
onRelativePositionChange,
|
|
36
53
|
onStart,
|
|
@@ -41,7 +58,8 @@ const App = () => {
|
|
|
41
58
|
<button
|
|
42
59
|
className="draggable"
|
|
43
60
|
style={{
|
|
44
|
-
|
|
61
|
+
transform: `translate(${position.x + positionOffset.x}px, ${position.y + positionOffset.y}px)`,
|
|
62
|
+
touchAction: 'none' // Recommended for mobile support
|
|
45
63
|
}}
|
|
46
64
|
{...elementProps}
|
|
47
65
|
>
|
|
@@ -50,3 +68,35 @@ const App = () => {
|
|
|
50
68
|
)
|
|
51
69
|
}
|
|
52
70
|
```
|
|
71
|
+
|
|
72
|
+
## API Reference
|
|
73
|
+
|
|
74
|
+
### `useDrag(options)`
|
|
75
|
+
|
|
76
|
+
#### Options
|
|
77
|
+
|
|
78
|
+
| Property | Type | Description |
|
|
79
|
+
| :--- | :--- | :--- |
|
|
80
|
+
| `onRelativePositionChange` | `(x: number, y: number) => void` | **Required.** Called when the position changes during dragging. `x` and `y` are relative to the start position. |
|
|
81
|
+
| `onStart` | `() => void` | Optional. Called when the dragging interaction starts. |
|
|
82
|
+
| `onEnd` | `(x: number, y: number) => void` | Optional. Called when the dragging interaction ends. Receives final relative `x` and `y`. |
|
|
83
|
+
|
|
84
|
+
#### Return Value
|
|
85
|
+
|
|
86
|
+
An object containing:
|
|
87
|
+
|
|
88
|
+
| Property | Type | Description |
|
|
89
|
+
| :--- | :--- | :--- |
|
|
90
|
+
| `isMoving` | `boolean` | `true` if a drag interaction is currently active. |
|
|
91
|
+
| `elementProps` | `object` | Props to be spread onto the target element. Contains `onPointerDown`, `onPointerUp`, `onPointerMove`, and `onPointerCancel`. |
|
|
92
|
+
|
|
93
|
+
## Features
|
|
94
|
+
|
|
95
|
+
- **Pointer Events:** Works with Mouse, Touch, and Pen out of the box.
|
|
96
|
+
- **Lightweight:** Zero dependencies (other than React) and tiny bundle size.
|
|
97
|
+
- **Predictable:** Simple API based on relative position changes.
|
|
98
|
+
- **TypeScript:** Fully typed for a great developer experience.
|
|
99
|
+
|
|
100
|
+
## License
|
|
101
|
+
|
|
102
|
+
ISC
|
package/dist/index.cjs
CHANGED
|
@@ -2,6 +2,20 @@
|
|
|
2
2
|
|
|
3
3
|
var react = require('react');
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* Hook to handle drag interactions using Pointer Events.
|
|
7
|
+
*
|
|
8
|
+
* @param options - Configuration options for the drag interaction.
|
|
9
|
+
* @returns An object containing:
|
|
10
|
+
* - `isMoving`: boolean indicating if dragging is active.
|
|
11
|
+
* - `elementProps`: props to spread onto the draggable element.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* const { elementProps, isMoving } = useDrag({
|
|
15
|
+
* onRelativePositionChange: (x, y) => console.log('Offset:', x, y),
|
|
16
|
+
* })
|
|
17
|
+
* return <div {...elementProps} style={{ touchAction: 'none' }} />
|
|
18
|
+
*/
|
|
5
19
|
var useDrag = function (options) {
|
|
6
20
|
var onRelativePositionChange = options.onRelativePositionChange, onStart = options.onStart, onEnd = options.onEnd;
|
|
7
21
|
var _a = react.useState(false), isMoving = _a[0], setIsMoving = _a[1];
|
|
@@ -18,7 +32,7 @@ var useDrag = function (options) {
|
|
|
18
32
|
event.currentTarget.setPointerCapture(event.pointerId);
|
|
19
33
|
setIsMoving(true);
|
|
20
34
|
onStart === null || onStart === void 0 ? void 0 : onStart();
|
|
21
|
-
}, [onStart]);
|
|
35
|
+
}, [onStart, setIsMoving]);
|
|
22
36
|
var handleEnd = react.useCallback(function (byCancellation) {
|
|
23
37
|
if (!isMoving) {
|
|
24
38
|
return undefined;
|
|
@@ -30,7 +44,7 @@ var useDrag = function (options) {
|
|
|
30
44
|
onEnd === null || onEnd === void 0 ? void 0 : onEnd(byCancellation ? 0 : offsetPosition.x, byCancellation ? 0 : offsetPosition.y);
|
|
31
45
|
setOffsetPosition({ x: 0, y: 0 });
|
|
32
46
|
};
|
|
33
|
-
}, []);
|
|
47
|
+
}, [isMoving, offsetPosition.x, offsetPosition.y, onEnd, setIsMoving, setOffsetPosition]);
|
|
34
48
|
var onPointerUp = react.useMemo(function () { return handleEnd(false); }, [handleEnd]);
|
|
35
49
|
var onPointerCancel = react.useMemo(function () { return handleEnd(true); }, [handleEnd]);
|
|
36
50
|
var onPointerMove = react.useMemo(function () {
|
|
@@ -49,7 +63,7 @@ var useDrag = function (options) {
|
|
|
49
63
|
};
|
|
50
64
|
setOffsetPosition(newOffsetPosition);
|
|
51
65
|
};
|
|
52
|
-
}, [isMoving]);
|
|
66
|
+
}, [isMoving, setOffsetPosition]);
|
|
53
67
|
react.useEffect(function () {
|
|
54
68
|
onRelativePositionChange(offsetPosition.x, offsetPosition.y);
|
|
55
69
|
}, [offsetPosition.x, offsetPosition.y, onRelativePositionChange]);
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","sources":["../src/useDrag.ts"],"sourcesContent":["import {\n\tPointerEvent,\n\tuseCallback,\n\tuseEffect,\n\tuseMemo,\n\tuseRef,\n\tuseState,\n} from 'react'\n\
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../src/useDrag.ts"],"sourcesContent":["import {\n\tPointerEvent,\n\tuseCallback,\n\tuseEffect,\n\tuseMemo,\n\tuseRef,\n\tuseState,\n} from 'react'\n\n/**\n * Options for the useDrag hook.\n */\nexport interface UseDragOptions {\n\t/** Called when the position changes during dragging. x and y are relative to the start position. */\n\tonRelativePositionChange: (x: number, y: number) => void\n\t/** Optional. Called when the dragging interaction starts. */\n\tonStart?: () => void\n\t/** Optional. Called when the dragging interaction ends. Receives final relative x and y. */\n\tonEnd?: (x: number, y: number) => void\n}\n\n/**\n * Hook to handle drag interactions using Pointer Events.\n * \n * @param options - Configuration options for the drag interaction.\n * @returns An object containing:\n * - `isMoving`: boolean indicating if dragging is active.\n * - `elementProps`: props to spread onto the draggable element.\n * \n * @example\n * const { elementProps, isMoving } = useDrag({\n * onRelativePositionChange: (x, y) => console.log('Offset:', x, y),\n * })\n * return <div {...elementProps} style={{ touchAction: 'none' }} />\n */\nexport const useDrag = (options: UseDragOptions) => {\n\tconst { onRelativePositionChange, onStart, onEnd } = options\n\tconst [isMoving, setIsMoving] = useState(false)\n\tconst startPosition = useRef({ x: 0, y: 0, scrollX: 0, scrollY: 0 })\n\tconst [offsetPosition, setOffsetPosition] = useState({ x: 0, y: 0 })\n\n\tconst onPointerDown = useCallback(\n\t\t(event: PointerEvent<HTMLElement>) => {\n\t\t\tevent.preventDefault()\n\t\t\tstartPosition.current = {\n\t\t\t\tx: event.clientX,\n\t\t\t\ty: event.clientY,\n\t\t\t\tscrollX: window.scrollX, // @TODO: handle any parent scroll\n\t\t\t\tscrollY: window.scrollY, // @TODO: handle any parent scroll\n\t\t\t}\n\t\t\tevent.currentTarget.setPointerCapture(event.pointerId)\n\t\t\tsetIsMoving(true)\n\t\t\tonStart?.()\n\t\t},\n\t\t[onStart, setIsMoving],\n\t)\n\n\tconst handleEnd = useCallback(\n\t\t(byCancellation: boolean) => {\n\t\t\tif (!isMoving) {\n\t\t\t\treturn undefined\n\t\t\t}\n\t\t\treturn (event: PointerEvent<HTMLElement>) => {\n\t\t\t\tevent.preventDefault()\n\t\t\t\tsetIsMoving(false)\n\t\t\t\tevent.currentTarget.releasePointerCapture(event.pointerId)\n\t\t\t\tonEnd?.(\n\t\t\t\t\tbyCancellation ? 0 : offsetPosition.x,\n\t\t\t\t\tbyCancellation ? 0 : offsetPosition.y,\n\t\t\t\t)\n\t\t\t\tsetOffsetPosition({ x: 0, y: 0 })\n\t\t\t}\n\t\t},\n\t\t[isMoving, offsetPosition.x, offsetPosition.y, onEnd, setIsMoving, setOffsetPosition],\n\t)\n\n\tconst onPointerUp = useMemo(() => handleEnd(false), [handleEnd])\n\tconst onPointerCancel = useMemo(() => handleEnd(true), [handleEnd])\n\n\tconst onPointerMove = useMemo(() => {\n\t\tif (!isMoving) {\n\t\t\treturn undefined\n\t\t}\n\t\treturn (event: PointerEvent<HTMLElement>) => {\n\t\t\tevent.preventDefault()\n\t\t\tconst newOffsetPosition = {\n\t\t\t\tx:\n\t\t\t\t\tevent.clientX +\n\t\t\t\t\twindow.scrollX -\n\t\t\t\t\t(startPosition.current.x + startPosition.current.scrollX),\n\t\t\t\ty:\n\t\t\t\t\tevent.clientY +\n\t\t\t\t\twindow.scrollY -\n\t\t\t\t\t(startPosition.current.y + startPosition.current.scrollY),\n\t\t\t}\n\t\t\tsetOffsetPosition(newOffsetPosition)\n\t\t}\n\t}, [isMoving, setOffsetPosition])\n\n\tuseEffect(() => {\n\t\tonRelativePositionChange(offsetPosition.x, offsetPosition.y)\n\t}, [offsetPosition.x, offsetPosition.y, onRelativePositionChange])\n\n\tconst elementProps = useMemo(\n\t\t() => ({\n\t\t\tonPointerDown,\n\t\t\tonPointerUp,\n\t\t\tonPointerMove,\n\t\t\tonPointerCancel,\n\t\t}),\n\t\t[onPointerDown, onPointerMove, onPointerUp, onPointerCancel],\n\t)\n\n\treturn useMemo(() => ({ isMoving, elementProps }), [isMoving, elementProps])\n}\n"],"names":["useState","useRef","useCallback","useMemo","useEffect"],"mappings":"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"}
|
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
import { useState, useRef, useCallback, useMemo, useEffect } from 'react';
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* Hook to handle drag interactions using Pointer Events.
|
|
5
|
+
*
|
|
6
|
+
* @param options - Configuration options for the drag interaction.
|
|
7
|
+
* @returns An object containing:
|
|
8
|
+
* - `isMoving`: boolean indicating if dragging is active.
|
|
9
|
+
* - `elementProps`: props to spread onto the draggable element.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* const { elementProps, isMoving } = useDrag({
|
|
13
|
+
* onRelativePositionChange: (x, y) => console.log('Offset:', x, y),
|
|
14
|
+
* })
|
|
15
|
+
* return <div {...elementProps} style={{ touchAction: 'none' }} />
|
|
16
|
+
*/
|
|
3
17
|
var useDrag = function (options) {
|
|
4
18
|
var onRelativePositionChange = options.onRelativePositionChange, onStart = options.onStart, onEnd = options.onEnd;
|
|
5
19
|
var _a = useState(false), isMoving = _a[0], setIsMoving = _a[1];
|
|
@@ -16,7 +30,7 @@ var useDrag = function (options) {
|
|
|
16
30
|
event.currentTarget.setPointerCapture(event.pointerId);
|
|
17
31
|
setIsMoving(true);
|
|
18
32
|
onStart === null || onStart === void 0 ? void 0 : onStart();
|
|
19
|
-
}, [onStart]);
|
|
33
|
+
}, [onStart, setIsMoving]);
|
|
20
34
|
var handleEnd = useCallback(function (byCancellation) {
|
|
21
35
|
if (!isMoving) {
|
|
22
36
|
return undefined;
|
|
@@ -28,7 +42,7 @@ var useDrag = function (options) {
|
|
|
28
42
|
onEnd === null || onEnd === void 0 ? void 0 : onEnd(byCancellation ? 0 : offsetPosition.x, byCancellation ? 0 : offsetPosition.y);
|
|
29
43
|
setOffsetPosition({ x: 0, y: 0 });
|
|
30
44
|
};
|
|
31
|
-
}, []);
|
|
45
|
+
}, [isMoving, offsetPosition.x, offsetPosition.y, onEnd, setIsMoving, setOffsetPosition]);
|
|
32
46
|
var onPointerUp = useMemo(function () { return handleEnd(false); }, [handleEnd]);
|
|
33
47
|
var onPointerCancel = useMemo(function () { return handleEnd(true); }, [handleEnd]);
|
|
34
48
|
var onPointerMove = useMemo(function () {
|
|
@@ -47,7 +61,7 @@ var useDrag = function (options) {
|
|
|
47
61
|
};
|
|
48
62
|
setOffsetPosition(newOffsetPosition);
|
|
49
63
|
};
|
|
50
|
-
}, [isMoving]);
|
|
64
|
+
}, [isMoving, setOffsetPosition]);
|
|
51
65
|
useEffect(function () {
|
|
52
66
|
onRelativePositionChange(offsetPosition.x, offsetPosition.y);
|
|
53
67
|
}, [offsetPosition.x, offsetPosition.y, onRelativePositionChange]);
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","sources":["../src/useDrag.ts"],"sourcesContent":["import {\n\tPointerEvent,\n\tuseCallback,\n\tuseEffect,\n\tuseMemo,\n\tuseRef,\n\tuseState,\n} from 'react'\n\
|
|
1
|
+
{"version":3,"file":"index.mjs","sources":["../src/useDrag.ts"],"sourcesContent":["import {\n\tPointerEvent,\n\tuseCallback,\n\tuseEffect,\n\tuseMemo,\n\tuseRef,\n\tuseState,\n} from 'react'\n\n/**\n * Options for the useDrag hook.\n */\nexport interface UseDragOptions {\n\t/** Called when the position changes during dragging. x and y are relative to the start position. */\n\tonRelativePositionChange: (x: number, y: number) => void\n\t/** Optional. Called when the dragging interaction starts. */\n\tonStart?: () => void\n\t/** Optional. Called when the dragging interaction ends. Receives final relative x and y. */\n\tonEnd?: (x: number, y: number) => void\n}\n\n/**\n * Hook to handle drag interactions using Pointer Events.\n * \n * @param options - Configuration options for the drag interaction.\n * @returns An object containing:\n * - `isMoving`: boolean indicating if dragging is active.\n * - `elementProps`: props to spread onto the draggable element.\n * \n * @example\n * const { elementProps, isMoving } = useDrag({\n * onRelativePositionChange: (x, y) => console.log('Offset:', x, y),\n * })\n * return <div {...elementProps} style={{ touchAction: 'none' }} />\n */\nexport const useDrag = (options: UseDragOptions) => {\n\tconst { onRelativePositionChange, onStart, onEnd } = options\n\tconst [isMoving, setIsMoving] = useState(false)\n\tconst startPosition = useRef({ x: 0, y: 0, scrollX: 0, scrollY: 0 })\n\tconst [offsetPosition, setOffsetPosition] = useState({ x: 0, y: 0 })\n\n\tconst onPointerDown = useCallback(\n\t\t(event: PointerEvent<HTMLElement>) => {\n\t\t\tevent.preventDefault()\n\t\t\tstartPosition.current = {\n\t\t\t\tx: event.clientX,\n\t\t\t\ty: event.clientY,\n\t\t\t\tscrollX: window.scrollX, // @TODO: handle any parent scroll\n\t\t\t\tscrollY: window.scrollY, // @TODO: handle any parent scroll\n\t\t\t}\n\t\t\tevent.currentTarget.setPointerCapture(event.pointerId)\n\t\t\tsetIsMoving(true)\n\t\t\tonStart?.()\n\t\t},\n\t\t[onStart, setIsMoving],\n\t)\n\n\tconst handleEnd = useCallback(\n\t\t(byCancellation: boolean) => {\n\t\t\tif (!isMoving) {\n\t\t\t\treturn undefined\n\t\t\t}\n\t\t\treturn (event: PointerEvent<HTMLElement>) => {\n\t\t\t\tevent.preventDefault()\n\t\t\t\tsetIsMoving(false)\n\t\t\t\tevent.currentTarget.releasePointerCapture(event.pointerId)\n\t\t\t\tonEnd?.(\n\t\t\t\t\tbyCancellation ? 0 : offsetPosition.x,\n\t\t\t\t\tbyCancellation ? 0 : offsetPosition.y,\n\t\t\t\t)\n\t\t\t\tsetOffsetPosition({ x: 0, y: 0 })\n\t\t\t}\n\t\t},\n\t\t[isMoving, offsetPosition.x, offsetPosition.y, onEnd, setIsMoving, setOffsetPosition],\n\t)\n\n\tconst onPointerUp = useMemo(() => handleEnd(false), [handleEnd])\n\tconst onPointerCancel = useMemo(() => handleEnd(true), [handleEnd])\n\n\tconst onPointerMove = useMemo(() => {\n\t\tif (!isMoving) {\n\t\t\treturn undefined\n\t\t}\n\t\treturn (event: PointerEvent<HTMLElement>) => {\n\t\t\tevent.preventDefault()\n\t\t\tconst newOffsetPosition = {\n\t\t\t\tx:\n\t\t\t\t\tevent.clientX +\n\t\t\t\t\twindow.scrollX -\n\t\t\t\t\t(startPosition.current.x + startPosition.current.scrollX),\n\t\t\t\ty:\n\t\t\t\t\tevent.clientY +\n\t\t\t\t\twindow.scrollY -\n\t\t\t\t\t(startPosition.current.y + startPosition.current.scrollY),\n\t\t\t}\n\t\t\tsetOffsetPosition(newOffsetPosition)\n\t\t}\n\t}, [isMoving, setOffsetPosition])\n\n\tuseEffect(() => {\n\t\tonRelativePositionChange(offsetPosition.x, offsetPosition.y)\n\t}, [offsetPosition.x, offsetPosition.y, onRelativePositionChange])\n\n\tconst elementProps = useMemo(\n\t\t() => ({\n\t\t\tonPointerDown,\n\t\t\tonPointerUp,\n\t\t\tonPointerMove,\n\t\t\tonPointerCancel,\n\t\t}),\n\t\t[onPointerDown, onPointerMove, onPointerUp, onPointerCancel],\n\t)\n\n\treturn useMemo(() => ({ isMoving, elementProps }), [isMoving, elementProps])\n}\n"],"names":[],"mappings":"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"}
|
package/dist/useDrag.d.ts
CHANGED
|
@@ -1,9 +1,30 @@
|
|
|
1
1
|
import { PointerEvent } from 'react';
|
|
2
|
-
|
|
2
|
+
/**
|
|
3
|
+
* Options for the useDrag hook.
|
|
4
|
+
*/
|
|
5
|
+
export interface UseDragOptions {
|
|
6
|
+
/** Called when the position changes during dragging. x and y are relative to the start position. */
|
|
3
7
|
onRelativePositionChange: (x: number, y: number) => void;
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
8
|
+
/** Optional. Called when the dragging interaction starts. */
|
|
9
|
+
onStart?: () => void;
|
|
10
|
+
/** Optional. Called when the dragging interaction ends. Receives final relative x and y. */
|
|
11
|
+
onEnd?: (x: number, y: number) => void;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Hook to handle drag interactions using Pointer Events.
|
|
15
|
+
*
|
|
16
|
+
* @param options - Configuration options for the drag interaction.
|
|
17
|
+
* @returns An object containing:
|
|
18
|
+
* - `isMoving`: boolean indicating if dragging is active.
|
|
19
|
+
* - `elementProps`: props to spread onto the draggable element.
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* const { elementProps, isMoving } = useDrag({
|
|
23
|
+
* onRelativePositionChange: (x, y) => console.log('Offset:', x, y),
|
|
24
|
+
* })
|
|
25
|
+
* return <div {...elementProps} style={{ touchAction: 'none' }} />
|
|
26
|
+
*/
|
|
27
|
+
export declare const useDrag: (options: UseDragOptions) => {
|
|
7
28
|
isMoving: boolean;
|
|
8
29
|
elementProps: {
|
|
9
30
|
onPointerDown: (event: PointerEvent<HTMLElement>) => void;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-use-drag",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.5",
|
|
4
4
|
"description": "Drag interactions made easier.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -9,11 +9,13 @@
|
|
|
9
9
|
"scripts": {
|
|
10
10
|
"start": "rollup -c -w",
|
|
11
11
|
"build": "rollup -c",
|
|
12
|
-
"prepare": "npm run build"
|
|
12
|
+
"prepare": "npm run build",
|
|
13
|
+
"lint": "eslint .",
|
|
14
|
+
"type-check": "tsc --noEmit"
|
|
13
15
|
},
|
|
14
16
|
"repository": {
|
|
15
17
|
"type": "git",
|
|
16
|
-
"url": "https://github.com/FilipChalupa/react-use-drag.git"
|
|
18
|
+
"url": "git+https://github.com/FilipChalupa/react-use-drag.git"
|
|
17
19
|
},
|
|
18
20
|
"keywords": [
|
|
19
21
|
"typescript",
|
|
@@ -28,9 +30,14 @@
|
|
|
28
30
|
},
|
|
29
31
|
"license": "ISC",
|
|
30
32
|
"devDependencies": {
|
|
33
|
+
"@eslint/js": "^9.39.3",
|
|
31
34
|
"@rollup/plugin-commonjs": "^25.0.7",
|
|
32
35
|
"@rollup/plugin-node-resolve": "^15.2.3",
|
|
33
36
|
"@types/react": "^18.0.10",
|
|
37
|
+
"eslint": "^9.39.3",
|
|
38
|
+
"eslint-config-prettier": "^9.1.2",
|
|
39
|
+
"eslint-plugin-react": "^7.37.5",
|
|
40
|
+
"eslint-plugin-react-hooks": "^5.2.0",
|
|
34
41
|
"prettier": "^3.0.3",
|
|
35
42
|
"react": "^18.1.0",
|
|
36
43
|
"rollup": "^4.2.0",
|
|
@@ -38,6 +45,7 @@
|
|
|
38
45
|
"rollup-plugin-peer-deps-external": "^2.2.4",
|
|
39
46
|
"rollup-plugin-typescript2": "^0.36.0",
|
|
40
47
|
"typescript": "^5.2.2",
|
|
48
|
+
"typescript-eslint": "^8.56.0",
|
|
41
49
|
"typescript-plugin-css-modules": "^5.0.2"
|
|
42
50
|
},
|
|
43
51
|
"peerDependencies": {
|