@aws-amplify/ui-react-native 1.1.2 → 1.1.4

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 (72) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/dist/Authenticator/common/DefaultContent/DefaultContent.js +1 -1
  3. package/dist/Authenticator/common/DefaultContent/styles.js +2 -1
  4. package/dist/Authenticator/common/DefaultContent/types.d.ts +2 -1
  5. package/dist/Authenticator/common/FederatedProviderButton/FederatedProviderButton.js +8 -7
  6. package/dist/hooks/index.d.ts +1 -0
  7. package/dist/hooks/index.js +1 -0
  8. package/dist/hooks/usePressableContainerStyles/index.d.ts +1 -0
  9. package/dist/hooks/usePressableContainerStyles/index.js +1 -0
  10. package/dist/hooks/usePressableContainerStyles/usePressableContainerStyles.d.ts +19 -0
  11. package/dist/hooks/usePressableContainerStyles/usePressableContainerStyles.js +14 -0
  12. package/dist/primitives/Button/Button.js +13 -12
  13. package/dist/primitives/ErrorMessage/ErrorMessage.d.ts +1 -1
  14. package/dist/primitives/ErrorMessage/ErrorMessage.js +2 -2
  15. package/dist/primitives/ErrorMessage/styles.js +4 -2
  16. package/dist/primitives/ErrorMessage/types.d.ts +2 -0
  17. package/dist/primitives/IconButton/IconButton.js +12 -11
  18. package/dist/primitives/Radio/Radio.js +12 -10
  19. package/dist/primitives/Radio/styles.js +4 -0
  20. package/dist/primitives/Radio/types.d.ts +1 -0
  21. package/dist/primitives/Tabs/Tab.js +13 -13
  22. package/dist/primitives/Tabs/styles.js +4 -0
  23. package/dist/primitives/Tabs/types.d.ts +1 -0
  24. package/package.json +3 -3
  25. package/src/Authenticator/Defaults/ConfirmResetPassword/__tests__/__snapshots__/ConfirmResetPassword.spec.tsx.snap +24 -37
  26. package/src/Authenticator/Defaults/ConfirmSignIn/__tests__/__snapshots__/ConfirmSignIn.spec.tsx.snap +16 -23
  27. package/src/Authenticator/Defaults/ConfirmSignUp/__tests__/__snapshots__/ConfirmSignUp.spec.tsx.snap +25 -41
  28. package/src/Authenticator/Defaults/ConfirmVerifyUser/__tests__/__snapshots__/ConfirmVerifyUser.spec.tsx.snap +19 -32
  29. package/src/Authenticator/Defaults/ForceNewPassword/__tests__/__snapshots__/ForceNewPassword.spec.tsx.snap +22 -38
  30. package/src/Authenticator/Defaults/ResetPassword/__tests__/__snapshots__/ResetPassword.spec.tsx.snap +16 -23
  31. package/src/Authenticator/Defaults/SetupTOTP/__tests__/__snapshots__/SetupTOTP.spec.tsx.snap +16 -23
  32. package/src/Authenticator/Defaults/SignIn/__tests__/__snapshots__/SignIn.spec.tsx.snap +24 -44
  33. package/src/Authenticator/Defaults/SignUp/__tests__/__snapshots__/SignUp.spec.tsx.snap +34 -67
  34. package/src/Authenticator/Defaults/VerifyUser/__tests__/__snapshots__/VerifyUser.spec.tsx.snap +20 -23
  35. package/src/Authenticator/common/DefaultContainer/__tests__/__snapshots__/DefaultContainer.spec.tsx.snap +3 -6
  36. package/src/Authenticator/common/DefaultContent/DefaultContent.tsx +2 -1
  37. package/src/Authenticator/common/DefaultContent/styles.ts +2 -1
  38. package/src/Authenticator/common/DefaultContent/types.ts +2 -1
  39. package/src/Authenticator/common/DefaultFooter/__tests__/__snapshots__/DefaultFooter.spec.tsx.snap +3 -6
  40. package/src/Authenticator/common/FederatedProviderButton/FederatedProviderButton.tsx +8 -12
  41. package/src/Authenticator/common/FederatedProviderButton/__tests__/FederatedProviderButton.spec.tsx +34 -3
  42. package/src/Authenticator/common/FederatedProviderButton/__tests__/__snapshots__/FederatedProviderButton.spec.tsx.snap +94 -3
  43. package/src/Authenticator/common/FederatedProviderButtons/__tests__/__snapshots__/FederatedProviderButtons.spec.tsx.snap +4 -6
  44. package/src/InAppMessaging/components/BannerMessage/__tests__/__snapshots__/BannerMessage.spec.tsx.snap +2 -4
  45. package/src/InAppMessaging/components/ModalMessage/__tests__/ModalMessage.spec.tsx +1 -1
  46. package/src/InAppMessaging/components/ModalMessage/__tests__/__snapshots__/ModalMessage.spec.tsx.snap +3 -6
  47. package/src/hooks/index.ts +1 -0
  48. package/src/hooks/usePressableContainerStyles/__tests__/usePressableContainerStyles.spec.ts +68 -0
  49. package/src/hooks/usePressableContainerStyles/index.ts +1 -0
  50. package/src/hooks/usePressableContainerStyles/usePressableContainerStyles.ts +51 -0
  51. package/src/primitives/Button/Button.tsx +16 -23
  52. package/src/primitives/Button/__tests__/__snapshots__/Button.spec.tsx.snap +9 -18
  53. package/src/primitives/ErrorMessage/ErrorMessage.tsx +6 -1
  54. package/src/primitives/ErrorMessage/__tests__/__snapshots__/ErrorMessage.spec.tsx.snap +18 -8
  55. package/src/primitives/ErrorMessage/styles.ts +4 -2
  56. package/src/primitives/ErrorMessage/types.ts +3 -0
  57. package/src/primitives/IconButton/IconButton.tsx +16 -19
  58. package/src/primitives/IconButton/__tests__/IconButton.spec.tsx +6 -6
  59. package/src/primitives/IconButton/__tests__/__snapshots__/IconButton.spec.tsx.snap +4 -8
  60. package/src/primitives/PasswordField/__tests__/__snapshots__/PasswordField.spec.tsx.snap +4 -8
  61. package/src/primitives/Radio/Radio.tsx +15 -16
  62. package/src/primitives/Radio/__tests__/Radio.spec.tsx +1 -0
  63. package/src/primitives/Radio/__tests__/__snapshots__/Radio.spec.tsx.snap +9 -0
  64. package/src/primitives/Radio/styles.ts +4 -0
  65. package/src/primitives/Radio/types.ts +1 -0
  66. package/src/primitives/RadioGroup/__tests__/__snapshots__/RadioGroup.spec.tsx.snap +24 -0
  67. package/src/primitives/Tabs/Tab.tsx +17 -18
  68. package/src/primitives/Tabs/__tests__/Tab.spec.tsx +20 -13
  69. package/src/primitives/Tabs/__tests__/__snapshots__/Tab.spec.tsx.snap +23 -43
  70. package/src/primitives/Tabs/__tests__/__snapshots__/Tabs.spec.tsx.snap +14 -26
  71. package/src/primitives/Tabs/styles.ts +4 -0
  72. package/src/primitives/Tabs/types.ts +1 -0
