@jobber/components-native 0.26.0 → 0.27.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 (33) hide show
  1. package/dist/src/ButtonGroup/ButtonGroup.js +29 -0
  2. package/dist/src/ButtonGroup/ButtonGroup.style.js +18 -0
  3. package/dist/src/ButtonGroup/ButtonGroupAction.js +10 -0
  4. package/dist/src/ButtonGroup/components/SecondaryActionSheet/SecondaryActionSheet.js +17 -0
  5. package/dist/src/ButtonGroup/components/SecondaryActionSheet/index.js +1 -0
  6. package/dist/src/ButtonGroup/index.js +2 -0
  7. package/dist/src/ButtonGroup/messages.js +18 -0
  8. package/dist/src/ButtonGroup/types.js +1 -0
  9. package/dist/src/ButtonGroup/utils.js +42 -0
  10. package/dist/src/index.js +1 -0
  11. package/dist/tsconfig.tsbuildinfo +1 -1
  12. package/dist/types/src/ButtonGroup/ButtonGroup.d.ts +30 -0
  13. package/dist/types/src/ButtonGroup/ButtonGroup.style.d.ts +16 -0
  14. package/dist/types/src/ButtonGroup/ButtonGroupAction.d.ts +47 -0
  15. package/dist/types/src/ButtonGroup/components/SecondaryActionSheet/SecondaryActionSheet.d.ts +13 -0
  16. package/dist/types/src/ButtonGroup/components/SecondaryActionSheet/index.d.ts +1 -0
  17. package/dist/types/src/ButtonGroup/index.d.ts +3 -0
  18. package/dist/types/src/ButtonGroup/messages.d.ts +17 -0
  19. package/dist/types/src/ButtonGroup/types.d.ts +7 -0
  20. package/dist/types/src/ButtonGroup/utils.d.ts +19 -0
  21. package/dist/types/src/index.d.ts +1 -0
  22. package/package.json +2 -2
  23. package/src/ButtonGroup/ButtonGroup.style.ts +19 -0
  24. package/src/ButtonGroup/ButtonGroup.test.tsx +325 -0
  25. package/src/ButtonGroup/ButtonGroup.tsx +113 -0
  26. package/src/ButtonGroup/ButtonGroupAction.tsx +66 -0
  27. package/src/ButtonGroup/components/SecondaryActionSheet/SecondaryActionSheet.tsx +55 -0
  28. package/src/ButtonGroup/components/SecondaryActionSheet/index.ts +1 -0
  29. package/src/ButtonGroup/index.ts +8 -0
  30. package/src/ButtonGroup/messages.ts +19 -0
  31. package/src/ButtonGroup/types.ts +30 -0
  32. package/src/ButtonGroup/utils.ts +86 -0
  33. package/src/index.ts +1 -0
