@jobber/components-native 0.98.5 → 0.100.0

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/dist/package.json +3 -6
  2. package/dist/src/AtlantisOverlayProvider/AtlantisOverlayProvider.js +5 -0
  3. package/dist/src/AtlantisOverlayProvider/index.js +1 -0
  4. package/dist/src/BottomSheet/BottomSheet.js +9 -11
  5. package/dist/src/BottomSheet/hooks/useBottomSheetBackHandler.js +2 -2
  6. package/dist/src/ButtonGroup/components/SecondaryActionSheet/SecondaryActionSheet.js +9 -11
  7. package/dist/src/ContentOverlay/BottomSheetKeyboardAwareScrollView.js +19 -0
  8. package/dist/src/ContentOverlay/ContentOverlay.js +143 -107
  9. package/dist/src/ContentOverlay/ContentOverlay.style.js +8 -12
  10. package/dist/src/ContentOverlay/computeContentOverlayBehavior.js +76 -0
  11. package/dist/src/ContentOverlay/constants.js +1 -0
  12. package/dist/src/ContentOverlay/hooks/useBottomSheetModalBackHandler.js +25 -0
  13. package/dist/src/ContentOverlay/index.js +1 -1
  14. package/dist/src/FormatFile/components/FormatFileBottomSheet/FormatFileBottomSheet.js +7 -9
  15. package/dist/src/InputText/InputText.js +44 -1
  16. package/dist/src/index.js +1 -0
  17. package/dist/src/utils/meta/meta.json +1 -0
  18. package/dist/tsconfig.build.tsbuildinfo +1 -1
  19. package/dist/types/src/AtlantisOverlayProvider/AtlantisOverlayProvider.d.ts +6 -0
  20. package/dist/types/src/AtlantisOverlayProvider/index.d.ts +1 -0
  21. package/dist/types/src/BottomSheet/hooks/useBottomSheetBackHandler.d.ts +3 -3
  22. package/dist/types/src/ContentOverlay/BottomSheetKeyboardAwareScrollView.d.ts +11 -0
  23. package/dist/types/src/ContentOverlay/ContentOverlay.d.ts +2 -5
  24. package/dist/types/src/ContentOverlay/ContentOverlay.style.d.ts +11 -10
  25. package/dist/types/src/ContentOverlay/computeContentOverlayBehavior.d.ts +32 -0
  26. package/dist/types/src/ContentOverlay/constants.d.ts +1 -0
  27. package/dist/types/src/ContentOverlay/hooks/useBottomSheetModalBackHandler.d.ts +7 -0
  28. package/dist/types/src/ContentOverlay/index.d.ts +1 -1
  29. package/dist/types/src/ContentOverlay/types.d.ts +5 -12
  30. package/dist/types/src/index.d.ts +1 -0
  31. package/jestSetup.js +2 -0
  32. package/package.json +3 -6
  33. package/src/AtlantisOverlayProvider/AtlantisOverlayProvider.tsx +12 -0
  34. package/src/AtlantisOverlayProvider/index.ts +1 -0
  35. package/src/BottomSheet/BottomSheet.tsx +13 -13
  36. package/src/BottomSheet/hooks/useBottomSheetBackHandler.test.ts +10 -10
  37. package/src/BottomSheet/hooks/useBottomSheetBackHandler.ts +4 -4
  38. package/src/ButtonGroup/ButtonGroup.stories.tsx +10 -8
  39. package/src/ButtonGroup/ButtonGroup.test.tsx +7 -10
  40. package/src/ButtonGroup/components/SecondaryActionSheet/SecondaryActionSheet.tsx +26 -29
  41. package/src/ContentOverlay/BottomSheetKeyboardAwareScrollView.tsx +36 -0
  42. package/src/ContentOverlay/ContentOverlay.stories.tsx +32 -36
  43. package/src/ContentOverlay/ContentOverlay.style.ts +12 -12
  44. package/src/ContentOverlay/ContentOverlay.test.tsx +157 -79
  45. package/src/ContentOverlay/ContentOverlay.tsx +247 -205
  46. package/src/ContentOverlay/computeContentOverlayBehavior.test.ts +276 -0
  47. package/src/ContentOverlay/computeContentOverlayBehavior.ts +119 -0
  48. package/src/ContentOverlay/constants.ts +1 -0
  49. package/src/ContentOverlay/hooks/useBottomSheetModalBackHandler.test.ts +81 -0
  50. package/src/ContentOverlay/hooks/useBottomSheetModalBackHandler.ts +36 -0
  51. package/src/ContentOverlay/index.ts +4 -1
  52. package/src/ContentOverlay/types.ts +5 -13
  53. package/src/Form/Form.stories.tsx +8 -4
  54. package/src/Form/Form.test.tsx +51 -54
  55. package/src/Form/components/FormSaveButton/FormSaveButton.test.tsx +7 -10
  56. package/src/FormatFile/FormatFile.stories.tsx +3 -4
  57. package/src/FormatFile/FormatFile.test.tsx +11 -14
  58. package/src/FormatFile/components/FormatFileBottomSheet/FormatFileBottomSheet.test.tsx +6 -9
  59. package/src/FormatFile/components/FormatFileBottomSheet/FormatFileBottomSheet.tsx +21 -24
  60. package/src/InputDate/InputDate.test.tsx +5 -8
  61. package/src/InputText/InputText.test.tsx +122 -0
  62. package/src/InputText/InputText.tsx +62 -2
  63. package/src/InputTime/InputTime.stories.tsx +8 -4
  64. package/src/InputTime/InputTime.test.tsx +5 -8
  65. package/src/ThumbnailList/ThumbnailList.stories.tsx +6 -4
  66. package/src/ThumbnailList/ThumbnailList.test.tsx +5 -8
  67. package/src/ThumbnailList/__snapshots__/ThumbnailList.test.tsx.snap +101 -150
  68. package/src/index.ts +1 -0
  69. package/src/utils/meta/meta.json +2 -1
  70. package/dist/src/ContentOverlay/UNSAFE_WrappedModalize.js +0 -23
  71. package/dist/types/src/ContentOverlay/UNSAFE_WrappedModalize.d.ts +0 -3
  72. package/src/ContentOverlay/UNSAFE_WrappedModalize.tsx +0 -41
