@riverflowpkg/riverflow 1.0.3 → 1.0.7

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/scroll/scroll.css CHANGED
@@ -1,91 +1,91 @@
1
- html.has-scroll-smooth {
2
- overflow: hidden
3
- }
4
-
5
- html.has-scroll-dragging {
6
- -webkit-user-select: none;
7
- -moz-user-select: none;
8
- -ms-user-select: none;
9
- user-select: none
10
- }
11
-
12
- .has-scroll-smooth body {
13
- overflow: hidden
14
- }
15
-
16
- .has-scroll-smooth [data-scroll-container] {
17
- min-height: 100vh
18
- }
19
-
20
- [data-scroll-direction=horizontal] [data-scroll-container] {
21
- display: inline-block;
22
- height: 100vh;
23
- white-space: nowrap
24
- }
25
-
26
- [data-scroll-direction=horizontal] [data-scroll-section] {
27
- display: inline-block;
28
- height: 100%;
29
- vertical-align: top;
30
- white-space: nowrap
31
- }
32
-
33
- .c-scrollbar {
34
- height: 100%;
35
- opacity: 0;
36
- position: absolute;
37
- right: 0;
38
- top: 0;
39
- transform-origin: center right;
40
- transition: transform .3s, opacity .3s;
41
- width: 11px
42
- }
43
-
44
- .c-scrollbar:hover {
45
- transform: scaleX(1.45)
46
- }
47
-
48
- .c-scrollbar:hover,
49
- .has-scroll-dragging .c-scrollbar,
50
- .has-scroll-scrolling .c-scrollbar {
51
- opacity: 1
52
- }
53
-
54
- [data-scroll-direction=horizontal] .c-scrollbar {
55
- bottom: 0;
56
- height: 10px;
57
- top: auto;
58
- transform: scaleY(1);
59
- width: 100%
60
- }
61
-
62
- [data-scroll-direction=horizontal] .c-scrollbar:hover {
63
- transform: scaleY(1.3)
64
- }
65
-
66
- .c-scrollbar_thumb {
67
- background-color: #000;
68
- border-radius: 10px;
69
- cursor: -webkit-grab;
70
- cursor: grab;
71
- margin: 2px;
72
- opacity: .5;
73
- position: absolute;
74
- right: 0;
75
- top: 0;
76
- width: 7px
77
- }
78
-
79
- .has-scroll-dragging .c-scrollbar_thumb {
80
- cursor: -webkit-grabbing;
81
- cursor: grabbing
82
- }
83
-
84
- [data-scroll-direction=horizontal] .c-scrollbar_thumb {
85
- bottom: 0;
86
- right: auto
87
- }
88
-
89
- [data-scroll-sticky] {
90
- will-change: transform;
91
- }
1
+ html.has-scroll-smooth {
2
+ overflow: hidden
3
+ }
4
+
5
+ html.has-scroll-dragging {
6
+ -webkit-user-select: none;
7
+ -moz-user-select: none;
8
+ -ms-user-select: none;
9
+ user-select: none
10
+ }
11
+
12
+ .has-scroll-smooth body {
13
+ overflow: hidden
14
+ }
15
+
16
+ .has-scroll-smooth [data-scroll-container] {
17
+ min-height: 100vh
18
+ }
19
+
20
+ [data-scroll-direction=horizontal] [data-scroll-container] {
21
+ display: inline-block;
22
+ height: 100vh;
23
+ white-space: nowrap
24
+ }
25
+
26
+ [data-scroll-direction=horizontal] [data-scroll-section] {
27
+ display: inline-block;
28
+ height: 100%;
29
+ vertical-align: top;
30
+ white-space: nowrap
31
+ }
32
+
33
+ .c-scrollbar {
34
+ height: 100%;
35
+ opacity: 0;
36
+ position: absolute;
37
+ right: 0;
38
+ top: 0;
39
+ transform-origin: center right;
40
+ transition: transform .3s, opacity .3s;
41
+ width: 11px
42
+ }
43
+
44
+ .c-scrollbar:hover {
45
+ transform: scaleX(1.45)
46
+ }
47
+
48
+ .c-scrollbar:hover,
49
+ .has-scroll-dragging .c-scrollbar,
50
+ .has-scroll-scrolling .c-scrollbar {
51
+ opacity: 1
52
+ }
53
+
54
+ [data-scroll-direction=horizontal] .c-scrollbar {
55
+ bottom: 0;
56
+ height: 10px;
57
+ top: auto;
58
+ transform: scaleY(1);
59
+ width: 100%
60
+ }
61
+
62
+ [data-scroll-direction=horizontal] .c-scrollbar:hover {
63
+ transform: scaleY(1.3)
64
+ }
65
+
66
+ .c-scrollbar_thumb {
67
+ background-color: #000;
68
+ border-radius: 10px;
69
+ cursor: -webkit-grab;
70
+ cursor: grab;
71
+ margin: 2px;
72
+ opacity: .5;
73
+ position: absolute;
74
+ right: 0;
75
+ top: 0;
76
+ width: 7px
77
+ }
78
+
79
+ .has-scroll-dragging .c-scrollbar_thumb {
80
+ cursor: -webkit-grabbing;
81
+ cursor: grabbing
82
+ }
83
+
84
+ [data-scroll-direction=horizontal] .c-scrollbar_thumb {
85
+ bottom: 0;
86
+ right: auto
87
+ }
88
+
89
+ [data-scroll-sticky] {
90
+ will-change: transform;
91
+ }
package/scroll/scroll.js CHANGED
@@ -1,244 +1,244 @@
1
- (function() {
2
- 'use strict';
3
-
4
- class SimpleScroll {
5
- constructor(options = {}) {
6
- this.options = {
7
- speed: 0.5,
8
- lerp: 0.1,
9
- ...options
10
- };
11
-
12
- this.body = document.body;
13
- this.html = document.documentElement;
14
- this.windowHeight = window.innerHeight;
15
- this.windowWidth = window.innerWidth;
16
- this.scrollY = 0;
17
- this.targetY = 0;
18
- this.isScrolling = false;
19
- this.rafId = null;
20
- this.content = null;
21
-
22
- // Get speed from attributes
23
- const speedAttr = this.body.getAttribute('scroll-speed') ||
24
- this.body.getAttribute('data-scroll-speed');
25
- if (speedAttr !== null) {
26
- this.options.speed = parseFloat(speedAttr);
27
- }
28
-
29
- this.init();
30
- }
31
-
32
- init() {
33
- // Create a wrapper for content
34
- this.content = document.createElement('div');
35
- this.content.className = 'scroll-content';
36
-
37
- // Move all body children into the wrapper
38
- while (this.body.firstChild) {
39
- this.content.appendChild(this.body.firstChild);
40
- }
41
- this.body.appendChild(this.content);
42
-
43
- // Set initial styles
44
- this.body.style.margin = '0';
45
- this.body.style.overflow = 'hidden';
46
- this.body.style.height = '100vh';
47
- this.body.style.position = 'relative';
48
-
49
- this.html.style.overflow = 'hidden';
50
- this.html.style.height = '100%';
51
-
52
- this.content.style.willChange = 'transform';
53
- this.content.style.transform = 'translate3d(0, 0, 0)';
54
-
55
- // Set initial scroll position
56
- this.targetY = 0;
57
- this.scrollY = 0;
58
-
59
- // Add classes
60
- this.html.classList.add('has-scroll-smooth');
61
- this.html.classList.add('has-scroll-init');
62
-
63
- // Setup event listeners
64
- this.setupVirtualScroll();
65
- window.addEventListener('resize', () => this.onResize());
66
-
67
- // Start the scroll loop
68
- this.loop();
69
- }
70
-
71
- setupVirtualScroll() {
72
- // Handle wheel events
73
- this.onWheel = this.onWheel.bind(this);
74
- window.addEventListener('wheel', this.onWheel, { passive: false });
75
-
76
- // Handle touch events
77
- this.onTouchStart = this.onTouchStart.bind(this);
78
- this.onTouchMove = this.onTouchMove.bind(this);
79
- window.addEventListener('touchstart', this.onTouchStart, { passive: true });
80
- window.addEventListener('touchmove', this.onTouchMove, { passive: false });
81
- }
82
-
83
- onWheel(e) {
84
- e.preventDefault();
85
- const delta = e.deltaY || e.wheelDelta || -e.detail;
86
- this.targetY += delta * this.options.speed;
87
- this.limitScroll();
88
- this.startScrolling();
89
- }
90
-
91
- onTouchStart(e) {
92
- this.touchY = e.touches[0].clientY;
93
- }
94
-
95
- onTouchMove(e) {
96
- e.preventDefault();
97
- const touchY = e.touches[0].clientY;
98
- const delta = (this.touchY - touchY) * 2;
99
- this.targetY += delta * this.options.speed;
100
- this.touchY = touchY;
101
- this.limitScroll();
102
- this.startScrolling();
103
- }
104
-
105
- limitScroll() {
106
- const contentHeight = this.content.offsetHeight;
107
- const maxScroll = Math.max(0, contentHeight - this.windowHeight);
108
- this.targetY = Math.max(0, Math.min(this.targetY, maxScroll));
109
- }
110
-
111
- startScrolling() {
112
- if (!this.isScrolling) {
113
- this.isScrolling = true;
114
- this.html.classList.add('has-scroll-scrolling');
115
- }
116
- }
117
-
118
- stopScrolling() {
119
- if (this.isScrolling) {
120
- this.isScrolling = false;
121
- this.html.classList.remove('has-scroll-scrolling');
122
- }
123
- }
124
-
125
- onResize() {
126
- this.windowHeight = window.innerHeight;
127
- this.windowWidth = window.innerWidth;
128
- this.limitScroll();
129
- }
130
-
131
- update() {
132
- // Smooth interpolation
133
- const diff = this.targetY - this.scrollY;
134
- if (Math.abs(diff) > 0.01) {
135
- this.scrollY += diff * this.options.lerp;
136
- this.isScrolling = true;
137
- } else {
138
- this.scrollY = this.targetY;
139
- this.stopScrolling();
140
- }
141
-
142
- // Apply transform to content
143
- this.content.style.transform = `translate3d(0, -${this.scrollY}px, 0)`;
144
-
145
- // Dispatch scroll event
146
- this.dispatchScrollEvent();
147
- }
148
-
149
- loop() {
150
- this.update();
151
- this.rafId = requestAnimationFrame(() => this.loop());
152
- }
153
-
154
- dispatchScrollEvent() {
155
- const event = new CustomEvent('scroll', {
156
- detail: {
157
- y: this.scrollY,
158
- targetY: this.targetY,
159
- limit: Math.max(0, this.content.offsetHeight - this.windowHeight),
160
- progress: this.scrollY / Math.max(1, this.content.offsetHeight - this.windowHeight),
161
- speed: this.options.speed
162
- }
163
- });
164
- document.dispatchEvent(event);
165
- }
166
-
167
- scrollTo(target, duration = 1000) {
168
- const startY = this.scrollY;
169
- let endY = typeof target === 'number' ? target :
170
- target.getBoundingClientRect().top + this.scrollY;
171
-
172
- // Clamp end position
173
- const maxScroll = Math.max(0, this.content.offsetHeight - this.windowHeight);
174
- endY = Math.max(0, Math.min(endY, maxScroll));
175
-
176
- const startTime = Date.now();
177
-
178
- const easeInOut = (t) => {
179
- return t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t;
180
- };
181
-
182
- const animate = () => {
183
- const elapsed = Date.now() - startTime;
184
- const progress = Math.min(elapsed / duration, 1);
185
- const easedProgress = easeInOut(progress);
186
-
187
- this.targetY = startY + (endY - startY) * easedProgress;
188
- this.limitScroll();
189
- this.startScrolling();
190
-
191
- if (progress < 1) {
192
- requestAnimationFrame(animate);
193
- }
194
- };
195
-
196
- animate();
197
- }
198
-
199
- destroy() {
200
- if (this.rafId) {
201
- cancelAnimationFrame(this.rafId);
202
- }
203
-
204
- window.removeEventListener('wheel', this.onWheel);
205
- window.removeEventListener('touchstart', this.onTouchStart);
206
- window.removeEventListener('touchmove', this.onTouchMove);
207
- window.removeEventListener('resize', this.onResize);
208
-
209
- // Restore content
210
- while (this.content.firstChild) {
211
- this.body.appendChild(this.content.firstChild);
212
- }
213
- this.content.remove();
214
-
215
- // Restore styles
216
- this.body.style.margin = '';
217
- this.body.style.overflow = '';
218
- this.body.style.height = '';
219
- this.body.style.position = '';
220
- this.html.style.overflow = '';
221
- this.html.style.height = '';
222
-
223
- this.html.classList.remove('has-scroll-smooth');
224
- this.html.classList.remove('has-scroll-scrolling');
225
- this.html.classList.remove('has-scroll-init');
226
- }
227
- }
228
-
229
- // Auto-initialize
230
- if (document.body.hasAttribute('scroll') || document.body.hasAttribute('data-scroll')) {
231
- if (document.readyState === 'loading') {
232
- document.addEventListener('DOMContentLoaded', () => {
233
- window.simpleScroll = new SimpleScroll();
234
- });
235
- } else {
236
- window.simpleScroll = new SimpleScroll();
237
- }
238
- }
239
-
240
- // Export for npm
241
- if (typeof module !== 'undefined' && module.exports) {
242
- module.exports = SimpleScroll;
243
- }
244
- })();
1
+ (function() {
2
+ 'use strict';
3
+
4
+ class SimpleScroll {
5
+ constructor(options = {}) {
6
+ this.options = {
7
+ speed: 0.5,
8
+ lerp: 0.1,
9
+ ...options
10
+ };
11
+
12
+ this.body = document.body;
13
+ this.html = document.documentElement;
14
+ this.windowHeight = window.innerHeight;
15
+ this.windowWidth = window.innerWidth;
16
+ this.scrollY = 0;
17
+ this.targetY = 0;
18
+ this.isScrolling = false;
19
+ this.rafId = null;
20
+ this.content = null;
21
+
22
+ // Get speed from attributes
23
+ const speedAttr = this.body.getAttribute('scroll-speed') ||
24
+ this.body.getAttribute('data-scroll-speed');
25
+ if (speedAttr !== null) {
26
+ this.options.speed = parseFloat(speedAttr);
27
+ }
28
+
29
+ this.init();
30
+ }
31
+
32
+ init() {
33
+ // Create a wrapper for content
34
+ this.content = document.createElement('div');
35
+ this.content.className = 'scroll-content';
36
+
37
+ // Move all body children into the wrapper
38
+ while (this.body.firstChild) {
39
+ this.content.appendChild(this.body.firstChild);
40
+ }
41
+ this.body.appendChild(this.content);
42
+
43
+ // Set initial styles
44
+ this.body.style.margin = '0';
45
+ this.body.style.overflow = 'hidden';
46
+ this.body.style.height = '100vh';
47
+ this.body.style.position = 'relative';
48
+
49
+ this.html.style.overflow = 'hidden';
50
+ this.html.style.height = '100%';
51
+
52
+ this.content.style.willChange = 'transform';
53
+ this.content.style.transform = 'translate3d(0, 0, 0)';
54
+
55
+ // Set initial scroll position
56
+ this.targetY = 0;
57
+ this.scrollY = 0;
58
+
59
+ // Add classes
60
+ this.html.classList.add('has-scroll-smooth');
61
+ this.html.classList.add('has-scroll-init');
62
+
63
+ // Setup event listeners
64
+ this.setupVirtualScroll();
65
+ window.addEventListener('resize', () => this.onResize());
66
+
67
+ // Start the scroll loop
68
+ this.loop();
69
+ }
70
+
71
+ setupVirtualScroll() {
72
+ // Handle wheel events
73
+ this.onWheel = this.onWheel.bind(this);
74
+ window.addEventListener('wheel', this.onWheel, { passive: false });
75
+
76
+ // Handle touch events
77
+ this.onTouchStart = this.onTouchStart.bind(this);
78
+ this.onTouchMove = this.onTouchMove.bind(this);
79
+ window.addEventListener('touchstart', this.onTouchStart, { passive: true });
80
+ window.addEventListener('touchmove', this.onTouchMove, { passive: false });
81
+ }
82
+
83
+ onWheel(e) {
84
+ e.preventDefault();
85
+ const delta = e.deltaY || e.wheelDelta || -e.detail;
86
+ this.targetY += delta * this.options.speed;
87
+ this.limitScroll();
88
+ this.startScrolling();
89
+ }
90
+
91
+ onTouchStart(e) {
92
+ this.touchY = e.touches[0].clientY;
93
+ }
94
+
95
+ onTouchMove(e) {
96
+ e.preventDefault();
97
+ const touchY = e.touches[0].clientY;
98
+ const delta = (this.touchY - touchY) * 2;
99
+ this.targetY += delta * this.options.speed;
100
+ this.touchY = touchY;
101
+ this.limitScroll();
102
+ this.startScrolling();
103
+ }
104
+
105
+ limitScroll() {
106
+ const contentHeight = this.content.offsetHeight;
107
+ const maxScroll = Math.max(0, contentHeight - this.windowHeight);
108
+ this.targetY = Math.max(0, Math.min(this.targetY, maxScroll));
109
+ }
110
+
111
+ startScrolling() {
112
+ if (!this.isScrolling) {
113
+ this.isScrolling = true;
114
+ this.html.classList.add('has-scroll-scrolling');
115
+ }
116
+ }
117
+
118
+ stopScrolling() {
119
+ if (this.isScrolling) {
120
+ this.isScrolling = false;
121
+ this.html.classList.remove('has-scroll-scrolling');
122
+ }
123
+ }
124
+
125
+ onResize() {
126
+ this.windowHeight = window.innerHeight;
127
+ this.windowWidth = window.innerWidth;
128
+ this.limitScroll();
129
+ }
130
+
131
+ update() {
132
+ // Smooth interpolation
133
+ const diff = this.targetY - this.scrollY;
134
+ if (Math.abs(diff) > 0.01) {
135
+ this.scrollY += diff * this.options.lerp;
136
+ this.isScrolling = true;
137
+ } else {
138
+ this.scrollY = this.targetY;
139
+ this.stopScrolling();
140
+ }
141
+
142
+ // Apply transform to content
143
+ this.content.style.transform = `translate3d(0, -${this.scrollY}px, 0)`;
144
+
145
+ // Dispatch scroll event
146
+ this.dispatchScrollEvent();
147
+ }
148
+
149
+ loop() {
150
+ this.update();
151
+ this.rafId = requestAnimationFrame(() => this.loop());
152
+ }
153
+
154
+ dispatchScrollEvent() {
155
+ const event = new CustomEvent('scroll', {
156
+ detail: {
157
+ y: this.scrollY,
158
+ targetY: this.targetY,
159
+ limit: Math.max(0, this.content.offsetHeight - this.windowHeight),
160
+ progress: this.scrollY / Math.max(1, this.content.offsetHeight - this.windowHeight),
161
+ speed: this.options.speed
162
+ }
163
+ });
164
+ document.dispatchEvent(event);
165
+ }
166
+
167
+ scrollTo(target, duration = 1000) {
168
+ const startY = this.scrollY;
169
+ let endY = typeof target === 'number' ? target :
170
+ target.getBoundingClientRect().top + this.scrollY;
171
+
172
+ // Clamp end position
173
+ const maxScroll = Math.max(0, this.content.offsetHeight - this.windowHeight);
174
+ endY = Math.max(0, Math.min(endY, maxScroll));
175
+
176
+ const startTime = Date.now();
177
+
178
+ const easeInOut = (t) => {
179
+ return t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t;
180
+ };
181
+
182
+ const animate = () => {
183
+ const elapsed = Date.now() - startTime;
184
+ const progress = Math.min(elapsed / duration, 1);
185
+ const easedProgress = easeInOut(progress);
186
+
187
+ this.targetY = startY + (endY - startY) * easedProgress;
188
+ this.limitScroll();
189
+ this.startScrolling();
190
+
191
+ if (progress < 1) {
192
+ requestAnimationFrame(animate);
193
+ }
194
+ };
195
+
196
+ animate();
197
+ }
198
+
199
+ destroy() {
200
+ if (this.rafId) {
201
+ cancelAnimationFrame(this.rafId);
202
+ }
203
+
204
+ window.removeEventListener('wheel', this.onWheel);
205
+ window.removeEventListener('touchstart', this.onTouchStart);
206
+ window.removeEventListener('touchmove', this.onTouchMove);
207
+ window.removeEventListener('resize', this.onResize);
208
+
209
+ // Restore content
210
+ while (this.content.firstChild) {
211
+ this.body.appendChild(this.content.firstChild);
212
+ }
213
+ this.content.remove();
214
+
215
+ // Restore styles
216
+ this.body.style.margin = '';
217
+ this.body.style.overflow = '';
218
+ this.body.style.height = '';
219
+ this.body.style.position = '';
220
+ this.html.style.overflow = '';
221
+ this.html.style.height = '';
222
+
223
+ this.html.classList.remove('has-scroll-smooth');
224
+ this.html.classList.remove('has-scroll-scrolling');
225
+ this.html.classList.remove('has-scroll-init');
226
+ }
227
+ }
228
+
229
+ // Auto-initialize
230
+ if (document.body.hasAttribute('scroll') || document.body.hasAttribute('data-scroll')) {
231
+ if (document.readyState === 'loading') {
232
+ document.addEventListener('DOMContentLoaded', () => {
233
+ window.simpleScroll = new SimpleScroll();
234
+ });
235
+ } else {
236
+ window.simpleScroll = new SimpleScroll();
237
+ }
238
+ }
239
+
240
+ // Export for npm
241
+ if (typeof module !== 'undefined' && module.exports) {
242
+ module.exports = SimpleScroll;
243
+ }
244
+ })();