@momo-kits/foundation 0.157.1-beta.2 → 0.157.1-beta.5-viewboundary-test
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/Application/Components/HeaderRight.tsx +1 -1
- package/CheckBox/index.tsx +27 -58
- package/CheckBox/types.ts +0 -5
- package/FoundationList/index.tsx +5 -50
- package/FoundationList/types.ts +1 -21
- package/IconButton/index.tsx +1 -28
- package/Radio/index.tsx +28 -37
- package/Radio/types.ts +0 -5
- package/Switch/index.tsx +14 -64
- package/Switch/styles.ts +0 -7
- package/Switch/types.ts +0 -6
- package/ViewBoundary/index.tsx +64 -0
- package/index.ts +1 -1
- package/package.json +1 -1
- package/Animation/index.ts +0 -1
- package/Animation/tokens.ts +0 -117
package/CheckBox/index.tsx
CHANGED
|
@@ -1,11 +1,5 @@
|
|
|
1
|
-
import React, { FC, useContext
|
|
1
|
+
import React, { FC, useContext } from 'react';
|
|
2
2
|
import { TouchableOpacity, View } from 'react-native';
|
|
3
|
-
import Animated, {
|
|
4
|
-
interpolateColor,
|
|
5
|
-
useAnimatedStyle,
|
|
6
|
-
useSharedValue,
|
|
7
|
-
withSpring,
|
|
8
|
-
} from 'react-native-reanimated';
|
|
9
3
|
import { CheckBoxProps } from './types';
|
|
10
4
|
import styles from './styles';
|
|
11
5
|
import { useComponentId } from '../Application';
|
|
@@ -16,7 +10,6 @@ import {
|
|
|
16
10
|
} from '../Context';
|
|
17
11
|
import { Text } from '../Text';
|
|
18
12
|
import { Icon } from '../Icon';
|
|
19
|
-
import { getSpringConfig } from '../Animation';
|
|
20
13
|
|
|
21
14
|
const CheckBox: FC<CheckBoxProps> = ({
|
|
22
15
|
value,
|
|
@@ -26,7 +19,6 @@ const CheckBox: FC<CheckBoxProps> = ({
|
|
|
26
19
|
label,
|
|
27
20
|
indeterminate,
|
|
28
21
|
params,
|
|
29
|
-
animationSpec,
|
|
30
22
|
accessibilityState,
|
|
31
23
|
...props
|
|
32
24
|
}) => {
|
|
@@ -34,6 +26,8 @@ const CheckBox: FC<CheckBoxProps> = ({
|
|
|
34
26
|
const context = useContext<any>(MiniAppContext);
|
|
35
27
|
const haveValue = value || indeterminate;
|
|
36
28
|
const iconSource = indeterminate ? 'ic_minus' : 'ic_checked';
|
|
29
|
+
let borderColor = theme.colors.text.default;
|
|
30
|
+
let backgroundColor = 'transparent';
|
|
37
31
|
const componentName = 'CheckBox';
|
|
38
32
|
const { componentId } = useComponentId(
|
|
39
33
|
`${componentName}${label ? `/${label}` : ''}`,
|
|
@@ -42,47 +36,19 @@ const CheckBox: FC<CheckBoxProps> = ({
|
|
|
42
36
|
|
|
43
37
|
const showBaseLineDebug = context?.features?.showBaseLineDebug ?? false;
|
|
44
38
|
|
|
45
|
-
|
|
46
|
-
|
|
39
|
+
if (haveValue) {
|
|
40
|
+
borderColor = theme.colors.primary;
|
|
41
|
+
backgroundColor = theme.colors.primary;
|
|
42
|
+
}
|
|
47
43
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
[0, 1],
|
|
57
|
-
[theme.colors.border.disable, theme.colors.background.tonal],
|
|
58
|
-
)
|
|
59
|
-
: interpolateColor(
|
|
60
|
-
progress.value,
|
|
61
|
-
[0, 1],
|
|
62
|
-
[theme.colors.text.default, theme.colors.primary],
|
|
63
|
-
);
|
|
64
|
-
const backgroundColor = disabled
|
|
65
|
-
? interpolateColor(
|
|
66
|
-
progress.value,
|
|
67
|
-
[0, 1],
|
|
68
|
-
['transparent', theme.colors.background.tonal],
|
|
69
|
-
)
|
|
70
|
-
: interpolateColor(
|
|
71
|
-
progress.value,
|
|
72
|
-
[0, 1],
|
|
73
|
-
['transparent', theme.colors.primary],
|
|
74
|
-
);
|
|
75
|
-
return {
|
|
76
|
-
borderColor,
|
|
77
|
-
backgroundColor,
|
|
78
|
-
borderWidth: 1,
|
|
79
|
-
};
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
const iconAnimatedStyle = useAnimatedStyle(() => ({
|
|
83
|
-
opacity: progress.value,
|
|
84
|
-
transform: [{ scale: progress.value }],
|
|
85
|
-
}));
|
|
44
|
+
if (disabled) {
|
|
45
|
+
borderColor = theme.colors.border.disable;
|
|
46
|
+
backgroundColor = 'transparent';
|
|
47
|
+
if (haveValue) {
|
|
48
|
+
borderColor = theme.colors.background.tonal;
|
|
49
|
+
backgroundColor = theme.colors.background.tonal;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
86
52
|
|
|
87
53
|
return (
|
|
88
54
|
<ComponentContext.Provider
|
|
@@ -111,17 +77,20 @@ const CheckBox: FC<CheckBoxProps> = ({
|
|
|
111
77
|
showBaseLineDebug && styles.debugBaseLine,
|
|
112
78
|
]}
|
|
113
79
|
>
|
|
114
|
-
<
|
|
80
|
+
<View
|
|
81
|
+
style={[
|
|
82
|
+
{ borderColor, backgroundColor, borderWidth: 1 },
|
|
83
|
+
styles.checkbox,
|
|
84
|
+
]}
|
|
85
|
+
>
|
|
115
86
|
{haveValue && (
|
|
116
|
-
<
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
/>
|
|
122
|
-
</Animated.View>
|
|
87
|
+
<Icon
|
|
88
|
+
color={theme.colors.background.surface}
|
|
89
|
+
size={20}
|
|
90
|
+
source={iconSource}
|
|
91
|
+
/>
|
|
123
92
|
)}
|
|
124
|
-
</
|
|
93
|
+
</View>
|
|
125
94
|
{!!label && (
|
|
126
95
|
<Text typography={'body_default_regular'} style={styles.label}>
|
|
127
96
|
{label}
|
package/CheckBox/types.ts
CHANGED
package/FoundationList/index.tsx
CHANGED
|
@@ -1,57 +1,12 @@
|
|
|
1
|
-
import React
|
|
1
|
+
import React from 'react';
|
|
2
2
|
import { FlashList, FlashListProps } from '@shopify/flash-list';
|
|
3
|
-
import Animated from 'react-native-reanimated';
|
|
4
3
|
import { FlatListProps } from 'react-native';
|
|
5
|
-
import type { FoundationListProps, FoundationListRef } from './types';
|
|
6
4
|
|
|
7
|
-
type CombinedListProps<ItemT> =
|
|
8
|
-
|
|
9
|
-
Partial<FlashListProps<ItemT>> & {
|
|
10
|
-
renderItem?: FlashListProps<ItemT>['renderItem'];
|
|
11
|
-
};
|
|
5
|
+
type CombinedListProps<ItemT> = FlatListProps<ItemT> &
|
|
6
|
+
Partial<FlashListProps<ItemT>>;
|
|
12
7
|
|
|
13
|
-
const
|
|
14
|
-
props
|
|
15
|
-
ref: React.Ref<FoundationListRef>
|
|
16
|
-
) => {
|
|
17
|
-
const { animationConfig, renderItem: renderItemProp, ...rest } = props;
|
|
18
|
-
|
|
19
|
-
const renderItem = useCallback(
|
|
20
|
-
(args: Parameters<NonNullable<typeof renderItemProp>>[0]) => {
|
|
21
|
-
const content = renderItemProp?.(args);
|
|
22
|
-
if (!content) return null;
|
|
23
|
-
|
|
24
|
-
if (!animationConfig?.entering && !animationConfig?.exiting) {
|
|
25
|
-
return content;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
const entering =
|
|
29
|
-
typeof animationConfig.entering === 'function'
|
|
30
|
-
? animationConfig.entering(args.index)
|
|
31
|
-
: animationConfig.entering;
|
|
32
|
-
|
|
33
|
-
return (
|
|
34
|
-
<Animated.View
|
|
35
|
-
entering={entering as any}
|
|
36
|
-
exiting={animationConfig.exiting as any}
|
|
37
|
-
>
|
|
38
|
-
{content}
|
|
39
|
-
</Animated.View>
|
|
40
|
-
);
|
|
41
|
-
},
|
|
42
|
-
[renderItemProp, animationConfig]
|
|
43
|
-
);
|
|
44
|
-
|
|
45
|
-
const finalRenderItem =
|
|
46
|
-
animationConfig && renderItemProp ? renderItem : renderItemProp;
|
|
47
|
-
|
|
48
|
-
return (
|
|
49
|
-
<FlashList ref={ref} {...rest} renderItem={finalRenderItem} />
|
|
50
|
-
);
|
|
8
|
+
const FoundationList = <ItemT,>(props: CombinedListProps<ItemT>) => {
|
|
9
|
+
return <FlashList {...props} />;
|
|
51
10
|
};
|
|
52
11
|
|
|
53
|
-
const FoundationList = forwardRef(FoundationListInner) as <ItemT>(
|
|
54
|
-
props: CombinedListProps<ItemT> & { ref?: React.Ref<FoundationListRef> }
|
|
55
|
-
) => React.ReactElement;
|
|
56
|
-
|
|
57
12
|
export { FoundationList };
|
package/FoundationList/types.ts
CHANGED
|
@@ -1,26 +1,6 @@
|
|
|
1
1
|
import { FlashListProps, FlashListRef } from '@shopify/flash-list';
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
* Animation builder for list item enter/exit.
|
|
5
|
-
* Use Reanimated's FadeInUp, FadeIn, FadeOut, etc.
|
|
6
|
-
*/
|
|
7
|
-
export type ListItemAnimationBuilder =
|
|
8
|
-
| { duration: (ms: number) => any; delay: (ms: number) => any }
|
|
9
|
-
| ((index: number) => any);
|
|
10
|
-
|
|
11
|
-
interface FoundationListProps extends FlashListProps<any> {
|
|
12
|
-
/**
|
|
13
|
-
* Optional. Animation config for list items.
|
|
14
|
-
* - entering: Animation when item appears (e.g. FadeInUp.duration(300).delay(index * 40))
|
|
15
|
-
* - exiting: Animation when item is removed
|
|
16
|
-
* Note: Call listRef.current?.prepareForLayoutAnimationRender() before inserting/removing items.
|
|
17
|
-
* Layout transitions (reorder) are not supported by FlashList.
|
|
18
|
-
*/
|
|
19
|
-
animationConfig?: {
|
|
20
|
-
entering?: ListItemAnimationBuilder;
|
|
21
|
-
exiting?: ListItemAnimationBuilder;
|
|
22
|
-
};
|
|
23
|
-
}
|
|
3
|
+
interface FoundationListProps extends FlashListProps<any> {}
|
|
24
4
|
|
|
25
5
|
interface FoundationListRef extends FlashListRef<any> {}
|
|
26
6
|
|
package/IconButton/index.tsx
CHANGED
|
@@ -1,15 +1,9 @@
|
|
|
1
1
|
import React, { useContext } from 'react';
|
|
2
2
|
import {
|
|
3
|
-
GestureResponderEvent,
|
|
4
3
|
StyleSheet,
|
|
5
4
|
TouchableOpacity,
|
|
6
5
|
TouchableOpacityProps,
|
|
7
6
|
} from 'react-native';
|
|
8
|
-
import Animated, {
|
|
9
|
-
useAnimatedStyle,
|
|
10
|
-
useSharedValue,
|
|
11
|
-
withTiming,
|
|
12
|
-
} from 'react-native-reanimated';
|
|
13
7
|
import {
|
|
14
8
|
ApplicationContext,
|
|
15
9
|
ComponentContext,
|
|
@@ -47,30 +41,13 @@ const IconButton: React.FC<IconButtonProps> = ({
|
|
|
47
41
|
icon,
|
|
48
42
|
size,
|
|
49
43
|
params,
|
|
50
|
-
onPressIn,
|
|
51
|
-
onPressOut,
|
|
52
44
|
...rest
|
|
53
45
|
}) => {
|
|
54
46
|
const { theme } = useContext(ApplicationContext);
|
|
55
47
|
const context = useContext<any>(MiniAppContext);
|
|
56
|
-
const pressAnim = useSharedValue(0);
|
|
57
48
|
|
|
58
49
|
const showBaseLineDebug = context?.features?.showBaseLineDebug ?? false;
|
|
59
50
|
|
|
60
|
-
const handlePressIn = (e: GestureResponderEvent) => {
|
|
61
|
-
onPressIn?.(e);
|
|
62
|
-
pressAnim.value = withTiming(1, { duration: 100 });
|
|
63
|
-
};
|
|
64
|
-
|
|
65
|
-
const handlePressOut = (e: GestureResponderEvent) => {
|
|
66
|
-
onPressOut?.(e);
|
|
67
|
-
pressAnim.value = withTiming(0, { duration: 100 });
|
|
68
|
-
};
|
|
69
|
-
|
|
70
|
-
const animatedStyle = useAnimatedStyle(() => ({
|
|
71
|
-
transform: [{ scale: 1 - pressAnim.value * 0.1 }],
|
|
72
|
-
}));
|
|
73
|
-
|
|
74
51
|
/**
|
|
75
52
|
* get size icon button
|
|
76
53
|
*/
|
|
@@ -156,13 +133,9 @@ const IconButton: React.FC<IconButtonProps> = ({
|
|
|
156
133
|
{...rest}
|
|
157
134
|
disabled={type === 'disabled'}
|
|
158
135
|
activeOpacity={activeOpacity}
|
|
159
|
-
onPressIn={handlePressIn}
|
|
160
|
-
onPressOut={handlePressOut}
|
|
161
136
|
style={[buttonStyle, showBaseLineDebug && styles.debugBaseLine]}
|
|
162
137
|
>
|
|
163
|
-
<
|
|
164
|
-
<Icon size={iconSize} source={icon} color={getIconColor()} />
|
|
165
|
-
</Animated.View>
|
|
138
|
+
<Icon size={iconSize} source={icon} color={getIconColor()} />
|
|
166
139
|
</TouchableOpacity>
|
|
167
140
|
</ComponentContext.Provider>
|
|
168
141
|
);
|
package/Radio/index.tsx
CHANGED
|
@@ -1,12 +1,6 @@
|
|
|
1
|
-
import React, { FC, useContext
|
|
2
|
-
import { TouchableOpacity } from 'react-native';
|
|
3
|
-
|
|
4
|
-
interpolate,
|
|
5
|
-
interpolateColor,
|
|
6
|
-
useAnimatedStyle,
|
|
7
|
-
useSharedValue,
|
|
8
|
-
withSpring,
|
|
9
|
-
} from 'react-native-reanimated';
|
|
1
|
+
import React, { FC, useContext } from 'react';
|
|
2
|
+
import { TouchableOpacity, View } from 'react-native';
|
|
3
|
+
|
|
10
4
|
import { RadioProps } from './types';
|
|
11
5
|
import { Text } from '../Text';
|
|
12
6
|
import styles from './styles';
|
|
@@ -17,7 +11,6 @@ import {
|
|
|
17
11
|
MiniAppContext,
|
|
18
12
|
} from '../Context';
|
|
19
13
|
import { Spacing } from '../Consts';
|
|
20
|
-
import { getSpringConfig } from '../Animation';
|
|
21
14
|
|
|
22
15
|
const Radio: FC<RadioProps> = ({
|
|
23
16
|
value,
|
|
@@ -27,7 +20,6 @@ const Radio: FC<RadioProps> = ({
|
|
|
27
20
|
label,
|
|
28
21
|
style,
|
|
29
22
|
params,
|
|
30
|
-
animationSpec,
|
|
31
23
|
accessibilityState,
|
|
32
24
|
accessibilityLabel,
|
|
33
25
|
...props
|
|
@@ -42,33 +34,25 @@ const Radio: FC<RadioProps> = ({
|
|
|
42
34
|
);
|
|
43
35
|
|
|
44
36
|
const showBaseLineDebug = context?.features?.showBaseLineDebug ?? false;
|
|
37
|
+
let disabledStyle = {};
|
|
38
|
+
let checkBoxStyle = {
|
|
39
|
+
borderWidth: 2,
|
|
40
|
+
borderColor: theme.colors.text.default,
|
|
41
|
+
};
|
|
45
42
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
progress.value,
|
|
58
|
-
[0, 1],
|
|
59
|
-
[theme.colors.text.disable, theme.colors.background.tonal],
|
|
60
|
-
)
|
|
61
|
-
: interpolateColor(
|
|
62
|
-
progress.value,
|
|
63
|
-
[0, 1],
|
|
64
|
-
[theme.colors.text.default, theme.colors.primary],
|
|
65
|
-
);
|
|
66
|
-
return {
|
|
67
|
-
borderWidth,
|
|
68
|
-
borderColor,
|
|
69
|
-
marginRight: label ? Spacing.S : 0,
|
|
43
|
+
if (selected) {
|
|
44
|
+
checkBoxStyle = {
|
|
45
|
+
borderWidth: 6,
|
|
46
|
+
borderColor: theme.colors.primary,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
if (disabled) {
|
|
50
|
+
disabledStyle = {
|
|
51
|
+
borderColor: selected
|
|
52
|
+
? theme.colors.background.tonal
|
|
53
|
+
: theme.colors.text.disable,
|
|
70
54
|
};
|
|
71
|
-
}
|
|
55
|
+
}
|
|
72
56
|
|
|
73
57
|
return (
|
|
74
58
|
<ComponentContext.Provider
|
|
@@ -99,7 +83,14 @@ const Radio: FC<RadioProps> = ({
|
|
|
99
83
|
}}
|
|
100
84
|
accessibilityLabel={componentId}
|
|
101
85
|
>
|
|
102
|
-
<
|
|
86
|
+
<View
|
|
87
|
+
style={[
|
|
88
|
+
styles.radio,
|
|
89
|
+
checkBoxStyle,
|
|
90
|
+
disabledStyle,
|
|
91
|
+
{ marginRight: label ? Spacing.S : 0 },
|
|
92
|
+
]}
|
|
93
|
+
/>
|
|
103
94
|
{!!label && (
|
|
104
95
|
<Text
|
|
105
96
|
typography={'body_default_regular'}
|
package/Radio/types.ts
CHANGED
|
@@ -28,9 +28,4 @@ export interface RadioProps extends TouchableOpacityProps {
|
|
|
28
28
|
* Optional. Params auto tracking component.
|
|
29
29
|
*/
|
|
30
30
|
params?: any;
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Optional. Spring config for selection animation.
|
|
34
|
-
*/
|
|
35
|
-
animationSpec?: import('../Animation').SpringConfig;
|
|
36
31
|
}
|
package/Switch/index.tsx
CHANGED
|
@@ -1,22 +1,10 @@
|
|
|
1
|
-
import React, { FC, useContext
|
|
1
|
+
import React, { FC, useContext } from 'react';
|
|
2
2
|
import { TouchableOpacity, View } from 'react-native';
|
|
3
|
-
import Animated, {
|
|
4
|
-
interpolateColor,
|
|
5
|
-
useAnimatedStyle,
|
|
6
|
-
useSharedValue,
|
|
7
|
-
withSpring,
|
|
8
|
-
} from 'react-native-reanimated';
|
|
9
3
|
import { SwitchProps } from './types';
|
|
10
4
|
import styles from './styles';
|
|
11
5
|
import { Colors } from '../Consts';
|
|
12
6
|
import { useComponentId } from '../Application';
|
|
13
|
-
import {
|
|
14
|
-
ComponentContext,
|
|
15
|
-
MiniAppContext,
|
|
16
|
-
} from '../Context';
|
|
17
|
-
import { getSpringConfig } from '../Animation';
|
|
18
|
-
|
|
19
|
-
const THUMB_OFFSET = 16;
|
|
7
|
+
import { ComponentContext, MiniAppContext } from '../Context';
|
|
20
8
|
|
|
21
9
|
const Switch: FC<SwitchProps> = ({
|
|
22
10
|
value = false,
|
|
@@ -24,52 +12,22 @@ const Switch: FC<SwitchProps> = ({
|
|
|
24
12
|
disabled = false,
|
|
25
13
|
style,
|
|
26
14
|
params,
|
|
27
|
-
animationSpec,
|
|
28
15
|
accessibilityLabel,
|
|
29
16
|
...props
|
|
30
17
|
}) => {
|
|
31
18
|
const context = useContext<any>(MiniAppContext);
|
|
19
|
+
const circleBackgroundColor = value ? Colors.black_01 : Colors.black_03;
|
|
20
|
+
const circleAlign = value ? 'flex-end' : 'flex-start';
|
|
32
21
|
const componentName = 'Switch';
|
|
33
22
|
|
|
34
23
|
const { componentId } = useComponentId(componentName, accessibilityLabel);
|
|
35
24
|
|
|
36
25
|
const showBaseLineDebug = context?.features?.showBaseLineDebug ?? false;
|
|
37
26
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
useEffect(() => {
|
|
43
|
-
progress.value = withSpring(value ? 1 : 0, springConfig);
|
|
44
|
-
}, [value, springConfig.stiffness, springConfig.damping]);
|
|
45
|
-
|
|
46
|
-
const trackAnimatedStyle = useAnimatedStyle(() => {
|
|
47
|
-
const trackColor = disabled
|
|
48
|
-
? interpolateColor(
|
|
49
|
-
progress.value,
|
|
50
|
-
[0, 1],
|
|
51
|
-
[Colors.black_05, Colors.green_09]
|
|
52
|
-
)
|
|
53
|
-
: interpolateColor(
|
|
54
|
-
progress.value,
|
|
55
|
-
[0, 1],
|
|
56
|
-
[Colors.black_07, Colors.green_03]
|
|
57
|
-
);
|
|
58
|
-
return { backgroundColor: trackColor };
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
const thumbAnimatedStyle = useAnimatedStyle(() => ({
|
|
62
|
-
transform: [{ translateX: progress.value * THUMB_OFFSET }],
|
|
63
|
-
}));
|
|
64
|
-
|
|
65
|
-
const circleBgColor = value ? Colors.black_01 : Colors.black_03;
|
|
66
|
-
const innerDotColor = disabled
|
|
67
|
-
? value
|
|
68
|
-
? Colors.green_09
|
|
69
|
-
: Colors.black_05
|
|
70
|
-
: value
|
|
71
|
-
? Colors.green_03
|
|
72
|
-
: Colors.black_07;
|
|
27
|
+
let backgroundColor = value ? Colors.green_03 : Colors.black_07;
|
|
28
|
+
if (disabled) {
|
|
29
|
+
backgroundColor = value ? Colors.green_09 : Colors.black_05;
|
|
30
|
+
}
|
|
73
31
|
|
|
74
32
|
return (
|
|
75
33
|
<ComponentContext.Provider
|
|
@@ -93,23 +51,15 @@ const Switch: FC<SwitchProps> = ({
|
|
|
93
51
|
style={[
|
|
94
52
|
style,
|
|
95
53
|
styles.container,
|
|
96
|
-
|
|
54
|
+
{ backgroundColor, alignItems: circleAlign },
|
|
97
55
|
showBaseLineDebug && styles.debugBaseLine,
|
|
98
56
|
]}
|
|
99
57
|
>
|
|
100
|
-
<
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
thumbAnimatedStyle,
|
|
106
|
-
]}
|
|
107
|
-
>
|
|
108
|
-
<View
|
|
109
|
-
style={[styles.circleSmall, { backgroundColor: innerDotColor }]}
|
|
110
|
-
/>
|
|
111
|
-
</Animated.View>
|
|
112
|
-
</Animated.View>
|
|
58
|
+
<View
|
|
59
|
+
style={[styles.circle, { backgroundColor: circleBackgroundColor }]}
|
|
60
|
+
>
|
|
61
|
+
<View style={[styles.circleSmall, { backgroundColor }]} />
|
|
62
|
+
</View>
|
|
113
63
|
</TouchableOpacity>
|
|
114
64
|
</ComponentContext.Provider>
|
|
115
65
|
);
|
package/Switch/styles.ts
CHANGED
|
@@ -8,13 +8,6 @@ export default StyleSheet.create({
|
|
|
8
8
|
borderRadius: 20,
|
|
9
9
|
justifyContent: 'center',
|
|
10
10
|
paddingHorizontal: 4,
|
|
11
|
-
// overflow: 'hidden',
|
|
12
|
-
},
|
|
13
|
-
track: {
|
|
14
|
-
width: 30,
|
|
15
|
-
height: 24,
|
|
16
|
-
borderRadius: 12,
|
|
17
|
-
justifyContent: 'center',
|
|
18
11
|
},
|
|
19
12
|
circle: {
|
|
20
13
|
width: 14,
|
package/Switch/types.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import {TouchableOpacityProps} from 'react-native';
|
|
2
|
-
import type {SpringConfig} from '../Animation';
|
|
3
2
|
|
|
4
3
|
export interface SwitchProps extends TouchableOpacityProps {
|
|
5
4
|
/**
|
|
@@ -17,9 +16,4 @@ export interface SwitchProps extends TouchableOpacityProps {
|
|
|
17
16
|
* Optional. Params auto tracking component.
|
|
18
17
|
*/
|
|
19
18
|
params?: any;
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Optional. Spring config for thumb/track animation. Uses default tokens when not provided.
|
|
23
|
-
*/
|
|
24
|
-
animationSpec?: SpringConfig;
|
|
25
19
|
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { NativeModules, ViewStyle, StyleProp } from 'react-native';
|
|
3
|
+
import { MiniAppContext } from '../Context';
|
|
4
|
+
|
|
5
|
+
export interface ViewBoundaryProps {
|
|
6
|
+
children: React.ReactNode;
|
|
7
|
+
fallback?: React.ReactNode;
|
|
8
|
+
fallbackStyle?: StyleProp<ViewStyle>;
|
|
9
|
+
onError?: (error: Error, errorInfo: React.ErrorInfo) => void;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
interface ViewBoundaryState {
|
|
13
|
+
hasError: boolean;
|
|
14
|
+
error: Error | null;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
class ViewBoundary extends React.Component<ViewBoundaryProps, ViewBoundaryState> {
|
|
18
|
+
static contextType = MiniAppContext;
|
|
19
|
+
|
|
20
|
+
constructor(props: ViewBoundaryProps) {
|
|
21
|
+
super(props);
|
|
22
|
+
this.state = { hasError: false, error: null };
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
static getDerivedStateFromError(error: Error): ViewBoundaryState {
|
|
26
|
+
return { hasError: true, error };
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {
|
|
30
|
+
this.props.onError?.(error, errorInfo);
|
|
31
|
+
|
|
32
|
+
const context = (this as any).context ?? {};
|
|
33
|
+
|
|
34
|
+
try {
|
|
35
|
+
NativeModules.MiniAppModule?.onJSWidgetCrash({
|
|
36
|
+
hostId: context.hostId ?? '',
|
|
37
|
+
appId: context.appId ?? '',
|
|
38
|
+
code: context.code ?? '',
|
|
39
|
+
buildNumber: context.buildNumber ?? '',
|
|
40
|
+
tag: 'ViewBoundary',
|
|
41
|
+
error: {
|
|
42
|
+
errorName: error.name,
|
|
43
|
+
errorMessage: error.message,
|
|
44
|
+
componentStack: errorInfo?.componentStack?.substring(0, 500) ?? '',
|
|
45
|
+
},
|
|
46
|
+
});
|
|
47
|
+
console.info('[ViewBoundary] onJSWidgetCrash success!');
|
|
48
|
+
} catch (_e) {
|
|
49
|
+
console.warn('[ViewBoundary] onJSWidgetCrash failed:', _e);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
render() {
|
|
54
|
+
if (this.state.hasError) {
|
|
55
|
+
if (this.props.fallback !== undefined) {
|
|
56
|
+
return this.props.fallback;
|
|
57
|
+
}
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
return this.props.children;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export { ViewBoundary };
|
package/index.ts
CHANGED
|
@@ -43,9 +43,9 @@ export * from './Loader';
|
|
|
43
43
|
export * from './Loader/types';
|
|
44
44
|
export * from './Title';
|
|
45
45
|
export * from './Title/types';
|
|
46
|
-
export * from './Animation';
|
|
47
46
|
export * from './Badge';
|
|
48
47
|
export * from './Badge/types';
|
|
49
48
|
export * from './FoundationList';
|
|
50
49
|
export * from './FoundationList/types';
|
|
50
|
+
export * from './ViewBoundary';
|
|
51
51
|
export { TouchableOpacity };
|
package/package.json
CHANGED
package/Animation/index.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from './tokens';
|
package/Animation/tokens.ts
DELETED
|
@@ -1,117 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Animation tokens inspired by M3 Material Motion and Motion.dev
|
|
3
|
-
* Spring/timing configs for consistent animation across components
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
export type SpringConfig = {
|
|
7
|
-
stiffness: number;
|
|
8
|
-
damping: number;
|
|
9
|
-
mass?: number;
|
|
10
|
-
};
|
|
11
|
-
|
|
12
|
-
export type TimingConfig = {
|
|
13
|
-
duration: number;
|
|
14
|
-
easing?: 'ease' | 'easeIn' | 'easeOut' | 'easeInOut' | 'linear';
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
export type MotionScheme = 'expressive' | 'standard';
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* M3 Expressive - overshoots final values, adds bounce
|
|
21
|
-
* Use for hero moments and key interactions
|
|
22
|
-
*/
|
|
23
|
-
export const EXPRESSIVE_FAST: SpringConfig = {
|
|
24
|
-
stiffness: 400,
|
|
25
|
-
damping: 15,
|
|
26
|
-
mass: 1,
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
export const EXPRESSIVE_DEFAULT: SpringConfig = {
|
|
30
|
-
stiffness: 300,
|
|
31
|
-
damping: 20,
|
|
32
|
-
mass: 1,
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
export const EXPRESSIVE_SLOW: SpringConfig = {
|
|
36
|
-
stiffness: 200,
|
|
37
|
-
damping: 25,
|
|
38
|
-
mass: 1,
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* M3 Standard - minimal bounce, utilitarian
|
|
43
|
-
* Use for utilitarian products
|
|
44
|
-
*/
|
|
45
|
-
export const STANDARD_FAST: SpringConfig = {
|
|
46
|
-
stiffness: 500,
|
|
47
|
-
damping: 30,
|
|
48
|
-
mass: 1,
|
|
49
|
-
};
|
|
50
|
-
|
|
51
|
-
export const STANDARD_DEFAULT: SpringConfig = {
|
|
52
|
-
stiffness: 400,
|
|
53
|
-
damping: 35,
|
|
54
|
-
mass: 1,
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
export const STANDARD_SLOW: SpringConfig = {
|
|
58
|
-
stiffness: 300,
|
|
59
|
-
damping: 40,
|
|
60
|
-
mass: 1,
|
|
61
|
-
};
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* Timing config for opacity, color (effects)
|
|
65
|
-
* No overshoot for effects
|
|
66
|
-
*/
|
|
67
|
-
export const TIMING_FAST: TimingConfig = {
|
|
68
|
-
duration: 150,
|
|
69
|
-
easing: 'easeOut',
|
|
70
|
-
};
|
|
71
|
-
|
|
72
|
-
export const TIMING_DEFAULT: TimingConfig = {
|
|
73
|
-
duration: 250,
|
|
74
|
-
easing: 'easeInOut',
|
|
75
|
-
};
|
|
76
|
-
|
|
77
|
-
export const TIMING_SLOW: TimingConfig = {
|
|
78
|
-
duration: 400,
|
|
79
|
-
easing: 'easeInOut',
|
|
80
|
-
};
|
|
81
|
-
|
|
82
|
-
/**
|
|
83
|
-
* Get spring config by scheme and speed
|
|
84
|
-
*/
|
|
85
|
-
export function getSpringConfig(
|
|
86
|
-
scheme: MotionScheme = 'expressive',
|
|
87
|
-
speed: 'fast' | 'default' | 'slow' = 'fast'
|
|
88
|
-
): SpringConfig {
|
|
89
|
-
if (scheme === 'expressive') {
|
|
90
|
-
switch (speed) {
|
|
91
|
-
case 'fast':
|
|
92
|
-
return { ...EXPRESSIVE_FAST };
|
|
93
|
-
case 'slow':
|
|
94
|
-
return { ...EXPRESSIVE_SLOW };
|
|
95
|
-
default:
|
|
96
|
-
return { ...EXPRESSIVE_DEFAULT };
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
switch (speed) {
|
|
100
|
-
case 'fast':
|
|
101
|
-
return { ...STANDARD_FAST };
|
|
102
|
-
case 'slow':
|
|
103
|
-
return { ...STANDARD_SLOW };
|
|
104
|
-
default:
|
|
105
|
-
return { ...STANDARD_DEFAULT };
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
/**
|
|
110
|
-
* Create custom spring config with overrides
|
|
111
|
-
*/
|
|
112
|
-
export function createSpringConfig(
|
|
113
|
-
base: SpringConfig,
|
|
114
|
-
overrides?: Partial<SpringConfig>
|
|
115
|
-
): SpringConfig {
|
|
116
|
-
return { ...base, ...overrides };
|
|
117
|
-
}
|