@lincle/react-native-interactive 0.4.0-next.2 → 0.4.0-next.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/dist/base.d.ts +1 -1
  2. package/dist/base.js +1 -1
  3. package/dist/components/Edge/Path/index.d.ts +1 -0
  4. package/dist/components/Edge/Path/index.js +1 -0
  5. package/dist/components/Edge/index.d.ts +2 -1
  6. package/dist/components/Edge/index.js +2 -1
  7. package/dist/components/Edges/Connections/index.d.ts +10 -0
  8. package/dist/components/Edges/Connections/index.js +46 -0
  9. package/dist/components/Edges/index.d.ts +4 -1
  10. package/dist/components/Edges/index.js +23 -1
  11. package/dist/components/{Grid → Graph/Grid}/index.d.ts +1 -1
  12. package/dist/components/Graph/Grid/index.js +56 -0
  13. package/dist/components/Graph/index.d.ts +1 -1
  14. package/dist/components/Graph/index.js +9 -7
  15. package/dist/components/Interaction/index.d.ts +1 -1
  16. package/dist/components/Interaction/index.js +125 -8
  17. package/dist/components/Node/Draggable.d.ts +41 -0
  18. package/dist/components/Node/Draggable.js +270 -0
  19. package/dist/components/Node/MoveNode/index.js +5 -3
  20. package/dist/components/Node/PullNode/index.js +119 -2
  21. package/dist/components/Node/index.d.ts +3 -1
  22. package/dist/components/Node/index.js +130 -16
  23. package/dist/components/Nodes/index.d.ts +2 -1
  24. package/dist/components/Nodes/index.js +3 -1
  25. package/dist/components/index.d.ts +6 -8
  26. package/dist/components/index.js +6 -8
  27. package/dist/shared.d.ts +15 -17
  28. package/dist/shared.js +2 -1
  29. package/package.json +20 -25
  30. package/dist/components/GraphContexts/index.d.ts +0 -4
  31. package/dist/components/GraphContexts/index.js +0 -162
  32. package/dist/components/Grid/index.js +0 -11
  33. package/dist/components/Path/index.d.ts +0 -1
  34. package/dist/components/Path/index.js +0 -1
  35. package/dist/components/Pull/index.d.ts +0 -4
  36. package/dist/components/Pull/index.js +0 -5
