@reown/appkit-ui-react-native 2.0.0-alpha.4 → 2.0.0-alpha.5

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 (80) hide show
  1. package/lib/commonjs/components/wui-card/index.js +1 -3
  2. package/lib/commonjs/components/wui-card/index.js.map +1 -1
  3. package/lib/commonjs/components/wui-loading-hexagon/index.js +9 -6
  4. package/lib/commonjs/components/wui-loading-hexagon/index.js.map +1 -1
  5. package/lib/commonjs/components/wui-loading-spinner/index.js +7 -5
  6. package/lib/commonjs/components/wui-loading-spinner/index.js.map +1 -1
  7. package/lib/commonjs/components/wui-loading-thumbnail/index.js +25 -12
  8. package/lib/commonjs/components/wui-loading-thumbnail/index.js.map +1 -1
  9. package/lib/commonjs/components/wui-modal/index.js +28 -28
  10. package/lib/commonjs/components/wui-modal/index.js.map +1 -1
  11. package/lib/commonjs/components/wui-modal/styles.js +10 -9
  12. package/lib/commonjs/components/wui-modal/styles.js.map +1 -1
  13. package/lib/commonjs/components/wui-shimmer/index.js +2 -2
  14. package/lib/commonjs/components/wui-shimmer/index.js.map +1 -1
  15. package/lib/commonjs/composites/wui-card-select/index.js +46 -44
  16. package/lib/commonjs/composites/wui-card-select/index.js.map +1 -1
  17. package/lib/commonjs/composites/wui-card-select-loader/index.js +3 -3
  18. package/lib/commonjs/composites/wui-card-select-loader/index.js.map +1 -1
  19. package/lib/commonjs/composites/wui-qr-code/index.js +6 -2
  20. package/lib/commonjs/composites/wui-qr-code/index.js.map +1 -1
  21. package/lib/commonjs/composites/wui-token-button/index.js +1 -1
  22. package/lib/commonjs/context/ThemeContext.js +18 -16
  23. package/lib/commonjs/context/ThemeContext.js.map +1 -1
  24. package/lib/commonjs/hooks/useCustomDimensions.js +12 -11
  25. package/lib/commonjs/hooks/useCustomDimensions.js.map +1 -1
  26. package/lib/module/components/wui-card/index.js +2 -4
  27. package/lib/module/components/wui-card/index.js.map +1 -1
  28. package/lib/module/components/wui-loading-hexagon/index.js +10 -7
  29. package/lib/module/components/wui-loading-hexagon/index.js.map +1 -1
  30. package/lib/module/components/wui-loading-spinner/index.js +8 -6
  31. package/lib/module/components/wui-loading-spinner/index.js.map +1 -1
  32. package/lib/module/components/wui-loading-thumbnail/index.js +26 -13
  33. package/lib/module/components/wui-loading-thumbnail/index.js.map +1 -1
  34. package/lib/module/components/wui-modal/index.js +30 -30
  35. package/lib/module/components/wui-modal/index.js.map +1 -1
  36. package/lib/module/components/wui-modal/styles.js +10 -9
  37. package/lib/module/components/wui-modal/styles.js.map +1 -1
  38. package/lib/module/components/wui-shimmer/index.js +2 -2
  39. package/lib/module/components/wui-shimmer/index.js.map +1 -1
  40. package/lib/module/composites/wui-card-select/index.js +47 -45
  41. package/lib/module/composites/wui-card-select/index.js.map +1 -1
  42. package/lib/module/composites/wui-card-select-loader/index.js +2 -2
  43. package/lib/module/composites/wui-card-select-loader/index.js.map +1 -1
  44. package/lib/module/composites/wui-qr-code/index.js +5 -2
  45. package/lib/module/composites/wui-qr-code/index.js.map +1 -1
  46. package/lib/module/composites/wui-token-button/index.js +1 -1
  47. package/lib/module/context/ThemeContext.js +19 -17
  48. package/lib/module/context/ThemeContext.js.map +1 -1
  49. package/lib/module/hooks/useCustomDimensions.js +13 -12
  50. package/lib/module/hooks/useCustomDimensions.js.map +1 -1
  51. package/lib/typescript/components/wui-card/index.d.ts.map +1 -1
  52. package/lib/typescript/components/wui-loading-hexagon/index.d.ts.map +1 -1
  53. package/lib/typescript/components/wui-loading-spinner/index.d.ts.map +1 -1
  54. package/lib/typescript/components/wui-loading-thumbnail/index.d.ts.map +1 -1
  55. package/lib/typescript/components/wui-modal/index.d.ts.map +1 -1
  56. package/lib/typescript/components/wui-modal/styles.d.ts +9 -9
  57. package/lib/typescript/components/wui-modal/styles.d.ts.map +1 -1
  58. package/lib/typescript/components/wui-shimmer/index.d.ts +2 -2
  59. package/lib/typescript/composites/wui-card-select/index.d.ts +2 -2
  60. package/lib/typescript/composites/wui-card-select/index.d.ts.map +1 -1
  61. package/lib/typescript/composites/wui-card-select-loader/index.d.ts +2 -2
  62. package/lib/typescript/composites/wui-qr-code/index.d.ts +3 -1
  63. package/lib/typescript/composites/wui-qr-code/index.d.ts.map +1 -1
  64. package/lib/typescript/context/ThemeContext.d.ts.map +1 -1
  65. package/lib/typescript/hooks/useCustomDimensions.d.ts +1 -2
  66. package/lib/typescript/hooks/useCustomDimensions.d.ts.map +1 -1
  67. package/package.json +5 -4
  68. package/src/components/wui-card/index.tsx +3 -5
  69. package/src/components/wui-loading-hexagon/index.tsx +12 -10
  70. package/src/components/wui-loading-spinner/index.tsx +8 -6
  71. package/src/components/wui-loading-thumbnail/index.tsx +17 -10
  72. package/src/components/wui-modal/index.tsx +25 -29
  73. package/src/components/wui-modal/styles.ts +10 -9
  74. package/src/components/wui-shimmer/index.tsx +2 -2
  75. package/src/composites/wui-card-select/index.tsx +48 -48
  76. package/src/composites/wui-card-select-loader/index.tsx +2 -2
  77. package/src/composites/wui-qr-code/index.tsx +10 -2
  78. package/src/composites/wui-token-button/index.tsx +1 -1
  79. package/src/context/ThemeContext.tsx +17 -15
  80. package/src/hooks/useCustomDimensions.ts +16 -13
