@momo-kits/foundation 0.169.1 → 0.169.2

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.
Files changed (38) hide show
  1. package/Application/BottomSheet.hooks.ts +17 -37
  2. package/Application/BottomSheet.parts.tsx +81 -165
  3. package/Application/BottomSheet.styles.ts +7 -23
  4. package/Application/BottomSheet.tsx +15 -67
  5. package/Application/BottomTab/ActiveIndicator.tsx +90 -0
  6. package/Application/BottomTab/BottomTabBar.styles.ts +48 -43
  7. package/Application/BottomTab/BottomTabBar.tsx +229 -223
  8. package/Application/BottomTab/BottomTabInset.tsx +14 -0
  9. package/Application/BottomTab/CurvedContainer.tsx +153 -0
  10. package/Application/BottomTab/CustomBottomTabItem.tsx +132 -108
  11. package/Application/BottomTab/DuoBarCompression.tsx +4 -12
  12. package/Application/BottomTab/DuoRailTabBar.tsx +174 -96
  13. package/Application/BottomTab/DuoTabBar.styles.ts +42 -84
  14. package/Application/BottomTab/DuoTabBar.tsx +35 -115
  15. package/Application/BottomTab/TabBarIcon.tsx +160 -72
  16. package/Application/BottomTab/TabScreen.tsx +48 -61
  17. package/Application/BottomTab/index.tsx +85 -125
  18. package/Application/BottomTab/metrics.ts +164 -0
  19. package/Application/BottomTab/tabItems.ts +46 -0
  20. package/Application/BottomTab/usePressLift.ts +32 -0
  21. package/Application/ModalIconButton.tsx +66 -0
  22. package/Application/ModalScreen.tsx +32 -15
  23. package/Application/__tests__/modalLayout.test.ts +128 -0
  24. package/Application/index.ts +10 -0
  25. package/Application/modalLayout.ts +177 -0
  26. package/Application/types.tabs.ts +5 -0
  27. package/Application/utils.ts +0 -36
  28. package/Layout/ReservedRegions.tsx +21 -4
  29. package/Layout/Screen.tsx +11 -2
  30. package/Layout/index.ts +2 -0
  31. package/Popup/PopupNotify.tsx +38 -68
  32. package/Popup/PopupPromotion.tsx +5 -4
  33. package/Popup/utils.ts +1 -26
  34. package/package.json +2 -1
  35. package/Application/BottomTab/DuoTabBar.parts.tsx +0 -202
  36. package/Application/BottomTab/badge.ts +0 -41
  37. package/Application/BottomTab/hooks.ts +0 -358
  38. package/Application/BottomTab/index.styles.ts +0 -30
@@ -0,0 +1,90 @@
1
+ import React, { useContext, useEffect, useRef } from 'react';
2
+ import { StyleProp, StyleSheet, ViewStyle } from 'react-native';
3
+ import Animated, {
4
+ useAnimatedStyle,
5
+ useSharedValue,
6
+ withTiming,
7
+ } from 'react-native-reanimated';
8
+ import { ApplicationContext } from '../../Context';
9
+ import { getIndicatorShadow, TabBarMotion } from './metrics';
10
+
11
+ type Props = {
12
+ axis: 'x' | 'y';
13
+ // position of the selected item along the axis, undefined until it is measured
14
+ offset?: number;
15
+ // horizontal bar: width of the selected item
16
+ extent?: number;
17
+ radius: number;
18
+ style: StyleProp<ViewStyle>;
19
+ };
20
+
21
+ /**
22
+ * one active indicator per bar (Background/tonal with its inner shadows) sliding to the
23
+ * selected item; it lands in place on the first measure and slides from then on
24
+ */
25
+ const ActiveIndicator: React.FC<Props> = ({
26
+ axis,
27
+ offset,
28
+ extent,
29
+ radius,
30
+ style,
31
+ }) => {
32
+ const { theme } = useContext(ApplicationContext);
33
+ const position = useSharedValue(offset ?? 0);
34
+ const size = useSharedValue(extent ?? 0);
35
+ const visible = useSharedValue(offset === undefined ? 0 : 1);
36
+ const placed = useRef(offset !== undefined);
37
+
38
+ useEffect(() => {
39
+ if (offset === undefined) {
40
+ return;
41
+ }
42
+ size.value = extent ?? 0;
43
+ if (!placed.current) {
44
+ placed.current = true;
45
+ position.value = offset;
46
+ visible.value = 1;
47
+ return;
48
+ }
49
+ position.value = withTiming(offset, TabBarMotion.indicator);
50
+ }, [offset, extent, position, size, visible]);
51
+
52
+ const animatedStyle = useAnimatedStyle(() =>
53
+ axis === 'x'
54
+ ? {
55
+ opacity: visible.value,
56
+ width: size.value,
57
+ transform: [{ translateX: position.value }],
58
+ }
59
+ : {
60
+ opacity: visible.value,
61
+ transform: [{ translateY: position.value }],
62
+ },
63
+ );
64
+
65
+ return (
66
+ <Animated.View
67
+ pointerEvents={'none'}
68
+ style={[
69
+ styles.indicator,
70
+ {
71
+ borderRadius: radius,
72
+ backgroundColor: theme.colors.background.tonal,
73
+ boxShadow: getIndicatorShadow(theme.colors.primary),
74
+ },
75
+ style,
76
+ animatedStyle,
77
+ ]}
78
+ />
79
+ );
80
+ };
81
+
82
+ const styles = StyleSheet.create({
83
+ indicator: {
84
+ position: 'absolute',
85
+ left: 0,
86
+ top: 0,
87
+ },
88
+ });
89
+
90
+ export { ActiveIndicator };
@@ -1,60 +1,65 @@
1
- import { Platform, StyleSheet } from 'react-native';
2
- import { Colors, Radius } from '../../Consts';
1
+ import { StyleSheet } from 'react-native';
2
+ import { Colors, Spacing } from '../../Consts';
3
+ import { CTA_SHADOW, TabBarMetrics } from './metrics';
3
4
 
