@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.
- package/dist/src/ButtonGroup/ButtonGroup.js +29 -0
- package/dist/src/ButtonGroup/ButtonGroup.style.js +18 -0
- package/dist/src/ButtonGroup/ButtonGroupAction.js +10 -0
- package/dist/src/ButtonGroup/components/SecondaryActionSheet/SecondaryActionSheet.js +17 -0
- package/dist/src/ButtonGroup/components/SecondaryActionSheet/index.js +1 -0
- package/dist/src/ButtonGroup/index.js +2 -0
- package/dist/src/ButtonGroup/messages.js +18 -0
- package/dist/src/ButtonGroup/types.js +1 -0
- package/dist/src/ButtonGroup/utils.js +42 -0
- package/dist/src/index.js +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types/src/ButtonGroup/ButtonGroup.d.ts +30 -0
- package/dist/types/src/ButtonGroup/ButtonGroup.style.d.ts +16 -0
- package/dist/types/src/ButtonGroup/ButtonGroupAction.d.ts +47 -0
- package/dist/types/src/ButtonGroup/components/SecondaryActionSheet/SecondaryActionSheet.d.ts +13 -0
- package/dist/types/src/ButtonGroup/components/SecondaryActionSheet/index.d.ts +1 -0
- package/dist/types/src/ButtonGroup/index.d.ts +3 -0
- package/dist/types/src/ButtonGroup/messages.d.ts +17 -0
- package/dist/types/src/ButtonGroup/types.d.ts +7 -0
- package/dist/types/src/ButtonGroup/utils.d.ts +19 -0
- package/dist/types/src/index.d.ts +1 -0
- package/package.json +2 -2
- package/src/ButtonGroup/ButtonGroup.style.ts +19 -0
- package/src/ButtonGroup/ButtonGroup.test.tsx +325 -0
- package/src/ButtonGroup/ButtonGroup.tsx +113 -0
- package/src/ButtonGroup/ButtonGroupAction.tsx +66 -0
- package/src/ButtonGroup/components/SecondaryActionSheet/SecondaryActionSheet.tsx +55 -0
- package/src/ButtonGroup/components/SecondaryActionSheet/index.ts +1 -0
- package/src/ButtonGroup/index.ts +8 -0
- package/src/ButtonGroup/messages.ts +19 -0
- package/src/ButtonGroup/types.ts +30 -0
- package/src/ButtonGroup/utils.ts +86 -0
- 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,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