@@ -1,4 +1,4 @@
1
- import { useEffect, useRef, type ReactNode } from 'react';
1
+ import { useEffect, useMemo, useRef, type ReactNode } from 'react';
2
2
  import { Animated, Easing, View } from 'react-native';
3
3
  import Svg, { Path, Use } from 'react-native-svg';
4
4
  import { useTheme } from '../../hooks/useTheme';
@@ -6,6 +6,9 @@ import styles from './styles';
6
6
 
7
7
  const AnimatedUse = Animated.createAnimatedComponent(Use);
8
8
 
9
+ const HEXAGON_PATH =
10
+ 'M17.22 5.295c3.877-2.277 5.737-3.363 7.72-3.726a11.44 11.44 0 0 1 4.12 0c1.983.363 3.844 1.45 7.72 3.726l6.065 3.562c3.876 2.276 5.731 3.372 7.032 4.938a11.896 11.896 0 0 1 2.06 3.63c.683 1.928.688 4.11.688 8.663v7.124c0 4.553-.005 6.735-.688 8.664a11.896 11.896 0 0 1-2.06 3.63c-1.3 1.565-3.156 2.66-7.032 4.937l-6.065 3.563c-3.877 2.276-5.737 3.362-7.72 3.725a11.46 11.46 0 0 1-4.12 0c-1.983-.363-3.844-1.449-7.72-3.726l-6.065-3.562c-3.876-2.276-5.731-3.372-7.032-4.938a11.885 11.885 0 0 1-2.06-3.63c-.682-1.928-.688-4.11-.688-8.663v-7.124c0-4.553.006-6.735.688-8.664a11.885 11.885 0 0 1 2.06-3.63c1.3-1.565 3.156-2.66 7.032-4.937l6.065-3.562Z';
11
+
9
12
  export interface LoadingHexagonProps {
10
13
  children?: ReactNode;
11
14
  paused?: boolean;
@@ -29,20 +32,19 @@ export function LoadingHexagon({ children, paused }: LoadingHexagonProps) {
29
32
  return () => {
30
33
  loop.stop();
31
34
  };
32
- }, [spinValue]);
35
+ }, []);
33
36
 
