@jobber/components-native 0.84.4-JOB-134681-8086ad4.25 → 0.84.4-JOB-138679-b1552ab.68

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 (278) hide show
  1. package/dist/package.json +23 -14
  2. package/dist/src/ActionItem/ActionItemGroup.js +1 -1
  3. package/dist/src/AutoLink/components/Link/Link.js +1 -1
  4. package/dist/src/Banner/Banner.js +2 -0
  5. package/dist/src/Banner/components/BannerIcon/BannerIcon.style.js +3 -0
  6. package/dist/src/BottomSheet/BottomSheet.js +2 -2
  7. package/dist/src/Button/components/InternalButtonLoading/InternalButtonLoading.js +0 -1
  8. package/dist/src/ButtonGroup/ButtonGroup.js +1 -1
  9. package/dist/src/ContentOverlay/ContentOverlay.js +5 -7
  10. package/dist/src/ContentOverlay/UNSAFE_WrappedModalize.js +23 -0
  11. package/dist/src/ErrorMessageWrapper/context/ErrorMessageProvider.js +1 -1
  12. package/dist/src/Form/Form.js +5 -2
  13. package/dist/src/Form/components/FormCache/FormCache.js +1 -0
  14. package/dist/src/Form/components/FormMessageBanner/FormMessageBanner.js +1 -1
  15. package/dist/src/Form/context/AtlantisFormContext.js +1 -0
  16. package/dist/src/Form/hooks/useInternalForm.js +6 -3
  17. package/dist/src/FormatFile/components/MediaView/MediaView.js +22 -5
  18. package/dist/src/FormatFile/utils/createUseCreateThumbnail.js +1 -1
  19. package/dist/src/InputCurrency/InputCurrency.js +42 -30
  20. package/dist/src/InputDate/InputDate.js +2 -2
  21. package/dist/src/InputEmail/InputEmail.js +12 -4
  22. package/dist/src/InputFieldWrapper/InputFieldWrapper.js +14 -12
  23. package/dist/src/InputFieldWrapper/InputFieldWrapper.style.js +1 -1
  24. package/dist/src/InputFieldWrapper/components/Prefix/Prefix.js +5 -2
  25. package/dist/src/InputFieldWrapper/components/Suffix/Suffix.js +5 -2
  26. package/dist/src/InputNumber/InputNumber.js +10 -4
  27. package/dist/src/InputPressable/InputPressable.js +20 -8
  28. package/dist/src/InputPressable/InputPressable.style.js +3 -0
  29. package/dist/src/InputSearch/InputSearch.js +1 -1
  30. package/dist/src/InputText/InputText.js +22 -11
  31. package/dist/src/InputText/InputText.style.js +4 -0
  32. package/dist/src/InputTime/InputTime.js +2 -2
  33. package/dist/src/Menu/Menu.js +2 -2
  34. package/dist/src/Select/Select.style.js +1 -0
  35. package/dist/src/Select/components/SelectPressable/SelectPressable.js +1 -1
  36. package/dist/src/Switch/components/BaseSwitch/BaseSwitch.js +7 -1
  37. package/dist/src/Typography/Typography.js +16 -5
  38. package/dist/src/hooks/useAtlantisI18n/locales/en.json +1 -0
  39. package/dist/src/hooks/useAtlantisI18n/locales/es.json +1 -0
  40. package/dist/src/hooks/useFormController.js +5 -14
  41. package/dist/tsconfig.build.json +7 -0
  42. package/dist/tsconfig.build.tsbuildinfo +1 -0
  43. package/dist/tsconfig.json +4 -6
  44. package/dist/types/src/ActionItem/ActionItem.d.ts +2 -1
  45. package/dist/types/src/ActionItem/ActionItemGroup.d.ts +2 -1
  46. package/dist/types/src/ActionItem/components/ActionItemContainer.d.ts +2 -1
  47. package/dist/types/src/ActionLabel/ActionLabel.d.ts +4 -3
  48. package/dist/types/src/ActivityIndicator/ActivityIndicator.d.ts +2 -1
  49. package/dist/types/src/AutoLink/AutoLink.d.ts +2 -1
  50. package/dist/types/src/AutoLink/components/ComposeTextWithLinks/ComposeTextWithLinks.d.ts +2 -1
  51. package/dist/types/src/AutoLink/components/Link/Link.d.ts +2 -1
  52. package/dist/types/src/Banner/Banner.d.ts +2 -1
  53. package/dist/types/src/Banner/components/BannerIcon/BannerIcon.d.ts +2 -1
  54. package/dist/types/src/Banner/components/BannerIcon/BannerIcon.style.d.ts +3 -0
  55. package/dist/types/src/Banner/types.d.ts +1 -1
  56. package/dist/types/src/BottomSheet/BottomSheet.d.ts +1 -1
  57. package/dist/types/src/BottomSheet/components/BottomSheetOption/BottomSheetOption.d.ts +2 -1
  58. package/dist/types/src/Button/Button.d.ts +2 -1
  59. package/dist/types/src/Button/components/InternalButtonLoading/InternalButtonLoading.d.ts +1 -1
  60. package/dist/types/src/ButtonGroup/ButtonGroup.d.ts +2 -1
  61. package/dist/types/src/ButtonGroup/ButtonGroupAction.d.ts +4 -3
  62. package/dist/types/src/ButtonGroup/components/SecondaryActionSheet/SecondaryActionSheet.d.ts +3 -2
  63. package/dist/types/src/Card/Card.d.ts +2 -1
  64. package/dist/types/src/Card/components/InternalCardHeader.d.ts +2 -1
  65. package/dist/types/src/Checkbox/Checkbox.d.ts +2 -1
  66. package/dist/types/src/Checkbox/CheckboxGroup.d.ts +2 -1
  67. package/dist/types/src/Chip/Chip.d.ts +2 -1
  68. package/dist/types/src/Content/Content.d.ts +2 -1
  69. package/dist/types/src/ContentOverlay/ContentOverlay.d.ts +1 -1
  70. package/dist/types/src/ContentOverlay/UNSAFE_WrappedModalize.d.ts +3 -0
  71. package/dist/types/src/Disclosure/Disclosure.d.ts +1 -1
  72. package/dist/types/src/Divider/Divider.d.ts +2 -1
  73. package/dist/types/src/EmptyState/EmptyState.d.ts +2 -1
  74. package/dist/types/src/ErrorMessageWrapper/ErrorMessageWrapper.d.ts +2 -1
  75. package/dist/types/src/ErrorMessageWrapper/context/ErrorMessageProvider.d.ts +2 -1
  76. package/dist/types/src/ErrorMessageWrapper/context/types.d.ts +1 -1
  77. package/dist/types/src/Flex/Flex.d.ts +2 -1
  78. package/dist/types/src/Form/Form.d.ts +2 -1
  79. package/dist/types/src/Form/components/FormActionBar/FormActionBar.d.ts +3 -2
  80. package/dist/types/src/Form/components/FormBody/FormBody.d.ts +3 -2
  81. package/dist/types/src/Form/components/FormCache/FormCache.d.ts +4 -3
  82. package/dist/types/src/Form/components/FormErrorBanner/FormErrorBanner.d.ts +2 -1
  83. package/dist/types/src/Form/components/FormMask/FormMask.d.ts +2 -1
  84. package/dist/types/src/Form/components/FormMessage/FormMessage.d.ts +2 -1
  85. package/dist/types/src/Form/components/FormMessage/components/InternalFormMessage/InternalFormMessage.d.ts +2 -1
  86. package/dist/types/src/Form/components/FormMessageBanner/FormMessageBanner.d.ts +2 -1
  87. package/dist/types/src/Form/components/FormSaveButton/FormSaveButton.d.ts +2 -1
  88. package/dist/types/src/Form/context/AtlantisFormContext.d.ts +2 -1
  89. package/dist/types/src/Form/context/types.d.ts +3 -2
  90. package/dist/types/src/Form/hooks/useFormViewRefs.d.ts +2 -2
  91. package/dist/types/src/Form/hooks/useInternalForm.d.ts +5 -5
  92. package/dist/types/src/Form/types.d.ts +13 -7
  93. package/dist/types/src/FormField/FormField.d.ts +1 -1
  94. package/dist/types/src/FormatFile/FormatFile.d.ts +2 -1
  95. package/dist/types/src/FormatFile/components/ErrorIcon/ErrorIcon.d.ts +2 -1
  96. package/dist/types/src/FormatFile/components/FileView/FileView.d.ts +2 -1
  97. package/dist/types/src/FormatFile/components/FormatFileBottomSheet/FormatFileBottomSheet.d.ts +3 -2
  98. package/dist/types/src/FormatFile/components/MediaView/MediaView.d.ts +2 -1
  99. package/dist/types/src/FormatFile/components/ProgressBar/ProgressBar.d.ts +2 -1
  100. package/dist/types/src/Heading/Heading.d.ts +4 -3
  101. package/dist/types/src/Icon/Icon.d.ts +2 -1
  102. package/dist/types/src/IconButton/IconButton.d.ts +1 -1
  103. package/dist/types/src/InputCurrency/InputCurrency.d.ts +2 -1
  104. package/dist/types/src/InputDate/InputDate.d.ts +4 -2
  105. package/dist/types/src/InputFieldWrapper/InputFieldWrapper.d.ts +9 -2
  106. package/dist/types/src/InputFieldWrapper/InputFieldWrapper.style.d.ts +1 -1
  107. package/dist/types/src/InputFieldWrapper/components/ClearAction/ClearAction.d.ts +2 -1
  108. package/dist/types/src/InputFieldWrapper/components/Prefix/Prefix.d.ts +4 -4
  109. package/dist/types/src/InputFieldWrapper/components/Suffix/Suffix.d.ts +4 -4
  110. package/dist/types/src/InputPressable/InputPressable.d.ts +9 -1
  111. package/dist/types/src/InputPressable/InputPressable.style.d.ts +3 -0
  112. package/dist/types/src/InputSearch/InputSearch.d.ts +1 -1
  113. package/dist/types/src/InputSearch/components/FilterButton.d.ts +2 -1
  114. package/dist/types/src/InputText/InputText.d.ts +10 -2
  115. package/dist/types/src/InputText/InputText.style.d.ts +4 -0
  116. package/dist/types/src/InputText/context/InputAccessoriesProvider.d.ts +2 -1
  117. package/dist/types/src/InputTime/InputTime.d.ts +4 -2
  118. package/dist/types/src/Menu/Menu.d.ts +2 -1
  119. package/dist/types/src/Menu/components/MenuOption/MenuOption.d.ts +2 -1
  120. package/dist/types/src/Menu/components/Overlay/Overlay.d.ts +2 -1
  121. package/dist/types/src/Menu/types.d.ts +6 -1
  122. package/dist/types/src/ProgressBar/ProgressBar.d.ts +2 -1
  123. package/dist/types/src/ProgressBar/ProgressBarInner.d.ts +2 -1
  124. package/dist/types/src/Select/Select.d.ts +3 -2
  125. package/dist/types/src/Select/components/SelectDefaultPicker/SelectDefaultPicker.d.ts +2 -1
  126. package/dist/types/src/Select/components/SelectDefaultPicker/SelectDefaultPicker.ios.d.ts +2 -1
  127. package/dist/types/src/Select/components/SelectInternalPicker/SelectInternalPicker.d.ts +2 -1
  128. package/dist/types/src/Select/components/SelectPressable/SelectPressable.d.ts +2 -1
  129. package/dist/types/src/StatusLabel/StatusLabel.d.ts +2 -1
  130. package/dist/types/src/Switch/Switch.d.ts +2 -1
  131. package/dist/types/src/Switch/components/BaseSwitch/BaseSwitch.d.ts +2 -1
  132. package/dist/types/src/Text/Text.d.ts +4 -3
  133. package/dist/types/src/TextList/TextList.d.ts +2 -1
  134. package/dist/types/src/ThumbnailList/ThumbnailList.d.ts +2 -1
  135. package/dist/types/src/Toast/Toast.d.ts +2 -1
  136. package/dist/types/src/Typography/Typography.d.ts +3 -3
  137. package/dist/types/src/Typography/TypographyGestureDetector.d.ts +2 -1
  138. package/dist/types/src/utils/test/MockSafeAreaProvider.d.ts +1 -1
  139. package/package.json +23 -14
  140. package/src/ActionItem/ActionItem.tsx +1 -1
  141. package/src/ActionItem/ActionItemGroup.tsx +1 -3
  142. package/src/ActionItem/components/ActionItemContainer.tsx +1 -1
  143. package/src/ActionLabel/ActionLabel.test.tsx +12 -0
  144. package/src/ActionLabel/ActionLabel.tsx +3 -3
  145. package/src/ActionLabel/__snapshots__/ActionLabel.test.tsx.snap +66 -0
  146. package/src/ActivityIndicator/ActivityIndicator.tsx +1 -3
  147. package/src/AtlantisContext/AtlantisContext.test.tsx +1 -1
  148. package/src/AtlantisThemeContext/AtlantisThemeContext.test.tsx +5 -5
  149. package/src/AutoLink/AutoLink.test.tsx +2 -4
  150. package/src/AutoLink/AutoLink.tsx +1 -1
  151. package/src/AutoLink/components/ComposeTextWithLinks/ComposeTextWithLinks.tsx +1 -1
  152. package/src/AutoLink/components/Link/Link.tsx +1 -5
  153. package/src/Banner/Banner.test.tsx +12 -0
  154. package/src/Banner/Banner.tsx +4 -2
  155. package/src/Banner/components/BannerIcon/BannerIcon.style.ts +3 -0
  156. package/src/Banner/components/BannerIcon/BannerIcon.tsx +1 -1
  157. package/src/Banner/types.ts +1 -1
  158. package/src/BottomSheet/BottomSheet.test.tsx +17 -17
  159. package/src/BottomSheet/BottomSheet.tsx +4 -3
  160. package/src/BottomSheet/components/BottomSheetOption/BottomSheetOption.tsx +1 -1
  161. package/src/Button/Button.tsx +1 -1
  162. package/src/Button/components/InternalButtonLoading/InternalButtonLoading.tsx +1 -2
  163. package/src/ButtonGroup/ButtonGroup.test.tsx +13 -11
  164. package/src/ButtonGroup/ButtonGroup.tsx +2 -2
  165. package/src/ButtonGroup/ButtonGroupAction.tsx +4 -4
  166. package/src/ButtonGroup/components/SecondaryActionSheet/SecondaryActionSheet.tsx +2 -2
  167. package/src/Card/Card.tsx +1 -1
  168. package/src/Card/components/InternalCardHeader.tsx +1 -1
  169. package/src/Checkbox/Checkbox.tsx +2 -2
  170. package/src/Checkbox/CheckboxGroup.test.tsx +3 -7
  171. package/src/Checkbox/CheckboxGroup.tsx +2 -2
  172. package/src/Chip/Chip.tsx +1 -1
  173. package/src/Content/Content.tsx +1 -1
  174. package/src/ContentOverlay/ContentOverlay.test.tsx +34 -27
  175. package/src/ContentOverlay/ContentOverlay.tsx +7 -7
  176. package/src/ContentOverlay/UNSAFE_WrappedModalize.tsx +41 -0
  177. package/src/ContentOverlay/hooks/useKeyboardVisibility.test.ts +7 -7
  178. package/src/ContentOverlay/hooks/useViewLayoutHeight.test.ts +1 -1
  179. package/src/Disclosure/Disclosure.tsx +1 -1
  180. package/src/Divider/Divider.tsx +1 -1
  181. package/src/EmptyState/EmptyState.test.tsx +29 -42
  182. package/src/EmptyState/EmptyState.tsx +1 -1
  183. package/src/ErrorMessageWrapper/ErrorMessageWrapper.tsx +1 -1
  184. package/src/ErrorMessageWrapper/context/ErrorMessageProvider.tsx +3 -5
  185. package/src/ErrorMessageWrapper/context/types.ts +1 -1
  186. package/src/Flex/Flex.tsx +2 -2
  187. package/src/Form/Form.test.tsx +145 -2
  188. package/src/Form/Form.tsx +8 -1
  189. package/src/Form/components/FormActionBar/FormActionBar.tsx +3 -3
  190. package/src/Form/components/FormBody/FormBody.tsx +3 -3
  191. package/src/Form/components/FormCache/FormCache.tsx +5 -4
  192. package/src/Form/components/FormErrorBanner/FormErrorBanner.tsx +1 -1
  193. package/src/Form/components/FormMask/FormMask.tsx +1 -1
  194. package/src/Form/components/FormMessage/FormMessage.test.tsx +40 -27
  195. package/src/Form/components/FormMessage/FormMessage.tsx +1 -1
  196. package/src/Form/components/FormMessage/components/InternalFormMessage/InternalFormMessage.tsx +1 -1
  197. package/src/Form/components/FormMessageBanner/FormMessageBanner.tsx +1 -3
  198. package/src/Form/components/FormSaveButton/FormSaveButton.test.tsx +2 -2
  199. package/src/Form/components/FormSaveButton/FormSaveButton.tsx +1 -1
  200. package/src/Form/context/AtlantisFormContext.test.tsx +1 -1
  201. package/src/Form/context/AtlantisFormContext.tsx +1 -0
  202. package/src/Form/context/types.ts +3 -2
  203. package/src/Form/hooks/useFormViewRefs.ts +4 -5
  204. package/src/Form/hooks/useInternalForm.ts +12 -4
  205. package/src/Form/hooks/useScrollToError/useScrollToError.test.tsx +2 -1
  206. package/src/Form/types.ts +14 -8
  207. package/src/FormField/FormField.tsx +1 -1
  208. package/src/FormatFile/FormatFile.test.tsx +21 -21
  209. package/src/FormatFile/FormatFile.tsx +3 -3
  210. package/src/FormatFile/components/ErrorIcon/ErrorIcon.tsx +1 -1
  211. package/src/FormatFile/components/FileView/FileView.tsx +1 -1
  212. package/src/FormatFile/components/FormatFileBottomSheet/FormatFileBottomSheet.test.tsx +14 -14
  213. package/src/FormatFile/components/FormatFileBottomSheet/FormatFileBottomSheet.tsx +2 -2
  214. package/src/FormatFile/components/MediaView/MediaView.test.tsx +283 -0
  215. package/src/FormatFile/components/MediaView/MediaView.tsx +28 -7
  216. package/src/FormatFile/components/ProgressBar/ProgressBar.tsx +1 -1
  217. package/src/FormatFile/utils/createUseCreateThumbnail.ts +1 -1
  218. package/src/Glimmer/Glimmer.test.tsx +2 -2
  219. package/src/Heading/Heading.test.tsx +13 -0
  220. package/src/Heading/Heading.tsx +3 -3
  221. package/src/Heading/__snapshots__/Heading.test.tsx.snap +65 -0
  222. package/src/Icon/Icon.tsx +1 -1
  223. package/src/Icon/__snapshots__/Icon.test.tsx.snap +7 -0
  224. package/src/IconButton/IconButton.tsx +1 -1
  225. package/src/InputCurrency/InputCurrency.tsx +72 -58
  226. package/src/InputDate/InputDate.tsx +7 -3
  227. package/src/InputEmail/InputEmail.tsx +15 -8
  228. package/src/InputFieldWrapper/InputFieldWrapper.style.ts +1 -1
  229. package/src/InputFieldWrapper/InputFieldWrapper.test.tsx +48 -1
  230. package/src/InputFieldWrapper/InputFieldWrapper.tsx +39 -29
  231. package/src/InputFieldWrapper/components/ClearAction/ClearAction.tsx +1 -1
  232. package/src/InputFieldWrapper/components/Prefix/Prefix.test.tsx +8 -16
  233. package/src/InputFieldWrapper/components/Prefix/Prefix.tsx +8 -6
  234. package/src/InputFieldWrapper/components/Suffix/Suffix.test.tsx +2 -4
  235. package/src/InputFieldWrapper/components/Suffix/Suffix.tsx +8 -6
  236. package/src/InputNumber/InputNumber.tsx +11 -7
  237. package/src/InputPassword/InputPassword.tsx +1 -1
  238. package/src/InputPressable/InputPressable.style.ts +4 -0
  239. package/src/InputPressable/InputPressable.test.tsx +75 -1
  240. package/src/InputPressable/InputPressable.tsx +34 -8
  241. package/src/InputSearch/InputSearch.tsx +2 -1
  242. package/src/InputSearch/components/FilterButton.tsx +1 -1
  243. package/src/InputText/InputText.style.ts +5 -0
  244. package/src/InputText/InputText.test.tsx +75 -0
  245. package/src/InputText/InputText.tsx +34 -17
  246. package/src/InputText/context/InputAccessoriesProvider.tsx +1 -1
  247. package/src/InputTime/InputTime.tsx +7 -3
  248. package/src/Menu/Menu.tsx +3 -3
  249. package/src/Menu/components/MenuOption/MenuOption.tsx +1 -1
  250. package/src/Menu/components/Overlay/Overlay.tsx +1 -1
  251. package/src/Menu/types.ts +7 -1
  252. package/src/ProgressBar/ProgressBar.tsx +1 -1
  253. package/src/ProgressBar/ProgressBarInner.tsx +1 -1
  254. package/src/Select/Select.style.ts +1 -0
  255. package/src/Select/Select.tsx +2 -2
  256. package/src/Select/components/SelectDefaultPicker/SelectDefaultPicker.ios.tsx +1 -1
  257. package/src/Select/components/SelectDefaultPicker/SelectDefaultPicker.tsx +1 -1
  258. package/src/Select/components/SelectInternalPicker/SelectInternalPicker.tsx +1 -1
  259. package/src/Select/components/SelectPressable/SelectPressable.tsx +1 -4
  260. package/src/StatusLabel/StatusLabel.tsx +1 -1
  261. package/src/Switch/Switch.tsx +1 -1
  262. package/src/Switch/components/BaseSwitch/BaseSwitch.tsx +8 -2
  263. package/src/Text/Text.test.tsx +10 -0
  264. package/src/Text/Text.tsx +3 -3
  265. package/src/Text/__snapshots__/Text.test.tsx.snap +66 -0
  266. package/src/TextList/TextList.tsx +1 -1
  267. package/src/ThumbnailList/ThumbnailList.test.tsx +5 -5
  268. package/src/ThumbnailList/ThumbnailList.tsx +1 -1
  269. package/src/Toast/Toast.tsx +2 -2
  270. package/src/Typography/Typography.test.tsx +61 -0
  271. package/src/Typography/Typography.tsx +25 -9
  272. package/src/Typography/TypographyGestureDetector.tsx +1 -3
  273. package/src/Typography/__snapshots__/Typography.test.tsx.snap +222 -0
  274. package/src/hooks/useAtlantisI18n/locales/en.json +1 -0
  275. package/src/hooks/useAtlantisI18n/locales/es.json +1 -0
  276. package/src/hooks/useFormController.ts +6 -13
  277. package/src/utils/test/MockSafeAreaProvider.tsx +1 -1
  278. package/dist/tsconfig.tsbuildinfo +0 -1
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jobber/components-native",
3
- "version": "0.84.4-JOB-134681-8086ad4.25+8086ad474",
3
+ "version": "0.84.4-JOB-138679-b1552ab.68+b1552ab31",
4
4
  "license": "MIT",