@@ -1,5 +1,4 @@
1
1
  import React from "react";
2
- import { Portal } from "react-native-portalize";
3
2
  import { BottomSheet } from "../../../BottomSheet/BottomSheet";
4
3
  import { BottomSheetOption } from "../../../BottomSheet/components/BottomSheetOption";
5
4
  import { useAtlantisI18n } from "../../../hooks/useAtlantisI18n";
@@ -10,12 +9,11 @@ export const FormatFileBottomSheet = ({ bottomSheetRef, onPreviewPress, onRemove
10
9
  onPressAction();
11
10
  (_a = bottomSheetRef.current) === null || _a === void 0 ? void 0 : _a.close();
12
11
  };
13
- return (React.createElement(Portal, null,
14
- React.createElement(BottomSheet, { ref: bottomSheetRef },
15
- onPreviewPress ? (React.createElement(BottomSheetOption, { icon: "eye", text: t("FormatFile.preview", {
16
- item: bottomSheetOptionsSuffix || "",
17
- }), onPress: () => handlePress(onPreviewPress) })) : undefined,
18
- onRemovePress ? (React.createElement(BottomSheetOption, { icon: "trash", destructive: true, text: t("FormatFile.remove", {
19
- item: bottomSheetOptionsSuffix || "",
20
- }), onPress: () => handlePress(onRemovePress) })) : undefined)));
12
+ return (React.createElement(BottomSheet, { ref: bottomSheetRef },
13
+ onPreviewPress ? (React.createElement(BottomSheetOption, { icon: "eye", text: t("FormatFile.preview", {
14
+ item: bottomSheetOptionsSuffix || "",
15
+ }), onPress: () => handlePress(onPreviewPress) })) : undefined,
16
+ onRemovePress ? (React.createElement(BottomSheetOption, { icon: "trash", destructive: true, text: t("FormatFile.remove", {
17
+ item: bottomSheetOptionsSuffix || "",
18
+ }), onPress: () => handlePress(onRemovePress) })) : undefined));
21
19
  };
@@ -1,9 +1,11 @@
1
1
  import React, { forwardRef, useEffect, useImperativeHandle, useMemo, useRef, useState, } from "react";
2
- import { Platform, TextInput } from "react-native";
2
+ import { Platform, TextInput, findNodeHandle } from "react-native";
3
+ import { useBottomSheetInternal } from "@gorhom/bottom-sheet";
3
4
  import identity from "lodash/identity";
4
5
  import { useShowClear } from "@jobber/hooks";
5
6
  import { useStyles } from "./InputText.style";
6
7
  import { useInputAccessoriesContext } from "./context";
8
+ import { useIsKeyboardHandledByScrollView } from "../ContentOverlay";
7
9
  import { useFormController } from "../hooks";
8
10
  import { InputFieldWrapper } from "../InputFieldWrapper";
9
11
  import { useCommonInputStyles } from "../InputFieldWrapper/CommonInputStyles.style";
@@ -32,6 +34,18 @@ function InputTextInternal({ invalid, disabled, readonly = false, name, placehol
32
34
  hasValue,
33
35
  disabled,
34
36
  });