package/dist/base.d.ts CHANGED
@@ -1 +1 @@
1
- export { Edge, Edges, Graph, GraphContexts, Grid, Node, Nodes, Path } from '@lincle/react-native-base';
1
+ export { Edge, Edges, Graph, Grid, Node, Nodes, Path } from '@lincle/react-native-base';
package/dist/base.js CHANGED
@@ -1 +1 @@
1
- export { Edge, Edges, Graph, GraphContexts, Grid, Node, Nodes, Path } from '@lincle/react-native-base';
1
+ export { Edge, Edges, Graph, Grid, Node, Nodes, Path } from '@lincle/react-native-base';
@@ -0,0 +1 @@
1
+ export { Path } from '../../../base';
@@ -0,0 +1 @@
1
+ export { Path } from '../../../base';
@@ -1 +1,2 @@
1
- export { Edge as default } from '../../base';
1
+ export { Edge } from '../../base';
2
+ export { Path } from './Path';
@@ -1 +1,2 @@
1
- export { Edge as default } from '../../base';
1
+ export { Edge } from '../../base';
2
+ export { Path } from './Path';
@@ -0,0 +1,10 @@
1
+ import { type FunctionComponent, type PropsWithChildren } from 'react';
2
+ declare const Connections: FunctionComponent<ConnectionsProps>;
3
+ export default Connections;
4
+ export type ConnectionsProps = PropsWithChildren<{
5
+ readonly scale: number;
6
+ readonly translate: {
7
+ x: number;
8
+ y: number;
9
+ };
10
+ }>;
@@ -0,0 +1,46 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Marker, useConnections } from '../../../shared';
3
+ import { Path } from '../../Edge';
4
+ import { useMemo } from 'react';
5
+ import { StyleSheet } from 'react-native';
6
+ import { Defs, Svg } from 'react-native-svg';
7
+ const { svgStyle } = StyleSheet.create({
8
+ svgStyle: {
9
+ bottom: 0,
10
+ height: '100%',
11
+ left: 0,
12
+ overflow: 'visible',
13
+ pointerEvents: 'none',
14
+ position: 'absolute',
15
+ right: 0,
16
+ top: 0,
17
+ width: '100%'
18
+ }
19
+ });
20
+ const Connections = ({ scale = 1, translate = {
21
+ x: 0,
22
+ y: 0
23
+ } }) => {
24
+ const connections = useConnections();
25
+ const paths = useMemo(() => {
26
+ return Object.keys(connections).map((sourceId) => {
27
+ const { line, source, target } = connections[sourceId];
28
+ return (_jsx(Path, { edgeId: sourceId + 'temp', line: line, source: source, target: target }, sourceId));
29
+ });
30
+ }, [
31
+ connections
32
+ ]);
33
+ const translateXYZ = useMemo(() => {
34
+ const tx = translate.x;
35
+ const ty = translate.y;
36
+ const tz = scale;
37
+ return `translate(${tx}, ${ty}) scale(${tz})`;
38
+ }, [
39
+ translate.x,
40
+ translate.y,
41
+ scale
42
+ ]);
43
+ return (_jsxs(Svg, { style: svgStyle, transform: translateXYZ, children: [_jsx(Defs, { children: _jsx(Marker, {}) }), paths] }));
44
+ };
45
+ Connections.displayName = 'LincleInteractiveConnections';
46
+ export default Connections;
@@ -1 +1,4 @@
1
- export { Edges as default } from '../../base';
1
+ import { type EdgesProps } from '../../shared';
2
+ import { type FunctionComponent } from 'react';
3
+ declare const Edges: FunctionComponent<EdgesProps>;
4
+ export { Edges };
@@ -1 +1,23 @@
1
- export { Edges as default } from '../../base';
1
+ var __rest = (this && this.__rest) || function (s, e) {
2
+ var t = {};
3
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
4
+ t[p] = s[p];
5
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
6
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
7
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
8
+ t[p[i]] = s[p[i]];
9
+ }
10
+ return t;
11
+ };
12
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
13
+ import { Edges as BaseEdges } from '../../base';
14
+ import { useScale, useTranslate } from '../../shared';
15
+ import Connections from './Connections';
16
+ const Edges = (_a) => {
17
+ var { children } = _a, props = __rest(_a, ["children"]);
18
+ const scale = useScale();
19
+ const translate = useTranslate();
20
+ return (_jsxs(_Fragment, { children: [_jsx(BaseEdges, Object.assign({ scale: scale, translate: translate }, props, { children: children })), _jsx(Connections, { scale: scale, translate: translate })] }));
21
+ };
22
+ Edges.displayName = 'LincleInteractiveEdges';
23
+ export { Edges };
@@ -1,4 +1,4 @@
1
- import { type GridProps } from '../../shared';
1
+ import { type GridProps } from '../../../shared';
2
2
  import { type FunctionComponent } from 'react';
3
3
  declare const Grid: FunctionComponent<GridProps>;
4
4
  export default Grid;
