react-sway 0.1.0 → 0.1.1
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 +87 -0
- package/dist/index.cjs +2 -13
- package/dist/index.js +2 -13
- package/package.json +1 -1
- package/src/ReactSway.tsx +2 -19
package/README.md
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# react-sway
|
|
2
|
+
|
|
3
|
+
A React component for smooth, infinite, and interactive content scrolling. It duplicates content to create a seamless looping effect, controllable via touch, mouse drag, wheel, and keyboard.
|
|
4
|
+
|
|
5
|
+
## What is `react-sway`?
|
|
6
|
+
|
|
7
|
+
React Sway takes your list of items and makes them scroll endlessly. It's designed to be easy to use and performant, with auto-scrolling that pauses when users interact.
|
|
8
|
+
|
|
9
|
+
It works by duplicating your content to create a seamless loop and uses CSS transforms for smooth animation. The duplicated content is wrapped in `<aside>` elements with `aria-hidden="true"` and `role="presentation"` to ensure good accessibility and helps search engines understand the content structure.
|
|
10
|
+
|
|
11
|
+
### Core Features
|
|
12
|
+
|
|
13
|
+
* **Smooth Infinite Scroll:** Content loops continuously.
|
|
14
|
+
* **Auto-Scroll:** Scrolls automatically, with configurable speed.
|
|
15
|
+
* **User Friendly Interactions:**
|
|
16
|
+
* Click and drag to scroll.
|
|
17
|
+
* Swipe on touch devices.
|
|
18
|
+
* Mouse wheel support.
|
|
19
|
+
* Keyboard controls: Spacebar to pause/resume, ArrowUp/ArrowDown to scroll, Home/End to jump.
|
|
20
|
+
* **Responsive:** Adjusts to window resizing.
|
|
21
|
+
* **Lazy Loading Hook:** Add a `content-item` class to your child elements, and `react-sway` will add a `.visible` class when they enter the viewport. Handy for animations or loading content.
|
|
22
|
+
|
|
23
|
+
## Installation
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
npm install react-sway
|
|
27
|
+
# or
|
|
28
|
+
yarn add react-sway
|
|
29
|
+
# or
|
|
30
|
+
pnpm add react-sway
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Usage
|
|
34
|
+
|
|
35
|
+
```tsx
|
|
36
|
+
import { ReactSway } from 'react-sway';
|
|
37
|
+
import './index.css'; // Your global styles
|
|
38
|
+
|
|
39
|
+
function SwayUsageExample() {
|
|
40
|
+
return (
|
|
41
|
+
<div className="scroller-container"> {/* Style this container to define ReactSway's area (e.g., full-page, or a specific height) */}
|
|
42
|
+
<ReactSway>
|
|
43
|
+
<div className="content-item" style={{ background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)' }}>
|
|
44
|
+
<h2>Seamless Scrolling</h2>
|
|
45
|
+
<p>Experience buttery smooth infinite scrolling with no stutters or pauses.</p>
|
|
46
|
+
</div>
|
|
47
|
+
|
|
48
|
+
<div className="content-item" style={{ background: 'linear-gradient(135deg, #f093fb 0%, #f5576c 100%)' }}>
|
|
49
|
+
<h2>Touch & Mouse Support</h2>
|
|
50
|
+
<p>Interact naturally with touch gestures, mouse wheel, or click-and-drag.</p>
|
|
51
|
+
</div>
|
|
52
|
+
|
|
53
|
+
<div className="content-item" style={{ background: 'linear-gradient(135deg, #4facfe 0%, #00f2fe 100%)' }}>
|
|
54
|
+
<h2>Momentum Scrolling</h2>
|
|
55
|
+
<p>Flick to scroll with realistic physics-based momentum and friction.</p>
|
|
56
|
+
</div>
|
|
57
|
+
|
|
58
|
+
<div className="content-item" style={{ background: 'linear-gradient(135deg, #43e97b 0%, #38f9d7 100%)' }}>
|
|
59
|
+
<h2>Performance Optimized</h2>
|
|
60
|
+
<p>Using requestAnimationFrame for 60+ FPS scrolling on all devices.</p>
|
|
61
|
+
</div>
|
|
62
|
+
|
|
63
|
+
<div className="content-item" style={{ background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)' }}>
|
|
64
|
+
<h2>Responsive Design</h2>
|
|
65
|
+
<p>Adapts perfectly to any screen size and device orientation.</p>
|
|
66
|
+
</div>
|
|
67
|
+
|
|
68
|
+
<div className="content-item" style={{ background: 'linear-gradient(135deg, #f093fb 0%, #f5576c 100%)' }}>
|
|
69
|
+
<h2>No Native Scroll</h2>
|
|
70
|
+
<p>Custom implementation avoids native scroll jank and inconsistencies.</p>
|
|
71
|
+
</div>
|
|
72
|
+
|
|
73
|
+
<div className="content-item" style={{ background: 'linear-gradient(135deg, #4facfe 0%, #00f2fe 100%)' }}>
|
|
74
|
+
<h2>Continuous Loop</h2>
|
|
75
|
+
<p>Content loops seamlessly without any visible seams or jumps.</p>
|
|
76
|
+
</div>
|
|
77
|
+
</ReactSway>
|
|
78
|
+
</div>
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export default SwayUsageExample;
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## License
|
|
86
|
+
|
|
87
|
+
This package is licensed under the [MIT License](../../LICENSE).
|
package/dist/index.cjs
CHANGED
|
@@ -55,7 +55,6 @@ function ReactSway({ children }) {
|
|
|
55
55
|
containerRef.current.offsetHeight;
|
|
56
56
|
const currentContentHeight = containerRef.current.scrollHeight;
|
|
57
57
|
const calculatedLoopPoint = currentContentHeight / 3;
|
|
58
|
-
console.log("Calculating dimensions:", { currentContentHeight, calculatedLoopPoint });
|
|
59
58
|
if (currentContentHeight > 0) {
|
|
60
59
|
setContentHeight(currentContentHeight);
|
|
61
60
|
setLoopPoint(calculatedLoopPoint);
|
|
@@ -314,18 +313,6 @@ function ReactSway({ children }) {
|
|
|
314
313
|
observer.disconnect();
|
|
315
314
|
};
|
|
316
315
|
}, [children, contentHeight]);
|
|
317
|
-
(0, import_react.useEffect)(() => {
|
|
318
|
-
const originalBodyStyle = {
|
|
319
|
-
touchAction: document.body.style.touchAction,
|
|
320
|
-
overflow: document.body.style.overflow
|
|
321
|
-
};
|
|
322
|
-
document.body.style.touchAction = "none";
|
|
323
|
-
document.body.style.overflow = "hidden";
|
|
324
|
-
return () => {
|
|
325
|
-
document.body.style.touchAction = originalBodyStyle.touchAction;
|
|
326
|
-
document.body.style.overflow = originalBodyStyle.overflow;
|
|
327
|
-
};
|
|
328
|
-
}, []);
|
|
329
316
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
330
317
|
"div",
|
|
331
318
|
{
|
|
@@ -344,6 +331,8 @@ function ReactSway({ children }) {
|
|
|
344
331
|
msUserSelect: "none",
|
|
345
332
|
MozUserSelect: "none",
|
|
346
333
|
overscrollBehavior: "contain",
|
|
334
|
+
overflow: "hidden",
|
|
335
|
+
// Prevent component's content from overflowing and causing page scroll
|
|
347
336
|
// Ensure it's on top and can receive events
|
|
348
337
|
pointerEvents: "auto",
|
|
349
338
|
zIndex: 1
|
package/dist/index.js
CHANGED
|
@@ -29,7 +29,6 @@ function ReactSway({ children }) {
|
|
|
29
29
|
containerRef.current.offsetHeight;
|
|
30
30
|
const currentContentHeight = containerRef.current.scrollHeight;
|
|
31
31
|
const calculatedLoopPoint = currentContentHeight / 3;
|
|
32
|
-
console.log("Calculating dimensions:", { currentContentHeight, calculatedLoopPoint });
|
|
33
32
|
if (currentContentHeight > 0) {
|
|
34
33
|
setContentHeight(currentContentHeight);
|
|
35
34
|
setLoopPoint(calculatedLoopPoint);
|
|
@@ -288,18 +287,6 @@ function ReactSway({ children }) {
|
|
|
288
287
|
observer.disconnect();
|
|
289
288
|
};
|
|
290
289
|
}, [children, contentHeight]);
|
|
291
|
-
useEffect(() => {
|
|
292
|
-
const originalBodyStyle = {
|
|
293
|
-
touchAction: document.body.style.touchAction,
|
|
294
|
-
overflow: document.body.style.overflow
|
|
295
|
-
};
|
|
296
|
-
document.body.style.touchAction = "none";
|
|
297
|
-
document.body.style.overflow = "hidden";
|
|
298
|
-
return () => {
|
|
299
|
-
document.body.style.touchAction = originalBodyStyle.touchAction;
|
|
300
|
-
document.body.style.overflow = originalBodyStyle.overflow;
|
|
301
|
-
};
|
|
302
|
-
}, []);
|
|
303
290
|
return /* @__PURE__ */ jsxs(
|
|
304
291
|
"div",
|
|
305
292
|
{
|
|
@@ -318,6 +305,8 @@ function ReactSway({ children }) {
|
|
|
318
305
|
msUserSelect: "none",
|
|
319
306
|
MozUserSelect: "none",
|
|
320
307
|
overscrollBehavior: "contain",
|
|
308
|
+
overflow: "hidden",
|
|
309
|
+
// Prevent component's content from overflowing and causing page scroll
|
|
321
310
|
// Ensure it's on top and can receive events
|
|
322
311
|
pointerEvents: "auto",
|
|
323
312
|
zIndex: 1
|
package/package.json
CHANGED
package/src/ReactSway.tsx
CHANGED
|
@@ -44,7 +44,7 @@ function ReactSway({ children }: ReactSwayProps) {
|
|
|
44
44
|
const currentContentHeight = containerRef.current.scrollHeight;
|
|
45
45
|
const calculatedLoopPoint = currentContentHeight / 3;
|
|
46
46
|
|
|
47
|
-
console.log('Calculating dimensions:', { currentContentHeight, calculatedLoopPoint });
|
|
47
|
+
// console.log('Calculating dimensions:', { currentContentHeight, calculatedLoopPoint });
|
|
48
48
|
|
|
49
49
|
if (currentContentHeight > 0) {
|
|
50
50
|
setContentHeight(currentContentHeight);
|
|
@@ -354,24 +354,6 @@ function ReactSway({ children }: ReactSwayProps) {
|
|
|
354
354
|
};
|
|
355
355
|
}, [children, contentHeight]);
|
|
356
356
|
|
|
357
|
-
// Apply styles to override conflicting CSS
|
|
358
|
-
useEffect(() => {
|
|
359
|
-
const originalBodyStyle = {
|
|
360
|
-
touchAction: document.body.style.touchAction,
|
|
361
|
-
overflow: document.body.style.overflow
|
|
362
|
-
};
|
|
363
|
-
|
|
364
|
-
// Override body styles that might conflict
|
|
365
|
-
document.body.style.touchAction = 'none';
|
|
366
|
-
document.body.style.overflow = 'hidden';
|
|
367
|
-
|
|
368
|
-
return () => {
|
|
369
|
-
// Restore original styles
|
|
370
|
-
document.body.style.touchAction = originalBodyStyle.touchAction;
|
|
371
|
-
document.body.style.overflow = originalBodyStyle.overflow;
|
|
372
|
-
};
|
|
373
|
-
}, []);
|
|
374
|
-
|
|
375
357
|
return (
|
|
376
358
|
<div
|
|
377
359
|
className="react-sway-container scroller-content"
|
|
@@ -389,6 +371,7 @@ function ReactSway({ children }: ReactSwayProps) {
|
|
|
389
371
|
msUserSelect: 'none',
|
|
390
372
|
MozUserSelect: 'none',
|
|
391
373
|
overscrollBehavior: 'contain',
|
|
374
|
+
overflow: 'hidden', // Prevent component's content from overflowing and causing page scroll
|
|
392
375
|
// Ensure it's on top and can receive events
|
|
393
376
|
pointerEvents: 'auto',
|
|
394
377
|
zIndex: 1
|