@jobber/components-native 0.24.1-migrate-te.4 → 0.25.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 (47) hide show
  1. package/dist/src/BottomSheet/BottomSheet.js +52 -0
  2. package/dist/src/BottomSheet/BottomSheet.style.js +28 -0
  3. package/dist/src/BottomSheet/components/BottomSheetOption/BottomSheetOption.js +17 -0
  4. package/dist/src/BottomSheet/components/BottomSheetOption/BottomSheetOption.styles.js +18 -0
  5. package/dist/src/BottomSheet/components/BottomSheetOption/index.js +1 -0
  6. package/dist/src/BottomSheet/index.js +1 -0
  7. package/dist/src/BottomSheet/messages.js +8 -0
  8. package/dist/src/hooks/index.js +1 -0
  9. package/dist/src/hooks/useIsScreenReaderEnabled.js +22 -0
  10. package/dist/src/index.js +1 -1
  11. package/dist/src/utils/test/wait.js +58 -0
  12. package/dist/tsconfig.tsbuildinfo +1 -1
  13. package/dist/types/src/BottomSheet/BottomSheet.d.ts +28 -0
  14. package/dist/types/src/BottomSheet/BottomSheet.style.d.ts +32 -0
  15. package/dist/types/src/BottomSheet/components/BottomSheetOption/BottomSheetOption.d.ts +13 -0
  16. package/dist/types/src/BottomSheet/components/BottomSheetOption/BottomSheetOption.styles.d.ts +16 -0
  17. package/dist/types/src/BottomSheet/components/BottomSheetOption/index.d.ts +1 -0
  18. package/dist/types/src/BottomSheet/index.d.ts +1 -0
  19. package/dist/types/src/BottomSheet/messages.d.ts +7 -0
  20. package/dist/types/src/hooks/index.d.ts +1 -0
  21. package/dist/types/src/hooks/useIsScreenReaderEnabled.d.ts +1 -0
  22. package/dist/types/src/index.d.ts +1 -1
  23. package/dist/types/src/utils/test/wait.d.ts +36 -0
  24. package/package.json +6 -4
  25. package/src/BottomSheet/BottomSheet.style.ts +35 -0
  26. package/src/BottomSheet/BottomSheet.test.tsx +152 -0
  27. package/src/BottomSheet/BottomSheet.tsx +149 -0
  28. package/src/BottomSheet/components/BottomSheetOption/BottomSheetOption.styles.ts +19 -0
  29. package/src/BottomSheet/components/BottomSheetOption/BottomSheetOption.test.tsx +34 -0
  30. package/src/BottomSheet/components/BottomSheetOption/BottomSheetOption.tsx +53 -0
  31. package/src/BottomSheet/components/BottomSheetOption/index.ts +1 -0
  32. package/src/BottomSheet/index.ts +1 -0
  33. package/src/BottomSheet/messages.ts +9 -0
  34. package/src/hooks/index.ts +1 -0
  35. package/src/hooks/useIsScreenReaderEnabled.ts +32 -0
  36. package/src/index.ts +1 -1
  37. package/src/utils/test/wait.ts +52 -0
  38. package/dist/src/TextList/TextList.js +0 -13
  39. package/dist/src/TextList/TextList.style.js +0 -16
  40. package/dist/src/TextList/index.js +0 -1
  41. package/dist/types/src/TextList/TextList.d.ts +0 -30
  42. package/dist/types/src/TextList/TextList.style.d.ts +0 -14
  43. package/dist/types/src/TextList/index.d.ts +0 -1
  44. package/src/TextList/TextList.style.ts +0 -17
  45. package/src/TextList/TextList.test.tsx +0 -20
  46. package/src/TextList/TextList.tsx +0 -68
  47. package/src/TextList/index.ts +0 -1
