scroll-snap-kit 1.1.0 → 2.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 +138 -120
- package/dist/index.cjs.js +913 -0
- package/dist/index.d.ts +281 -0
- package/dist/index.esm.js +885 -0
- package/dist/index.umd.js +779 -0
- package/package.json +21 -10
- package/src/index.d.ts +281 -0
- package/src/index.js +5 -0
- package/src/utils.js +406 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Fabian Faraz Farid
|
|
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
CHANGED
|
@@ -32,6 +32,10 @@ npm install scroll-snap-kit
|
|
|
32
32
|
| `onScrollEnd` | Fire a callback when scrolling stops |
|
|
33
33
|
| `scrollIntoViewIfNeeded` | Only scroll if element is off-screen |
|
|
34
34
|
| `easeScroll` + `Easings` | Custom easing curves for scroll animation |
|
|
35
|
+
| `scrollSequence` | Chain multiple scroll animations in order |
|
|
36
|
+
| `parallax` | Attach parallax speed multipliers to elements |
|
|
37
|
+
| `scrollProgress` | Track how far through an element the user has scrolled |
|
|
38
|
+
| `snapToSection` | Auto-snap to the nearest section after scrolling stops |
|
|
35
39
|
|
|
36
40
|
| Hook | Description |
|
|
37
41
|
|------|-------------|
|
|
@@ -51,7 +55,8 @@ import {
|
|
|
51
55
|
getScrollPosition, onScroll, isInViewport,
|
|
52
56
|
lockScroll, unlockScroll,
|
|
53
57
|
scrollSpy, onScrollEnd, scrollIntoViewIfNeeded,
|
|
54
|
-
easeScroll, Easings
|
|
58
|
+
easeScroll, Easings,
|
|
59
|
+
scrollSequence, parallax, scrollProgress, snapToSection
|
|
55
60
|
} from 'scroll-snap-kit';
|
|
56
61
|
```
|
|
57
62
|
|
|
@@ -92,7 +97,6 @@ Returns the current scroll position and scroll percentage for the page or any sc
|
|
|
92
97
|
const { x, y, percentX, percentY } = getScrollPosition();
|
|
93
98
|
// percentY → how far down the page (0–100)
|
|
94
99
|
|
|
95
|
-
// Works on containers too
|
|
96
100
|
const pos = getScrollPosition(document.querySelector('.sidebar'));
|
|
97
101
|
```
|
|
98
102
|
|
|
@@ -100,7 +104,7 @@ const pos = getScrollPosition(document.querySelector('.sidebar'));
|
|
|
100
104
|
|
|
101
105
|
### `onScroll(callback, options?)`
|
|
102
106
|
|
|
103
|
-
Throttled scroll listener. Returns a cleanup function
|
|
107
|
+
Throttled scroll listener. Returns a cleanup function.
|
|
104
108
|
|
|
105
109
|
```js
|
|
106
110
|
const stop = onScroll(({ x, y, percentX, percentY }) => {
|
|
@@ -119,8 +123,6 @@ stop(); // removes the listener
|
|
|
119
123
|
|
|
120
124
|
### `isInViewport(element, options?)`
|
|
121
125
|
|
|
122
|
-
Check whether an element is currently visible in the viewport.
|
|
123
|
-
|
|
124
126
|
```js
|
|
125
127
|
if (isInViewport(document.querySelector('.card'), { threshold: 0.5 })) {
|
|
126
128
|
// At least 50% of the card is visible
|
|
@@ -135,47 +137,44 @@ if (isInViewport(document.querySelector('.card'), { threshold: 0.5 })) {
|
|
|
135
137
|
|
|
136
138
|
### `lockScroll()` / `unlockScroll()`
|
|
137
139
|
|
|
138
|
-
Lock page scroll (e.g. when a modal is open) and restore the exact position on unlock — no layout jump.
|
|
139
|
-
|
|
140
140
|
```js
|
|
141
141
|
lockScroll(); // body stops scrolling, position saved
|
|
142
|
-
unlockScroll(); // position restored precisely
|
|
142
|
+
unlockScroll(); // position restored precisely — no layout jump
|
|
143
143
|
```
|
|
144
144
|
|
|
145
145
|
---
|
|
146
146
|
|
|
147
147
|
### `scrollSpy(sectionsSelector, linksSelector, options?)`
|
|
148
148
|
|
|
149
|
-
Watches scroll position and automatically adds an active class to the nav link matching the current section.
|
|
149
|
+
Watches scroll position and automatically adds an active class to the nav link matching the current section.
|
|
150
150
|
|
|
151
151
|
```js
|
|
152
152
|
const stop = scrollSpy(
|
|
153
|
-
'section[id]',
|
|
154
|
-
'nav a',
|
|
155
|
-
{
|
|
156
|
-
offset: 80, // px from top to trigger (default: 0)
|
|
157
|
-
activeClass: 'scroll-spy-active' // class to toggle (default: 'scroll-spy-active')
|
|
158
|
-
}
|
|
153
|
+
'section[id]',
|
|
154
|
+
'nav a',
|
|
155
|
+
{ offset: 80, activeClass: 'scroll-spy-active' }
|
|
159
156
|
);
|
|
160
157
|
|
|
161
|
-
stop(); // remove
|
|
158
|
+
stop(); // remove listener
|
|
162
159
|
```
|
|
163
160
|
|
|
164
161
|
```css
|
|
165
|
-
/* Style the active link however you like */
|
|
166
162
|
nav a.scroll-spy-active {
|
|
167
163
|
color: #00ffaa;
|
|
168
164
|
border-bottom: 1px solid currentColor;
|
|
169
165
|
}
|
|
170
166
|
```
|
|
171
167
|
|
|
172
|
-
|
|
168
|
+
| Option | Type | Default | Description |
|
|
169
|
+
|--------|------|---------|-------------|
|
|
170
|
+
| `offset` | `number` | `0` | px from top to trigger section change |
|
|
171
|
+
| `activeClass` | `string` | `'scroll-spy-active'` | Class added to the active link |
|
|
173
172
|
|
|
174
173
|
---
|
|
175
174
|
|
|
176
175
|
### `onScrollEnd(callback, options?)`
|
|
177
176
|
|
|
178
|
-
Fires
|
|
177
|
+
Fires once the user has stopped scrolling for a configurable delay.
|
|
179
178
|
|
|
180
179
|
```js
|
|
181
180
|
const stop = onScrollEnd(() => {
|
|
@@ -183,7 +182,7 @@ const stop = onScrollEnd(() => {
|
|
|
183
182
|
saveScrollPosition();
|
|
184
183
|
}, { delay: 200 });
|
|
185
184
|
|
|
186
|
-
stop();
|
|
185
|
+
stop();
|
|
187
186
|
```
|
|
188
187
|
|
|
189
188
|
| Option | Type | Default | Description |
|
|
@@ -195,13 +194,10 @@ stop(); // cleanup
|
|
|
195
194
|
|
|
196
195
|
### `scrollIntoViewIfNeeded(element, options?)`
|
|
197
196
|
|
|
198
|
-
Scrolls to an element only if it is
|
|
197
|
+
Scrolls to an element only if it is outside the visible viewport. If it's already visible enough, nothing happens.
|
|
199
198
|
|
|
200
199
|
```js
|
|
201
|
-
// Only scrolls if the element is off-screen
|
|
202
200
|
scrollIntoViewIfNeeded(document.querySelector('.card'));
|
|
203
|
-
|
|
204
|
-
// threshold: how much must be visible before we skip scrolling
|
|
205
201
|
scrollIntoViewIfNeeded(element, { threshold: 0.5, offset: -80 });
|
|
206
202
|
```
|
|
207
203
|
|
|
@@ -215,14 +211,10 @@ scrollIntoViewIfNeeded(element, { threshold: 0.5, offset: -80 });
|
|
|
215
211
|
|
|
216
212
|
### `easeScroll(target, options?)` + `Easings`
|
|
217
213
|
|
|
218
|
-
Scroll to a position with a fully custom easing curve
|
|
214
|
+
Scroll to a position with a fully custom easing curve. Returns a `Promise` that resolves when animation completes.
|
|
219
215
|
|
|
220
216
|
```js
|
|
221
|
-
|
|
222
|
-
await easeScroll('#contact', {
|
|
223
|
-
duration: 800,
|
|
224
|
-
easing: Easings.easeOutElastic
|
|
225
|
-
});
|
|
217
|
+
await easeScroll('#contact', { duration: 800, easing: Easings.easeOutElastic });
|
|
226
218
|
|
|
227
219
|
// Chain animations
|
|
228
220
|
await easeScroll('#hero', { duration: 600, easing: Easings.easeInOutCubic });
|
|
@@ -236,37 +228,115 @@ easeScroll(element, { easing: t => t * t * t });
|
|
|
236
228
|
|--------|------|---------|-------------|
|
|
237
229
|
| `duration` | `number` | `600` | Animation duration in ms |
|
|
238
230
|
| `easing` | `(t: number) => number` | `Easings.easeInOutCubic` | Easing function |
|
|
239
|
-
| `offset` | `number` | `0` | Pixel offset applied to target
|
|
231
|
+
| `offset` | `number` | `0` | Pixel offset applied to target |
|
|
232
|
+
|
|
233
|
+
**Built-in easings:** `linear`, `easeInQuad`, `easeOutQuad`, `easeInOutQuad`, `easeInCubic`, `easeOutCubic`, `easeInOutCubic`, `easeInQuart`, `easeOutQuart`, `easeOutElastic`, `easeOutBounce`
|
|
234
|
+
|
|
235
|
+
---
|
|
236
|
+
|
|
237
|
+
### `scrollSequence(steps)`
|
|
240
238
|
|
|
241
|
-
|
|
239
|
+
Run multiple `easeScroll` animations one after another as a choreographed sequence. Supports pauses between steps. Returns `{ promise, cancel }`.
|
|
242
240
|
|
|
243
241
|
```js
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
Easings.
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
Easings.easeInOutCubic // ← default
|
|
253
|
-
Easings.easeInQuart
|
|
254
|
-
Easings.easeOutQuart
|
|
255
|
-
Easings.easeOutElastic // springy overshoot
|
|
256
|
-
Easings.easeOutBounce // bouncy landing
|
|
242
|
+
const { promise, cancel } = scrollSequence([
|
|
243
|
+
{ target: '#intro', duration: 600 },
|
|
244
|
+
{ target: '#features', duration: 800, pause: 400 }, // pause 400ms before next step
|
|
245
|
+
{ target: '#pricing', duration: 600, easing: Easings.easeOutElastic },
|
|
246
|
+
]);
|
|
247
|
+
|
|
248
|
+
await promise; // resolves when all steps complete
|
|
249
|
+
cancel(); // abort at any point mid-sequence
|
|
257
250
|
```
|
|
258
251
|
|
|
252
|
+
| Step option | Type | Default | Description |
|
|
253
|
+
|-------------|------|---------|-------------|
|
|
254
|
+
| `target` | `Element \| string \| number` | — | Scroll destination (required) |
|
|
255
|
+
| `duration` | `number` | `600` | Duration of this step in ms |
|
|
256
|
+
| `easing` | `Function` | `easeInOutCubic` | Easing for this step |
|
|
257
|
+
| `offset` | `number` | `0` | Pixel offset |
|
|
258
|
+
| `pause` | `number` | `0` | ms to wait after this step before the next |
|
|
259
|
+
|
|
260
|
+
---
|
|
261
|
+
|
|
262
|
+
### `parallax(targets, options?)`
|
|
263
|
+
|
|
264
|
+
Attach a parallax scroll effect to one or more elements. Each element moves relative to its original position at the given `speed` multiplier.
|
|
265
|
+
|
|
266
|
+
```js
|
|
267
|
+
// speed < 1 = moves slower than scroll (background feel)
|
|
268
|
+
// speed > 1 = moves faster than scroll (foreground feel)
|
|
269
|
+
// speed < 0 = moves in the opposite direction to scroll
|
|
270
|
+
|
|
271
|
+
const destroy = parallax('.hero-bg', { speed: 0.4 });
|
|
272
|
+
const destroy = parallax('.clouds', { speed: -0.2, axis: 'x' });
|
|
273
|
+
const destroy = parallax([el1, el2], { speed: 0.6, axis: 'both' });
|
|
274
|
+
|
|
275
|
+
destroy(); // removes the effect and resets all transforms
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
| Option | Type | Default | Description |
|
|
279
|
+
|--------|------|---------|-------------|
|
|
280
|
+
| `speed` | `number` | `0.5` | Movement multiplier |
|
|
281
|
+
| `axis` | `'y' \| 'x' \| 'both'` | `'y'` | Axis to apply parallax on |
|
|
282
|
+
| `container` | `Element` | `window` | Scrollable container |
|
|
283
|
+
|
|
284
|
+
---
|
|
285
|
+
|
|
286
|
+
### `scrollProgress(element, callback, options?)`
|
|
287
|
+
|
|
288
|
+
Track how far the user has scrolled through a specific element, independent of overall page progress.
|
|
289
|
+
|
|
290
|
+
- `0` = element top just entered the bottom of the viewport
|
|
291
|
+
- `1` = element bottom just exited the top of the viewport
|
|
292
|
+
|
|
293
|
+
```js
|
|
294
|
+
const stop = scrollProgress('#article', (progress) => {
|
|
295
|
+
progressBar.style.width = `${progress * 100}%`;
|
|
296
|
+
if (progress === 1) console.log('Article fully read!');
|
|
297
|
+
});
|
|
298
|
+
|
|
299
|
+
stop(); // cleanup
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
| Option | Type | Default | Description |
|
|
303
|
+
|--------|------|---------|-------------|
|
|
304
|
+
| `offset` | `number` | `0` | Pixel adjustment to progress calculation |
|
|
305
|
+
|
|
306
|
+
---
|
|
307
|
+
|
|
308
|
+
### `snapToSection(sections, options?)`
|
|
309
|
+
|
|
310
|
+
After the user stops scrolling, automatically snap to the nearest section. Returns a destroy function.
|
|
311
|
+
|
|
312
|
+
```js
|
|
313
|
+
const destroy = snapToSection('section[id]', {
|
|
314
|
+
delay: 150, // ms to wait after scroll stops (default: 150)
|
|
315
|
+
offset: -70, // account for sticky nav (default: 0)
|
|
316
|
+
duration: 500, // snap animation duration (default: 500)
|
|
317
|
+
easing: Easings.easeInOutCubic // snap animation easing
|
|
318
|
+
});
|
|
319
|
+
|
|
320
|
+
destroy(); // remove snap behaviour
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
| Option | Type | Default | Description |
|
|
324
|
+
|--------|------|---------|-------------|
|
|
325
|
+
| `delay` | `number` | `150` | ms after scrolling stops before snap fires |
|
|
326
|
+
| `offset` | `number` | `0` | Pixel offset applied to snap target |
|
|
327
|
+
| `duration` | `number` | `500` | Snap animation duration in ms |
|
|
328
|
+
| `easing` | `Function` | `Easings.easeInOutCubic` | Snap animation easing |
|
|
329
|
+
|
|
330
|
+
> Works on both window scroll and scrollable containers. Pass an array of elements instead of a selector for more control.
|
|
331
|
+
|
|
259
332
|
---
|
|
260
333
|
|
|
261
334
|
## React Hooks
|
|
262
335
|
|
|
263
336
|
```js
|
|
264
337
|
import {
|
|
265
|
-
useScrollPosition,
|
|
266
|
-
|
|
267
|
-
useScrollTo,
|
|
268
|
-
useScrolledPast,
|
|
269
|
-
useScrollDirection
|
|
338
|
+
useScrollPosition, useInViewport, useScrollTo,
|
|
339
|
+
useScrolledPast, useScrollDirection
|
|
270
340
|
} from 'scroll-snap-kit/hooks';
|
|
271
341
|
```
|
|
272
342
|
|
|
@@ -276,129 +346,71 @@ import {
|
|
|
276
346
|
|
|
277
347
|
### `useScrollPosition(options?)`
|
|
278
348
|
|
|
279
|
-
Returns the current scroll position, updated live on scroll.
|
|
280
|
-
|
|
281
349
|
```jsx
|
|
282
350
|
function ProgressBar() {
|
|
283
|
-
const {
|
|
351
|
+
const { percentY } = useScrollPosition({ throttle: 50 });
|
|
284
352
|
return <div style={{ width: `${percentY}%` }} className="progress-bar" />;
|
|
285
353
|
}
|
|
286
354
|
```
|
|
287
355
|
|
|
288
|
-
| Option | Type | Default | Description |
|
|
289
|
-
|--------|------|---------|-------------|
|
|
290
|
-
| `throttle` | `number` | `100` | ms between updates |
|
|
291
|
-
| `container` | `Element` | `window` | Scrollable container |
|
|
292
|
-
|
|
293
|
-
---
|
|
294
|
-
|
|
295
356
|
### `useInViewport(options?)`
|
|
296
357
|
|
|
297
|
-
Returns a `[ref, inView]` tuple. Attach `ref` to any element to track its viewport visibility using `IntersectionObserver`.
|
|
298
|
-
|
|
299
358
|
```jsx
|
|
300
359
|
function FadeInCard() {
|
|
301
360
|
const [ref, inView] = useInViewport({ threshold: 0.2, once: true });
|
|
302
|
-
|
|
303
361
|
return (
|
|
304
|
-
<div
|
|
305
|
-
|
|
306
|
-
style={{
|
|
307
|
-
opacity: inView ? 1 : 0,
|
|
308
|
-
transform: inView ? 'translateY(0)' : 'translateY(20px)',
|
|
309
|
-
transition: 'all 0.5s ease'
|
|
310
|
-
}}
|
|
311
|
-
>
|
|
312
|
-
I animate in when visible!
|
|
362
|
+
<div ref={ref} style={{ opacity: inView ? 1 : 0, transition: 'opacity 0.5s' }}>
|
|
363
|
+
Fades in when visible!
|
|
313
364
|
</div>
|
|
314
365
|
);
|
|
315
366
|
}
|
|
316
367
|
```
|
|
317
368
|
|
|
318
|
-
| Option | Type | Default | Description |
|
|
319
|
-
|--------|------|---------|-------------|
|
|
320
|
-
| `threshold` | `number` | `0` | 0–1 portion of element visible to trigger |
|
|
321
|
-
| `once` | `boolean` | `false` | Only trigger on first entry, then stop observing |
|
|
322
|
-
|
|
323
|
-
---
|
|
324
|
-
|
|
325
369
|
### `useScrollTo()`
|
|
326
370
|
|
|
327
|
-
Returns a `[containerRef, scrollToTarget]` tuple. Scope smooth scrolling to a specific scrollable container, or fall back to window scroll.
|
|
328
|
-
|
|
329
371
|
```jsx
|
|
330
|
-
function
|
|
372
|
+
function Page() {
|
|
331
373
|
const [containerRef, scrollToTarget] = useScrollTo();
|
|
332
374
|
const sectionRef = useRef(null);
|
|
333
|
-
|
|
334
375
|
return (
|
|
335
376
|
<div ref={containerRef} style={{ overflowY: 'scroll', height: '400px' }}>
|
|
336
|
-
<button onClick={() => scrollToTarget(sectionRef.current
|
|
337
|
-
|
|
338
|
-
</button>
|
|
339
|
-
<div style={{ height: 300 }} />
|
|
340
|
-
<div ref={sectionRef}>Target section</div>
|
|
377
|
+
<button onClick={() => scrollToTarget(sectionRef.current)}>Jump</button>
|
|
378
|
+
<div ref={sectionRef}>Target</div>
|
|
341
379
|
</div>
|
|
342
380
|
);
|
|
343
381
|
}
|
|
344
382
|
```
|
|
345
383
|
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
### `useScrolledPast(threshold?, options?)`
|
|
349
|
-
|
|
350
|
-
Returns `true` once the user has scrolled past a given pixel value. Useful for showing back-to-top buttons, sticky CTAs, and similar patterns.
|
|
384
|
+
### `useScrolledPast(threshold?)`
|
|
351
385
|
|
|
352
386
|
```jsx
|
|
353
387
|
function BackToTopButton() {
|
|
354
388
|
const scrolledPast = useScrolledPast(300);
|
|
355
|
-
return scrolledPast ?
|
|
356
|
-
<button onClick={() => scrollToTop()}>↑ Back to top</button>
|
|
357
|
-
) : null;
|
|
389
|
+
return scrolledPast ? <button onClick={scrollToTop}>↑ Top</button> : null;
|
|
358
390
|
}
|
|
359
391
|
```
|
|
360
392
|
|
|
361
|
-
| Param | Type | Default | Description |
|
|
362
|
-
|-------|------|---------|-------------|
|
|
363
|
-
| `threshold` | `number` | `100` | Y pixel value to check against |
|
|
364
|
-
| `options.container` | `Element` | `window` | Scrollable container |
|
|
365
|
-
|
|
366
|
-
---
|
|
367
|
-
|
|
368
393
|
### `useScrollDirection()`
|
|
369
394
|
|
|
370
|
-
Returns the current scroll direction: `'up'`, `'down'`, or `null` on initial render.
|
|
371
|
-
|
|
372
395
|
```jsx
|
|
373
396
|
function HideOnScrollNav() {
|
|
374
397
|
const direction = useScrollDirection();
|
|
375
|
-
|
|
376
398
|
return (
|
|
377
|
-
<nav style={{
|
|
378
|
-
transform: direction === 'down' ? 'translateY(-100%)' : 'translateY(0)',
|
|
379
|
-
transition: 'transform 0.3s ease'
|
|
380
|
-
}}>
|
|
399
|
+
<nav style={{ transform: direction === 'down' ? 'translateY(-100%)' : 'translateY(0)' }}>
|
|
381
400
|
My Navbar
|
|
382
401
|
</nav>
|
|
383
402
|
);
|
|
384
403
|
}
|
|
385
404
|
```
|
|
386
405
|
|
|
387
|
-
| Option | Type | Default | Description |
|
|
388
|
-
|--------|------|---------|-------------|
|
|
389
|
-
| `throttle` | `number` | `100` | ms between direction checks |
|
|
390
|
-
|
|
391
406
|
---
|
|
392
407
|
|
|
393
408
|
## Tree-shaking
|
|
394
409
|
|
|
395
|
-
All exports are named and side-effect free
|
|
410
|
+
All exports are named and side-effect free:
|
|
396
411
|
|
|
397
412
|
```js
|
|
398
|
-
|
|
399
|
-
import { scrollToTop } from 'scroll-snap-kit';
|
|
400
|
-
|
|
401
|
-
// Import utils and hooks separately for maximum tree-shaking
|
|
413
|
+
import { scrollToTop } from 'scroll-snap-kit'; // ~400 bytes
|
|
402
414
|
import { onScroll, scrollSpy } from 'scroll-snap-kit/utils';
|
|
403
415
|
import { useScrollPosition } from 'scroll-snap-kit/hooks';
|
|
404
416
|
```
|
|
@@ -407,12 +419,18 @@ import { useScrollPosition } from 'scroll-snap-kit/hooks';
|
|
|
407
419
|
|
|
408
420
|
## Browser support
|
|
409
421
|
|
|
410
|
-
All modern browsers
|
|
422
|
+
All modern browsers. `easeScroll` and `scrollSequence` use `requestAnimationFrame`. `useInViewport` / `isInViewport` use `IntersectionObserver` — polyfill if you need IE11.
|
|
411
423
|
|
|
412
424
|
---
|
|
413
425
|
|
|
414
426
|
## Changelog
|
|
415
427
|
|
|
428
|
+
### v1.2.0
|
|
429
|
+
- ✨ `scrollSequence()` — chain multiple scroll animations with pauses and cancel support
|
|
430
|
+
- ✨ `parallax()` — multi-element parallax with configurable speed, axis, and cleanup
|
|
431
|
+
- ✨ `scrollProgress()` — per-element scroll progress tracking (0→1)
|
|
432
|
+
- ✨ `snapToSection()` — auto-snap to nearest section after scrolling stops
|
|
433
|
+
|
|
416
434
|
### v1.1.0
|
|
417
435
|
- ✨ `scrollSpy()` — highlight nav links by active section
|
|
418
436
|
- ✨ `onScrollEnd()` — callback when scrolling stops
|