34
- const spin = spinValue.current.interpolate({
35
- inputRange: [0, 1],
36
- outputRange: [0, -172]
37
- });
37
+ const spin = useMemo(() => {
38
+ return spinValue.current.interpolate({
39
+ inputRange: [0, 1],
40
+ outputRange: [0, -172]
41
+ });
42
+ }, []);
38
43
 
39
44
  return (
40
45
  <View style={styles.container}>
41
46
  <Svg width={120} height={120} viewBox="0 0 54 59" style={styles.loader} fill="none">
42
- <Path
43
- id="wui-loader-path"
44
- d="M17.22 5.295c3.877-2.277 5.737-3.363 7.72-3.726a11.44 11.44 0 0 1 4.12 0c1.983.363 3.844 1.45 7.72 3.726l6.065 3.562c3.876 2.276 5.731 3.372 7.032 4.938a11.896 11.896 0 0 1 2.06 3.63c.683 1.928.688 4.11.688 8.663v7.124c0 4.553-.005 6.735-.688 8.664a11.896 11.896 0 0 1-2.06 3.63c-1.3 1.565-3.156 2.66-7.032 4.937l-6.065 3.563c-3.877 2.276-5.737 3.362-7.72 3.725a11.46 11.46 0 0 1-4.12 0c-1.983-.363-3.844-1.449-7.72-3.726l-6.065-3.562c-3.876-2.276-5.731-3.372-7.032-4.938a11.885 11.885 0 0 1-2.06-3.63c-.682-1.928-.688-4.11-.688-8.663v-7.124c0-4.553.006-6.735.688-8.664a11.885 11.885 0 0 1 2.06-3.63c1.3-1.565 3.156-2.66 7.032-4.937l6.065-3.562Z"
45
- />
47
+ <Path id="wui-loader-path" d={HEXAGON_PATH} />
46
48
  <AnimatedUse
47
49
  stroke={paused ? 'transparent' : Theme['accent-100']}
48
50
  strokeDasharray="54, 118"
@@ -1,4 +1,4 @@
1
- import { useEffect, useRef } from 'react';
1
+ import { useEffect, useMemo, useRef } from 'react';
2
2
  import { Animated, Easing, View, type StyleProp, type ViewStyle } from 'react-native';
3
3
  import Svg, { Circle } from 'react-native-svg';
4
4
  import { useTheme } from '../../hooks/useTheme';
@@ -39,12 +39,14 @@ export function LoadingSpinner({
39
39
  return () => {
40
40
  loop.stop();
41
41
  };
42
- }, [spinValue]);
42
+ }, []);
43
43
 
44
- const spin = spinValue.current.interpolate({
45
- inputRange: [0, 1],
46
- outputRange: ['0deg', '360deg']
47
- });
44
+ const spin = useMemo(() => {
45
+ return spinValue.current.interpolate({
46
+ inputRange: [0, 1],
47
+ outputRange: ['0deg', '360deg']
48
+ });
49
+ }, []);
48
50
 
49
51
  return (
50
52
  <View style={[styles.container, style]} testID={testID}>
@@ -1,4 +1,4 @@
1
- import { useEffect, useRef, type ReactNode } from 'react';
1
+ import { useEffect, useMemo, useRef, type ReactNode } from 'react';
2
2
  import { Animated, Easing, View } from 'react-native';
3
3
  import Svg, { Rect } from 'react-native-svg';
4
4
  import { useTheme } from '../../hooks/useTheme';
@@ -38,23 +38,30 @@ export function LoadingThumbnail({
38
38
  return () => {
39
39
  loop.stop();
40
40
  };
41
- }, [spinValue]);
41
+ }, []);
42
42
 