37
+ // When inside a scrollable ContentOverlay, keyboard offset is handled by
38
+ // KeyboardAwareScrollView. Registering with the bottom-sheet's keyboard
39
+ // state would cause double-counted spacing, so we skip it.
40
+ const isKeyboardHandledByScrollView = useIsKeyboardHandledByScrollView();
41
+ const bottomSheetContext = useBottomSheetInternal(true);
42
+ const shouldHandleBottomSheetKeyboard = bottomSheetContext !== null && !isKeyboardHandledByScrollView;
43
+ const animatedKeyboardState = shouldHandleBottomSheetKeyboard
44
+ ? bottomSheetContext.animatedKeyboardState
45
+ : undefined;
46
+ const textInputNodesRef = shouldHandleBottomSheetKeyboard
47
+ ? bottomSheetContext.textInputNodesRef
48
+ : undefined;
35
49
  // Android doesn't have an accessibility label like iOS does. By adding
36
50
  // it as a placeholder it readds it like a label. However we don't want to
37
51
  // add a placeholder on iOS.
@@ -97,10 +111,12 @@ function InputTextInternal({ invalid, disabled, readonly = false, name, placehol
97
111
  // This is tech debt related to an issue where keyboard aware scrollview doesn't work if `scrollEnabled` is true. However,
98
112
  // when `scrollEnabled` is false it causes an issue where super long text inputs will jump to the top when a new line is added to the bottom of the input.
99
113
  scrollEnabled: Platform.OS === "ios" && multiline, textContentType: textContentType, onChangeText: handleChangeText, onSubmitEditing: handleOnSubmitEditing, returnKeyType: returnKeyType, blurOnSubmit: shouldBlurOnSubmit, accessibilityLabel: accessibilityLabel || placeholder, accessibilityHint: accessibilityHint, accessibilityState: { busy: loading }, secureTextEntry: secureTextEntry }, androidA11yProps, { onFocus: event => {
114
+ handleBottomSheetFocus(event);
100
115
  _name && setFocusedInput(_name);
101
116
  setFocused(true);
102
117
  onFocus === null || onFocus === void 0 ? void 0 : onFocus(event);
103
118
  }, onBlur: event => {
119
+ handleBottomSheetBlur(event);
104
120
  _name && setFocusedInput("");
105
121
  setFocused(false);
106
122
  onBlur === null || onBlur === void 0 ? void 0 : onBlur(event);
@@ -121,6 +137,33 @@ function InputTextInternal({ invalid, disabled, readonly = false, name, placehol
121
137
  const removedIOSCharValue = isIOS ? value.replace(/\uFFFC/g, "") : value;
122
138
  updateFormAndState(removedIOSCharValue);
123
139
  }
140
+ function handleBottomSheetFocus(event) {
141
+ if (!animatedKeyboardState || !textInputNodesRef || !(event === null || event === void 0 ? void 0 : event.nativeEvent)) {
142
+ return;
143
+ }
144
+ animatedKeyboardState.set(state => (Object.assign(Object.assign({}, state), { target: event.nativeEvent.target })));
145
+ }
146
+ function handleBottomSheetBlur(event) {
147
+ if (!animatedKeyboardState || !textInputNodesRef || !(event === null || event === void 0 ? void 0 : event.nativeEvent)) {
148
+ return;
149
+ }
150
+ const keyboardState = animatedKeyboardState.get();
151
+ const currentlyFocusedInput = TextInput.State.currentlyFocusedInput();
152
+ const currentFocusedInput = currentlyFocusedInput !== null
153
+ ? findNodeHandle(
154
+ // @ts-expect-error - TextInput.State.currentlyFocusedInput() returns NativeMethods
155
+ // which is not directly assignable to findNodeHandle's expected type,
156
+ // but it works at runtime. This is a known type limitation in React Native.
157
+ currentlyFocusedInput)
158
+ : null;
159
+ // Only remove the target if it belongs to the current component
160
+ // and if the currently focused input is not in the targets set
161
+ const shouldRemoveCurrentTarget = keyboardState.target === event.nativeEvent.target;
162
+ const shouldIgnoreBlurEvent = currentFocusedInput && textInputNodesRef.current.has(currentFocusedInput);
163
+ if (shouldRemoveCurrentTarget && !shouldIgnoreBlurEvent) {
164
+ animatedKeyboardState.set(state => (Object.assign(Object.assign({}, state), { target: undefined })));
165
+ }
166
+ }
124
167
  function handleClear() {
125
168
  handleChangeText("");
126
169
  }
package/dist/src/index.js CHANGED
@@ -2,6 +2,7 @@ export * from "./ActionItem";
2
2
  export * from "./ActionLabel";
3
3
  export * from "./ActivityIndicator";
4
4
  export * from "./AtlantisContext";
5
+ export * from "./AtlantisOverlayProvider";
5
6
  export * from "./AtlantisThemeContext";
6
7
  export * from "./AutoLink";
7
8
  export * from "./Banner";
@@ -9,6 +9,7 @@
9
9
  "AtlantisContext.Provider",
10
10
  "AtlantisFormContext.Consumer",
11
11
  "AtlantisFormContext.Provider",
12
+ "AtlantisOverlayProvider",
12
13
  "AtlantisThemeContextProvider",
13
14
  "AutoLink",
14
15
  "Banner",