@@ -0,0 +1,56 @@
1
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Grid as GridBase } from '../../../base';
3
+ import { useMode, useScale, useTranslate } from '../../../shared';
4
+ import { useMemo } from 'react';
5
+ import { Circle, Line } from 'react-native-svg';
6
+ const WIDTH = 0.4;
7
+ const Grid = ({ children }) => {
8
+ const scale = useScale();
9
+ const translate = useTranslate();
10
+ const mode = useMode();
11
+ const line = useMemo(() => {
12
+ const t1 = 1 + scale;
13
+ const t2 = 4 * scale;
14
+ return (_jsx(Line, { stroke: 'black', strokeWidth: WIDTH, x1: t1, x2: t2, y1: t1, y2: t2 }));
15
+ }, [
16
+ scale
17
+ ]);
18
+ const plus = useMemo(() => {
19
+ const t1 = scale;
20
+ const t2 = 4 * scale;
21
+ return (_jsxs(_Fragment, { children: [_jsx(Line, { stroke: 'black', strokeWidth: WIDTH, x1: t1, x2: t2, y1: t2, y2: t2 }), _jsx(Line, { stroke: 'black', strokeWidth: WIDTH, x1: t2, x2: t2, y1: t1, y2: t2 })] }));
22
+ }, [
23
+ scale
24
+ ]);
25
+ const circle = useMemo(() => {
26
+ const t2 = 4 * scale;
27
+ return (_jsx(Circle, { cx: t2, cy: t2, fill: 'black', r: WIDTH }));
28
+ }, [
29
+ scale
30
+ ]);
31
+ const child = useMemo(() => {
32
+ if (!children) {
33
+ switch (mode) {
34
+ case 'pull': {
35
+ return line;
36
+ }
37
+ case 'select': {
38
+ return plus;
39
+ }
40
+ case 'move': {
41
+ return circle;
42
+ }
43
+ }
44
+ }
45
+ return children;
46
+ }, [
47
+ children,
48
+ circle,
49
+ line,
50
+ mode,
51
+ plus
52
+ ]);
53
+ return (_jsx(GridBase, { scale: scale, xOffset: translate.x, yOffset: translate.y, children: child }));
54
+ };
55
+ Grid.displayName = 'LincleInteractiveGrid';
56
+ export default Grid;
@@ -1,4 +1,4 @@
1
1
  import { type GraphProps } from '../../shared';
2
2
  import { type FunctionComponent } from 'react';
3
3
  declare const Graph: FunctionComponent<GraphProps>;
4
- export default Graph;
4
+ export { Graph };
@@ -1,13 +1,15 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- import { Graph as WrappedGraph } from '../../base';
3
- import GraphContexts from '../GraphContexts';
4
- import Interaction from '../Interaction';
5
- const Graph = ({ children, disableMove, disablePan, disablePull, disableScale, edgeFrequency, grid, id, line, maxScale, minScale, mode: givenMode, nodeFrequency, nodeHeight, nodeWidth, onEdgeDrop, onMouseDown, onMouseUp, onNodeDrag, onNodeSelect, onNodeStart, onNodeStop, onScale, onTouchEnd, onTouchStart, onTranslate, scale, shape, snap, xOffset, yOffset }) => {
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { GraphBase, Providers } from '../../shared';
3
+ import Grid from './Grid';
4
+ const Graph = ({ children, edgeFrequency, grid, id, line, maxScale, minScale, mode, move, nodeFrequency, nodeHeight, nodeWidth, onNodeDrag, onNodeEdgeDrop, onNodeSelect, onNodeStart, onNodeStop, onScale, onTranslate, pan, pull, scale, shape, showGrid, snap, translate, zoom }) => {
6
5
  if (!id) {
7
6
  console.error('No ID provided to @lincle/interactive Graph!');
8
7
  return null;
9
8
  }
10
- return (_jsx(GraphContexts, { disableMove: disableMove, disablePan: disablePan, disablePull: disablePull, disableScale: disableScale, edgeFrequency: edgeFrequency, grid: grid, id: id !== null && id !== void 0 ? id : 0, line: line, maxScale: maxScale, minScale: minScale, mode: givenMode, nodeFrequency: nodeFrequency, nodeHeight: nodeHeight, nodeWidth: nodeWidth, onEdgeDrop: onEdgeDrop, onNodeDrag: onNodeDrag, onNodeSelect: onNodeSelect, onNodeStart: onNodeStart, onNodeStop: onNodeStop, onScale: onScale, onTranslate: onTranslate, scale: scale, shape: shape, snap: snap, xOffset: xOffset, yOffset: yOffset, children: _jsx(WrappedGraph, { grid: false, id: id, children: _jsx(Interaction, { onMouseDown: onMouseDown, onMouseUp: onMouseUp, onTouchEnd: onTouchEnd, onTouchStart: onTouchStart, children: children }) }) }));
9
+ const gird = showGrid === false ?
10
+ null :
11
+ _jsx(Grid, {});
12
+ return (_jsx(GraphBase, { edgeFrequency: edgeFrequency, grid: grid, id: id, line: line, nodeFrequency: nodeFrequency, nodeHeight: nodeHeight, nodeWidth: nodeWidth, shape: shape, showGrid: false, children: _jsxs(Providers, { maxScale: maxScale, minScale: minScale, mode: mode, move: move, onNodeDrag: onNodeDrag, onNodeEdgeDrop: onNodeEdgeDrop, onNodeSelect: onNodeSelect, onNodeStart: onNodeStart, onNodeStop: onNodeStop, onScale: onScale, onTranslate: onTranslate, pan: pan, pull: pull, scale: scale, snap: snap, translate: translate, zoom: zoom, children: [gird, children] }) }));
11
13
  };
12
14
  Graph.displayName = 'LincleInteractiveGraph';
13
- export default Graph;
15
+ export { Graph };
@@ -1,4 +1,4 @@
1
1
  import { type InteractionProps } from '../../shared';
2
2
  import { type FunctionComponent } from 'react';
3
3
  declare const Interaction: FunctionComponent<InteractionProps>;
4
- export default Interaction;
4
+ export { Interaction };
@@ -1,17 +1,134 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useMode, useOnMode, useOnScale, useOnTranslateThrottle, useScale, useTranslate } from '../../shared';
2
3
  import { ReactNativeZoomableView } from '@openspacelabs/react-native-zoomable-view';
