@pagopa/io-app-design-system 5.3.9 → 5.4.1

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 (253) hide show
  1. package/README.md +3 -2
  2. package/lib/commonjs/components/accordion/AccordionItem.js +4 -2
  3. package/lib/commonjs/components/accordion/AccordionItem.js.map +1 -1
  4. package/lib/commonjs/components/alert/Alert.js +5 -11
  5. package/lib/commonjs/components/alert/Alert.js.map +1 -1
  6. package/lib/commonjs/components/alert/AlertEdgeToEdge.js +3 -2
  7. package/lib/commonjs/components/alert/AlertEdgeToEdge.js.map +1 -1
  8. package/lib/commonjs/components/alert/AlertEdgeToEdgeWrapper.js +3 -2
  9. package/lib/commonjs/components/alert/AlertEdgeToEdgeWrapper.js.map +1 -1
  10. package/lib/commonjs/components/buttons/ButtonLink.js +5 -2
  11. package/lib/commonjs/components/buttons/ButtonLink.js.map +1 -1
  12. package/lib/commonjs/components/buttons/ButtonOutline.js +20 -15
  13. package/lib/commonjs/components/buttons/ButtonOutline.js.map +1 -1
  14. package/lib/commonjs/components/buttons/ButtonSolid.js +4 -1
  15. package/lib/commonjs/components/buttons/ButtonSolid.js.map +1 -1
  16. package/lib/commonjs/components/buttons/IOButton/IOButton.js +230 -0
  17. package/lib/commonjs/components/buttons/IOButton/IOButton.js.map +1 -0
  18. package/lib/commonjs/components/buttons/IOButton/__test__/IOButton.test.js +43 -0
  19. package/lib/commonjs/components/buttons/IOButton/__test__/IOButton.test.js.map +1 -0
  20. package/lib/commonjs/components/buttons/IOButton/__test__/__snapshots__/IOButton.test.tsx.snap +391 -0
  21. package/lib/commonjs/components/buttons/IOButton/index.js +17 -0
  22. package/lib/commonjs/components/buttons/IOButton/index.js.map +1 -0
  23. package/lib/commonjs/components/buttons/IOButton/styles.js +166 -0
  24. package/lib/commonjs/components/buttons/IOButton/styles.js.map +1 -0
  25. package/lib/commonjs/components/buttons/IconButton.js +2 -3
  26. package/lib/commonjs/components/buttons/IconButton.js.map +1 -1
  27. package/lib/commonjs/components/buttons/IconButtonContained.js +1 -2
  28. package/lib/commonjs/components/buttons/IconButtonContained.js.map +1 -1
  29. package/lib/commonjs/components/buttons/__test__/__snapshots__/button.test.tsx.snap +6 -402
  30. package/lib/commonjs/components/buttons/__test__/button.test.js +0 -24
  31. package/lib/commonjs/components/buttons/__test__/button.test.js.map +1 -1
  32. package/lib/commonjs/components/buttons/index.js +11 -0
  33. package/lib/commonjs/components/buttons/index.js.map +1 -1
  34. package/lib/commonjs/components/claimsSelector/__test__/__snapshots__/ClaimsSelector.test.tsx.snap +13 -30
  35. package/lib/commonjs/components/icons/Icon.js +11 -9
  36. package/lib/commonjs/components/icons/Icon.js.map +1 -1
  37. package/lib/commonjs/components/layout/FooterActions.js +10 -9
  38. package/lib/commonjs/components/layout/FooterActions.js.map +1 -1
  39. package/lib/commonjs/components/layout/FooterActionsInline.js +8 -8
  40. package/lib/commonjs/components/layout/FooterActionsInline.js.map +1 -1
  41. package/lib/commonjs/components/layout/GradientBottomActions.js +8 -8
  42. package/lib/commonjs/components/layout/GradientBottomActions.js.map +1 -1
  43. package/lib/commonjs/components/layout/GradientScrollView.js.map +1 -1
  44. package/lib/commonjs/components/layout/ModalBSHeader.js +3 -1
  45. package/lib/commonjs/components/layout/ModalBSHeader.js.map +1 -1
  46. package/lib/commonjs/components/listitems/ListItemAmount.js +3 -1
  47. package/lib/commonjs/components/listitems/ListItemAmount.js.map +1 -1
  48. package/lib/commonjs/components/listitems/ListItemCheckbox.js +3 -2
  49. package/lib/commonjs/components/listitems/ListItemCheckbox.js.map +1 -1
  50. package/lib/commonjs/components/listitems/ListItemHeader.js +4 -2
  51. package/lib/commonjs/components/listitems/ListItemHeader.js.map +1 -1
  52. package/lib/commonjs/components/listitems/ListItemInfo.js +3 -1
  53. package/lib/commonjs/components/listitems/ListItemInfo.js.map +1 -1
  54. package/lib/commonjs/components/listitems/ListItemInfoCopy.js +3 -1
  55. package/lib/commonjs/components/listitems/ListItemInfoCopy.js.map +1 -1
  56. package/lib/commonjs/components/listitems/ListItemNav.js +1 -1
  57. package/lib/commonjs/components/listitems/ListItemNav.js.map +1 -1
  58. package/lib/commonjs/components/listitems/ListItemNavAlert.js +3 -1
  59. package/lib/commonjs/components/listitems/ListItemNavAlert.js.map +1 -1
  60. package/lib/commonjs/components/listitems/ListItemRadio.js +10 -2
  61. package/lib/commonjs/components/listitems/ListItemRadio.js.map +1 -1
  62. package/lib/commonjs/components/listitems/__test__/__snapshots__/listitem.test.tsx.snap +10 -40
  63. package/lib/commonjs/components/loadingSpinner/LoadingSpinner.js +6 -6
  64. package/lib/commonjs/components/loadingSpinner/LoadingSpinner.js.map +1 -1
  65. package/lib/commonjs/components/numberpad/NumberButton.js +15 -2
  66. package/lib/commonjs/components/numberpad/NumberButton.js.map +1 -1
  67. package/lib/commonjs/components/numberpad/NumberPad.js +9 -6
  68. package/lib/commonjs/components/numberpad/NumberPad.js.map +1 -1
  69. package/lib/commonjs/components/numberpad/__test__/__snapshots__/NumberPad.test.tsx.snap +42 -96
  70. package/lib/commonjs/components/otpInput/OTPInput.js +3 -3
  71. package/lib/commonjs/components/otpInput/OTPInput.js.map +1 -1
  72. package/lib/commonjs/components/radio/RadioButtonLabel.js +3 -3
  73. package/lib/commonjs/components/radio/RadioButtonLabel.js.map +1 -1
  74. package/lib/commonjs/components/stepper/Stepper.js +5 -2
  75. package/lib/commonjs/components/stepper/Stepper.js.map +1 -1
  76. package/lib/commonjs/components/typography/IOText.js +4 -1
  77. package/lib/commonjs/components/typography/IOText.js.map +1 -1
  78. package/lib/commonjs/core/IOStyles.js +3 -53
  79. package/lib/commonjs/core/IOStyles.js.map +1 -1
  80. package/lib/module/components/accordion/AccordionItem.js +5 -3
  81. package/lib/module/components/accordion/AccordionItem.js.map +1 -1
  82. package/lib/module/components/alert/Alert.js +6 -12
  83. package/lib/module/components/alert/Alert.js.map +1 -1
  84. package/lib/module/components/alert/AlertEdgeToEdge.js +3 -2
  85. package/lib/module/components/alert/AlertEdgeToEdge.js.map +1 -1
  86. package/lib/module/components/alert/AlertEdgeToEdgeWrapper.js +3 -2
  87. package/lib/module/components/alert/AlertEdgeToEdgeWrapper.js.map +1 -1
  88. package/lib/module/components/buttons/ButtonLink.js +6 -3
  89. package/lib/module/components/buttons/ButtonLink.js.map +1 -1
  90. package/lib/module/components/buttons/ButtonOutline.js +21 -16
  91. package/lib/module/components/buttons/ButtonOutline.js.map +1 -1
  92. package/lib/module/components/buttons/ButtonSolid.js +4 -1
  93. package/lib/module/components/buttons/ButtonSolid.js.map +1 -1
  94. package/lib/module/components/buttons/IOButton/IOButton.js +223 -0
  95. package/lib/module/components/buttons/IOButton/IOButton.js.map +1 -0
  96. package/lib/module/components/buttons/IOButton/__test__/IOButton.test.js +40 -0
  97. package/lib/module/components/buttons/IOButton/__test__/IOButton.test.js.map +1 -0
  98. package/lib/module/components/buttons/IOButton/__test__/__snapshots__/IOButton.test.tsx.snap +391 -0
  99. package/lib/module/components/buttons/IOButton/index.js +4 -0
  100. package/lib/module/components/buttons/IOButton/index.js.map +1 -0
  101. package/lib/module/components/buttons/IOButton/styles.js +160 -0
  102. package/lib/module/components/buttons/IOButton/styles.js.map +1 -0
  103. package/lib/module/components/buttons/IconButton.js +4 -5
  104. package/lib/module/components/buttons/IconButton.js.map +1 -1
  105. package/lib/module/components/buttons/IconButtonContained.js +2 -3
  106. package/lib/module/components/buttons/IconButtonContained.js.map +1 -1
  107. package/lib/module/components/buttons/__test__/__snapshots__/button.test.tsx.snap +6 -402
  108. package/lib/module/components/buttons/__test__/button.test.js +0 -24
  109. package/lib/module/components/buttons/__test__/button.test.js.map +1 -1
  110. package/lib/module/components/buttons/index.js +1 -0
  111. package/lib/module/components/buttons/index.js.map +1 -1
  112. package/lib/module/components/claimsSelector/__test__/__snapshots__/ClaimsSelector.test.tsx.snap +13 -30
  113. package/lib/module/components/icons/Icon.js +10 -7
  114. package/lib/module/components/icons/Icon.js.map +1 -1
  115. package/lib/module/components/layout/FooterActions.js +11 -10
  116. package/lib/module/components/layout/FooterActions.js.map +1 -1
  117. package/lib/module/components/layout/FooterActionsInline.js +9 -9
  118. package/lib/module/components/layout/FooterActionsInline.js.map +1 -1
  119. package/lib/module/components/layout/GradientBottomActions.js +9 -9
  120. package/lib/module/components/layout/GradientBottomActions.js.map +1 -1
  121. package/lib/module/components/layout/GradientScrollView.js.map +1 -1
  122. package/lib/module/components/layout/ModalBSHeader.js +4 -2
  123. package/lib/module/components/layout/ModalBSHeader.js.map +1 -1
  124. package/lib/module/components/listitems/ListItemAmount.js +4 -2
  125. package/lib/module/components/listitems/ListItemAmount.js.map +1 -1
  126. package/lib/module/components/listitems/ListItemCheckbox.js +4 -3
  127. package/lib/module/components/listitems/ListItemCheckbox.js.map +1 -1
  128. package/lib/module/components/listitems/ListItemHeader.js +5 -3
  129. package/lib/module/components/listitems/ListItemHeader.js.map +1 -1
  130. package/lib/module/components/listitems/ListItemInfo.js +4 -2
  131. package/lib/module/components/listitems/ListItemInfo.js.map +1 -1
  132. package/lib/module/components/listitems/ListItemInfoCopy.js +4 -2
  133. package/lib/module/components/listitems/ListItemInfoCopy.js.map +1 -1
  134. package/lib/module/components/listitems/ListItemNav.js +2 -2
  135. package/lib/module/components/listitems/ListItemNav.js.map +1 -1
  136. package/lib/module/components/listitems/ListItemNavAlert.js +4 -2
  137. package/lib/module/components/listitems/ListItemNavAlert.js.map +1 -1
  138. package/lib/module/components/listitems/ListItemRadio.js +11 -3
  139. package/lib/module/components/listitems/ListItemRadio.js.map +1 -1
  140. package/lib/module/components/listitems/__test__/__snapshots__/listitem.test.tsx.snap +10 -40
  141. package/lib/module/components/loadingSpinner/LoadingSpinner.js +6 -6
  142. package/lib/module/components/loadingSpinner/LoadingSpinner.js.map +1 -1
  143. package/lib/module/components/numberpad/NumberButton.js +16 -3
  144. package/lib/module/components/numberpad/NumberButton.js.map +1 -1
  145. package/lib/module/components/numberpad/NumberPad.js +10 -7
  146. package/lib/module/components/numberpad/NumberPad.js.map +1 -1
  147. package/lib/module/components/numberpad/__test__/__snapshots__/NumberPad.test.tsx.snap +42 -96
  148. package/lib/module/components/otpInput/OTPInput.js +3 -3
  149. package/lib/module/components/otpInput/OTPInput.js.map +1 -1
  150. package/lib/module/components/radio/RadioButtonLabel.js +3 -3
  151. package/lib/module/components/radio/RadioButtonLabel.js.map +1 -1
  152. package/lib/module/components/stepper/Stepper.js +6 -3
  153. package/lib/module/components/stepper/Stepper.js.map +1 -1
  154. package/lib/module/components/typography/IOText.js +2 -0
  155. package/lib/module/components/typography/IOText.js.map +1 -1
  156. package/lib/module/core/IOStyles.js +3 -53
  157. package/lib/module/core/IOStyles.js.map +1 -1
  158. package/lib/typescript/components/accordion/AccordionItem.d.ts.map +1 -1
  159. package/lib/typescript/components/alert/Alert.d.ts.map +1 -1
  160. package/lib/typescript/components/alert/AlertEdgeToEdge.d.ts.map +1 -1
  161. package/lib/typescript/components/alert/AlertEdgeToEdgeWrapper.d.ts.map +1 -1
  162. package/lib/typescript/components/buttons/ButtonLink.d.ts +3 -0
  163. package/lib/typescript/components/buttons/ButtonLink.d.ts.map +1 -1
  164. package/lib/typescript/components/buttons/ButtonOutline.d.ts +3 -0
  165. package/lib/typescript/components/buttons/ButtonOutline.d.ts.map +1 -1
  166. package/lib/typescript/components/buttons/ButtonSolid.d.ts +3 -0
  167. package/lib/typescript/components/buttons/ButtonSolid.d.ts.map +1 -1
  168. package/lib/typescript/components/buttons/IOButton/IOButton.d.ts +57 -0
  169. package/lib/typescript/components/buttons/IOButton/IOButton.d.ts.map +1 -0
  170. package/lib/typescript/components/buttons/IOButton/__test__/IOButton.test.d.ts +2 -0
  171. package/lib/typescript/components/buttons/IOButton/__test__/IOButton.test.d.ts.map +1 -0
  172. package/lib/typescript/components/buttons/IOButton/index.d.ts +2 -0
  173. package/lib/typescript/components/buttons/IOButton/index.d.ts.map +1 -0
  174. package/lib/typescript/components/buttons/IOButton/styles.d.ts +35 -0
  175. package/lib/typescript/components/buttons/IOButton/styles.d.ts.map +1 -0
  176. package/lib/typescript/components/buttons/IconButton.d.ts.map +1 -1
  177. package/lib/typescript/components/buttons/IconButtonContained.d.ts.map +1 -1
  178. package/lib/typescript/components/buttons/index.d.ts +1 -0
  179. package/lib/typescript/components/buttons/index.d.ts.map +1 -1
  180. package/lib/typescript/components/icons/Icon.d.ts +1 -4
  181. package/lib/typescript/components/icons/Icon.d.ts.map +1 -1
  182. package/lib/typescript/components/icons/types.d.ts +3 -2
  183. package/lib/typescript/components/icons/types.d.ts.map +1 -1
  184. package/lib/typescript/components/layout/FooterActions.d.ts +10 -8
  185. package/lib/typescript/components/layout/FooterActions.d.ts.map +1 -1
  186. package/lib/typescript/components/layout/FooterActionsInline.d.ts +5 -4
  187. package/lib/typescript/components/layout/FooterActionsInline.d.ts.map +1 -1
  188. package/lib/typescript/components/layout/GradientBottomActions.d.ts +12 -6
  189. package/lib/typescript/components/layout/GradientBottomActions.d.ts.map +1 -1
  190. package/lib/typescript/components/layout/GradientScrollView.d.ts.map +1 -1
  191. package/lib/typescript/components/listitems/ListItemAmount.d.ts.map +1 -1
  192. package/lib/typescript/components/listitems/ListItemCheckbox.d.ts.map +1 -1
  193. package/lib/typescript/components/listitems/ListItemHeader.d.ts.map +1 -1
  194. package/lib/typescript/components/listitems/ListItemInfo.d.ts.map +1 -1
  195. package/lib/typescript/components/listitems/ListItemInfoCopy.d.ts.map +1 -1
  196. package/lib/typescript/components/listitems/ListItemNavAlert.d.ts.map +1 -1
  197. package/lib/typescript/components/listitems/ListItemRadio.d.ts.map +1 -1
  198. package/lib/typescript/components/loadingSpinner/LoadingSpinner.d.ts +2 -2
  199. package/lib/typescript/components/loadingSpinner/LoadingSpinner.d.ts.map +1 -1
  200. package/lib/typescript/components/numberpad/NumberButton.d.ts +11 -0
  201. package/lib/typescript/components/numberpad/NumberButton.d.ts.map +1 -1
  202. package/lib/typescript/components/numberpad/NumberPad.d.ts.map +1 -1
  203. package/lib/typescript/components/otpInput/OTPInput.d.ts.map +1 -1
  204. package/lib/typescript/components/radio/RadioButtonLabel.d.ts.map +1 -1
  205. package/lib/typescript/components/stepper/Stepper.d.ts.map +1 -1
  206. package/lib/typescript/components/typography/IOText.d.ts +1 -0
  207. package/lib/typescript/components/typography/IOText.d.ts.map +1 -1
  208. package/lib/typescript/core/IOStyles.d.ts +0 -47
  209. package/lib/typescript/core/IOStyles.d.ts.map +1 -1
  210. package/package.json +1 -1
  211. package/src/components/accordion/AccordionItem.tsx +7 -14
  212. package/src/components/alert/Alert.tsx +7 -21
  213. package/src/components/alert/AlertEdgeToEdge.tsx +1 -2
  214. package/src/components/alert/AlertEdgeToEdgeWrapper.tsx +1 -2
  215. package/src/components/buttons/ButtonLink.tsx +6 -6
  216. package/src/components/buttons/ButtonOutline.tsx +21 -21
  217. package/src/components/buttons/ButtonSolid.tsx +4 -1
  218. package/src/components/buttons/IOButton/IOButton.tsx +363 -0
  219. package/src/components/buttons/IOButton/__test__/IOButton.test.tsx +46 -0
  220. package/src/components/buttons/IOButton/__test__/__snapshots__/IOButton.test.tsx.snap +391 -0
  221. package/src/components/buttons/IOButton/index.tsx +1 -0
  222. package/src/components/buttons/IOButton/styles.tsx +228 -0
  223. package/src/components/buttons/IconButton.tsx +4 -9
  224. package/src/components/buttons/IconButtonContained.tsx +3 -6
  225. package/src/components/buttons/__test__/__snapshots__/button.test.tsx.snap +6 -402
  226. package/src/components/buttons/__test__/button.test.tsx +1 -33
  227. package/src/components/buttons/index.tsx +1 -0
  228. package/src/components/claimsSelector/__test__/__snapshots__/ClaimsSelector.test.tsx.snap +13 -30
  229. package/src/components/icons/Icon.tsx +12 -3
  230. package/src/components/icons/types.ts +3 -2
  231. package/src/components/layout/FooterActions.tsx +26 -14
  232. package/src/components/layout/FooterActionsInline.tsx +19 -12
  233. package/src/components/layout/GradientBottomActions.tsx +17 -18
  234. package/src/components/layout/GradientScrollView.tsx +2 -1
  235. package/src/components/layout/ModalBSHeader.tsx +2 -2
  236. package/src/components/listitems/ListItemAmount.tsx +1 -2
  237. package/src/components/listitems/ListItemCheckbox.tsx +8 -11
  238. package/src/components/listitems/ListItemHeader.tsx +2 -3
  239. package/src/components/listitems/ListItemInfo.tsx +1 -2
  240. package/src/components/listitems/ListItemInfoCopy.tsx +1 -2
  241. package/src/components/listitems/ListItemNav.tsx +1 -1
  242. package/src/components/listitems/ListItemNavAlert.tsx +1 -2
  243. package/src/components/listitems/ListItemRadio.tsx +7 -7
  244. package/src/components/listitems/__test__/__snapshots__/listitem.test.tsx.snap +10 -40
  245. package/src/components/loadingSpinner/LoadingSpinner.tsx +8 -8
  246. package/src/components/numberpad/NumberButton.tsx +18 -11
  247. package/src/components/numberpad/NumberPad.tsx +8 -10
  248. package/src/components/numberpad/__test__/__snapshots__/NumberPad.test.tsx.snap +42 -96
  249. package/src/components/otpInput/OTPInput.tsx +1 -2
  250. package/src/components/radio/RadioButtonLabel.tsx +7 -10
  251. package/src/components/stepper/Stepper.tsx +7 -12
  252. package/src/components/typography/IOText.tsx +3 -0
  253. package/src/core/IOStyles.ts +3 -55