5
5
  "description": "React Native implementation of Atlantis",
6
6
  "repository": {
@@ -32,7 +32,7 @@
32
32
  "build": "npm run build:clean && npm run compile",
33
33
  "bootstrap": "npm run build",
34
34
  "prepack": "npm run build",
35
- "compile": "tsc -b",
35
+ "compile": "tsc -p tsconfig.build.json",
36
36
  "build:clean": "rm -rf ./dist",
37
37
  "storybook": "storybook dev -p 6008 --disable-telemetry",
38
38
  "storybook:build": "storybook build --disable-telemetry"
@@ -43,8 +43,8 @@
43
43
  "autolinker": "^4.0.0",
44
44
  "deepmerge": "^4.2.2",
45
45
  "lodash": "^4.17.21",
46
- "react-hook-form": "^7.30.0",
47
- "react-intl": "^6.4.2",
46
+ "react-hook-form": "^7.52.0",
47
+ "react-intl": "^7.1.11",
48
48
  "react-native-keyboard-aware-scroll-view": "^0.9.5",
49
49
  "react-native-modalize": "^2.0.13",
50
50
  "react-native-portalize": "^1.0.7",
@@ -53,18 +53,27 @@
53
53
  "ts-xor": "^1.1.0"
54
54
  },
55
55
  "devDependencies": {
56
+ "@react-native-community/datetimepicker": "^8.4.5",
57
+ "@react-native/babel-preset": "^0.81.1",
56
58
  "@storybook/addon-a11y": "^9.1.2",
57
59
  "@storybook/react": "^9.1.2",
58
60
  "@storybook/react-native-web-vite": "^9.1.2",
59
- "@testing-library/jest-native": "^5.4.2",
60
- "@testing-library/react-native": "^12.0.1",
61
+ "@testing-library/react-native": "^13.3.3",
61
62
  "@types/lodash.chunk": "^4.2.7",
62
63
  "@types/lodash.debounce": "^4.0.7",
63
64
  "@types/lodash.identity": "^3.0.7",
64
- "@types/react": "^18.0.28",
65
65
  "@types/react-native-uuid": "^1.4.0",
66
- "metro-react-native-babel-preset": "^0.76.0",
67
- "react-test-renderer": "^18.2.0",
66
+ "@types/react-test-renderer": "19.1.0",
67
+ "date-fns": "^2.30.0",
68
+ "date-fns-tz": "^2.0.0",
69
+ "react-native": "^0.82.1",
70
+ "react-native-gesture-handler": "^2.29.1",
71
+ "react-native-modal-datetime-picker": "^18.0.0",
72
+ "react-native-reanimated": "^3.7.1",
73
+ "react-native-safe-area-context": "^5.4.0",
74
+ "react-native-svg": "^15.1.0",
75
+ "react-native-web": "^0.20.0",
76
+ "react-test-renderer": "^19.1.1",
68
77
  "storybook": "^9.1.2"
69
78
  },
