use-scroller 2.0.0 → 2.1.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/README.md +8 -5
- package/dist/{chunk-BDIJT5M4.js → chunk-IFT3KMZJ.js} +28 -13
- package/dist/core.d.ts +3 -1
- package/dist/core.js +3 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +3 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -104,7 +104,8 @@ It sets `touch-action: pan-y pinch-zoom` on the track (`pan-x pinch-zoom` for `a
|
|
|
104
104
|
cross-axis movement scrolls the page natively and pinch-zoom keeps working. A gesture
|
|
105
105
|
is judged after 8px: mostly sideways and the track follows the finger, otherwise it is left to the
|
|
106
106
|
browser. Release continues with momentum and lands on a CSS scroll-snap position if the track has
|
|
107
|
-
any.
|
|
107
|
+
any. Like native scrolling, it never carries past a snap position whose area has
|
|
108
|
+
`scroll-snap-stop: always`. A drag doesn't fire a click on whatever is under the finger. Wheel, trackpad, keyboard and the scrollbar stay
|
|
108
109
|
native. `mouse: true` also lets a mouse drag the track.
|
|
109
110
|
|
|
110
111
|
### `useScrollLock`
|
|
@@ -298,6 +299,7 @@ const stop = observeActiveSection(sections, (index) => highlight(index), {
|
|
|
298
299
|
readScroll(target) // { x, y, minX, maxX, maxY, viewportWidth, viewportHeight }
|
|
299
300
|
isScrollable(element, 'y')
|
|
300
301
|
findScrollParent(element, 'y') // nearest scrollable ancestor, or window
|
|
302
|
+
readSnapPositions(element, 'x') // CSS scroll-snap positions the container can rest at, ascending
|
|
301
303
|
```
|
|
302
304
|
|
|
303
305
|
## Recipes
|
|
@@ -431,11 +433,12 @@ names its axis, and the package is ESM-only.
|
|
|
431
433
|
| `createEasingAnimation`, `createMomentumAnimation` | Removed. Use `animateScroll` |
|
|
432
434
|
| Types `ScrollOptions`, `EasingOptions`, `UseScrollReturn` | `AnimateScrollOptions`, `ScrollAnimation`, `Easing`, `ScrollActions`, `ScrollState` |
|
|
433
435
|
|
|
434
|
-
##
|
|
436
|
+
## Demo site
|
|
435
437
|
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
438
|
+
[silverlila.github.io/use-scroller](https://silverlila.github.io/use-scroller/) walks through every
|
|
439
|
+
export with its code and a live demo. The source is in `site/`: run `yarn` at the root, then
|
|
440
|
+
`npm install && npm run dev` inside `site/`; the dev server listens on your LAN so you can open it on
|
|
441
|
+
a phone.
|
|
439
442
|
|
|
440
443
|
## License
|
|
441
444
|
|
|
@@ -600,21 +600,25 @@ function fling(target, axis, velocity) {
|
|
|
600
600
|
// src/core/snap.ts
|
|
601
601
|
var FLICK_VELOCITY = 300;
|
|
602
602
|
function readSnapPositions(container, axis) {
|
|
603
|
+
return readSnapPoints(container, axis).map(({ position }) => position);
|
|
604
|
+
}
|
|
605
|
+
function readSnapPoints(container, axis) {
|
|
603
606
|
const containerStyle = getComputedStyle(container);
|
|
604
607
|
if (containerStyle.scrollSnapType === "none") return [];
|
|
605
608
|
const rightToLeft = axis === "x" && containerStyle.direction === "rtl";
|
|
606
609
|
const port = scrollport(container, axis);
|
|
607
610
|
const origin = contentOrigin(container, axis);
|
|
608
611
|
const metrics = readScroll(container);
|
|
609
|
-
const
|
|
612
|
+
const stops = /* @__PURE__ */ new Map();
|
|
610
613
|
for (const [child, style] of snapAreaCandidates(container)) {
|
|
611
614
|
const logical = snapAlignment(style.scrollSnapAlign, axis);
|
|
612
615
|
if (logical === null) continue;
|
|
613
616
|
const alignment = rightToLeft ? mirrored(logical) : logical;
|
|
614
617
|
const area = snapArea(child, style, origin, axis);
|
|
615
|
-
|
|
618
|
+
const position = clampToRange(metrics, axis, alignedPosition(area, port, alignment));
|
|
619
|
+
stops.set(position, stops.get(position) === true || style.scrollSnapStop === "always");
|
|
616
620
|
}
|
|
617
|
-
return [...
|
|
621
|
+
return [...stops].map(([position, stop]) => ({ position, stop })).sort((a, b) => a.position - b.position);
|
|
618
622
|
}
|
|
619
623
|
function* snapAreaCandidates(root) {
|
|
620
624
|
for (const child of root.children) {
|
|
@@ -636,6 +640,14 @@ function pickSnapTarget(positions, current, projected, velocity) {
|
|
|
636
640
|
if (ahead.length === 0) return nearest;
|
|
637
641
|
return direction > 0 ? ahead[0] : ahead[ahead.length - 1];
|
|
638
642
|
}
|
|
643
|
+
function stopShortOfSnapStops(points, current, target) {
|
|
644
|
+
const direction = Math.sign(target - current);
|
|
645
|
+
const passed = points.filter(
|
|
646
|
+
({ position, stop }) => stop && (position - current) * direction > EDGE_TOLERANCE && (target - position) * direction > 0
|
|
647
|
+
);
|
|
648
|
+
if (passed.length === 0) return target;
|
|
649
|
+
return direction > 0 ? passed[0].position : passed[passed.length - 1].position;
|
|
650
|
+
}
|
|
639
651
|
function snapAlignment(value, axis) {
|
|
640
652
|
const [block, inline = block] = value.split(" ");
|
|
641
653
|
const keyword = axis === "x" ? inline : block;
|
|
@@ -732,9 +744,9 @@ function dragScroll(element, { axis = "x", mouse = false } = {}) {
|
|
|
732
744
|
}
|
|
733
745
|
function interruptRelease() {
|
|
734
746
|
if (!release) return null;
|
|
735
|
-
const { handle,
|
|
747
|
+
const { handle, points } = release;
|
|
736
748
|
handle.cancel();
|
|
737
|
-
return {
|
|
749
|
+
return { points, restore: suspendSnap2() };
|
|
738
750
|
}
|
|
739
751
|
function suspendSnap2() {
|
|
740
752
|
return setInlineStyles(element, { "scroll-snap-type": "none" });
|
|
@@ -763,7 +775,7 @@ function dragScroll(element, { axis = "x", mouse = false } = {}) {
|
|
|
763
775
|
element.setPointerCapture(event.pointerId);
|
|
764
776
|
cancelScroll(element);
|
|
765
777
|
const snap = (_a = pending.snap) != null ? _a : {
|
|
766
|
-
|
|
778
|
+
points: readSnapPoints(element, axis),
|
|
767
779
|
restore: suspendSnap2()
|
|
768
780
|
};
|
|
769
781
|
const startScroll = readScroll(element)[axis];
|
|
@@ -797,24 +809,26 @@ function dragScroll(element, { axis = "x", mouse = false } = {}) {
|
|
|
797
809
|
if ((ended == null ? void 0 : ended.kind) === "dragging") ended.restoreUserSelect();
|
|
798
810
|
if (ended == null ? void 0 : ended.snap) settle(ended.snap, velocity);
|
|
799
811
|
}
|
|
800
|
-
function settle({
|
|
801
|
-
if (
|
|
812
|
+
function settle({ points, restore }, velocity) {
|
|
813
|
+
if (points.length === 0) {
|
|
802
814
|
restore();
|
|
803
|
-
track(fling(element, axis, velocity),
|
|
815
|
+
track(fling(element, axis, velocity), points);
|
|
804
816
|
return;
|
|
805
817
|
}
|
|
806
818
|
const current = readScroll(element)[axis];
|
|
807
|
-
const
|
|
819
|
+
const positions = points.map(({ position }) => position);
|
|
820
|
+
const picked = pickSnapTarget(positions, current, current + projectMomentum(velocity), velocity);
|
|
821
|
+
const target = stopShortOfSnapStops(points, current, picked);
|
|
808
822
|
restore();
|
|
809
823
|
const handle = animateScroll(element, axis === "x" ? { x: target } : { y: target }, {
|
|
810
824
|
animation: { type: "spring", velocity: axis === "x" ? { x: velocity } : { y: velocity } },
|
|
811
825
|
respectReducedMotion: false
|
|
812
826
|
});
|
|
813
|
-
track(handle,
|
|
827
|
+
track(handle, points);
|
|
814
828
|
}
|
|
815
|
-
function track(handle,
|
|
829
|
+
function track(handle, points) {
|
|
816
830
|
if (!handle) return;
|
|
817
|
-
const current = { handle,
|
|
831
|
+
const current = { handle, points };
|
|
818
832
|
release = current;
|
|
819
833
|
void handle.finished.then(() => {
|
|
820
834
|
if (release === current) release = null;
|
|
@@ -1178,6 +1192,7 @@ export {
|
|
|
1178
1192
|
initialScrollState,
|
|
1179
1193
|
observeScroll,
|
|
1180
1194
|
lockScroll,
|
|
1195
|
+
readSnapPositions,
|
|
1181
1196
|
dragScroll,
|
|
1182
1197
|
scrollToEdge,
|
|
1183
1198
|
scrollBy,
|
package/dist/core.d.ts
CHANGED
|
@@ -91,6 +91,8 @@ interface DragScrollOptions {
|
|
|
91
91
|
}
|
|
92
92
|
declare function dragScroll(element: HTMLElement, { axis, mouse }?: DragScrollOptions): () => void;
|
|
93
93
|
|
|
94
|
+
declare function readSnapPositions(container: HTMLElement, axis: Axis): number[];
|
|
95
|
+
|
|
94
96
|
declare function observeActiveSection(sections: HTMLElement[], listener: (index: number) => void, { root, offset }?: {
|
|
95
97
|
root?: ScrollTarget;
|
|
96
98
|
offset?: number;
|
|
@@ -118,4 +120,4 @@ interface StickToBottom {
|
|
|
118
120
|
}
|
|
119
121
|
declare function stickToBottom(element: HTMLElement, onChange?: (isAtBottom: boolean) => void): StickToBottom;
|
|
120
122
|
|
|
121
|
-
export { type AnimateScrollOptions, type Axis, type DragScrollOptions, type Easing, type Edge, type RestoreScrollOptions, type ScrollAlign, type ScrollAnimation, type ScrollDestination, type ScrollHandle, type ScrollMetrics, type ScrollResult, type ScrollState, type ScrollTarget, type ScrollToElementOptions, type StickToBottom, animateScroll, cancelScroll, cubicBezier, dragScroll, easings, findScrollParent, isScrollable, lockScroll, observeActiveSection, observeScroll, readScroll, restoreScroll, scrollBy, scrollToEdge, scrollToElement, stickToBottom };
|
|
123
|
+
export { type AnimateScrollOptions, type Axis, type DragScrollOptions, type Easing, type Edge, type RestoreScrollOptions, type ScrollAlign, type ScrollAnimation, type ScrollDestination, type ScrollHandle, type ScrollMetrics, type ScrollResult, type ScrollState, type ScrollTarget, type ScrollToElementOptions, type StickToBottom, animateScroll, cancelScroll, cubicBezier, dragScroll, easings, findScrollParent, isScrollable, lockScroll, observeActiveSection, observeScroll, readScroll, readSnapPositions, restoreScroll, scrollBy, scrollToEdge, scrollToElement, stickToBottom };
|
package/dist/core.js
CHANGED
|
@@ -10,12 +10,13 @@ import {
|
|
|
10
10
|
observeActiveSection,
|
|
11
11
|
observeScroll,
|
|
12
12
|
readScroll,
|
|
13
|
+
readSnapPositions,
|
|
13
14
|
restoreScroll,
|
|
14
15
|
scrollBy,
|
|
15
16
|
scrollToEdge,
|
|
16
17
|
scrollToElement,
|
|
17
18
|
stickToBottom
|
|
18
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-IFT3KMZJ.js";
|
|
19
20
|
export {
|
|
20
21
|
animateScroll,
|
|
21
22
|
cancelScroll,
|
|
@@ -28,6 +29,7 @@ export {
|
|
|
28
29
|
observeActiveSection,
|
|
29
30
|
observeScroll,
|
|
30
31
|
readScroll,
|
|
32
|
+
readSnapPositions,
|
|
31
33
|
restoreScroll,
|
|
32
34
|
scrollBy,
|
|
33
35
|
scrollToEdge,
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ScrollDestination, AnimateScrollOptions, ScrollHandle, Edge, ScrollToElementOptions, ScrollState, DragScrollOptions, RestoreScrollOptions } from './core.js';
|
|
2
|
-
export { Axis, Easing, ScrollAlign, ScrollAnimation, ScrollMetrics, ScrollResult, ScrollTarget, StickToBottom, animateScroll, cancelScroll, cubicBezier, dragScroll, easings, findScrollParent, isScrollable, lockScroll, observeActiveSection, observeScroll, readScroll, restoreScroll, scrollBy, scrollToEdge, scrollToElement, stickToBottom } from './core.js';
|
|
2
|
+
export { Axis, Easing, ScrollAlign, ScrollAnimation, ScrollMetrics, ScrollResult, ScrollTarget, StickToBottom, animateScroll, cancelScroll, cubicBezier, dragScroll, easings, findScrollParent, isScrollable, lockScroll, observeActiveSection, observeScroll, readScroll, readSnapPositions, restoreScroll, scrollBy, scrollToEdge, scrollToElement, stickToBottom } from './core.js';
|
|
3
3
|
import { RefObject } from 'react';
|
|
4
4
|
|
|
5
5
|
type ElementTarget = RefObject<HTMLElement | null> | 'window';
|
package/dist/index.js
CHANGED
|
@@ -13,12 +13,13 @@ import {
|
|
|
13
13
|
observeActiveSection,
|
|
14
14
|
observeScroll,
|
|
15
15
|
readScroll,
|
|
16
|
+
readSnapPositions,
|
|
16
17
|
restoreScroll,
|
|
17
18
|
scrollBy,
|
|
18
19
|
scrollToEdge,
|
|
19
20
|
scrollToElement,
|
|
20
21
|
stickToBottom
|
|
21
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-IFT3KMZJ.js";
|
|
22
23
|
|
|
23
24
|
// src/react/use-scroll.ts
|
|
24
25
|
import { useRef as useRef2, useState } from "react";
|
|
@@ -330,6 +331,7 @@ export {
|
|
|
330
331
|
observeActiveSection,
|
|
331
332
|
observeScroll,
|
|
332
333
|
readScroll,
|
|
334
|
+
readSnapPositions,
|
|
333
335
|
restoreScroll,
|
|
334
336
|
scrollBy,
|
|
335
337
|
scrollToEdge,
|