3
- import { View } from 'react-native';
4
- const styles = {
4
+ import { Children, useCallback, useEffect, useMemo, useRef } from 'react';
5
+ import { StyleSheet, View } from 'react-native';
6
+ const CLICK_TIME = 500;
7
+ const useDoubleTap = () => {
8
+ const timer = useRef(null);
9
+ useEffect(() => {
10
+ return () => {
11
+ if (timer.current) {
12
+ clearTimeout(timer.current);
13
+ timer.current = null;
14
+ }
15
+ };
16
+ }, []);
17
+ return useCallback((callback, threshold = CLICK_TIME) => {
18
+ if (timer.current) {
19
+ clearTimeout(timer.current);
20
+ timer.current = null;
21
+ return callback();
22
+ }
23
+ else {
24
+ timer.current = setTimeout(() => {
25
+ timer.current = null;
26
+ }, threshold);
27
+ return;
28
+ }
29
+ }, []);
30
+ };
31
+ const styles = StyleSheet.create({
5
32
  container: {
6
33
  height: '100%',
7
- overflow: 'hidden'
34
+ overflow: 'visible'
8
35
  },
9
36
  content: {
37
+ height: '100%',
38
+ position: 'absolute',
39
+ width: '100%'
40
+ },
41
+ zoomable: {
10
42
  overflow: 'visible'
11
43
  }
12
- };
13
- const Interaction = ({ children }) => {
14
- return (_jsx(View, { style: styles.container, children: _jsx(ReactNativeZoomableView, { bindToBorders: false, initialZoom: 1, maxZoom: 1.5, minZoom: 0.5, style: styles.content, zoomStep: 0.5, children: children }) }));
44
+ });
45
+ const Interaction = ({ children, onPointerUp }) => {
46
+ const scale = useScale();
47
+ const translate = useTranslate();
48
+ const onScale = useOnScale();
49
+ const onTranslateThrottle = useOnTranslateThrottle();
50
+ const graphMode = useMode();
51
+ const onMode = useOnMode();
52
+ const handleDoubleTap = useDoubleTap();
53
+ const handleOnTransform = useCallback((event) => {
54
+ const { offsetX, offsetY, originalHeight, originalWidth, zoomLevel } = event;
55
+ onTranslateThrottle(originalWidth, originalHeight, offsetX, offsetY, zoomLevel);
56
+ }, [
57
+ onTranslateThrottle
58
+ ]);
59
+ const handleZoom = useCallback((event, gestureState, zoomableViewEventObject) => {
60
+ const { offsetX, offsetY, originalHeight, originalWidth, zoomLevel } = zoomableViewEventObject;
61
+ onTranslateThrottle(originalWidth, originalHeight, offsetX, offsetY, zoomLevel);
62
+ if (onScale) {
63
+ onScale(zoomLevel);
64
+ }
65
+ }, [
66
+ onScale,
67
+ onTranslateThrottle
68
+ ]);
69
+ const { edges, nodes } = useMemo(() => {
70
+ const filteredChildren = Children.toArray(children).filter((child) => {
71
+ var _a;
72
+ const name = (_a = child === null || child === void 0 ? void 0 : child.type) === null || _a === void 0 ? void 0 : _a.displayName;
73
+ return name === 'LincleInteractiveNodes' ||
74
+ 'LincleInteractiveEdges';
75
+ });
76
+ const filteredNodes = filteredChildren.filter((child) => {
77
+ var _a;
78
+ const name = (_a = child === null || child === void 0 ? void 0 : child.type) === null || _a === void 0 ? void 0 : _a.displayName;
79
+ return name === 'LincleInteractiveNodes';
80
+ });
81
+ const filteredEdges = filteredChildren.filter((child) => {
82
+ var _a;
83
+ const name = (_a = child === null || child === void 0 ? void 0 : child.type) === null || _a === void 0 ? void 0 : _a.displayName;
84
+ return name === 'LincleInteractiveEdges';
85
+ });
86
+ return {
87
+ edges: filteredEdges,
88
+ nodes: filteredNodes
89
+ };
90
+ }, [
91
+ children
92
+ ]);
93
+ const handleTapEnd = useCallback(() => {
94
+ if (onMode) {
95
+ switch (graphMode) {
96
+ case 'move': {
97
+ return handleDoubleTap(() => {
98
+ onMode('pull');
99
+ });
100
+ }
101
+ case 'pull': {
102
+ return handleDoubleTap(() => {
103
+ onMode('select');
104
+ });
105
+ }
106
+ case 'select':
107
+ default: {
108
+ return handleDoubleTap(() => {
109
+ onMode('move');
110
+ });
111
+ }
112
+ }
113
+ }
114
+ else {
115
+ return;
116
+ }
117
+ }, [
118
+ graphMode,
119
+ handleDoubleTap,
120
+ onMode
121
+ ]);
122
+ const handlePointerUp = useCallback((event) => {
123
+ handleTapEnd();
124
+ if (onPointerUp) {
125
+ onPointerUp(event);
126
+ }
127
+ }, [
128
+ handleTapEnd,
129
+ onPointerUp
130
+ ]);
131
+ return (_jsxs(View, { style: styles.container, children: [_jsx(ReactNativeZoomableView, { bindToBorders: false, doubleTapDelay: 1, doubleTapZoomToCenter: false, initialOffsetX: translate.x, initialOffsetY: translate.y, initialZoom: scale, maxZoom: 1.5, minZoom: 0.5, movementSensibility: 1, onSingleTap: handlePointerUp, onTransform: handleOnTransform, onZoomAfter: handleZoom, panEnabled: true, style: styles.zoomable, visualTouchFeedbackEnabled: false, zoomStep: 0.5, children: nodes }), _jsx(View, { style: styles.content, children: edges })] }));
15
132
  };
16
133
  Interaction.displayName = 'LincleInteractiveInteraction';
17
- export default Interaction;
134
+ export { Interaction };
@@ -0,0 +1,41 @@
1
+ import React, { type FunctionComponent } from 'react';
2
+ import { type GestureResponderEvent, type PanResponderGestureState } from 'react-native';
3
+ declare const Draggable: FunctionComponent<IProps>;
4
+ export default Draggable;
5
+ type IProps = {
6
+ readonly animatedViewProps?: object;
7
+ readonly children?: React.ReactNode;
8
+ readonly debug?: boolean;
9
+ readonly disabled?: boolean;
10
+ readonly imageSource?: number;
11
+ readonly isCircle?: boolean;
12
+ readonly maxX?: number;
13
+ readonly maxY?: number;
14
+ readonly minX?: number;
15
+ readonly minY?: number;
16
+ readonly onDrag?: (event: GestureResponderEvent, gestureState: PanResponderGestureState) => void;
17
+ readonly onDragRelease?: (event: GestureResponderEvent, gestureState: PanResponderGestureState, bounds: {
18
+ bottom: number;
19
+ left: number;
20
+ right: number;
21
+ top: number;
22
+ }) => void;
23
+ readonly onLongPress?: (event: GestureResponderEvent) => void;
24
+ readonly onPressIn?: (event: GestureResponderEvent) => void;
25
+ readonly onPressOut?: (event: GestureResponderEvent) => void;
26
+ readonly onRelease?: (event: GestureResponderEvent, wasDragging: boolean) => void;
27
+ readonly onReverse?: () => {
28
+ x: number;
29
+ y: number;
30
+ };
31
+ readonly onShortPressRelease?: (event: GestureResponderEvent) => void;
32
+ readonly renderColor?: string;
33
+ readonly renderSize?: number;
34
+ readonly renderText?: string;
35
+ readonly scale?: number;
36
+ readonly shouldReverse?: boolean;
37
+ readonly touchableOpacityProps?: object;
38
+ readonly x?: number;
39
+ readonly y?: number;
40
+ readonly zIndex?: number;
41
+ };
@@ -0,0 +1,270 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useCallback, useEffect, useMemo, useRef } from 'react';
3
+ import { Animated, Dimensions, Image, PanResponder, StyleSheet, Text, TouchableOpacity, View } from 'react-native';
4
+ const clamp = (number, min, max) => {
5
+ return Math.max(min, Math.min(number, max));
6
+ };
7
+ const styles = StyleSheet.create({
8
+ debugView: {
9
+ backgroundColor: '#ff000044',
10
+ borderColor: '#fced0ecc',
11
+ borderWidth: 4,
12
+ position: 'absolute'
13
+ },
14
+ text: {
15
+ color: '#fff',
16
+ textAlign: 'center'
17
+ }
18
+ });
19
+ const Draggable = ({ animatedViewProps, children, debug = false, disabled = false, imageSource, isCircle, maxX, maxY, minX, minY, onDrag, onDragRelease, onLongPress, onPressIn, onPressOut, onRelease, onShortPressRelease, renderColor, renderSize = 36, renderText = '+', scale = 1, shouldReverse = false, touchableOpacityProps, x = 0, y = 0, zIndex = 1 }) => {
20
+ const pan = useRef(new Animated.ValueXY());
21
+ const offsetFromStart = useRef({
22
+ x: 0,
23
+ y: 0
24
+ });
25
+ const childSize = useRef({
26
+ x: renderSize,
27
+ y: renderSize
28
+ });
29
+ const startBounds = useRef({
30
+ bottom: 0,
31
+ left: 0,
32
+ right: 0,
33
+ top: 0
34
+ });
35
+ const isDragging = useRef(false);
36
+ const getBounds = useCallback(() => {
37
+ const left = x + offsetFromStart.current.x;
38
+ const top = y + offsetFromStart.current.y;
39
+ return {
40
+ bottom: top + childSize.current.y,
41
+ left,
42
+ right: left + childSize.current.x,
43
+ top
44
+ };
45
+ }, [
46
+ x,
47
+ y
48
+ ]);
49
+ const shouldStartDrag = useCallback((gs) => {
50
+ return !disabled && (Math.abs(gs.dx) > 2 || Math.abs(gs.dy) > 2);
51
+ }, [
52
+ disabled
53
+ ]);
54
+ const reversePosition = useCallback(() => {
55
+ Animated.spring(pan.current, {
56
+ toValue: {
57
+ x: 0,
58
+ y: 0
59
+ },
60
+ useNativeDriver: false
61
+ }).start();
62
+ }, [
63
+ pan
64
+ ]);
65
+ const onPanResponderRelease = useCallback((event, gestureState) => {
66
+ isDragging.current = false;
67
+ if (onDragRelease) {
68
+ onDragRelease(event, gestureState, getBounds());
69
+ if (onRelease) {
70
+ onRelease(event, true);
71
+ }
72
+ }
73
+ if (shouldReverse) {
74
+ reversePosition();
75
+ }
76
+ else {
77
+ pan.current.flattenOffset();
78
+ }
79
+ }, [
80
+ getBounds,
81
+ onDragRelease,
82
+ onRelease,
83
+ reversePosition,
84
+ shouldReverse
85
+ ]);
86
+ const onPanResponderGrant = useCallback((event, gestureState) => {
87
+ startBounds.current = getBounds();
88
+ isDragging.current = true;
89
+ if (!shouldReverse) {
90
+ pan.current.setOffset(offsetFromStart.current);
91
+ pan.current.setValue({
92
+ x: 0,
93
+ y: 0
94
+ });
95
+ }
96
+ }, [
97
+ getBounds,
98
+ shouldReverse
99
+ ]);
100
+ const handleOnDrag = useCallback((event, gestureState) => {
101
+ const { dx, dy } = gestureState;
102
+ const { bottom, left, right, top } = startBounds.current;
103
+ const far = 999999999;
104
+ const changeX = clamp(dx, Number.isFinite(minX) ?
105
+ minX - left :
106
+ -far, Number.isFinite(maxX) ?
107
+ maxX - right :
108
+ far);
109
+ const changeY = clamp(dy, Number.isFinite(minY) ?
110
+ minY - top :
111
+ -far, Number.isFinite(maxY) ?
112
+ maxY - bottom :
113
+ far);
114
+ pan.current.setValue({
115
+ x: changeX / scale,
116
+ y: changeY / scale
117
+ });
118
+ if (onDrag) {
119
+ onDrag(event, Object.assign(Object.assign({}, gestureState), { dx: changeX / scale, dy: changeY / scale }));
120
+ }
121
+ }, [
122
+ maxX,
123
+ maxY,
124
+ minX,
125
+ minY,
126
+ onDrag,
127
+ scale
128
+ ]);
129
+ const panResponder = useMemo(() => {
130
+ return PanResponder.create({
131
+ onMoveShouldSetPanResponder: (_, gestureState) => {
132
+ return shouldStartDrag(gestureState);
133
+ },
134
+ onMoveShouldSetPanResponderCapture: (_, gestureState) => {
135
+ return shouldStartDrag(gestureState);
136
+ },
137
+ onPanResponderGrant,
138
+ onPanResponderMove: Animated.event([], {
139
+ listener: handleOnDrag,
140
+ useNativeDriver: false
141
+ }),
142
+ onPanResponderRelease
143
+ });
144
+ }, [
145
+ handleOnDrag,
146
+ onPanResponderGrant,
147
+ onPanResponderRelease,
148
+ shouldStartDrag
149
+ ]);
150
+ useEffect(() => {
151
+ const currentPan = pan.current;
152
+ if (!shouldReverse) {
153
+ currentPan.addListener((cp) => {
154
+ offsetFromStart.current = cp;
155
+ return offsetFromStart.current;
156
+ });
157
+ }
158
+ return () => {
159
+ currentPan.removeAllListeners();
160
+ };
161
+ }, [
162
+ shouldReverse
163
+ ]);
164
+ const positionCss = useMemo(() => {
165
+ const Window = Dimensions.get('window');
166
+ return {
167
+ height: Window.height,
168
+ left: 0,
169
+ position: 'absolute',
170
+ top: 0,
171
+ width: Window.width
172
+ };
173
+ }, []);
174
+ const hasChildren = Boolean(children);
175
+ const dragItemCss = useMemo(() => {
176
+ const style = {
177
+ elevation: zIndex,
178
+ left: x,
179
+ top: y,
180
+ zIndex
181
+ };
182
+ if (renderColor) {
183
+ style.backgroundColor = renderColor;
184
+ }
185
+ if (isCircle) {
186
+ style.borderRadius = renderSize;
187
+ }
188
+ if (hasChildren) {
189
+ style.alignSelf = 'baseline';
190
+ return style;
191
+ }
192
+ else {
193
+ style.height = renderSize;
194
+ style.justifyContent = 'center';
195
+ style.width = renderSize;
196
+ return style;
197
+ }
198
+ }, [
199
+ hasChildren,
200
+ isCircle,
201
+ renderColor,
202
+ renderSize,
203
+ x,
204
+ y,
205
+ zIndex
206
+ ]);
207
+ const touchableContent = useMemo(() => {
208
+ if (imageSource) {
209
+ const style = {
210
+ height: renderSize,
211
+ width: renderSize
212
+ };
213
+ return (_jsx(Image, { source: imageSource, style: style }));
214
+ }
215
+ else {
216
+ return (_jsx(Text, { style: styles.text, children: renderText }));
217
+ }
218
+ }, [
219
+ imageSource,
220
+ renderSize,
221
+ renderText
222
+ ]);
223
+ const handleOnLayout = useCallback((event) => {
224
+ const { height, width } = event.nativeEvent.layout;
225
+ childSize.current = {
226
+ x: width,
227
+ y: height
228
+ };
229
+ }, []);
230
+ const handlePressOut = useCallback((event) => {
231
+ if (onPressOut) {
232
+ onPressOut(event);
233
+ }
234
+ if (!isDragging.current &&
235
+ onRelease) {
236
+ onRelease(event, false);
237
+ }
238
+ }, [
239
+ onPressOut,
240
+ onRelease
241
+ ]);
242
+ const getDebugView = useCallback(() => {
243
+ const { height, width } = Dimensions.get('window');
244
+ const far = 9999;
245
+ const constrained = minX || maxX || minY || maxY;
246
+ if (!constrained) {
247
+ return null;
248
+ }
249
+ const left = minX || -far;
250
+ const right = maxX ?
251
+ width - maxX :
252
+ -far;
253
+ const top = minY || -far;
254
+ const bottom = maxY ?
255
+ height - maxY :
256
+ -far;
257
+ return (_jsx(View, { pointerEvents: 'box-none', style: Object.assign({ bottom,
258
+ left,
259
+ right,
260
+ top }, styles.debugView) }));
261
+ }, [
262
+ maxX,
263
+ maxY,
264
+ minX,
265
+ minY
266
+ ]);
267
+ return (_jsxs(View, { pointerEvents: 'box-none', style: positionCss, children: [debug && getDebugView(), _jsx(Animated.View, Object.assign({ pointerEvents: 'box-none' }, animatedViewProps, panResponder.panHandlers, { style: pan.current.getLayout(), children: _jsx(TouchableOpacity, Object.assign({}, touchableOpacityProps, { activeOpacity: 1, disabled: disabled, onLayout: handleOnLayout, onLongPress: onLongPress, onPress: onShortPressRelease, onPressIn: onPressIn, onPressOut: handlePressOut, style: dragItemCss, children: children !== null && children !== void 0 ? children : touchableContent })) }))] }));
268
+ };
269
+ Draggable.displayName = 'ReactNativeDraggable';
270
+ export default Draggable;