43
- // Calculate one side of the Rectangle with borders
44
- const sideLength = rectangleSize - borderRadius * 2 + (Math.PI * borderRadius) / 2;
43
+ const { sideLength, strokeColor, containerStyle } = useMemo(() => {
44
+ const _sideLength = rectangleSize - borderRadius * 2 + (Math.PI * borderRadius) / 2;
45
+ const _strokeColor = paused ? 'transparent' : Theme['accent-100'];
46
+ const _containerStyle = { height: outerContainerSize, width: outerContainerSize };
45
47
 
46
- const spin = spinValue.current.interpolate({
47
- inputRange: [0, 1],
48
- outputRange: [0, -sideLength * 4]
49
- });
48
+ return { sideLength: _sideLength, strokeColor: _strokeColor, containerStyle: _containerStyle };
49
+ }, [rectangleSize, borderRadius, paused, Theme, outerContainerSize]);
50
+
51
+ const spin = useMemo(() => {
52
+ return spinValue.current.interpolate({
53
+ inputRange: [0, 1],
54
+ outputRange: [0, -sideLength * 4]
55
+ });
56
+ }, [sideLength]);
50
57
 
51
58
  return (
52
- <View style={[styles.container, { height: outerContainerSize, width: outerContainerSize }]}>
59
+ <View style={[styles.container, containerStyle]}>
53
60
  <Svg width={outerContainerSize} height={outerContainerSize} style={styles.loader}>
54
61
  <AnimatedRect
55
62
  height={rectangleSize}
56
63
  width={rectangleSize}
57
- stroke={paused ? 'transparent' : Theme['accent-100']}
64
+ stroke={strokeColor}
58
65
  strokeWidth={strokeWidth}
59
66
  x={strokeWidth / 2}
60
67
  y={strokeWidth / 2}
@@ -3,9 +3,9 @@ import {
3
3
  useWindowDimensions,
4
4
  Modal as RNModal,
5
5
  type ModalProps as RNModalProps,
6
- TouchableOpacity,
7
6
  Animated,
8
- StatusBar
7
+ Pressable,
8
+ View
9
9
  } from 'react-native';
10
10
  import { useTheme } from '../../hooks/useTheme';
11
11
  import styles from './styles';
@@ -18,10 +18,11 @@ export type ModalProps = Pick<
18
18
  onBackdropPress?: () => void;
19
19
  };
20
20
 
