react-swipe-action 0.0.1 → 0.0.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.
- package/README.md +2 -0
- package/dist/SwipeAction.js +9 -1
- package/dist/SwipeAction.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# React swipe action [](https://www.npmjs.com/package/react-swipe-action) 
|
|
2
2
|
|
|
3
|
+
Swipe to reveal or perform an action. Try interactive [Storybook demo](https://filipchalupa.cz/react-swipe-action/).
|
|
4
|
+
|
|
3
5
|
## Installation
|
|
4
6
|
|
|
5
7
|
```bash
|
package/dist/SwipeAction.js
CHANGED
|
@@ -16,6 +16,7 @@ var SwipeAction = function (_a) {
|
|
|
16
16
|
}
|
|
17
17
|
setPositionOffset(x);
|
|
18
18
|
}, []);
|
|
19
|
+
var isLongSwipeEnabled = useRef(true); // Prevents long swipe from being triggered twice in React strict mode
|
|
19
20
|
var onEnd = useCallback(function (x) {
|
|
20
21
|
if (x === 0) {
|
|
21
22
|
setIsSwiping(false);
|
|
@@ -34,7 +35,10 @@ var SwipeAction = function (_a) {
|
|
|
34
35
|
contentWidth !== undefined &&
|
|
35
36
|
normalizedSwipePosition >
|
|
36
37
|
Math.max(mainWidth / 4, contentWidth) * 1.6) {
|
|
37
|
-
|
|
38
|
+
if (isLongSwipeEnabled.current) {
|
|
39
|
+
onLongSwipe();
|
|
40
|
+
isLongSwipeEnabled.current = false;
|
|
41
|
+
}
|
|
38
42
|
return positionSign * mainWidth;
|
|
39
43
|
}
|
|
40
44
|
if (contentWidth !== 0 &&
|
|
@@ -54,7 +58,11 @@ var SwipeAction = function (_a) {
|
|
|
54
58
|
}
|
|
55
59
|
setPositionOffset(0);
|
|
56
60
|
}, [startAction === null || startAction === void 0 ? void 0 : startAction.onLongSwipe, endAction === null || endAction === void 0 ? void 0 : endAction.onLongSwipe]);
|
|
61
|
+
var onStart = useCallback(function () {
|
|
62
|
+
isLongSwipeEnabled.current = true;
|
|
63
|
+
}, []);
|
|
57
64
|
var elementProps = useDrag({
|
|
65
|
+
onStart: onStart,
|
|
58
66
|
onRelativePositionChange: onRelativePositionChange,
|
|
59
67
|
onEnd: onEnd,
|
|
60
68
|
}).elementProps;
|
package/dist/SwipeAction.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SwipeAction.js","sources":["../src/SwipeAction.tsx"],"sourcesContent":["'use client'\n\nimport type {\n\tCSSProperties,\n\tFunctionComponent,\n\tReactNode,\n\tRefObject,\n} from 'react'\nimport { useCallback, useMemo, useRef, useState } from 'react'\nimport { useDrag } from 'react-use-drag'\nimport styles from './SwipeAction.module.css'\n\n// @TODO: add inertia\n// @TODO: animate snapping\n// @TODO: add threshold - maybe to react-use-drag\n\ntype OnLongSwipe = () => void\ntype Content = ReactNode\n\ntype Action = {\n\tbackground?: ReactNode\n\tcontent?: Content\n\tonLongSwipe?: OnLongSwipe\n} & (\n\t
|
|
1
|
+
{"version":3,"file":"SwipeAction.js","sources":["../src/SwipeAction.tsx"],"sourcesContent":["'use client'\n\nimport type {\n\tCSSProperties,\n\tFunctionComponent,\n\tReactNode,\n\tRefObject,\n} from 'react'\nimport { useCallback, useMemo, useRef, useState } from 'react'\nimport { useDrag } from 'react-use-drag'\nimport styles from './SwipeAction.module.css'\n\n// @TODO: add inertia\n// @TODO: animate snapping\n// @TODO: add threshold - maybe to react-use-drag\n\ntype OnLongSwipe = () => void\ntype Content = ReactNode\n\ntype Action = {\n\tbackground?: ReactNode\n\tcontent?: Content\n\tonLongSwipe?: OnLongSwipe\n} & (\n\t| {\n\t\t\tcontent: Content\n\t }\n\t| {\n\t\t\tonLongSwipe: OnLongSwipe\n\t }\n)\n\ntype SwipeActionProps = {\n\tmain: (handle: ReactNode) => ReactNode\n\tstartAction?: Action\n\tendAction?: Action\n}\n\nexport const SwipeAction: FunctionComponent<SwipeActionProps> = ({\n\tstartAction,\n\tendAction,\n\tmain,\n}) => {\n\tconst [position, setPosition] = useState(0)\n\tconst [positionOffset, setPositionOffset] = useState(0)\n\tconst [isSwiping, setIsSwiping] = useState(false)\n\tconst onRelativePositionChange = useCallback((x: number) => {\n\t\tif (Math.abs(x) > 5) {\n\t\t\tsetIsSwiping(true)\n\t\t}\n\t\tsetPositionOffset(x)\n\t}, [])\n\tconst isLongSwipeEnabled = useRef(true) // Prevents long swipe from being triggered twice in React strict mode\n\tconst onEnd = useCallback(\n\t\t(x: number) => {\n\t\t\tif (x === 0) {\n\t\t\t\tsetIsSwiping(false)\n\t\t\t} else {\n\t\t\t\tsetPosition((position) => {\n\t\t\t\t\tconst newPosition = position + x\n\t\t\t\t\tconst mainWidth = mainRef.current?.offsetWidth ?? 0\n\n\t\t\t\t\tconst handleContent = (\n\t\t\t\t\t\tref: RefObject<HTMLDivElement>,\n\t\t\t\t\t\tposition: Position,\n\t\t\t\t\t\tonLongSwipe: undefined | OnLongSwipe,\n\t\t\t\t\t) => {\n\t\t\t\t\t\tconst contentWidth = ref.current?.offsetWidth\n\t\t\t\t\t\tconst positionSign = position === 'start' ? 1 : -1\n\t\t\t\t\t\tconst normalizedSwipePosition = positionSign * newPosition\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\tonLongSwipe &&\n\t\t\t\t\t\t\tcontentWidth !== undefined &&\n\t\t\t\t\t\t\tnormalizedSwipePosition >\n\t\t\t\t\t\t\t\tMath.max(mainWidth / 4, contentWidth) * 1.6\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\tif (isLongSwipeEnabled.current) {\n\t\t\t\t\t\t\t\tonLongSwipe()\n\t\t\t\t\t\t\t\tisLongSwipeEnabled.current = false\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn positionSign * mainWidth\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\tcontentWidth !== 0 &&\n\t\t\t\t\t\t\tcontentWidth !== undefined &&\n\t\t\t\t\t\t\tnormalizedSwipePosition > contentWidth * 0.7\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\treturn positionSign * contentWidth\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (Math.sign(newPosition) === positionSign) {\n\t\t\t\t\t\t\tsetTimeout(() => {\n\t\t\t\t\t\t\t\tsetIsSwiping(false)\n\t\t\t\t\t\t\t}, 200) // Delay to ignore immediate click\n\t\t\t\t\t\t\treturn 0\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\treturn (\n\t\t\t\t\t\thandleContent(\n\t\t\t\t\t\t\tstartActionContentRef,\n\t\t\t\t\t\t\t'start',\n\t\t\t\t\t\t\tstartAction?.onLongSwipe,\n\t\t\t\t\t\t) ??\n\t\t\t\t\t\thandleContent(endActionContentRef, 'end', endAction?.onLongSwipe) ??\n\t\t\t\t\t\tnewPosition\n\t\t\t\t\t)\n\t\t\t\t})\n\t\t\t}\n\t\t\tsetPositionOffset(0)\n\t\t},\n\t\t[startAction?.onLongSwipe, endAction?.onLongSwipe],\n\t)\n\tconst onStart = useCallback(() => {\n\t\tisLongSwipeEnabled.current = true\n\t}, [])\n\tconst { elementProps } = useDrag({\n\t\tonStart,\n\t\tonRelativePositionChange,\n\t\tonEnd,\n\t})\n\tconst mainRef = useRef<HTMLDivElement>(null)\n\tconst startActionContentRef = useRef<HTMLDivElement>(null)\n\tconst endActionContentRef = useRef<HTMLDivElement>(null)\n\n\tconst x = useMemo(\n\t\t() =>\n\t\t\tMath.max(\n\t\t\t\tendAction ? Number.NEGATIVE_INFINITY : 0,\n\t\t\t\tMath.min(\n\t\t\t\t\tstartAction ? Number.POSITIVE_INFINITY : 0,\n\t\t\t\t\tposition + positionOffset,\n\t\t\t\t),\n\t\t\t),\n\t\t[position, positionOffset, startAction, endAction],\n\t)\n\n\treturn (\n\t\t<div className={styles.wrapper}>\n\t\t\t{startAction && x > 0 && (\n\t\t\t\t<Action\n\t\t\t\t\tposition=\"start\"\n\t\t\t\t\tcontent={startAction.content}\n\t\t\t\t\tbackground={startAction.background}\n\t\t\t\t\tcontentRef={startActionContentRef}\n\t\t\t\t/>\n\t\t\t)}\n\t\t\t{endAction && x < 0 && (\n\t\t\t\t<Action\n\t\t\t\t\tposition=\"end\"\n\t\t\t\t\tcontent={endAction.content}\n\t\t\t\t\tbackground={endAction.background}\n\t\t\t\t\tcontentRef={endActionContentRef}\n\t\t\t\t/>\n\t\t\t)}\n\t\t\t<div\n\t\t\t\tclassName={styles.main}\n\t\t\t\tref={mainRef}\n\t\t\t\tstyle={\n\t\t\t\t\t{\n\t\t\t\t\t\t'--x': `${x}px`,\n\t\t\t\t\t} as CSSProperties\n\t\t\t\t}\n\t\t\t>\n\t\t\t\t{main(\n\t\t\t\t\t<div\n\t\t\t\t\t\tclassName={styles.handle}\n\t\t\t\t\t\t{...elementProps}\n\t\t\t\t\t\tonClick={(event) => {\n\t\t\t\t\t\t\tif (isSwiping) {\n\t\t\t\t\t\t\t\tevent.stopPropagation()\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}}\n\t\t\t\t\t/>,\n\t\t\t\t)}\n\t\t\t</div>\n\t\t</div>\n\t)\n}\n\ntype Position = 'start' | 'end'\n\nconst Action: FunctionComponent<{\n\tposition: Position\n\tcontent: ReactNode\n\tbackground: ReactNode\n\tcontentRef: RefObject<HTMLDivElement>\n}> = ({ content, background, position, contentRef }) => {\n\t// @TODO: allow focus by tab key before visible\n\treturn (\n\t\t<div className={`${styles.action} ${styles[`is_position_${position}`]}`}>\n\t\t\t<div className={styles.action_background}>{background}</div>\n\t\t\t<div className={styles.action_content} ref={contentRef}>\n\t\t\t\t{content}\n\t\t\t</div>\n\t\t</div>\n\t)\n}\n"],"names":[],"mappings":";;;;;;;AAsCO;AACN;;;;AAOA;;;;;;;AAOA;AAEE;;;;;;AAIE;;AAGA;;;AAMC;AACA;AACA;AAEC;;AAEC;AAED;AACC;AACA;;;;;AAMD;AACA;;;;AAKA;;AAEA;AACA;;AAEF;AAEA;AASD;;;AAGF;;AAIA;;;AAGA;AACA;AACA;AACA;AACD;AACA;AACA;;AAIE;;AAUF;;AAwBsB;;;;AAWjB;AAMN;AAIA;;;AAOC;AAQD;;"}
|
package/package.json
CHANGED