swipeon-react 0.0.1-alpha.2

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 react-forge
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,332 @@
1
+ # ðŸŽī SwipeOn React
2
+
3
+ [![npm version](https://img.shields.io/npm/v/swipeon-react.svg)](https://www.npmjs.com/package/swipeon-react)
4
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
5
+ [![TypeScript](https://img.shields.io/badge/TypeScript-Ready-blue.svg)](https://www.typescriptlang.org/)
6
+
7
+ A high-performance, zero-dependency React swipe card library with smooth animations and multi-directional swipe support. Perfect for building Tinder-like interfaces, interactive card stacks, and gesture-based UI components.
8
+
9
+ ## âœĻ Features
10
+
11
+ - 🚀 **High Performance**: Optimized with `requestAnimationFrame` and hardware-accelerated transforms
12
+ - ðŸŽŊ **4-Way Swipe**: Support for left, right, up, and down swipes
13
+ - ðŸ“ą **Touch & Mouse**: Works seamlessly on both desktop and mobile devices
14
+ - ðŸŽĻ **Smooth Animations**: Butter-smooth 60fps animations with spring-back effects
15
+ - 💊 **TypeScript**: Full TypeScript support with comprehensive type definitions
16
+ - ðŸŠķ **Zero Dependencies**: No external dependencies except React
17
+ - ⚙ïļ **Highly Configurable**: Customizable thresholds, velocities, and animations
18
+ - 🎭 **Rotation Effects**: Optional card rotation during drag for realistic feel
19
+
20
+ ## ðŸ“Ķ Installation
21
+
22
+ ```bash
23
+ npm install swipeon-react
24
+ ```
25
+
26
+ ```bash
27
+ yarn add swipeon-react
28
+ ```
29
+
30
+ ```bash
31
+ pnpm add swipeon-react
32
+ ```
33
+
34
+ ## 🚀 Quick Start
35
+
36
+ ```tsx
37
+ import React from 'react';
38
+ import { SwipeCard } from 'swipeon-react';
39
+
40
+ function App() {
41
+ return (
42
+ <SwipeCard
43
+ onSwipeLeft={() => console.log('Swiped left! 👈')}
44
+ onSwipeRight={() => console.log('Swiped right! 👉')}
45
+ onSwipeUp={() => console.log('Swiped up! 👆')}
46
+ onSwipeDown={() => console.log('Swiped down! 👇')}
47
+ >
48
+ <div style={{ padding: '40px', background: '#fff', borderRadius: '10px' }}>
49
+ <h2>Swipe me in any direction!</h2>
50
+ <p>Works with mouse and touch</p>
51
+ </div>
52
+ </SwipeCard>
53
+ );
54
+ }
55
+
56
+ export default App;
57
+ ```
58
+
59
+ ## 📖 API Reference
60
+
61
+ ### SwipeCard Component
62
+
63
+ #### Props
64
+
65
+ | Prop | Type | Default | Description |
66
+ |------|------|---------|-------------|
67
+ | `children` | `ReactNode` | **required** | Content to render inside the card |
68
+ | `onSwipeLeft` | `() => void` | `undefined` | Callback triggered when card is swiped left |
69
+ | `onSwipeRight` | `() => void` | `undefined` | Callback triggered when card is swiped right |
70
+ | `onSwipeUp` | `() => void` | `undefined` | Callback triggered when card is swiped up |
71
+ | `onSwipeDown` | `() => void` | `undefined` | Callback triggered when card is swiped down |
72
+ | `onSwipeStart` | `() => void` | `undefined` | Callback triggered when swipe starts |
73
+ | `onSwipeEnd` | `() => void` | `undefined` | Callback triggered when swipe ends |
74
+ | `threshold` | `number` | `100` | Minimum distance (px) required to trigger a swipe |
75
+ | `velocityThreshold` | `number` | `0.5` | Minimum velocity required to trigger a swipe |
76
+ | `maxRotation` | `number` | `15` | Maximum rotation angle (degrees) during drag |
77
+ | `exitDuration` | `number` | `300` | Duration (ms) of the exit animation |
78
+ | `returnDuration` | `number` | `200` | Duration (ms) of the spring-back animation |
79
+ | `enableRotation` | `boolean` | `true` | Enable/disable rotation effect during drag |
80
+ | `className` | `string` | `''` | Additional CSS class name |
81
+ | `style` | `CSSProperties` | `{}` | Additional inline styles |
82
+
83
+ ### useSwipe Hook
84
+
85
+ For advanced use cases, you can use the `useSwipe` hook directly:
86
+
87
+ ```tsx
88
+ import { useSwipe } from 'swipeon-react';
89
+
90
+ function CustomCard() {
91
+ const { ref, transform, opacity, transition, isDragging } = useSwipe(
92
+ {
93
+ onSwipeLeft: () => console.log('Left!'),
94
+ onSwipeRight: () => console.log('Right!'),
95
+ },
96
+ {
97
+ threshold: 100,
98
+ velocityThreshold: 0.5,
99
+ }
100
+ );
101
+
102
+ return (
103
+ <div
104
+ ref={ref}
105
+ style={{
106
+ transform,
107
+ opacity,
108
+ transition,
109
+ cursor: isDragging ? 'grabbing' : 'grab',
110
+ }}
111
+ >
112
+ Your content here
113
+ </div>
114
+ );
115
+ }
116
+ ```
117
+
118
+ #### Hook Return Values
119
+
120
+ | Property | Type | Description |
121
+ |----------|------|-------------|
122
+ | `ref` | `RefObject<HTMLDivElement>` | Ref to attach to your swipeable element |
123
+ | `transform` | `string` | CSS transform value for positioning/rotation |
124
+ | `opacity` | `number` | Opacity value based on drag distance |
125
+ | `transition` | `string` | CSS transition value for animations |
126
+ | `isDragging` | `boolean` | Whether the element is currently being dragged |
127
+
128
+ ## ðŸ’Ą Examples
129
+
130
+ ### Card Stack (Tinder-like)
131
+
132
+ ```tsx
133
+ import React, { useState } from 'react';
134
+ import { SwipeCard } from 'swipeon-react';
135
+
136
+ const cards = [
137
+ { id: 1, name: 'Card 1', image: '/card1.jpg' },
138
+ { id: 2, name: 'Card 2', image: '/card2.jpg' },
139
+ { id: 3, name: 'Card 3', image: '/card3.jpg' },
140
+ ];
141
+
142
+ function CardStack() {
143
+ const [deck, setDeck] = useState(cards);
144
+
145
+ const handleRemove = () => {
146
+ setTimeout(() => {
147
+ setDeck((prev) => prev.slice(0, -1));
148
+ }, 300);
149
+ };
150
+
151
+ if (deck.length === 0) {
152
+ return <div>No more cards!</div>;
153
+ }
154
+
155
+ return (
156
+ <div style={{ position: 'relative', width: '300px', height: '400px' }}>
157
+ {deck.map((card, index) => (
158
+ <SwipeCard
159
+ key={card.id}
160
+ onSwipeLeft={handleRemove}
161
+ onSwipeRight={handleRemove}
162
+ onSwipeUp={handleRemove}
163
+ onSwipeDown={handleRemove}
164
+ style={{
165
+ position: 'absolute',
166
+ width: '100%',
167
+ height: '100%',
168
+ zIndex: deck.length - index,
169
+ }}
170
+ >
171
+ <div style={{
172
+ width: '100%',
173
+ height: '100%',
174
+ background: '#fff',
175
+ borderRadius: '10px',
176
+ boxShadow: '0 4px 8px rgba(0,0,0,0.1)',
177
+ }}>
178
+ <img src={card.image} alt={card.name} style={{ width: '100%' }} />
179
+ <h3>{card.name}</h3>
180
+ </div>
181
+ </SwipeCard>
182
+ ))}
183
+ </div>
184
+ );
185
+ }
186
+ ```
187
+
188
+ ### Custom Thresholds
189
+
190
+ ```tsx
191
+ <SwipeCard
192
+ threshold={150} // Require 150px movement
193
+ velocityThreshold={0.8} // Require faster swipes
194
+ maxRotation={25} // More dramatic rotation
195
+ exitDuration={500} // Slower exit animation
196
+ >
197
+ <YourContent />
198
+ </SwipeCard>
199
+ ```
200
+
201
+ ### Disable Rotation
202
+
203
+ ```tsx
204
+ <SwipeCard
205
+ enableRotation={false}
206
+ onSwipeLeft={() => console.log('Left')}
207
+ onSwipeRight={() => console.log('Right')}
208
+ >
209
+ <YourContent />
210
+ </SwipeCard>
211
+ ```
212
+
213
+ ### Only Horizontal Swipes
214
+
215
+ ```tsx
216
+ <SwipeCard
217
+ onSwipeLeft={() => handleSwipe('left')}
218
+ onSwipeRight={() => handleSwipe('right')}
219
+ // Don't provide onSwipeUp/onSwipeDown
220
+ >
221
+ <YourContent />
222
+ </SwipeCard>
223
+ ```
224
+
225
+ ## ðŸŽĻ Styling
226
+
227
+ The component applies minimal styling by default. You can customize appearance using:
228
+
229
+ 1. **CSS Classes**:
230
+ ```tsx
231
+ <SwipeCard className="my-custom-card">
232
+ <YourContent />
233
+ </SwipeCard>
234
+ ```
235
+
236
+ 2. **Inline Styles**:
237
+ ```tsx
238
+ <SwipeCard
239
+ style={{
240
+ borderRadius: '20px',
241
+ boxShadow: '0 10px 40px rgba(0,0,0,0.2)'
242
+ }}
243
+ >
244
+ <YourContent />
245
+ </SwipeCard>
246
+ ```
247
+
248
+ 3. **Styled Components / Emotion**:
249
+ ```tsx
250
+ const StyledSwipeCard = styled(SwipeCard)`
251
+ border-radius: 20px;
252
+ background: white;
253
+ box-shadow: 0 10px 40px rgba(0,0,0,0.2);
254
+ `;
255
+ ```
256
+
257
+ ## ⚡ Performance Tips
258
+
259
+ 1. **Use `key` prop**: When rendering multiple cards, always provide a unique `key`
260
+ 2. **Optimize callbacks**: Use `useCallback` for swipe handlers to prevent unnecessary re-renders
261
+ 3. **Limit card stack**: Don't render more than 3-5 cards in a stack
262
+ 4. **Optimize images**: Use appropriately sized images to improve performance
263
+ 5. **CSS containment**: The library uses `will-change` and `transform3d` for hardware acceleration
264
+
265
+ ## 🌐 Browser Support
266
+
267
+ - Chrome (latest)
268
+ - Firefox (latest)
269
+ - Safari (latest)
270
+ - Edge (latest)
271
+ - Mobile browsers (iOS Safari, Chrome Mobile)
272
+
273
+ ## ðŸ“ą Running the Demo
274
+
275
+ ```bash
276
+ # Clone the repository
277
+ git clone https://github.com/react-forge/swipeon-react.git
278
+ cd swipeon-react
279
+
280
+ # Install dependencies
281
+ npm install
282
+
283
+ # Run the demo
284
+ cd example
285
+ npm install
286
+ npm run dev
287
+ ```
288
+
289
+ The demo will open at `http://localhost:3000`
290
+
291
+ ## 🛠ïļ Development
292
+
293
+ ```bash
294
+ # Install dependencies
295
+ npm install
296
+
297
+ # Build the library
298
+ npm run build
299
+
300
+ # Watch mode for development
301
+ npm run dev
302
+ ```
303
+
304
+ ## ðŸĪ Contributing
305
+
306
+ Contributions are welcome! Please feel free to submit a Pull Request.
307
+
308
+ 1. Fork the repository
309
+ 2. Create your feature branch (`git checkout -b feature/AmazingFeature`)
310
+ 3. Commit your changes (`git commit -m 'Add some AmazingFeature'`)
311
+ 4. Push to the branch (`git push origin feature/AmazingFeature`)
312
+ 5. Open a Pull Request
313
+
314
+ ## 📄 License
315
+
316
+ MIT ÂĐ [react-forge](https://github.com/react-forge)
317
+
318
+ ## 🙏 Acknowledgments
319
+
320
+ - Inspired by Tinder's swipe interface
321
+ - Built with React and TypeScript
322
+ - Uses Pointer Events API for unified input handling
323
+
324
+ ## 📧 Support
325
+
326
+ - 🐛 [Report a bug](https://github.com/react-forge/swipeon-react/issues)
327
+ - ðŸ’Ą [Request a feature](https://github.com/react-forge/swipeon-react/issues)
328
+ - 📖 [Read the docs](https://github.com/react-forge/swipeon-react#readme)
329
+
330
+ ---
331
+
332
+ Made with âĪïļ by [react-forge](https://github.com/react-forge)
package/dist/index.cjs ADDED
@@ -0,0 +1,2 @@
1
+ var e=Object.create,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,i=Object.getPrototypeOf,a=Object.prototype.hasOwnProperty,o=(e,i,o,s)=>{if(i&&typeof i==`object`||typeof i==`function`)for(var c=r(i),l=0,u=c.length,d;l<u;l++)d=c[l],!a.call(e,d)&&d!==o&&t(e,d,{get:(e=>i[e]).bind(null,d),enumerable:!(s=n(i,d))||s.enumerable});return e},s=(n,r,a)=>(a=n==null?{}:e(i(n)),o(r||!n||!n.__esModule?t(a,`default`,{value:n,enumerable:!0}):a,n));let c=require(`react`);c=s(c);const l=(e,t)=>t===0?0:Math.abs(e/t),u=(e,t,n=50)=>{let r=Math.abs(e),i=Math.abs(t);return r<n&&i<n?null:r>i?e>0?`right`:`left`:t>0?`down`:`up`},d=(e,t=15,n=300)=>{let r=e/n*t;return Math.max(-t,Math.min(t,r))},f=(e,t,n=100)=>{let r=1-Math.sqrt(e*e+t*t)/(n*3);return Math.max(.5,Math.min(1,r))},p=e=>`touches`in e&&e.touches&&e.touches.length>0?{x:e.touches[0].clientX,y:e.touches[0].clientY}:`clientX`in e&&`clientY`in e?{x:e.clientX,y:e.clientY}:{x:0,y:0},m={threshold:100,velocityThreshold:.5,maxRotation:15,exitDuration:300,returnDuration:200,enableRotation:!0},h=(e={},t={})=>{let{threshold:n,velocityThreshold:r,maxRotation:i,exitDuration:a,returnDuration:o,enableRotation:s}={...m,...t},h=(0,c.useRef)(null),g=(0,c.useRef)(null),[_,v]=(0,c.useState)({isDragging:!1,startX:0,startY:0,currentX:0,currentY:0,deltaX:0,deltaY:0,velocity:0,direction:null,startTime:0}),[y,b]=(0,c.useState)(`translate3d(0px, 0px, 0px) rotate(0deg)`),[x,S]=(0,c.useState)(1),[C,w]=(0,c.useState)(`none`),T=(0,c.useCallback)(t=>{let n=p(t),r=Date.now();v({isDragging:!0,startX:n.x,startY:n.y,currentX:n.x,currentY:n.y,deltaX:0,deltaY:0,velocity:0,direction:null,startTime:r}),w(`none`),e.onSwipeStart&&e.onSwipeStart()},[e]),E=(0,c.useCallback)(e=>{if(!_.isDragging)return;let t=p(e),r=t.x-_.startX,a=t.y-_.startY;v(e=>({...e,currentX:t.x,currentY:t.y,deltaX:r,deltaY:a})),g.current&&cancelAnimationFrame(g.current),g.current=requestAnimationFrame(()=>{let e=s?d(r,i):0,t=f(r,a,n);b(`translate3d(${r}px, ${a}px, 0px) rotate(${e}deg)`),S(t)})},[_.isDragging,_.startX,_.startY,s,i,n]),D=(0,c.useCallback)(()=>{if(!_.isDragging)return;let{deltaX:t,deltaY:c,startTime:f}=_,p=Date.now()-f,m=Math.sqrt(t*t+c*c),h=l(m,p),g=u(t,c,n/2);if((m>=n||h>=r)&&g){w(`transform ${a}ms ease-out, opacity ${a}ms ease-out`);let n=t*2;b(`translate3d(${n}px, ${c*2}px, 0px) rotate(${s?d(n,i*2):0}deg)`),S(0),setTimeout(()=>{switch(g){case`left`:e.onSwipeLeft?.();break;case`right`:e.onSwipeRight?.();break;case`up`:e.onSwipeUp?.();break;case`down`:e.onSwipeDown?.();break}e.onSwipeEnd&&e.onSwipeEnd(),setTimeout(()=>{w(`none`),b(`translate3d(0px, 0px, 0px) rotate(0deg)`),S(1)},50)},a)}else w(`transform ${o}ms cubic-bezier(0.175, 0.885, 0.32, 1.275), opacity ${o}ms ease-out`),b(`translate3d(0px, 0px, 0px) rotate(0deg)`),S(1),e.onSwipeEnd&&e.onSwipeEnd();v(e=>({...e,isDragging:!1}))},[_,n,r,a,o,s,i,e]);return(0,c.useEffect)(()=>{let e=h.current;if(!e)return;let t=e=>{T(e)},n=e=>{_.isDragging&&E(e)},r=()=>{D()};return e.addEventListener(`pointerdown`,t),_.isDragging&&(document.addEventListener(`pointermove`,n),document.addEventListener(`pointerup`,r),document.addEventListener(`pointercancel`,r)),()=>{e.removeEventListener(`pointerdown`,t),document.removeEventListener(`pointermove`,n),document.removeEventListener(`pointerup`,r),document.removeEventListener(`pointercancel`,r),g.current&&cancelAnimationFrame(g.current)}},[_.isDragging,T,E,D]),{ref:h,transform:y,opacity:x,transition:C,isDragging:_.isDragging}},g=({children:e,className:t=``,style:n={},onSwipeLeft:r,onSwipeRight:i,onSwipeUp:a,onSwipeDown:o,onSwipeStart:s,onSwipeEnd:l,threshold:u=100,velocityThreshold:d=.5,maxRotation:f=15,exitDuration:p=300,returnDuration:m=200,enableRotation:g=!0})=>{let{ref:_,transform:v,opacity:y,transition:b,isDragging:x}=h({onSwipeLeft:r,onSwipeRight:i,onSwipeUp:a,onSwipeDown:o,onSwipeStart:s,onSwipeEnd:l},{threshold:u,velocityThreshold:d,maxRotation:f,exitDuration:p,returnDuration:m,enableRotation:g}),S={...n,transform:v,opacity:y,transition:b,touchAction:`none`,userSelect:`none`,WebkitUserSelect:`none`,cursor:x?`grabbing`:`grab`,willChange:x?`transform, opacity`:`auto`,position:`relative`};return c.default.createElement(`div`,{ref:_,className:`swipeon-card ${t}`,style:S},e)};exports.SwipeCard=g,exports.useSwipe=h;
2
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs","names":["DEFAULT_CONFIG: Required<SwipeConfig>","SwipeCard: React.FC<SwipeCardProps>","cardStyle: CSSProperties"],"sources":["../src/utils/helpers.ts","../src/hooks/useSwipe.ts","../src/components/SwipeCard.tsx"],"sourcesContent":["import { SwipeDirection } from '../types';\n\n/**\n * Calculate the distance between two points\n */\nexport const getDistance = (x1: number, y1: number, x2: number, y2: number): number => {\n const dx = x2 - x1;\n const dy = y2 - y1;\n return Math.sqrt(dx * dx + dy * dy);\n};\n\n/**\n * Calculate velocity based on distance and time\n */\nexport const calculateVelocity = (distance: number, time: number): number => {\n if (time === 0) return 0;\n return Math.abs(distance / time);\n};\n\n/**\n * Determine the swipe direction based on deltas\n */\nexport const getSwipeDirection = (\n deltaX: number,\n deltaY: number,\n threshold: number = 50\n): SwipeDirection | null => {\n const absDeltaX = Math.abs(deltaX);\n const absDeltaY = Math.abs(deltaY);\n\n // Need minimum movement\n if (absDeltaX < threshold && absDeltaY < threshold) {\n return null;\n }\n\n // Determine primary direction\n if (absDeltaX > absDeltaY) {\n return deltaX > 0 ? 'right' : 'left';\n } else {\n return deltaY > 0 ? 'down' : 'up';\n }\n};\n\n/**\n * Calculate rotation angle based on horizontal movement\n */\nexport const calculateRotation = (\n deltaX: number,\n maxRotation: number = 15,\n containerWidth: number = 300\n): number => {\n const rotation = (deltaX / containerWidth) * maxRotation;\n return Math.max(-maxRotation, Math.min(maxRotation, rotation));\n};\n\n/**\n * Calculate opacity based on drag distance\n */\nexport const calculateOpacity = (\n deltaX: number,\n deltaY: number,\n threshold: number = 100\n): number => {\n const distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);\n const opacity = 1 - distance / (threshold * 3);\n return Math.max(0.5, Math.min(1, opacity));\n};\n\n/**\n * Clamp a value between min and max\n */\nexport const clamp = (value: number, min: number, max: number): number => {\n return Math.max(min, Math.min(max, value));\n};\n\n/**\n * Get touch/pointer coordinates from event\n */\nexport const getEventCoordinates = (\n event: TouchEvent | PointerEvent | MouseEvent | any\n): { x: number; y: number } => {\n if ('touches' in event && event.touches && event.touches.length > 0) {\n return {\n x: event.touches[0].clientX,\n y: event.touches[0].clientY,\n };\n }\n \n if ('clientX' in event && 'clientY' in event) {\n return {\n x: event.clientX,\n y: event.clientY,\n };\n }\n \n return { x: 0, y: 0 };\n};\n\n","import { useRef, useState, useCallback, useEffect } from 'react';\nimport { SwipeConfig, SwipeCallbacks, GestureState, UseSwipeReturn } from '../types';\nimport {\n getSwipeDirection,\n calculateRotation,\n calculateOpacity,\n calculateVelocity,\n getEventCoordinates,\n} from '../utils/helpers';\n\nconst DEFAULT_CONFIG: Required<SwipeConfig> = {\n threshold: 100,\n velocityThreshold: 0.5,\n maxRotation: 15,\n exitDuration: 300,\n returnDuration: 200,\n enableRotation: true,\n};\n\nexport const useSwipe = (\n callbacks: SwipeCallbacks = {},\n config: SwipeConfig = {}\n): UseSwipeReturn => {\n const mergedConfig = { ...DEFAULT_CONFIG, ...config };\n const {\n threshold,\n velocityThreshold,\n maxRotation,\n exitDuration,\n returnDuration,\n enableRotation,\n } = mergedConfig;\n\n const ref = useRef<HTMLDivElement>(null);\n const animationFrameRef = useRef<number | null>(null);\n const [gestureState, setGestureState] = useState<GestureState>({\n isDragging: false,\n startX: 0,\n startY: 0,\n currentX: 0,\n currentY: 0,\n deltaX: 0,\n deltaY: 0,\n velocity: 0,\n direction: null,\n startTime: 0,\n });\n\n const [transform, setTransform] = useState('translate3d(0px, 0px, 0px) rotate(0deg)');\n const [opacity, setOpacity] = useState(1);\n const [transition, setTransition] = useState('none');\n\n // Handle swipe start\n const handleSwipeStart = useCallback(\n (event: PointerEvent | TouchEvent | MouseEvent) => {\n const coords = getEventCoordinates(event as any);\n const now = Date.now();\n\n setGestureState({\n isDragging: true,\n startX: coords.x,\n startY: coords.y,\n currentX: coords.x,\n currentY: coords.y,\n deltaX: 0,\n deltaY: 0,\n velocity: 0,\n direction: null,\n startTime: now,\n });\n\n setTransition('none');\n \n if (callbacks.onSwipeStart) {\n callbacks.onSwipeStart();\n }\n },\n [callbacks]\n );\n\n // Handle swipe move\n const handleSwipeMove = useCallback(\n (event: PointerEvent | TouchEvent | MouseEvent) => {\n if (!gestureState.isDragging) return;\n\n const coords = getEventCoordinates(event as any);\n const deltaX = coords.x - gestureState.startX;\n const deltaY = coords.y - gestureState.startY;\n\n // Update gesture state\n setGestureState((prev: GestureState) => ({\n ...prev,\n currentX: coords.x,\n currentY: coords.y,\n deltaX,\n deltaY,\n }));\n\n // Use RAF for smooth updates\n if (animationFrameRef.current) {\n cancelAnimationFrame(animationFrameRef.current);\n }\n\n animationFrameRef.current = requestAnimationFrame(() => {\n const rotation = enableRotation ? calculateRotation(deltaX, maxRotation) : 0;\n const newOpacity = calculateOpacity(deltaX, deltaY, threshold);\n\n setTransform(\n `translate3d(${deltaX}px, ${deltaY}px, 0px) rotate(${rotation}deg)`\n );\n setOpacity(newOpacity);\n });\n },\n [gestureState.isDragging, gestureState.startX, gestureState.startY, enableRotation, maxRotation, threshold]\n );\n\n // Handle swipe end\n const handleSwipeEnd = useCallback(() => {\n if (!gestureState.isDragging) return;\n\n const { deltaX, deltaY, startTime } = gestureState;\n const timeDelta = Date.now() - startTime;\n const distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);\n const velocity = calculateVelocity(distance, timeDelta);\n\n const direction = getSwipeDirection(deltaX, deltaY, threshold / 2);\n const shouldSwipe =\n distance >= threshold || velocity >= velocityThreshold;\n\n if (shouldSwipe && direction) {\n // Execute swipe\n setTransition(`transform ${exitDuration}ms ease-out, opacity ${exitDuration}ms ease-out`);\n \n // Calculate exit position (move far enough off screen)\n const multiplier = 2;\n const exitX = deltaX * multiplier;\n const exitY = deltaY * multiplier;\n const rotation = enableRotation ? calculateRotation(exitX, maxRotation * 2) : 0;\n\n setTransform(\n `translate3d(${exitX}px, ${exitY}px, 0px) rotate(${rotation}deg)`\n );\n setOpacity(0);\n\n // Trigger callback after animation\n setTimeout(() => {\n switch (direction) {\n case 'left':\n callbacks.onSwipeLeft?.();\n break;\n case 'right':\n callbacks.onSwipeRight?.();\n break;\n case 'up':\n callbacks.onSwipeUp?.();\n break;\n case 'down':\n callbacks.onSwipeDown?.();\n break;\n }\n \n if (callbacks.onSwipeEnd) {\n callbacks.onSwipeEnd();\n }\n\n // Reset after callback\n setTimeout(() => {\n setTransition('none');\n setTransform('translate3d(0px, 0px, 0px) rotate(0deg)');\n setOpacity(1);\n }, 50);\n }, exitDuration);\n } else {\n // Spring back\n setTransition(\n `transform ${returnDuration}ms cubic-bezier(0.175, 0.885, 0.32, 1.275), opacity ${returnDuration}ms ease-out`\n );\n setTransform('translate3d(0px, 0px, 0px) rotate(0deg)');\n setOpacity(1);\n\n if (callbacks.onSwipeEnd) {\n callbacks.onSwipeEnd();\n }\n }\n\n setGestureState((prev: GestureState) => ({ ...prev, isDragging: false }));\n }, [\n gestureState,\n threshold,\n velocityThreshold,\n exitDuration,\n returnDuration,\n enableRotation,\n maxRotation,\n callbacks,\n ]);\n\n // Attach event listeners\n useEffect(() => {\n const element = ref.current;\n if (!element) return;\n\n const handlePointerDown = (e: PointerEvent) => {\n handleSwipeStart(e);\n };\n\n const handlePointerMove = (e: PointerEvent) => {\n if (gestureState.isDragging) {\n handleSwipeMove(e);\n }\n };\n\n const handlePointerUp = () => {\n handleSwipeEnd();\n };\n\n element.addEventListener('pointerdown', handlePointerDown);\n\n if (gestureState.isDragging) {\n document.addEventListener('pointermove', handlePointerMove);\n document.addEventListener('pointerup', handlePointerUp);\n document.addEventListener('pointercancel', handlePointerUp);\n }\n\n return () => {\n element.removeEventListener('pointerdown', handlePointerDown);\n document.removeEventListener('pointermove', handlePointerMove);\n document.removeEventListener('pointerup', handlePointerUp);\n document.removeEventListener('pointercancel', handlePointerUp);\n \n if (animationFrameRef.current) {\n cancelAnimationFrame(animationFrameRef.current);\n }\n };\n }, [gestureState.isDragging, handleSwipeStart, handleSwipeMove, handleSwipeEnd]);\n\n return {\n ref,\n transform,\n opacity,\n transition,\n isDragging: gestureState.isDragging,\n };\n};\n\n","import React, { CSSProperties } from 'react';\nimport { useSwipe } from '../hooks/useSwipe';\nimport { SwipeCardProps } from '../types';\n\n/**\n * SwipeCard Component\n * \n * A performant swipeable card component with smooth animations.\n * Supports swipe in all four directions: left, right, up, and down.\n * \n * @example\n * ```tsx\n * <SwipeCard\n * onSwipeLeft={() => console.log('Swiped left')}\n * onSwipeRight={() => console.log('Swiped right')}\n * threshold={100}\n * >\n * <div>Your content here</div>\n * </SwipeCard>\n * ```\n */\nexport const SwipeCard: React.FC<SwipeCardProps> = ({\n children,\n className = '',\n style = {},\n onSwipeLeft,\n onSwipeRight,\n onSwipeUp,\n onSwipeDown,\n onSwipeStart,\n onSwipeEnd,\n threshold = 100,\n velocityThreshold = 0.5,\n maxRotation = 15,\n exitDuration = 300,\n returnDuration = 200,\n enableRotation = true,\n}) => {\n const callbacks = {\n onSwipeLeft,\n onSwipeRight,\n onSwipeUp,\n onSwipeDown,\n onSwipeStart,\n onSwipeEnd,\n };\n\n const config = {\n threshold,\n velocityThreshold,\n maxRotation,\n exitDuration,\n returnDuration,\n enableRotation,\n };\n\n const { ref, transform, opacity, transition, isDragging } = useSwipe(callbacks, config);\n\n const cardStyle: CSSProperties = {\n ...style,\n transform,\n opacity,\n transition,\n touchAction: 'none', // Prevent default touch behaviors\n userSelect: 'none', // Prevent text selection during drag\n WebkitUserSelect: 'none',\n cursor: isDragging ? 'grabbing' : 'grab',\n willChange: isDragging ? 'transform, opacity' : 'auto',\n position: 'relative',\n };\n\n return (\n <div\n ref={ref}\n className={`swipeon-card ${className}`}\n style={cardStyle}\n >\n {children}\n </div>\n );\n};\n\nexport default SwipeCard;\n\n"],"mappings":"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"}
@@ -0,0 +1,100 @@
1
+ import React$1, { CSSProperties, ReactNode } from "react";
2
+
3
+ //#region src/types/index.d.ts
4
+
5
+ /**
6
+ * Swipe direction types
7
+ */
8
+ type SwipeDirection = 'left' | 'right' | 'up' | 'down';
9
+ /**
10
+ * Callback function signatures for swipe events
11
+ */
12
+ interface SwipeCallbacks {
13
+ onSwipeLeft?: () => void;
14
+ onSwipeRight?: () => void;
15
+ onSwipeUp?: () => void;
16
+ onSwipeDown?: () => void;
17
+ onSwipeStart?: () => void;
18
+ onSwipeEnd?: () => void;
19
+ }
20
+ /**
21
+ * Configuration options for swipe behavior
22
+ */
23
+ interface SwipeConfig {
24
+ /** Minimum distance (in pixels) required to trigger a swipe */
25
+ threshold?: number;
26
+ /** Minimum velocity required to trigger a swipe */
27
+ velocityThreshold?: number;
28
+ /** Maximum rotation angle in degrees during drag */
29
+ maxRotation?: number;
30
+ /** Duration of the exit animation in milliseconds */
31
+ exitDuration?: number;
32
+ /** Duration of the spring-back animation in milliseconds */
33
+ returnDuration?: number;
34
+ /** Enable/disable rotation effect during drag */
35
+ enableRotation?: boolean;
36
+ }
37
+ /**
38
+ * Props for the SwipeCard component
39
+ */
40
+ interface SwipeCardProps extends SwipeCallbacks, SwipeConfig {
41
+ /** Content to render inside the card */
42
+ children: ReactNode;
43
+ /** Additional CSS class name */
44
+ className?: string;
45
+ /** Additional inline styles */
46
+ style?: CSSProperties;
47
+ /** Unique key for the card (useful in lists) */
48
+ cardKey?: string | number;
49
+ }
50
+ /**
51
+ * Internal gesture state for tracking swipe progress
52
+ */
53
+ interface GestureState {
54
+ isDragging: boolean;
55
+ startX: number;
56
+ startY: number;
57
+ currentX: number;
58
+ currentY: number;
59
+ deltaX: number;
60
+ deltaY: number;
61
+ velocity: number;
62
+ direction: SwipeDirection | null;
63
+ startTime: number;
64
+ }
65
+ /**
66
+ * Return type of the useSwipe hook
67
+ */
68
+ interface UseSwipeReturn {
69
+ ref: React.RefObject<HTMLDivElement>;
70
+ transform: string;
71
+ opacity: number;
72
+ transition: string;
73
+ isDragging: boolean;
74
+ }
75
+ //#endregion
76
+ //#region src/components/SwipeCard.d.ts
77
+ /**
78
+ * SwipeCard Component
79
+ *
80
+ * A performant swipeable card component with smooth animations.
81
+ * Supports swipe in all four directions: left, right, up, and down.
82
+ *
83
+ * @example
84
+ * ```tsx
85
+ * <SwipeCard
86
+ * onSwipeLeft={() => console.log('Swiped left')}
87
+ * onSwipeRight={() => console.log('Swiped right')}
88
+ * threshold={100}
89
+ * >
90
+ * <div>Your content here</div>
91
+ * </SwipeCard>
92
+ * ```
93
+ */
94
+ declare const SwipeCard: React$1.FC<SwipeCardProps>;
95
+ //#endregion
96
+ //#region src/hooks/useSwipe.d.ts
97
+ declare const useSwipe: (callbacks?: SwipeCallbacks, config?: SwipeConfig) => UseSwipeReturn;
98
+ //#endregion
99
+ export { type GestureState, type SwipeCallbacks, SwipeCard, type SwipeCardProps, type SwipeConfig, type SwipeDirection, type UseSwipeReturn, useSwipe };
100
+ //# sourceMappingURL=index.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.cts","names":[],"sources":["../src/types/index.ts","../src/components/SwipeCard.tsx","../src/hooks/useSwipe.ts"],"sourcesContent":[],"mappings":";;;;;;AAKA;AAKiB,KALL,cAAA,GAKmB,MAAA,GAAA,OAAA,GAAA,IAAA,GAAA,MAAA;AAY/B;AAkBA;;AAMU,UApCO,cAAA,CAoCP;EAN8B,WAAA,CAAA,EAAA,GAAA,GAAA,IAAA;EAAgB,YAAA,CAAA,EAAA,GAAA,GAAA,IAAA;EAAW,SAAA,CAAA,EAAA,GAAA,GAAA,IAAA;EAclD,WAAA,CAAA,EAAA,GAAY,GAAA,IAAA;EAgBZ,YAAA,CAAA,EAAA,GAAc,GAAA,IAAA;;;;ACjD/B;;UDCiB,WAAA;;EEHJ,SAAA,CAAA,EAgOZ,MAAA;EA/NY;EACH,iBAAA,CAAA,EAAA,MAAA;EACP;EA6NF,WAAA,CAAA,EAAA,MAAA;;;;;;;;;;;UF3MgB,cAAA,SAAuB,gBAAgB;;YAE5C;;;;UAIF;;;;;;;UAQO,YAAA;;;;;;;;;aASJ;;;;;;UAOI,cAAA;OACV,KAAA,CAAM,UAAU;;;;;;;;;AAlEvB;AAKA;AAYA;AAkBA;;;;;;AAcA;AAgBA;;;;ACjDA;;cAAa,WAAW,OAAA,CAAM,GAAG;;;cCFpB,uBACA,yBACH,gBACP"}
@@ -0,0 +1,100 @@
1
+ import React$1, { CSSProperties, ReactNode } from "react";
2
+
3
+ //#region src/types/index.d.ts
4
+
5
+ /**
6
+ * Swipe direction types
7
+ */
8
+ type SwipeDirection = 'left' | 'right' | 'up' | 'down';
9
+ /**
10
+ * Callback function signatures for swipe events
11
+ */
12
+ interface SwipeCallbacks {
13
+ onSwipeLeft?: () => void;
14
+ onSwipeRight?: () => void;
15
+ onSwipeUp?: () => void;
16
+ onSwipeDown?: () => void;
17
+ onSwipeStart?: () => void;
18
+ onSwipeEnd?: () => void;
19
+ }
20
+ /**
21
+ * Configuration options for swipe behavior
22
+ */
23
+ interface SwipeConfig {
24
+ /** Minimum distance (in pixels) required to trigger a swipe */
25
+ threshold?: number;
26
+ /** Minimum velocity required to trigger a swipe */
27
+ velocityThreshold?: number;
28
+ /** Maximum rotation angle in degrees during drag */
29
+ maxRotation?: number;
30
+ /** Duration of the exit animation in milliseconds */
31
+ exitDuration?: number;
32
+ /** Duration of the spring-back animation in milliseconds */
33
+ returnDuration?: number;
34
+ /** Enable/disable rotation effect during drag */
35
+ enableRotation?: boolean;
36
+ }
37
+ /**
38
+ * Props for the SwipeCard component
39
+ */
40
+ interface SwipeCardProps extends SwipeCallbacks, SwipeConfig {
41
+ /** Content to render inside the card */
42
+ children: ReactNode;
43
+ /** Additional CSS class name */
44
+ className?: string;
45
+ /** Additional inline styles */
46
+ style?: CSSProperties;
47
+ /** Unique key for the card (useful in lists) */
48
+ cardKey?: string | number;
49
+ }
50
+ /**
51
+ * Internal gesture state for tracking swipe progress
52
+ */
53
+ interface GestureState {
54
+ isDragging: boolean;
55
+ startX: number;
56
+ startY: number;
57
+ currentX: number;
58
+ currentY: number;
59
+ deltaX: number;
60
+ deltaY: number;
61
+ velocity: number;
62
+ direction: SwipeDirection | null;
63
+ startTime: number;
64
+ }
65
+ /**
66
+ * Return type of the useSwipe hook
67
+ */
68
+ interface UseSwipeReturn {
69
+ ref: React.RefObject<HTMLDivElement>;
70
+ transform: string;
71
+ opacity: number;
72
+ transition: string;
73
+ isDragging: boolean;
74
+ }
75
+ //#endregion
76
+ //#region src/components/SwipeCard.d.ts
77
+ /**
78
+ * SwipeCard Component
79
+ *
80
+ * A performant swipeable card component with smooth animations.
81
+ * Supports swipe in all four directions: left, right, up, and down.
82
+ *
83
+ * @example
84
+ * ```tsx
85
+ * <SwipeCard
86
+ * onSwipeLeft={() => console.log('Swiped left')}
87
+ * onSwipeRight={() => console.log('Swiped right')}
88
+ * threshold={100}
89
+ * >
90
+ * <div>Your content here</div>
91
+ * </SwipeCard>
92
+ * ```
93
+ */
94
+ declare const SwipeCard: React$1.FC<SwipeCardProps>;
95
+ //#endregion
96
+ //#region src/hooks/useSwipe.d.ts
97
+ declare const useSwipe: (callbacks?: SwipeCallbacks, config?: SwipeConfig) => UseSwipeReturn;
98
+ //#endregion
99
+ export { type GestureState, type SwipeCallbacks, SwipeCard, type SwipeCardProps, type SwipeConfig, type SwipeDirection, type UseSwipeReturn, useSwipe };
100
+ //# sourceMappingURL=index.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../src/types/index.ts","../src/components/SwipeCard.tsx","../src/hooks/useSwipe.ts"],"sourcesContent":[],"mappings":";;;;;;AAKA;AAKiB,KALL,cAAA,GAKmB,MAAA,GAAA,OAAA,GAAA,IAAA,GAAA,MAAA;AAY/B;AAkBA;;AAMU,UApCO,cAAA,CAoCP;EAN8B,WAAA,CAAA,EAAA,GAAA,GAAA,IAAA;EAAgB,YAAA,CAAA,EAAA,GAAA,GAAA,IAAA;EAAW,SAAA,CAAA,EAAA,GAAA,GAAA,IAAA;EAclD,WAAA,CAAA,EAAA,GAAY,GAAA,IAAA;EAgBZ,YAAA,CAAA,EAAA,GAAc,GAAA,IAAA;;;;ACjD/B;;UDCiB,WAAA;;EEHJ,SAAA,CAAA,EAgOZ,MAAA;EA/NY;EACH,iBAAA,CAAA,EAAA,MAAA;EACP;EA6NF,WAAA,CAAA,EAAA,MAAA;;;;;;;;;;;UF3MgB,cAAA,SAAuB,gBAAgB;;YAE5C;;;;UAIF;;;;;;;UAQO,YAAA;;;;;;;;;aASJ;;;;;;UAOI,cAAA;OACV,KAAA,CAAM,UAAU;;;;;;;;;AAlEvB;AAKA;AAYA;AAkBA;;;;;;AAcA;AAgBA;;;;ACjDA;;cAAa,WAAW,OAAA,CAAM,GAAG;;;cCFpB,uBACA,yBACH,gBACP"}
package/dist/index.mjs ADDED
@@ -0,0 +1,2 @@
1
+ import e,{useCallback as t,useEffect as n,useRef as r,useState as i}from"react";const a=(e,t)=>t===0?0:Math.abs(e/t),o=(e,t,n=50)=>{let r=Math.abs(e),i=Math.abs(t);return r<n&&i<n?null:r>i?e>0?`right`:`left`:t>0?`down`:`up`},s=(e,t=15,n=300)=>{let r=e/n*t;return Math.max(-t,Math.min(t,r))},c=(e,t,n=100)=>{let r=1-Math.sqrt(e*e+t*t)/(n*3);return Math.max(.5,Math.min(1,r))},l=e=>`touches`in e&&e.touches&&e.touches.length>0?{x:e.touches[0].clientX,y:e.touches[0].clientY}:`clientX`in e&&`clientY`in e?{x:e.clientX,y:e.clientY}:{x:0,y:0},u={threshold:100,velocityThreshold:.5,maxRotation:15,exitDuration:300,returnDuration:200,enableRotation:!0},d=(e={},d={})=>{let{threshold:f,velocityThreshold:p,maxRotation:m,exitDuration:h,returnDuration:g,enableRotation:_}={...u,...d},v=r(null),y=r(null),[b,x]=i({isDragging:!1,startX:0,startY:0,currentX:0,currentY:0,deltaX:0,deltaY:0,velocity:0,direction:null,startTime:0}),[S,C]=i(`translate3d(0px, 0px, 0px) rotate(0deg)`),[w,T]=i(1),[E,D]=i(`none`),O=t(t=>{let n=l(t),r=Date.now();x({isDragging:!0,startX:n.x,startY:n.y,currentX:n.x,currentY:n.y,deltaX:0,deltaY:0,velocity:0,direction:null,startTime:r}),D(`none`),e.onSwipeStart&&e.onSwipeStart()},[e]),k=t(e=>{if(!b.isDragging)return;let t=l(e),n=t.x-b.startX,r=t.y-b.startY;x(e=>({...e,currentX:t.x,currentY:t.y,deltaX:n,deltaY:r})),y.current&&cancelAnimationFrame(y.current),y.current=requestAnimationFrame(()=>{let e=_?s(n,m):0,t=c(n,r,f);C(`translate3d(${n}px, ${r}px, 0px) rotate(${e}deg)`),T(t)})},[b.isDragging,b.startX,b.startY,_,m,f]),A=t(()=>{if(!b.isDragging)return;let{deltaX:t,deltaY:n,startTime:r}=b,i=Date.now()-r,c=Math.sqrt(t*t+n*n),l=a(c,i),u=o(t,n,f/2);if((c>=f||l>=p)&&u){D(`transform ${h}ms ease-out, opacity ${h}ms ease-out`);let r=t*2;C(`translate3d(${r}px, ${n*2}px, 0px) rotate(${_?s(r,m*2):0}deg)`),T(0),setTimeout(()=>{switch(u){case`left`:e.onSwipeLeft?.();break;case`right`:e.onSwipeRight?.();break;case`up`:e.onSwipeUp?.();break;case`down`:e.onSwipeDown?.();break}e.onSwipeEnd&&e.onSwipeEnd(),setTimeout(()=>{D(`none`),C(`translate3d(0px, 0px, 0px) rotate(0deg)`),T(1)},50)},h)}else D(`transform ${g}ms cubic-bezier(0.175, 0.885, 0.32, 1.275), opacity ${g}ms ease-out`),C(`translate3d(0px, 0px, 0px) rotate(0deg)`),T(1),e.onSwipeEnd&&e.onSwipeEnd();x(e=>({...e,isDragging:!1}))},[b,f,p,h,g,_,m,e]);return n(()=>{let e=v.current;if(!e)return;let t=e=>{O(e)},n=e=>{b.isDragging&&k(e)},r=()=>{A()};return e.addEventListener(`pointerdown`,t),b.isDragging&&(document.addEventListener(`pointermove`,n),document.addEventListener(`pointerup`,r),document.addEventListener(`pointercancel`,r)),()=>{e.removeEventListener(`pointerdown`,t),document.removeEventListener(`pointermove`,n),document.removeEventListener(`pointerup`,r),document.removeEventListener(`pointercancel`,r),y.current&&cancelAnimationFrame(y.current)}},[b.isDragging,O,k,A]),{ref:v,transform:S,opacity:w,transition:E,isDragging:b.isDragging}},f=({children:t,className:n=``,style:r={},onSwipeLeft:i,onSwipeRight:a,onSwipeUp:o,onSwipeDown:s,onSwipeStart:c,onSwipeEnd:l,threshold:u=100,velocityThreshold:f=.5,maxRotation:p=15,exitDuration:m=300,returnDuration:h=200,enableRotation:g=!0})=>{let{ref:_,transform:v,opacity:y,transition:b,isDragging:x}=d({onSwipeLeft:i,onSwipeRight:a,onSwipeUp:o,onSwipeDown:s,onSwipeStart:c,onSwipeEnd:l},{threshold:u,velocityThreshold:f,maxRotation:p,exitDuration:m,returnDuration:h,enableRotation:g}),S={...r,transform:v,opacity:y,transition:b,touchAction:`none`,userSelect:`none`,WebkitUserSelect:`none`,cursor:x?`grabbing`:`grab`,willChange:x?`transform, opacity`:`auto`,position:`relative`};return e.createElement(`div`,{ref:_,className:`swipeon-card ${n}`,style:S},t)};export{f as SwipeCard,d as useSwipe};
2
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","names":["DEFAULT_CONFIG: Required<SwipeConfig>","SwipeCard: React.FC<SwipeCardProps>","cardStyle: CSSProperties"],"sources":["../src/utils/helpers.ts","../src/hooks/useSwipe.ts","../src/components/SwipeCard.tsx"],"sourcesContent":["import { SwipeDirection } from '../types';\n\n/**\n * Calculate the distance between two points\n */\nexport const getDistance = (x1: number, y1: number, x2: number, y2: number): number => {\n const dx = x2 - x1;\n const dy = y2 - y1;\n return Math.sqrt(dx * dx + dy * dy);\n};\n\n/**\n * Calculate velocity based on distance and time\n */\nexport const calculateVelocity = (distance: number, time: number): number => {\n if (time === 0) return 0;\n return Math.abs(distance / time);\n};\n\n/**\n * Determine the swipe direction based on deltas\n */\nexport const getSwipeDirection = (\n deltaX: number,\n deltaY: number,\n threshold: number = 50\n): SwipeDirection | null => {\n const absDeltaX = Math.abs(deltaX);\n const absDeltaY = Math.abs(deltaY);\n\n // Need minimum movement\n if (absDeltaX < threshold && absDeltaY < threshold) {\n return null;\n }\n\n // Determine primary direction\n if (absDeltaX > absDeltaY) {\n return deltaX > 0 ? 'right' : 'left';\n } else {\n return deltaY > 0 ? 'down' : 'up';\n }\n};\n\n/**\n * Calculate rotation angle based on horizontal movement\n */\nexport const calculateRotation = (\n deltaX: number,\n maxRotation: number = 15,\n containerWidth: number = 300\n): number => {\n const rotation = (deltaX / containerWidth) * maxRotation;\n return Math.max(-maxRotation, Math.min(maxRotation, rotation));\n};\n\n/**\n * Calculate opacity based on drag distance\n */\nexport const calculateOpacity = (\n deltaX: number,\n deltaY: number,\n threshold: number = 100\n): number => {\n const distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);\n const opacity = 1 - distance / (threshold * 3);\n return Math.max(0.5, Math.min(1, opacity));\n};\n\n/**\n * Clamp a value between min and max\n */\nexport const clamp = (value: number, min: number, max: number): number => {\n return Math.max(min, Math.min(max, value));\n};\n\n/**\n * Get touch/pointer coordinates from event\n */\nexport const getEventCoordinates = (\n event: TouchEvent | PointerEvent | MouseEvent | any\n): { x: number; y: number } => {\n if ('touches' in event && event.touches && event.touches.length > 0) {\n return {\n x: event.touches[0].clientX,\n y: event.touches[0].clientY,\n };\n }\n \n if ('clientX' in event && 'clientY' in event) {\n return {\n x: event.clientX,\n y: event.clientY,\n };\n }\n \n return { x: 0, y: 0 };\n};\n\n","import { useRef, useState, useCallback, useEffect } from 'react';\nimport { SwipeConfig, SwipeCallbacks, GestureState, UseSwipeReturn } from '../types';\nimport {\n getSwipeDirection,\n calculateRotation,\n calculateOpacity,\n calculateVelocity,\n getEventCoordinates,\n} from '../utils/helpers';\n\nconst DEFAULT_CONFIG: Required<SwipeConfig> = {\n threshold: 100,\n velocityThreshold: 0.5,\n maxRotation: 15,\n exitDuration: 300,\n returnDuration: 200,\n enableRotation: true,\n};\n\nexport const useSwipe = (\n callbacks: SwipeCallbacks = {},\n config: SwipeConfig = {}\n): UseSwipeReturn => {\n const mergedConfig = { ...DEFAULT_CONFIG, ...config };\n const {\n threshold,\n velocityThreshold,\n maxRotation,\n exitDuration,\n returnDuration,\n enableRotation,\n } = mergedConfig;\n\n const ref = useRef<HTMLDivElement>(null);\n const animationFrameRef = useRef<number | null>(null);\n const [gestureState, setGestureState] = useState<GestureState>({\n isDragging: false,\n startX: 0,\n startY: 0,\n currentX: 0,\n currentY: 0,\n deltaX: 0,\n deltaY: 0,\n velocity: 0,\n direction: null,\n startTime: 0,\n });\n\n const [transform, setTransform] = useState('translate3d(0px, 0px, 0px) rotate(0deg)');\n const [opacity, setOpacity] = useState(1);\n const [transition, setTransition] = useState('none');\n\n // Handle swipe start\n const handleSwipeStart = useCallback(\n (event: PointerEvent | TouchEvent | MouseEvent) => {\n const coords = getEventCoordinates(event as any);\n const now = Date.now();\n\n setGestureState({\n isDragging: true,\n startX: coords.x,\n startY: coords.y,\n currentX: coords.x,\n currentY: coords.y,\n deltaX: 0,\n deltaY: 0,\n velocity: 0,\n direction: null,\n startTime: now,\n });\n\n setTransition('none');\n \n if (callbacks.onSwipeStart) {\n callbacks.onSwipeStart();\n }\n },\n [callbacks]\n );\n\n // Handle swipe move\n const handleSwipeMove = useCallback(\n (event: PointerEvent | TouchEvent | MouseEvent) => {\n if (!gestureState.isDragging) return;\n\n const coords = getEventCoordinates(event as any);\n const deltaX = coords.x - gestureState.startX;\n const deltaY = coords.y - gestureState.startY;\n\n // Update gesture state\n setGestureState((prev: GestureState) => ({\n ...prev,\n currentX: coords.x,\n currentY: coords.y,\n deltaX,\n deltaY,\n }));\n\n // Use RAF for smooth updates\n if (animationFrameRef.current) {\n cancelAnimationFrame(animationFrameRef.current);\n }\n\n animationFrameRef.current = requestAnimationFrame(() => {\n const rotation = enableRotation ? calculateRotation(deltaX, maxRotation) : 0;\n const newOpacity = calculateOpacity(deltaX, deltaY, threshold);\n\n setTransform(\n `translate3d(${deltaX}px, ${deltaY}px, 0px) rotate(${rotation}deg)`\n );\n setOpacity(newOpacity);\n });\n },\n [gestureState.isDragging, gestureState.startX, gestureState.startY, enableRotation, maxRotation, threshold]\n );\n\n // Handle swipe end\n const handleSwipeEnd = useCallback(() => {\n if (!gestureState.isDragging) return;\n\n const { deltaX, deltaY, startTime } = gestureState;\n const timeDelta = Date.now() - startTime;\n const distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);\n const velocity = calculateVelocity(distance, timeDelta);\n\n const direction = getSwipeDirection(deltaX, deltaY, threshold / 2);\n const shouldSwipe =\n distance >= threshold || velocity >= velocityThreshold;\n\n if (shouldSwipe && direction) {\n // Execute swipe\n setTransition(`transform ${exitDuration}ms ease-out, opacity ${exitDuration}ms ease-out`);\n \n // Calculate exit position (move far enough off screen)\n const multiplier = 2;\n const exitX = deltaX * multiplier;\n const exitY = deltaY * multiplier;\n const rotation = enableRotation ? calculateRotation(exitX, maxRotation * 2) : 0;\n\n setTransform(\n `translate3d(${exitX}px, ${exitY}px, 0px) rotate(${rotation}deg)`\n );\n setOpacity(0);\n\n // Trigger callback after animation\n setTimeout(() => {\n switch (direction) {\n case 'left':\n callbacks.onSwipeLeft?.();\n break;\n case 'right':\n callbacks.onSwipeRight?.();\n break;\n case 'up':\n callbacks.onSwipeUp?.();\n break;\n case 'down':\n callbacks.onSwipeDown?.();\n break;\n }\n \n if (callbacks.onSwipeEnd) {\n callbacks.onSwipeEnd();\n }\n\n // Reset after callback\n setTimeout(() => {\n setTransition('none');\n setTransform('translate3d(0px, 0px, 0px) rotate(0deg)');\n setOpacity(1);\n }, 50);\n }, exitDuration);\n } else {\n // Spring back\n setTransition(\n `transform ${returnDuration}ms cubic-bezier(0.175, 0.885, 0.32, 1.275), opacity ${returnDuration}ms ease-out`\n );\n setTransform('translate3d(0px, 0px, 0px) rotate(0deg)');\n setOpacity(1);\n\n if (callbacks.onSwipeEnd) {\n callbacks.onSwipeEnd();\n }\n }\n\n setGestureState((prev: GestureState) => ({ ...prev, isDragging: false }));\n }, [\n gestureState,\n threshold,\n velocityThreshold,\n exitDuration,\n returnDuration,\n enableRotation,\n maxRotation,\n callbacks,\n ]);\n\n // Attach event listeners\n useEffect(() => {\n const element = ref.current;\n if (!element) return;\n\n const handlePointerDown = (e: PointerEvent) => {\n handleSwipeStart(e);\n };\n\n const handlePointerMove = (e: PointerEvent) => {\n if (gestureState.isDragging) {\n handleSwipeMove(e);\n }\n };\n\n const handlePointerUp = () => {\n handleSwipeEnd();\n };\n\n element.addEventListener('pointerdown', handlePointerDown);\n\n if (gestureState.isDragging) {\n document.addEventListener('pointermove', handlePointerMove);\n document.addEventListener('pointerup', handlePointerUp);\n document.addEventListener('pointercancel', handlePointerUp);\n }\n\n return () => {\n element.removeEventListener('pointerdown', handlePointerDown);\n document.removeEventListener('pointermove', handlePointerMove);\n document.removeEventListener('pointerup', handlePointerUp);\n document.removeEventListener('pointercancel', handlePointerUp);\n \n if (animationFrameRef.current) {\n cancelAnimationFrame(animationFrameRef.current);\n }\n };\n }, [gestureState.isDragging, handleSwipeStart, handleSwipeMove, handleSwipeEnd]);\n\n return {\n ref,\n transform,\n opacity,\n transition,\n isDragging: gestureState.isDragging,\n };\n};\n\n","import React, { CSSProperties } from 'react';\nimport { useSwipe } from '../hooks/useSwipe';\nimport { SwipeCardProps } from '../types';\n\n/**\n * SwipeCard Component\n * \n * A performant swipeable card component with smooth animations.\n * Supports swipe in all four directions: left, right, up, and down.\n * \n * @example\n * ```tsx\n * <SwipeCard\n * onSwipeLeft={() => console.log('Swiped left')}\n * onSwipeRight={() => console.log('Swiped right')}\n * threshold={100}\n * >\n * <div>Your content here</div>\n * </SwipeCard>\n * ```\n */\nexport const SwipeCard: React.FC<SwipeCardProps> = ({\n children,\n className = '',\n style = {},\n onSwipeLeft,\n onSwipeRight,\n onSwipeUp,\n onSwipeDown,\n onSwipeStart,\n onSwipeEnd,\n threshold = 100,\n velocityThreshold = 0.5,\n maxRotation = 15,\n exitDuration = 300,\n returnDuration = 200,\n enableRotation = true,\n}) => {\n const callbacks = {\n onSwipeLeft,\n onSwipeRight,\n onSwipeUp,\n onSwipeDown,\n onSwipeStart,\n onSwipeEnd,\n };\n\n const config = {\n threshold,\n velocityThreshold,\n maxRotation,\n exitDuration,\n returnDuration,\n enableRotation,\n };\n\n const { ref, transform, opacity, transition, isDragging } = useSwipe(callbacks, config);\n\n const cardStyle: CSSProperties = {\n ...style,\n transform,\n opacity,\n transition,\n touchAction: 'none', // Prevent default touch behaviors\n userSelect: 'none', // Prevent text selection during drag\n WebkitUserSelect: 'none',\n cursor: isDragging ? 'grabbing' : 'grab',\n willChange: isDragging ? 'transform, opacity' : 'auto',\n position: 'relative',\n };\n\n return (\n <div\n ref={ref}\n className={`swipeon-card ${className}`}\n style={cardStyle}\n >\n {children}\n </div>\n );\n};\n\nexport default SwipeCard;\n\n"],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,60 @@
1
+ {
2
+ "name": "swipeon-react",
3
+ "version": "0.0.1-alpha.2",
4
+ "type": "module",
5
+ "description": "A high-performance React swipe card library with smooth animations and multi-directional swipe support",
6
+ "main": "dist/index.js",
7
+ "module": "dist/index.esm.js",
8
+ "types": "dist/index.d.ts",
9
+ "files": [
10
+ "dist",
11
+ "README.md",
12
+ "LICENSE"
13
+ ],
14
+ "exports": {
15
+ ".": {
16
+ "import": "./dist/index.esm.js",
17
+ "require": "./dist/index.js",
18
+ "types": "./dist/index.d.ts"
19
+ }
20
+ },
21
+ "scripts": {
22
+ "build": "tsdown",
23
+ "dev": "tsdown --watch",
24
+ "prepublishOnly": "npm run build",
25
+ "clean": "rm -rf dist",
26
+ "prebuild": "npm run clean",
27
+ "publish:alpha": "npm version prerelease --preid=alpha && npm run build && npm publish --tag alpha",
28
+ "publish:rc": "npm version prerelease --preid=rc && npm run build && npm publish --tag next",
29
+ "publish:stable": "npm version patch && npm run build && npm publish --tag latest"
30
+ },
31
+ "keywords": [
32
+ "react",
33
+ "swipe",
34
+ "swipe-cards",
35
+ "tinder",
36
+ "gestures",
37
+ "touch",
38
+ "animation",
39
+ "typescript"
40
+ ],
41
+ "author": "react-forge",
42
+ "license": "MIT",
43
+ "repository": {
44
+ "type": "git",
45
+ "url": "https://github.com/react-forge/swipeon-react"
46
+ },
47
+ "peerDependencies": {
48
+ "react": ">=16.8.0",
49
+ "react-dom": ">=16.8.0"
50
+ },
51
+ "devDependencies": {
52
+ "@types/react": "^18.2.45",
53
+ "@types/react-dom": "^18.2.18",
54
+ "react": "^18.2.0",
55
+ "react-dom": "^18.2.0",
56
+ "tsdown": "0.18.2",
57
+ "tslib": "^2.6.2",
58
+ "typescript": "^5.3.3"
59
+ }
60
+ }