@@ -0,0 +1,52 @@
1
+ import React, { forwardRef, useState } from "react";
2
+ import { Modalize } from "react-native-modalize";
3
+ import { useSafeAreaInsets } from "react-native-safe-area-context";
4
+ import { Keyboard, View } from "react-native";
5
+ import { useIntl } from "react-intl";
6
+ import { BottomSheetOption } from "./components/BottomSheetOption";
7
+ import { styles } from "./BottomSheet.style";
8
+ import { messages } from "./messages";
9
+ import { useIsScreenReaderEnabled } from "../hooks";
10
+ import { Divider } from "../Divider";
11
+ import { Heading } from "../Heading";
12
+ export const BottomSheet = forwardRef(BottomSheetInternal);
13
+ function BottomSheetInternal({ children, showCancel, loading = false, heading, onOpen, onClose, }, ref) {
14
+ const isScreenReaderEnabled = useIsScreenReaderEnabled();
15
+ const [open, setOpen] = useState(false);
16
+ return (React.createElement(React.Fragment, null,
17
+ open && React.createElement(Overlay, null),
18
+ React.createElement(Modalize, { ref: ref, adjustToContentHeight: true, modalStyle: styles.modal, overlayStyle: styles.overlayModalize, HeaderComponent: heading && React.createElement(Header, { heading: heading }), FooterComponent: React.createElement(Footer, { cancellable: (showCancel && !loading) || isScreenReaderEnabled, onCancel: () => {
19
+ var _a;
20
+ (_a = ref === null || ref === void 0 ? void 0 : ref.current) === null || _a === void 0 ? void 0 : _a.close();
21
+ } }), withHandle: false, withReactModal: isScreenReaderEnabled, onOpen: openModal, onClose: closeModal },
22
+ React.createElement(View, { style: !showCancel && !isScreenReaderEnabled ? styles.children : undefined }, children))));
23
+ function openModal() {
24
+ onOpen === null || onOpen === void 0 ? void 0 : onOpen();
25
+ setOpen(true);
26
+ dismissKeyboard();
27
+ }
28
+ function closeModal() {
29
+ onClose === null || onClose === void 0 ? void 0 : onClose();
30
+ setOpen(false);
31
+ }
32
+ }
33
+ function Header({ heading }) {
34
+ return (React.createElement(View, { style: styles.header },
35
+ React.createElement(Heading, { level: "subtitle" }, heading)));
36
+ }
37
+ function Footer({ cancellable, onCancel, }) {
38
+ const insets = useSafeAreaInsets();
39
+ const { formatMessage } = useIntl();
40
+ return (React.createElement(View, { style: { marginBottom: insets.bottom } }, cancellable && (React.createElement(View, { style: styles.children },
41
+ React.createElement(View, { style: styles.footerDivider },
42
+ React.createElement(Divider, null)),
43
+ React.createElement(BottomSheetOption, { text: formatMessage(messages.cancel), icon: "remove", onPress: onCancel })))));
44
+ }
45
+ function dismissKeyboard() {
46
+ //Dismisses the keyboard before opening the bottom sheet.
47
+ //In the case where an input text field is focused we don't want to show the bottom sheet behind or above keyboard
48
+ Keyboard.dismiss();
49
+ }
50
+ function Overlay() {
51
+ return React.createElement(View, { style: styles.overlay });
52
+ }
@@ -0,0 +1,28 @@
1
+ import { Dimensions, StyleSheet } from "react-native";
2
+ import { tokens } from "../utils/design";
3
+ const { height } = Dimensions.get("window");
4
+ const modalBorderRadius = tokens["radius-larger"];
5
+ export const styles = StyleSheet.create({
6
+ overlayModalize: {
7
+ backgroundColor: "transparent",
8
+ },
9
+ overlay: Object.assign(Object.assign({}, StyleSheet.absoluteFillObject), { backgroundColor: tokens["color-overlay"], height }),
10
+ modal: {
11
+ borderTopLeftRadius: modalBorderRadius,
12
+ borderTopRightRadius: modalBorderRadius,
13
+ paddingTop: tokens["space-small"],
14
+ },
15
+ children: {
16
+ paddingBottom: tokens["space-small"],
17
+ },
18
+ header: {
19
+ paddingHorizontal: tokens["space-base"],
20
+ paddingTop: tokens["space-small"],
21
+ paddingBottom: tokens["space-base"],
22
+ },
23
+ footerDivider: {
24
+ marginHorizontal: tokens["space-base"],
25
+ marginTop: tokens["space-small"],
26
+ marginBottom: tokens["space-smaller"],
27
+ },
28
+ });
@@ -0,0 +1,17 @@
1
+ import React from "react";
2
+ import { TouchableOpacity, View } from "react-native";
3
+ import { styles } from "./BottomSheetOption.styles";
4
+ import { capitalize } from "../../../utils/intl";
5
+ import { Text } from "../../../Text";
6
+ import { Icon } from "../../../Icon";
7
+ export function BottomSheetOption({ text, icon, iconColor, textAlign, destructive, textTransform = "capitalize", onPress, }) {
8
+ const destructiveColor = "critical";
9
+ const textVariation = destructive ? destructiveColor : "subdued";
10
+ return (React.createElement(TouchableOpacity, { style: styles.bottomSheetOption, onPress: onPress, accessibilityLabel: text },
11
+ icon && (React.createElement(View, { style: styles.icon },
12
+ React.createElement(Icon, { name: icon, color: destructive ? destructiveColor : iconColor }))),
13
+ React.createElement(View, { style: styles.title },
14
+ React.createElement(Text, { variation: textVariation, emphasis: "strong", align: textAlign }, textTransform === "capitalize"
15
+ ? capitalize(text.toLocaleLowerCase())
16
+ : text))));
17
+ }
@@ -0,0 +1,18 @@
1
+ import { StyleSheet } from "react-native";
2
+ import { tokens } from "../../../utils/design";
3
+ export const styles = StyleSheet.create({
4
+ bottomSheetOption: {
5
+ display: "flex",
6
+ flexDirection: "row",
7
+ alignContent: "center",
8
+ alignItems: "center",
9
+ padding: tokens["space-small"],
10
+ },
11
+ icon: {
12
+ paddingHorizontal: tokens["space-small"],
13
+ },
14
+ title: {
15
+ paddingHorizontal: tokens["space-small"],
16
+ flexShrink: 1,
17
+ },
18
+ });
@@ -0,0 +1 @@
1
+ export { BottomSheetOption } from "./BottomSheetOption";
@@ -0,0 +1 @@
1
+ export { BottomSheet } from "./BottomSheet";
@@ -0,0 +1,8 @@
1
+ import { defineMessages } from "react-intl";
2
+ export const messages = defineMessages({
3
+ cancel: {
4
+ id: "cancel",
5
+ defaultMessage: "Cancel",
6
+ description: "Text for the cancel action",
7
+ },
8
+ });
@@ -1 +1,2 @@
1
1
  export * from "./useFormController";