4
5
  export const styles = StyleSheet.create({
6
+ bar: {
7
+ position: 'absolute',
8
+ left: 0,
9
+ right: 0,
10
+ bottom: 0,
11
+ alignItems: 'center',
12
+ },
13
+ // transparent strip that keeps the rising center action touchable
14
+ barCtaRise: {
15
+ paddingTop: TabBarMetrics.ctaLift,
16
+ },
17
+ container: {
18
+ height: TabBarMetrics.height,
19
+ },
5
20
  content: {
6
21
  flex: 1,
7
22
  flexDirection: 'row',
23
+ alignItems: 'center',
24
+ gap: TabBarMetrics.itemGap,
25
+ paddingVertical: TabBarMetrics.paddingVertical,
26
+ paddingHorizontal: TabBarMetrics.paddingHorizontal,
8
27
  },
9
- tabBar: {
10
- left: 0,
11
- right: 0,
12
- bottom: 0,
13
- borderTopWidth: StyleSheet.hairlineWidth,
14
- elevation: 8,
28
+ indicator: {
29
+ height: TabBarMetrics.indicatorHeight,
15
30
  },
16
- tabBarFloatingButton: {
17
- left: 0,
18
- right: 0,
19
- bottom: 0,
20
- zIndex: 1,
21
- shadowColor: Colors.black_20,
22
- shadowOffset: { width: 0, height: -2 },
23
- shadowOpacity: 0.05,
24
- shadowRadius: 3,
25
- elevation: 8,
26
- },
27
- floatingContainer: {
31
+ ctaSlot: {
32
+ width: TabBarMetrics.ctaSlotWidth,
33
+ alignSelf: 'stretch',
34
+ },
35
+ // the button rises ctaLift above the container top, the label ends on the item baseline
36
+ cta: {
28
37
  position: 'absolute',
29
- alignItems: 'center',
30
38
  left: 0,
31
39
  right: 0,
32
- top: -2,
33
- bottom: Platform.OS === 'ios' ? -6 : 4,
40
+ top: -TabBarMetrics.ctaLift - TabBarMetrics.paddingVertical,
41
+ alignItems: 'center',
42
+ gap: TabBarMetrics.ctaLabelGap,
34
43
  },
35
- floatingContent: {
44
+ ctaButton: {
45
+ boxShadow: CTA_SHADOW,
46
+ width: TabBarMetrics.ctaSize,
47
+ height: TabBarMetrics.ctaSize,
48
+ borderRadius: TabBarMetrics.ctaSize / 2,
36
49
  alignItems: 'center',
37
50
  justifyContent: 'center',
38
- height: 48,
39
- width: 48,
40
- borderRadius: 24,
41
- top: -10,
42
- },
43
- indicator: {
44
- height: 2,
45
- width: 44,
46
- alignSelf: 'center',
47
- borderBottomLeftRadius: 1,
48
- borderBottomRightRadius: 1,
49
51
  },
50
- debugBaseLine: { borderWidth: 1, borderColor: Colors.green_06 },
51
- floatingLabel: {
52
- top: -4,
53
- borderRadius: Radius.XL,
54
- paddingHorizontal: 6,
52
+ // custom label content over the label text, centered and unclipped
53
+ ctaLabelOverlay: {
54
+ ...StyleSheet.absoluteFillObject,
55
+ alignItems: 'center',
56
+ justifyContent: 'center',
55
57
  },
56
- indicatorContainer: {
57
- position: 'absolute',
58
- top: 0,
58
+ ctaLabel: {
59
+ maxWidth: TabBarMetrics.ctaSlotWidth,
60
+ minHeight: TabBarMetrics.ctaLabelHeight,
61
+ paddingHorizontal: Spacing.XXS,
62
+ justifyContent: 'center',
59
63
  },
64
+ debugBaseLine: { borderWidth: 1, borderColor: Colors.green_06 },
60
65
  });