@@ -64,17 +64,14 @@ exports[`DefaultContainer renders as expected with children 1`] = `
64
64
  Object {
65
65
  "alignItems": "center",
66
66
  "backgroundColor": "transparent",
67
+ "borderColor": "hsl(210, 10%, 58%)",
67
68
  "borderRadius": 4,
69
+ "borderWidth": 1,
68
70
  "justifyContent": "center",
69
71
  "paddingHorizontal": 16,
70
72
  "paddingVertical": 12,
71
73
  },
72
- Object {
73
- "borderColor": "hsl(210, 10%, 58%)",
74
- "borderWidth": 1,
75
- },
76
- null,
77
- null,
74
+ undefined,
78
75
  undefined,
79
76
  ]
80
77
  }
@@ -66,8 +66,9 @@ export default function DefaultContent<
66
66
  />
67
67
  {error ? (
68
68
  <ErrorMessage
69
- style={themedStyles.errorMessage}
69
+ iconStyle={themedStyles.errorMessageIcon}
70
70
  labelStyle={themedStyles.errorMessageLabel}
71
+ style={themedStyles.errorMessage}
71
72
  >
72
73
  {error}
73
74
  </ErrorMessage>
@@ -21,8 +21,9 @@ export const getDefaultStyle = ({
21
21
  },
22
22
  buttonSecondaryLabel: {}, // themed value only
23
23
  errorMessage: {
24
- marginVertical: space.small,
24
+ marginHorizontal: space.small,
25
25
  },
26
+ errorMessageIcon: {}, // themed value only
26
27
  errorMessageLabel: {}, // themed value only
27
28
  fieldContainer: {
28
29
  paddingHorizontal: space.small,
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- import { StyleProp, TextStyle, ViewStyle } from 'react-native';
2
+ import { ImageStyle, StyleProp, TextStyle, ViewStyle } from 'react-native';
3
3
 
4
4
  import {
5
5
  AuthenticatorComponentDefaultProps,
@@ -24,6 +24,7 @@ export interface DefaultContentStyle {
24
24
  buttonSecondary?: ViewStyle;
25
25
  buttonSecondaryLabel?: TextStyle;
26
26
  errorMessage?: ViewStyle;
27
+ errorMessageIcon?: ImageStyle;
27
28
  errorMessageLabel?: TextStyle;
28
29
  fieldErrorsContainer?: ViewStyle;
29
30
  fieldContainer?: ViewStyle;
@@ -21,17 +21,14 @@ exports[`DefaultFooter renders as expected with children 1`] = `
21
21
  Object {
22
22
  "alignItems": "center",
23
23
  "backgroundColor": "transparent",
24
+ "borderColor": "hsl(210, 10%, 58%)",
24
25
  "borderRadius": 4,
26
+ "borderWidth": 1,
25
27
  "justifyContent": "center",
26
28
  "paddingHorizontal": 16,
27
29
  "paddingVertical": 12,
28
30
  },