@@ -0,0 +1,363 @@
1
+ import React, {
2
+ ComponentProps,
3
+ forwardRef,
4
+ useCallback,
5
+ useEffect,
6
+ useRef
7
+ } from "react";
8
+ import {
9
+ AccessibilityRole,
10
+ ColorValue,
11
+ GestureResponderEvent,
12
+ Pressable,
13
+ PressableProps,
14
+ StyleSheet,
15
+ TextProps,
16
+ TextStyle,
17
+ View,
18
+ ViewStyle
19
+ } from "react-native";
20
+ import ReactNativeHapticFeedback from "react-native-haptic-feedback";
21
+ import Animated, { useReducedMotion } from "react-native-reanimated";
22
+ import {
23
+ enterTransitionInnerContent,
24
+ enterTransitionInnerContentSmall,
25
+ exitTransitionInnerContent,
26
+ useIONewTypeface
27
+ } from "../../../core";
28
+ import { useScaleAnimation } from "../../../hooks";
29
+ import { WithTestID } from "../../../utils/types";
30
+ import {
31
+ AnimatedIcon,
32
+ AnimatedIconWithColorTransition,
33
+ IOIconSizeScale,
34
+ IOIcons
35
+ } from "../../icons";
36
+ import { LoadingSpinner } from "../../loadingSpinner";
37
+ import { AnimatedIOText } from "../../typography";
38
+ import {
39
+ buttonTextFontSize,
40
+ buttonTextLineHeight
41
+ } from "../../typography/ButtonText";
42
+ import { useButtonAnimatedStyles, useButtonColorMap } from "./styles";
43
+
44
+ export type IOButtonColor = "primary" | "danger" | "contrast";
45
+ export type IOButtonVariant = "solid" | "outline" | "link";
46
+
47
+ export type IOButtonBlockSpecificProps = Omit<
48
+ ComponentProps<typeof IOButton>,
49
+ "numberOfLines" | "textAlign"
50
+ >;
51
+
52
+ export type IOButtonLinkSpecificProps = Omit<
53
+ ComponentProps<typeof IOButton>,
54
+ "fullWidth" | "loading"
55
+ >;
56
+
57
+ type IOButtonSpecificProps =
58
+ | {
59
+ variant?: "link";
60
+ numberOfLines?: TextProps["numberOfLines"];
61
+ textAlign?: TextStyle["textAlign"];
62
+ fullWidth?: never;
63
+ loading?: never;
64
+ }
65
+ | {
66
+ variant?: "solid" | "outline";
67
+ fullWidth?: boolean;
68
+ loading?: boolean;
69
+ numberOfLines?: never;
70
+ textAlign?: never;
71
+ };
72
+
73
+ export type IOButtonProps = WithTestID<
74
+ IOButtonSpecificProps & {
75
+ /**
76
+ * @default primary
77
+ */
78
+ color?: IOButtonColor;
79
+ label: string;
80
+ icon?: IOIcons;
81
+ /**
82
+ * @default false
83
+ */
84
+ fullWidth?: boolean;
85
+ /**
86
+ * @default false
87
+ */
88
+ loading?: boolean;
89
+ /**
90
+ * @default start
91
+ */
92
+ iconPosition?: "start" | "end";
93
+ /**
94
+ * @default 1
95
+ */
96
+ numberOfLines?: number;
97
+ /**
98
+ * @default auto
99
+ */
100
+ textAlign?: TextStyle["textAlign"];
101
+ onPress: (event: GestureResponderEvent) => void;
102
+ /**
103
+ * @default button
104
+ */
105
+ accessibilityRole?: Extract<AccessibilityRole, "button" | "link">;
106
+ } & Pick<
107
+ ComponentProps<typeof Pressable>,
108
+ "disabled" | "accessibilityLabel" | "accessibilityHint"
109
+ >
110
+ >;
111
+
112
+ export const IOButton = forwardRef<View, IOButtonProps>(
113
+ (
114
+ {
115
+ variant = "solid",
116
+ color = "primary",
117
+ label,
118
+ fullWidth = false,
119
+ disabled = false,
120
+ loading = false,
121
+ numberOfLines = 1,
122
+ textAlign = "auto",
123
+ icon,
124
+ iconPosition = "start",
125
+ onPress,
126
+ accessibilityLabel,
127
+ accessibilityHint,
128
+ accessibilityRole = "button",
129
+ testID
130
+ },
131
+ ref
132
+ ) => {
133
+ const mapColorStates = useButtonColorMap(variant);
134
+ const { progress, onPressIn, onPressOut, scaleAnimatedStyle } =
135
+ useScaleAnimation();
136
+ const { buttonAnimatedStyle, labelAnimatedStyle, iconColorAnimatedStyle } =
137
+ useButtonAnimatedStyles(variant, color, progress);
138
+ const reducedMotion = useReducedMotion();
139
+ const { newTypefaceEnabled } = useIONewTypeface();
140
+
141
+ const isLinkButton = variant === "link";
142
+
143
+ // ---------------------------------------
144
+ // VISUAL ATTRIBUTES
145
+ // ---------------------------------------
146
+ const btnIconSizeMap: Record<IOButtonVariant, IOIconSizeScale> = {
147
+ solid: 20,
148
+ outline: 20,
149
+ link: 24
150
+ };
151
+
152
+ const btnBorderWidthMap: Record<IOButtonVariant, ViewStyle["borderWidth"]> =
153
+ {
154
+ solid: 0,
155
+ outline: 2,
156
+ link: 0
157
+ };
158
+
159
+ const btnPaddingHorizontalMap: Record<
160
+ string,
161
+ ViewStyle["paddingHorizontal"]
162
+ > = {
163
+ default: 24,
164
+ fullWidth: 16,
165
+ link: 0
166
+ };
167
+
168
+ const btnLinkHitSlop: PressableProps["hitSlop"] = {
169
+ top: 14,
170
+ right: 24,
171
+ bottom: 14,
172
+ left: 24
173
+ };
174
+
175
+ const btnIconSize = btnIconSizeMap[variant];
176
+ const btnBorderWidth = btnBorderWidthMap[variant];
177
+ const btnBorderRadius = 8;
178
+ const btnSizeDefault = 48;
179
+
180
+ const ICON_MARGIN = 8;
181
+ const DISABLED_OPACITY = 0.5;
182
+
183
+ // Background color
184
+ const backgroundColor: ColorValue = disabled
185
+ ? mapColorStates[color].background.disabled
186
+ : mapColorStates[color].background.default;
187
+
188
+ // Label & Icons colors
189
+ const foregroundColor: ColorValue = disabled
190
+ ? mapColorStates[color]?.foreground?.disabled
191
+ : mapColorStates[color]?.foreground?.default;
192
+
193
+ // ---------------------------------------
194
+ // BUTTON INNER LOGIC
195
+ // ---------------------------------------
196
+
197
+ /* Prevent the component from triggering the `isEntering' transition
198
+ on the on the first render. Solution from this discussion:
199
+ https://github.com/software-mansion/react-native-reanimated/discussions/2513
200
+ */
201
+ const isMounted = useRef<boolean>(false);
202
+
203
+ useEffect(() => {
204
+ // eslint-disable-next-line functional/immutable-data
205
+ isMounted.current = true;
206
+ }, []);
207
+
208
+ const handleOnPress = useCallback(
209
+ (event: GestureResponderEvent) => {
210
+ /* Don't call `onPress` if the button is
211
+ in loading state */
212
+ if (loading) {
213
+ return;
214
+ }
215
+ ReactNativeHapticFeedback.trigger("impactLight");
216
+ onPress(event);
217
+ },
218
+ [loading, onPress]
219
+ );
220
+
221
+ // ---------------------------------------
222
+ // BUTTON INNER CONTENT
223
+ // ---------------------------------------
224
+ const renderButtonContent = () => (
225
+ <>
226
+ {loading && (
227
+ <Animated.View
228
+ style={styles.buttonInner}
229
+ entering={
230
+ isMounted.current ? enterTransitionInnerContentSmall : undefined
231
+ }
232
+ exiting={exitTransitionInnerContent}
233
+ >
234
+ <LoadingSpinner color={foregroundColor} />
235
+ </Animated.View>
236
+ )}
237
+
238
+ {!loading && (
239
+ <Animated.View
240
+ style={[
241
+ styles.buttonInner,
242
+ { columnGap: ICON_MARGIN },
243
+ iconPosition === "end" && { flexDirection: "row-reverse" }
244
+ ]}
245
+ entering={
246
+ isMounted.current ? enterTransitionInnerContent : undefined
247
+ }
248
+ >
249
+ {icon &&
250
+ (!disabled ? (
251
+ <AnimatedIconWithColorTransition
252
+ allowFontScaling
253
+ name={icon}
254
+ animatedProps={iconColorAnimatedStyle}
255
+ size={btnIconSize}
256
+ />
257
+ ) : (
258
+ <AnimatedIcon
259
+ allowFontScaling
260
+ name={icon}
261
+ color={mapColorStates[color]?.foreground?.disabled}
262
+ size={btnIconSize}
263
+ />
264
+ ))}
265
+ <AnimatedIOText
266
+ font={newTypefaceEnabled ? "Titillio" : "TitilliumSansPro"}
267
+ weight={"Semibold"}
268
+ size={buttonTextFontSize}
269
+ lineHeight={isLinkButton ? buttonTextLineHeight : undefined}
270
+ accessible={false}
271
+ accessibilityElementsHidden
272
+ importantForAccessibility="no-hide-descendants"
273
+ numberOfLines={numberOfLines}
274
+ ellipsizeMode="tail"
275
+ style={[
276
+ { textAlign },
277
+ disabled
278
+ ? { color: mapColorStates[color]?.foreground?.disabled }
279
+ : { ...labelAnimatedStyle }
280
+ ]}
281
+ >
282
+ {label}
283
+ </AnimatedIOText>
284
+ </Animated.View>
285
+ )}
286
+ </>
287
+ );
288
+
289
+ return (
290
+ <Pressable
291
+ ref={ref}
292
+ accessible={true}
293
+ // Using || operator because empty string is not an accepted value
294
+ accessibilityLabel={accessibilityLabel || label}
295
+ accessibilityHint={accessibilityHint}
296
+ accessibilityRole={accessibilityRole}
297
+ accessibilityState={{
298
+ busy: loading,
299
+ disabled: disabled || false
300
+ }}
301
+ onPress={handleOnPress}
302
+ onPressIn={onPressIn}
303
+ onPressOut={onPressOut}
304
+ disabled={disabled}
305
+ hitSlop={isLinkButton ? btnLinkHitSlop : undefined}
306
+ style={
307
+ isLinkButton
308
+ ? { alignSelf: "flex-start" }
309
+ : fullWidth
310
+ ? { flexShrink: 0, alignSelf: "stretch" }
311
+ : { flexShrink: 1, alignSelf: "auto" }
312
+ }
313
+ testID={testID}
314
+ >
315
+ <Animated.View
316
+ style={[
317
+ styles.button,
318
+ {
319
+ paddingHorizontal: isLinkButton
320
+ ? btnPaddingHorizontalMap.link
321
+ : fullWidth
322
+ ? btnPaddingHorizontalMap.fullWidth
323
+ : btnPaddingHorizontalMap.default
324
+ },
325
+ {
326
+ height: isLinkButton ? undefined : btnSizeDefault,
327
+ backgroundColor,
328
+ borderWidth: btnBorderWidth,
329
+ borderRadius: btnBorderRadius,
330
+ borderColor: foregroundColor
331
+ },
332
+ disabled ? { opacity: DISABLED_OPACITY } : {},
333
+ /* Prevent Reanimated from overriding background colors
334
+ if button is disabled */
335
+ !disabled && !reducedMotion && scaleAnimatedStyle,
336
+ !disabled && buttonAnimatedStyle
337
+ ]}
338
+ >
339
+ {renderButtonContent()}
340
+ </Animated.View>
341
+ </Pressable>
342
+ );
343
+ }
344
+ );
345
+
346
+ const styles = StyleSheet.create({
347
+ button: {
348
+ flexDirection: "row",
349
+ alignItems: "center",
350
+ justifyContent: "center",
351
+ textAlignVertical: "center", // Prop supported on Android only
352
+ borderCurve: "continuous",
353
+ overflow: "hidden",
354
+ elevation: 0
355
+ },
356
+ buttonInner: {
357
+ flexDirection: "row",
358
+ alignItems: "center",
359
+ justifyContent: "center"
360
+ }
361
+ });
362
+
363
+ export default IOButton;
@@ -0,0 +1,46 @@
1
+ import React from "react";
2
+ import { Alert } from "react-native";
3
+ import * as TestRenderer from "react-test-renderer";
4
+ import IOButton from "../IOButton";
5
+
6
+ const onButtonPress = () => {
7
+ Alert.alert("Alert", "Action triggered");
8
+ };
9
+
10
+ describe("Test Buttons Components", () => {
11
+ it("IOButton Snapshot · Solid variant", () => {
12
+ const buttonSolid = TestRenderer.create(
13
+ <IOButton
14
+ variant="solid"
15
+ label={"label"}
16
+ accessibilityLabel={"accessibilityLabel"}
17
+ onPress={onButtonPress}
18
+ ></IOButton>
19
+ ).toJSON();
20
+ expect(buttonSolid).toMatchSnapshot();
21
+ });
22
+
23
+ it("IOButton Snapshot · Link variant", () => {
24
+ const buttonLink = TestRenderer.create(
25
+ <IOButton
26
+ variant="link"
27
+ label={"label"}
28
+ accessibilityLabel={"accessibilityLabel"}
29
+ onPress={onButtonPress}
30
+ ></IOButton>
31
+ ).toJSON();
32
+ expect(buttonLink).toMatchSnapshot();
33
+ });
34
+
35
+ it("IOButton Snapshot · Outline variant", () => {
36
+ const buttonOutline = TestRenderer.create(
37
+ <IOButton
38
+ variant="outline"
39
+ label={"label"}
40
+ accessibilityLabel={"accessibilityLabel"}
41
+ onPress={onButtonPress}
42
+ ></IOButton>
43
+ ).toJSON();
44
+ expect(buttonOutline).toMatchSnapshot();
45
+ });
46
+ });