2
+ export * from "./useIsScreenReaderEnabled";
@@ -0,0 +1,22 @@
1
+ import { useEffect, useState } from "react";
2
+ import { AccessibilityInfo } from "react-native";
3
+ export function useIsScreenReaderEnabled() {
4
+ const [screenReaderEnabled, setScreenReaderEnabled] = useState(false);
5
+ useEffect(() => {
6
+ function handleScreenReaderToggle(isScreenReaderEnabled) {
7
+ setScreenReaderEnabled(isScreenReaderEnabled);
8
+ }
9
+ AccessibilityInfo.isScreenReaderEnabled()
10
+ .then(enabled => {
11
+ setScreenReaderEnabled(enabled);
12
+ })
13
+ .catch(() => {
14
+ setScreenReaderEnabled(false);
15
+ });
16
+ const listener = AccessibilityInfo.addEventListener("screenReaderChanged", handleScreenReaderToggle);
17
+ return () => {
18
+ listener.remove();
19
+ };
20
+ }, []);
21
+ return screenReaderEnabled;
22
+ }
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 "./BottomSheet";
5
6
  export * from "./Button";
6
7
  export * from "./Card";
7
8
  export * from "./Chip";
@@ -16,7 +17,6 @@ export * from "./IconButton";
16
17
  export * from "./InputFieldWrapper";
17
18
  export * from "./InputPressable";
18
19
  export * from "./InputText";
19
- export * from "./TextList";
20
20
  export * from "./ProgressBar";
21
21
  export * from "./StatusLabel";
22
22
  export * from "./Switch";
@@ -0,0 +1,58 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import { screen } from "@testing-library/react-native";
11
+ import { act } from "react-test-renderer";
12
+ /**
13
+ * wait is used in our tests for testing Apollo Mocks
14
+ * useQuery returns fetching equal to true in the first render
15
+ * and the second render would return the mock result
16
+ * using "await act(wait)", we can wait for the next rerender
17
+ * to get the mock result of the query
18
+ * @param milliseconds time to wait in milliseconds
19
+ */
20
+ export function wait(milliseconds = 0) {
21
+ return __awaiter(this, void 0, void 0, function* () {
22
+ yield new Promise(resolve => setTimeout(resolve, milliseconds));
23
+ });
24
+ }
25
+ /**
26
+ * Use this test helper thoughtfully. If you are running into the
27
+ * "not wrapped in act(...)" warning while running your test it is
28
+ * recommended that:
29
+ *
30
+ * 1. Double check that there are really no layout changes that you can test against.
31
+ * waitForUntestableRender will fail your test if it detects layout changes
32
+ * 2. Re-evalutate your implementation. Maybe the managed state can be deferred to
33
+ * to a component further down the hierarchy? This can help prevent renders since
34
+ * your managed state isn't being used yet maybe?
35
+ *
36
+ * `waitForUntestableRender` is meant to be used as an alternative to
37
+ *
38
+ * ```tsx
39
+ * await act(wait)
40
+ * ```
41
+ *
42
+ * to make tests more readable.
43
+ *
44
+ * The `explanation` argument is required to ensure that a developer _thinks_
45
+ * about why they need use this function. It is _really_ important that devs
46
+ * understand when _and why_ a component's render cycle is flagged to be untested
47
+ * So do not put a throwaway explanation here. If you don't know why your test
48
+ * needs this function, find out!
49
+
50
+ */
51
+ export const waitForUntestableRender = (
52
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
53
+ _explanation) => __awaiter(void 0, void 0, void 0, function* () {
54
+ const before = JSON.stringify(screen.toJSON(), null, 2);
55
+ yield act(wait);
56
+ const after = JSON.stringify(screen.toJSON(), null, 2);
57
+ expect(before).toEqual(after);
58
+ });