70
79
  "peerDependencies": {
@@ -73,10 +82,10 @@
73
82
  "@react-native-community/datetimepicker": ">=6.7.0",
74
83
  "date-fns": "^2.30.0",
75
84
  "date-fns-tz": "^2.0.0",
76
- "react": "^18.2.0",
77
- "react-intl": "^6.4.2",
78
- "react-native": ">=0.76.0",
79
- "react-native-gesture-handler": ">=2.10.0",
85
+ "react": "^19",
86
+ "react-intl": "^6 || ^7",
87
+ "react-native": ">=0.79.5",
88
+ "react-native-gesture-handler": ">=2.22.0",
80
89
  "react-native-keyboard-aware-scroll-view": "^0.9.5",
81
90
  "react-native-modal-datetime-picker": " >=13.0.0",
82
91
  "react-native-modalize": "^2.0.13",
@@ -85,5 +94,5 @@
85
94
  "react-native-safe-area-context": "^5.4.0",
86
95
  "react-native-svg": ">=12.0.0"
87
96
  },
88
- "gitHead": "8086ad474bae8138621804bd18aed5d9c88dd6bf"
97
+ "gitHead": "b1552ab319204ce883046ea2c22d875952746675"
89
98
  }
@@ -2,7 +2,7 @@ import React from "react";
2
2
  import { View } from "react-native";