29
- Object {
30
- "borderColor": "hsl(210, 10%, 58%)",
31
- "borderWidth": 1,
32
- },
33
- null,
34
- null,
31
+ undefined,
35
32
  undefined,
36
33
  ]
37
34
  }
@@ -1,7 +1,7 @@
1
- import React, { useCallback } from 'react';
2
- import { PressableStateCallbackType, StyleProp, ViewStyle } from 'react-native';
1
+ import React from 'react';
3
2
 
4
3
  import { Button, Icon, Label } from '../../../primitives';
4
+ import { usePressableContainerStyles } from '../../../hooks';
5
5
 
6
6
  import { styles } from './styles';
7
7
  import { FederatedProviderButtonProps } from './types';
@@ -13,18 +13,14 @@ export default function FederatedProviderButton({
13
13
  textStyle,
14
14
  ...rest
15
15
  }: FederatedProviderButtonProps): JSX.Element {
16
- const containerStyle = useCallback(
17
- ({ pressed }: PressableStateCallbackType): StyleProp<ViewStyle> => {
18
- const pressedStateStyle =
19
- typeof style === 'function' ? style({ pressed }) : style;
20
- return [styles.container, pressedStateStyle];
21
- },
22
- [style]
23
- );
16
+ const pressableStyle = usePressableContainerStyles({
17
+ containerStyle: styles.container,
18
+ overrideStyle: style,
19
+ });
24
20
 
25
21
  return (
26
- <Button {...rest} style={containerStyle}>
27
- {source ? <Icon source={source} style={styles.icon} size={20} /> : null}
22
+ <Button {...rest} style={pressableStyle}>
23
+ <Icon source={source} style={styles.icon} size={20} />
28
24
  <Label style={[styles.label, textStyle]}>{children}</Label>
29
25
  </Button>
30
26
  );
@@ -1,20 +1,27 @@
1
1
  import React from 'react';
2
- import { fireEvent, render } from '@testing-library/react-native';
2
+ import { fireEvent, render, renderHook } from '@testing-library/react-native';
3
3
 
4
4
  import { icons } from '../../../../assets';
5
5
  import FederatedProviderButton from '../FederatedProviderButton';
6
+ import { useTheme } from '../../../../theme';
7
+ import { getThemedStyles as getButtonThemedStyles } from '../../../../primitives/Button/styles';
8
+ import { styles } from '../styles';
6
9
 
7
10
  const signInText = 'Sign In with Amazon';
8
11
 
9
- /* TODO: Add more tests */
10
12
  describe('FederatedProviderButton', () => {
11
13
  it('renders default button as expected', () => {
12
- const { toJSON } = render(
14
+ const { toJSON, getByRole } = render(
13
15
  <FederatedProviderButton source={icons.amazonLogo}>
14
16
  {signInText}
15
17
  </FederatedProviderButton>
16
18
  );
17
19
  expect(toJSON()).toMatchSnapshot();
20
+
21
+ expect(getByRole('button')).toBeDefined();
22
+ const icon = getByRole('image');
23
+ expect(icon).toBeDefined();
24
+ expect(icon.props.source).toEqual(icons.amazonLogo);
18
25
  });
19
26
 
20
27
  it('handles an onPress callback', () => {
@@ -33,4 +40,28 @@ describe('FederatedProviderButton', () => {
33
40
 
34
41
  expect(toFederatedSignInMock).toHaveBeenCalledTimes(1);
35
42
  });
43
+
44
+ it('applies style props', () => {
45
+ const customStyle = { backgroundColor: 'blue' };
46
+
47
+ const { toJSON, getByRole } = render(
48
+ <FederatedProviderButton source={icons.amazonLogo} style={customStyle}>
49
+ {signInText}
50
+ </FederatedProviderButton>
51
+ );
52
+
53
+ const { result } = renderHook(() => useTheme());
54
+ const buttonThemedStyle = getButtonThemedStyles(result.current);
55
+ expect(getByRole('button').props.style).toStrictEqual([
56
+ { ...buttonThemedStyle.container, ...buttonThemedStyle.containerDefault },
57
+ undefined, // button pressed styles
58
+ [
59
+ styles.container,
60
+ undefined, // pressed style
61
+ customStyle,
62
+ ],
63
+ ]);
64
+
65
+ expect(toJSON()).toMatchSnapshot();
66
+ });
36
67
  });
@@ -1,6 +1,6 @@
1
1
  // Jest Snapshot v1, https://goo.gl/fbAQLP
2
2
 
3
- exports[`FederatedProviderButton renders default button as expected 1`] = `
3
+ exports[`FederatedProviderButton applies style props 1`] = `
4
4
  <View
5
5
  accessibilityRole="button"
6
6
  accessible={true}
@@ -20,17 +20,107 @@ exports[`FederatedProviderButton renders default button as expected 1`] = `
20
20
  Object {
21
21
  "alignItems": "center",
22
22
  "backgroundColor": "transparent",
23
+ "borderColor": "hsl(210, 10%, 58%)",
23
24
  "borderRadius": 4,
25
+ "borderWidth": 1,
24
26
  "justifyContent": "center",
25
27
  "paddingHorizontal": 16,
26
28
  "paddingVertical": 12,
27
29
  },
30
+ undefined,
31
+ Array [
32
+ Object {
33
+ "alignItems": "center",
34
+ "borderRadius": 4,
35
+ "borderWidth": 0.5,
36
+ "flexDirection": "row",
37
+ "justifyContent": "center",
38
+ "paddingVertical": 8,
39
+ "width": "100%",
40
+ },
41
+ undefined,
42
+ Object {
43
+ "backgroundColor": "blue",
44
+ },
45
+ ],
46
+ ]
47
+ }
48
+ >
49
+ <Image
50
+ accessibilityRole="image"
51
+ source={
28
52
  Object {
53
+ "testUri": "../../../src/assets/icons/amazonLogo.png",
54
+ }
55
+ }
56
+ style={
57
+ Array [
58
+ Object {
59
+ "height": 20,
60
+ "resizeMode": "contain",
61
+ "tintColor": undefined,
62
+ "width": 20,
63
+ },
64
+ Object {
65
+ "paddingHorizontal": 16,
66
+ },
67
+ ]
68
+ }
69
+ />
70
+ <Text
71
+ accessibilityRole="text"
72
+ style={
73
+ Array [
74
+ Object {
75
+ "fontSize": 14,
76
+ "fontWeight": "400",
77
+ "lineHeight": 21,
78
+ },
79
+ Object {
80
+ "color": "hsl(210, 50%, 10%)",
81
+ },
82
+ Array [
83
+ Object {
84
+ "fontWeight": "400",
85
+ },
86
+ undefined,
87
+ ],
88
+ ]
89
+ }
90
+ >
91
+ Sign In with Amazon
92
+ </Text>
93
+ </View>
94
+ `;
95
+
96
+ exports[`FederatedProviderButton renders default button as expected 1`] = `
97
+ <View
98
+ accessibilityRole="button"
99
+ accessible={true}
100
+ collapsable={false}
101
+ focusable={true}
102
+ onBlur={[Function]}
103
+ onClick={[Function]}
104
+ onFocus={[Function]}
105
+ onResponderGrant={[Function]}
106
+ onResponderMove={[Function]}
107
+ onResponderRelease={[Function]}
108
+ onResponderTerminate={[Function]}
109
+ onResponderTerminationRequest={[Function]}
110
+ onStartShouldSetResponder={[Function]}
111
+ style={
112
+ Array [
113
+ Object {
114
+ "alignItems": "center",
115
+ "backgroundColor": "transparent",
29
116
  "borderColor": "hsl(210, 10%, 58%)",
117
+ "borderRadius": 4,
30
118
  "borderWidth": 1,
119
+ "justifyContent": "center",
120
+ "paddingHorizontal": 16,
121
+ "paddingVertical": 12,
31
122
  },
32
- null,
33
- null,
123
+ undefined,
34
124
  Array [
35
125
  Object {
36
126
  "alignItems": "center",
@@ -42,6 +132,7 @@ exports[`FederatedProviderButton renders default button as expected 1`] = `
42
132
  "width": "100%",
43
133
  },
44
134
  undefined,
135
+ undefined,
45
136
  ],
46
137
  ]
47
138
  }
