@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.
- package/dist/src/BottomSheet/BottomSheet.js +52 -0
- package/dist/src/BottomSheet/BottomSheet.style.js +28 -0
- package/dist/src/BottomSheet/components/BottomSheetOption/BottomSheetOption.js +17 -0
- package/dist/src/BottomSheet/components/BottomSheetOption/BottomSheetOption.styles.js +18 -0
- package/dist/src/BottomSheet/components/BottomSheetOption/index.js +1 -0
- package/dist/src/BottomSheet/index.js +1 -0
- package/dist/src/BottomSheet/messages.js +8 -0
- package/dist/src/hooks/index.js +1 -0
- package/dist/src/hooks/useIsScreenReaderEnabled.js +22 -0
- package/dist/src/index.js +1 -1
- package/dist/src/utils/test/wait.js +58 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types/src/BottomSheet/BottomSheet.d.ts +28 -0
- package/dist/types/src/BottomSheet/BottomSheet.style.d.ts +32 -0
- package/dist/types/src/BottomSheet/components/BottomSheetOption/BottomSheetOption.d.ts +13 -0
- package/dist/types/src/BottomSheet/components/BottomSheetOption/BottomSheetOption.styles.d.ts +16 -0
- package/dist/types/src/BottomSheet/components/BottomSheetOption/index.d.ts +1 -0
- package/dist/types/src/BottomSheet/index.d.ts +1 -0
- package/dist/types/src/BottomSheet/messages.d.ts +7 -0
- package/dist/types/src/hooks/index.d.ts +1 -0
- package/dist/types/src/hooks/useIsScreenReaderEnabled.d.ts +1 -0
- package/dist/types/src/index.d.ts +1 -1
- package/dist/types/src/utils/test/wait.d.ts +36 -0
- package/package.json +6 -4
- package/src/BottomSheet/BottomSheet.style.ts +35 -0
- package/src/BottomSheet/BottomSheet.test.tsx +152 -0
- package/src/BottomSheet/BottomSheet.tsx +149 -0
- package/src/BottomSheet/components/BottomSheetOption/BottomSheetOption.styles.ts +19 -0
- package/src/BottomSheet/components/BottomSheetOption/BottomSheetOption.test.tsx +34 -0
- package/src/BottomSheet/components/BottomSheetOption/BottomSheetOption.tsx +53 -0
- package/src/BottomSheet/components/BottomSheetOption/index.ts +1 -0
- package/src/BottomSheet/index.ts +1 -0
- package/src/BottomSheet/messages.ts +9 -0
- package/src/hooks/index.ts +1 -0
- package/src/hooks/useIsScreenReaderEnabled.ts +32 -0
- package/src/index.ts +1 -1
- package/src/utils/test/wait.ts +52 -0
- package/dist/src/TextList/TextList.js +0 -13
- package/dist/src/TextList/TextList.style.js +0 -16
- package/dist/src/TextList/index.js +0 -1
- package/dist/types/src/TextList/TextList.d.ts +0 -30
- package/dist/types/src/TextList/TextList.style.d.ts +0 -14
- package/dist/types/src/TextList/index.d.ts +0 -1
- package/src/TextList/TextList.style.ts +0 -17
- package/src/TextList/TextList.test.tsx +0 -20
- package/src/TextList/TextList.tsx +0 -68
- 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";
|
package/dist/src/hooks/index.js
CHANGED
|
@@ -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
|
+
});
|