@metamask/design-system-react-native 0.33.0 → 0.35.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/CHANGELOG.md +30 -1
- package/dist/components/ActionListItem/ActionListItem.cjs +1 -1
- package/dist/components/ActionListItem/ActionListItem.cjs.map +1 -1
- package/dist/components/ActionListItem/ActionListItem.mjs +1 -1
- package/dist/components/ActionListItem/ActionListItem.mjs.map +1 -1
- package/dist/components/BottomSheetDialog/BottomSheetDialog.cjs +6 -5
- package/dist/components/BottomSheetDialog/BottomSheetDialog.cjs.map +1 -1
- package/dist/components/BottomSheetDialog/BottomSheetDialog.mjs +7 -6
- package/dist/components/BottomSheetDialog/BottomSheetDialog.mjs.map +1 -1
- package/dist/components/ButtonBase/ButtonBase.cjs +1 -1
- package/dist/components/ButtonBase/ButtonBase.cjs.map +1 -1
- package/dist/components/ButtonBase/ButtonBase.d.cts.map +1 -1
- package/dist/components/ButtonBase/ButtonBase.d.mts.map +1 -1
- package/dist/components/ButtonBase/ButtonBase.mjs +1 -1
- package/dist/components/ButtonBase/ButtonBase.mjs.map +1 -1
- package/dist/components/FilterButton/FilterButton.cjs +24 -36
- package/dist/components/FilterButton/FilterButton.cjs.map +1 -1
- package/dist/components/FilterButton/FilterButton.d.cts.map +1 -1
- package/dist/components/FilterButton/FilterButton.d.mts.map +1 -1
- package/dist/components/FilterButton/FilterButton.mjs +25 -37
- package/dist/components/FilterButton/FilterButton.mjs.map +1 -1
- package/dist/components/Icon/Icon.assets.cjs +2 -0
- package/dist/components/Icon/Icon.assets.cjs.map +1 -1
- package/dist/components/Icon/Icon.assets.d.cts.map +1 -1
- package/dist/components/Icon/Icon.assets.d.mts.map +1 -1
- package/dist/components/Icon/Icon.assets.mjs +2 -0
- package/dist/components/Icon/Icon.assets.mjs.map +1 -1
- package/dist/components/Icon/assets/candlestick-filled.svg +1 -0
- package/dist/components/Slider/Slider.cjs +139 -0
- package/dist/components/Slider/Slider.cjs.map +1 -0
- package/dist/components/Slider/Slider.constants.cjs +36 -0
- package/dist/components/Slider/Slider.constants.cjs.map +1 -0
- package/dist/components/Slider/Slider.constants.d.cts +33 -0
- package/dist/components/Slider/Slider.constants.d.cts.map +1 -0
- package/dist/components/Slider/Slider.constants.d.mts +33 -0
- package/dist/components/Slider/Slider.constants.d.mts.map +1 -0
- package/dist/components/Slider/Slider.constants.mjs +33 -0
- package/dist/components/Slider/Slider.constants.mjs.map +1 -0
- package/dist/components/Slider/Slider.d.cts +7 -0
- package/dist/components/Slider/Slider.d.cts.map +1 -0
- package/dist/components/Slider/Slider.d.mts +7 -0
- package/dist/components/Slider/Slider.d.mts.map +1 -0
- package/dist/components/Slider/Slider.mjs +116 -0
- package/dist/components/Slider/Slider.mjs.map +1 -0
- package/dist/components/Slider/Slider.types.cjs +3 -0
- package/dist/components/Slider/Slider.types.cjs.map +1 -0
- package/dist/components/Slider/Slider.types.d.cts +135 -0
- package/dist/components/Slider/Slider.types.d.cts.map +1 -0
- package/dist/components/Slider/Slider.types.d.mts +135 -0
- package/dist/components/Slider/Slider.types.d.mts.map +1 -0
- package/dist/components/Slider/Slider.types.mjs +2 -0
- package/dist/components/Slider/Slider.types.mjs.map +1 -0
- package/dist/components/Slider/Slider.utilities.cjs +202 -0
- package/dist/components/Slider/Slider.utilities.cjs.map +1 -0
- package/dist/components/Slider/Slider.utilities.d.cts +108 -0
- package/dist/components/Slider/Slider.utilities.d.cts.map +1 -0
- package/dist/components/Slider/Slider.utilities.d.mts +108 -0
- package/dist/components/Slider/Slider.utilities.d.mts.map +1 -0
- package/dist/components/Slider/Slider.utilities.mjs +186 -0
- package/dist/components/Slider/Slider.utilities.mjs.map +1 -0
- package/dist/components/Slider/index.cjs +9 -0
- package/dist/components/Slider/index.cjs.map +1 -0
- package/dist/components/Slider/index.d.cts +4 -0
- package/dist/components/Slider/index.d.cts.map +1 -0
- package/dist/components/Slider/index.d.mts +4 -0
- package/dist/components/Slider/index.d.mts.map +1 -0
- package/dist/components/Slider/index.mjs +3 -0
- package/dist/components/Slider/index.mjs.map +1 -0
- package/dist/components/Slider/useSliderGesture.cjs +219 -0
- package/dist/components/Slider/useSliderGesture.cjs.map +1 -0
- package/dist/components/Slider/useSliderGesture.d.cts +17 -0
- package/dist/components/Slider/useSliderGesture.d.cts.map +1 -0
- package/dist/components/Slider/useSliderGesture.d.mts +17 -0
- package/dist/components/Slider/useSliderGesture.d.mts.map +1 -0
- package/dist/components/Slider/useSliderGesture.mjs +215 -0
- package/dist/components/Slider/useSliderGesture.mjs.map +1 -0
- package/dist/components/Toast/Toaster.cjs +7 -3
- package/dist/components/Toast/Toaster.cjs.map +1 -1
- package/dist/components/Toast/Toaster.d.cts.map +1 -1
- package/dist/components/Toast/Toaster.d.mts.map +1 -1
- package/dist/components/Toast/Toaster.mjs +8 -4
- package/dist/components/Toast/Toaster.mjs.map +1 -1
- package/dist/components/index.cjs +5 -1
- package/dist/components/index.cjs.map +1 -1
- package/dist/components/index.d.cts +2 -0
- package/dist/components/index.d.cts.map +1 -1
- package/dist/components/index.d.mts +2 -0
- package/dist/components/index.d.mts.map +1 -1
- package/dist/components/index.mjs +1 -0
- package/dist/components/index.mjs.map +1 -1
- package/dist/index.cjs +0 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +0 -1
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +0 -1
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +0 -4
- package/dist/index.mjs.map +1 -1
- package/package.json +7 -8
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.useSliderGesture = void 0;
|
|
4
|
+
const react_1 = require("react");
|
|
5
|
+
const react_native_gesture_handler_1 = require("react-native-gesture-handler");
|
|
6
|
+
const react_native_reanimated_1 = require("react-native-reanimated");
|
|
7
|
+
const Slider_constants_1 = require("./Slider.constants.cjs");
|
|
8
|
+
const Slider_utilities_1 = require("./Slider.utilities.cjs");
|
|
9
|
+
/**
|
|
10
|
+
* Owns Slider gesture handling, animated thumb/fill position, and range-label taps.
|
|
11
|
+
*
|
|
12
|
+
* Flow during drag (UI thread):
|
|
13
|
+
* touch X → clamp to track width → trackPercent → domain value → callbacks
|
|
14
|
+
*
|
|
15
|
+
* Flow when `value` prop changes (JS thread):
|
|
16
|
+
* domain value → trackPercent → translateX (thumb + progress fill)
|
|
17
|
+
*
|
|
18
|
+
* `mapValueToTrackPercent` / `mapTrackPercentToValue` must be worklets when provided.
|
|
19
|
+
*
|
|
20
|
+
* @param params - Gesture configuration and callbacks.
|
|
21
|
+
* @returns Gesture state and handlers for Slider.
|
|
22
|
+
*/
|
|
23
|
+
function useSliderGesture(params) {
|
|
24
|
+
const { value, minimumValue = 0, maximumValue = 100, step = 1, isDisabled = false, onValueChange, onDragEnd, onGrip, onTick, tickThresholds = Slider_constants_1.DEFAULT_TICK_THRESHOLDS, mapValueToTrackPercent, mapTrackPercentToValue, stepToValue: stepToValueProp, } = params;
|
|
25
|
+
const stepToValue = (0, react_1.useMemo)(() => stepToValueProp ??
|
|
26
|
+
((rangeStep) => (0, Slider_utilities_1.defaultStepToValue)(rangeStep, minimumValue, maximumValue)), [maximumValue, minimumValue, stepToValueProp]);
|
|
27
|
+
// --- Animated state ---
|
|
28
|
+
const sliderWidth = (0, react_native_reanimated_1.useSharedValue)(0);
|
|
29
|
+
const translateX = (0, react_native_reanimated_1.useSharedValue)(0);
|
|
30
|
+
const thumbScale = (0, react_native_reanimated_1.useSharedValue)(1);
|
|
31
|
+
const previousTrackPercentRef = (0, react_1.useRef)((0, Slider_utilities_1.getTrackPercentFromValue)(value, minimumValue, maximumValue, mapValueToTrackPercent));
|
|
32
|
+
const isDraggingRef = (0, react_1.useRef)(false);
|
|
33
|
+
// --- Position sync (domain value → thumb pixels) ---
|
|
34
|
+
const syncPositionFromValue = (0, react_1.useCallback)((nextValue, width = sliderWidth.value) => {
|
|
35
|
+
const trackPercent = (0, Slider_utilities_1.getTrackPercentFromValue)(nextValue, minimumValue, maximumValue, mapValueToTrackPercent);
|
|
36
|
+
translateX.value = (0, Slider_utilities_1.trackPercentToPosition)(trackPercent, width);
|
|
37
|
+
}, [
|
|
38
|
+
mapValueToTrackPercent,
|
|
39
|
+
maximumValue,
|
|
40
|
+
minimumValue,
|
|
41
|
+
sliderWidth,
|
|
42
|
+
translateX,
|
|
43
|
+
]);
|
|
44
|
+
const handleLayout = (0, react_1.useCallback)((event) => {
|
|
45
|
+
const { width } = event.nativeEvent.layout;
|
|
46
|
+
sliderWidth.value = width;
|
|
47
|
+
syncPositionFromValue(value, width);
|
|
48
|
+
}, [sliderWidth, syncPositionFromValue, value]);
|
|
49
|
+
(0, react_1.useEffect)(() => {
|
|
50
|
+
syncPositionFromValue(value);
|
|
51
|
+
if (!isDraggingRef.current) {
|
|
52
|
+
previousTrackPercentRef.current = (0, Slider_utilities_1.getTrackPercentFromValue)(value, minimumValue, maximumValue, mapValueToTrackPercent);
|
|
53
|
+
}
|
|
54
|
+
}, [
|
|
55
|
+
mapValueToTrackPercent,
|
|
56
|
+
maximumValue,
|
|
57
|
+
minimumValue,
|
|
58
|
+
syncPositionFromValue,
|
|
59
|
+
value,
|
|
60
|
+
]);
|
|
61
|
+
// --- JS-thread bridges (stable refs for runOnJS from worklets) ---
|
|
62
|
+
const emitValueChange = (0, react_1.useCallback)((nextValue) => {
|
|
63
|
+
onValueChange(nextValue);
|
|
64
|
+
}, [onValueChange]);
|
|
65
|
+
const emitDragEnd = (0, react_1.useCallback)((nextValue) => {
|
|
66
|
+
onDragEnd?.(nextValue);
|
|
67
|
+
}, [onDragEnd]);
|
|
68
|
+
const triggerGrip = (0, react_1.useCallback)(() => {
|
|
69
|
+
if (!isDisabled) {
|
|
70
|
+
onGrip?.();
|
|
71
|
+
}
|
|
72
|
+
}, [isDisabled, onGrip]);
|
|
73
|
+
const setDragging = (0, react_1.useCallback)((dragging) => {
|
|
74
|
+
isDraggingRef.current = dragging;
|
|
75
|
+
}, []);
|
|
76
|
+
const checkThresholdCrossing = (0, react_1.useCallback)((newTrackPercent) => {
|
|
77
|
+
const prevTrackPercent = previousTrackPercentRef.current;
|
|
78
|
+
for (const threshold of tickThresholds) {
|
|
79
|
+
if ((prevTrackPercent < threshold && newTrackPercent >= threshold) ||
|
|
80
|
+
(prevTrackPercent > threshold && newTrackPercent <= threshold)) {
|
|
81
|
+
onTick?.();
|
|
82
|
+
break;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
previousTrackPercentRef.current = newTrackPercent;
|
|
86
|
+
}, [onTick, tickThresholds]);
|
|
87
|
+
// --- Animated styles (thumb + fill width follow translateX) ---
|
|
88
|
+
const progressStyle = (0, react_native_reanimated_1.useAnimatedStyle)(() => ({
|
|
89
|
+
width: translateX.value,
|
|
90
|
+
}));
|
|
91
|
+
const thumbStyle = (0, react_native_reanimated_1.useAnimatedStyle)(() => ({
|
|
92
|
+
transform: [{ translateX: translateX.value }, { scale: thumbScale.value }],
|
|
93
|
+
}));
|
|
94
|
+
// --- Pan + tap gestures ---
|
|
95
|
+
const gesture = (0, react_1.useMemo)(() => {
|
|
96
|
+
// Gesture callbacks need explicit 'worklet' directives because this package
|
|
97
|
+
// ships pre-built dist compiled by ts-bridge. The consumer's Reanimated Babel
|
|
98
|
+
// plugin does not auto-detect the compiled namespaced Gesture form.
|
|
99
|
+
const gripEasing = react_native_reanimated_1.Easing.bezier(0.3, 0.8, 0.3, 1);
|
|
100
|
+
const positionToDomainValue = (position) => {
|
|
101
|
+
'worklet';
|
|
102
|
+
const trackPercent = (0, Slider_utilities_1.positionToTrackPercent)(position, sliderWidth.value);
|
|
103
|
+
const domainValue = (0, Slider_utilities_1.resolveTrackPercentToValue)(trackPercent, minimumValue, maximumValue, step, mapTrackPercentToValue);
|
|
104
|
+
return { trackPercent, domainValue };
|
|
105
|
+
};
|
|
106
|
+
const snapThumbToValue = (domainValue) => {
|
|
107
|
+
'worklet';
|
|
108
|
+
const snappedTrackPercent = (0, Slider_utilities_1.resolveValueToTrackPercent)(domainValue, minimumValue, maximumValue, mapValueToTrackPercent);
|
|
109
|
+
translateX.value = (0, Slider_utilities_1.trackPercentToPosition)(snappedTrackPercent, sliderWidth.value);
|
|
110
|
+
};
|
|
111
|
+
// Finalize a gesture: emit callbacks, then re-sync thumb to stepped value.
|
|
112
|
+
const commitAtPosition = (position, options) => {
|
|
113
|
+
'worklet';
|
|
114
|
+
translateX.value = position;
|
|
115
|
+
const { trackPercent, domainValue } = positionToDomainValue(position);
|
|
116
|
+
(0, react_native_reanimated_1.runOnJS)(emitValueChange)(domainValue);
|
|
117
|
+
if (options.checkThreshold) {
|
|
118
|
+
(0, react_native_reanimated_1.runOnJS)(checkThresholdCrossing)(trackPercent);
|
|
119
|
+
}
|
|
120
|
+
(0, react_native_reanimated_1.runOnJS)(emitDragEnd)(domainValue);
|
|
121
|
+
if (options.triggerGrip) {
|
|
122
|
+
(0, react_native_reanimated_1.runOnJS)(triggerGrip)();
|
|
123
|
+
}
|
|
124
|
+
snapThumbToValue(domainValue);
|
|
125
|
+
};
|
|
126
|
+
const panGesture = react_native_gesture_handler_1.Gesture.Pan()
|
|
127
|
+
.enabled(!isDisabled)
|
|
128
|
+
.onStart(() => {
|
|
129
|
+
'worklet';
|
|
130
|
+
thumbScale.value = (0, react_native_reanimated_1.withTiming)(Slider_constants_1.THUMB_GRIP_SCALE, {
|
|
131
|
+
duration: Slider_constants_1.THUMB_GRIP_ANIMATION_DURATION,
|
|
132
|
+
easing: gripEasing,
|
|
133
|
+
});
|
|
134
|
+
(0, react_native_reanimated_1.runOnJS)(setDragging)(true);
|
|
135
|
+
(0, react_native_reanimated_1.runOnJS)(triggerGrip)();
|
|
136
|
+
})
|
|
137
|
+
.onUpdate((event) => {
|
|
138
|
+
'worklet';
|
|
139
|
+
const position = (0, Slider_utilities_1.clampGesturePosition)(event.x, sliderWidth.value);
|
|
140
|
+
translateX.value = position;
|
|
141
|
+
const { trackPercent, domainValue } = positionToDomainValue(position);
|
|
142
|
+
(0, react_native_reanimated_1.runOnJS)(emitValueChange)(domainValue);
|
|
143
|
+
(0, react_native_reanimated_1.runOnJS)(checkThresholdCrossing)(trackPercent);
|
|
144
|
+
})
|
|
145
|
+
.onEnd(() => {
|
|
146
|
+
'worklet';
|
|
147
|
+
// Thresholds already checked during onUpdate; grip fires again on release.
|
|
148
|
+
commitAtPosition(translateX.value, {
|
|
149
|
+
checkThreshold: false,
|
|
150
|
+
triggerGrip: true,
|
|
151
|
+
});
|
|
152
|
+
})
|
|
153
|
+
.onFinalize(() => {
|
|
154
|
+
'worklet';
|
|
155
|
+
thumbScale.value = (0, react_native_reanimated_1.withTiming)(1, {
|
|
156
|
+
duration: Slider_constants_1.THUMB_GRIP_ANIMATION_DURATION,
|
|
157
|
+
easing: gripEasing,
|
|
158
|
+
});
|
|
159
|
+
(0, react_native_reanimated_1.runOnJS)(setDragging)(false);
|
|
160
|
+
});
|
|
161
|
+
const tapGesture = react_native_gesture_handler_1.Gesture.Tap()
|
|
162
|
+
.enabled(!isDisabled)
|
|
163
|
+
.onEnd((event) => {
|
|
164
|
+
'worklet';
|
|
165
|
+
const position = (0, Slider_utilities_1.clampGesturePosition)(event.x, sliderWidth.value);
|
|
166
|
+
commitAtPosition(position, {
|
|
167
|
+
checkThreshold: true,
|
|
168
|
+
triggerGrip: false,
|
|
169
|
+
});
|
|
170
|
+
});
|
|
171
|
+
return react_native_gesture_handler_1.Gesture.Simultaneous(tapGesture, panGesture);
|
|
172
|
+
}, [
|
|
173
|
+
checkThresholdCrossing,
|
|
174
|
+
emitDragEnd,
|
|
175
|
+
emitValueChange,
|
|
176
|
+
isDisabled,
|
|
177
|
+
mapTrackPercentToValue,
|
|
178
|
+
mapValueToTrackPercent,
|
|
179
|
+
maximumValue,
|
|
180
|
+
minimumValue,
|
|
181
|
+
setDragging,
|
|
182
|
+
sliderWidth,
|
|
183
|
+
step,
|
|
184
|
+
thumbScale,
|
|
185
|
+
translateX,
|
|
186
|
+
triggerGrip,
|
|
187
|
+
]);
|
|
188
|
+
// --- Range label tap (JS thread; uses stepToValue from Slider.tsx) ---
|
|
189
|
+
const handlePressStep = (0, react_1.useCallback)((rangeStep) => {
|
|
190
|
+
if (isDisabled) {
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
const newValue = stepToValue(rangeStep);
|
|
194
|
+
onValueChange(newValue);
|
|
195
|
+
const trackPercent = (0, Slider_utilities_1.getTrackPercentFromValue)(newValue, minimumValue, maximumValue, mapValueToTrackPercent);
|
|
196
|
+
checkThresholdCrossing(trackPercent);
|
|
197
|
+
onDragEnd?.(newValue);
|
|
198
|
+
syncPositionFromValue(newValue);
|
|
199
|
+
}, [
|
|
200
|
+
checkThresholdCrossing,
|
|
201
|
+
isDisabled,
|
|
202
|
+
mapValueToTrackPercent,
|
|
203
|
+
maximumValue,
|
|
204
|
+
minimumValue,
|
|
205
|
+
onDragEnd,
|
|
206
|
+
onValueChange,
|
|
207
|
+
stepToValue,
|
|
208
|
+
syncPositionFromValue,
|
|
209
|
+
]);
|
|
210
|
+
return {
|
|
211
|
+
handleLayout,
|
|
212
|
+
progressStyle,
|
|
213
|
+
thumbStyle,
|
|
214
|
+
gesture,
|
|
215
|
+
handlePressStep,
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
exports.useSliderGesture = useSliderGesture;
|
|
219
|
+
//# sourceMappingURL=useSliderGesture.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useSliderGesture.cjs","sourceRoot":"","sources":["../../../src/components/Slider/useSliderGesture.ts"],"names":[],"mappings":"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","sourcesContent":["import { useCallback, useEffect, useMemo, useRef } from 'react';\nimport { Gesture } from 'react-native-gesture-handler';\nimport {\n Easing,\n runOnJS,\n useAnimatedStyle,\n useSharedValue,\n withTiming,\n} from 'react-native-reanimated';\n\nimport {\n DEFAULT_TICK_THRESHOLDS,\n THUMB_GRIP_ANIMATION_DURATION,\n THUMB_GRIP_SCALE,\n} from './Slider.constants';\nimport type {\n UseSliderGestureParams,\n UseSliderGestureResult,\n} from './Slider.types';\nimport {\n clampGesturePosition,\n defaultStepToValue,\n getTrackPercentFromValue,\n positionToTrackPercent,\n resolveTrackPercentToValue,\n resolveValueToTrackPercent,\n trackPercentToPosition,\n} from './Slider.utilities';\n\n/**\n * Owns Slider gesture handling, animated thumb/fill position, and range-label taps.\n *\n * Flow during drag (UI thread):\n * touch X → clamp to track width → trackPercent → domain value → callbacks\n *\n * Flow when `value` prop changes (JS thread):\n * domain value → trackPercent → translateX (thumb + progress fill)\n *\n * `mapValueToTrackPercent` / `mapTrackPercentToValue` must be worklets when provided.\n *\n * @param params - Gesture configuration and callbacks.\n * @returns Gesture state and handlers for Slider.\n */\nexport function useSliderGesture(\n params: UseSliderGestureParams,\n): UseSliderGestureResult {\n const {\n value,\n minimumValue = 0,\n maximumValue = 100,\n step = 1,\n isDisabled = false,\n onValueChange,\n onDragEnd,\n onGrip,\n onTick,\n tickThresholds = DEFAULT_TICK_THRESHOLDS,\n mapValueToTrackPercent,\n mapTrackPercentToValue,\n stepToValue: stepToValueProp,\n } = params;\n const stepToValue = useMemo(\n () =>\n stepToValueProp ??\n ((rangeStep: number) =>\n defaultStepToValue(rangeStep, minimumValue, maximumValue)),\n [maximumValue, minimumValue, stepToValueProp],\n );\n\n // --- Animated state ---\n\n const sliderWidth = useSharedValue(0);\n const translateX = useSharedValue(0);\n const thumbScale = useSharedValue(1);\n const previousTrackPercentRef = useRef(\n getTrackPercentFromValue(\n value,\n minimumValue,\n maximumValue,\n mapValueToTrackPercent,\n ),\n );\n const isDraggingRef = useRef(false);\n\n // --- Position sync (domain value → thumb pixels) ---\n\n const syncPositionFromValue = useCallback(\n (nextValue: number, width = sliderWidth.value) => {\n const trackPercent = getTrackPercentFromValue(\n nextValue,\n minimumValue,\n maximumValue,\n mapValueToTrackPercent,\n );\n translateX.value = trackPercentToPosition(trackPercent, width);\n },\n [\n mapValueToTrackPercent,\n maximumValue,\n minimumValue,\n sliderWidth,\n translateX,\n ],\n );\n\n const handleLayout = useCallback(\n (event: { nativeEvent: { layout: { width: number } } }) => {\n const { width } = event.nativeEvent.layout;\n sliderWidth.value = width;\n syncPositionFromValue(value, width);\n },\n [sliderWidth, syncPositionFromValue, value],\n );\n\n useEffect(() => {\n syncPositionFromValue(value);\n if (!isDraggingRef.current) {\n previousTrackPercentRef.current = getTrackPercentFromValue(\n value,\n minimumValue,\n maximumValue,\n mapValueToTrackPercent,\n );\n }\n }, [\n mapValueToTrackPercent,\n maximumValue,\n minimumValue,\n syncPositionFromValue,\n value,\n ]);\n\n // --- JS-thread bridges (stable refs for runOnJS from worklets) ---\n\n const emitValueChange = useCallback(\n (nextValue: number) => {\n onValueChange(nextValue);\n },\n [onValueChange],\n );\n\n const emitDragEnd = useCallback(\n (nextValue: number) => {\n onDragEnd?.(nextValue);\n },\n [onDragEnd],\n );\n\n const triggerGrip = useCallback(() => {\n if (!isDisabled) {\n onGrip?.();\n }\n }, [isDisabled, onGrip]);\n\n const setDragging = useCallback((dragging: boolean) => {\n isDraggingRef.current = dragging;\n }, []);\n\n const checkThresholdCrossing = useCallback(\n (newTrackPercent: number) => {\n const prevTrackPercent = previousTrackPercentRef.current;\n\n for (const threshold of tickThresholds) {\n if (\n (prevTrackPercent < threshold && newTrackPercent >= threshold) ||\n (prevTrackPercent > threshold && newTrackPercent <= threshold)\n ) {\n onTick?.();\n break;\n }\n }\n\n previousTrackPercentRef.current = newTrackPercent;\n },\n [onTick, tickThresholds],\n );\n\n // --- Animated styles (thumb + fill width follow translateX) ---\n\n const progressStyle = useAnimatedStyle(() => ({\n width: translateX.value,\n }));\n\n const thumbStyle = useAnimatedStyle(() => ({\n transform: [{ translateX: translateX.value }, { scale: thumbScale.value }],\n }));\n\n // --- Pan + tap gestures ---\n\n const gesture = useMemo(() => {\n // Gesture callbacks need explicit 'worklet' directives because this package\n // ships pre-built dist compiled by ts-bridge. The consumer's Reanimated Babel\n // plugin does not auto-detect the compiled namespaced Gesture form.\n\n const gripEasing = Easing.bezier(0.3, 0.8, 0.3, 1);\n\n const positionToDomainValue = (position: number) => {\n 'worklet';\n\n const trackPercent = positionToTrackPercent(position, sliderWidth.value);\n const domainValue = resolveTrackPercentToValue(\n trackPercent,\n minimumValue,\n maximumValue,\n step,\n mapTrackPercentToValue,\n );\n\n return { trackPercent, domainValue };\n };\n\n const snapThumbToValue = (domainValue: number) => {\n 'worklet';\n\n const snappedTrackPercent = resolveValueToTrackPercent(\n domainValue,\n minimumValue,\n maximumValue,\n mapValueToTrackPercent,\n );\n translateX.value = trackPercentToPosition(\n snappedTrackPercent,\n sliderWidth.value,\n );\n };\n\n // Finalize a gesture: emit callbacks, then re-sync thumb to stepped value.\n const commitAtPosition = (\n position: number,\n options: { checkThreshold: boolean; triggerGrip: boolean },\n ) => {\n 'worklet';\n\n translateX.value = position;\n const { trackPercent, domainValue } = positionToDomainValue(position);\n\n runOnJS(emitValueChange)(domainValue);\n if (options.checkThreshold) {\n runOnJS(checkThresholdCrossing)(trackPercent);\n }\n runOnJS(emitDragEnd)(domainValue);\n if (options.triggerGrip) {\n runOnJS(triggerGrip)();\n }\n snapThumbToValue(domainValue);\n };\n\n const panGesture = Gesture.Pan()\n .enabled(!isDisabled)\n .onStart(() => {\n 'worklet';\n\n thumbScale.value = withTiming(THUMB_GRIP_SCALE, {\n duration: THUMB_GRIP_ANIMATION_DURATION,\n easing: gripEasing,\n });\n runOnJS(setDragging)(true);\n runOnJS(triggerGrip)();\n })\n .onUpdate((event) => {\n 'worklet';\n\n const position = clampGesturePosition(event.x, sliderWidth.value);\n translateX.value = position;\n const { trackPercent, domainValue } = positionToDomainValue(position);\n\n runOnJS(emitValueChange)(domainValue);\n runOnJS(checkThresholdCrossing)(trackPercent);\n })\n .onEnd(() => {\n 'worklet';\n\n // Thresholds already checked during onUpdate; grip fires again on release.\n commitAtPosition(translateX.value, {\n checkThreshold: false,\n triggerGrip: true,\n });\n })\n .onFinalize(() => {\n 'worklet';\n\n thumbScale.value = withTiming(1, {\n duration: THUMB_GRIP_ANIMATION_DURATION,\n easing: gripEasing,\n });\n runOnJS(setDragging)(false);\n });\n\n const tapGesture = Gesture.Tap()\n .enabled(!isDisabled)\n .onEnd((event) => {\n 'worklet';\n\n const position = clampGesturePosition(event.x, sliderWidth.value);\n commitAtPosition(position, {\n checkThreshold: true,\n triggerGrip: false,\n });\n });\n\n return Gesture.Simultaneous(tapGesture, panGesture);\n }, [\n checkThresholdCrossing,\n emitDragEnd,\n emitValueChange,\n isDisabled,\n mapTrackPercentToValue,\n mapValueToTrackPercent,\n maximumValue,\n minimumValue,\n setDragging,\n sliderWidth,\n step,\n thumbScale,\n translateX,\n triggerGrip,\n ]);\n\n // --- Range label tap (JS thread; uses stepToValue from Slider.tsx) ---\n\n const handlePressStep = useCallback(\n (rangeStep: number) => {\n if (isDisabled) {\n return;\n }\n\n const newValue = stepToValue(rangeStep);\n onValueChange(newValue);\n const trackPercent = getTrackPercentFromValue(\n newValue,\n minimumValue,\n maximumValue,\n mapValueToTrackPercent,\n );\n checkThresholdCrossing(trackPercent);\n onDragEnd?.(newValue);\n syncPositionFromValue(newValue);\n },\n [\n checkThresholdCrossing,\n isDisabled,\n mapValueToTrackPercent,\n maximumValue,\n minimumValue,\n onDragEnd,\n onValueChange,\n stepToValue,\n syncPositionFromValue,\n ],\n );\n\n return {\n handleLayout,\n progressStyle,\n thumbStyle,\n gesture,\n handlePressStep,\n };\n}\n"]}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { UseSliderGestureParams, UseSliderGestureResult } from "./Slider.types.cjs";
|
|
2
|
+
/**
|
|
3
|
+
* Owns Slider gesture handling, animated thumb/fill position, and range-label taps.
|
|
4
|
+
*
|
|
5
|
+
* Flow during drag (UI thread):
|
|
6
|
+
* touch X → clamp to track width → trackPercent → domain value → callbacks
|
|
7
|
+
*
|
|
8
|
+
* Flow when `value` prop changes (JS thread):
|
|
9
|
+
* domain value → trackPercent → translateX (thumb + progress fill)
|
|
10
|
+
*
|
|
11
|
+
* `mapValueToTrackPercent` / `mapTrackPercentToValue` must be worklets when provided.
|
|
12
|
+
*
|
|
13
|
+
* @param params - Gesture configuration and callbacks.
|
|
14
|
+
* @returns Gesture state and handlers for Slider.
|
|
15
|
+
*/
|
|
16
|
+
export declare function useSliderGesture(params: UseSliderGestureParams): UseSliderGestureResult;
|
|
17
|
+
//# sourceMappingURL=useSliderGesture.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useSliderGesture.d.cts","sourceRoot":"","sources":["../../../src/components/Slider/useSliderGesture.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EACV,sBAAsB,EACtB,sBAAsB,EACvB,2BAAuB;AAWxB;;;;;;;;;;;;;GAaG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,sBAAsB,GAC7B,sBAAsB,CAyTxB"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { UseSliderGestureParams, UseSliderGestureResult } from "./Slider.types.mjs";
|
|
2
|
+
/**
|
|
3
|
+
* Owns Slider gesture handling, animated thumb/fill position, and range-label taps.
|
|
4
|
+
*
|
|
5
|
+
* Flow during drag (UI thread):
|
|
6
|
+
* touch X → clamp to track width → trackPercent → domain value → callbacks
|
|
7
|
+
*
|
|
8
|
+
* Flow when `value` prop changes (JS thread):
|
|
9
|
+
* domain value → trackPercent → translateX (thumb + progress fill)
|
|
10
|
+
*
|
|
11
|
+
* `mapValueToTrackPercent` / `mapTrackPercentToValue` must be worklets when provided.
|
|
12
|
+
*
|
|
13
|
+
* @param params - Gesture configuration and callbacks.
|
|
14
|
+
* @returns Gesture state and handlers for Slider.
|
|
15
|
+
*/
|
|
16
|
+
export declare function useSliderGesture(params: UseSliderGestureParams): UseSliderGestureResult;
|
|
17
|
+
//# sourceMappingURL=useSliderGesture.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useSliderGesture.d.mts","sourceRoot":"","sources":["../../../src/components/Slider/useSliderGesture.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EACV,sBAAsB,EACtB,sBAAsB,EACvB,2BAAuB;AAWxB;;;;;;;;;;;;;GAaG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,sBAAsB,GAC7B,sBAAsB,CAyTxB"}
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
import { useCallback, useEffect, useMemo, useRef } from "react";
|
|
2
|
+
import { Gesture } from "react-native-gesture-handler";
|
|
3
|
+
import { Easing, runOnJS, useAnimatedStyle, useSharedValue, withTiming } from "react-native-reanimated";
|
|
4
|
+
import { DEFAULT_TICK_THRESHOLDS, THUMB_GRIP_ANIMATION_DURATION, THUMB_GRIP_SCALE } from "./Slider.constants.mjs";
|
|
5
|
+
import { clampGesturePosition, defaultStepToValue, getTrackPercentFromValue, positionToTrackPercent, resolveTrackPercentToValue, resolveValueToTrackPercent, trackPercentToPosition } from "./Slider.utilities.mjs";
|
|
6
|
+
/**
|
|
7
|
+
* Owns Slider gesture handling, animated thumb/fill position, and range-label taps.
|
|
8
|
+
*
|
|
9
|
+
* Flow during drag (UI thread):
|
|
10
|
+
* touch X → clamp to track width → trackPercent → domain value → callbacks
|
|
11
|
+
*
|
|
12
|
+
* Flow when `value` prop changes (JS thread):
|
|
13
|
+
* domain value → trackPercent → translateX (thumb + progress fill)
|
|
14
|
+
*
|
|
15
|
+
* `mapValueToTrackPercent` / `mapTrackPercentToValue` must be worklets when provided.
|
|
16
|
+
*
|
|
17
|
+
* @param params - Gesture configuration and callbacks.
|
|
18
|
+
* @returns Gesture state and handlers for Slider.
|
|
19
|
+
*/
|
|
20
|
+
export function useSliderGesture(params) {
|
|
21
|
+
const { value, minimumValue = 0, maximumValue = 100, step = 1, isDisabled = false, onValueChange, onDragEnd, onGrip, onTick, tickThresholds = DEFAULT_TICK_THRESHOLDS, mapValueToTrackPercent, mapTrackPercentToValue, stepToValue: stepToValueProp, } = params;
|
|
22
|
+
const stepToValue = useMemo(() => stepToValueProp ??
|
|
23
|
+
((rangeStep) => defaultStepToValue(rangeStep, minimumValue, maximumValue)), [maximumValue, minimumValue, stepToValueProp]);
|
|
24
|
+
// --- Animated state ---
|
|
25
|
+
const sliderWidth = useSharedValue(0);
|
|
26
|
+
const translateX = useSharedValue(0);
|
|
27
|
+
const thumbScale = useSharedValue(1);
|
|
28
|
+
const previousTrackPercentRef = useRef(getTrackPercentFromValue(value, minimumValue, maximumValue, mapValueToTrackPercent));
|
|
29
|
+
const isDraggingRef = useRef(false);
|
|
30
|
+
// --- Position sync (domain value → thumb pixels) ---
|
|
31
|
+
const syncPositionFromValue = useCallback((nextValue, width = sliderWidth.value) => {
|
|
32
|
+
const trackPercent = getTrackPercentFromValue(nextValue, minimumValue, maximumValue, mapValueToTrackPercent);
|
|
33
|
+
translateX.value = trackPercentToPosition(trackPercent, width);
|
|
34
|
+
}, [
|
|
35
|
+
mapValueToTrackPercent,
|
|
36
|
+
maximumValue,
|
|
37
|
+
minimumValue,
|
|
38
|
+
sliderWidth,
|
|
39
|
+
translateX,
|
|
40
|
+
]);
|
|
41
|
+
const handleLayout = useCallback((event) => {
|
|
42
|
+
const { width } = event.nativeEvent.layout;
|
|
43
|
+
sliderWidth.value = width;
|
|
44
|
+
syncPositionFromValue(value, width);
|
|
45
|
+
}, [sliderWidth, syncPositionFromValue, value]);
|
|
46
|
+
useEffect(() => {
|
|
47
|
+
syncPositionFromValue(value);
|
|
48
|
+
if (!isDraggingRef.current) {
|
|
49
|
+
previousTrackPercentRef.current = getTrackPercentFromValue(value, minimumValue, maximumValue, mapValueToTrackPercent);
|
|
50
|
+
}
|
|
51
|
+
}, [
|
|
52
|
+
mapValueToTrackPercent,
|
|
53
|
+
maximumValue,
|
|
54
|
+
minimumValue,
|
|
55
|
+
syncPositionFromValue,
|
|
56
|
+
value,
|
|
57
|
+
]);
|
|
58
|
+
// --- JS-thread bridges (stable refs for runOnJS from worklets) ---
|
|
59
|
+
const emitValueChange = useCallback((nextValue) => {
|
|
60
|
+
onValueChange(nextValue);
|
|
61
|
+
}, [onValueChange]);
|
|
62
|
+
const emitDragEnd = useCallback((nextValue) => {
|
|
63
|
+
onDragEnd?.(nextValue);
|
|
64
|
+
}, [onDragEnd]);
|
|
65
|
+
const triggerGrip = useCallback(() => {
|
|
66
|
+
if (!isDisabled) {
|
|
67
|
+
onGrip?.();
|
|
68
|
+
}
|
|
69
|
+
}, [isDisabled, onGrip]);
|
|
70
|
+
const setDragging = useCallback((dragging) => {
|
|
71
|
+
isDraggingRef.current = dragging;
|
|
72
|
+
}, []);
|
|
73
|
+
const checkThresholdCrossing = useCallback((newTrackPercent) => {
|
|
74
|
+
const prevTrackPercent = previousTrackPercentRef.current;
|
|
75
|
+
for (const threshold of tickThresholds) {
|
|
76
|
+
if ((prevTrackPercent < threshold && newTrackPercent >= threshold) ||
|
|
77
|
+
(prevTrackPercent > threshold && newTrackPercent <= threshold)) {
|
|
78
|
+
onTick?.();
|
|
79
|
+
break;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
previousTrackPercentRef.current = newTrackPercent;
|
|
83
|
+
}, [onTick, tickThresholds]);
|
|
84
|
+
// --- Animated styles (thumb + fill width follow translateX) ---
|
|
85
|
+
const progressStyle = useAnimatedStyle(() => ({
|
|
86
|
+
width: translateX.value,
|
|
87
|
+
}));
|
|
88
|
+
const thumbStyle = useAnimatedStyle(() => ({
|
|
89
|
+
transform: [{ translateX: translateX.value }, { scale: thumbScale.value }],
|
|
90
|
+
}));
|
|
91
|
+
// --- Pan + tap gestures ---
|
|
92
|
+
const gesture = useMemo(() => {
|
|
93
|
+
// Gesture callbacks need explicit 'worklet' directives because this package
|
|
94
|
+
// ships pre-built dist compiled by ts-bridge. The consumer's Reanimated Babel
|
|
95
|
+
// plugin does not auto-detect the compiled namespaced Gesture form.
|
|
96
|
+
const gripEasing = Easing.bezier(0.3, 0.8, 0.3, 1);
|
|
97
|
+
const positionToDomainValue = (position) => {
|
|
98
|
+
'worklet';
|
|
99
|
+
const trackPercent = positionToTrackPercent(position, sliderWidth.value);
|
|
100
|
+
const domainValue = resolveTrackPercentToValue(trackPercent, minimumValue, maximumValue, step, mapTrackPercentToValue);
|
|
101
|
+
return { trackPercent, domainValue };
|
|
102
|
+
};
|
|
103
|
+
const snapThumbToValue = (domainValue) => {
|
|
104
|
+
'worklet';
|
|
105
|
+
const snappedTrackPercent = resolveValueToTrackPercent(domainValue, minimumValue, maximumValue, mapValueToTrackPercent);
|
|
106
|
+
translateX.value = trackPercentToPosition(snappedTrackPercent, sliderWidth.value);
|
|
107
|
+
};
|
|
108
|
+
// Finalize a gesture: emit callbacks, then re-sync thumb to stepped value.
|
|
109
|
+
const commitAtPosition = (position, options) => {
|
|
110
|
+
'worklet';
|
|
111
|
+
translateX.value = position;
|
|
112
|
+
const { trackPercent, domainValue } = positionToDomainValue(position);
|
|
113
|
+
runOnJS(emitValueChange)(domainValue);
|
|
114
|
+
if (options.checkThreshold) {
|
|
115
|
+
runOnJS(checkThresholdCrossing)(trackPercent);
|
|
116
|
+
}
|
|
117
|
+
runOnJS(emitDragEnd)(domainValue);
|
|
118
|
+
if (options.triggerGrip) {
|
|
119
|
+
runOnJS(triggerGrip)();
|
|
120
|
+
}
|
|
121
|
+
snapThumbToValue(domainValue);
|
|
122
|
+
};
|
|
123
|
+
const panGesture = Gesture.Pan()
|
|
124
|
+
.enabled(!isDisabled)
|
|
125
|
+
.onStart(() => {
|
|
126
|
+
'worklet';
|
|
127
|
+
thumbScale.value = withTiming(THUMB_GRIP_SCALE, {
|
|
128
|
+
duration: THUMB_GRIP_ANIMATION_DURATION,
|
|
129
|
+
easing: gripEasing,
|
|
130
|
+
});
|
|
131
|
+
runOnJS(setDragging)(true);
|
|
132
|
+
runOnJS(triggerGrip)();
|
|
133
|
+
})
|
|
134
|
+
.onUpdate((event) => {
|
|
135
|
+
'worklet';
|
|
136
|
+
const position = clampGesturePosition(event.x, sliderWidth.value);
|
|
137
|
+
translateX.value = position;
|
|
138
|
+
const { trackPercent, domainValue } = positionToDomainValue(position);
|
|
139
|
+
runOnJS(emitValueChange)(domainValue);
|
|
140
|
+
runOnJS(checkThresholdCrossing)(trackPercent);
|
|
141
|
+
})
|
|
142
|
+
.onEnd(() => {
|
|
143
|
+
'worklet';
|
|
144
|
+
// Thresholds already checked during onUpdate; grip fires again on release.
|
|
145
|
+
commitAtPosition(translateX.value, {
|
|
146
|
+
checkThreshold: false,
|
|
147
|
+
triggerGrip: true,
|
|
148
|
+
});
|
|
149
|
+
})
|
|
150
|
+
.onFinalize(() => {
|
|
151
|
+
'worklet';
|
|
152
|
+
thumbScale.value = withTiming(1, {
|
|
153
|
+
duration: THUMB_GRIP_ANIMATION_DURATION,
|
|
154
|
+
easing: gripEasing,
|
|
155
|
+
});
|
|
156
|
+
runOnJS(setDragging)(false);
|
|
157
|
+
});
|
|
158
|
+
const tapGesture = Gesture.Tap()
|
|
159
|
+
.enabled(!isDisabled)
|
|
160
|
+
.onEnd((event) => {
|
|
161
|
+
'worklet';
|
|
162
|
+
const position = clampGesturePosition(event.x, sliderWidth.value);
|
|
163
|
+
commitAtPosition(position, {
|
|
164
|
+
checkThreshold: true,
|
|
165
|
+
triggerGrip: false,
|
|
166
|
+
});
|
|
167
|
+
});
|
|
168
|
+
return Gesture.Simultaneous(tapGesture, panGesture);
|
|
169
|
+
}, [
|
|
170
|
+
checkThresholdCrossing,
|
|
171
|
+
emitDragEnd,
|
|
172
|
+
emitValueChange,
|
|
173
|
+
isDisabled,
|
|
174
|
+
mapTrackPercentToValue,
|
|
175
|
+
mapValueToTrackPercent,
|
|
176
|
+
maximumValue,
|
|
177
|
+
minimumValue,
|
|
178
|
+
setDragging,
|
|
179
|
+
sliderWidth,
|
|
180
|
+
step,
|
|
181
|
+
thumbScale,
|
|
182
|
+
translateX,
|
|
183
|
+
triggerGrip,
|
|
184
|
+
]);
|
|
185
|
+
// --- Range label tap (JS thread; uses stepToValue from Slider.tsx) ---
|
|
186
|
+
const handlePressStep = useCallback((rangeStep) => {
|
|
187
|
+
if (isDisabled) {
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
const newValue = stepToValue(rangeStep);
|
|
191
|
+
onValueChange(newValue);
|
|
192
|
+
const trackPercent = getTrackPercentFromValue(newValue, minimumValue, maximumValue, mapValueToTrackPercent);
|
|
193
|
+
checkThresholdCrossing(trackPercent);
|
|
194
|
+
onDragEnd?.(newValue);
|
|
195
|
+
syncPositionFromValue(newValue);
|
|
196
|
+
}, [
|
|
197
|
+
checkThresholdCrossing,
|
|
198
|
+
isDisabled,
|
|
199
|
+
mapValueToTrackPercent,
|
|
200
|
+
maximumValue,
|
|
201
|
+
minimumValue,
|
|
202
|
+
onDragEnd,
|
|
203
|
+
onValueChange,
|
|
204
|
+
stepToValue,
|
|
205
|
+
syncPositionFromValue,
|
|
206
|
+
]);
|
|
207
|
+
return {
|
|
208
|
+
handleLayout,
|
|
209
|
+
progressStyle,
|
|
210
|
+
thumbStyle,
|
|
211
|
+
gesture,
|
|
212
|
+
handlePressStep,
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
//# sourceMappingURL=useSliderGesture.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useSliderGesture.mjs","sourceRoot":"","sources":["../../../src/components/Slider/useSliderGesture.ts"],"names":[],"mappings":"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","sourcesContent":["import { useCallback, useEffect, useMemo, useRef } from 'react';\nimport { Gesture } from 'react-native-gesture-handler';\nimport {\n Easing,\n runOnJS,\n useAnimatedStyle,\n useSharedValue,\n withTiming,\n} from 'react-native-reanimated';\n\nimport {\n DEFAULT_TICK_THRESHOLDS,\n THUMB_GRIP_ANIMATION_DURATION,\n THUMB_GRIP_SCALE,\n} from './Slider.constants';\nimport type {\n UseSliderGestureParams,\n UseSliderGestureResult,\n} from './Slider.types';\nimport {\n clampGesturePosition,\n defaultStepToValue,\n getTrackPercentFromValue,\n positionToTrackPercent,\n resolveTrackPercentToValue,\n resolveValueToTrackPercent,\n trackPercentToPosition,\n} from './Slider.utilities';\n\n/**\n * Owns Slider gesture handling, animated thumb/fill position, and range-label taps.\n *\n * Flow during drag (UI thread):\n * touch X → clamp to track width → trackPercent → domain value → callbacks\n *\n * Flow when `value` prop changes (JS thread):\n * domain value → trackPercent → translateX (thumb + progress fill)\n *\n * `mapValueToTrackPercent` / `mapTrackPercentToValue` must be worklets when provided.\n *\n * @param params - Gesture configuration and callbacks.\n * @returns Gesture state and handlers for Slider.\n */\nexport function useSliderGesture(\n params: UseSliderGestureParams,\n): UseSliderGestureResult {\n const {\n value,\n minimumValue = 0,\n maximumValue = 100,\n step = 1,\n isDisabled = false,\n onValueChange,\n onDragEnd,\n onGrip,\n onTick,\n tickThresholds = DEFAULT_TICK_THRESHOLDS,\n mapValueToTrackPercent,\n mapTrackPercentToValue,\n stepToValue: stepToValueProp,\n } = params;\n const stepToValue = useMemo(\n () =>\n stepToValueProp ??\n ((rangeStep: number) =>\n defaultStepToValue(rangeStep, minimumValue, maximumValue)),\n [maximumValue, minimumValue, stepToValueProp],\n );\n\n // --- Animated state ---\n\n const sliderWidth = useSharedValue(0);\n const translateX = useSharedValue(0);\n const thumbScale = useSharedValue(1);\n const previousTrackPercentRef = useRef(\n getTrackPercentFromValue(\n value,\n minimumValue,\n maximumValue,\n mapValueToTrackPercent,\n ),\n );\n const isDraggingRef = useRef(false);\n\n // --- Position sync (domain value → thumb pixels) ---\n\n const syncPositionFromValue = useCallback(\n (nextValue: number, width = sliderWidth.value) => {\n const trackPercent = getTrackPercentFromValue(\n nextValue,\n minimumValue,\n maximumValue,\n mapValueToTrackPercent,\n );\n translateX.value = trackPercentToPosition(trackPercent, width);\n },\n [\n mapValueToTrackPercent,\n maximumValue,\n minimumValue,\n sliderWidth,\n translateX,\n ],\n );\n\n const handleLayout = useCallback(\n (event: { nativeEvent: { layout: { width: number } } }) => {\n const { width } = event.nativeEvent.layout;\n sliderWidth.value = width;\n syncPositionFromValue(value, width);\n },\n [sliderWidth, syncPositionFromValue, value],\n );\n\n useEffect(() => {\n syncPositionFromValue(value);\n if (!isDraggingRef.current) {\n previousTrackPercentRef.current = getTrackPercentFromValue(\n value,\n minimumValue,\n maximumValue,\n mapValueToTrackPercent,\n );\n }\n }, [\n mapValueToTrackPercent,\n maximumValue,\n minimumValue,\n syncPositionFromValue,\n value,\n ]);\n\n // --- JS-thread bridges (stable refs for runOnJS from worklets) ---\n\n const emitValueChange = useCallback(\n (nextValue: number) => {\n onValueChange(nextValue);\n },\n [onValueChange],\n );\n\n const emitDragEnd = useCallback(\n (nextValue: number) => {\n onDragEnd?.(nextValue);\n },\n [onDragEnd],\n );\n\n const triggerGrip = useCallback(() => {\n if (!isDisabled) {\n onGrip?.();\n }\n }, [isDisabled, onGrip]);\n\n const setDragging = useCallback((dragging: boolean) => {\n isDraggingRef.current = dragging;\n }, []);\n\n const checkThresholdCrossing = useCallback(\n (newTrackPercent: number) => {\n const prevTrackPercent = previousTrackPercentRef.current;\n\n for (const threshold of tickThresholds) {\n if (\n (prevTrackPercent < threshold && newTrackPercent >= threshold) ||\n (prevTrackPercent > threshold && newTrackPercent <= threshold)\n ) {\n onTick?.();\n break;\n }\n }\n\n previousTrackPercentRef.current = newTrackPercent;\n },\n [onTick, tickThresholds],\n );\n\n // --- Animated styles (thumb + fill width follow translateX) ---\n\n const progressStyle = useAnimatedStyle(() => ({\n width: translateX.value,\n }));\n\n const thumbStyle = useAnimatedStyle(() => ({\n transform: [{ translateX: translateX.value }, { scale: thumbScale.value }],\n }));\n\n // --- Pan + tap gestures ---\n\n const gesture = useMemo(() => {\n // Gesture callbacks need explicit 'worklet' directives because this package\n // ships pre-built dist compiled by ts-bridge. The consumer's Reanimated Babel\n // plugin does not auto-detect the compiled namespaced Gesture form.\n\n const gripEasing = Easing.bezier(0.3, 0.8, 0.3, 1);\n\n const positionToDomainValue = (position: number) => {\n 'worklet';\n\n const trackPercent = positionToTrackPercent(position, sliderWidth.value);\n const domainValue = resolveTrackPercentToValue(\n trackPercent,\n minimumValue,\n maximumValue,\n step,\n mapTrackPercentToValue,\n );\n\n return { trackPercent, domainValue };\n };\n\n const snapThumbToValue = (domainValue: number) => {\n 'worklet';\n\n const snappedTrackPercent = resolveValueToTrackPercent(\n domainValue,\n minimumValue,\n maximumValue,\n mapValueToTrackPercent,\n );\n translateX.value = trackPercentToPosition(\n snappedTrackPercent,\n sliderWidth.value,\n );\n };\n\n // Finalize a gesture: emit callbacks, then re-sync thumb to stepped value.\n const commitAtPosition = (\n position: number,\n options: { checkThreshold: boolean; triggerGrip: boolean },\n ) => {\n 'worklet';\n\n translateX.value = position;\n const { trackPercent, domainValue } = positionToDomainValue(position);\n\n runOnJS(emitValueChange)(domainValue);\n if (options.checkThreshold) {\n runOnJS(checkThresholdCrossing)(trackPercent);\n }\n runOnJS(emitDragEnd)(domainValue);\n if (options.triggerGrip) {\n runOnJS(triggerGrip)();\n }\n snapThumbToValue(domainValue);\n };\n\n const panGesture = Gesture.Pan()\n .enabled(!isDisabled)\n .onStart(() => {\n 'worklet';\n\n thumbScale.value = withTiming(THUMB_GRIP_SCALE, {\n duration: THUMB_GRIP_ANIMATION_DURATION,\n easing: gripEasing,\n });\n runOnJS(setDragging)(true);\n runOnJS(triggerGrip)();\n })\n .onUpdate((event) => {\n 'worklet';\n\n const position = clampGesturePosition(event.x, sliderWidth.value);\n translateX.value = position;\n const { trackPercent, domainValue } = positionToDomainValue(position);\n\n runOnJS(emitValueChange)(domainValue);\n runOnJS(checkThresholdCrossing)(trackPercent);\n })\n .onEnd(() => {\n 'worklet';\n\n // Thresholds already checked during onUpdate; grip fires again on release.\n commitAtPosition(translateX.value, {\n checkThreshold: false,\n triggerGrip: true,\n });\n })\n .onFinalize(() => {\n 'worklet';\n\n thumbScale.value = withTiming(1, {\n duration: THUMB_GRIP_ANIMATION_DURATION,\n easing: gripEasing,\n });\n runOnJS(setDragging)(false);\n });\n\n const tapGesture = Gesture.Tap()\n .enabled(!isDisabled)\n .onEnd((event) => {\n 'worklet';\n\n const position = clampGesturePosition(event.x, sliderWidth.value);\n commitAtPosition(position, {\n checkThreshold: true,\n triggerGrip: false,\n });\n });\n\n return Gesture.Simultaneous(tapGesture, panGesture);\n }, [\n checkThresholdCrossing,\n emitDragEnd,\n emitValueChange,\n isDisabled,\n mapTrackPercentToValue,\n mapValueToTrackPercent,\n maximumValue,\n minimumValue,\n setDragging,\n sliderWidth,\n step,\n thumbScale,\n translateX,\n triggerGrip,\n ]);\n\n // --- Range label tap (JS thread; uses stepToValue from Slider.tsx) ---\n\n const handlePressStep = useCallback(\n (rangeStep: number) => {\n if (isDisabled) {\n return;\n }\n\n const newValue = stepToValue(rangeStep);\n onValueChange(newValue);\n const trackPercent = getTrackPercentFromValue(\n newValue,\n minimumValue,\n maximumValue,\n mapValueToTrackPercent,\n );\n checkThresholdCrossing(trackPercent);\n onDragEnd?.(newValue);\n syncPositionFromValue(newValue);\n },\n [\n checkThresholdCrossing,\n isDisabled,\n mapValueToTrackPercent,\n maximumValue,\n minimumValue,\n onDragEnd,\n onValueChange,\n stepToValue,\n syncPositionFromValue,\n ],\n );\n\n return {\n handleLayout,\n progressStyle,\n thumbStyle,\n gesture,\n handlePressStep,\n };\n}\n"]}
|
|
@@ -30,6 +30,7 @@ const react_1 = __importStar(require("react"));
|
|
|
30
30
|
const react_native_1 = require("react-native");
|
|
31
31
|
const react_native_reanimated_1 = __importStar(require("react-native-reanimated"));
|
|
32
32
|
const react_native_safe_area_context_1 = require("react-native-safe-area-context");
|
|
33
|
+
const react_native_worklets_1 = require("react-native-worklets");
|
|
33
34
|
// Internal dependencies.
|
|
34
35
|
const Toast_1 = require("./Toast.cjs");
|
|
35
36
|
const Toast_constants_1 = require("./Toast.constants.cjs");
|
|
@@ -53,7 +54,10 @@ const ToasterComponent = (0, react_1.forwardRef)(({ twClassName, ...props }, ref
|
|
|
53
54
|
const animatedStyle = (0, react_native_reanimated_1.useAnimatedStyle)(() => ({
|
|
54
55
|
transform: [{ translateY: translateYProgress.value - bottomOffset }],
|
|
55
56
|
}));
|
|
56
|
-
const baseStyle = (0, react_1.useMemo)(() => [
|
|
57
|
+
const baseStyle = (0, react_1.useMemo)(() => [
|
|
58
|
+
tw.style('absolute left-4 right-4 bottom-0'),
|
|
59
|
+
animatedStyle,
|
|
60
|
+
], [tw, animatedStyle]);
|
|
57
61
|
const innerRef = (0, react_1.useRef)(null);
|
|
58
62
|
const resetState = () => setToastOptions(undefined);
|
|
59
63
|
const showToast = (options) => {
|
|
@@ -81,7 +85,7 @@ const ToasterComponent = (0, react_1.forwardRef)(({ twClassName, ...props }, ref
|
|
|
81
85
|
replacementTimerRef.current = null;
|
|
82
86
|
}
|
|
83
87
|
translateYProgress.value = (0, react_native_reanimated_1.withTiming)(screenHeight, { duration: Toast_constants_1.TOAST_ANIMATION_DURATION }, () => {
|
|
84
|
-
(0,
|
|
88
|
+
(0, react_native_worklets_1.scheduleOnRN)(resetState);
|
|
85
89
|
});
|
|
86
90
|
};
|
|
87
91
|
innerRef.current = {
|
|
@@ -117,7 +121,7 @@ const ToasterComponent = (0, react_1.forwardRef)(({ twClassName, ...props }, ref
|
|
|
117
121
|
}
|
|
118
122
|
else {
|
|
119
123
|
translateYProgress.value = (0, react_native_reanimated_1.withTiming)(translateYToValue, { duration: Toast_constants_1.TOAST_ANIMATION_DURATION }, () => {
|
|
120
|
-
translateYProgress.value = (0, react_native_reanimated_1.withDelay)(Toast_constants_1.TOAST_VISIBILITY_DURATION, (0, react_native_reanimated_1.withTiming)(height, { duration: Toast_constants_1.TOAST_ANIMATION_DURATION }, (0,
|
|
124
|
+
translateYProgress.value = (0, react_native_reanimated_1.withDelay)(Toast_constants_1.TOAST_VISIBILITY_DURATION, (0, react_native_reanimated_1.withTiming)(height, { duration: Toast_constants_1.TOAST_ANIMATION_DURATION }, () => (0, react_native_worklets_1.scheduleOnRN)(resetState)));
|
|
121
125
|
});
|
|
122
126
|
}
|
|
123
127
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Toaster.cjs","sourceRoot":"","sources":["../../../src/components/Toast/Toaster.tsx"],"names":[],"mappings":"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","sourcesContent":["// Third party dependencies.\nimport { useTailwind } from '@metamask/design-system-twrnc-preset';\nimport React, {\n forwardRef,\n useImperativeHandle,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport type { RefObject } from 'react';\nimport { Dimensions } from 'react-native';\nimport type { LayoutChangeEvent, StyleProp, ViewStyle } from 'react-native';\nimport Animated, {\n cancelAnimation,\n runOnJS,\n useAnimatedStyle,\n useSharedValue,\n withDelay,\n withTiming,\n} from 'react-native-reanimated';\nimport { useSafeAreaInsets } from 'react-native-safe-area-context';\n\n// Internal dependencies.\nimport { Toast } from './Toast';\nimport {\n TOAST_ANIMATION_DURATION,\n TOAST_BOTTOM_PADDING,\n TOAST_VISIBILITY_DURATION,\n} from './Toast.constants';\nimport type {\n ToastOptions,\n ToastProps,\n ToasterProps,\n ToasterRef,\n} from './Toast.types';\n\nconst screenHeight = Dimensions.get('window').height;\n\nlet registeredRef: RefObject<ToasterRef | null> | null = null;\n\nconst assertRegisteredRef = (method: 'dismiss' | 'toast'): ToasterRef => {\n if (!registeredRef?.current) {\n const invocation = method === 'toast' ? 'toast()' : `toast.${method}()`;\n throw new Error(\n `${invocation} called before <Toaster /> mounted. Render <Toaster /> once at the root of your app.`,\n );\n }\n return registeredRef.current;\n};\n\nconst getToastProps = ({\n bottomOffset: _bottomOffset,\n hasNoTimeout: _hasNoTimeout,\n onClose: _onClose,\n twClassName: _twClassName,\n ...toastProps\n}: ToastOptions): Omit<ToastProps, 'twClassName'> => toastProps;\n\nconst ToasterComponent = forwardRef<ToasterRef, ToasterProps>(\n ({ twClassName, ...props }, ref) => {\n const tw = useTailwind();\n const [toastOptions, setToastOptions] = useState<ToastOptions | undefined>(\n undefined,\n );\n const replacementTimerRef = useRef<ReturnType<typeof setTimeout> | null>(\n null,\n );\n const { bottom: bottomNotchSpacing } = useSafeAreaInsets();\n const translateYProgress = useSharedValue(screenHeight);\n const bottomOffset = toastOptions?.bottomOffset ?? 0;\n const animatedStyle = useAnimatedStyle(() => ({\n transform: [{ translateY: translateYProgress.value - bottomOffset }],\n }));\n const baseStyle: StyleProp<ViewStyle> = useMemo(\n () => [tw.style('absolute left-4 right-4 bottom-0'), animatedStyle],\n [tw, animatedStyle],\n );\n const innerRef = useRef<ToasterRef | null>(null);\n\n const resetState = () => setToastOptions(undefined);\n\n const showToast = (options: ToastOptions) => {\n let timeoutDuration = 0;\n const normalizedOptions = {\n hasNoTimeout: false,\n ...options,\n };\n if (toastOptions) {\n cancelAnimation(translateYProgress);\n timeoutDuration = 100;\n setToastOptions(undefined);\n }\n if (replacementTimerRef.current !== null) {\n clearTimeout(replacementTimerRef.current);\n }\n replacementTimerRef.current = setTimeout(() => {\n replacementTimerRef.current = null;\n setToastOptions(normalizedOptions);\n }, timeoutDuration);\n };\n\n const closeToast = () => {\n if (replacementTimerRef.current !== null) {\n clearTimeout(replacementTimerRef.current);\n replacementTimerRef.current = null;\n }\n translateYProgress.value = withTiming(\n screenHeight,\n { duration: TOAST_ANIMATION_DURATION },\n () => {\n runOnJS(resetState)();\n },\n );\n };\n\n innerRef.current = {\n closeToast,\n showToast,\n };\n\n useImperativeHandle(ref, () => innerRef.current as ToasterRef);\n\n useLayoutEffect(() => {\n registeredRef = innerRef;\n return () => {\n if (registeredRef === innerRef) {\n registeredRef = null;\n }\n };\n }, []);\n\n if (!toastOptions) {\n return null;\n }\n\n const { onClose: toastOnClose, twClassName: toastTwClassName } =\n toastOptions;\n const toastProps = getToastProps(toastOptions);\n const { actionButtonLabel, actionButtonOnPress, ...restToastProps } =\n toastProps;\n const toastTwClassNames = [twClassName, toastTwClassName]\n .filter(Boolean)\n .join(' ');\n\n const onAnimatedViewLayout = (e: LayoutChangeEvent) => {\n const { height } = e.nativeEvent.layout;\n const translateYToValue = -(TOAST_BOTTOM_PADDING + bottomNotchSpacing);\n\n translateYProgress.value = height;\n\n if (toastOptions.hasNoTimeout) {\n translateYProgress.value = withTiming(translateYToValue, {\n duration: TOAST_ANIMATION_DURATION,\n });\n } else {\n translateYProgress.value = withTiming(\n translateYToValue,\n { duration: TOAST_ANIMATION_DURATION },\n () => {\n translateYProgress.value = withDelay(\n TOAST_VISIBILITY_DURATION,\n withTiming(\n height,\n { duration: TOAST_ANIMATION_DURATION },\n runOnJS(resetState),\n ),\n );\n },\n );\n }\n };\n\n return (\n <Animated.View\n onLayout={onAnimatedViewLayout}\n style={baseStyle}\n {...props}\n >\n {actionButtonLabel && actionButtonOnPress ? (\n <Toast\n {...toastProps}\n actionButtonLabel={actionButtonLabel}\n actionButtonOnPress={actionButtonOnPress}\n onClose={() => {\n closeToast();\n toastOnClose?.();\n }}\n twClassName={toastTwClassNames}\n />\n ) : (\n <Toast\n {...restToastProps}\n onClose={() => {\n closeToast();\n toastOnClose?.();\n }}\n twClassName={toastTwClassNames}\n />\n )}\n </Animated.View>\n );\n },\n);\n\nToasterComponent.displayName = 'Toaster';\n\ntype ToastFunction = ((options: ToastOptions) => void) & {\n dismiss: () => void;\n};\n\nexport const Toaster = ToasterComponent;\n\nexport const toast = ((options: ToastOptions) => {\n assertRegisteredRef('toast').showToast(options);\n}) as ToastFunction;\n\ntoast.dismiss = () => {\n assertRegisteredRef('dismiss').closeToast();\n};\n"]}
|
|
1
|
+
{"version":3,"file":"Toaster.cjs","sourceRoot":"","sources":["../../../src/components/Toast/Toaster.tsx"],"names":[],"mappings":"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","sourcesContent":["// Third party dependencies.\nimport { useTailwind } from '@metamask/design-system-twrnc-preset';\nimport React, {\n forwardRef,\n useImperativeHandle,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport type { RefObject } from 'react';\nimport { Dimensions } from 'react-native';\nimport type { LayoutChangeEvent, StyleProp, ViewStyle } from 'react-native';\nimport Animated, {\n cancelAnimation,\n useAnimatedStyle,\n useSharedValue,\n withDelay,\n withTiming,\n} from 'react-native-reanimated';\nimport { useSafeAreaInsets } from 'react-native-safe-area-context';\nimport { scheduleOnRN } from 'react-native-worklets';\n\n// Internal dependencies.\nimport { Toast } from './Toast';\nimport {\n TOAST_ANIMATION_DURATION,\n TOAST_BOTTOM_PADDING,\n TOAST_VISIBILITY_DURATION,\n} from './Toast.constants';\nimport type {\n ToastOptions,\n ToastProps,\n ToasterProps,\n ToasterRef,\n} from './Toast.types';\n\nconst screenHeight = Dimensions.get('window').height;\n\nlet registeredRef: RefObject<ToasterRef | null> | null = null;\n\nconst assertRegisteredRef = (method: 'dismiss' | 'toast'): ToasterRef => {\n if (!registeredRef?.current) {\n const invocation = method === 'toast' ? 'toast()' : `toast.${method}()`;\n throw new Error(\n `${invocation} called before <Toaster /> mounted. Render <Toaster /> once at the root of your app.`,\n );\n }\n return registeredRef.current;\n};\n\nconst getToastProps = ({\n bottomOffset: _bottomOffset,\n hasNoTimeout: _hasNoTimeout,\n onClose: _onClose,\n twClassName: _twClassName,\n ...toastProps\n}: ToastOptions): Omit<ToastProps, 'twClassName'> => toastProps;\n\nconst ToasterComponent = forwardRef<ToasterRef, ToasterProps>(\n ({ twClassName, ...props }, ref) => {\n const tw = useTailwind();\n const [toastOptions, setToastOptions] = useState<ToastOptions | undefined>(\n undefined,\n );\n const replacementTimerRef = useRef<ReturnType<typeof setTimeout> | null>(\n null,\n );\n const { bottom: bottomNotchSpacing } = useSafeAreaInsets();\n const translateYProgress = useSharedValue(screenHeight);\n const bottomOffset = toastOptions?.bottomOffset ?? 0;\n const animatedStyle = useAnimatedStyle(() => ({\n transform: [{ translateY: translateYProgress.value - bottomOffset }],\n }));\n const baseStyle = useMemo(\n () =>\n [\n tw.style('absolute left-4 right-4 bottom-0'),\n animatedStyle,\n ] as StyleProp<ViewStyle>,\n [tw, animatedStyle],\n );\n const innerRef = useRef<ToasterRef | null>(null);\n\n const resetState = () => setToastOptions(undefined);\n\n const showToast = (options: ToastOptions) => {\n let timeoutDuration = 0;\n const normalizedOptions = {\n hasNoTimeout: false,\n ...options,\n };\n if (toastOptions) {\n cancelAnimation(translateYProgress);\n timeoutDuration = 100;\n setToastOptions(undefined);\n }\n if (replacementTimerRef.current !== null) {\n clearTimeout(replacementTimerRef.current);\n }\n replacementTimerRef.current = setTimeout(() => {\n replacementTimerRef.current = null;\n setToastOptions(normalizedOptions);\n }, timeoutDuration);\n };\n\n const closeToast = () => {\n if (replacementTimerRef.current !== null) {\n clearTimeout(replacementTimerRef.current);\n replacementTimerRef.current = null;\n }\n translateYProgress.value = withTiming(\n screenHeight,\n { duration: TOAST_ANIMATION_DURATION },\n () => {\n scheduleOnRN(resetState);\n },\n );\n };\n\n innerRef.current = {\n closeToast,\n showToast,\n };\n\n useImperativeHandle(ref, () => innerRef.current as ToasterRef);\n\n useLayoutEffect(() => {\n registeredRef = innerRef;\n return () => {\n if (registeredRef === innerRef) {\n registeredRef = null;\n }\n };\n }, []);\n\n if (!toastOptions) {\n return null;\n }\n\n const { onClose: toastOnClose, twClassName: toastTwClassName } =\n toastOptions;\n const toastProps = getToastProps(toastOptions);\n const { actionButtonLabel, actionButtonOnPress, ...restToastProps } =\n toastProps;\n const toastTwClassNames = [twClassName, toastTwClassName]\n .filter(Boolean)\n .join(' ');\n\n const onAnimatedViewLayout = (e: LayoutChangeEvent) => {\n const { height } = e.nativeEvent.layout;\n const translateYToValue = -(TOAST_BOTTOM_PADDING + bottomNotchSpacing);\n\n translateYProgress.value = height;\n\n if (toastOptions.hasNoTimeout) {\n translateYProgress.value = withTiming(translateYToValue, {\n duration: TOAST_ANIMATION_DURATION,\n });\n } else {\n translateYProgress.value = withTiming(\n translateYToValue,\n { duration: TOAST_ANIMATION_DURATION },\n () => {\n translateYProgress.value = withDelay(\n TOAST_VISIBILITY_DURATION,\n withTiming(height, { duration: TOAST_ANIMATION_DURATION }, () =>\n scheduleOnRN(resetState),\n ),\n );\n },\n );\n }\n };\n\n return (\n <Animated.View\n onLayout={onAnimatedViewLayout}\n style={baseStyle}\n {...props}\n >\n {actionButtonLabel && actionButtonOnPress ? (\n <Toast\n {...toastProps}\n actionButtonLabel={actionButtonLabel}\n actionButtonOnPress={actionButtonOnPress}\n onClose={() => {\n closeToast();\n toastOnClose?.();\n }}\n twClassName={toastTwClassNames}\n />\n ) : (\n <Toast\n {...restToastProps}\n onClose={() => {\n closeToast();\n toastOnClose?.();\n }}\n twClassName={toastTwClassNames}\n />\n )}\n </Animated.View>\n );\n },\n);\n\nToasterComponent.displayName = 'Toaster';\n\ntype ToastFunction = ((options: ToastOptions) => void) & {\n dismiss: () => void;\n};\n\nexport const Toaster = ToasterComponent;\n\nexport const toast = ((options: ToastOptions) => {\n assertRegisteredRef('toast').showToast(options);\n}) as ToastFunction;\n\ntoast.dismiss = () => {\n assertRegisteredRef('dismiss').closeToast();\n};\n"]}
|