@astryxdesign/core 0.7.6 → 0.7.7-canary.0eb44a2
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/dist/AppShell/AppShell.d.ts.map +1 -1
- package/dist/AppShell/AppShell.js +23 -3
- package/dist/Avatar/Avatar.d.ts.map +1 -1
- package/dist/Avatar/Avatar.js +1 -1
- package/dist/BottomSheet/BottomSheetPanel.d.ts.map +1 -1
- package/dist/BottomSheet/BottomSheetPanel.js +16 -9
- package/dist/Breadcrumbs/BreadcrumbItem.d.ts.map +1 -1
- package/dist/Breadcrumbs/BreadcrumbItem.js +2 -1
- package/dist/Button/Button.d.ts.map +1 -1
- package/dist/Button/Button.js +3 -2
- package/dist/Chat/ChatComposerInput.d.ts +9 -0
- package/dist/Chat/ChatComposerInput.d.ts.map +1 -1
- package/dist/Chat/ChatComposerInput.js +2 -0
- package/dist/Chat/ChatMessage.js +2 -2
- package/dist/Chat/chatMessage.vars.stylex.d.ts +8 -8
- package/dist/Chat/chatMessage.vars.stylex.js +8 -8
- package/dist/CommandPalette/CommandPaletteInput.d.ts.map +1 -1
- package/dist/CommandPalette/CommandPaletteInput.js +8 -1
- package/dist/DateInput/MonthScroller.d.ts.map +1 -1
- package/dist/DateInput/MonthScroller.js +72 -2
- package/dist/DateInput/Wheel.d.ts +17 -1
- package/dist/DateInput/Wheel.d.ts.map +1 -1
- package/dist/DateInput/Wheel.js +179 -19
- package/dist/DateRangeInput/DateRangeInput.d.ts.map +1 -1
- package/dist/DateRangeInput/DateRangeInput.js +63 -49
- package/dist/Dialog/Dialog.d.ts.map +1 -1
- package/dist/Dialog/Dialog.js +37 -1
- package/dist/Drawer/Drawer.d.ts.map +1 -1
- package/dist/Drawer/Drawer.js +6 -0
- package/dist/Drawer/useDrawerDialogPresence.d.ts.map +1 -1
- package/dist/Drawer/useDrawerDialogPresence.js +4 -0
- package/dist/DropdownMenu/DropdownMenu.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenu.js +20 -4
- package/dist/DropdownMenu/useMenuOverflow.d.ts +13 -3
- package/dist/DropdownMenu/useMenuOverflow.d.ts.map +1 -1
- package/dist/DropdownMenu/useMenuOverflow.js +31 -8
- package/dist/Field/PanelSearchInput.d.ts.map +1 -1
- package/dist/Field/PanelSearchInput.js +8 -1
- package/dist/Field/textEntryTraits.d.ts +6 -6
- package/dist/Field/textEntryTraits.js +6 -6
- package/dist/Layer/layerClickBoundary.d.ts +7 -1
- package/dist/Layer/layerClickBoundary.d.ts.map +1 -1
- package/dist/Layer/layerClickBoundary.js +2 -2
- package/dist/Layer/usePressPin.d.ts +95 -0
- package/dist/Layer/usePressPin.d.ts.map +1 -0
- package/dist/Layer/usePressPin.js +365 -0
- package/dist/Layer/useTouchTrigger.d.ts +23 -1
- package/dist/Layer/useTouchTrigger.d.ts.map +1 -1
- package/dist/Layer/useTouchTrigger.js +45 -7
- package/dist/Lightbox/Lightbox.d.ts.map +1 -1
- package/dist/Lightbox/Lightbox.js +2 -1
- package/dist/Link/Link.d.ts.map +1 -1
- package/dist/Link/Link.js +1 -0
- package/dist/Popover/usePopover.d.ts.map +1 -1
- package/dist/Popover/usePopover.js +56 -7
- package/dist/PowerSearch/PowerSearch.d.ts.map +1 -1
- package/dist/PowerSearch/PowerSearch.js +38 -30
- package/dist/ProgressBar/ProgressBar.d.ts +1 -1
- package/dist/ProgressBar/ProgressBar.d.ts.map +1 -1
- package/dist/ProgressBar/ProgressBar.js +52 -14
- package/dist/ProgressBar/ProgressBarTouch.d.ts +29 -0
- package/dist/ProgressBar/ProgressBarTouch.d.ts.map +1 -0
- package/dist/ProgressBar/ProgressBarTouch.js +91 -0
- package/dist/SegmentedControl/SegmentedControlItem.d.ts.map +1 -1
- package/dist/SegmentedControl/SegmentedControlItem.js +2 -1
- package/dist/Selector/Selector.d.ts.map +1 -1
- package/dist/Selector/Selector.js +25 -13
- package/dist/Slider/Slider.d.ts.map +1 -1
- package/dist/Slider/Slider.js +404 -131
- package/dist/Slider/sliderTouchController.d.ts +189 -0
- package/dist/Slider/sliderTouchController.d.ts.map +1 -0
- package/dist/Slider/sliderTouchController.js +1017 -0
- package/dist/Slider/useSliderTouch.d.ts +22 -0
- package/dist/Slider/useSliderTouch.d.ts.map +1 -0
- package/dist/Slider/useSliderTouch.js +56 -0
- package/dist/Switch/Switch.d.ts +1 -1
- package/dist/Switch/Switch.d.ts.map +1 -1
- package/dist/Switch/Switch.js +200 -46
- package/dist/Switch/switchFill.d.ts +31 -0
- package/dist/Switch/switchFill.d.ts.map +1 -0
- package/dist/Switch/switchFill.js +88 -0
- package/dist/Switch/switchTouch.d.ts +81 -0
- package/dist/Switch/switchTouch.d.ts.map +1 -0
- package/dist/Switch/switchTouch.js +133 -0
- package/dist/Switch/useSwitchTouch.d.ts +285 -0
- package/dist/Switch/useSwitchTouch.d.ts.map +1 -0
- package/dist/Switch/useSwitchTouch.js +998 -0
- package/dist/TabList/Tab.d.ts.map +1 -1
- package/dist/TabList/Tab.js +4 -3
- package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
- package/dist/Tokenizer/Tokenizer.js +12 -5
- package/dist/Tokenizer/TokenizerItemRemovableContext.d.ts +3 -0
- package/dist/Tokenizer/TokenizerItemRemovableContext.d.ts.map +1 -0
- package/dist/Tokenizer/TokenizerItemRemovableContext.js +17 -0
- package/dist/Tooltip/Tooltip.d.ts +30 -6
- package/dist/Tooltip/Tooltip.d.ts.map +1 -1
- package/dist/Tooltip/Tooltip.js +5 -0
- package/dist/Tooltip/index.d.ts +1 -1
- package/dist/Tooltip/index.d.ts.map +1 -1
- package/dist/Tooltip/useTooltip.d.ts +31 -5
- package/dist/Tooltip/useTooltip.d.ts.map +1 -1
- package/dist/Tooltip/useTooltip.js +59 -18
- package/dist/Typeahead/BaseTypeahead.d.ts.map +1 -1
- package/dist/Typeahead/BaseTypeahead.js +19 -9
- package/dist/Typeahead/Typeahead.d.ts.map +1 -1
- package/dist/Typeahead/Typeahead.js +26 -15
- package/dist/astryx.css +91 -8
- package/dist/gestures/GestureArena.d.ts +21 -2
- package/dist/gestures/GestureArena.d.ts.map +1 -1
- package/dist/gestures/GestureArena.js +23 -3
- package/dist/gestures/GestureHost.d.ts +123 -3
- package/dist/gestures/GestureHost.d.ts.map +1 -1
- package/dist/gestures/GestureHost.js +797 -15
- package/dist/gestures/GestureRecognizer.d.ts +15 -1
- package/dist/gestures/GestureRecognizer.d.ts.map +1 -1
- package/dist/gestures/GestureRecognizer.js +12 -0
- package/dist/gestures/PanGestureRecognizer.d.ts +8 -0
- package/dist/gestures/PanGestureRecognizer.d.ts.map +1 -1
- package/dist/gestures/PinchGestureRecognizer.d.ts +5 -1
- package/dist/gestures/PinchGestureRecognizer.d.ts.map +1 -1
- package/dist/gestures/PinchGestureRecognizer.js +10 -0
- package/dist/gestures/PressTracker.d.ts +6 -0
- package/dist/gestures/PressTracker.d.ts.map +1 -1
- package/dist/gestures/PressTracker.js +3 -0
- package/dist/gestures/ScreenEdgePanGestureRecognizer.d.ts +3 -3
- package/dist/gestures/ScreenEdgePanGestureRecognizer.d.ts.map +1 -1
- package/dist/gestures/ScreenEdgePanGestureRecognizer.js +7 -5
- package/dist/gestures/nativeScroll.d.ts +16 -2
- package/dist/gestures/nativeScroll.d.ts.map +1 -1
- package/dist/gestures/nativeScroll.js +39 -8
- package/dist/gestures/recognizerInternals.d.ts +4 -2
- package/dist/gestures/recognizerInternals.d.ts.map +1 -1
- package/dist/gestures/types.d.ts +17 -0
- package/dist/gestures/types.d.ts.map +1 -1
- package/dist/gestures/types.js +7 -0
- package/dist/gestures/usePressTracker.d.ts.map +1 -1
- package/dist/gestures/usePressTracker.js +1 -0
- package/dist/gestures/wheelSegmenter.d.ts +56 -0
- package/dist/gestures/wheelSegmenter.d.ts.map +1 -0
- package/dist/gestures/wheelSegmenter.js +122 -0
- package/dist/hooks/useAttachment.d.ts +16 -8
- package/dist/hooks/useAttachment.d.ts.map +1 -1
- package/dist/hooks/useAttachment.js +35 -15
- package/dist/hooks/useFocusTrap.d.ts +15 -0
- package/dist/hooks/useFocusTrap.d.ts.map +1 -1
- package/dist/hooks/useFocusTrap.js +13 -2
- package/dist/hooks/usePager.d.ts +261 -0
- package/dist/hooks/usePager.d.ts.map +1 -0
- package/dist/hooks/usePager.js +1169 -0
- package/dist/motion/animator.d.ts.map +1 -1
- package/dist/motion/animator.js +140 -19
- package/dist/motion/paging.d.ts +69 -0
- package/dist/motion/paging.d.ts.map +1 -0
- package/dist/motion/paging.js +148 -0
- package/dist/motion/uikit/index.d.ts +8 -4
- package/dist/motion/uikit/index.d.ts.map +1 -1
- package/dist/motion/uikit/index.js +8 -4
- package/dist/motion/uikit/paging.d.ts +171 -0
- package/dist/motion/uikit/paging.d.ts.map +1 -0
- package/dist/motion/uikit/paging.js +192 -0
- package/dist/motion/uikit/progressBar.d.ts +79 -0
- package/dist/motion/uikit/progressBar.d.ts.map +1 -0
- package/dist/motion/uikit/progressBar.js +102 -0
- package/dist/motion/uikit/scroll.d.ts +0 -19
- package/dist/motion/uikit/scroll.d.ts.map +1 -1
- package/dist/motion/uikit/scroll.js +2 -21
- package/dist/motion/uikit/slider.d.ts +97 -0
- package/dist/motion/uikit/slider.d.ts.map +1 -0
- package/dist/motion/uikit/slider.js +111 -0
- package/dist/motion/uikit/springs.d.ts +59 -30
- package/dist/motion/uikit/springs.d.ts.map +1 -1
- package/dist/motion/uikit/springs.js +64 -34
- package/dist/motion/uikit/switch.d.ts +166 -0
- package/dist/motion/uikit/switch.d.ts.map +1 -0
- package/dist/motion/uikit/switch.js +186 -0
- package/dist/privateAttributes/pressHoldsDrag.stylex.d.ts +18 -0
- package/dist/privateAttributes/pressHoldsDrag.stylex.d.ts.map +1 -0
- package/dist/privateAttributes/pressHoldsDrag.stylex.js +28 -0
- package/dist/utils/pressFeedback.d.ts.map +1 -1
- package/dist/utils/pressFeedback.js +5 -0
- package/dist/utils/selectionLock.d.ts +43 -0
- package/dist/utils/selectionLock.d.ts.map +1 -1
- package/dist/utils/selectionLock.js +394 -6
- package/package.json +5 -5
- package/src/AppShell/AppShell.doc.mjs +10 -0
- package/src/AppShell/AppShell.tsx +48 -2
- package/src/Avatar/Avatar.tsx +3 -1
- package/src/BottomSheet/BottomSheetPanel.tsx +16 -9
- package/src/Breadcrumbs/BreadcrumbItem.tsx +4 -1
- package/src/Button/Button.tsx +3 -2
- package/src/Chat/Chat.doc.mjs +1 -0
- package/src/Chat/ChatComposerInput.doc.mjs +11 -0
- package/src/Chat/ChatComposerInput.tsx +11 -0
- package/src/Chat/ChatMessage.tsx +2 -2
- package/src/Chat/chatMessage.vars.stylex.ts +8 -8
- package/src/CommandPalette/CommandPaletteInput.tsx +6 -0
- package/src/DateInput/MonthScroller.tsx +63 -5
- package/src/DateInput/Wheel.tsx +174 -14
- package/src/DateRangeInput/DateRangeInput.doc.mjs +3 -2
- package/src/DateRangeInput/DateRangeInput.tsx +117 -71
- package/src/Dialog/Dialog.tsx +37 -1
- package/src/Drawer/Drawer.tsx +6 -0
- package/src/Drawer/useDrawerDialogPresence.ts +4 -0
- package/src/DropdownMenu/DropdownMenu.tsx +28 -6
- package/src/DropdownMenu/useMenuOverflow.ts +44 -8
- package/src/Field/PanelSearchInput.tsx +6 -0
- package/src/Field/textEntryTraits.ts +6 -6
- package/src/Layer/layerClickBoundary.ts +2 -2
- package/src/Layer/usePressPin.ts +516 -0
- package/src/Layer/useTouchTrigger.ts +56 -6
- package/src/Lightbox/Lightbox.tsx +2 -1
- package/src/Link/Link.tsx +3 -0
- package/src/Popover/usePopover.tsx +71 -9
- package/src/PowerSearch/PowerSearch.tsx +38 -31
- package/src/ProgressBar/ProgressBar.doc.mjs +7 -5
- package/src/ProgressBar/ProgressBar.tsx +147 -16
- package/src/ProgressBar/ProgressBarTouch.ts +109 -0
- package/src/SegmentedControl/SegmentedControlItem.tsx +2 -1
- package/src/Selector/Selector.tsx +29 -2
- package/src/Slider/Slider.doc.mjs +11 -7
- package/src/Slider/Slider.tsx +539 -132
- package/src/Slider/sliderTouchController.ts +1209 -0
- package/src/Slider/useSliderTouch.ts +78 -0
- package/src/Switch/Switch.doc.mjs +3 -3
- package/src/Switch/Switch.tsx +412 -86
- package/src/Switch/switchFill.ts +106 -0
- package/src/Switch/switchTouch.ts +194 -0
- package/src/Switch/useSwitchTouch.ts +1121 -0
- package/src/TabList/Tab.tsx +5 -3
- package/src/Tokenizer/Tokenizer.tsx +15 -5
- package/src/Tokenizer/TokenizerItemRemovableContext.ts +22 -0
- package/src/Tooltip/Tooltip.doc.mjs +21 -6
- package/src/Tooltip/Tooltip.tsx +42 -5
- package/src/Tooltip/index.ts +1 -0
- package/src/Tooltip/useTooltip.doc.mjs +4 -2
- package/src/Tooltip/useTooltip.tsx +84 -21
- package/src/Typeahead/BaseTypeahead.tsx +16 -8
- package/src/Typeahead/Typeahead.tsx +29 -15
- package/src/gestures/GestureArena.ts +45 -4
- package/src/gestures/GestureHost.ts +958 -15
- package/src/gestures/GestureRecognizer.ts +28 -0
- package/src/gestures/PanGestureRecognizer.ts +8 -0
- package/src/gestures/PinchGestureRecognizer.ts +16 -1
- package/src/gestures/PressTracker.ts +10 -0
- package/src/gestures/README.md +82 -3
- package/src/gestures/ScreenEdgePanGestureRecognizer.ts +7 -5
- package/src/gestures/nativeScroll.ts +49 -9
- package/src/gestures/recognizerInternals.ts +9 -2
- package/src/gestures/types.ts +18 -0
- package/src/gestures/usePressTracker.ts +2 -0
- package/src/gestures/wheelSegmenter.ts +143 -0
- package/src/hooks/useAttachment.ts +56 -14
- package/src/hooks/useFocusTrap.ts +26 -2
- package/src/hooks/usePager.ts +1446 -0
- package/src/motion/MEASUREMENTS.md +36 -27
- package/src/motion/README.md +7 -3
- package/src/motion/animator.ts +193 -25
- package/src/motion/paging.ts +161 -0
- package/src/motion/uikit/index.ts +7 -4
- package/src/motion/uikit/paging.ts +193 -0
- package/src/motion/uikit/progressBar.ts +102 -0
- package/src/motion/uikit/scroll.ts +2 -18
- package/src/motion/uikit/slider.ts +105 -0
- package/src/motion/uikit/springs.ts +53 -32
- package/src/motion/uikit/switch.ts +174 -0
- package/src/privateAttributes/pressHoldsDrag.stylex.ts +28 -0
- package/src/utils/pressFeedback.ts +5 -0
- package/src/utils/selectionLock.ts +501 -6
- package/dist/motion/selectPage.d.ts +0 -26
- package/dist/motion/selectPage.d.ts.map +0 -1
- package/dist/motion/selectPage.js +0 -55
- package/src/motion/selectPage.ts +0 -55
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @file wheelSegmenter.ts
|
|
5
|
+
* @input A wheel stream's deltas along one axis, with their event times
|
|
6
|
+
* @output Exports WheelSegmenter and isBunched. WheelSegmenter splits the
|
|
7
|
+
* stream into gestures and reads a trackpad's lift (the onset of momentum).
|
|
8
|
+
* isBunched tells one stall's merge from a frame.
|
|
9
|
+
* @position Read by GestureHost.ts's wheel input: the web reports no
|
|
10
|
+
* trackpad contact or phase, so both are inferred.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
/** Momentum arrives at frame rate: a pause this long ends it. */
|
|
14
|
+
const MOMENTUM_GAP_MS = 50;
|
|
15
|
+
/**
|
|
16
|
+
* A wheel this close to the one before, ms, is one stall's merge. Frames come
|
|
17
|
+
* further apart at every display rate up to 500 Hz, which is 2 ms.
|
|
18
|
+
*/
|
|
19
|
+
const BUNCHED_MS = 1.5;
|
|
20
|
+
/** Shrinking deltas in a row before the lift is read. */
|
|
21
|
+
const LIFT_RUN = 4;
|
|
22
|
+
/** And how much of its size the run has lost by then. */
|
|
23
|
+
const LIFT_DECAY = 0.8;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Whether a wheel `intervalMs` after the one before is one stall's merge, not
|
|
27
|
+
* a frame. A stalled page receives the wheels it held back together, within
|
|
28
|
+
* 1.5 ms of each other. The rule reads no history, so slow wheels never make
|
|
29
|
+
* a real frame look like a merge.
|
|
30
|
+
*/
|
|
31
|
+
export function isBunched(intervalMs) {
|
|
32
|
+
return intervalMs <= BUNCHED_MS;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* A trackpad gesture has a finger phase and, after a fling, a momentum phase.
|
|
37
|
+
* In the finger phase, deltas come while the fingers move, with pauses when
|
|
38
|
+
* they move slowly. In the momentum phase, deltas come at frame rate and
|
|
39
|
+
* shrink smoothly. The lift is the start of a run of shrinking deltas that
|
|
40
|
+
* has lost a fifth of its size. In the finger phase, a pause of `idleMs`
|
|
41
|
+
* ends the gesture. In the momentum phase, a reversal, a jump up against the
|
|
42
|
+
* decay, or a pause of 50 ms starts a new gesture. A bunched wheel is never
|
|
43
|
+
* a jump. The decay reads it by its last step. Momentum never pauses,
|
|
44
|
+
* reverses or grows.
|
|
45
|
+
*/
|
|
46
|
+
export class WheelSegmenter {
|
|
47
|
+
gesture = 0;
|
|
48
|
+
phase = 'finger';
|
|
49
|
+
last = -Infinity;
|
|
50
|
+
previous = 0;
|
|
51
|
+
sign = 0;
|
|
52
|
+
count = 0;
|
|
53
|
+
run = 0;
|
|
54
|
+
runStart = 0;
|
|
55
|
+
push(time, delta, idleMs) {
|
|
56
|
+
const size = Math.abs(delta);
|
|
57
|
+
const sign = Math.sign(delta);
|
|
58
|
+
const gap = time - this.last;
|
|
59
|
+
const bunched = this.count > 0 && isBunched(gap);
|
|
60
|
+
let boundary = null;
|
|
61
|
+
if (this.count === 0) {
|
|
62
|
+
boundary = this.gesture === 0 ? 'first' : 'idle';
|
|
63
|
+
} else if (this.phase === 'finger' && gap >= idleMs) {
|
|
64
|
+
boundary = 'idle';
|
|
65
|
+
} else if (this.phase === 'momentum') {
|
|
66
|
+
if (sign !== 0 && this.sign !== 0 && sign !== this.sign) {
|
|
67
|
+
boundary = 'reversal';
|
|
68
|
+
} else if (gap >= MOMENTUM_GAP_MS) {
|
|
69
|
+
boundary = 'gap';
|
|
70
|
+
} else if (!bunched && size >= 2 && size > this.previous * 1.3 + 0.5) {
|
|
71
|
+
boundary = 'jump';
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
// A bunched wheel carries the steps of the frames it merged. The decay
|
|
75
|
+
// goes on from its last step, so the steps after it read as they are.
|
|
76
|
+
const steps = boundary == null && bunched && this.previous > 0 ? Math.max(1, Math.round(size / this.previous)) : 1;
|
|
77
|
+
if (boundary != null) {
|
|
78
|
+
this.gesture += 1;
|
|
79
|
+
this.phase = 'finger';
|
|
80
|
+
this.count = 0;
|
|
81
|
+
this.run = 0;
|
|
82
|
+
}
|
|
83
|
+
let liftNow = false;
|
|
84
|
+
let decaying = false;
|
|
85
|
+
if (this.phase === 'finger' && this.count >= 3 && size > 0) {
|
|
86
|
+
// A bunched wheel is read by its last step, as the decay goes on from it.
|
|
87
|
+
const step = size / steps;
|
|
88
|
+
decaying = step <= this.previous * 0.995 && step >= this.previous * 0.5;
|
|
89
|
+
if (decaying) {
|
|
90
|
+
if (this.run === 0) {
|
|
91
|
+
this.runStart = this.previous;
|
|
92
|
+
}
|
|
93
|
+
this.run += 1;
|
|
94
|
+
} else {
|
|
95
|
+
this.run = 0;
|
|
96
|
+
}
|
|
97
|
+
if (this.run >= LIFT_RUN && step <= this.runStart * LIFT_DECAY) {
|
|
98
|
+
this.phase = 'momentum';
|
|
99
|
+
liftNow = true;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
this.count += 1;
|
|
103
|
+
this.previous = size / steps;
|
|
104
|
+
if (sign !== 0) {
|
|
105
|
+
this.sign = sign;
|
|
106
|
+
}
|
|
107
|
+
this.last = time;
|
|
108
|
+
return {
|
|
109
|
+
boundary,
|
|
110
|
+
phase: this.phase,
|
|
111
|
+
gesture: this.gesture,
|
|
112
|
+
liftNow,
|
|
113
|
+
decaying: decaying && !liftNow,
|
|
114
|
+
bunched: boundary == null && bunched
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/** The gesture ended on its own (its timer): the next event starts one. */
|
|
119
|
+
end() {
|
|
120
|
+
this.count = 0;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @file useAttachment.ts
|
|
3
|
-
* @input
|
|
3
|
+
* @input Node refs (an element's, or the document's), an attach function
|
|
4
4
|
* and a key
|
|
5
|
-
* @output Exports useAttachment
|
|
6
|
-
* the
|
|
7
|
-
* @position Internal React helper, not in hooks/index.ts: the one attach
|
|
8
|
-
*
|
|
9
|
-
* usePressTracker, useFingerScroll)
|
|
5
|
+
* @output Exports useAttachment and useAttachmentPair (two elements): they keep
|
|
6
|
+
* the attach function bound to the nodes the refs hold across commits
|
|
7
|
+
* @position Internal React helper, not in hooks/index.ts: the one attach and
|
|
8
|
+
* release lifecycle of the gesture hooks and the pager
|
|
10
9
|
*
|
|
11
|
-
* SYNC: When modified, update gestures/__tests__/useGestureRecognizer.test.tsx
|
|
12
|
-
*
|
|
10
|
+
* SYNC: When modified, update gestures/__tests__/useGestureRecognizer.test.tsx,
|
|
11
|
+
* gestures/__tests__/useFingerScroll.test.tsx and
|
|
12
|
+
* __tests__/useAttachmentPair.test.tsx.
|
|
13
13
|
*/
|
|
14
14
|
import { type RefObject } from 'react';
|
|
15
15
|
/**
|
|
@@ -19,4 +19,12 @@ import { type RefObject } from 'react';
|
|
|
19
19
|
* a commit that changes neither does nothing (react-component-runtime INV3).
|
|
20
20
|
*/
|
|
21
21
|
export declare function useAttachment<T extends Node = Element>(ref: RefObject<T | null>, attach: (element: T) => () => void, key: unknown): void;
|
|
22
|
+
/**
|
|
23
|
+
* `useAttachment` for two elements. It keeps `attach` bound to the pair the
|
|
24
|
+
* refs hold after each commit, once both are there. Replacing either element
|
|
25
|
+
* releases the attachment and attaches the new pair. A changed `key`
|
|
26
|
+
* re-attaches, and the last attachment is released on unmount. A commit that
|
|
27
|
+
* changes neither does nothing.
|
|
28
|
+
*/
|
|
29
|
+
export declare function useAttachmentPair<A extends Element, B extends Element>(firstRef: RefObject<A | null>, secondRef: RefObject<B | null>, attach: (first: A, second: B) => () => void, key: unknown): void;
|
|
22
30
|
//# sourceMappingURL=useAttachment.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useAttachment.d.ts","sourceRoot":"","sources":["../../src/hooks/useAttachment.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAS,KAAK,SAAS,EAAC,MAAM,OAAO,CAAC;AAG7C;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,CAAC,SAAS,IAAI,GAAG,OAAO,EACpD,GAAG,EAAE,SAAS,CAAC,CAAC,GAAG,IAAI,CAAC,EACxB,MAAM,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,MAAM,IAAI,EAClC,GAAG,EAAE,OAAO,GACX,IAAI,
|
|
1
|
+
{"version":3,"file":"useAttachment.d.ts","sourceRoot":"","sources":["../../src/hooks/useAttachment.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAS,KAAK,SAAS,EAAC,MAAM,OAAO,CAAC;AAG7C;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,CAAC,SAAS,IAAI,GAAG,OAAO,EACpD,GAAG,EAAE,SAAS,CAAC,CAAC,GAAG,IAAI,CAAC,EACxB,MAAM,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,MAAM,IAAI,EAClC,GAAG,EAAE,OAAO,GACX,IAAI,CAEN;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,SAAS,OAAO,EAAE,CAAC,SAAS,OAAO,EACpE,QAAQ,EAAE,SAAS,CAAC,CAAC,GAAG,IAAI,CAAC,EAC7B,SAAS,EAAE,SAAS,CAAC,CAAC,GAAG,IAAI,CAAC,EAC9B,MAAM,EAAE,CAAC,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,KAAK,MAAM,IAAI,EAC3C,GAAG,EAAE,OAAO,GACX,IAAI,CAMN"}
|
|
@@ -4,16 +4,16 @@
|
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* @file useAttachment.ts
|
|
7
|
-
* @input
|
|
7
|
+
* @input Node refs (an element's, or the document's), an attach function
|
|
8
8
|
* and a key
|
|
9
|
-
* @output Exports useAttachment
|
|
10
|
-
* the
|
|
11
|
-
* @position Internal React helper, not in hooks/index.ts: the one attach
|
|
12
|
-
*
|
|
13
|
-
* usePressTracker, useFingerScroll)
|
|
9
|
+
* @output Exports useAttachment and useAttachmentPair (two elements): they keep
|
|
10
|
+
* the attach function bound to the nodes the refs hold across commits
|
|
11
|
+
* @position Internal React helper, not in hooks/index.ts: the one attach and
|
|
12
|
+
* release lifecycle of the gesture hooks and the pager
|
|
14
13
|
*
|
|
15
|
-
* SYNC: When modified, update gestures/__tests__/useGestureRecognizer.test.tsx
|
|
16
|
-
*
|
|
14
|
+
* SYNC: When modified, update gestures/__tests__/useGestureRecognizer.test.tsx,
|
|
15
|
+
* gestures/__tests__/useFingerScroll.test.tsx and
|
|
16
|
+
* __tests__/useAttachmentPair.test.tsx.
|
|
17
17
|
*/
|
|
18
18
|
import { useRef } from 'react';
|
|
19
19
|
import { useIsomorphicLayoutEffect } from "./useIsomorphicLayoutEffect.js";
|
|
@@ -25,21 +25,41 @@ import { useIsomorphicLayoutEffect } from "./useIsomorphicLayoutEffect.js";
|
|
|
25
25
|
* a commit that changes neither does nothing (react-component-runtime INV3).
|
|
26
26
|
*/
|
|
27
27
|
export function useAttachment(ref, attach, key) {
|
|
28
|
+
useAttachedNodes([ref], ([node]) => attach(node), key);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* `useAttachment` for two elements. It keeps `attach` bound to the pair the
|
|
33
|
+
* refs hold after each commit, once both are there. Replacing either element
|
|
34
|
+
* releases the attachment and attaches the new pair. A changed `key`
|
|
35
|
+
* re-attaches, and the last attachment is released on unmount. A commit that
|
|
36
|
+
* changes neither does nothing.
|
|
37
|
+
*/
|
|
38
|
+
export function useAttachmentPair(firstRef, secondRef, attach, key) {
|
|
39
|
+
useAttachedNodes([firstRef, secondRef], ([first, second]) => attach(first, second), key);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* The lifecycle both share: one attachment of the nodes the refs hold. It is
|
|
44
|
+
* made once every node is there, and released when a node or `key` changes
|
|
45
|
+
* and at unmount.
|
|
46
|
+
*/
|
|
47
|
+
function useAttachedNodes(refs, attach, key) {
|
|
28
48
|
const attachmentRef = useRef(null);
|
|
29
49
|
|
|
30
|
-
// Syncs the attachment with the DOM
|
|
50
|
+
// Syncs the attachment with the DOM nodes the refs hold after this commit.
|
|
31
51
|
useIsomorphicLayoutEffect(() => {
|
|
32
|
-
const
|
|
52
|
+
const nodes = refs.map(ref => ref.current);
|
|
33
53
|
const current = attachmentRef.current;
|
|
34
|
-
if (current
|
|
54
|
+
if (current != null && current.key === key && nodes.every((node, index) => node === current.nodes[index])) {
|
|
35
55
|
return;
|
|
36
56
|
}
|
|
37
57
|
current?.release();
|
|
38
|
-
attachmentRef.current =
|
|
39
|
-
|
|
58
|
+
attachmentRef.current = nodes.every(node => node != null) ? {
|
|
59
|
+
nodes: nodes,
|
|
40
60
|
key,
|
|
41
|
-
release: attach(
|
|
42
|
-
};
|
|
61
|
+
release: attach(nodes)
|
|
62
|
+
} : null;
|
|
43
63
|
});
|
|
44
64
|
|
|
45
65
|
// Releases the attachment at unmount.
|
|
@@ -83,4 +83,19 @@ export interface UseFocusTrapReturn<T extends HTMLElement = HTMLElement> {
|
|
|
83
83
|
* ```
|
|
84
84
|
*/
|
|
85
85
|
export declare function useFocusTrap<T extends HTMLElement = HTMLElement>(options: UseFocusTrapOptions): UseFocusTrapReturn<T>;
|
|
86
|
+
/**
|
|
87
|
+
* Package-internal options. Not re-exported from the package entry point.
|
|
88
|
+
*/
|
|
89
|
+
interface InternalFocusTrapOptions extends UseFocusTrapOptions {
|
|
90
|
+
/**
|
|
91
|
+
* The element to restore focus to on deactivation, read at activation. For
|
|
92
|
+
* an overlay that may move focus inside before the trap activates (initial
|
|
93
|
+
* focus within the opening event), the element focused at activation is
|
|
94
|
+
* already inside, so the overlay names its opener instead. Returning `null`
|
|
95
|
+
* falls back to the element focused at activation.
|
|
96
|
+
*/
|
|
97
|
+
getRestoreTarget?: () => HTMLElement | null;
|
|
98
|
+
}
|
|
99
|
+
export declare function useFocusTrapInternal<T extends HTMLElement = HTMLElement>(options: InternalFocusTrapOptions): UseFocusTrapReturn<T>;
|
|
100
|
+
export {};
|
|
86
101
|
//# sourceMappingURL=useFocusTrap.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useFocusTrap.d.ts","sourceRoot":"","sources":["../../src/hooks/useFocusTrap.ts"],"names":[],"mappings":"AA+BA;;;;;;;;GAQG;AACH,wBAAgB,wBAAwB,IAAI,OAAO,CAElD;AAED;;;;;;GAMG;AACH,wBAAgB,qCAAqC,CAAC,QAAQ,EAAE,OAAO,GAAG,IAAI,CAU7E;AA+BD;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,WAAW,GAAG,WAAW,EAAE,CAI1E;AA8DD;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC;;OAEG;IACH,QAAQ,EAAE,OAAO,CAAC;IAElB;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;CACvB;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB,CAAC,CAAC,SAAS,WAAW,GAAG,WAAW;IACrE;;OAEG;IACH,YAAY,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IAExC;;OAEG;IACH,UAAU,EAAE,MAAM,IAAI,CAAC;CACxB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,wBAAgB,YAAY,CAAC,CAAC,SAAS,WAAW,GAAG,WAAW,EAC9D,OAAO,EAAE,mBAAmB,GAC3B,kBAAkB,CAAC,CAAC,CAAC,
|
|
1
|
+
{"version":3,"file":"useFocusTrap.d.ts","sourceRoot":"","sources":["../../src/hooks/useFocusTrap.ts"],"names":[],"mappings":"AA+BA;;;;;;;;GAQG;AACH,wBAAgB,wBAAwB,IAAI,OAAO,CAElD;AAED;;;;;;GAMG;AACH,wBAAgB,qCAAqC,CAAC,QAAQ,EAAE,OAAO,GAAG,IAAI,CAU7E;AA+BD;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,WAAW,GAAG,WAAW,EAAE,CAI1E;AA8DD;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC;;OAEG;IACH,QAAQ,EAAE,OAAO,CAAC;IAElB;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;CACvB;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB,CAAC,CAAC,SAAS,WAAW,GAAG,WAAW;IACrE;;OAEG;IACH,YAAY,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IAExC;;OAEG;IACH,UAAU,EAAE,MAAM,IAAI,CAAC;CACxB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,wBAAgB,YAAY,CAAC,CAAC,SAAS,WAAW,GAAG,WAAW,EAC9D,OAAO,EAAE,mBAAmB,GAC3B,kBAAkB,CAAC,CAAC,CAAC,CAEvB;AAED;;GAEG;AACH,UAAU,wBAAyB,SAAQ,mBAAmB;IAC5D;;;;;;OAMG;IACH,gBAAgB,CAAC,EAAE,MAAM,WAAW,GAAG,IAAI,CAAC;CAC7C;AAED,wBAAgB,oBAAoB,CAAC,CAAC,SAAS,WAAW,GAAG,WAAW,EACtE,OAAO,EAAE,wBAAwB,GAChC,kBAAkB,CAAC,CAAC,CAAC,CA2QvB"}
|
|
@@ -200,10 +200,21 @@ function focusLastDescendant(container) {
|
|
|
200
200
|
* ```
|
|
201
201
|
*/
|
|
202
202
|
export function useFocusTrap(options) {
|
|
203
|
+
return useFocusTrapInternal(options);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Package-internal options. Not re-exported from the package entry point.
|
|
208
|
+
*/
|
|
209
|
+
|
|
210
|
+
export function useFocusTrapInternal(options) {
|
|
203
211
|
const {
|
|
204
212
|
isActive,
|
|
205
|
-
onEscape
|
|
213
|
+
onEscape,
|
|
214
|
+
getRestoreTarget
|
|
206
215
|
} = options;
|
|
216
|
+
const getRestoreTargetRef = useRef(getRestoreTarget);
|
|
217
|
+
getRestoreTargetRef.current = getRestoreTarget;
|
|
207
218
|
const containerRef = useRef(null);
|
|
208
219
|
const lastFocusRef = useRef(null);
|
|
209
220
|
// Track if focus change was triggered by keyboard (Tab key)
|
|
@@ -274,7 +285,7 @@ export function useFocusTrap(options) {
|
|
|
274
285
|
// Snapshot the container now; by cleanup it may be detached or unmounted.
|
|
275
286
|
const container = containerRef.current;
|
|
276
287
|
const doc = trapDocument(container);
|
|
277
|
-
const previouslyFocused = doc.activeElement;
|
|
288
|
+
const previouslyFocused = getRestoreTargetRef.current?.() ?? doc.activeElement;
|
|
278
289
|
|
|
279
290
|
// Whether focus ever entered the trap container while it was active.
|
|
280
291
|
// Initialized from the current active element in case focus was already
|
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file usePager.ts
|
|
3
|
+
* @input A viewport and its track, a page count and gap (or the track's
|
|
4
|
+
* children), the gesture system and the animator
|
|
5
|
+
* @output Exports `createPager` (the framework-free pager), `usePager` (its
|
|
6
|
+
* React face) and their types
|
|
7
|
+
* @position Shared hook for core components that page like a UIKit paging
|
|
8
|
+
* scroll view, such as Carousel's paging presentation
|
|
9
|
+
*
|
|
10
|
+
* SYNC: When modified, update:
|
|
11
|
+
* - /packages/core/src/hooks/usePager.test.ts
|
|
12
|
+
* - /packages/core/src/hooks/__tests__/usePager.interaction.browser.spec.ts
|
|
13
|
+
*/
|
|
14
|
+
import { type RefObject } from 'react';
|
|
15
|
+
import { type GestureHost } from '../gestures/GestureHost.js';
|
|
16
|
+
import { PanGestureRecognizer, type PanGestureRecognizerOptions } from '../gestures/PanGestureRecognizer.js';
|
|
17
|
+
import { type Animator } from '../motion/animator.js';
|
|
18
|
+
/** A release the pager settles: where the content is, how fast, and the page it left. */
|
|
19
|
+
export interface PageRelease {
|
|
20
|
+
/** Content offset at the lift, px, or pages for children pages (may be past either end). */
|
|
21
|
+
position: number;
|
|
22
|
+
/** Content velocity at the release, px/s (the shared release velocity). */
|
|
23
|
+
velocity: number;
|
|
24
|
+
/** Distance between consecutive pages: page width plus the gap, px (1 for children pages). */
|
|
25
|
+
stride: number;
|
|
26
|
+
/** Number of pages (at least 1). */
|
|
27
|
+
count: number;
|
|
28
|
+
/** The page the drag started on (its rest position when the finger landed). */
|
|
29
|
+
startIndex: number;
|
|
30
|
+
/** Wraps around: the target may leave [0, count - 1] (the owner wraps it). */
|
|
31
|
+
loop?: boolean;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* The page a release settles on. It applies UIKit's measured paging rule
|
|
35
|
+
* (`release` in uikit/paging.ts) through the release policy of
|
|
36
|
+
* resolveSnapPoint.ts, with the pager's own pages and thresholds.
|
|
37
|
+
*
|
|
38
|
+
* - A release at `advanceSpeed` or faster is a flick: it goes to the next page
|
|
39
|
+
* in the direction of the velocity, from any content position.
|
|
40
|
+
* - A slower release goes to the page nearest the content. UIKit's measured
|
|
41
|
+
* `commitFraction` is half a page, the policy's nearest snap point.
|
|
42
|
+
* - A release whose velocity points back toward the start page settles there,
|
|
43
|
+
* at any travel, through the policy's `start`.
|
|
44
|
+
* - The page is never more than `maxPagesFromStart` from the start page
|
|
45
|
+
* (`maxSteps`). It is clamped to the pages unless the pager loops.
|
|
46
|
+
* - The policy sees only the pages within that reach of the start page. So a
|
|
47
|
+
* looping target may leave the range, and the owner wraps it.
|
|
48
|
+
*
|
|
49
|
+
* With children pages, positions are in pages, but the velocity stays px/s.
|
|
50
|
+
* The policy reads the velocity only against `advanceSpeed` and for its
|
|
51
|
+
* direction.
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* ```
|
|
55
|
+
* // Released at rest 60 % of the way from page 1 to page 2: page 2.
|
|
56
|
+
* pageForRelease({position: 1.6 * 402, velocity: 0, stride: 402, count: 6, startIndex: 1});
|
|
57
|
+
* // Flicked forward at 600 px/s from 6 % past page 1: page 2.
|
|
58
|
+
* pageForRelease({position: 1.06 * 402, velocity: 600, stride: 402, count: 6, startIndex: 1});
|
|
59
|
+
* ```
|
|
60
|
+
*/
|
|
61
|
+
export declare function pageForRelease({ position, velocity, stride, count, startIndex, loop, }: PageRelease): number;
|
|
62
|
+
/** Why the target page changed. */
|
|
63
|
+
export type PagerChangeReason = 'drag' | 'goTo' | 'controlled';
|
|
64
|
+
export interface PagerOptions {
|
|
65
|
+
/** Number of pages (at least 1). */
|
|
66
|
+
count: number;
|
|
67
|
+
/** Space between pages, px; it shows only while a page moves. @default 0 */
|
|
68
|
+
gap?: number;
|
|
69
|
+
/** Pages wrap around; indexes become unbounded. @default false */
|
|
70
|
+
loop?: boolean;
|
|
71
|
+
/**
|
|
72
|
+
* What a page is. With `'viewport'`, every page is the viewport's width, at
|
|
73
|
+
* index × (width + `gap`). With `'children'`, each child of the track is a
|
|
74
|
+
* page at its own start edge, as `scroll-snap-align: start` places it.
|
|
75
|
+
*
|
|
76
|
+
* With children pages, the viewport's padding stays an inset. The travel
|
|
77
|
+
* ends where the track's end meets the end of the viewport's content box. A
|
|
78
|
+
* child whose start lies past that point rests there, so the last children
|
|
79
|
+
* can share one page. The count is then the number of distinct pages
|
|
80
|
+
* (`pageCount`). `count` and `gap` serve only before the first measure, and
|
|
81
|
+
* children pages do not loop. The pager measures the children on attach, on
|
|
82
|
+
* a resize, on an options change and when a drag begins. It never measures
|
|
83
|
+
* while a finger moves.
|
|
84
|
+
* @default 'viewport'
|
|
85
|
+
*/
|
|
86
|
+
pages?: 'viewport' | 'children';
|
|
87
|
+
/** Starting page. @default 0 */
|
|
88
|
+
defaultIndex?: number;
|
|
89
|
+
/**
|
|
90
|
+
* The target page changed (index wrapped into [0, count)). A release
|
|
91
|
+
* reports once its settle is moving; `index` has the page from the lift.
|
|
92
|
+
* A controlled move (the `index` prop, or a `count` that clamps the page)
|
|
93
|
+
* is the owner's own and is not reported.
|
|
94
|
+
*/
|
|
95
|
+
onIndexChange?: (index: number, reason: PagerChangeReason) => void;
|
|
96
|
+
/**
|
|
97
|
+
* The track came to rest on `index` after moving on its own (a settle, a
|
|
98
|
+
* `goTo`), having last rested on `previous` (equal when it returned).
|
|
99
|
+
*/
|
|
100
|
+
onSettle?: (index: number, previous: number) => void;
|
|
101
|
+
/**
|
|
102
|
+
* With `pages: 'children'`: a measure found different pages (how many, or
|
|
103
|
+
* where they rest) after the viewport or the track resized or the options
|
|
104
|
+
* changed. Not called for the measure an attach makes: read `pageCount`
|
|
105
|
+
* after attaching.
|
|
106
|
+
*/
|
|
107
|
+
onPagesChange?: (pageCount: number) => void;
|
|
108
|
+
/**
|
|
109
|
+
* Called when the pan would begin, with the drag's first physical direction
|
|
110
|
+
* on screen, the same in RTL. Return false to leave the touch to someone
|
|
111
|
+
* else, such as a zoomed photo that can still pan that way.
|
|
112
|
+
*/
|
|
113
|
+
shouldBeginPan?: (direction: 'left' | 'right') => boolean;
|
|
114
|
+
/** Constructor options for the pan (e.g. `allowedPointerTypes`). */
|
|
115
|
+
panOptions?: Partial<PanGestureRecognizerOptions>;
|
|
116
|
+
}
|
|
117
|
+
export interface GoToOptions {
|
|
118
|
+
/** Animate with `setContentOffset(_:animated:)`'s curve. @default true */
|
|
119
|
+
animated?: boolean;
|
|
120
|
+
/** @default 'goTo' */
|
|
121
|
+
reason?: PagerChangeReason;
|
|
122
|
+
}
|
|
123
|
+
export interface Pager {
|
|
124
|
+
/** The page pan, for failure requirements and simultaneity. */
|
|
125
|
+
readonly pan: PanGestureRecognizer;
|
|
126
|
+
/** The target page, wrapped into [0, count). */
|
|
127
|
+
readonly index: number;
|
|
128
|
+
/** The target page, unbounded when looping. */
|
|
129
|
+
readonly virtualIndex: number;
|
|
130
|
+
/**
|
|
131
|
+
* How many pages there are: `count`, or with `pages: 'children'` the
|
|
132
|
+
* distinct pages last measured.
|
|
133
|
+
*/
|
|
134
|
+
readonly pageCount: number;
|
|
135
|
+
/** Whether the track is moving on its own (a settle or a `goTo`). */
|
|
136
|
+
readonly isSettling: boolean;
|
|
137
|
+
/** Whether a finger is dragging the track. */
|
|
138
|
+
readonly isDragging: boolean;
|
|
139
|
+
/** The content offset on screen right now, from the curve (px). */
|
|
140
|
+
presentation(): number;
|
|
141
|
+
/** Where page `index` rests (px). */
|
|
142
|
+
pageOffset(index: number): number;
|
|
143
|
+
/** The page whose rest is nearest content offset `position` (px). */
|
|
144
|
+
nearestPage(position: number): number;
|
|
145
|
+
/** Move to a page (wrapped to the nearest copy when looping). */
|
|
146
|
+
goTo(index: number, options?: GoToOptions): void;
|
|
147
|
+
/** Update options; a smaller count clamps the target page. */
|
|
148
|
+
setOptions(options: Partial<PagerOptions>): void;
|
|
149
|
+
/**
|
|
150
|
+
* Turns the page pan on or off (the hook's `isPanEnabled`). While it is off,
|
|
151
|
+
* a touch does not stop a settle or a `goTo`. A drag that it ends settles as
|
|
152
|
+
* a cancelled drag does. The callbacks of that settle wait for the next
|
|
153
|
+
* frame, so no callback runs inside the caller's update.
|
|
154
|
+
*/
|
|
155
|
+
setPanEnabled(enabled: boolean): void;
|
|
156
|
+
/** Attach to the elements; returns a detach function. */
|
|
157
|
+
attach(viewport: HTMLElement, track: HTMLElement): () => void;
|
|
158
|
+
/** Detach and stop everything (attaching again restarts it). */
|
|
159
|
+
dispose(): void;
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* The copy of page `index` nearest virtual page `from`, in a loop of `count`
|
|
163
|
+
* pages. Two copies can be equally near: with two pages, or half an even
|
|
164
|
+
* count away. Then it is `index` itself when that is one of them, so a step
|
|
165
|
+
* to `from + 1` always goes forward.
|
|
166
|
+
*/
|
|
167
|
+
export declare function nearestLoopCopy(index: number, from: number, count: number): number;
|
|
168
|
+
/** What a pager runs on; tests pass their own clocked host and animator. */
|
|
169
|
+
export interface PagerEnvironment {
|
|
170
|
+
/** The gesture host; the document's shared host by default. */
|
|
171
|
+
host?: GestureHost;
|
|
172
|
+
/** The track's animator; `animatorFor(track)` by default. */
|
|
173
|
+
animator?: Animator;
|
|
174
|
+
/** Timers for the catch delay; the viewport's window's by default. */
|
|
175
|
+
setTimeout?: (callback: () => void, ms: number) => unknown;
|
|
176
|
+
clearTimeout?: (handle: unknown) => void;
|
|
177
|
+
/** The next animation frame; the viewport's window's by default. */
|
|
178
|
+
requestFrame?: (callback: () => void) => void;
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Creates a pager: UIKit's paging scroll view, driven by the gesture system
|
|
182
|
+
* and played on the compositor. A native scroll-snap container does not run
|
|
183
|
+
* UIKit's paging integrator, and it cannot share a gesture with a pinch.
|
|
184
|
+
* Attach the pager to its viewport and track. It measures the page width on
|
|
185
|
+
* attach, on a resize and when a drag begins, never while a finger moves.
|
|
186
|
+
*
|
|
187
|
+
* - A horizontal pan moves the track 1:1, with one `translate` write per
|
|
188
|
+
* move, no layout read and no React render. Past the first or last page,
|
|
189
|
+
* the track follows UIKit's rubber band, with d = the page width.
|
|
190
|
+
* - At the lift, `pageForRelease` picks the page with UIKit's measured rule.
|
|
191
|
+
* The track then settles on UIKit's paging integrator (`solvePaging`),
|
|
192
|
+
* baked into keyframes.
|
|
193
|
+
* - A finger that lands on a settling pager catches it `paging.catchStopMs`
|
|
194
|
+
* after the touch, as in UIKit. A drag catches it at once, from the value
|
|
195
|
+
* on screen. While the pan is off, a touch does not stop the motion.
|
|
196
|
+
* - `goTo` runs the curve of `setContentOffset(_:animated:)` and cancels a
|
|
197
|
+
* drag in progress. It reads that duration and curve through
|
|
198
|
+
* `resolveMotion`.
|
|
199
|
+
* - Under Reduce Motion, the drag still follows the finger, but nothing
|
|
200
|
+
* travels after the lift. A touch's release cross-fades in 200 ms on any
|
|
201
|
+
* pointer. `goTo` and a mouse's or a pen's release cross-fade on a coarse
|
|
202
|
+
* pointer, and land at once on any other.
|
|
203
|
+
* - `onIndexChange` reports a release's page once its settle runs on the
|
|
204
|
+
* compositor, two frames after the frame it started in. It reports a
|
|
205
|
+
* `goTo` at once, and never a controlled change. A report still waiting at
|
|
206
|
+
* a detach or a controlled move is dropped. `onSettle` runs when the track
|
|
207
|
+
* rests.
|
|
208
|
+
* - A detach ends a drag on its start page, and an unmount calls nothing.
|
|
209
|
+
* When a replaced viewport or track attaches, a motion that the detach
|
|
210
|
+
* stopped ends on its page. Its report and `onSettle` go out from a frame.
|
|
211
|
+
* - A controlled `index` wins. A page that the pager reports and the owner
|
|
212
|
+
* does not take returns the pager to `index`, without a report.
|
|
213
|
+
* - The pan and the catch attach for every pointer. A mouse drags the track
|
|
214
|
+
* as a finger does. The pan follows a trackpad's scroll along its axis, but
|
|
215
|
+
* never a mouse wheel's.
|
|
216
|
+
* - A trackpad swipe moves the track at most one page from its start page.
|
|
217
|
+
* A swipe that moves under a tenth of a page releases still, at any speed.
|
|
218
|
+
* A swipe that lands during the last swipe's settle begins from that
|
|
219
|
+
* settle's page.
|
|
220
|
+
*
|
|
221
|
+
* Positions are content offsets in px, 0 at page 0 and growing toward later
|
|
222
|
+
* pages. The track is translated by −position, or by +position in a
|
|
223
|
+
* right-to-left viewport. The owner renders the pages: all of them, a window,
|
|
224
|
+
* or a wrapped copy for a loop. With `loop`, indexes are unbounded, and
|
|
225
|
+
* `index` wraps them into [0, count).
|
|
226
|
+
*
|
|
227
|
+
* Give the current page and its neighbors their own layers
|
|
228
|
+
* (`will-change: transform`). Through a busy main thread, Mobile Safari moves
|
|
229
|
+
* the track but cannot paint new content, so part of a page that slides in
|
|
230
|
+
* stays blank. A page on its own layer is painted whole before it moves.
|
|
231
|
+
*/
|
|
232
|
+
export declare function createPager(initial: PagerOptions, environment?: PagerEnvironment): Pager;
|
|
233
|
+
export interface UsePagerOptions extends PagerOptions {
|
|
234
|
+
/** The gesture surface: the clipped box the pages show through. */
|
|
235
|
+
viewportRef: RefObject<HTMLElement | null>;
|
|
236
|
+
/** The row of pages the pager translates. */
|
|
237
|
+
trackRef: RefObject<HTMLElement | null>;
|
|
238
|
+
/**
|
|
239
|
+
* Controlled target page; a change animates to it (reason 'controlled'),
|
|
240
|
+
* and a page the pager reports that the owner does not take returns it
|
|
241
|
+
* here.
|
|
242
|
+
*/
|
|
243
|
+
index?: number;
|
|
244
|
+
/** Live toggle for the pan; turning it off mid-drag cancels the drag. */
|
|
245
|
+
isPanEnabled?: boolean;
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* A pager on two elements. Callbacks are read through a ref, so passing new
|
|
249
|
+
* functions each render costs nothing; a gesture never renders.
|
|
250
|
+
*
|
|
251
|
+
* @example
|
|
252
|
+
* ```
|
|
253
|
+
* const pager = usePager({viewportRef, trackRef, count: photos.length, gap: 40,
|
|
254
|
+
* onIndexChange: setCounter});
|
|
255
|
+
* <div ref={viewportRef} style={{overflow: 'hidden'}}>
|
|
256
|
+
* <div ref={trackRef} style={{display: 'flex', gap: 40}}>…pages…</div>
|
|
257
|
+
* </div>
|
|
258
|
+
* ```
|
|
259
|
+
*/
|
|
260
|
+
export declare function usePager({ viewportRef, trackRef, index, isPanEnabled, ...options }: UsePagerOptions): Pager;
|
|
261
|
+
//# sourceMappingURL=usePager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usePager.d.ts","sourceRoot":"","sources":["../../src/hooks/usePager.ts"],"names":[],"mappings":"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"}
|