react-swipe-action 0.1.1 → 0.2.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/dist/SwipeAction.d.ts +2 -1
- package/dist/SwipeAction.js +24 -11
- package/dist/SwipeAction.js.map +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
package/dist/SwipeAction.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { FunctionComponent, ReactNode } from 'react';
|
|
2
|
-
type OnLongSwipe = () => void
|
|
2
|
+
type OnLongSwipe = () => void | Promise<void>;
|
|
3
3
|
type Content = ReactNode;
|
|
4
4
|
export type Action = {
|
|
5
5
|
background?: ReactNode;
|
|
@@ -16,4 +16,5 @@ export type SwipeActionProps = {
|
|
|
16
16
|
endAction?: Action;
|
|
17
17
|
};
|
|
18
18
|
export declare const SwipeAction: FunctionComponent<SwipeActionProps>;
|
|
19
|
+
export declare const useSwipeActionReset: () => () => void;
|
|
19
20
|
export {};
|
package/dist/SwipeAction.js
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { __assign } from './_virtual/_tslib.js';
|
|
3
|
-
import {
|
|
4
|
-
import { useState, useCallback, useRef, useMemo } from 'react';
|
|
3
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
4
|
+
import { createContext, useState, useCallback, useRef, useMemo, useContext } from 'react';
|
|
5
5
|
import { useDrag } from 'react-use-drag';
|
|
6
6
|
import styles from './SwipeAction.module.css.js';
|
|
7
7
|
|
|
8
|
+
var context = createContext({
|
|
9
|
+
reset: function () {
|
|
10
|
+
throw new Error("Can't call reset outside SwipeAction component.");
|
|
11
|
+
},
|
|
12
|
+
});
|
|
8
13
|
var SwipeAction = function (_a) {
|
|
9
14
|
var startAction = _a.startAction, endAction = _a.endAction, main = _a.main;
|
|
10
15
|
var _b = useState(0), position = _b[0], setPosition = _b[1];
|
|
@@ -36,7 +41,9 @@ var SwipeAction = function (_a) {
|
|
|
36
41
|
normalizedSwipePosition >
|
|
37
42
|
Math.max(mainWidth / 4, contentWidth) * 1.6) {
|
|
38
43
|
if (isLongSwipeEnabled.current) {
|
|
39
|
-
onLongSwipe()
|
|
44
|
+
Promise.resolve(onLongSwipe()).then(function () {
|
|
45
|
+
setPosition(0);
|
|
46
|
+
});
|
|
40
47
|
isLongSwipeEnabled.current = false;
|
|
41
48
|
}
|
|
42
49
|
return positionSign * mainWidth;
|
|
@@ -72,19 +79,25 @@ var SwipeAction = function (_a) {
|
|
|
72
79
|
var x = useMemo(function () {
|
|
73
80
|
return Math.max(endAction ? Number.NEGATIVE_INFINITY : 0, Math.min(startAction ? Number.POSITIVE_INFINITY : 0, position + positionOffset));
|
|
74
81
|
}, [position, positionOffset, startAction, endAction]);
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
+
var reset = useCallback(function () {
|
|
83
|
+
setPosition(0);
|
|
84
|
+
setPositionOffset(0);
|
|
85
|
+
setIsSwiping(false);
|
|
86
|
+
}, []);
|
|
87
|
+
return (jsx(context.Provider, { value: { reset: reset }, children: jsxs("div", { className: styles.wrapper, children: [startAction && x > 0 && (jsx(Action, { position: "start", content: startAction.content, background: startAction.background, contentRef: startActionContentRef })), endAction && x < 0 && (jsx(Action, { position: "end", content: endAction.content, background: endAction.background, contentRef: endActionContentRef })), jsx("div", { className: styles.main, ref: mainRef, style: {
|
|
88
|
+
'--x': "".concat(x, "px"),
|
|
89
|
+
}, children: main(jsx("div", __assign({ className: styles.handle }, elementProps, { onClick: function (event) {
|
|
90
|
+
if (isSwiping) {
|
|
91
|
+
event.stopPropagation();
|
|
92
|
+
}
|
|
93
|
+
} }))) })] }) }));
|
|
82
94
|
};
|
|
83
95
|
var Action = function (_a) {
|
|
84
96
|
var content = _a.content, background = _a.background, position = _a.position, contentRef = _a.contentRef;
|
|
85
97
|
// @TODO: allow focus by tab key before visible
|
|
86
98
|
return (jsxs("div", { className: "".concat(styles.action, " ").concat(styles["is_position_".concat(position)]), children: [jsx("div", { className: styles.action_background, children: background }), jsx("div", { className: styles.action_content, ref: contentRef, children: content })] }));
|
|
87
99
|
};
|
|
100
|
+
var useSwipeActionReset = function () { return useContext(context).reset; };
|
|
88
101
|
|
|
89
|
-
export { SwipeAction };
|
|
102
|
+
export { SwipeAction, useSwipeActionReset };
|
|
90
103
|
//# sourceMappingURL=SwipeAction.js.map
|
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 {
|
|
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 {\n\tcreateContext,\n\tuseCallback,\n\tuseContext,\n\tuseMemo,\n\tuseRef,\n\tuseState,\n} 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 | Promise<void>\ntype Content = ReactNode\n\nexport type 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\nconst context = createContext({\n\treset: (): void => {\n\t\tthrow new Error(\"Can't call reset outside SwipeAction component.\")\n\t},\n})\n\nexport type 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\tPromise.resolve(onLongSwipe()).then(() => {\n\t\t\t\t\t\t\t\t\tsetPosition(0)\n\t\t\t\t\t\t\t\t})\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\tconst reset = useCallback(() => {\n\t\tsetPosition(0)\n\t\tsetPositionOffset(0)\n\t\tsetIsSwiping(false)\n\t}, [])\n\n\treturn (\n\t\t<context.Provider value={{ reset }}>\n\t\t\t<div className={styles.wrapper}>\n\t\t\t\t{startAction && x > 0 && (\n\t\t\t\t\t<Action\n\t\t\t\t\t\tposition=\"start\"\n\t\t\t\t\t\tcontent={startAction.content}\n\t\t\t\t\t\tbackground={startAction.background}\n\t\t\t\t\t\tcontentRef={startActionContentRef}\n\t\t\t\t\t/>\n\t\t\t\t)}\n\t\t\t\t{endAction && x < 0 && (\n\t\t\t\t\t<Action\n\t\t\t\t\t\tposition=\"end\"\n\t\t\t\t\t\tcontent={endAction.content}\n\t\t\t\t\t\tbackground={endAction.background}\n\t\t\t\t\t\tcontentRef={endActionContentRef}\n\t\t\t\t\t/>\n\t\t\t\t)}\n\t\t\t\t<div\n\t\t\t\t\tclassName={styles.main}\n\t\t\t\t\tref={mainRef}\n\t\t\t\t\tstyle={\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t'--x': `${x}px`,\n\t\t\t\t\t\t} as CSSProperties\n\t\t\t\t\t}\n\t\t\t\t>\n\t\t\t\t\t{main(\n\t\t\t\t\t\t<div\n\t\t\t\t\t\t\tclassName={styles.handle}\n\t\t\t\t\t\t\t{...elementProps}\n\t\t\t\t\t\t\tonClick={(event) => {\n\t\t\t\t\t\t\t\tif (isSwiping) {\n\t\t\t\t\t\t\t\t\tevent.stopPropagation()\n\t\t\t\t\t\t\t\t}\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</div>\n\t\t\t</div>\n\t\t</context.Provider>\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\nexport const useSwipeActionReset = () => useContext(context).reset\n"],"names":[],"mappings":";;;;;;;AAuCA;AACC;AACC;;AAED;AAQM;AACN;;;;AAOA;;;;;;;AAOA;AAEE;;;;;;AAIE;;AAGA;;;AAMC;AACA;AACA;AAEC;;AAEC;AAED;;;AAGC;AACA;;;;;AAMD;AACA;;;;AAKA;;AAEA;AACA;;AAEF;AAEA;AASD;;;AAGF;;AAIA;;;AAGA;AACA;AACA;AACA;AACD;AACA;AACA;;AAIE;;;;;;;;;AAyCqB;;;;AAWjB;AAOP;AAIA;;;AAOC;AAQD;AAEO;;"}
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { SwipeAction } from './SwipeAction.js';
|
|
1
|
+
export { SwipeAction, useSwipeActionReset } from './SwipeAction.js';
|
|
2
2
|
//# sourceMappingURL=index.js.map
|