3
3
  import { useStyles } from "./ActionItem.style";
4
4
  import { Divider } from "../Divider";
5
- export function ActionItemGroup({ children, }) {
5
+ export function ActionItemGroup({ children }) {
6
6
  return React.createElement(View, null, renderChildren(children));
7
7
  }
8
8
  function renderChildren(children) {
@@ -1,7 +1,7 @@
1
1
  import React from "react";
2
2
  import { Text as RNText } from "react-native";
3
3
  import { Text } from "../../../Text";
4
- export function Link({ children, onPress, onLongPress, }) {
4
+ export function Link({ children, onPress, onLongPress }) {
5
5
  return (React.createElement(RNText, { onPress: onPress, onLongPress: onLongPress },
6
6
  React.createElement(Text, { variation: "interactive" }, children)));
7
7
  }
@@ -48,5 +48,7 @@ function getBannerIcon(type) {
48
48
  return "help";
49
49
  case "error":
50
50
  return "alert";
51
+ case "success":
52
+ return "checkmark";
51
53
  }
52
54
  }
@@ -14,5 +14,8 @@ export const useStyles = buildThemedStyles(tokens => {
14
14
  notice: {
15
15
  backgroundColor: tokens["color-informative"],
16
16
  },
17
+ success: {
18
+ backgroundColor: tokens["color-success"],
19
+ },
17
20
  };
18
21
  });
@@ -1,9 +1,9 @@
1
1
  import React, { forwardRef, useState } from "react";
2
- import { Modalize } from "react-native-modalize";
3
2
  import { useSafeAreaInsets } from "react-native-safe-area-context";
4
3
  import { Keyboard, View } from "react-native";
5
4
  import { BottomSheetOption } from "./components/BottomSheetOption";
6
5
  import { useStyles } from "./BottomSheet.style";
6
+ import { UNSAFE_WrappedModalize } from "../ContentOverlay/UNSAFE_WrappedModalize";
7
7
  import { useIsScreenReaderEnabled } from "../hooks";
8
8
  import { Divider } from "../Divider";
9
9
  import { Heading } from "../Heading";
@@ -15,7 +15,7 @@ function BottomSheetInternal({ children, showCancel, loading = false, heading, o
15
15
  const styles = useStyles();
16
16
  return (React.createElement(React.Fragment, null,
17
17
  open && React.createElement(Overlay, { styles: styles }),
18
- React.createElement(Modalize, { ref: ref, adjustToContentHeight: true, modalStyle: styles.modal, overlayStyle: styles.overlayModalize, HeaderComponent: heading && React.createElement(Header, { heading: heading, styles: styles }), FooterComponent: React.createElement(Footer, { cancellable: (showCancel && !loading) || isScreenReaderEnabled, onCancel: () => {
18
+ React.createElement(UNSAFE_WrappedModalize, { ref: ref, adjustToContentHeight: true, modalStyle: styles.modal, overlayStyle: styles.overlayModalize, HeaderComponent: heading && React.createElement(Header, { heading: heading, styles: styles }), FooterComponent: React.createElement(Footer, { cancellable: (showCancel && !loading) || isScreenReaderEnabled, onCancel: () => {
19
19
  var _a;
20
20
  (_a = ref === null || ref === void 0 ? void 0 : ref.current) === null || _a === void 0 ? void 0 : _a.close();
21
21
  }, styles: styles }), withHandle: false, withReactModal: isScreenReaderEnabled, onOpen: openModal, onClose: closeModal },
@@ -8,7 +8,6 @@ const offset = PixelRatio.roundToNearestPixel(imageWidth / PixelRatio.get());
8
8
  const leftOffset = -1 * offset;
9
9
  // looks like deprecation for FlatList in reanimated is cascading down to other exports
10
10
  // This is not createAnimatedComponent(FlatList), we are fine
11
- // eslint-disable-next-line import/no-deprecated
12
11
  const AnimatedImage = Animated.createAnimatedComponent(ImageBackground);
13
12
  function InternalButtonLoadingInternal({ variation, type, }) {
14
13
  const translateX = useSharedValue(0);
@@ -9,7 +9,7 @@ import { useAtlantisI18n } from "../hooks/useAtlantisI18n";
9
9
  export function ButtonGroup({ children, showCancelInBottomSheet, bottomSheetHeading, onOpenBottomSheet, onCloseBottomSheet, allowTapWhenOffline = false, }) {
10
10
  const { t } = useAtlantisI18n();
11
11
  const { handlePress } = usePreventTapWhenOffline();
12
- const secondaryActionsRef = useRef();
12
+ const secondaryActionsRef = useRef(null);
13
13
  const { primaryActions, secondaryActions } = getActions(children);
14
14
  const styles = useStyles();
15
15
  return (React.createElement(View, { style: styles.buttonGroup },
@@ -1,11 +1,11 @@
1
1
  import React, { forwardRef, useCallback, useImperativeHandle, useMemo, useRef, useState, } from "react";
2
- import { Modalize } from "react-native-modalize";
3
2
  import { useSafeAreaInsets } from "react-native-safe-area-context";
4
3
  import { AccessibilityInfo, Platform, View, findNodeHandle, useWindowDimensions, } from "react-native";
5
4
  import { Portal } from "react-native-portalize";
6
5
  import { useKeyboardVisibility } from "./hooks/useKeyboardVisibility";
7
6
  import { useStyles } from "./ContentOverlay.style";
8
7
  import { useViewLayoutHeight } from "./hooks/useViewLayoutHeight";
8
+ import { UNSAFE_WrappedModalize } from "./UNSAFE_WrappedModalize";
9
9
  import { useIsScreenReaderEnabled } from "../hooks";
10
10
  import { IconButton } from "../IconButton";
11
11
  import { Heading } from "../Heading";
@@ -26,8 +26,8 @@ function ContentOverlayInternal({ children, title, accessibilityLabel, fullScree
26
26
  const isFullScreenOrTopPosition = fullScreen || (!adjustToContentHeight && position === "top");
27
27
  const shouldShowDismiss = showDismiss || isScreenReaderEnabled || isFullScreenOrTopPosition;
28
28
  const [showHeaderShadow, setShowHeaderShadow] = useState(false);
29
- const overlayHeader = useRef();
30
- const internalRef = useRef();
29
+ const overlayHeader = useRef(null);
30
+ const internalRef = useRef(null);
31
31
  const [modalizeMethods, setModalizeMethods] = useState();
32
32
  const callbackInternalRef = useCallback((instance) => {
33
33
  if (instance && !internalRef.current) {
@@ -86,7 +86,7 @@ function ContentOverlayInternal({ children, title, accessibilityLabel, fullScree
86
86
  }
87
87
  };
88
88
  return (React.createElement(React.Fragment, null,
89
- headerHeightKnown && childrenHeightKnown && (React.createElement(Modalize, { ref: callbackInternalRef, overlayStyle: styles.overlay, handleStyle: styles.handle, handlePosition: "inside", modalStyle: modalStyle, modalTopOffset: tokens["space-larger"], snapPoint: snapPoint, closeSnapPointStraightEnabled: false, withHandle: isDraggable, panGestureEnabled: isDraggable, adjustToContentHeight: adjustToContentHeight, disableScrollIfPossible: !adjustToContentHeight, onClose: onClose, onOpen: onOpen, keyboardAvoidingBehavior: keyboardAvoidingBehavior, avoidKeyboardLikeIOS: avoidKeyboardLikeIOS, childrenStyle: styles.childrenStyle, onBackButtonPress: onCloseController, closeOnOverlayTap: isCloseableOnOverlayTap, onOpened: () => {
89
+ headerHeightKnown && childrenHeightKnown && (React.createElement(UNSAFE_WrappedModalize, { ref: callbackInternalRef, overlayStyle: styles.overlay, handleStyle: styles.handle, handlePosition: "inside", modalStyle: modalStyle, modalTopOffset: tokens["space-larger"], snapPoint: snapPoint, closeSnapPointStraightEnabled: false, withHandle: isDraggable, panGestureEnabled: isDraggable, adjustToContentHeight: adjustToContentHeight, disableScrollIfPossible: !adjustToContentHeight, onClose: onClose, onOpen: onOpen, keyboardAvoidingBehavior: keyboardAvoidingBehavior, avoidKeyboardLikeIOS: avoidKeyboardLikeIOS, childrenStyle: styles.childrenStyle, onBackButtonPress: onCloseController, closeOnOverlayTap: isCloseableOnOverlayTap, onOpened: () => {
90
90
  if (overlayHeader.current) {
91
91
  const reactTag = findNodeHandle(overlayHeader.current);
92
92
  if (reactTag) {
@@ -124,9 +124,7 @@ function ContentOverlayInternal({ children, title, accessibilityLabel, fullScree
124
124
  : styles.titleWithoutDismiss,
125
125
  ] },
126
126
  React.createElement(Heading, { level: "subtitle", variation: loading ? "subdued" : "heading", align: "start" }, title)),
127
- shouldShowDismiss && (React.createElement(View, { style: styles.dismissButton,
128
- // @ts-expect-error tsc-ci
129
- ref: overlayHeader, accessibilityLabel: accessibilityLabel || closeOverlayA11YLabel, accessible: true },
127
+ shouldShowDismiss && (React.createElement(View, { style: styles.dismissButton, ref: overlayHeader, accessibilityLabel: accessibilityLabel || closeOverlayA11YLabel, accessible: true },
130
128
  React.createElement(IconButton, { name: "cross", customColor: loading ? tokens["color-disabled"] : tokens["color-heading"], onPress: () => onCloseController(), accessibilityLabel: closeOverlayA11YLabel, testID: "ATL-Overlay-CloseButton" }))))));
131
129
  }
132
130
  function renderChildren() {
@@ -0,0 +1,23 @@
1
+ import React, { forwardRef, useImperativeHandle, useRef, useState, } from "react";
2
+ import { Modalize } from "react-native-modalize";
3
+ export const UNSAFE_WrappedModalize = forwardRef((props, ref) => {
4
+ const innerRef = useRef(null);
5
+ const [openRenderId, setOpenRenderId] = useState(0);
6
+ useImperativeHandle(ref, () => ({
7
+ open(dest) {
8
+ setOpenRenderId(id => id + 1);
9
+ // Open on a fresh tick for additional safety
10
+ requestAnimationFrame(() => {
11
+ var _a;
12
+ (_a = innerRef.current) === null || _a === void 0 ? void 0 : _a.open(dest);
13
+ });
14
+ },
15
+ close(dest) {
16
+ var _a;
17
+ (_a = innerRef.current) === null || _a === void 0 ? void 0 : _a.close(dest);
18
+ },
19
+ }), []);
20
+ // Use a unique key to force a remount, ensuring we get fresh gesture handler nodes within modalize
21
+ return (React.createElement(Modalize, Object.assign({ key: `modalize-${openRenderId}`, ref: innerRef }, props)));
22
+ });
23
+ UNSAFE_WrappedModalize.displayName = "UNSAFE_WrappedModalize";
@@ -1,7 +1,7 @@
1
1
  import React, { useState } from "react";
2
2
  import { AccessibilityInfo, findNodeHandle } from "react-native";
3
3
  import { ErrorMessageContext } from "./ErrorMessageContext";
4
- export function ErrorMessageProvider({ children, }) {
4
+ export function ErrorMessageProvider({ children }) {
5
5
  const [elements, setElements] = useState({});
6
6
  return (React.createElement(ErrorMessageContext.Provider, { value: {
7
7
  elements,
@@ -38,6 +38,7 @@ import { useScrollToError } from "./hooks/useScrollToError";
38
38
  import { FormSaveButton } from "./components/FormSaveButton";
39
39
  import { useSaveButtonPosition } from "./hooks/useSaveButtonPosition";
40
40
  import { FormCache } from "./components/FormCache/FormCache";
41
+ import { useAtlantisFormContext } from "./context/AtlantisFormContext";
41
42
  import { InputAccessoriesProvider } from "../InputText";
42
43
  import { tokens } from "../utils/design";
43
44
  import { ErrorMessageProvider } from "../ErrorMessageWrapper";
@@ -48,7 +49,7 @@ export function Form(_a) {
48
49
  React.createElement(ErrorMessageProvider, null, child)));
49
50
  }
50
51
  // eslint-disable-next-line max-statements
51
- function InternalForm({ children, onBeforeSubmit, onSubmit, onSubmitError, onSubmitSuccess, bannerErrors, bannerMessages, initialValues, mode = "onTouched", reValidateMode = "onChange", formRef, saveButtonLabel, renderStickySection, localCacheKey, localCacheExclude, localCacheId, secondaryActions, saveButtonOffset, showStickySaveButton = false, renderFooter, }) {
52
+ function InternalForm({ children, onBeforeSubmit, onSubmit, onSubmitError, onSubmitSuccess, bannerErrors, bannerMessages, initialValues, mode = "onTouched", reValidateMode = "onChange", formRef, saveButtonLabel, renderStickySection, localCacheKey, localCacheExclude, localCacheId, secondaryActions, saveButtonOffset, showStickySaveButton = false, renderFooter, UNSAFE_allowDiscardLocalCacheWhenOffline, }) {
52
53
  var _a;
53
54
  const { scrollViewRef, bottomViewRef, scrollToTop } = useFormViewRefs();
54
55
  const [saveButtonHeight, setSaveButtonHeight] = useState(0);
@@ -64,6 +65,7 @@ function InternalForm({ children, onBeforeSubmit, onSubmit, onSubmitError, onSub
64
65
  scrollViewRef,
65
66
  saveButtonHeight,
66
67
  messageBannerHeight,
68
+ UNSAFE_allowDiscardLocalCacheWhenOffline,
67
69
  });
68
70
  const { windowHeight, headerHeight } = useScreenInformation();
69
71
  const [keyboardHeight, setKeyboardHeight] = useState(0);
@@ -102,12 +104,13 @@ function InternalForm({ children, onBeforeSubmit, onSubmit, onSubmitError, onSub
102
104
  setMessageBannerHeight(event.nativeEvent.layout.height);
103
105
  };
104
106
  const styles = useStyles();
107
+ const { edgeToEdgeEnabled } = useAtlantisFormContext();
105
108
  return (React.createElement(FormProvider, Object.assign({}, formMethods),
106
109
  React.createElement(React.Fragment, null,
107
110
  (isSubmitting || isSecondaryActionLoading) && React.createElement(FormMask, null),
108
111
  React.createElement(FormCache, { localCacheKey: localCacheKey, localCacheExclude: localCacheExclude, setLocalCache: setLocalCache }),
109
112
  React.createElement(FormBody, { keyboardHeight: calculateSaveButtonOffset(), submit: handleSubmit(internalSubmit), isFormSubmitting: isSubmitting, saveButtonLabel: saveButtonLabel, shouldRenderActionBar: saveButtonPosition === "sticky", renderStickySection: renderStickySection, secondaryActions: secondaryActions, setSecondaryActionLoading: setIsSecondaryActionLoading, setSaveButtonHeight: setSaveButtonHeight, saveButtonOffset: saveButtonOffset },
110
- React.createElement(KeyboardAwareScrollView, Object.assign({ enableResetScrollToCoords: false, enableAutomaticScroll: true, keyboardOpeningTime: Platform.OS === "ios" ? tokens["timing-slowest"] : 0, keyboardShouldPersistTaps: "handled", ref: scrollViewRef }, keyboardProps, { extraHeight: headerHeight, contentContainerStyle: !keyboardHeight && styles.scrollContentContainer }),
113
+ React.createElement(KeyboardAwareScrollView, Object.assign({ enableResetScrollToCoords: false, enableAutomaticScroll: true, enableOnAndroid: edgeToEdgeEnabled, keyboardOpeningTime: Platform.OS === "ios" ? tokens["timing-slowest"] : 0, keyboardShouldPersistTaps: "handled", ref: scrollViewRef }, keyboardProps, { extraHeight: headerHeight, extraScrollHeight: edgeToEdgeEnabled ? tokens["space-large"] : 0, contentContainerStyle: !keyboardHeight && styles.scrollContentContainer }),
111
114
  React.createElement(View, { onLayout: ({ nativeEvent }) => {
112
115
  setFormContentHeight(nativeEvent.layout.height);
113
116
  } },
@@ -28,5 +28,6 @@ export function FormCache({ localCacheExclude, localCacheKey, setLocalCache, })
28
28
  setLocalCache(formData);
29
29
  }
30
30
  }, [formData, isDirty, localCacheExclude, setLocalCache, shouldExclude]);
31
+ // eslint-disable-next-line react/jsx-no-useless-fragment
31
32
  return React.createElement(React.Fragment, null);
32
33
  }
@@ -1,7 +1,7 @@
1
1
  import React from "react";
2
2
  import { FormBannerMessageType } from "../../types";
3
3
  import { Banner } from "../../../Banner";
4
- export function FormMessageBanner({ bannerMessages, }) {
4
+ export function FormMessageBanner({ bannerMessages }) {
5
5
  return (React.createElement(React.Fragment, null, bannerMessages === null || bannerMessages === void 0 ? void 0 : bannerMessages.map((message, index) => (React.createElement(Banner, { key: index, text: message.message, type: getBannerType(message.messageType) })))));
6
6
  }
7
7
  function getBannerType(messageType) {
@@ -8,6 +8,7 @@ export const atlantisFormContextDefaultValues = {
8
8
  setLocalCache: () => undefined,
9
9
  removeLocalCache: () => undefined,
10
10
  }),
11
+ edgeToEdgeEnabled: false,
11
12
  };
12
13
  export const AtlantisFormContext = createContext(atlantisFormContextDefaultValues);
13
14
  export function useAtlantisFormContext() {
@@ -1,7 +1,7 @@
1
1
  import { useForm } from "react-hook-form";
2
2
  import { useAtlantisContext } from "../../AtlantisContext";
3
3
  import { useAtlantisFormContext } from "../context/AtlantisFormContext";
4
- export function useInternalForm({ mode, reValidateMode, initialValues, formRef, localCacheKey, localCacheId, scrollViewRef, saveButtonHeight, messageBannerHeight, }) {
4
+ export function useInternalForm({ mode, reValidateMode, initialValues, formRef, localCacheKey, localCacheId, scrollViewRef, saveButtonHeight, messageBannerHeight, UNSAFE_allowDiscardLocalCacheWhenOffline = false, }) {
5
5
  const { useConfirmBeforeBack, useInternalFormLocalCache } = useAtlantisFormContext();
6
6
  const { isOnline } = useAtlantisContext();
7
7
  const formMethods = useForm({
@@ -20,11 +20,14 @@ export function useInternalForm({ mode, reValidateMode, initialValues, formRef,
20
20
  messageBannerHeight,
21
21
  scrollViewRef });
22
22
  }
23
+ const shouldRemoveCacheOnBack = UNSAFE_allowDiscardLocalCacheWhenOffline
24
+ ? true
25
+ : isOnline;
23
26
  const removeListenerRef = useConfirmBeforeBack({
24
27
  alwaysPreventBack: isSubmitting,
25
28
  shouldShowAlert: isDirty,
26
- onAcceptEvent: isOnline ? removeLocalCache : undefined,
27
- showLostProgressMessage: isOnline || !clientSideSaveOn ? true : false,
29
+ onAcceptEvent: shouldRemoveCacheOnBack ? removeLocalCache : undefined,
30
+ showLostProgressMessage: shouldRemoveCacheOnBack || !clientSideSaveOn ? true : false,
28
31
  });
29
32
  return {
30
33
  setLocalCache,
@@ -1,4 +1,4 @@
1
- import React, { useState } from "react";
1
+ import React, { useEffect, useRef, useState } from "react";
2
2
  import { ImageBackground, View } from "react-native";
3
3
  import { useStyles } from "./MediaView.style";
4
4
  import { StatusCode } from "../../types";
@@ -14,20 +14,37 @@ export function MediaView({ accessibilityLabel, showOverlay, showError, file, st
14
14
  const { useCreateThumbnail } = useAtlantisFormatFileContext();
15
15
  const { thumbnail, error } = useCreateThumbnail(file);
16
16
  const [isLoading, setIsLoading] = useState(false);
17
+ /**
18
+ * Tracks whether onLoadEnd has fired to prevent race conditions.
19
+ * ImageBackground can fire onLoadEnd before onLoadStart when loading cached images,
20
+ * which would cause isLoading to get stuck at true, showing an infinite spinner.
21
+ */
22
+ const hasLoadedRef = useRef(false);
17
23
  const a11yLabel = computeA11yLabel({
18
24
  accessibilityLabel,
19
25
  showOverlay,
20
26
  showError,
21
27
  t,
22
28
  });
23
- const hasError = showError || error;
24
- const uri = thumbnail || file.thumbnailUrl || file.source;
25
- const styles = useStyles();
29
+ const hasError = showError || error, uri = thumbnail || file.thumbnailUrl || file.source, styles = useStyles();
30
+ const handleLoadStart = () => {
31
+ if (!hasLoadedRef.current) {
32
+ setIsLoading(true);
33
+ }
34
+ };
35
+ const handleLoadEnd = () => {
36
+ hasLoadedRef.current = true;
37
+ setIsLoading(false);
38
+ };
39
+ useEffect(() => {
40
+ hasLoadedRef.current = false;
41
+ setIsLoading(false);
42
+ }, [uri]);
26
43
  return (React.createElement(View, { accessible: true, accessibilityLabel: a11yLabel },
27
44
  React.createElement(ImageBackground, { style: [
28
45
  styles.imageBackground,
29
46
  styleInGrid ? styles.imageBackgroundGrid : styles.imageBackgroundFlat,
30
- ], resizeMode: styleInGrid ? "cover" : "contain", source: { uri }, testID: "test-image", onLoadStart: () => setIsLoading(true), onLoadEnd: () => setIsLoading(false) },
47
+ ], resizeMode: styleInGrid ? "cover" : "contain", source: { uri }, testID: "test-image", onLoadStart: handleLoadStart, onLoadEnd: handleLoadEnd },
31
48
  React.createElement(Overlay, { isLoading: isLoading, showOverlay: showOverlay, hasError: hasError, file: file, onUploadComplete: onUploadComplete, styles: styles }))));
32
49
  }
33
50
  function Overlay({ isLoading, showOverlay, hasError, file, onUploadComplete, styles, }) {
@@ -1,4 +1,4 @@
1
- import { useIsMounted } from "@jobber/hooks/useIsMounted";
1
+ import { useIsMounted } from "@jobber/hooks";
2
2
  import { useCallback, useEffect, useState } from "react";
3
3
  export function createUseCreateThumbnail(createThumbnail) {
4
4
  const useCreateThumbnail = useCallback((file) => {
@@ -24,6 +24,31 @@ const getKeyboard = (props) => {
24
24
  return "numeric";
25
25
  }
26
26
  };
27
+ const computeDisplayFromNumericInput = (numberedValue, decimalNumbers, decimalCount, maxLength, maxDecimalPlaces, decimalPlaces, formatNumber) => {
28
+ const transformedValue = limitInputWholeDigits(numberedValue, maxLength);
29
+ const stringValue = decimalNumbers !== ""
30
+ ? transformedValue.toString() + "." + decimalNumbers.slice(1)
31
+ : transformedValue.toString();
32
+ if (checkLastChar(stringValue)) {
33
+ const roundedDecimal = configureDecimal(decimalCount, maxDecimalPlaces, stringValue, decimalPlaces);
34
+ const internationalizedValueToDisplay = formatNumber(roundedDecimal, {
35
+ maximumFractionDigits: maxDecimalPlaces,
36
+ });
37
+ return {
38
+ onChangeValue: roundedDecimal,
39
+ displayValue: internationalizedValueToDisplay,
40
+ };
41
+ }
42
+ else {
43
+ const internationalizedValueToDisplay = formatNumber(transformedValue, {
44
+ maximumFractionDigits: maxDecimalPlaces,
45
+ }) + decimalNumbers;
46
+ return {
47
+ onChangeValue: transformedValue.toString() + "." + decimalNumbers.slice(1),
48
+ displayValue: internationalizedValueToDisplay,
49
+ };
50
+ }
51
+ };
27
52
  export function InputCurrency(props) {
28
53
  var _a, _b;
29
54
  const { showCurrencySymbol = true, maxDecimalPlaces = 5, decimalPlaces = 2, maxLength = 10, } = props;
@@ -35,52 +60,39 @@ export function InputCurrency(props) {
35
60
  });
36
61
  const internalValue = getInternalValue(props, field, intl.formatNumber);
37
62
  const [displayValue, setDisplayValue] = useState(internalValue);
38
- const setOnChangeAndDisplayValues = (onChangeValue, valueToDisplay) => {
39
- var _a;
40
- (_a = props.onChange) === null || _a === void 0 ? void 0 : _a.call(props, onChangeValue);
41
- setDisplayValue(valueToDisplay);
42
- };
43
- const checkDecimalAndI18nOfDisplayValue = (numberedValue, decimalNumbers, decimalCount) => {
44
- const transformedValue = limitInputWholeDigits(numberedValue, maxLength);
45
- const stringValue = decimalNumbers !== ""
46
- ? transformedValue.toString() + "." + decimalNumbers.slice(1)
47
- : transformedValue.toString();
48
- if (checkLastChar(stringValue)) {
49
- const roundedDecimal = configureDecimal(decimalCount, maxDecimalPlaces, stringValue, decimalPlaces);
50
- const internationalizedValueToDisplay = intl.formatNumber(roundedDecimal, {
51
- maximumFractionDigits: maxDecimalPlaces,
52
- });
53
- setOnChangeAndDisplayValues(roundedDecimal, internationalizedValueToDisplay);
54
- }
55
- else {
56
- const internationalizedValueToDisplay = intl.formatNumber(transformedValue, {
57
- maximumFractionDigits: maxDecimalPlaces,
58
- }) + decimalNumbers;
59
- setOnChangeAndDisplayValues(transformedValue.toString() + "." + decimalNumbers.slice(1), internationalizedValueToDisplay);
60
- }
61
- };
62
63
  const handleChange = (newValue) => {
64
+ var _a, _b;
63
65
  const [decimalCount, wholeIntegerValue, decimalNumbers] = parseGivenInput(newValue, floatSeparators.decimal);
64
66
  const numberedValue = wholeIntegerValue
65
67
  ? convertToNumber(wholeIntegerValue)
66
68
  : wholeIntegerValue;
67
69
  if (isValidNumber(numberedValue) && typeof numberedValue === "number") {
68
- checkDecimalAndI18nOfDisplayValue(numberedValue, decimalNumbers, decimalCount);
70
+ const result = computeDisplayFromNumericInput(numberedValue, decimalNumbers, decimalCount, maxLength, maxDecimalPlaces, decimalPlaces, intl.formatNumber);
71
+ const { onChangeValue, displayValue: valueToDisplay } = result;
72
+ (_a = props.onChange) === null || _a === void 0 ? void 0 : _a.call(props, onChangeValue);
73
+ setDisplayValue(valueToDisplay);
69
74
  }
70
75
  else {
71
76
  const value = (numberedValue === null || numberedValue === void 0 ? void 0 : numberedValue.toString()) + decimalNumbers;
72
- setOnChangeAndDisplayValues(value, value);
77
+ (_b = props.onChange) === null || _b === void 0 ? void 0 : _b.call(props, value);
78
+ setDisplayValue(value);
73
79
  }
74
80
  };
75
81
  const { t } = useAtlantisI18n();
82
+ const defaultValidations = {
83
+ pattern: {
84
+ value: NUMBER_VALIDATION_REGEX,
85
+ message: t("errors.notANumber"),
86
+ },
87
+ };
88
+ const mergedValidations = props.validations
89
+ ? Object.assign({}, defaultValidations, props.validations)
90
+ : defaultValidations;
76
91
  return (React.createElement(InputText, Object.assign({}, props, { prefix: showCurrencySymbol ? { label: currencySymbol } : undefined, keyboard: getKeyboard(props), value: ((_a = props.value) === null || _a === void 0 ? void 0 : _a.toString()) || displayValue, defaultValue: (_b = props.defaultValue) === null || _b === void 0 ? void 0 : _b.toString(), onChangeText: handleChange, transform: {
77
92
  output: val => {
78
93
  return val === null || val === void 0 ? void 0 : val.split(floatSeparators.group).join("").replace(floatSeparators.decimal, ".");
79
94
  },
80
- }, validations: Object.assign({ pattern: {
81
- value: NUMBER_VALIDATION_REGEX,
82
- message: t("errors.notANumber"),
83
- } }, props.validations), onBlur: () => {
95
+ }, validations: mergedValidations, onBlur: () => {
84
96
  var _a;
85
97
  (_a = props.onBlur) === null || _a === void 0 ? void 0 : _a.call(props);
86
98
  if (field.value === 0 ||
@@ -27,7 +27,7 @@ export function InputDate(props) {
27
27
  }
28
28
  return React.createElement(InternalInputDate, Object.assign({}, props));
29
29
  }
30
- function InternalInputDate({ clearable = "always", disabled, emptyValueLabel, invalid, maxDate, minDate, placeholder, value, name, onChange, accessibilityLabel, accessibilityHint, }) {
30
+ function InternalInputDate({ clearable = "always", disabled, emptyValueLabel, invalid, maxDate, minDate, placeholder, value, showMiniLabel = true, name, onChange, accessibilityLabel, accessibilityHint, }) {
31
31
  const [showPicker, setShowPicker] = useState(false);
32
32
  const { t, locale, formatDate } = useAtlantisI18n();
33
33
  const date = useMemo(() => {
@@ -44,7 +44,7 @@ function InternalInputDate({ clearable = "always", disabled, emptyValueLabel, in
44
44
  const canClearDate = formattedDate === emptyValueLabel ? "never" : clearable;
45
45
  const placeholderLabel = placeholder !== null && placeholder !== void 0 ? placeholder : t("date");
46
46
  return (React.createElement(React.Fragment, null,
47
- React.createElement(InputPressable, { focused: showPicker, clearable: canClearDate, disabled: disabled, invalid: invalid, placeholder: placeholderLabel, prefix: { icon: "calendar" }, value: formattedDate, onClear: handleClear, onPress: showDatePicker, accessibilityLabel: accessibilityLabel, accessibilityHint: accessibilityHint }),
47
+ React.createElement(InputPressable, { showMiniLabel: showMiniLabel, focused: showPicker, clearable: canClearDate, disabled: disabled, invalid: invalid, placeholder: placeholderLabel, prefix: { icon: "calendar" }, value: formattedDate, onClear: handleClear, onPress: showDatePicker, accessibilityLabel: accessibilityLabel, accessibilityHint: accessibilityHint }),
48
48
  React.createElement(DateTimePicker, { testID: "inputDate-datePicker", date: date || undefined, display: display, isVisible: showPicker, maximumDate: maxDate, minimumDate: minDate, mode: "date", confirmTextIOS: t("confirm"), cancelTextIOS: t("cancel"), locale: locale, onCancel: handleCancel, onConfirm: handleConfirm })));
49
49
  function showDatePicker() {
50
50
  Keyboard.dismiss();
@@ -1,9 +1,17 @@
1
1
  import React, { forwardRef } from "react";
2
2
  import { InputText } from "../InputText";
3
+ import { useAtlantisI18n } from "../hooks/useAtlantisI18n";
3
4
  export const InputEmail = forwardRef(InputEmailInternal);
4
5
  function InputEmailInternal(props, ref) {
5
- return (React.createElement(InputText, Object.assign({}, props, { ref: ref, autoCapitalize: "none", autoCorrect: false, keyboard: "email-address", validations: Object.assign({ pattern: {
6
- value: /[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?\.)+[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?/,
7
- message: "Enter a valid email address (email@example.com)",
8
- } }, props.validations) })));
6
+ const { t } = useAtlantisI18n();
7
+ const defaultValidations = {
8
+ pattern: {
9
+ value: /[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?\.)+[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?/,
10
+ message: t("InputEmail.enterEmail"),
11
+ },
12
+ };
13
+ const mergedValidations = props.validations
14
+ ? Object.assign({}, defaultValidations, props.validations)
15
+ : defaultValidations;
16
+ return (React.createElement(InputText, Object.assign({}, props, { ref: ref, autoCapitalize: "none", autoCorrect: false, keyboard: "email-address", validations: mergedValidations })));
9
17
  }
@@ -11,7 +11,7 @@ import { Text } from "../Text";
11
11
  import { ActivityIndicator } from "../ActivityIndicator";
12
12
  export const INPUT_FIELD_WRAPPER_GLIMMERS_TEST_ID = "ATL-InputFieldWrapper-Glimmers";
13
13
  export const INPUT_FIELD_WRAPPER_SPINNER_TEST_ID = "ATL-InputFieldWrapper-Spinner";
14
- export function InputFieldWrapper({ invalid, disabled, placeholder, assistiveText, prefix, suffix, hasMiniLabel = false, hasValue = false, error, focused = false, children, onClear, showClearAction = false, styleOverride, toolbar, toolbarVisibility = "while-editing", loading = false, loadingType = "spinner", }) {
14
+ export function InputFieldWrapper({ invalid, disabled, placeholder, assistiveText, prefix, suffix, placeholderMode = "normal", hasValue = false, error, focused = false, children, onClear, showClearAction = false, styleOverride, toolbar, toolbarVisibility = "while-editing", loading = false, loadingType = "spinner", }) {
15
15
  fieldAffixRequiredPropsCheck([prefix, suffix]);
16
16
  const handleClear = onClear !== null && onClear !== void 0 ? onClear : noopClear;
17
17
  warnIfClearActionWithNoOnClear(onClear, showClearAction);
@@ -20,6 +20,8 @@ export function InputFieldWrapper({ invalid, disabled, placeholder, assistiveTex
20
20
  const showLoadingSpinner = loading && loadingType === "spinner";
21
21
  const showLoadingGlimmer = loading && loadingType === "glimmer";
22
22
  const styles = useStyles();
23
+ const placeholderVisible = placeholderMode !== "hidden";
24
+ const miniLabelActive = placeholderMode === "mini";
23
25
  return (React.createElement(ErrorMessageWrapper, { message: getMessage({ invalid, error }) },
24
26
  React.createElement(View, { testID: "ATL-InputFieldWrapper", style: [
25
27
  styles.container,
@@ -29,18 +31,18 @@ export function InputFieldWrapper({ invalid, disabled, placeholder, assistiveTex
29
31
  styleOverride === null || styleOverride === void 0 ? void 0 : styleOverride.container,
30
32
  ] },
31
33
  React.createElement(View, { style: styles.field },
32
- (prefix === null || prefix === void 0 ? void 0 : prefix.icon) && (React.createElement(PrefixIcon, { disabled: disabled, focused: focused, hasMiniLabel: hasMiniLabel, inputInvalid: inputInvalid, icon: prefix.icon })),
34
+ (prefix === null || prefix === void 0 ? void 0 : prefix.icon) && (React.createElement(PrefixIcon, { disabled: disabled, focused: focused, inputInvalid: inputInvalid, icon: prefix.icon })),
33
35
  React.createElement(View, { style: [styles.inputContainer] },
34
- React.createElement(View, { style: [
36
+ placeholderVisible && (React.createElement(View, { style: [
35
37
  !!placeholder && styles.label,
36
- hasMiniLabel && styles.miniLabel,
38
+ miniLabelActive && styles.miniLabel,
37
39
  disabled && styles.disabled,
38
- hasMiniLabel &&
40
+ miniLabelActive &&
39
41
  showClearAction &&
40
42
  styles.miniLabelShowClearAction,
41
43
  ], pointerEvents: "none" },
42
- React.createElement(Placeholder, { placeholder: placeholder, labelVariation: getLabelVariation(error, invalid, disabled), hasMiniLabel: hasMiniLabel, styleOverride: styleOverride === null || styleOverride === void 0 ? void 0 : styleOverride.placeholderText })),
43
- (prefix === null || prefix === void 0 ? void 0 : prefix.label) && hasValue && (React.createElement(PrefixLabel, { disabled: disabled, focused: focused, hasMiniLabel: hasMiniLabel, inputInvalid: inputInvalid, label: prefix.label, styleOverride: styleOverride === null || styleOverride === void 0 ? void 0 : styleOverride.prefixLabel })),
44
+ React.createElement(Placeholder, { placeholder: placeholder, labelVariation: getLabelVariation(error, invalid, disabled), miniLabelActive: miniLabelActive, styleOverride: styleOverride === null || styleOverride === void 0 ? void 0 : styleOverride.placeholderText }))),
45
+ (prefix === null || prefix === void 0 ? void 0 : prefix.label) && hasValue && (React.createElement(PrefixLabel, { disabled: disabled, focused: focused, miniLabelActive: miniLabelActive, inputInvalid: inputInvalid, label: prefix.label, styleOverride: styleOverride === null || styleOverride === void 0 ? void 0 : styleOverride.prefixLabel })),
44
46
  children,
45
47
  showLoadingGlimmer && (React.createElement(View, { testID: INPUT_FIELD_WRAPPER_GLIMMERS_TEST_ID, style: [
46
48
  styles.loadingGlimmers,
@@ -54,10 +56,10 @@ export function InputFieldWrapper({ invalid, disabled, placeholder, assistiveTex
54
56
  (suffix === null || suffix === void 0 ? void 0 : suffix.icon) ||
55
57
  showLoadingSpinner) && (React.createElement(View, { style: styles.inputEndContainer },
56
58
  showClearAction && (React.createElement(ClearAction, { hasMarginRight: !!(suffix === null || suffix === void 0 ? void 0 : suffix.icon) || !!(suffix === null || suffix === void 0 ? void 0 : suffix.label), onPress: handleClear })),
57
- (suffix === null || suffix === void 0 ? void 0 : suffix.label) && hasValue && (React.createElement(SuffixLabel, { disabled: disabled, focused: focused, hasMiniLabel: hasMiniLabel, inputInvalid: inputInvalid, label: suffix.label, hasLeftMargin: !showClearAction, styleOverride: styleOverride === null || styleOverride === void 0 ? void 0 : styleOverride.suffixLabel })),
59
+ (suffix === null || suffix === void 0 ? void 0 : suffix.label) && hasValue && (React.createElement(SuffixLabel, { disabled: disabled, focused: focused, miniLabelActive: miniLabelActive, inputInvalid: inputInvalid, label: suffix.label, hasLeftMargin: !showClearAction, styleOverride: styleOverride === null || styleOverride === void 0 ? void 0 : styleOverride.suffixLabel })),
58
60
  showLoadingSpinner && (React.createElement(View, { style: styles.loadingSpinner },
59
61
  React.createElement(ActivityIndicator, { testID: INPUT_FIELD_WRAPPER_SPINNER_TEST_ID }))),
60
- (suffix === null || suffix === void 0 ? void 0 : suffix.icon) && (React.createElement(SuffixIcon, { disabled: disabled, focused: focused, hasMiniLabel: hasMiniLabel, hasLeftMargin: !!(!showClearAction || (suffix === null || suffix === void 0 ? void 0 : suffix.label)), inputInvalid: inputInvalid, icon: suffix.icon, onPress: suffix.onPress })))))),
62
+ (suffix === null || suffix === void 0 ? void 0 : suffix.icon) && (React.createElement(SuffixIcon, { disabled: disabled, focused: focused, hasLeftMargin: !!(!showClearAction || (suffix === null || suffix === void 0 ? void 0 : suffix.label)), inputInvalid: inputInvalid, icon: suffix.icon, onPress: suffix.onPress })))))),
61
63
  isToolbarVisible && React.createElement(View, { style: styles.toolbar }, toolbar)),
62
64
  assistiveText && !error && !invalid && (React.createElement(Text, { level: "textSupporting", variation: disabled ? "disabled" : focused ? "interactive" : "subdued" }, assistiveText))));
63
65
  }
@@ -93,12 +95,12 @@ function getMessage({ invalid, error, }) {
93
95
  messages.push(invalid);
94
96
  return messages.join("\n");
95
97
  }
96
- function Placeholder({ placeholder, styleOverride, labelVariation, hasMiniLabel, }) {
98
+ function Placeholder({ placeholder, styleOverride, labelVariation, miniLabelActive, }) {
97
99
  const typographyStyles = useTypographyStyles();
98
- return (React.createElement(React.Fragment, null, !styleOverride ? (React.createElement(Text, { hideFromScreenReader: true, maxLines: "single", variation: labelVariation, level: hasMiniLabel ? "textSupporting" : "text" }, placeholder)) : (React.createElement(RNText, { accessibilityRole: "none", accessible: false, importantForAccessibility: "no-hide-descendants", numberOfLines: 1, style: [
100
+ return (React.createElement(React.Fragment, null, !styleOverride ? (React.createElement(Text, { hideFromScreenReader: true, maxLines: "single", variation: labelVariation, level: miniLabelActive ? "textSupporting" : "text" }, placeholder)) : (React.createElement(RNText, { accessibilityRole: "none", accessible: false, importantForAccessibility: "no-hide-descendants", numberOfLines: 1, style: [
99
101
  typographyStyles[labelVariation],
100
102
  typographyStyles.baseRegularRegular,
101
- hasMiniLabel
103
+ miniLabelActive
102
104
  ? typographyStyles.smallSize
103
105
  : typographyStyles.defaultSize,
104
106
  styleOverride,