@riverflowpkg/riverflow 1.0.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/LICENSE +21 -0
- package/README.md +51 -0
- package/bar/bar.js +90 -0
- package/bar/theCodes.html +144 -0
- package/editor/editor.js +312 -0
- package/editor/highlight.min.js +2441 -0
- package/editor/terminal.js +309 -0
- package/effects/typing.js +105 -0
- package/effects/underwater.js +117 -0
- package/package.json +32 -0
- package/scroll/scroll.css +91 -0
- package/scroll/scroll.js +244 -0
package/scroll/scroll.js
ADDED
|
@@ -0,0 +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
|
+
})();
|