scroll-snap-kit 1.0.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 +302 -36
- 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 +28 -13
- package/src/index.d.ts +281 -0
- package/src/index.js +11 -0
- package/src/utils.js +589 -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
|
@@ -4,6 +4,10 @@
|
|
|
4
4
|
|
|
5
5
|
Zero dependencies. Tree-shakeable. Works with or without React.
|
|
6
6
|
|
|
7
|
+
[](https://www.npmjs.com/package/scroll-snap-kit)
|
|
8
|
+
[](./LICENSE)
|
|
9
|
+
[](https://bundlephobia.com/package/scroll-snap-kit)
|
|
10
|
+
|
|
7
11
|
---
|
|
8
12
|
|
|
9
13
|
## Install
|
|
@@ -14,27 +18,65 @@ npm install scroll-snap-kit
|
|
|
14
18
|
|
|
15
19
|
---
|
|
16
20
|
|
|
21
|
+
## What's included
|
|
22
|
+
|
|
23
|
+
| Utility | Description |
|
|
24
|
+
|---------|-------------|
|
|
25
|
+
| `scrollTo` | Smooth scroll to an element or pixel value |
|
|
26
|
+
| `scrollToTop` / `scrollToBottom` | Page-level scroll helpers |
|
|
27
|
+
| `getScrollPosition` | Current scroll x/y + percentages |
|
|
28
|
+
| `onScroll` | Throttled scroll listener with cleanup |
|
|
29
|
+
| `isInViewport` | Check if an element is visible |
|
|
30
|
+
| `lockScroll` / `unlockScroll` | Freeze body scroll, restore position |
|
|
31
|
+
| `scrollSpy` | Highlight nav links based on active section |
|
|
32
|
+
| `onScrollEnd` | Fire a callback when scrolling stops |
|
|
33
|
+
| `scrollIntoViewIfNeeded` | Only scroll if element is off-screen |
|
|
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 |
|
|
39
|
+
|
|
40
|
+
| Hook | Description |
|
|
41
|
+
|------|-------------|
|
|
42
|
+
| `useScrollPosition` | Live scroll position + percentage |
|
|
43
|
+
| `useInViewport` | Whether a ref'd element is visible |
|
|
44
|
+
| `useScrollTo` | Scroll function scoped to a container ref |
|
|
45
|
+
| `useScrolledPast` | Boolean — has user scrolled past a threshold |
|
|
46
|
+
| `useScrollDirection` | `'up'` \| `'down'` \| `null` |
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
17
50
|
## Vanilla JS Utilities
|
|
18
51
|
|
|
19
52
|
```js
|
|
20
|
-
import {
|
|
53
|
+
import {
|
|
54
|
+
scrollTo, scrollToTop, scrollToBottom,
|
|
55
|
+
getScrollPosition, onScroll, isInViewport,
|
|
56
|
+
lockScroll, unlockScroll,
|
|
57
|
+
scrollSpy, onScrollEnd, scrollIntoViewIfNeeded,
|
|
58
|
+
easeScroll, Easings,
|
|
59
|
+
scrollSequence, parallax, scrollProgress, snapToSection
|
|
60
|
+
} from 'scroll-snap-kit';
|
|
21
61
|
```
|
|
22
62
|
|
|
63
|
+
---
|
|
64
|
+
|
|
23
65
|
### `scrollTo(target, options?)`
|
|
24
66
|
|
|
25
67
|
Smoothly scroll to a DOM element or a Y pixel value.
|
|
26
68
|
|
|
27
69
|
```js
|
|
28
70
|
scrollTo(document.querySelector('#section'));
|
|
29
|
-
scrollTo(500);
|
|
30
|
-
scrollTo(document.querySelector('#hero'), { offset: -80 }); //
|
|
71
|
+
scrollTo(500); // scroll to y=500px
|
|
72
|
+
scrollTo(document.querySelector('#hero'), { offset: -80 }); // offset for sticky headers
|
|
31
73
|
```
|
|
32
74
|
|
|
33
75
|
| Option | Type | Default | Description |
|
|
34
76
|
|--------|------|---------|-------------|
|
|
35
77
|
| `behavior` | `'smooth' \| 'instant'` | `'smooth'` | Scroll behavior |
|
|
36
78
|
| `block` | `ScrollLogicalPosition` | `'start'` | Vertical alignment |
|
|
37
|
-
| `offset` | `number` | `0` | Pixel offset
|
|
79
|
+
| `offset` | `number` | `0` | Pixel offset (e.g. `-80` for a sticky nav) |
|
|
38
80
|
|
|
39
81
|
---
|
|
40
82
|
|
|
@@ -49,9 +91,13 @@ scrollToBottom({ behavior: 'instant' });
|
|
|
49
91
|
|
|
50
92
|
### `getScrollPosition(container?)`
|
|
51
93
|
|
|
94
|
+
Returns the current scroll position and scroll percentage for the page or any scrollable container.
|
|
95
|
+
|
|
52
96
|
```js
|
|
53
97
|
const { x, y, percentX, percentY } = getScrollPosition();
|
|
54
|
-
// percentY
|
|
98
|
+
// percentY → how far down the page (0–100)
|
|
99
|
+
|
|
100
|
+
const pos = getScrollPosition(document.querySelector('.sidebar'));
|
|
55
101
|
```
|
|
56
102
|
|
|
57
103
|
---
|
|
@@ -61,14 +107,18 @@ const { x, y, percentX, percentY } = getScrollPosition();
|
|
|
61
107
|
Throttled scroll listener. Returns a cleanup function.
|
|
62
108
|
|
|
63
109
|
```js
|
|
64
|
-
const stop = onScroll(({ y, percentY }) => {
|
|
110
|
+
const stop = onScroll(({ x, y, percentX, percentY }) => {
|
|
65
111
|
console.log(`Scrolled ${percentY}% down`);
|
|
66
|
-
}, { throttle:
|
|
112
|
+
}, { throttle: 100 });
|
|
67
113
|
|
|
68
|
-
// Later:
|
|
69
114
|
stop(); // removes the listener
|
|
70
115
|
```
|
|
71
116
|
|
|
117
|
+
| Option | Type | Default | Description |
|
|
118
|
+
|--------|------|---------|-------------|
|
|
119
|
+
| `throttle` | `number` | `100` | Minimum ms between callbacks |
|
|
120
|
+
| `container` | `Element` | `window` | Scrollable container to listen on |
|
|
121
|
+
|
|
72
122
|
---
|
|
73
123
|
|
|
74
124
|
### `isInViewport(element, options?)`
|
|
@@ -79,76 +129,259 @@ if (isInViewport(document.querySelector('.card'), { threshold: 0.5 })) {
|
|
|
79
129
|
}
|
|
80
130
|
```
|
|
81
131
|
|
|
132
|
+
| Option | Type | Default | Description |
|
|
133
|
+
|--------|------|---------|-------------|
|
|
134
|
+
| `threshold` | `number` | `0` | 0–1 portion of element that must be visible |
|
|
135
|
+
|
|
82
136
|
---
|
|
83
137
|
|
|
84
138
|
### `lockScroll()` / `unlockScroll()`
|
|
85
139
|
|
|
86
|
-
|
|
140
|
+
```js
|
|
141
|
+
lockScroll(); // body stops scrolling, position saved
|
|
142
|
+
unlockScroll(); // position restored precisely — no layout jump
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
---
|
|
146
|
+
|
|
147
|
+
### `scrollSpy(sectionsSelector, linksSelector, options?)`
|
|
148
|
+
|
|
149
|
+
Watches scroll position and automatically adds an active class to the nav link matching the current section.
|
|
150
|
+
|
|
151
|
+
```js
|
|
152
|
+
const stop = scrollSpy(
|
|
153
|
+
'section[id]',
|
|
154
|
+
'nav a',
|
|
155
|
+
{ offset: 80, activeClass: 'scroll-spy-active' }
|
|
156
|
+
);
|
|
157
|
+
|
|
158
|
+
stop(); // remove listener
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
```css
|
|
162
|
+
nav a.scroll-spy-active {
|
|
163
|
+
color: #00ffaa;
|
|
164
|
+
border-bottom: 1px solid currentColor;
|
|
165
|
+
}
|
|
166
|
+
```
|
|
167
|
+
|
|
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 |
|
|
172
|
+
|
|
173
|
+
---
|
|
174
|
+
|
|
175
|
+
### `onScrollEnd(callback, options?)`
|
|
176
|
+
|
|
177
|
+
Fires once the user has stopped scrolling for a configurable delay.
|
|
178
|
+
|
|
179
|
+
```js
|
|
180
|
+
const stop = onScrollEnd(() => {
|
|
181
|
+
console.log('User stopped scrolling!');
|
|
182
|
+
saveScrollPosition();
|
|
183
|
+
}, { delay: 200 });
|
|
184
|
+
|
|
185
|
+
stop();
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
| Option | Type | Default | Description |
|
|
189
|
+
|--------|------|---------|-------------|
|
|
190
|
+
| `delay` | `number` | `150` | ms of idle scrolling before callback fires |
|
|
191
|
+
| `container` | `Element` | `window` | Scrollable container to watch |
|
|
192
|
+
|
|
193
|
+
---
|
|
194
|
+
|
|
195
|
+
### `scrollIntoViewIfNeeded(element, options?)`
|
|
196
|
+
|
|
197
|
+
Scrolls to an element only if it is outside the visible viewport. If it's already visible enough, nothing happens.
|
|
198
|
+
|
|
199
|
+
```js
|
|
200
|
+
scrollIntoViewIfNeeded(document.querySelector('.card'));
|
|
201
|
+
scrollIntoViewIfNeeded(element, { threshold: 0.5, offset: -80 });
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
| Option | Type | Default | Description |
|
|
205
|
+
|--------|------|---------|-------------|
|
|
206
|
+
| `threshold` | `number` | `1` | 0–1 visibility ratio required to skip scrolling |
|
|
207
|
+
| `offset` | `number` | `0` | Pixel offset applied when scrolling |
|
|
208
|
+
| `behavior` | `'smooth' \| 'instant'` | `'smooth'` | Scroll behavior |
|
|
209
|
+
|
|
210
|
+
---
|
|
211
|
+
|
|
212
|
+
### `easeScroll(target, options?)` + `Easings`
|
|
213
|
+
|
|
214
|
+
Scroll to a position with a fully custom easing curve. Returns a `Promise` that resolves when animation completes.
|
|
215
|
+
|
|
216
|
+
```js
|
|
217
|
+
await easeScroll('#contact', { duration: 800, easing: Easings.easeOutElastic });
|
|
218
|
+
|
|
219
|
+
// Chain animations
|
|
220
|
+
await easeScroll('#hero', { duration: 600, easing: Easings.easeInOutCubic });
|
|
221
|
+
await easeScroll('#features', { duration: 400, easing: Easings.easeOutQuart });
|
|
222
|
+
|
|
223
|
+
// BYO easing function — any (t: 0→1) => (0→1)
|
|
224
|
+
easeScroll(element, { easing: t => t * t * t });
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
| Option | Type | Default | Description |
|
|
228
|
+
|--------|------|---------|-------------|
|
|
229
|
+
| `duration` | `number` | `600` | Animation duration in ms |
|
|
230
|
+
| `easing` | `(t: number) => number` | `Easings.easeInOutCubic` | Easing function |
|
|
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)`
|
|
238
|
+
|
|
239
|
+
Run multiple `easeScroll` animations one after another as a choreographed sequence. Supports pauses between steps. Returns `{ promise, cancel }`.
|
|
240
|
+
|
|
241
|
+
```js
|
|
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
|
|
250
|
+
```
|
|
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
|
|
87
292
|
|
|
88
293
|
```js
|
|
89
|
-
|
|
90
|
-
|
|
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
|
|
91
300
|
```
|
|
92
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
|
+
|
|
93
332
|
---
|
|
94
333
|
|
|
95
334
|
## React Hooks
|
|
96
335
|
|
|
97
336
|
```js
|
|
98
|
-
import {
|
|
337
|
+
import {
|
|
338
|
+
useScrollPosition, useInViewport, useScrollTo,
|
|
339
|
+
useScrolledPast, useScrollDirection
|
|
340
|
+
} from 'scroll-snap-kit/hooks';
|
|
99
341
|
```
|
|
100
342
|
|
|
343
|
+
> Requires React 16.8+. React is a peer dependency — install it separately.
|
|
344
|
+
|
|
345
|
+
---
|
|
346
|
+
|
|
101
347
|
### `useScrollPosition(options?)`
|
|
102
348
|
|
|
103
349
|
```jsx
|
|
104
350
|
function ProgressBar() {
|
|
105
351
|
const { percentY } = useScrollPosition({ throttle: 50 });
|
|
106
|
-
return <div style={{ width: `${percentY}%` }} className="progress" />;
|
|
352
|
+
return <div style={{ width: `${percentY}%` }} className="progress-bar" />;
|
|
107
353
|
}
|
|
108
354
|
```
|
|
109
355
|
|
|
110
|
-
---
|
|
111
|
-
|
|
112
356
|
### `useInViewport(options?)`
|
|
113
357
|
|
|
114
358
|
```jsx
|
|
115
|
-
function
|
|
359
|
+
function FadeInCard() {
|
|
116
360
|
const [ref, inView] = useInViewport({ threshold: 0.2, once: true });
|
|
117
361
|
return (
|
|
118
362
|
<div ref={ref} style={{ opacity: inView ? 1 : 0, transition: 'opacity 0.5s' }}>
|
|
119
|
-
|
|
363
|
+
Fades in when visible!
|
|
120
364
|
</div>
|
|
121
365
|
);
|
|
122
366
|
}
|
|
123
367
|
```
|
|
124
368
|
|
|
125
|
-
| Option | Type | Default | Description |
|
|
126
|
-
|--------|------|---------|-------------|
|
|
127
|
-
| `threshold` | `number` | `0` | 0–1 portion of element visible to trigger |
|
|
128
|
-
| `once` | `boolean` | `false` | Only trigger the first time |
|
|
129
|
-
|
|
130
|
-
---
|
|
131
|
-
|
|
132
369
|
### `useScrollTo()`
|
|
133
370
|
|
|
134
371
|
```jsx
|
|
135
372
|
function Page() {
|
|
136
373
|
const [containerRef, scrollToTarget] = useScrollTo();
|
|
137
374
|
const sectionRef = useRef(null);
|
|
138
|
-
|
|
139
375
|
return (
|
|
140
376
|
<div ref={containerRef} style={{ overflowY: 'scroll', height: '400px' }}>
|
|
141
|
-
<button onClick={() => scrollToTarget(sectionRef.current)}>Jump
|
|
142
|
-
<div
|
|
143
|
-
<div ref={sectionRef}>Target section</div>
|
|
377
|
+
<button onClick={() => scrollToTarget(sectionRef.current)}>Jump</button>
|
|
378
|
+
<div ref={sectionRef}>Target</div>
|
|
144
379
|
</div>
|
|
145
380
|
);
|
|
146
381
|
}
|
|
147
382
|
```
|
|
148
383
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
### `useScrolledPast(threshold?, options?)`
|
|
384
|
+
### `useScrolledPast(threshold?)`
|
|
152
385
|
|
|
153
386
|
```jsx
|
|
154
387
|
function BackToTopButton() {
|
|
@@ -157,12 +390,10 @@ function BackToTopButton() {
|
|
|
157
390
|
}
|
|
158
391
|
```
|
|
159
392
|
|
|
160
|
-
---
|
|
161
|
-
|
|
162
393
|
### `useScrollDirection()`
|
|
163
394
|
|
|
164
395
|
```jsx
|
|
165
|
-
function
|
|
396
|
+
function HideOnScrollNav() {
|
|
166
397
|
const direction = useScrollDirection();
|
|
167
398
|
return (
|
|
168
399
|
<nav style={{ transform: direction === 'down' ? 'translateY(-100%)' : 'translateY(0)' }}>
|
|
@@ -172,10 +403,45 @@ function Navbar() {
|
|
|
172
403
|
}
|
|
173
404
|
```
|
|
174
405
|
|
|
175
|
-
|
|
406
|
+
---
|
|
407
|
+
|
|
408
|
+
## Tree-shaking
|
|
409
|
+
|
|
410
|
+
All exports are named and side-effect free:
|
|
411
|
+
|
|
412
|
+
```js
|
|
413
|
+
import { scrollToTop } from 'scroll-snap-kit'; // ~400 bytes
|
|
414
|
+
import { onScroll, scrollSpy } from 'scroll-snap-kit/utils';
|
|
415
|
+
import { useScrollPosition } from 'scroll-snap-kit/hooks';
|
|
416
|
+
```
|
|
417
|
+
|
|
418
|
+
---
|
|
419
|
+
|
|
420
|
+
## Browser support
|
|
421
|
+
|
|
422
|
+
All modern browsers. `easeScroll` and `scrollSequence` use `requestAnimationFrame`. `useInViewport` / `isInViewport` use `IntersectionObserver` — polyfill if you need IE11.
|
|
423
|
+
|
|
424
|
+
---
|
|
425
|
+
|
|
426
|
+
## Changelog
|
|
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
|
+
|
|
434
|
+
### v1.1.0
|
|
435
|
+
- ✨ `scrollSpy()` — highlight nav links by active section
|
|
436
|
+
- ✨ `onScrollEnd()` — callback when scrolling stops
|
|
437
|
+
- ✨ `scrollIntoViewIfNeeded()` — scroll only when off-screen
|
|
438
|
+
- ✨ `easeScroll()` + `Easings` — custom easing engine with 11 built-in curves
|
|
439
|
+
|
|
440
|
+
### v1.0.0
|
|
441
|
+
- 🎉 Initial release — 8 core utilities and 5 React hooks
|
|
176
442
|
|
|
177
443
|
---
|
|
178
444
|
|
|
179
445
|
## License
|
|
180
446
|
|
|
181
|
-
MIT
|
|
447
|
+
MIT © Fabian Faraz Farid
|