@@ -0,0 +1,29 @@
1
+ import React, { useRef } from "react";
2
+ import { useIntl } from "react-intl";
3
+ import { View } from "react-native";
4
+ import { PrimaryAction, SecondaryAction } from "./ButtonGroupAction";
5
+ import { messages } from "./messages";
6
+ import { styles } from "./ButtonGroup.style";
7
+ import { SecondaryActionSheet } from "./components/SecondaryActionSheet";
8
+ import { getActions, usePreventTapWhenOffline } from "./utils";
9
+ import { Button } from "../Button";
10
+ export function ButtonGroup({ children, showCancelInBottomSheet, bottomSheetHeading, onOpenBottomSheet, onCloseBottomSheet, allowTapWhenOffline = false, }) {
11
+ const { formatMessage } = useIntl();
12
+ const { handlePress } = usePreventTapWhenOffline();
13
+ const secondaryActionsRef = useRef();
14
+ const { primaryActions, secondaryActions } = getActions(children);
15
+ return (React.createElement(View, { style: styles.buttonGroup },
16
+ primaryActions.map((action, index) => {
17
+ const { label, onPress, buttonType, buttonVariation, icon, customButton, loading, } = action.props;
18
+ return (React.createElement(View, { style: styles.button, key: index }, customButton || (React.createElement(Button, { label: label, accessibilityLabel: label, onPress: allowTapWhenOffline ? onPress : handlePress(onPress), type: buttonType, variation: buttonVariation, fullHeight: true, icon: icon, loading: loading }))));
19
+ }),
20
+ secondaryActions.length > 0 && (React.createElement(View, { style: styles.moreButton },
21
+ React.createElement(Button, { icon: "more", accessibilityLabel: formatMessage(messages.more), onPress: handlePress(openBottomSheet), fullHeight: true }))),
22
+ React.createElement(SecondaryActionSheet, { heading: bottomSheetHeading, showCancel: showCancelInBottomSheet, secondaryActionsRef: secondaryActionsRef, actions: secondaryActions.map(secondaryAction => secondaryAction.props), onOpenBottomSheet: onOpenBottomSheet, onCloseBottomSheet: onCloseBottomSheet })));
23
+ function openBottomSheet() {
24
+ var _a;
25
+ (_a = secondaryActionsRef.current) === null || _a === void 0 ? void 0 : _a.open();
26
+ }
27
+ }
28
+ ButtonGroup.PrimaryAction = PrimaryAction;
29
+ ButtonGroup.SecondaryAction = SecondaryAction;
@@ -0,0 +1,18 @@
1
+ import { StyleSheet } from "react-native";
2
+ import { tokens } from "../utils/design";
3
+ export const styles = StyleSheet.create({
4
+ buttonGroup: {
5
+ width: "100%",
6
+ flexDirection: "row",
7
+ justifyContent: "flex-end",
8
+ },
9
+ button: {
10
+ flexBasis: tokens["space-largest"],
11
+ flexGrow: 1,
12
+ paddingRight: tokens["space-smaller"],
13
+ },
14
+ moreButton: {
15
+ flexBasis: tokens["space-largest"],
16
+ flexGrow: 0,
17
+ },
18
+ });
@@ -0,0 +1,10 @@
1
+ import React from "react";
2
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
3
+ export function PrimaryAction(_) {
4
+ return React.createElement(React.Fragment, null);
5
+ }
6
+ export function SecondaryAction(
7
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
8
+ _) {
9
+ return React.createElement(React.Fragment, null);
10
+ }
@@ -0,0 +1,17 @@
1
+ import React from "react";
2
+ import { View } from "react-native";
3
+ import { Portal } from "react-native-portalize";
4
+ import { BottomSheetOption } from "../../../BottomSheet/components/BottomSheetOption";
5
+ import { BottomSheet } from "../../../BottomSheet/BottomSheet";
6
+ export function SecondaryActionSheet({ actions, secondaryActionsRef, heading, showCancel, onOpenBottomSheet, onCloseBottomSheet, }) {
7
+ return (React.createElement(Portal, null,
8
+ React.createElement(BottomSheet, { heading: heading, showCancel: showCancel, ref: secondaryActionsRef, onOpen: onOpenBottomSheet, onClose: onCloseBottomSheet },
9
+ React.createElement(View, null, actions.map((action, index) => {
10
+ const { label, onPress, icon, iconColor, destructive } = action;
11
+ return (React.createElement(BottomSheetOption, { destructive: destructive, key: index, text: label, onPress: () => {
12
+ var _a;
13
+ (_a = secondaryActionsRef === null || secondaryActionsRef === void 0 ? void 0 : secondaryActionsRef.current) === null || _a === void 0 ? void 0 : _a.close();
14
+ onPress();
15
+ }, icon: icon, iconColor: iconColor }));
16
+ })))));
17
+ }
@@ -0,0 +1 @@
1
+ export { SecondaryActionSheet } from "./SecondaryActionSheet";
@@ -0,0 +1,2 @@
1
+ export { ButtonGroup } from "./ButtonGroup";
2
+ export { usePreventTapWhenOffline } from "./utils";
@@ -0,0 +1,18 @@
1
+ import { defineMessages } from "react-intl";
2
+ export const messages = defineMessages({
3
+ more: {
4
+ id: "more",
5
+ defaultMessage: "More",
6
+ description: "Accessibility label for the More button",
7
+ },
8
+ unavailableNetworkTitle: {
9
+ id: "unavailableNetworkTitle",
10
+ defaultMessage: "Network unavailable",
11
+ description: "The title for alert about network unavailable",
12
+ },
13
+ unavailableNetworkMessage: {
14
+ id: "unavailableNetworkMessage",
15
+ defaultMessage: "Check your internet connection and try again later.",
16
+ description: "The message for alert about network unavailable",
17
+ },
18
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,42 @@
1
+ import React, { useCallback } from "react";
2
+ import { useIntl } from "react-intl";
3
+ import { Alert } from "react-native";
4
+ import { messages } from "./messages";
5
+ import { PrimaryAction, SecondaryAction, } from "./ButtonGroupAction";
6
+ import { useAtlantisContext } from "../AtlantisContext/AtlantisContext";
7
+ /**
8
+ * Determine if the onPress should be fired or an alert when the device is
9
+ * online or offline
10
+ */
11
+ export function usePreventTapWhenOffline() {
12
+ const { formatMessage } = useIntl();
13
+ const { isOnline } = useAtlantisContext();
14
+ const handlePress = useCallback((callback) => {
15
+ if (isOnline)
16
+ return callback;
17
+ return () => Alert.alert(formatMessage(messages.unavailableNetworkTitle), formatMessage(messages.unavailableNetworkMessage));
18
+ }, [formatMessage, isOnline]);
19
+ return { handlePress };
20
+ }
21
+ /**
22
+ * Separate the Primary and Secondary actions into 2 const
23
+ */
24
+ export function getActions(children) {
25
+ const childArray = React.Children.toArray(children);
26
+ let primaryActions = childArray.filter(action =>
27
+ /* Checking the component type does not work in dev environments due to
28
+ * wrapper components used for hot-reload
29
+ * However, checking the type name does not work in prod due to code minification
30
+ * Hence 2 different checks here */
31
+ action.type === PrimaryAction || action.type.name === "PrimaryAction");
32
+ let secondaryActions = childArray.filter(action => action.type === SecondaryAction || action.type.name === "SecondaryAction");
33
+ if (primaryActions.length > 2) {
34
+ secondaryActions = primaryActions.slice(2).concat(secondaryActions);
35
+ primaryActions = primaryActions.slice(0, 2);
36
+ }
37
+ if (primaryActions.length === 0) {
38
+ primaryActions = secondaryActions.slice(0, 1);
39
+ secondaryActions = secondaryActions.slice(1);
40
+ }
41
+ return { primaryActions, secondaryActions };
42
+ }
package/dist/src/index.js CHANGED
@@ -4,6 +4,7 @@ export * from "./ActivityIndicator";
4
4
  export * from "./AtlantisContext";
5
5
  export * from "./BottomSheet";
6
6
  export * from "./Button";
7
+ export * from "./ButtonGroup";
7
8
  export * from "./Card";
8
9
  export * from "./Chip";
9
10
  export * from "./Content";