@@ -27,17 +27,14 @@ exports[`FederatedProviderButtons renders as expected 1`] = `
27
27
  Object {
28
28
  "alignItems": "center",
29
29
  "backgroundColor": "transparent",
30
+ "borderColor": "hsl(210, 10%, 58%)",
30
31
  "borderRadius": 4,
32
+ "borderWidth": 1,
31
33
  "justifyContent": "center",
32
34
  "paddingHorizontal": 16,
33
35
  "paddingVertical": 12,
34
36
  },
35
- Object {
36
- "borderColor": "hsl(210, 10%, 58%)",
37
- "borderWidth": 1,
38
- },
39
- null,
40
- null,
37
+ undefined,
41
38
  Array [
42
39
  Object {
43
40
  "alignItems": "center",
@@ -48,6 +45,7 @@ exports[`FederatedProviderButtons renders as expected 1`] = `
48
45
  "paddingVertical": 8,
49
46
  "width": "100%",
50
47
  },
48
+ undefined,
51
49
  Object {
52
50
  "marginVertical": 8,
53
51
  },
@@ -96,8 +96,7 @@ exports[`BannerMessage renders a message as expected with an image 1`] = `
96
96
  style={
97
97
  Array [
98
98
  Object {},
99
- null,
100
- null,
99
+ undefined,
101
100
  Array [
102
101
  Object {
103
102
  "alignSelf": "flex-start",
@@ -205,8 +204,7 @@ exports[`BannerMessage renders a message as expected without an image 1`] = `
205
204
  style={
206
205
  Array [
207
206
  Object {},
208
- null,
209
- null,
207
+ undefined,
210
208
  Array [
211
209
  Object {
212
210
  "alignSelf": "flex-start",
@@ -7,7 +7,7 @@ import { useMessageImage } from '../../../hooks';
7
7
 
8
8
  import ModalMessage from '../ModalMessage';
9
9
 
10
- jest.mock('../../../../hooks');
10
+ jest.mock('../../../../hooks/useDeviceOrientation');
11
11
  jest.mock('../../../hooks/useMessageImage');
12
12
  jest.mock('../../MessageWrapper', () => ({ MessageWrapper: 'MessageWrapper' }));
13
13
 
@@ -62,8 +62,7 @@ exports[`ModalMessage renders a message as expected with an image 1`] = `
62
62
  style={
63
63
  Array [
64
64
  Object {},
65
- null,
66
- null,
65
+ undefined,
67
66
  Array [
68
67
  Object {
69
68
  "alignSelf": "flex-start",
@@ -206,8 +205,7 @@ exports[`ModalMessage renders as expected in landscape mode 1`] = `
206
205
  style={
207
206
  Array [
208
207
  Object {},
209
- null,
210
- null,
208
+ undefined,
211
209
  Array [
212
210
  Object {
213
211
  "alignSelf": "flex-start",
@@ -307,8 +305,7 @@ exports[`ModalMessage renders as expected in portrait mode 1`] = `
307
305
  style={
308
306
  Array [
309
307
  Object {},
310
- null,
311
- null,
308
+ undefined,
312
309
  Array [
313
310
  Object {
314
311
  "alignSelf": "flex-start",
@@ -2,3 +2,4 @@ export {
2
2
  DeviceOrientation,
3
3
  useDeviceOrientation,
4
4
  } from './useDeviceOrientation';
5
+ export { usePressableContainerStyles } from './usePressableContainerStyles';
@@ -0,0 +1,68 @@
1
+ import { renderHook } from '@testing-library/react-native';
2
+ import { ViewStyle } from 'react-native';
3
+
4
+ import {
5
+ UsePressableContainerStyleProps,
6
+ usePressableContainerStyles,
7
+ } from '../usePressableContainerStyles';
8
+
9
+ const style: ViewStyle = {
10
+ backgroundColor: 'red',
11
+ };
12
+ const themedStyle: ViewStyle = {
13
+ padding: 10,
14
+ };
15
+ const pressedStyle: ViewStyle = {
16
+ opacity: 70,
17
+ };
18
+
19
+ describe('usePressableContainerStyles', () => {
20
+ it('should apply styles correctly and return a style object', () => {
21
+ const props: UsePressableContainerStyleProps = {
22
+ overrideStyle: style,
23
+ containerStyle: themedStyle,
24
+ pressedStyle,
25
+ };
26
+
27
+ const { result } = renderHook(() => usePressableContainerStyles(props));
28
+
29
+ expect(result.current({ pressed: false })).toStrictEqual([
30
+ { ...themedStyle },
31
+ undefined, // no pressed styles
32
+ { ...style },
33
+ ]);
34
+ });
35
+
36
+ it('should apply pressed styles correctly and return a style object', () => {
37
+ const props: UsePressableContainerStyleProps = {
38
+ overrideStyle: style,
39
+ containerStyle: themedStyle,
40
+ pressedStyle,
41
+ };
42
+
43
+ const { result } = renderHook(() => usePressableContainerStyles(props));
44
+
45
+ expect(result.current({ pressed: true })).toStrictEqual([
46
+ { ...themedStyle },
47
+ { ...pressedStyle },
48
+ { ...style },
49
+ ]);
50
+ });
51
+
52
+ it('should apply style function correctly and return a style object', () => {
53
+ const props: UsePressableContainerStyleProps = {
54
+ overrideStyle: () => {
55
+ return style;
56
+ },
57
+ containerStyle: themedStyle,
58
+ };
59
+
60
+ const { result } = renderHook(() => usePressableContainerStyles(props));
61
+
62
+ expect(result.current({ pressed: false })).toStrictEqual([
63
+ { ...themedStyle },
64
+ undefined,
65
+ { ...style },
66
+ ]);
67
+ });
68
+ });
@@ -0,0 +1 @@
1
+ export { usePressableContainerStyles } from './usePressableContainerStyles';
@@ -0,0 +1,51 @@
1
+ import { useCallback } from 'react';
2
+ import {
3
+ PressableProps,
4
+ PressableStateCallbackType,
5
+ StyleProp,
6
+ ViewStyle,
7
+ } from 'react-native';
8
+
9
+ export interface UsePressableContainerStyleProps {
10
+ /**
11
+ * @description
12
+ * Either view styles or a function representing override styles for the pressed state
13
+ */
14
+ overrideStyle: PressableProps['style'];
15
+
16
+ /**
17
+ * @description
18
+ * Pass-through view styles, typically includes theme, disabled, variant styles
19
+ */
20
+ containerStyle?: StyleProp<ViewStyle>;
21
+
22
+ /**
23
+ * @description
24
+ * Pass-through view styles for the pressed state applied before the override styles
25
+ */
26
+ pressedStyle?: StyleProp<ViewStyle>;
27
+ }
28
+
29
+ export const usePressableContainerStyles = ({
30
+ overrideStyle,
31
+ containerStyle,
32
+ pressedStyle,
33
+ }: UsePressableContainerStyleProps): (({
34
+ pressed,
35
+ }: PressableStateCallbackType) => StyleProp<ViewStyle>) => {
36
+ return useCallback(
37
+ ({ pressed }: PressableStateCallbackType): StyleProp<ViewStyle> => {
38
+ const pressedOverrideStyle =
39
+ typeof overrideStyle === 'function'
40
+ ? overrideStyle({ pressed })
41
+ : overrideStyle;
42
+ return [
43
+ containerStyle,
44
+ pressed ? pressedStyle : undefined,
45
+ // include last to override other styles
46
+ pressedOverrideStyle,
47
+ ];
48
+ },
49
+ [containerStyle, overrideStyle, pressedStyle]
50
+ );
51
+ };
@@ -1,12 +1,6 @@
1
- import React, { useCallback, useMemo } from 'react';
2
- import {
3
- Pressable,
4
- PressableStateCallbackType,
5
- StyleProp,
6
- Text,
7
- TextStyle,
8
- ViewStyle,
9
- } from 'react-native';
1
+ import React, { useMemo } from 'react';
2
+ import { Pressable, Text, TextStyle, ViewStyle } from 'react-native';
3
+ import { usePressableContainerStyles } from '../../hooks';
10
4
 
11
5
  import { useTheme } from '../../theme';
12
6
  import { capitalize } from '../../utils';
@@ -25,22 +19,21 @@ export default function Button({
25
19
  const theme = useTheme();
26
20
  const themedStyle = getThemedStyles(theme);
27
21
 
28
- const pressableStyle = useCallback(
29
- ({ pressed }: PressableStateCallbackType): StyleProp<ViewStyle> => {
30
- const pressedStateStyle =
31
- typeof style === 'function' ? style({ pressed }) : style;
32
-
33
- return [
34
- themedStyle.container,
35
- themedStyle[`container${capitalize(variant)}`],
36
- disabled ? themedStyle.disabled : null,
37
- pressed ? themedStyle.pressed : null,
38
- pressedStateStyle,
39
- ];
40
- },
41
- [disabled, style, themedStyle, variant]
22
+ const containerStyle: ViewStyle = useMemo(
23
+ (): ViewStyle => ({
24
+ ...themedStyle.container,
25
+ ...themedStyle[`container${capitalize(variant)}`],
26
+ ...(disabled && themedStyle.disabled),
27
+ }),
28
+ [disabled, themedStyle, variant]
42
29
  );
43
30
 
31
+ const pressableStyle = usePressableContainerStyles({
32
+ overrideStyle: style,
33
+ containerStyle,
34
+ pressedStyle: themedStyle.pressed,
35
+ });
36
+
44
37
  const buttonTextStyle: TextStyle = useMemo(
45
38
  (): TextStyle => ({
46
39
  ...themedStyle.text,
@@ -20,17 +20,14 @@ exports[`Button applies theme and style props 1`] = `
20
20
  Object {
21
21
  "alignItems": "center",
22
22
  "backgroundColor": "transparent",
23
+ "borderColor": "hsl(210, 10%, 58%)",
23
24
  "borderRadius": 4,
25
+ "borderWidth": 1,
24
26
  "justifyContent": "center",
25
27
  "paddingHorizontal": 16,
26
28
  "paddingVertical": 12,
27
29
  },
28
- Object {
29
- "borderColor": "hsl(210, 10%, 58%)",
30
- "borderWidth": 1,
31
- },
32
- null,
33
- null,
30
+ undefined,
34
31
  Object {
35
32
  "backgroundColor": "blue",
36
33
  },
@@ -77,17 +74,14 @@ exports[`Button renders as expected with a component passed as children 1`] = `
77
74
  Object {
78
75
  "alignItems": "center",
79
76
  "backgroundColor": "transparent",
77
+ "borderColor": "hsl(210, 10%, 58%)",
80
78
  "borderRadius": 4,
79
+ "borderWidth": 1,
81
80
  "justifyContent": "center",
82
81
  "paddingHorizontal": 16,
83
82
  "paddingVertical": 12,
84
83
  },
85
- Object {
86
- "borderColor": "hsl(210, 10%, 58%)",
87
- "borderWidth": 1,
88
- },
89
- null,
90
- null,
84
+ undefined,
91
85
  undefined,
92
86
  ]
93
87
  }
@@ -118,17 +112,14 @@ exports[`Button renders as expected with a string passed as children 1`] = `
118
112
  Object {
119
113
  "alignItems": "center",
120
114
  "backgroundColor": "transparent",
115
+ "borderColor": "hsl(210, 10%, 58%)",
121
116
  "borderRadius": 4,
117
+ "borderWidth": 1,
122
118
  "justifyContent": "center",
123
119
  "paddingHorizontal": 16,
124
120
  "paddingVertical": 12,
125
121
  },
126
- Object {
127
- "borderColor": "hsl(210, 10%, 58%)",
128
- "borderWidth": 1,
129
- },
130
- null,
131
- null,
122
+ undefined,
132
123
  undefined,
133
124
  ]
134
125
  }
@@ -14,6 +14,7 @@ export const CLOSE_BUTTON_TEST_ID =
14
14
 
15
15
  export default function ErrorMessage({
16
16
  children,
17
+ iconStyle,
17
18
  labelStyle,
18
19
  onDismiss,
19
20
  style,
@@ -28,7 +29,11 @@ export default function ErrorMessage({
28
29
  accessibilityRole="alert"
29
30
  style={[themedStyle.container, style]}
30
31
  >
31
- <Icon size={20} source={icons.error} style={themedStyle.icon} />
32
+ <Icon
33
+ size={20}
34
+ source={icons.error}
35
+ style={[themedStyle.icon, iconStyle]}
36
+ />
32
37
  <Text style={[themedStyle.label, labelStyle]}>{children}</Text>
33
38
  {onDismiss ? (
34
39
  <IconButton