zkit-ui 1.0.2 → 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ui/Button/index.d.ts.map +1 -1
- package/dist/ui/Button/index.js +124 -11
- package/package.json +1 -1
- package/src/ui/Button/README.md +1 -1
- package/src/ui/Button/index.tsx +267 -12
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/ui/Button/index.tsx"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/ui/Button/index.tsx"],"names":[],"mappings":"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"}
|
package/dist/ui/Button/index.js
CHANGED
|
@@ -53,6 +53,7 @@ const LOADING_TIMING = {
|
|
|
53
53
|
easing: react_native_reanimated_1.Easing.out(react_native_reanimated_1.Easing.cubic),
|
|
54
54
|
reduceMotion: react_native_reanimated_1.ReduceMotion.System,
|
|
55
55
|
};
|
|
56
|
+
const ANIMATED_EXIT_RESIDENCY_MS = LOADING_TIMING.duration + 40;
|
|
56
57
|
const DISABLED_OPACITY = 0.52;
|
|
57
58
|
const PRESSED_OPACITY = 0.82;
|
|
58
59
|
const PRESSED_SCALE = 0.985;
|
|
@@ -373,7 +374,7 @@ function resolvePressEffect(effect, interactionDisabled) {
|
|
|
373
374
|
return 'none';
|
|
374
375
|
if (effect !== 'auto')
|
|
375
376
|
return effect;
|
|
376
|
-
return '
|
|
377
|
+
return 'opacity';
|
|
377
378
|
}
|
|
378
379
|
function resolvePressEffectFlags(effect) {
|
|
379
380
|
return {
|
|
@@ -544,12 +545,10 @@ function requiresAnimatedPressEffect(effect) {
|
|
|
544
545
|
effect === 'highlight' ||
|
|
545
546
|
effect === 'scale-highlight');
|
|
546
547
|
}
|
|
547
|
-
function
|
|
548
|
-
if (loading)
|
|
549
|
-
return false;
|
|
548
|
+
function shouldRequestAnimatedPressPath({ disabled, pressEffect, }) {
|
|
550
549
|
if (disabled)
|
|
551
|
-
return
|
|
552
|
-
return
|
|
550
|
+
return false;
|
|
551
|
+
return requiresAnimatedPressEffect(pressEffect);
|
|
553
552
|
}
|
|
554
553
|
function useButtonFrame({ variant = 'solid', tone = 'primary', size = 'md', shape = 'rounded', block = false, disabled = false, loading = false, icon, iconPlacement = 'start', iconOnly = false, color, colors, border, layout, gradient, shadow = 'none', children, textStyle, accessibilityLabel, }) {
|
|
555
554
|
var _a, _b;
|
|
@@ -741,6 +740,101 @@ function ButtonStaticImpl({ variant = 'solid', tone = 'primary', size = 'md', sh
|
|
|
741
740
|
contentStyle,
|
|
742
741
|
], children: [LinearGradientComponent && gradientCfg ? ((0, jsx_runtime_1.jsx)(LinearGradientComponent, { pointerEvents: "none", colors: gradientCfg.colors, start: gradientCfg.start, end: gradientCfg.end, style: [react_native_1.StyleSheet.absoluteFillObject, radiusStyle] })) : null, iconOnly ? ((icon !== null && icon !== void 0 ? icon : resolvedText)) : ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [icon && iconPlacement === 'start' ? ((0, jsx_runtime_1.jsx)(react_native_1.View, { style: [iconBaseBoxStyle, iconPlacedBoxStyle], children: icon })) : null, resolvedText, icon && iconPlacement === 'end' ? ((0, jsx_runtime_1.jsx)(react_native_1.View, { style: [iconBaseBoxStyle, iconPlacedBoxStyle], children: icon })) : null] }))] }) }));
|
|
743
742
|
}
|
|
743
|
+
function ButtonPressAnimatedImpl({ variant = 'solid', tone = 'primary', size = 'md', shape = 'rounded', block = false, disabled = false, loading = false, loadingMode: _loadingMode = 'inline', pressEffect = 'auto', icon, iconPlacement = 'start', iconOnly = false, color, colors, border, layout, gradient, shadow = 'none', children, style, contentStyle, textStyle, accessibilityLabel, accessibilityState, hitSlop, onPress, onPressIn, onPressOut, testID, ...pressableProps }, ref) {
|
|
744
|
+
const frame = useButtonFrame({
|
|
745
|
+
accessibilityLabel,
|
|
746
|
+
block,
|
|
747
|
+
border,
|
|
748
|
+
children,
|
|
749
|
+
color,
|
|
750
|
+
colors,
|
|
751
|
+
disabled,
|
|
752
|
+
gradient,
|
|
753
|
+
icon,
|
|
754
|
+
iconOnly,
|
|
755
|
+
iconPlacement,
|
|
756
|
+
layout,
|
|
757
|
+
loading,
|
|
758
|
+
shadow,
|
|
759
|
+
shape,
|
|
760
|
+
size,
|
|
761
|
+
textStyle,
|
|
762
|
+
tone,
|
|
763
|
+
variant,
|
|
764
|
+
});
|
|
765
|
+
const { accentColor, borderStyle, contentSizeStyle, defaultHitSlop, gradientCfg, hasGradientBackground, hasIcon, iconBaseBoxStyle, iconPlacedBoxStyle, interactionDisabled, LinearGradientComponent, paddingStyle, radiusStyle, resolvedAccessibilityLabel, resolvedText, rootSizeStyle, shadowStyle, visualColors, visualDisabled, webCursorStyle, } = frame;
|
|
766
|
+
const pressSv = (0, react_native_reanimated_1.useSharedValue)(0);
|
|
767
|
+
const resolvedPressEffect = React.useMemo(() => resolvePressEffect(pressEffect, interactionDisabled), [interactionDisabled, pressEffect]);
|
|
768
|
+
const pressEffectFlags = React.useMemo(() => resolvePressEffectFlags(resolvedPressEffect), [resolvedPressEffect]);
|
|
769
|
+
const pressHighlightEnabled = pressEffectFlags.highlight;
|
|
770
|
+
const pressOpacityEnabled = pressEffectFlags.opacity;
|
|
771
|
+
const pressScaleEnabled = pressEffectFlags.scale;
|
|
772
|
+
const pressOverlay = React.useMemo(() => resolveOverlay({
|
|
773
|
+
accentColor,
|
|
774
|
+
colors,
|
|
775
|
+
hasGradientBackground,
|
|
776
|
+
variant,
|
|
777
|
+
}), [accentColor, colors, hasGradientBackground, variant]);
|
|
778
|
+
React.useEffect(() => {
|
|
779
|
+
if (interactionDisabled || resolvedPressEffect === 'none') {
|
|
780
|
+
pressSv.value = 0;
|
|
781
|
+
}
|
|
782
|
+
}, [interactionDisabled, pressSv, resolvedPressEffect]);
|
|
783
|
+
const rootAnimatedStyle = (0, react_native_reanimated_1.useAnimatedStyle)(() => {
|
|
784
|
+
const baseOpacity = visualDisabled ? DISABLED_OPACITY : 1;
|
|
785
|
+
const scale = pressScaleEnabled
|
|
786
|
+
? (0, react_native_reanimated_1.interpolate)(pressSv.value, [0, 1], [1, PRESSED_SCALE])
|
|
787
|
+
: 1;
|
|
788
|
+
const opacity = pressOpacityEnabled
|
|
789
|
+
? (0, react_native_reanimated_1.interpolate)(pressSv.value, [0, 1], [baseOpacity, PRESSED_OPACITY])
|
|
790
|
+
: baseOpacity;
|
|
791
|
+
return {
|
|
792
|
+
opacity,
|
|
793
|
+
transform: [{ scale }],
|
|
794
|
+
};
|
|
795
|
+
}, [pressOpacityEnabled, pressScaleEnabled, visualDisabled]);
|
|
796
|
+
const overlayAnimatedStyle = (0, react_native_reanimated_1.useAnimatedStyle)(() => {
|
|
797
|
+
const opacity = pressHighlightEnabled
|
|
798
|
+
? (0, react_native_reanimated_1.interpolate)(pressSv.value, [0, 1], [0, pressOverlay.strength])
|
|
799
|
+
: 0;
|
|
800
|
+
return { opacity };
|
|
801
|
+
}, [pressHighlightEnabled, pressOverlay.strength]);
|
|
802
|
+
const handlePress = React.useCallback((event) => {
|
|
803
|
+
if (interactionDisabled)
|
|
804
|
+
return;
|
|
805
|
+
onPress === null || onPress === void 0 ? void 0 : onPress(event);
|
|
806
|
+
}, [interactionDisabled, onPress]);
|
|
807
|
+
const handlePressIn = React.useCallback((event) => {
|
|
808
|
+
if (!interactionDisabled && resolvedPressEffect !== 'none') {
|
|
809
|
+
pressSv.value = (0, react_native_reanimated_1.withTiming)(1, PRESS_TIMING);
|
|
810
|
+
}
|
|
811
|
+
onPressIn === null || onPressIn === void 0 ? void 0 : onPressIn(event);
|
|
812
|
+
}, [interactionDisabled, onPressIn, pressSv, resolvedPressEffect]);
|
|
813
|
+
const handlePressOut = React.useCallback((event) => {
|
|
814
|
+
if (!interactionDisabled && resolvedPressEffect !== 'none') {
|
|
815
|
+
pressSv.value = (0, react_native_reanimated_1.withTiming)(0, PRESS_TIMING);
|
|
816
|
+
}
|
|
817
|
+
onPressOut === null || onPressOut === void 0 ? void 0 : onPressOut(event);
|
|
818
|
+
}, [interactionDisabled, onPressOut, pressSv, resolvedPressEffect]);
|
|
819
|
+
return ((0, jsx_runtime_1.jsx)(AnimatedPressable, { ...pressableProps, ref: ref, accessibilityLabel: resolvedAccessibilityLabel, accessibilityRole: "button", accessibilityState: {
|
|
820
|
+
...accessibilityState,
|
|
821
|
+
busy: Boolean(loading || (accessibilityState === null || accessibilityState === void 0 ? void 0 : accessibilityState.busy)),
|
|
822
|
+
disabled: Boolean(interactionDisabled || (accessibilityState === null || accessibilityState === void 0 ? void 0 : accessibilityState.disabled)),
|
|
823
|
+
}, disabled: interactionDisabled, hitSlop: hitSlop !== null && hitSlop !== void 0 ? hitSlop : defaultHitSlop, onPress: handlePress, onPressIn: handlePressIn, onPressOut: handlePressOut, style: [styles.root, rootSizeStyle, radiusStyle, shadowStyle, rootAnimatedStyle, webCursorStyle, style], testID: testID, children: (0, jsx_runtime_1.jsxs)(react_native_1.View, { pointerEvents: "none", style: [
|
|
824
|
+
styles.content,
|
|
825
|
+
contentSizeStyle,
|
|
826
|
+
paddingStyle,
|
|
827
|
+
radiusStyle,
|
|
828
|
+
borderStyle,
|
|
829
|
+
{ backgroundColor: visualColors.backgroundColor },
|
|
830
|
+
contentStyle,
|
|
831
|
+
], children: [LinearGradientComponent && gradientCfg ? ((0, jsx_runtime_1.jsx)(LinearGradientComponent, { pointerEvents: "none", colors: gradientCfg.colors, start: gradientCfg.start, end: gradientCfg.end, style: [react_native_1.StyleSheet.absoluteFillObject, radiusStyle] })) : null, pressHighlightEnabled ? ((0, jsx_runtime_1.jsx)(react_native_reanimated_1.default.View, { pointerEvents: "none", style: [
|
|
832
|
+
react_native_1.StyleSheet.absoluteFillObject,
|
|
833
|
+
radiusStyle,
|
|
834
|
+
{ backgroundColor: pressOverlay.color },
|
|
835
|
+
overlayAnimatedStyle,
|
|
836
|
+
] })) : null, iconOnly ? ((icon !== null && icon !== void 0 ? icon : resolvedText)) : ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [icon && iconPlacement === 'start' ? ((0, jsx_runtime_1.jsx)(react_native_1.View, { style: [iconBaseBoxStyle, iconPlacedBoxStyle], children: icon })) : null, resolvedText, icon && iconPlacement === 'end' ? ((0, jsx_runtime_1.jsx)(react_native_1.View, { style: [iconBaseBoxStyle, iconPlacedBoxStyle], children: icon })) : null] }))] }) }));
|
|
837
|
+
}
|
|
744
838
|
function ButtonAnimatedImpl({ variant = 'solid', tone = 'primary', size = 'md', shape = 'rounded', block = false, disabled = false, loading = false, loadingMode = 'inline', pressEffect = 'auto', icon, iconPlacement = 'start', iconOnly = false, color, colors, border, layout, gradient, shadow = 'none', children, style, contentStyle, textStyle, accessibilityLabel, accessibilityState, hitSlop, onPress, onPressIn, onPressOut, testID, ...pressableProps }, ref) {
|
|
745
839
|
const resolvedLoadingMode = iconOnly ? 'overlay' : loadingMode;
|
|
746
840
|
const centeredLoading = resolvedLoadingMode !== 'inline';
|
|
@@ -773,7 +867,7 @@ function ButtonAnimatedImpl({ variant = 'solid', tone = 'primary', size = 'md',
|
|
|
773
867
|
variant,
|
|
774
868
|
}), [iconOnly, layout, metrics, variant]);
|
|
775
869
|
const pressSv = (0, react_native_reanimated_1.useSharedValue)(0);
|
|
776
|
-
const loadingSv = (0, react_native_reanimated_1.useSharedValue)(
|
|
870
|
+
const loadingSv = (0, react_native_reanimated_1.useSharedValue)(0);
|
|
777
871
|
const [spinnerMounted, setSpinnerMounted] = React.useState(loading);
|
|
778
872
|
const hideSpinnerTimerRef = React.useRef(null);
|
|
779
873
|
const resolvedPressEffect = React.useMemo(() => resolvePressEffect(pressEffect, interactionDisabled), [interactionDisabled, pressEffect]);
|
|
@@ -924,13 +1018,32 @@ function ButtonAnimatedImpl({ variant = 'solid', tone = 'primary', size = 'md',
|
|
|
924
1018
|
}
|
|
925
1019
|
const ButtonStaticWithRef = React.forwardRef(ButtonStaticImpl);
|
|
926
1020
|
ButtonStaticWithRef.displayName = 'ButtonStatic';
|
|
1021
|
+
const ButtonPressAnimatedWithRef = React.forwardRef(ButtonPressAnimatedImpl);
|
|
1022
|
+
ButtonPressAnimatedWithRef.displayName = 'ButtonPressAnimated';
|
|
927
1023
|
const ButtonAnimatedWithRef = React.forwardRef(ButtonAnimatedImpl);
|
|
928
|
-
ButtonAnimatedWithRef.displayName = '
|
|
1024
|
+
ButtonAnimatedWithRef.displayName = 'ButtonLoadingAnimated';
|
|
929
1025
|
function ButtonImpl(props, ref) {
|
|
930
|
-
|
|
931
|
-
|
|
1026
|
+
const loadingRequested = Boolean(props.loading);
|
|
1027
|
+
const animatedPressRequested = shouldRequestAnimatedPressPath(props);
|
|
1028
|
+
const [retainLoadingAnimated, setRetainLoadingAnimated] = React.useState(loadingRequested);
|
|
1029
|
+
React.useEffect(() => {
|
|
1030
|
+
if (loadingRequested) {
|
|
1031
|
+
setRetainLoadingAnimated(true);
|
|
1032
|
+
return undefined;
|
|
1033
|
+
}
|
|
1034
|
+
if (!retainLoadingAnimated)
|
|
1035
|
+
return undefined;
|
|
1036
|
+
const timer = setTimeout(() => {
|
|
1037
|
+
setRetainLoadingAnimated(false);
|
|
1038
|
+
}, ANIMATED_EXIT_RESIDENCY_MS);
|
|
1039
|
+
return () => {
|
|
1040
|
+
clearTimeout(timer);
|
|
1041
|
+
};
|
|
1042
|
+
}, [loadingRequested, retainLoadingAnimated]);
|
|
1043
|
+
if (loadingRequested || retainLoadingAnimated) {
|
|
1044
|
+
return (0, jsx_runtime_1.jsx)(ButtonAnimatedWithRef, { ...props, ref: ref });
|
|
932
1045
|
}
|
|
933
|
-
return (0, jsx_runtime_1.jsx)(
|
|
1046
|
+
return animatedPressRequested ? ((0, jsx_runtime_1.jsx)(ButtonPressAnimatedWithRef, { ...props, ref: ref })) : ((0, jsx_runtime_1.jsx)(ButtonStaticWithRef, { ...props, ref: ref }));
|
|
934
1047
|
}
|
|
935
1048
|
const ButtonWithRef = React.forwardRef(ButtonImpl);
|
|
936
1049
|
ButtonWithRef.displayName = 'Button';
|
package/package.json
CHANGED
package/src/ui/Button/README.md
CHANGED
|
@@ -154,7 +154,7 @@ export function Demo() {
|
|
|
154
154
|
}
|
|
155
155
|
```
|
|
156
156
|
|
|
157
|
-
渐变依赖 `expo-linear-gradient`,缺失时会使用第一段颜色作为稳定兜底。默认 `pressEffect="auto"` 走普通 `Pressable` 静态路径,并用原生 pressed style 做轻量透明度反馈;只有 `scale`、`scale-opacity`、`highlight`、`scale-highlight` 和 loading 过渡会升级到 Reanimated
|
|
157
|
+
渐变依赖 `expo-linear-gradient`,缺失时会使用第一段颜色作为稳定兜底。默认 `pressEffect="auto"` 走普通 `Pressable` 静态路径,并用原生 pressed style 做轻量透明度反馈;只有 `scale`、`scale-opacity`、`highlight`、`scale-highlight` 和 loading 过渡会升级到 Reanimated 动画路径。动静态切换由 Button 内部自动管理,loading 退出动画结束后才会回到静态路径。
|
|
158
158
|
|
|
159
159
|
## 列表高频渲染
|
|
160
160
|
|
package/src/ui/Button/index.tsx
CHANGED
|
@@ -202,6 +202,7 @@ const LOADING_TIMING = {
|
|
|
202
202
|
easing: Easing.out(Easing.cubic),
|
|
203
203
|
reduceMotion: ReduceMotion.System,
|
|
204
204
|
} as const;
|
|
205
|
+
const ANIMATED_EXIT_RESIDENCY_MS = LOADING_TIMING.duration + 40;
|
|
205
206
|
|
|
206
207
|
const DISABLED_OPACITY = 0.52;
|
|
207
208
|
const PRESSED_OPACITY = 0.82;
|
|
@@ -575,7 +576,7 @@ function resolveVisualColors({
|
|
|
575
576
|
function resolvePressEffect(effect: ButtonPressEffect, interactionDisabled: boolean): ButtonPressEffect {
|
|
576
577
|
if (interactionDisabled) return 'none';
|
|
577
578
|
if (effect !== 'auto') return effect;
|
|
578
|
-
return '
|
|
579
|
+
return 'opacity';
|
|
579
580
|
}
|
|
580
581
|
|
|
581
582
|
function resolvePressEffectFlags(effect: ButtonPressEffect): PressEffectFlags {
|
|
@@ -847,18 +848,15 @@ function requiresAnimatedPressEffect(effect: ButtonPressEffect | undefined) {
|
|
|
847
848
|
);
|
|
848
849
|
}
|
|
849
850
|
|
|
850
|
-
function
|
|
851
|
+
function shouldRequestAnimatedPressPath({
|
|
851
852
|
disabled,
|
|
852
|
-
loading,
|
|
853
853
|
pressEffect,
|
|
854
854
|
}: {
|
|
855
855
|
disabled?: boolean;
|
|
856
|
-
loading?: boolean;
|
|
857
856
|
pressEffect?: ButtonPressEffect;
|
|
858
857
|
}) {
|
|
859
|
-
if (
|
|
860
|
-
|
|
861
|
-
return !requiresAnimatedPressEffect(pressEffect);
|
|
858
|
+
if (disabled) return false;
|
|
859
|
+
return requiresAnimatedPressEffect(pressEffect);
|
|
862
860
|
}
|
|
863
861
|
|
|
864
862
|
function useButtonFrame({
|
|
@@ -1243,6 +1241,235 @@ function ButtonStaticImpl(
|
|
|
1243
1241
|
);
|
|
1244
1242
|
}
|
|
1245
1243
|
|
|
1244
|
+
function ButtonPressAnimatedImpl(
|
|
1245
|
+
{
|
|
1246
|
+
variant = 'solid',
|
|
1247
|
+
tone = 'primary',
|
|
1248
|
+
size = 'md',
|
|
1249
|
+
shape = 'rounded',
|
|
1250
|
+
block = false,
|
|
1251
|
+
disabled = false,
|
|
1252
|
+
loading = false,
|
|
1253
|
+
loadingMode: _loadingMode = 'inline',
|
|
1254
|
+
pressEffect = 'auto',
|
|
1255
|
+
icon,
|
|
1256
|
+
iconPlacement = 'start',
|
|
1257
|
+
iconOnly = false,
|
|
1258
|
+
color,
|
|
1259
|
+
colors,
|
|
1260
|
+
border,
|
|
1261
|
+
layout,
|
|
1262
|
+
gradient,
|
|
1263
|
+
shadow = 'none',
|
|
1264
|
+
children,
|
|
1265
|
+
style,
|
|
1266
|
+
contentStyle,
|
|
1267
|
+
textStyle,
|
|
1268
|
+
accessibilityLabel,
|
|
1269
|
+
accessibilityState,
|
|
1270
|
+
hitSlop,
|
|
1271
|
+
onPress,
|
|
1272
|
+
onPressIn,
|
|
1273
|
+
onPressOut,
|
|
1274
|
+
testID,
|
|
1275
|
+
...pressableProps
|
|
1276
|
+
}: ButtonProps,
|
|
1277
|
+
ref: React.ForwardedRef<ButtonRef>
|
|
1278
|
+
) {
|
|
1279
|
+
const frame = useButtonFrame({
|
|
1280
|
+
accessibilityLabel,
|
|
1281
|
+
block,
|
|
1282
|
+
border,
|
|
1283
|
+
children,
|
|
1284
|
+
color,
|
|
1285
|
+
colors,
|
|
1286
|
+
disabled,
|
|
1287
|
+
gradient,
|
|
1288
|
+
icon,
|
|
1289
|
+
iconOnly,
|
|
1290
|
+
iconPlacement,
|
|
1291
|
+
layout,
|
|
1292
|
+
loading,
|
|
1293
|
+
shadow,
|
|
1294
|
+
shape,
|
|
1295
|
+
size,
|
|
1296
|
+
textStyle,
|
|
1297
|
+
tone,
|
|
1298
|
+
variant,
|
|
1299
|
+
});
|
|
1300
|
+
const {
|
|
1301
|
+
accentColor,
|
|
1302
|
+
borderStyle,
|
|
1303
|
+
contentSizeStyle,
|
|
1304
|
+
defaultHitSlop,
|
|
1305
|
+
gradientCfg,
|
|
1306
|
+
hasGradientBackground,
|
|
1307
|
+
hasIcon,
|
|
1308
|
+
iconBaseBoxStyle,
|
|
1309
|
+
iconPlacedBoxStyle,
|
|
1310
|
+
interactionDisabled,
|
|
1311
|
+
LinearGradientComponent,
|
|
1312
|
+
paddingStyle,
|
|
1313
|
+
radiusStyle,
|
|
1314
|
+
resolvedAccessibilityLabel,
|
|
1315
|
+
resolvedText,
|
|
1316
|
+
rootSizeStyle,
|
|
1317
|
+
shadowStyle,
|
|
1318
|
+
visualColors,
|
|
1319
|
+
visualDisabled,
|
|
1320
|
+
webCursorStyle,
|
|
1321
|
+
} = frame;
|
|
1322
|
+
|
|
1323
|
+
const pressSv = useSharedValue(0);
|
|
1324
|
+
const resolvedPressEffect = React.useMemo(
|
|
1325
|
+
() => resolvePressEffect(pressEffect, interactionDisabled),
|
|
1326
|
+
[interactionDisabled, pressEffect]
|
|
1327
|
+
);
|
|
1328
|
+
const pressEffectFlags = React.useMemo(
|
|
1329
|
+
() => resolvePressEffectFlags(resolvedPressEffect),
|
|
1330
|
+
[resolvedPressEffect]
|
|
1331
|
+
);
|
|
1332
|
+
const pressHighlightEnabled = pressEffectFlags.highlight;
|
|
1333
|
+
const pressOpacityEnabled = pressEffectFlags.opacity;
|
|
1334
|
+
const pressScaleEnabled = pressEffectFlags.scale;
|
|
1335
|
+
const pressOverlay = React.useMemo(
|
|
1336
|
+
() =>
|
|
1337
|
+
resolveOverlay({
|
|
1338
|
+
accentColor,
|
|
1339
|
+
colors,
|
|
1340
|
+
hasGradientBackground,
|
|
1341
|
+
variant,
|
|
1342
|
+
}),
|
|
1343
|
+
[accentColor, colors, hasGradientBackground, variant]
|
|
1344
|
+
);
|
|
1345
|
+
|
|
1346
|
+
React.useEffect(() => {
|
|
1347
|
+
if (interactionDisabled || resolvedPressEffect === 'none') {
|
|
1348
|
+
pressSv.value = 0;
|
|
1349
|
+
}
|
|
1350
|
+
}, [interactionDisabled, pressSv, resolvedPressEffect]);
|
|
1351
|
+
|
|
1352
|
+
const rootAnimatedStyle = useAnimatedStyle(() => {
|
|
1353
|
+
const baseOpacity = visualDisabled ? DISABLED_OPACITY : 1;
|
|
1354
|
+
const scale = pressScaleEnabled
|
|
1355
|
+
? interpolate(pressSv.value, [0, 1], [1, PRESSED_SCALE])
|
|
1356
|
+
: 1;
|
|
1357
|
+
const opacity = pressOpacityEnabled
|
|
1358
|
+
? interpolate(pressSv.value, [0, 1], [baseOpacity, PRESSED_OPACITY])
|
|
1359
|
+
: baseOpacity;
|
|
1360
|
+
|
|
1361
|
+
return {
|
|
1362
|
+
opacity,
|
|
1363
|
+
transform: [{ scale }],
|
|
1364
|
+
};
|
|
1365
|
+
}, [pressOpacityEnabled, pressScaleEnabled, visualDisabled]);
|
|
1366
|
+
|
|
1367
|
+
const overlayAnimatedStyle = useAnimatedStyle(() => {
|
|
1368
|
+
const opacity = pressHighlightEnabled
|
|
1369
|
+
? interpolate(pressSv.value, [0, 1], [0, pressOverlay.strength])
|
|
1370
|
+
: 0;
|
|
1371
|
+
return { opacity };
|
|
1372
|
+
}, [pressHighlightEnabled, pressOverlay.strength]);
|
|
1373
|
+
|
|
1374
|
+
const handlePress = React.useCallback(
|
|
1375
|
+
(event: GestureResponderEvent) => {
|
|
1376
|
+
if (interactionDisabled) return;
|
|
1377
|
+
onPress?.(event);
|
|
1378
|
+
},
|
|
1379
|
+
[interactionDisabled, onPress]
|
|
1380
|
+
);
|
|
1381
|
+
|
|
1382
|
+
const handlePressIn = React.useCallback(
|
|
1383
|
+
(event: GestureResponderEvent) => {
|
|
1384
|
+
if (!interactionDisabled && resolvedPressEffect !== 'none') {
|
|
1385
|
+
pressSv.value = withTiming(1, PRESS_TIMING);
|
|
1386
|
+
}
|
|
1387
|
+
onPressIn?.(event);
|
|
1388
|
+
},
|
|
1389
|
+
[interactionDisabled, onPressIn, pressSv, resolvedPressEffect]
|
|
1390
|
+
);
|
|
1391
|
+
|
|
1392
|
+
const handlePressOut = React.useCallback(
|
|
1393
|
+
(event: GestureResponderEvent) => {
|
|
1394
|
+
if (!interactionDisabled && resolvedPressEffect !== 'none') {
|
|
1395
|
+
pressSv.value = withTiming(0, PRESS_TIMING);
|
|
1396
|
+
}
|
|
1397
|
+
onPressOut?.(event);
|
|
1398
|
+
},
|
|
1399
|
+
[interactionDisabled, onPressOut, pressSv, resolvedPressEffect]
|
|
1400
|
+
);
|
|
1401
|
+
|
|
1402
|
+
return (
|
|
1403
|
+
<AnimatedPressable
|
|
1404
|
+
{...pressableProps}
|
|
1405
|
+
ref={ref}
|
|
1406
|
+
accessibilityLabel={resolvedAccessibilityLabel}
|
|
1407
|
+
accessibilityRole="button"
|
|
1408
|
+
accessibilityState={{
|
|
1409
|
+
...accessibilityState,
|
|
1410
|
+
busy: Boolean(loading || accessibilityState?.busy),
|
|
1411
|
+
disabled: Boolean(interactionDisabled || accessibilityState?.disabled),
|
|
1412
|
+
}}
|
|
1413
|
+
disabled={interactionDisabled}
|
|
1414
|
+
hitSlop={hitSlop ?? defaultHitSlop}
|
|
1415
|
+
onPress={handlePress}
|
|
1416
|
+
onPressIn={handlePressIn}
|
|
1417
|
+
onPressOut={handlePressOut}
|
|
1418
|
+
style={[styles.root, rootSizeStyle, radiusStyle, shadowStyle, rootAnimatedStyle, webCursorStyle, style]}
|
|
1419
|
+
testID={testID}
|
|
1420
|
+
>
|
|
1421
|
+
<View
|
|
1422
|
+
pointerEvents="none"
|
|
1423
|
+
style={[
|
|
1424
|
+
styles.content,
|
|
1425
|
+
contentSizeStyle,
|
|
1426
|
+
paddingStyle,
|
|
1427
|
+
radiusStyle,
|
|
1428
|
+
borderStyle,
|
|
1429
|
+
{ backgroundColor: visualColors.backgroundColor },
|
|
1430
|
+
contentStyle,
|
|
1431
|
+
]}
|
|
1432
|
+
>
|
|
1433
|
+
{LinearGradientComponent && gradientCfg ? (
|
|
1434
|
+
<LinearGradientComponent
|
|
1435
|
+
pointerEvents="none"
|
|
1436
|
+
colors={gradientCfg.colors}
|
|
1437
|
+
start={gradientCfg.start}
|
|
1438
|
+
end={gradientCfg.end}
|
|
1439
|
+
style={[StyleSheet.absoluteFillObject, radiusStyle]}
|
|
1440
|
+
/>
|
|
1441
|
+
) : null}
|
|
1442
|
+
|
|
1443
|
+
{pressHighlightEnabled ? (
|
|
1444
|
+
<Animated.View
|
|
1445
|
+
pointerEvents="none"
|
|
1446
|
+
style={[
|
|
1447
|
+
StyleSheet.absoluteFillObject,
|
|
1448
|
+
radiusStyle,
|
|
1449
|
+
{ backgroundColor: pressOverlay.color },
|
|
1450
|
+
overlayAnimatedStyle,
|
|
1451
|
+
]}
|
|
1452
|
+
/>
|
|
1453
|
+
) : null}
|
|
1454
|
+
|
|
1455
|
+
{iconOnly ? (
|
|
1456
|
+
(icon ?? resolvedText)
|
|
1457
|
+
) : (
|
|
1458
|
+
<>
|
|
1459
|
+
{icon && iconPlacement === 'start' ? (
|
|
1460
|
+
<View style={[iconBaseBoxStyle, iconPlacedBoxStyle]}>{icon}</View>
|
|
1461
|
+
) : null}
|
|
1462
|
+
{resolvedText}
|
|
1463
|
+
{icon && iconPlacement === 'end' ? (
|
|
1464
|
+
<View style={[iconBaseBoxStyle, iconPlacedBoxStyle]}>{icon}</View>
|
|
1465
|
+
) : null}
|
|
1466
|
+
</>
|
|
1467
|
+
)}
|
|
1468
|
+
</View>
|
|
1469
|
+
</AnimatedPressable>
|
|
1470
|
+
);
|
|
1471
|
+
}
|
|
1472
|
+
|
|
1246
1473
|
function ButtonAnimatedImpl(
|
|
1247
1474
|
{
|
|
1248
1475
|
variant = 'solid',
|
|
@@ -1340,7 +1567,7 @@ function ButtonAnimatedImpl(
|
|
|
1340
1567
|
);
|
|
1341
1568
|
|
|
1342
1569
|
const pressSv = useSharedValue(0);
|
|
1343
|
-
const loadingSv = useSharedValue(
|
|
1570
|
+
const loadingSv = useSharedValue(0);
|
|
1344
1571
|
const [spinnerMounted, setSpinnerMounted] = React.useState(loading);
|
|
1345
1572
|
const hideSpinnerTimerRef = React.useRef<ReturnType<typeof setTimeout> | null>(null);
|
|
1346
1573
|
|
|
@@ -1628,15 +1855,43 @@ function ButtonAnimatedImpl(
|
|
|
1628
1855
|
const ButtonStaticWithRef = React.forwardRef<ButtonRef, ButtonProps>(ButtonStaticImpl);
|
|
1629
1856
|
ButtonStaticWithRef.displayName = 'ButtonStatic';
|
|
1630
1857
|
|
|
1858
|
+
const ButtonPressAnimatedWithRef = React.forwardRef<ButtonRef, ButtonProps>(ButtonPressAnimatedImpl);
|
|
1859
|
+
ButtonPressAnimatedWithRef.displayName = 'ButtonPressAnimated';
|
|
1860
|
+
|
|
1631
1861
|
const ButtonAnimatedWithRef = React.forwardRef<ButtonRef, ButtonProps>(ButtonAnimatedImpl);
|
|
1632
|
-
ButtonAnimatedWithRef.displayName = '
|
|
1862
|
+
ButtonAnimatedWithRef.displayName = 'ButtonLoadingAnimated';
|
|
1633
1863
|
|
|
1634
1864
|
function ButtonImpl(props: ButtonProps, ref: React.ForwardedRef<ButtonRef>) {
|
|
1635
|
-
|
|
1636
|
-
|
|
1865
|
+
const loadingRequested = Boolean(props.loading);
|
|
1866
|
+
const animatedPressRequested = shouldRequestAnimatedPressPath(props);
|
|
1867
|
+
const [retainLoadingAnimated, setRetainLoadingAnimated] = React.useState(loadingRequested);
|
|
1868
|
+
|
|
1869
|
+
React.useEffect(() => {
|
|
1870
|
+
if (loadingRequested) {
|
|
1871
|
+
setRetainLoadingAnimated(true);
|
|
1872
|
+
return undefined;
|
|
1873
|
+
}
|
|
1874
|
+
|
|
1875
|
+
if (!retainLoadingAnimated) return undefined;
|
|
1876
|
+
|
|
1877
|
+
const timer = setTimeout(() => {
|
|
1878
|
+
setRetainLoadingAnimated(false);
|
|
1879
|
+
}, ANIMATED_EXIT_RESIDENCY_MS);
|
|
1880
|
+
|
|
1881
|
+
return () => {
|
|
1882
|
+
clearTimeout(timer);
|
|
1883
|
+
};
|
|
1884
|
+
}, [loadingRequested, retainLoadingAnimated]);
|
|
1885
|
+
|
|
1886
|
+
if (loadingRequested || retainLoadingAnimated) {
|
|
1887
|
+
return <ButtonAnimatedWithRef {...props} ref={ref} />;
|
|
1637
1888
|
}
|
|
1638
1889
|
|
|
1639
|
-
return
|
|
1890
|
+
return animatedPressRequested ? (
|
|
1891
|
+
<ButtonPressAnimatedWithRef {...props} ref={ref} />
|
|
1892
|
+
) : (
|
|
1893
|
+
<ButtonStaticWithRef {...props} ref={ref} />
|
|
1894
|
+
);
|
|
1640
1895
|
}
|
|
1641
1896
|
|
|
1642
1897
|
const ButtonWithRef = React.forwardRef<ButtonRef, ButtonProps>(ButtonImpl);
|