@cdx-ui/components 0.0.1-beta.79 → 0.0.1-beta.80
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/lib/commonjs/animation/hooks/index.js +17 -0
- package/lib/commonjs/animation/hooks/index.js.map +1 -0
- package/lib/commonjs/animation/hooks/useCombinedAnimationDisabledState.js +50 -0
- package/lib/commonjs/animation/hooks/useCombinedAnimationDisabledState.js.map +1 -0
- package/lib/commonjs/animation/index.js +39 -0
- package/lib/commonjs/animation/index.js.map +1 -0
- package/lib/commonjs/animation/types.js +6 -0
- package/lib/commonjs/animation/types.js.map +1 -0
- package/lib/commonjs/animation/utils.js +223 -0
- package/lib/commonjs/animation/utils.js.map +1 -0
- package/lib/commonjs/components/CLAUDE.md +1 -1
- package/lib/commonjs/components/Card/index.js +45 -17
- package/lib/commonjs/components/Card/index.js.map +1 -1
- package/lib/commonjs/components/Toast/animation.js +329 -0
- package/lib/commonjs/components/Toast/animation.js.map +1 -0
- package/lib/commonjs/components/Toast/hooks.js +66 -0
- package/lib/commonjs/components/Toast/hooks.js.map +1 -0
- package/lib/commonjs/components/Toast/index.js +493 -0
- package/lib/commonjs/components/Toast/index.js.map +1 -0
- package/lib/commonjs/components/Toast/styles.js +141 -0
- package/lib/commonjs/components/Toast/styles.js.map +1 -0
- package/lib/commonjs/components/Toast/types.js +6 -0
- package/lib/commonjs/components/Toast/types.js.map +1 -0
- package/lib/commonjs/components/index.js +12 -0
- package/lib/commonjs/components/index.js.map +1 -1
- package/lib/commonjs/index.js +15 -0
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/providers/animation-settings/index.js +31 -0
- package/lib/commonjs/providers/animation-settings/index.js.map +1 -0
- package/lib/commonjs/providers/animation-settings/provider.js +59 -0
- package/lib/commonjs/providers/animation-settings/provider.js.map +1 -0
- package/lib/commonjs/providers/animation-settings/types.js +6 -0
- package/lib/commonjs/providers/animation-settings/types.js.map +1 -0
- package/lib/commonjs/providers/forge-design/index.js +29 -0
- package/lib/commonjs/providers/forge-design/index.js.map +1 -0
- package/lib/commonjs/providers/forge-design/provider.js +71 -0
- package/lib/commonjs/providers/forge-design/provider.js.map +1 -0
- package/lib/commonjs/providers/forge-design/types.js +6 -0
- package/lib/commonjs/providers/forge-design/types.js.map +1 -0
- package/lib/commonjs/providers/text-component/index.js +28 -0
- package/lib/commonjs/providers/text-component/index.js.map +1 -0
- package/lib/commonjs/providers/text-component/provider.js +11 -0
- package/lib/commonjs/providers/text-component/provider.js.map +1 -0
- package/lib/commonjs/providers/text-component/types.js +6 -0
- package/lib/commonjs/providers/text-component/types.js.map +1 -0
- package/lib/commonjs/providers/toast/index.js +33 -0
- package/lib/commonjs/providers/toast/index.js.map +1 -0
- package/lib/commonjs/providers/toast/insets-container.js +160 -0
- package/lib/commonjs/providers/toast/insets-container.js.map +1 -0
- package/lib/commonjs/providers/toast/lifecycle.context.js +36 -0
- package/lib/commonjs/providers/toast/lifecycle.context.js.map +1 -0
- package/lib/commonjs/providers/toast/provider.js +508 -0
- package/lib/commonjs/providers/toast/provider.js.map +1 -0
- package/lib/commonjs/providers/toast/reducer.js +46 -0
- package/lib/commonjs/providers/toast/reducer.js.map +1 -0
- package/lib/commonjs/providers/toast/toast-config.context.js +29 -0
- package/lib/commonjs/providers/toast/toast-config.context.js.map +1 -0
- package/lib/commonjs/providers/toast/toast-item-renderer.js +43 -0
- package/lib/commonjs/providers/toast/toast-item-renderer.js.map +1 -0
- package/lib/commonjs/providers/toast/types.js +6 -0
- package/lib/commonjs/providers/toast/types.js.map +1 -0
- package/lib/module/animation/hooks/index.js +4 -0
- package/lib/module/animation/hooks/index.js.map +1 -0
- package/lib/module/animation/hooks/useCombinedAnimationDisabledState.js +47 -0
- package/lib/module/animation/hooks/useCombinedAnimationDisabledState.js.map +1 -0
- package/lib/module/animation/index.js +6 -0
- package/lib/module/animation/index.js.map +1 -0
- package/lib/module/animation/types.js +4 -0
- package/lib/module/animation/types.js.map +1 -0
- package/lib/module/animation/utils.js +212 -0
- package/lib/module/animation/utils.js.map +1 -0
- package/lib/module/components/CLAUDE.md +1 -1
- package/lib/module/components/Card/index.js +47 -19
- package/lib/module/components/Card/index.js.map +1 -1
- package/lib/module/components/Toast/animation.js +324 -0
- package/lib/module/components/Toast/animation.js.map +1 -0
- package/lib/module/components/Toast/hooks.js +61 -0
- package/lib/module/components/Toast/hooks.js.map +1 -0
- package/lib/module/components/Toast/index.js +487 -0
- package/lib/module/components/Toast/index.js.map +1 -0
- package/lib/module/components/Toast/styles.js +138 -0
- package/lib/module/components/Toast/styles.js.map +1 -0
- package/lib/module/components/Toast/types.js +4 -0
- package/lib/module/components/Toast/types.js.map +1 -0
- package/lib/module/components/index.js +1 -0
- package/lib/module/components/index.js.map +1 -1
- package/lib/module/index.js +1 -0
- package/lib/module/index.js.map +1 -1
- package/lib/module/providers/animation-settings/index.js +4 -0
- package/lib/module/providers/animation-settings/index.js.map +1 -0
- package/lib/module/providers/animation-settings/provider.js +52 -0
- package/lib/module/providers/animation-settings/provider.js.map +1 -0
- package/lib/module/providers/animation-settings/types.js +4 -0
- package/lib/module/providers/animation-settings/types.js.map +1 -0
- package/lib/module/providers/forge-design/index.js +5 -0
- package/lib/module/providers/forge-design/index.js.map +1 -0
- package/lib/module/providers/forge-design/provider.js +66 -0
- package/lib/module/providers/forge-design/provider.js.map +1 -0
- package/lib/module/providers/forge-design/types.js +4 -0
- package/lib/module/providers/forge-design/types.js.map +1 -0
- package/lib/module/providers/text-component/index.js +5 -0
- package/lib/module/providers/text-component/index.js.map +1 -0
- package/lib/module/providers/text-component/provider.js +6 -0
- package/lib/module/providers/text-component/provider.js.map +1 -0
- package/lib/module/providers/text-component/types.js +4 -0
- package/lib/module/providers/text-component/types.js.map +1 -0
- package/lib/module/providers/toast/index.js +6 -0
- package/lib/module/providers/toast/index.js.map +1 -0
- package/lib/module/providers/toast/insets-container.js +156 -0
- package/lib/module/providers/toast/insets-container.js.map +1 -0
- package/lib/module/providers/toast/lifecycle.context.js +32 -0
- package/lib/module/providers/toast/lifecycle.context.js.map +1 -0
- package/lib/module/providers/toast/provider.js +503 -0
- package/lib/module/providers/toast/provider.js.map +1 -0
- package/lib/module/providers/toast/reducer.js +42 -0
- package/lib/module/providers/toast/reducer.js.map +1 -0
- package/lib/module/providers/toast/toast-config.context.js +25 -0
- package/lib/module/providers/toast/toast-config.context.js.map +1 -0
- package/lib/module/providers/toast/toast-item-renderer.js +39 -0
- package/lib/module/providers/toast/toast-item-renderer.js.map +1 -0
- package/lib/module/providers/toast/types.js +4 -0
- package/lib/module/providers/toast/types.js.map +1 -0
- package/lib/typescript/animation/hooks/index.d.ts +2 -0
- package/lib/typescript/animation/hooks/index.d.ts.map +1 -0
- package/lib/typescript/animation/hooks/useCombinedAnimationDisabledState.d.ts +22 -0
- package/lib/typescript/animation/hooks/useCombinedAnimationDisabledState.d.ts.map +1 -0
- package/lib/typescript/animation/index.d.ts +4 -0
- package/lib/typescript/animation/index.d.ts.map +1 -0
- package/lib/typescript/animation/types.d.ts +105 -0
- package/lib/typescript/animation/types.d.ts.map +1 -0
- package/lib/typescript/animation/utils.d.ts +120 -0
- package/lib/typescript/animation/utils.d.ts.map +1 -0
- package/lib/typescript/components/Card/index.d.ts +4 -0
- package/lib/typescript/components/Card/index.d.ts.map +1 -1
- package/lib/typescript/components/Toast/animation.d.ts +21 -0
- package/lib/typescript/components/Toast/animation.d.ts.map +1 -0
- package/lib/typescript/components/Toast/hooks.d.ts +17 -0
- package/lib/typescript/components/Toast/hooks.d.ts.map +1 -0
- package/lib/typescript/components/Toast/index.d.ts +28 -0
- package/lib/typescript/components/Toast/index.d.ts.map +1 -0
- package/lib/typescript/components/Toast/styles.d.ts +73 -0
- package/lib/typescript/components/Toast/styles.d.ts.map +1 -0
- package/lib/typescript/components/Toast/types.d.ts +303 -0
- package/lib/typescript/components/Toast/types.d.ts.map +1 -0
- package/lib/typescript/components/index.d.ts +1 -0
- package/lib/typescript/components/index.d.ts.map +1 -1
- package/lib/typescript/index.d.ts +2 -0
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/providers/animation-settings/index.d.ts +3 -0
- package/lib/typescript/providers/animation-settings/index.d.ts.map +1 -0
- package/lib/typescript/providers/animation-settings/provider.d.ts +28 -0
- package/lib/typescript/providers/animation-settings/provider.d.ts.map +1 -0
- package/lib/typescript/providers/animation-settings/types.d.ts +35 -0
- package/lib/typescript/providers/animation-settings/types.d.ts.map +1 -0
- package/lib/typescript/providers/forge-design/index.d.ts +3 -0
- package/lib/typescript/providers/forge-design/index.d.ts.map +1 -0
- package/lib/typescript/providers/forge-design/provider.d.ts +24 -0
- package/lib/typescript/providers/forge-design/provider.d.ts.map +1 -0
- package/lib/typescript/providers/forge-design/types.d.ts +82 -0
- package/lib/typescript/providers/forge-design/types.d.ts.map +1 -0
- package/lib/typescript/providers/text-component/index.d.ts +3 -0
- package/lib/typescript/providers/text-component/index.d.ts.map +1 -0
- package/lib/typescript/providers/text-component/provider.d.ts +7 -0
- package/lib/typescript/providers/text-component/provider.d.ts.map +1 -0
- package/lib/typescript/providers/text-component/types.d.ts +51 -0
- package/lib/typescript/providers/text-component/types.d.ts.map +1 -0
- package/lib/typescript/providers/toast/index.d.ts +5 -0
- package/lib/typescript/providers/toast/index.d.ts.map +1 -0
- package/lib/typescript/providers/toast/insets-container.d.ts +72 -0
- package/lib/typescript/providers/toast/insets-container.d.ts.map +1 -0
- package/lib/typescript/providers/toast/lifecycle.context.d.ts +32 -0
- package/lib/typescript/providers/toast/lifecycle.context.d.ts.map +1 -0
- package/lib/typescript/providers/toast/provider.d.ts +32 -0
- package/lib/typescript/providers/toast/provider.d.ts.map +1 -0
- package/lib/typescript/providers/toast/reducer.d.ts +14 -0
- package/lib/typescript/providers/toast/reducer.d.ts.map +1 -0
- package/lib/typescript/providers/toast/toast-config.context.d.ts +20 -0
- package/lib/typescript/providers/toast/toast-config.context.d.ts.map +1 -0
- package/lib/typescript/providers/toast/toast-item-renderer.d.ts +7 -0
- package/lib/typescript/providers/toast/toast-item-renderer.d.ts.map +1 -0
- package/lib/typescript/providers/toast/types.d.ts +422 -0
- package/lib/typescript/providers/toast/types.d.ts.map +1 -0
- package/package.json +4 -4
- package/src/animation/hooks/index.ts +1 -0
- package/src/animation/hooks/useCombinedAnimationDisabledState.ts +46 -0
- package/src/animation/index.ts +3 -0
- package/src/animation/types.ts +128 -0
- package/src/animation/utils.ts +249 -0
- package/src/components/CLAUDE.md +1 -1
- package/src/components/Card/index.tsx +58 -28
- package/src/components/Toast/animation.ts +387 -0
- package/src/components/Toast/hooks.ts +92 -0
- package/src/components/Toast/index.tsx +520 -0
- package/src/components/Toast/styles.ts +186 -0
- package/src/components/Toast/types.ts +332 -0
- package/src/components/index.ts +1 -0
- package/src/index.ts +2 -0
- package/src/providers/animation-settings/index.ts +11 -0
- package/src/providers/animation-settings/provider.tsx +54 -0
- package/src/providers/animation-settings/types.ts +37 -0
- package/src/providers/forge-design/index.ts +2 -0
- package/src/providers/forge-design/provider.tsx +61 -0
- package/src/providers/forge-design/types.ts +84 -0
- package/src/providers/text-component/index.ts +2 -0
- package/src/providers/text-component/provider.tsx +7 -0
- package/src/providers/text-component/types.ts +52 -0
- package/src/providers/toast/index.ts +4 -0
- package/src/providers/toast/insets-container.tsx +230 -0
- package/src/providers/toast/lifecycle.context.tsx +37 -0
- package/src/providers/toast/provider.tsx +567 -0
- package/src/providers/toast/reducer.ts +40 -0
- package/src/providers/toast/toast-config.context.ts +25 -0
- package/src/providers/toast/toast-item-renderer.tsx +40 -0
- package/src/providers/toast/types.ts +431 -0
|
@@ -0,0 +1,387 @@
|
|
|
1
|
+
import { Platform, useWindowDimensions } from 'react-native';
|
|
2
|
+
import { Gesture } from 'react-native-gesture-handler';
|
|
3
|
+
import {
|
|
4
|
+
Easing,
|
|
5
|
+
EntryOrExitLayoutType,
|
|
6
|
+
Extrapolation,
|
|
7
|
+
FadeInDown,
|
|
8
|
+
FadeInUp,
|
|
9
|
+
interpolate,
|
|
10
|
+
Keyframe,
|
|
11
|
+
useAnimatedStyle,
|
|
12
|
+
useSharedValue,
|
|
13
|
+
withDecay,
|
|
14
|
+
withSpring,
|
|
15
|
+
withTiming,
|
|
16
|
+
} from 'react-native-reanimated';
|
|
17
|
+
import { scheduleOnRN } from 'react-native-worklets';
|
|
18
|
+
import {
|
|
19
|
+
useCombinedAnimationDisabledState,
|
|
20
|
+
getAnimationValueMergedConfig,
|
|
21
|
+
getAnimationValueProperty,
|
|
22
|
+
getIsAnimationDisabledValue,
|
|
23
|
+
getRootAnimationState,
|
|
24
|
+
} from '../../animation';
|
|
25
|
+
import type { UseToastRootAnimationOptions } from './types';
|
|
26
|
+
|
|
27
|
+
// --------------------------------------------------
|
|
28
|
+
|
|
29
|
+
export const enteringTop = FadeInUp.springify()
|
|
30
|
+
.withInitialValues({
|
|
31
|
+
opacity: 1,
|
|
32
|
+
transform: [{ translateY: -100 }],
|
|
33
|
+
})
|
|
34
|
+
.mass(3);
|
|
35
|
+
|
|
36
|
+
export const exitingTop = new Keyframe({
|
|
37
|
+
0: {
|
|
38
|
+
opacity: 1,
|
|
39
|
+
transform: [{ translateY: 0 }, { scale: 1 }],
|
|
40
|
+
},
|
|
41
|
+
100: {
|
|
42
|
+
opacity: 0.5,
|
|
43
|
+
transform: [{ translateY: -100 }, { scale: 0.97 }],
|
|
44
|
+
easing: Easing.bezier(0.4, 0, 1, 1),
|
|
45
|
+
},
|
|
46
|
+
}).duration(150);
|
|
47
|
+
|
|
48
|
+
export const enteringBottom = FadeInDown.springify()
|
|
49
|
+
.withInitialValues({
|
|
50
|
+
opacity: 1,
|
|
51
|
+
transform: [{ translateY: 100 }],
|
|
52
|
+
})
|
|
53
|
+
.mass(3);
|
|
54
|
+
|
|
55
|
+
export const exitingBottom = new Keyframe({
|
|
56
|
+
0: {
|
|
57
|
+
opacity: 1,
|
|
58
|
+
transform: [{ translateY: 0 }, { scale: 1 }],
|
|
59
|
+
},
|
|
60
|
+
100: {
|
|
61
|
+
opacity: 0.5,
|
|
62
|
+
transform: [{ translateY: 100 }, { scale: 0.97 }],
|
|
63
|
+
easing: Easing.bezier(0.4, 0, 1, 1),
|
|
64
|
+
},
|
|
65
|
+
}).duration(150);
|
|
66
|
+
|
|
67
|
+
export interface UseToastRootAnimationResult {
|
|
68
|
+
rContainerStyle: ReturnType<typeof useAnimatedStyle>;
|
|
69
|
+
isAllAnimationsDisabled: boolean;
|
|
70
|
+
entering: EntryOrExitLayoutType | undefined;
|
|
71
|
+
exiting: EntryOrExitLayoutType | undefined;
|
|
72
|
+
panGesture: ReturnType<typeof Gesture.Pan>;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// --------------------------------------------------
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Animation hook for Toast root component
|
|
79
|
+
* Handles opacity, translateY, and scale animations based on toast index and placement
|
|
80
|
+
* Also handles gesture-based swipe to dismiss and rubber-band drag effects
|
|
81
|
+
*/
|
|
82
|
+
export function useToastRootAnimation(
|
|
83
|
+
options: UseToastRootAnimationOptions,
|
|
84
|
+
): UseToastRootAnimationResult {
|
|
85
|
+
const {
|
|
86
|
+
animation,
|
|
87
|
+
index,
|
|
88
|
+
total,
|
|
89
|
+
heights,
|
|
90
|
+
placement = 'bottom',
|
|
91
|
+
hide,
|
|
92
|
+
id,
|
|
93
|
+
isSwipeable = true,
|
|
94
|
+
maxVisibleToasts = 3,
|
|
95
|
+
} = options;
|
|
96
|
+
|
|
97
|
+
const { height: screenHeight } = useWindowDimensions();
|
|
98
|
+
|
|
99
|
+
const { animationConfig, isAnimationDisabled } = getRootAnimationState(animation);
|
|
100
|
+
|
|
101
|
+
const isAllAnimationsDisabled = useCombinedAnimationDisabledState(animation);
|
|
102
|
+
|
|
103
|
+
const isAnimationDisabledValue = getIsAnimationDisabledValue({
|
|
104
|
+
isAnimationDisabled,
|
|
105
|
+
isAllAnimationsDisabled,
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
// Entering animation
|
|
109
|
+
const enteringTopValue = getAnimationValueProperty({
|
|
110
|
+
animationValue: animationConfig?.entering,
|
|
111
|
+
property: 'top',
|
|
112
|
+
defaultValue: enteringTop,
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
const enteringBottomValue = getAnimationValueProperty({
|
|
116
|
+
animationValue: animationConfig?.entering,
|
|
117
|
+
property: 'bottom',
|
|
118
|
+
defaultValue: enteringBottom,
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
// Exiting animation
|
|
122
|
+
const exitingTopValue = getAnimationValueProperty({
|
|
123
|
+
animationValue: animationConfig?.exiting,
|
|
124
|
+
property: 'top',
|
|
125
|
+
defaultValue: exitingTop,
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
const exitingBottomValue = getAnimationValueProperty({
|
|
129
|
+
animationValue: animationConfig?.exiting,
|
|
130
|
+
property: 'bottom',
|
|
131
|
+
defaultValue: exitingBottom,
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
// Opacity animation
|
|
135
|
+
const opacityValue = getAnimationValueProperty({
|
|
136
|
+
animationValue: animationConfig?.opacity,
|
|
137
|
+
property: 'value',
|
|
138
|
+
defaultValue: [1, 0] as [number, number],
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
const opacityTimingConfig = getAnimationValueMergedConfig({
|
|
142
|
+
animationValue: animationConfig?.opacity,
|
|
143
|
+
property: 'timingConfig',
|
|
144
|
+
defaultValue: { duration: 300 },
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
// TranslateY animation
|
|
148
|
+
const translateYValue = getAnimationValueProperty({
|
|
149
|
+
animationValue: animationConfig?.translateY,
|
|
150
|
+
property: 'value',
|
|
151
|
+
defaultValue: [0, 10] as [number, number],
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
const translateYTimingConfig = getAnimationValueMergedConfig({
|
|
155
|
+
animationValue: animationConfig?.translateY,
|
|
156
|
+
property: 'timingConfig',
|
|
157
|
+
defaultValue: { duration: 300 },
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
// Scale animation
|
|
161
|
+
const scaleValue = getAnimationValueProperty({
|
|
162
|
+
animationValue: animationConfig?.scale,
|
|
163
|
+
property: 'value',
|
|
164
|
+
defaultValue: [1, 0.97] as [number, number],
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
const scaleTimingConfig = getAnimationValueMergedConfig({
|
|
168
|
+
animationValue: animationConfig?.scale,
|
|
169
|
+
property: 'timingConfig',
|
|
170
|
+
defaultValue: { duration: 300 },
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
// Gesture state shared values
|
|
174
|
+
const isDragging = useSharedValue(false);
|
|
175
|
+
const gestureTranslateY = useSharedValue(0);
|
|
176
|
+
const gestureScale = useSharedValue(1);
|
|
177
|
+
|
|
178
|
+
// Helper function to delay hide call based on velocity
|
|
179
|
+
const delayedHide = (toastId: string | undefined, velocity: number) => {
|
|
180
|
+
const velocityBasedTimeout = Math.min(200, Math.abs(velocity));
|
|
181
|
+
setTimeout(() => {
|
|
182
|
+
if (hide && toastId) {
|
|
183
|
+
hide(toastId);
|
|
184
|
+
}
|
|
185
|
+
}, velocityBasedTimeout);
|
|
186
|
+
};
|
|
187
|
+
|
|
188
|
+
// Create pan gesture handler
|
|
189
|
+
const panGesture = Gesture.Pan()
|
|
190
|
+
.enabled(!isAnimationDisabledValue && isSwipeable)
|
|
191
|
+
.onBegin(() => {
|
|
192
|
+
isDragging.set(true);
|
|
193
|
+
gestureTranslateY.set(0);
|
|
194
|
+
gestureScale.set(0.995);
|
|
195
|
+
})
|
|
196
|
+
.onChange((event) => {
|
|
197
|
+
if (!isDragging.get()) return;
|
|
198
|
+
|
|
199
|
+
const translationY = event.translationY;
|
|
200
|
+
const maxDragDistance = screenHeight;
|
|
201
|
+
const rubberEffectDistance = 40;
|
|
202
|
+
|
|
203
|
+
if (placement.startsWith('top')) {
|
|
204
|
+
// Top placement: swipe up (negative Y) to dismiss, drag down (positive Y) with rubber effect
|
|
205
|
+
if (translationY < 0) {
|
|
206
|
+
// Swiping up - direct translation for dismissal
|
|
207
|
+
gestureTranslateY.set(translationY);
|
|
208
|
+
} else if (translationY > 0) {
|
|
209
|
+
// Dragging down - apply rubber effect
|
|
210
|
+
const rubberTranslateY = interpolate(
|
|
211
|
+
translationY,
|
|
212
|
+
[0, maxDragDistance],
|
|
213
|
+
[0, rubberEffectDistance],
|
|
214
|
+
Extrapolation.CLAMP,
|
|
215
|
+
);
|
|
216
|
+
gestureTranslateY.set(rubberTranslateY);
|
|
217
|
+
}
|
|
218
|
+
} else {
|
|
219
|
+
// Bottom placement: swipe down (positive Y) to dismiss, drag up (negative Y) with rubber effect
|
|
220
|
+
if (translationY > 0) {
|
|
221
|
+
// Swiping down - direct translation for dismissal
|
|
222
|
+
gestureTranslateY.set(translationY);
|
|
223
|
+
} else if (translationY < 0) {
|
|
224
|
+
// Dragging up - apply rubber effect
|
|
225
|
+
const rubberTranslateY = interpolate(
|
|
226
|
+
Math.abs(translationY),
|
|
227
|
+
[0, maxDragDistance],
|
|
228
|
+
[0, rubberEffectDistance],
|
|
229
|
+
Extrapolation.CLAMP,
|
|
230
|
+
);
|
|
231
|
+
gestureTranslateY.set(-rubberTranslateY);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
})
|
|
235
|
+
.onFinalize((event) => {
|
|
236
|
+
gestureScale.set(1);
|
|
237
|
+
|
|
238
|
+
const translationY = event.translationY;
|
|
239
|
+
const velocityY = event.velocityY;
|
|
240
|
+
const dismissThreshold = 50;
|
|
241
|
+
const velocityThreshold = 500;
|
|
242
|
+
|
|
243
|
+
// Check if dismissal threshold is met (distance > 50px OR velocity > 500)
|
|
244
|
+
const shouldDismiss =
|
|
245
|
+
Math.abs(translationY) > dismissThreshold || Math.abs(velocityY) > velocityThreshold;
|
|
246
|
+
|
|
247
|
+
if (placement.startsWith('top')) {
|
|
248
|
+
// Top placement: dismiss if swiped up (negative Y)
|
|
249
|
+
if (shouldDismiss && translationY < 0 && id) {
|
|
250
|
+
// Use withDecay to continue motion with velocity
|
|
251
|
+
gestureTranslateY.set(
|
|
252
|
+
withDecay(
|
|
253
|
+
{
|
|
254
|
+
velocity: velocityY * 1.5,
|
|
255
|
+
clamp: [Number.NEGATIVE_INFINITY, 0],
|
|
256
|
+
},
|
|
257
|
+
() => {
|
|
258
|
+
isDragging.set(false);
|
|
259
|
+
},
|
|
260
|
+
),
|
|
261
|
+
);
|
|
262
|
+
// Delay hide call to allow decay animation to play
|
|
263
|
+
scheduleOnRN(delayedHide, id, velocityY);
|
|
264
|
+
} else {
|
|
265
|
+
// Animate back to 0
|
|
266
|
+
gestureTranslateY.set(withSpring(0));
|
|
267
|
+
isDragging.set(false);
|
|
268
|
+
}
|
|
269
|
+
} else {
|
|
270
|
+
// Bottom placement: dismiss if swiped down (positive Y)
|
|
271
|
+
if (shouldDismiss && translationY > 0 && id) {
|
|
272
|
+
// Use withDecay to continue motion with velocity
|
|
273
|
+
gestureTranslateY.set(
|
|
274
|
+
withDecay(
|
|
275
|
+
{
|
|
276
|
+
velocity: velocityY * 1.5,
|
|
277
|
+
clamp: [0, Number.POSITIVE_INFINITY],
|
|
278
|
+
},
|
|
279
|
+
() => {
|
|
280
|
+
isDragging.set(false);
|
|
281
|
+
},
|
|
282
|
+
),
|
|
283
|
+
);
|
|
284
|
+
// Delay hide call to allow decay animation to play
|
|
285
|
+
scheduleOnRN(delayedHide, id, velocityY);
|
|
286
|
+
} else {
|
|
287
|
+
// Animate back to 0
|
|
288
|
+
gestureTranslateY.set(withSpring(0));
|
|
289
|
+
isDragging.set(false);
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
});
|
|
293
|
+
|
|
294
|
+
// Web drives enter/exit via CSS transitions on `data-state` (see Toast/styles.ts
|
|
295
|
+
// and Toast/index.tsx). Its `height` is left unset so the toast owns its own
|
|
296
|
+
// natural height — the Reanimated `height: withSpring(...)` channel collides
|
|
297
|
+
// with the CSS engine during handoff and produces the "translate down/up + right"
|
|
298
|
+
// blink that the review flagged. Native keeps the spring so stack-height changes
|
|
299
|
+
// animate smoothly.
|
|
300
|
+
const isWeb = Platform.OS === 'web';
|
|
301
|
+
|
|
302
|
+
const rContainerStyle = useAnimatedStyle(() => {
|
|
303
|
+
const lastToastId = Object.keys(heights.get())[Object.keys(heights.get()).length - 1];
|
|
304
|
+
const lastToastHeight = lastToastId ? heights.get()[lastToastId] : undefined;
|
|
305
|
+
|
|
306
|
+
const sign = placement.startsWith('top') ? 1 : -1;
|
|
307
|
+
|
|
308
|
+
const totalValue = total.get();
|
|
309
|
+
|
|
310
|
+
const inputRange = [totalValue - 1, totalValue - 2];
|
|
311
|
+
const opacityInputRange = [totalValue - maxVisibleToasts, totalValue - maxVisibleToasts - 1];
|
|
312
|
+
|
|
313
|
+
const opacity = interpolate(index, opacityInputRange, opacityValue);
|
|
314
|
+
|
|
315
|
+
// Handle translateY based on dragging state
|
|
316
|
+
let translateY: number;
|
|
317
|
+
let scale: number;
|
|
318
|
+
if (isDragging.get()) {
|
|
319
|
+
// During gesture: use gesture-based translateY
|
|
320
|
+
translateY = gestureTranslateY.get();
|
|
321
|
+
scale = gestureScale.get();
|
|
322
|
+
} else {
|
|
323
|
+
// Normal state: use stack-based interpolation
|
|
324
|
+
translateY = interpolate(index, inputRange, [translateYValue[0], translateYValue[1] * sign], {
|
|
325
|
+
extrapolateLeft: Extrapolation.CLAMP,
|
|
326
|
+
});
|
|
327
|
+
scale = interpolate(index, inputRange, scaleValue, {
|
|
328
|
+
extrapolateLeft: Extrapolation.CLAMP,
|
|
329
|
+
});
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
if (isAnimationDisabledValue) {
|
|
333
|
+
return {
|
|
334
|
+
height: isWeb ? undefined : lastToastHeight,
|
|
335
|
+
pointerEvents: opacity === 0 ? 'none' : 'auto',
|
|
336
|
+
opacity,
|
|
337
|
+
transform: [
|
|
338
|
+
{
|
|
339
|
+
translateY,
|
|
340
|
+
},
|
|
341
|
+
{
|
|
342
|
+
scale,
|
|
343
|
+
},
|
|
344
|
+
],
|
|
345
|
+
};
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
return {
|
|
349
|
+
height: isWeb
|
|
350
|
+
? undefined
|
|
351
|
+
: lastToastHeight
|
|
352
|
+
? withSpring(lastToastHeight, {
|
|
353
|
+
damping: 100,
|
|
354
|
+
stiffness: 1200,
|
|
355
|
+
mass: 3,
|
|
356
|
+
})
|
|
357
|
+
: undefined,
|
|
358
|
+
pointerEvents: opacity === 0 ? 'none' : 'auto',
|
|
359
|
+
opacity: withTiming(opacity, opacityTimingConfig),
|
|
360
|
+
transform: [
|
|
361
|
+
{
|
|
362
|
+
translateY: isDragging.get()
|
|
363
|
+
? translateY
|
|
364
|
+
: withTiming(translateY, translateYTimingConfig),
|
|
365
|
+
},
|
|
366
|
+
{
|
|
367
|
+
scale: isDragging.get() ? withSpring(scale) : withTiming(scale, scaleTimingConfig),
|
|
368
|
+
},
|
|
369
|
+
],
|
|
370
|
+
};
|
|
371
|
+
});
|
|
372
|
+
|
|
373
|
+
// Determine entering and exiting animations based on placement
|
|
374
|
+
const enteringAnimation = placement.startsWith('top') ? enteringTopValue : enteringBottomValue;
|
|
375
|
+
const exitingAnimation = placement.startsWith('top') ? exitingTopValue : exitingBottomValue;
|
|
376
|
+
|
|
377
|
+
return {
|
|
378
|
+
rContainerStyle,
|
|
379
|
+
isAllAnimationsDisabled,
|
|
380
|
+
// Web replaces Reanimated layout animations with CSS transitions driven
|
|
381
|
+
// by `data-state`; returning `undefined` here prevents the two channels
|
|
382
|
+
// from colliding on the wrapper `Animated.View`.
|
|
383
|
+
entering: isAnimationDisabledValue || isWeb ? undefined : enteringAnimation,
|
|
384
|
+
exiting: isAnimationDisabledValue || isWeb ? undefined : exitingAnimation,
|
|
385
|
+
panGesture,
|
|
386
|
+
};
|
|
387
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { useMemo } from 'react';
|
|
2
|
+
import type { StyleProp, ViewStyle } from 'react-native';
|
|
3
|
+
import { StyleSheet } from 'react-native';
|
|
4
|
+
import { useResolveClassNames } from 'uniwind';
|
|
5
|
+
import type { ButtonProps } from '../Button';
|
|
6
|
+
import { ToastColor } from './types';
|
|
7
|
+
|
|
8
|
+
export function useButtonColor({
|
|
9
|
+
color,
|
|
10
|
+
toastColor,
|
|
11
|
+
}: {
|
|
12
|
+
color: ButtonProps['color'];
|
|
13
|
+
toastColor: ToastColor;
|
|
14
|
+
}) {
|
|
15
|
+
// TODO: Add toastActionVariants to styles.ts to restore color-aware action styling
|
|
16
|
+
return useMemo(() => {
|
|
17
|
+
if (color) return color;
|
|
18
|
+
|
|
19
|
+
switch (toastColor) {
|
|
20
|
+
case 'info':
|
|
21
|
+
return 'info';
|
|
22
|
+
case 'success':
|
|
23
|
+
return 'success';
|
|
24
|
+
case 'warning':
|
|
25
|
+
return 'warning';
|
|
26
|
+
case 'danger':
|
|
27
|
+
return 'danger';
|
|
28
|
+
default:
|
|
29
|
+
return 'action';
|
|
30
|
+
}
|
|
31
|
+
}, [toastColor, color]);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
interface UseVerticalPlaceholderStylesParams {
|
|
35
|
+
rootClassName?: string;
|
|
36
|
+
style?: StyleProp<ViewStyle>;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function useVerticalPlaceholderStyles({
|
|
40
|
+
rootClassName,
|
|
41
|
+
style,
|
|
42
|
+
}: UseVerticalPlaceholderStylesParams) {
|
|
43
|
+
const resolvedRootClassName = useResolveClassNames(rootClassName ?? '');
|
|
44
|
+
|
|
45
|
+
return useMemo(() => {
|
|
46
|
+
const resolvedStyle = style ? StyleSheet.flatten(style) : undefined;
|
|
47
|
+
|
|
48
|
+
const stylePaddingTop =
|
|
49
|
+
resolvedStyle?.paddingTop ?? resolvedStyle?.paddingVertical ?? resolvedStyle?.padding;
|
|
50
|
+
const stylePaddingBottom =
|
|
51
|
+
resolvedStyle?.paddingBottom ?? resolvedStyle?.paddingVertical ?? resolvedStyle?.padding;
|
|
52
|
+
|
|
53
|
+
const classNamePaddingTop =
|
|
54
|
+
resolvedRootClassName?.paddingTop ??
|
|
55
|
+
resolvedRootClassName?.paddingVertical ??
|
|
56
|
+
resolvedRootClassName?.padding;
|
|
57
|
+
const classNamePaddingBottom =
|
|
58
|
+
resolvedRootClassName?.paddingBottom ??
|
|
59
|
+
resolvedRootClassName?.paddingVertical ??
|
|
60
|
+
resolvedRootClassName?.padding;
|
|
61
|
+
|
|
62
|
+
const paddingTopValue = stylePaddingTop ?? classNamePaddingTop;
|
|
63
|
+
const paddingBottomValue = stylePaddingBottom ?? classNamePaddingBottom;
|
|
64
|
+
|
|
65
|
+
const topHeight =
|
|
66
|
+
typeof paddingTopValue === 'number' && paddingTopValue >= 0 ? paddingTopValue : 0;
|
|
67
|
+
const bottomHeight =
|
|
68
|
+
typeof paddingBottomValue === 'number' && paddingBottomValue >= 0 ? paddingBottomValue : 0;
|
|
69
|
+
|
|
70
|
+
const styleBackgroundColor = resolvedStyle?.backgroundColor;
|
|
71
|
+
const classNameBackgroundColor = resolvedRootClassName?.backgroundColor;
|
|
72
|
+
const backgroundColor = styleBackgroundColor ?? classNameBackgroundColor ?? undefined;
|
|
73
|
+
|
|
74
|
+
const topStyle: ViewStyle = {
|
|
75
|
+
height: topHeight,
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
const bottomStyle: ViewStyle = {
|
|
79
|
+
height: bottomHeight,
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
if (backgroundColor !== undefined) {
|
|
83
|
+
topStyle.backgroundColor = backgroundColor;
|
|
84
|
+
bottomStyle.backgroundColor = backgroundColor;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
return {
|
|
88
|
+
topStyle,
|
|
89
|
+
bottomStyle,
|
|
90
|
+
};
|
|
91
|
+
}, [resolvedRootClassName, style]);
|
|
92
|
+
}
|