21
+ const AnimatedPressable = Animated.createAnimatedComponent(Pressable);
22
+
21
23
  export function Modal({ visible, onBackdropPress, onRequestClose, testID, children }: ModalProps) {
22
- const Theme = useTheme();
23
24
  const { height } = useWindowDimensions();
24
-
25
+ const Theme = useTheme();
25
26
  const backdropOpacity = useRef(new Animated.Value(0)).current;
26
27
  const translateY = useRef(new Animated.Value(height)).current;
27
28
  const [showBackdrop, setShowBackdrop] = useState(false);
@@ -75,8 +76,7 @@ export function Modal({ visible, onBackdropPress, onRequestClose, testID, childr
75
76
 
76
77
  if (visible && modalVisible) {
77
78
  // Calculate the target position (screen height - card height)
78
- const targetY =
79
- contentHeight > 0 ? height - contentHeight + (StatusBar.currentHeight ?? 0) : height * 0.2; // fallback to 20% from bottom
79
+ const targetY = contentHeight > 0 ? height - contentHeight : height * 0.2; // fallback to 20% from bottom
80
80
 
81
81
  modalAnimation = Animated.spring(translateY, {
82
82
  toValue: targetY,
@@ -112,31 +112,27 @@ export function Modal({ visible, onBackdropPress, onRequestClose, testID, childr
112
112
  }, [modalVisible, translateY, backdropOpacity, height]);
113
113
 
114
114
  return (
115
- <>
115
+ <RNModal
116
+ visible={modalVisible}
117
+ transparent
118
+ animationType="none"
119
+ statusBarTranslucent
120
+ onRequestClose={onRequestClose}
121
+ testID={testID}
122
+ >
116
123
  {showBackdrop ? (
117
- <Animated.View style={[styles.outerBackdrop, { opacity: backdropOpacity }]} />
124
+ <AnimatedPressable
125
+ style={[styles.backdrop, { opacity: backdropOpacity }]}
126
+ onPress={onBackdropPress}
127
+ />
118
128
  ) : null}
119
- <RNModal
120
- visible={modalVisible}
121
- transparent
122
- animationType="none"
123
- statusBarTranslucent
124
- onRequestClose={onRequestClose}
125
- testID={testID}
129
+ <AnimatedPressable
130
+ onPress={onBackdropPress}
131
+ style={[styles.modal, { transform: [{ translateY }] }]}
126
132
  >
127
- {showBackdrop ? (
128
- <TouchableOpacity
129
- style={styles.innerBackdropTouchable}
130
- activeOpacity={1}
131
- onPress={onBackdropPress}
132
- />
133
- ) : null}
134
- <Animated.View
135
- style={[styles.modal, { backgroundColor: Theme['bg-100'], transform: [{ translateY }] }]}
136
- >
137
- <Animated.View onLayout={onContentLayout}>{children}</Animated.View>
138
- </Animated.View>
139
- </RNModal>
140
- </>
133
+ <Animated.View onLayout={onContentLayout}>{children}</Animated.View>
134
+ <View style={[styles.bottomBackground, { backgroundColor: Theme['bg-100'] }]} />
135
+ </AnimatedPressable>
136
+ </RNModal>
141
137
  );
142
138
  }
@@ -2,18 +2,13 @@ import { StyleSheet } from 'react-native';
2
2
  import { BorderRadius } from '../../utils/ThemeUtil';
3
3
 
4
4
  export default StyleSheet.create({
5
- outerBackdrop: {
6
- position: 'absolute',
7
- top: 0,
8
- left: 0,
9
- right: 0,
10
- bottom: 0,
5
+ backdrop: {
6
+ flexGrow: 1,
11
7
  backgroundColor: 'rgba(0, 0, 0, 0.5)'
12
8
  },
13
- innerBackdropTouchable: {
14
- flexGrow: 1
15
- },
16
9
  modal: {
10
+ backgroundColor: 'transparent',
11
+ borderWidth: 0,
17
12
  borderTopLeftRadius: BorderRadius.l,
18
13
  borderTopRightRadius: BorderRadius.l,
19
14
  position: 'absolute',
@@ -21,5 +16,11 @@ export default StyleSheet.create({
21
16
  left: 0,
22
17
  right: 0,
23
18
  bottom: 0
19
+ },
20
+ bottomBackground: {
21
+ flexGrow: 1,
22
+ // workaround to fix the bottom background color
23
+ top: -2,
24
+ bottom: -20
24
25
  }
25
26
  });
@@ -18,7 +18,7 @@ export interface ShimmerProps {
18
18
  style?: StyleProp<ViewStyle>;
19
19
  }
20
20
 
21
- function _Shimmer({
21
+ function Shimmer_({
22
22
  width = 200,
23
23
  height = 200,
24
24
  duration = 1000,
@@ -127,6 +127,6 @@ function _Shimmer({
127
127
  );
128
128
  }
129
129
 
130
- export const Shimmer = memo(_Shimmer, () => {
130
+ export const Shimmer = memo(Shimmer_, () => {
131
131
  return true;
132
132
  });
@@ -1,4 +1,4 @@
1
- import { memo } from 'react';
1
+ import { memo, useMemo } from 'react';
2
2
  import { Animated, Pressable, View, type StyleProp, type ViewStyle } from 'react-native';
3
3
  import { Text } from '../../components/wui-text';
4
4
  import { IconBox } from '../wui-icon-box';
@@ -9,6 +9,7 @@ import { NetworkImage } from '../wui-network-image';
9
9
  import { WalletImage } from '../wui-wallet-image';
10
10
  import styles, { getBackgroundColor, ITEM_HEIGHT, ITEM_WIDTH } from './styles';
11
11
  import { UiUtil } from '../../utils/UiUtil';
12
+ import { FlexView } from '../../layout/wui-flex';
12
13
 
13
14
  const AnimatedPressable = Animated.createAnimatedComponent(Pressable);
14
15
 
@@ -28,7 +29,7 @@ export interface CardSelectProps {
28
29
  testID?: string;
29
30
  }
30
31
 
31
- function _CardSelect({
32
+ function CardSelect_({
32
33
  name,
33
34
  type = 'wallet',
34
35
  imageSrc,
@@ -43,6 +44,7 @@ function _CardSelect({
43
44
  const Theme = useTheme();
44
45
  const normalbackgroundColor = getBackgroundColor({ selected, disabled, pressed: false });
45
46
  const pressedBackgroundColor = getBackgroundColor({ selected, disabled, pressed: true });
47
+ const Image = useMemo(() => (type === 'wallet' ? WalletImage : NetworkImage), [type]);
46
48
 
47
49
  const { animatedValue, setStartValue, setEndValue } = useAnimatedValue(
48
50
  Theme[normalbackgroundColor],
@@ -51,54 +53,52 @@ function _CardSelect({
51
53
 
52
54
  const textColor = disabled ? 'fg-300' : selected ? 'accent-100' : 'fg-100';
53
55
 
54
- const Image = type === 'wallet' ? WalletImage : NetworkImage;
55
-
56
- const templateInstalled = () => {
57
- if (!installed) return null;
58
-
59
- return (
60
- <IconBox
61
- icon="checkmark"
62
- iconSize="xs"
63
- iconColor={'success-100'}
64
- border
65
- borderSize={6}
66
- borderColor="bg-150"
67
- background
68
- backgroundColor="icon-box-bg-success-100"
69
- size="sm"
70
- style={styles.installedBox}
71
- />
72
- );
73
- };
74
-
75
56
  return (
76
- <AnimatedPressable
77
- onPress={onPress}
78
- onPressIn={setEndValue}
79
- onPressOut={setStartValue}
80
- disabled={disabled}
81
- style={[styles.container, { backgroundColor: animatedValue }, style]}
82
- testID={testID}
83
- >
84
- <View>
85
- <Image
86
- imageSrc={imageSrc}
87
- imageHeaders={imageHeaders}
88
- size="md"
89
- style={disabled ? styles.disabledImage : null}
90
- selected={selected}
91
- disabled={disabled}
92
- />
93
- {templateInstalled()}
94
- </View>
95
- <Text variant="tiny-500" color={textColor} style={styles.text} numberOfLines={1}>
96
- {UiUtil.getWalletName(name)}
97
- </Text>
98
- </AnimatedPressable>
57
+ <FlexView style={style} alignItems="center" justifyContent="center">
58
+ <AnimatedPressable
59
+ onPress={onPress}
60
+ onPressIn={setEndValue}
61
+ onPressOut={setStartValue}
62
+ disabled={disabled}
63
+ style={[styles.container, { backgroundColor: animatedValue }]}
64
+ testID={testID}
65
+ >
66
+ <View>
67
+ <Image
68
+ imageSrc={imageSrc}
69
+ imageHeaders={imageHeaders}
70
+ size="md"
71
+ style={disabled ? styles.disabledImage : null}
72
+ selected={selected}
73
+ disabled={disabled}
74
+ />
75
+ {installed ? (
76
+ <IconBox
77
+ icon="checkmark"
78
+ iconSize="xs"
79
+ iconColor={'success-100'}
80
+ border
81
+ borderSize={6}
82
+ borderColor="bg-150"
83
+ background
84
+ backgroundColor="icon-box-bg-success-100"
85
+ size="sm"
86
+ style={styles.installedBox}
87
+ />
88
+ ) : null}
89
+ </View>
90
+ <Text variant="tiny-500" color={textColor} style={styles.text} numberOfLines={1}>
91
+ {UiUtil.getWalletName(name)}
92
+ </Text>
93
+ </AnimatedPressable>
94
+ </FlexView>
99
95
  );
100
96
  }
101
97
 
102
- export const CardSelect = memo(_CardSelect, (prevProps, nextProps) => {
103
- return prevProps.name === nextProps.name && prevProps.imageSrc === nextProps.imageSrc;
98
+ export const CardSelect = memo(CardSelect_, (prevProps, nextProps) => {
99
+ return (
100
+ prevProps.name === nextProps.name &&
101
+ prevProps.imageSrc === nextProps.imageSrc &&
102
+ prevProps.selected === nextProps.selected
103
+ );
104
104
  });
@@ -12,7 +12,7 @@ export interface CardSelectLoaderProps {
12
12
  style?: StyleProp<ViewStyle>;
13
13
  }
14
14
 
15
- export function _CardSelectLoader({ style }: CardSelectLoaderProps) {
15
+ export function CardSelectLoader_({ style }: CardSelectLoaderProps) {
16
16
  const Theme = useTheme();
17
17
 
18
18
  return (
@@ -35,6 +35,6 @@ export function _CardSelectLoader({ style }: CardSelectLoaderProps) {
35
35
  </FlexView>
36
36
  );
37
37
  }
38
- export const CardSelectLoader = memo(_CardSelectLoader, () => {
38
+ export const CardSelectLoader = memo(CardSelectLoader_, () => {
39
39
  return true;
40
40
  });
@@ -1,4 +1,4 @@
1
- import { useMemo } from 'react';
1
+ import { memo, useMemo } from 'react';
2
2
  import { View, type StyleProp, type ViewStyle } from 'react-native';
3
3
  import Svg from 'react-native-svg';
4
4
  import { Icon } from '../../components/wui-icon';
@@ -19,7 +19,7 @@ export interface QrCodeProps {
19
19
  style?: StyleProp<ViewStyle>;
20
20
  }
21
21
 
22
- export function QrCode({ size, uri, imageSrc, testID, arenaClear, icon, style }: QrCodeProps) {
22
+ export function QrCode_({ size, uri, imageSrc, testID, arenaClear, icon, style }: QrCodeProps) {
23
23
  const Theme = LightTheme;
24
24
  const containerPadding = Spacing.l;
25
25
  const qrSize = size - containerPadding * 2;
@@ -76,3 +76,11 @@ export function QrCode({ size, uri, imageSrc, testID, arenaClear, icon, style }:
76
76
  <Shimmer width={size} height={size} borderRadius={BorderRadius.l} />
77
77
  );
78
78
  }
79
+
80
+ export const QrCode = memo(QrCode_, (prevProps, nextProps) => {
81
+ return (
82
+ prevProps.size === nextProps.size &&
83
+ prevProps.uri === nextProps.uri &&
84
+ prevProps.style === nextProps.style
85
+ );
86
+ });
@@ -28,7 +28,7 @@ export function TokenButton({
28
28
  onPress,
29
29
  style,
30
30
  disabled = false,
31
- placeholder = 'Select token',
31
+ placeholder = 'Select Token',
32
32
  chevron,
33
33
  renderClip,
34
34
  testID
@@ -1,5 +1,5 @@
1
1
  import { useColorScheme } from 'react-native';
2
- import { createContext, useContext, type ReactNode } from 'react';
2
+ import { createContext, useContext, useMemo, type ReactNode } from 'react';
3
3
  import type { ThemeMode, ThemeVariables } from '@reown/appkit-common-react-native';
4
4
 
5
5
  import { DarkTheme, LightTheme, getAccentColors } from '../utils/ThemeUtil';
@@ -18,27 +18,29 @@ interface ThemeProviderProps {
18
18
  }
19
19
 
20
20
  export function ThemeProvider({ children, themeMode, themeVariables }: ThemeProviderProps) {
21
- return (
22
- <ThemeContext.Provider value={{ themeMode, themeVariables }}>{children}</ThemeContext.Provider>
23
- );
21
+ const contextValue = useMemo(() => ({ themeMode, themeVariables }), [themeMode, themeVariables]);
22
+
23
+ return <ThemeContext.Provider value={contextValue}>{children}</ThemeContext.Provider>;
24
24
  }
25
25
 
26
26
  export function useTheme() {
27
27
  const context = useContext(ThemeContext);
28
28
  const scheme = useColorScheme();
29
29
 
30
- // If the theme mode is not set, use the system color scheme
31
- const themeMode = context?.themeMode ?? scheme;
32
- const themeVariables = context?.themeVariables ?? {};
30
+ return useMemo(() => {
31
+ // If the theme mode is not set, use the system color scheme
32
+ const themeMode = context?.themeMode ?? scheme;
33
+ const themeVariables = context?.themeVariables ?? {};
33
34
 
34
- let Theme = themeMode === 'dark' ? DarkTheme : LightTheme;
35
+ let Theme = themeMode === 'dark' ? DarkTheme : LightTheme;
35
36
 
36
- if (themeVariables.accent) {
37
- Theme = {
38
- ...Theme,
39
- ...getAccentColors(themeVariables.accent)
40
- };
41
- }
37
+ if (themeVariables.accent) {
38
+ Theme = {
39
+ ...Theme,
40
+ ...getAccentColors(themeVariables.accent)
41
+ };
42
+ }
42
43
 
43
- return Theme;
44
+ return Theme;
45
+ }, [context?.themeMode, context?.themeVariables, scheme]);
44
46
  }
@@ -1,38 +1,41 @@
1
1
  import { useState, useEffect } from 'react';
2
- import { useWindowDimensions } from 'react-native';
2
+ import { StatusBar, useWindowDimensions } from 'react-native';
3
3
 
4
4
  /**
5
5
  * Hook used to get the width of the screen and the padding needed to accomplish portrait and landscape modes.
6
- * @returns { width: number, isPortrait: boolean, isLandscape: boolean, padding: number }
6
+ * @returns { maxHeight: number, isPortrait: boolean, isLandscape: boolean, padding: number }
7
7
  */
8
8
 
9
9
  type CustomDimensionsType = {
10
- maxWidth: number;
11
10
  maxHeight: number;
12
11
  isPortrait: boolean;
13
12
  isLandscape: boolean;
14
13
  padding: number;
15
14
  };
16
15
 
17
- const MAX_HEIGHT_PERCENTAGE = 0.9;
16
+ const MAX_PORTRAIT_PERCENTAGE = 0.9;
17
+ const MAX_LANDSCAPE_PERCENTAGE = 0.85;
18
+ const IOS_STATUS_BAR_HEIGHT = 20;
18
19
 
19
- const getMaxHeight = (width: number, height: number) => {
20
- return Math.max(width, height) * MAX_HEIGHT_PERCENTAGE;
20
+ const getMaxHeight = (height: number, isPortrait: boolean) => {
21
+ const percentage = isPortrait ? MAX_PORTRAIT_PERCENTAGE : MAX_LANDSCAPE_PERCENTAGE;
22
+
23
+ return height * percentage - (StatusBar.currentHeight ?? IOS_STATUS_BAR_HEIGHT);
21
24
  };
22
25
 
23
26
  export function useCustomDimensions(): CustomDimensionsType {
24
27
  const { width, height } = useWindowDimensions();
25
- const [maxWidth, setMaxWidth] = useState<number>(Math.min(width, height));
26
- const [maxHeight, setMaxHeight] = useState<number>(getMaxHeight(width, height));
27
28
  const [isPortrait, setIsPortrait] = useState<boolean>(height > width);
29
+ const [maxHeight, setMaxHeight] = useState<number>(getMaxHeight(height, height > width));
28
30
  const [padding, setPadding] = useState<number>(0);
29
31
 
30
32
  useEffect(() => {
31
- setMaxWidth(Math.min(width, height));
32
- setMaxHeight(getMaxHeight(width, height));
33
- setIsPortrait(height > width);
34
- setPadding(width < height ? 0 : (width - height) / 2);
33
+ const _isPortrait = height > width;
34
+
35
+ setMaxHeight(getMaxHeight(height, _isPortrait));
36
+ setIsPortrait(_isPortrait);
37
+ setPadding(_isPortrait ? 0 : (width - height) / 2);
35
38
  }, [width, height]);
36
39
 
37
- return { maxWidth, maxHeight, isPortrait, isLandscape: !isPortrait, padding };
40
+ return { maxHeight, isPortrait, isLandscape: !isPortrait, padding };
38
41
  }