@os-design/use-drag 1.0.0

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/LICENCE.md ADDED
@@ -0,0 +1 @@
1
+ Copyright (c) 2019-present, Ilya Ordin, all rights reserved
package/README.md ADDED
@@ -0,0 +1,15 @@
1
+ # @os-design/use-drag [![NPM version](https://img.shields.io/npm/v/@os-design/use-drag)](https://yarnpkg.com/package/@os-design/use-drag) [![BundlePhobia](https://img.shields.io/bundlephobia/minzip/@os-design/use-drag)](https://bundlephobia.com/result?p=@os-design/use-drag)
2
+
3
+ Handles the drag gesture. On touch devices, the event is triggered by a long press. On the mouse devices, the event is triggered when you click on the element and start dragging it.
4
+
5
+ ## Installation
6
+
7
+ Install the package using the following command:
8
+
9
+ ```
10
+ yarn add @os-design/use-drag
11
+ ```
12
+
13
+ ---
14
+
15
+ See all the features in the [Storybook](https://os-team.gitlab.io/libs/os-design/).
@@ -0,0 +1,138 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports["default"] = void 0;
7
+
8
+ var _react = require("react");
9
+
10
+ var _useLongPress2 = _interopRequireDefault(require("@os-design/use-long-press"));
11
+
12
+ var _useEvent = _interopRequireDefault(require("@os-design/use-event"));
13
+
14
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
15
+
16
+ var userSelection = {
17
+ disable: function disable() {
18
+ document.body.style.userSelect = 'none';
19
+ },
20
+ enable: function enable() {
21
+ document.body.style.userSelect = '';
22
+ }
23
+ };
24
+
25
+ var useDrag = function useDrag(props) {
26
+ var _props$minMouseDistPx = props.minMouseDistPx,
27
+ minMouseDistPx = _props$minMouseDistPx === void 0 ? 10 : _props$minMouseDistPx,
28
+ _props$longPressMs = props.longPressMs,
29
+ longPressMs = _props$longPressMs === void 0 ? 500 : _props$longPressMs;
30
+ var isDraggingRef = (0, _react.useRef)(false);
31
+ var startMousePosRef = (0, _react.useRef)(null);
32
+ var minMouseDistPxRef = (0, _react.useRef)(minMouseDistPx);
33
+ var handlersRef = (0, _react.useRef)({
34
+ onDragStart: props.onDragStart || function () {},
35
+ onDragMove: props.onDragMove || function () {},
36
+ onDragEnd: props.onDragEnd || function () {}
37
+ });
38
+ (0, _react.useEffect)(function () {
39
+ minMouseDistPxRef.current = minMouseDistPx;
40
+ }, [minMouseDistPx]);
41
+ (0, _react.useEffect)(function () {
42
+ handlersRef.current = {
43
+ onDragStart: props.onDragStart || function () {},
44
+ onDragMove: props.onDragMove || function () {},
45
+ onDragEnd: props.onDragEnd || function () {}
46
+ };
47
+ }, [props.onDragEnd, props.onDragMove, props.onDragStart]);
48
+ var dragStartHandler = (0, _react.useCallback)(function (position, startPosition) {
49
+ var onDragStart = handlersRef.current.onDragStart;
50
+ onDragStart(position, startPosition);
51
+ isDraggingRef.current = true;
52
+ startMousePosRef.current = null;
53
+ }, []);
54
+ var dragEndHandler = (0, _react.useCallback)(function () {
55
+ var onDragEnd = handlersRef.current.onDragEnd;
56
+ if (isDraggingRef.current) onDragEnd();
57
+ isDraggingRef.current = false;
58
+ startMousePosRef.current = null;
59
+ userSelection.enable();
60
+ }, []);
61
+ var onMouseDown = (0, _react.useCallback)(function (e) {
62
+ if (e.button !== 0) return; // Allow only the left mouse button
63
+
64
+ startMousePosRef.current = {
65
+ x: e.clientX,
66
+ y: e.clientY
67
+ };
68
+ userSelection.disable();
69
+ }, []);
70
+ var onMouseMove = (0, _react.useCallback)(function (e) {
71
+ var pos = {
72
+ x: e.clientX,
73
+ y: e.clientY
74
+ };
75
+
76
+ if (isDraggingRef.current) {
77
+ var onDragMove = handlersRef.current.onDragMove;
78
+ onDragMove(pos);
79
+ return;
80
+ }
81
+
82
+ var startPos = startMousePosRef.current;
83
+ if (!startPos) return;
84
+ var diffX = Math.abs(pos.x - startPos.x);
85
+ var diffY = Math.abs(pos.y - startPos.y);
86
+ var diff = Math.sqrt(Math.pow(diffX, 2) + Math.pow(diffY, 2));
87
+
88
+ if (diff >= minMouseDistPxRef.current) {
89
+ dragStartHandler(pos, startPos);
90
+ }
91
+ }, [dragStartHandler]);
92
+ var onMouseUp = (0, _react.useCallback)(function () {
93
+ dragEndHandler();
94
+ }, [dragEndHandler]);
95
+ var longPressHandler = (0, _react.useCallback)(function (e) {
96
+ if (e.touches.length === 0) return;
97
+ var pos = {
98
+ x: e.touches[0].clientX,
99
+ y: e.touches[0].clientY
100
+ };
101
+ dragStartHandler(pos, pos);
102
+ }, [dragStartHandler]);
103
+
104
+ var _useLongPress = (0, _useLongPress2["default"])(longPressHandler, longPressMs),
105
+ onTouchStart = _useLongPress.onTouchStart,
106
+ onTouchMove = _useLongPress.onTouchMove,
107
+ onTouchEnd = _useLongPress.onTouchEnd;
108
+
109
+ var touchStartHandler = (0, _react.useCallback)(function (e) {
110
+ onTouchStart(e);
111
+ userSelection.disable();
112
+ }, [onTouchStart]);
113
+ var touchMoveHandler = (0, _react.useCallback)(function (e) {
114
+ onTouchMove();
115
+ if (!isDraggingRef.current || e.touches.length === 0) return;
116
+ var onDragMove = handlersRef.current.onDragMove;
117
+ onDragMove({
118
+ x: e.touches[0].clientX,
119
+ y: e.touches[0].clientY
120
+ });
121
+ }, [onTouchMove]);
122
+ var touchEndHandler = (0, _react.useCallback)(function () {
123
+ onTouchEnd();
124
+ dragEndHandler();
125
+ }, [dragEndHandler, onTouchEnd]);
126
+ (0, _useEvent["default"])(document, 'mousemove', onMouseMove);
127
+ (0, _useEvent["default"])(document, 'mouseup', onMouseUp);
128
+ (0, _useEvent["default"])(document, 'touchmove', touchMoveHandler);
129
+ (0, _useEvent["default"])(document, 'touchend', touchEndHandler);
130
+ return {
131
+ onMouseDown: onMouseDown,
132
+ onTouchStart: touchStartHandler
133
+ };
134
+ };
135
+
136
+ var _default = useDrag;
137
+ exports["default"] = _default;
138
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/index.ts"],"names":["userSelection","disable","document","body","style","userSelect","enable","useDrag","props","minMouseDistPx","longPressMs","isDraggingRef","startMousePosRef","minMouseDistPxRef","handlersRef","onDragStart","onDragMove","onDragEnd","current","dragStartHandler","position","startPosition","dragEndHandler","onMouseDown","e","button","x","clientX","y","clientY","onMouseMove","pos","startPos","diffX","Math","abs","diffY","diff","sqrt","onMouseUp","longPressHandler","touches","length","onTouchStart","onTouchMove","onTouchEnd","touchStartHandler","touchMoveHandler","touchEndHandler"],"mappings":"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","sourcesContent":["import {\n MouseEventHandler,\n TouchEventHandler,\n useCallback,\n useEffect,\n useRef,\n} from 'react';\nimport useLongPress from '@os-design/use-long-press';\nimport useEvent from '@os-design/use-event';\n\nexport interface Position {\n x: number;\n y: number;\n}\n\nexport type OnDragStart = (position: Position, startPosition: Position) => void;\nexport type OnDragMove = (position: Position) => void;\nexport type OnDragEnd = () => void;\n\nexport interface UseDragProps {\n minMouseDistPx?: number;\n longPressMs?: number;\n onDragStart?: OnDragStart;\n onDragMove?: OnDragMove;\n onDragEnd?: OnDragEnd;\n}\n\nconst userSelection = {\n disable: () => {\n document.body.style.userSelect = 'none';\n },\n enable: () => {\n document.body.style.userSelect = '';\n },\n};\n\nexport interface DragHandlers {\n onMouseDown: MouseEventHandler;\n onTouchStart: TouchEventHandler;\n}\n\nconst useDrag = (props: UseDragProps): DragHandlers => {\n const { minMouseDistPx = 10, longPressMs = 500 } = props;\n\n const isDraggingRef = useRef(false);\n const startMousePosRef = useRef<Position | null>(null);\n const minMouseDistPxRef = useRef(minMouseDistPx);\n const handlersRef = useRef({\n onDragStart: props.onDragStart || (() => {}),\n onDragMove: props.onDragMove || (() => {}),\n onDragEnd: props.onDragEnd || (() => {}),\n });\n\n useEffect(() => {\n minMouseDistPxRef.current = minMouseDistPx;\n }, [minMouseDistPx]);\n\n useEffect(() => {\n handlersRef.current = {\n onDragStart: props.onDragStart || (() => {}),\n onDragMove: props.onDragMove || (() => {}),\n onDragEnd: props.onDragEnd || (() => {}),\n };\n }, [props.onDragEnd, props.onDragMove, props.onDragStart]);\n\n const dragStartHandler = useCallback(\n (position: Position, startPosition: Position) => {\n const { onDragStart } = handlersRef.current;\n onDragStart(position, startPosition);\n isDraggingRef.current = true;\n startMousePosRef.current = null;\n },\n []\n );\n\n const dragEndHandler = useCallback(() => {\n const { onDragEnd } = handlersRef.current;\n if (isDraggingRef.current) onDragEnd();\n isDraggingRef.current = false;\n startMousePosRef.current = null;\n userSelection.enable();\n }, []);\n\n const onMouseDown = useCallback<MouseEventHandler>((e) => {\n if (e.button !== 0) return; // Allow only the left mouse button\n startMousePosRef.current = { x: e.clientX, y: e.clientY };\n userSelection.disable();\n }, []);\n\n const onMouseMove = useCallback(\n (e: MouseEvent) => {\n const pos = { x: e.clientX, y: e.clientY };\n if (isDraggingRef.current) {\n const { onDragMove } = handlersRef.current;\n onDragMove(pos);\n return;\n }\n const startPos = startMousePosRef.current;\n if (!startPos) return;\n const diffX = Math.abs(pos.x - startPos.x);\n const diffY = Math.abs(pos.y - startPos.y);\n const diff = Math.sqrt(diffX ** 2 + diffY ** 2);\n if (diff >= minMouseDistPxRef.current) {\n dragStartHandler(pos, startPos);\n }\n },\n [dragStartHandler]\n );\n\n const onMouseUp = useCallback(() => {\n dragEndHandler();\n }, [dragEndHandler]);\n\n const longPressHandler = useCallback<TouchEventHandler>(\n (e) => {\n if (e.touches.length === 0) return;\n const pos = { x: e.touches[0].clientX, y: e.touches[0].clientY };\n dragStartHandler(pos, pos);\n },\n [dragStartHandler]\n );\n\n const { onTouchStart, onTouchMove, onTouchEnd } = useLongPress(\n longPressHandler,\n longPressMs\n );\n\n const touchStartHandler = useCallback<TouchEventHandler>(\n (e) => {\n onTouchStart(e);\n userSelection.disable();\n },\n [onTouchStart]\n );\n\n const touchMoveHandler = useCallback(\n (e: TouchEvent) => {\n onTouchMove();\n if (!isDraggingRef.current || e.touches.length === 0) return;\n const { onDragMove } = handlersRef.current;\n onDragMove({ x: e.touches[0].clientX, y: e.touches[0].clientY });\n },\n [onTouchMove]\n );\n\n const touchEndHandler = useCallback(() => {\n onTouchEnd();\n dragEndHandler();\n }, [dragEndHandler, onTouchEnd]);\n\n useEvent(document, 'mousemove', onMouseMove);\n useEvent(document, 'mouseup', onMouseUp);\n useEvent(document, 'touchmove', touchMoveHandler);\n useEvent(document, 'touchend', touchEndHandler);\n\n return {\n onMouseDown,\n onTouchStart: touchStartHandler,\n };\n};\n\nexport default useDrag;\n"],"file":"index.js"}
@@ -0,0 +1,132 @@
1
+ import { useCallback, useEffect, useRef } from 'react';
2
+ import useLongPress from '@os-design/use-long-press';
3
+ import useEvent from '@os-design/use-event';
4
+ const userSelection = {
5
+ disable: () => {
6
+ document.body.style.userSelect = 'none';
7
+ },
8
+ enable: () => {
9
+ document.body.style.userSelect = '';
10
+ }
11
+ };
12
+
13
+ const useDrag = props => {
14
+ const {
15
+ minMouseDistPx = 10,
16
+ longPressMs = 500
17
+ } = props;
18
+ const isDraggingRef = useRef(false);
19
+ const startMousePosRef = useRef(null);
20
+ const minMouseDistPxRef = useRef(minMouseDistPx);
21
+ const handlersRef = useRef({
22
+ onDragStart: props.onDragStart || (() => {}),
23
+ onDragMove: props.onDragMove || (() => {}),
24
+ onDragEnd: props.onDragEnd || (() => {})
25
+ });
26
+ useEffect(() => {
27
+ minMouseDistPxRef.current = minMouseDistPx;
28
+ }, [minMouseDistPx]);
29
+ useEffect(() => {
30
+ handlersRef.current = {
31
+ onDragStart: props.onDragStart || (() => {}),
32
+ onDragMove: props.onDragMove || (() => {}),
33
+ onDragEnd: props.onDragEnd || (() => {})
34
+ };
35
+ }, [props.onDragEnd, props.onDragMove, props.onDragStart]);
36
+ const dragStartHandler = useCallback((position, startPosition) => {
37
+ const {
38
+ onDragStart
39
+ } = handlersRef.current;
40
+ onDragStart(position, startPosition);
41
+ isDraggingRef.current = true;
42
+ startMousePosRef.current = null;
43
+ }, []);
44
+ const dragEndHandler = useCallback(() => {
45
+ const {
46
+ onDragEnd
47
+ } = handlersRef.current;
48
+ if (isDraggingRef.current) onDragEnd();
49
+ isDraggingRef.current = false;
50
+ startMousePosRef.current = null;
51
+ userSelection.enable();
52
+ }, []);
53
+ const onMouseDown = useCallback(e => {
54
+ if (e.button !== 0) return; // Allow only the left mouse button
55
+
56
+ startMousePosRef.current = {
57
+ x: e.clientX,
58
+ y: e.clientY
59
+ };
60
+ userSelection.disable();
61
+ }, []);
62
+ const onMouseMove = useCallback(e => {
63
+ const pos = {
64
+ x: e.clientX,
65
+ y: e.clientY
66
+ };
67
+
68
+ if (isDraggingRef.current) {
69
+ const {
70
+ onDragMove
71
+ } = handlersRef.current;
72
+ onDragMove(pos);
73
+ return;
74
+ }
75
+
76
+ const startPos = startMousePosRef.current;
77
+ if (!startPos) return;
78
+ const diffX = Math.abs(pos.x - startPos.x);
79
+ const diffY = Math.abs(pos.y - startPos.y);
80
+ const diff = Math.sqrt(diffX ** 2 + diffY ** 2);
81
+
82
+ if (diff >= minMouseDistPxRef.current) {
83
+ dragStartHandler(pos, startPos);
84
+ }
85
+ }, [dragStartHandler]);
86
+ const onMouseUp = useCallback(() => {
87
+ dragEndHandler();
88
+ }, [dragEndHandler]);
89
+ const longPressHandler = useCallback(e => {
90
+ if (e.touches.length === 0) return;
91
+ const pos = {
92
+ x: e.touches[0].clientX,
93
+ y: e.touches[0].clientY
94
+ };
95
+ dragStartHandler(pos, pos);
96
+ }, [dragStartHandler]);
97
+ const {
98
+ onTouchStart,
99
+ onTouchMove,
100
+ onTouchEnd
101
+ } = useLongPress(longPressHandler, longPressMs);
102
+ const touchStartHandler = useCallback(e => {
103
+ onTouchStart(e);
104
+ userSelection.disable();
105
+ }, [onTouchStart]);
106
+ const touchMoveHandler = useCallback(e => {
107
+ onTouchMove();
108
+ if (!isDraggingRef.current || e.touches.length === 0) return;
109
+ const {
110
+ onDragMove
111
+ } = handlersRef.current;
112
+ onDragMove({
113
+ x: e.touches[0].clientX,
114
+ y: e.touches[0].clientY
115
+ });
116
+ }, [onTouchMove]);
117
+ const touchEndHandler = useCallback(() => {
118
+ onTouchEnd();
119
+ dragEndHandler();
120
+ }, [dragEndHandler, onTouchEnd]);
121
+ useEvent(document, 'mousemove', onMouseMove);
122
+ useEvent(document, 'mouseup', onMouseUp);
123
+ useEvent(document, 'touchmove', touchMoveHandler);
124
+ useEvent(document, 'touchend', touchEndHandler);
125
+ return {
126
+ onMouseDown,
127
+ onTouchStart: touchStartHandler
128
+ };
129
+ };
130
+
131
+ export default useDrag;
132
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/index.ts"],"names":["useCallback","useEffect","useRef","useLongPress","useEvent","userSelection","disable","document","body","style","userSelect","enable","useDrag","props","minMouseDistPx","longPressMs","isDraggingRef","startMousePosRef","minMouseDistPxRef","handlersRef","onDragStart","onDragMove","onDragEnd","current","dragStartHandler","position","startPosition","dragEndHandler","onMouseDown","e","button","x","clientX","y","clientY","onMouseMove","pos","startPos","diffX","Math","abs","diffY","diff","sqrt","onMouseUp","longPressHandler","touches","length","onTouchStart","onTouchMove","onTouchEnd","touchStartHandler","touchMoveHandler","touchEndHandler"],"mappings":"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","sourcesContent":["import {\n MouseEventHandler,\n TouchEventHandler,\n useCallback,\n useEffect,\n useRef,\n} from 'react';\nimport useLongPress from '@os-design/use-long-press';\nimport useEvent from '@os-design/use-event';\n\nexport interface Position {\n x: number;\n y: number;\n}\n\nexport type OnDragStart = (position: Position, startPosition: Position) => void;\nexport type OnDragMove = (position: Position) => void;\nexport type OnDragEnd = () => void;\n\nexport interface UseDragProps {\n minMouseDistPx?: number;\n longPressMs?: number;\n onDragStart?: OnDragStart;\n onDragMove?: OnDragMove;\n onDragEnd?: OnDragEnd;\n}\n\nconst userSelection = {\n disable: () => {\n document.body.style.userSelect = 'none';\n },\n enable: () => {\n document.body.style.userSelect = '';\n },\n};\n\nexport interface DragHandlers {\n onMouseDown: MouseEventHandler;\n onTouchStart: TouchEventHandler;\n}\n\nconst useDrag = (props: UseDragProps): DragHandlers => {\n const { minMouseDistPx = 10, longPressMs = 500 } = props;\n\n const isDraggingRef = useRef(false);\n const startMousePosRef = useRef<Position | null>(null);\n const minMouseDistPxRef = useRef(minMouseDistPx);\n const handlersRef = useRef({\n onDragStart: props.onDragStart || (() => {}),\n onDragMove: props.onDragMove || (() => {}),\n onDragEnd: props.onDragEnd || (() => {}),\n });\n\n useEffect(() => {\n minMouseDistPxRef.current = minMouseDistPx;\n }, [minMouseDistPx]);\n\n useEffect(() => {\n handlersRef.current = {\n onDragStart: props.onDragStart || (() => {}),\n onDragMove: props.onDragMove || (() => {}),\n onDragEnd: props.onDragEnd || (() => {}),\n };\n }, [props.onDragEnd, props.onDragMove, props.onDragStart]);\n\n const dragStartHandler = useCallback(\n (position: Position, startPosition: Position) => {\n const { onDragStart } = handlersRef.current;\n onDragStart(position, startPosition);\n isDraggingRef.current = true;\n startMousePosRef.current = null;\n },\n []\n );\n\n const dragEndHandler = useCallback(() => {\n const { onDragEnd } = handlersRef.current;\n if (isDraggingRef.current) onDragEnd();\n isDraggingRef.current = false;\n startMousePosRef.current = null;\n userSelection.enable();\n }, []);\n\n const onMouseDown = useCallback<MouseEventHandler>((e) => {\n if (e.button !== 0) return; // Allow only the left mouse button\n startMousePosRef.current = { x: e.clientX, y: e.clientY };\n userSelection.disable();\n }, []);\n\n const onMouseMove = useCallback(\n (e: MouseEvent) => {\n const pos = { x: e.clientX, y: e.clientY };\n if (isDraggingRef.current) {\n const { onDragMove } = handlersRef.current;\n onDragMove(pos);\n return;\n }\n const startPos = startMousePosRef.current;\n if (!startPos) return;\n const diffX = Math.abs(pos.x - startPos.x);\n const diffY = Math.abs(pos.y - startPos.y);\n const diff = Math.sqrt(diffX ** 2 + diffY ** 2);\n if (diff >= minMouseDistPxRef.current) {\n dragStartHandler(pos, startPos);\n }\n },\n [dragStartHandler]\n );\n\n const onMouseUp = useCallback(() => {\n dragEndHandler();\n }, [dragEndHandler]);\n\n const longPressHandler = useCallback<TouchEventHandler>(\n (e) => {\n if (e.touches.length === 0) return;\n const pos = { x: e.touches[0].clientX, y: e.touches[0].clientY };\n dragStartHandler(pos, pos);\n },\n [dragStartHandler]\n );\n\n const { onTouchStart, onTouchMove, onTouchEnd } = useLongPress(\n longPressHandler,\n longPressMs\n );\n\n const touchStartHandler = useCallback<TouchEventHandler>(\n (e) => {\n onTouchStart(e);\n userSelection.disable();\n },\n [onTouchStart]\n );\n\n const touchMoveHandler = useCallback(\n (e: TouchEvent) => {\n onTouchMove();\n if (!isDraggingRef.current || e.touches.length === 0) return;\n const { onDragMove } = handlersRef.current;\n onDragMove({ x: e.touches[0].clientX, y: e.touches[0].clientY });\n },\n [onTouchMove]\n );\n\n const touchEndHandler = useCallback(() => {\n onTouchEnd();\n dragEndHandler();\n }, [dragEndHandler, onTouchEnd]);\n\n useEvent(document, 'mousemove', onMouseMove);\n useEvent(document, 'mouseup', onMouseUp);\n useEvent(document, 'touchmove', touchMoveHandler);\n useEvent(document, 'touchend', touchEndHandler);\n\n return {\n onMouseDown,\n onTouchStart: touchStartHandler,\n };\n};\n\nexport default useDrag;\n"],"file":"index.js"}
@@ -0,0 +1,22 @@
1
+ import { MouseEventHandler, TouchEventHandler } from 'react';
2
+ export interface Position {
3
+ x: number;
4
+ y: number;
5
+ }
6
+ export declare type OnDragStart = (position: Position, startPosition: Position) => void;
7
+ export declare type OnDragMove = (position: Position) => void;
8
+ export declare type OnDragEnd = () => void;
9
+ export interface UseDragProps {
10
+ minMouseDistPx?: number;
11
+ longPressMs?: number;
12
+ onDragStart?: OnDragStart;
13
+ onDragMove?: OnDragMove;
14
+ onDragEnd?: OnDragEnd;
15
+ }
16
+ export interface DragHandlers {
17
+ onMouseDown: MouseEventHandler;
18
+ onTouchStart: TouchEventHandler;
19
+ }
20
+ declare const useDrag: (props: UseDragProps) => DragHandlers;
21
+ export default useDrag;
22
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,iBAAiB,EACjB,iBAAiB,EAIlB,MAAM,OAAO,CAAC;AAIf,MAAM,WAAW,QAAQ;IACvB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACX;AAED,oBAAY,WAAW,GAAG,CAAC,QAAQ,EAAE,QAAQ,EAAE,aAAa,EAAE,QAAQ,KAAK,IAAI,CAAC;AAChF,oBAAY,UAAU,GAAG,CAAC,QAAQ,EAAE,QAAQ,KAAK,IAAI,CAAC;AACtD,oBAAY,SAAS,GAAG,MAAM,IAAI,CAAC;AAEnC,MAAM,WAAW,YAAY;IAC3B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,SAAS,CAAC,EAAE,SAAS,CAAC;CACvB;AAWD,MAAM,WAAW,YAAY;IAC3B,WAAW,EAAE,iBAAiB,CAAC;IAC/B,YAAY,EAAE,iBAAiB,CAAC;CACjC;AAED,QAAA,MAAM,OAAO,UAAW,YAAY,KAAG,YAsHtC,CAAC;AAEF,eAAe,OAAO,CAAC"}
package/package.json ADDED
@@ -0,0 +1,38 @@
1
+ {
2
+ "name": "@os-design/use-drag",
3
+ "version": "1.0.0",
4
+ "license": "UNLICENSED",
5
+ "repository": "git@gitlab.com:os-team/libs/os-design.git",
6
+ "main": "dist/cjs/index.js",
7
+ "module": "dist/esm/index.js",
8
+ "types": "dist/types/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "require": "./dist/cjs/index.js",
12
+ "default": "./dist/esm/index.js"
13
+ }
14
+ },
15
+ "files": [
16
+ "dist"
17
+ ],
18
+ "sideEffects": false,
19
+ "scripts": {
20
+ "clean": "rimraf dist",
21
+ "build:esm": "cross-env BABEL_ENV=esm babel src --root-mode upward --extensions .ts,.tsx --out-dir dist/esm --source-maps",
22
+ "build:cjs": "cross-env BABEL_ENV=cjs babel src --root-mode upward --extensions .ts,.tsx --out-dir dist/cjs --source-maps",
23
+ "build:types": "tsc --emitDeclarationOnly --declaration --declarationDir dist/types",
24
+ "build": "yarn clean && npm-run-all build:*",
25
+ "ncu": "ncu -u"
26
+ },
27
+ "publishConfig": {
28
+ "access": "public"
29
+ },
30
+ "dependencies": {
31
+ "@os-design/use-event": "^1.0.5",
32
+ "@os-design/use-long-press": "^1.0.0"
33
+ },
34
+ "peerDependencies": {
35
+ "react": ">=17"
36
+ },
37
+ "gitHead": "4f41a962d4c0afb57d65e8c3e104215794d3c6a7"
38
+ }