@jobber/components-native 0.13.0 → 0.15.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/ActionItem/ActionItem.js +37 -0
- package/dist/src/ActionItem/ActionItem.style.js +23 -0
- package/dist/src/ActionItem/ActionItemGroup.js +19 -0
- package/dist/src/ActionItem/components/ActionItemContainer.js +14 -0
- package/dist/src/ActionItem/components/ActionItemContainer.style.js +12 -0
- package/dist/src/ActionItem/index.js +2 -0
- package/dist/src/Button/Button.js +0 -1
- package/dist/src/Card/Card.js +0 -1
- package/dist/src/ProgressBar/ProgressBar.js +21 -0
- package/dist/src/ProgressBar/ProgressBar.style.js +24 -0
- package/dist/src/ProgressBar/ProgressBarInner.js +29 -0
- package/dist/src/ProgressBar/index.js +1 -0
- package/dist/src/ProgressBar/messages.js +13 -0
- package/dist/src/ProgressBar/types.js +1 -0
- package/dist/src/index.js +2 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types/src/ActionItem/ActionItem.d.ts +41 -0
- package/dist/types/src/ActionItem/ActionItem.style.d.ts +21 -0
- package/dist/types/src/ActionItem/ActionItemGroup.d.ts +11 -0
- package/dist/types/src/ActionItem/components/ActionItemContainer.d.ts +9 -0
- package/dist/types/src/ActionItem/components/ActionItemContainer.style.d.ts +10 -0
- package/dist/types/src/ActionItem/index.d.ts +2 -0
- package/dist/types/src/Card/Card.d.ts +2 -2
- package/dist/types/src/Card/index.d.ts +1 -1
- package/dist/types/src/ProgressBar/ProgressBar.d.ts +3 -0
- package/dist/types/src/ProgressBar/ProgressBar.style.d.ts +22 -0
- package/dist/types/src/ProgressBar/ProgressBarInner.d.ts +9 -0
- package/dist/types/src/ProgressBar/index.d.ts +2 -0
- package/dist/types/src/ProgressBar/messages.d.ts +12 -0
- package/dist/types/src/ProgressBar/types.d.ts +28 -0
- package/dist/types/src/index.d.ts +2 -0
- package/package.json +2 -2
- package/src/ActionItem/ActionItem.style.ts +29 -0
- package/src/ActionItem/ActionItem.test.tsx +121 -0
- package/src/ActionItem/ActionItem.tsx +131 -0
- package/src/ActionItem/ActionItemGroup.test.tsx +34 -0
- package/src/ActionItem/ActionItemGroup.tsx +43 -0
- package/src/ActionItem/components/ActionItemContainer.style.ts +14 -0
- package/src/ActionItem/components/ActionItemContainer.test.tsx +37 -0
- package/src/ActionItem/components/ActionItemContainer.tsx +45 -0
- package/src/ActionItem/index.ts +2 -0
- package/src/Button/Button.tsx +0 -1
- package/src/Card/Card.tsx +2 -3
- package/src/Card/index.ts +1 -1
- package/src/ProgressBar/ProgressBar.style.ts +25 -0
- package/src/ProgressBar/ProgressBar.test.tsx +41 -0
- package/src/ProgressBar/ProgressBar.tsx +58 -0
- package/src/ProgressBar/ProgressBarInner.tsx +47 -0
- package/src/ProgressBar/__snapshots__/ProgressBar.test.tsx.snap +138 -0
- package/src/ProgressBar/index.tsx +2 -0
- package/src/ProgressBar/messages.ts +14 -0
- package/src/ProgressBar/types.ts +34 -0
- package/src/index.ts +2 -0
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import React, { ReactNode } from "react";
|
|
2
|
+
import { Pressable, View } from "react-native";
|
|
3
|
+
import { styles } from "./ActionItemContainer.style";
|
|
4
|
+
import { styles as actionItemStyles } from "../ActionItem.style";
|
|
5
|
+
|
|
6
|
+
interface ActionItemContainerProps {
|
|
7
|
+
readonly children: ReactNode;
|
|
8
|
+
readonly title?: string;
|
|
9
|
+
readonly onPress?: () => void;
|
|
10
|
+
readonly testID?: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function ActionItemContainer({
|
|
14
|
+
onPress,
|
|
15
|
+
title,
|
|
16
|
+
children,
|
|
17
|
+
testID,
|
|
18
|
+
}: ActionItemContainerProps): JSX.Element {
|
|
19
|
+
if (onPress) {
|
|
20
|
+
return (
|
|
21
|
+
<Pressable
|
|
22
|
+
onPress={onPress}
|
|
23
|
+
style={({ pressed }) => [
|
|
24
|
+
styles.container,
|
|
25
|
+
actionItemStyles.actionItemHorizontalOffset,
|
|
26
|
+
pressed && styles.pressed,
|
|
27
|
+
]}
|
|
28
|
+
accessibilityRole="button"
|
|
29
|
+
accessibilityLabel={title}
|
|
30
|
+
testID={testID}
|
|
31
|
+
>
|
|
32
|
+
{children}
|
|
33
|
+
</Pressable>
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return (
|
|
38
|
+
<View
|
|
39
|
+
style={[styles.container, actionItemStyles.actionItemHorizontalOffset]}
|
|
40
|
+
testID={testID}
|
|
41
|
+
>
|
|
42
|
+
{children}
|
|
43
|
+
</View>
|
|
44
|
+
);
|
|
45
|
+
}
|
package/src/Button/Button.tsx
CHANGED
|
@@ -3,7 +3,6 @@ import { TouchableHighlight, View } from "react-native";
|
|
|
3
3
|
import { IconColorNames, IconNames } from "@jobber/design";
|
|
4
4
|
import { XOR } from "ts-xor";
|
|
5
5
|
import { styles } from "./Button.style";
|
|
6
|
-
// eslint-disable-next-line import/no-internal-modules
|
|
7
6
|
import { InternalButtonLoading } from "./components/InternalButtonLoading";
|
|
8
7
|
import { ButtonSize, ButtonType, ButtonVariation } from "./types";
|
|
9
8
|
import { ActionLabel, ActionLabelVariation } from "../ActionLabel";
|
package/src/Card/Card.tsx
CHANGED
|
@@ -8,7 +8,6 @@ import {
|
|
|
8
8
|
import { IconNames } from "@jobber/design";
|
|
9
9
|
import { XOR } from "ts-xor";
|
|
10
10
|
import { styles } from "./Card.style";
|
|
11
|
-
// eslint-disable-next-line import/no-internal-modules
|
|
12
11
|
import { InternalCardHeader } from "./components/InternalCardHeader";
|
|
13
12
|
import { ErrorMessageWrapper } from "../ErrorMessageWrapper";
|
|
14
13
|
import { ActionLabel } from "../ActionLabel";
|
|
@@ -49,7 +48,7 @@ type HeaderActionProps =
|
|
|
49
48
|
}
|
|
50
49
|
| {
|
|
51
50
|
readonly onPress: () => void;
|
|
52
|
-
readonly actionItem:
|
|
51
|
+
readonly actionItem: CardAction;
|
|
53
52
|
};
|
|
54
53
|
|
|
55
54
|
interface IconAction {
|
|
@@ -60,7 +59,7 @@ interface ButtonAction {
|
|
|
60
59
|
readonly label: string;
|
|
61
60
|
}
|
|
62
61
|
|
|
63
|
-
export type
|
|
62
|
+
export type CardAction = XOR<IconAction, ButtonAction>;
|
|
64
63
|
|
|
65
64
|
function getElevationStyle(elevation: elevationProp) {
|
|
66
65
|
if (elevation === "none") {
|
package/src/Card/index.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export { Card } from "./Card";
|
|
2
|
-
export type {
|
|
2
|
+
export type { CardAction, HeaderProps } from "./Card";
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { StyleSheet } from "react-native";
|
|
2
|
+
import { tokens } from "../utils/design";
|
|
3
|
+
|
|
4
|
+
export const styles = StyleSheet.create({
|
|
5
|
+
progressBarContainer: {
|
|
6
|
+
marginTop: tokens["space-small"],
|
|
7
|
+
marginBottom: tokens["space-small"],
|
|
8
|
+
height: 20,
|
|
9
|
+
position: "relative",
|
|
10
|
+
flexDirection: "row",
|
|
11
|
+
},
|
|
12
|
+
progressBarInner: {
|
|
13
|
+
backgroundColor: "rgba(255,255,255,0.3)",
|
|
14
|
+
width: "100%",
|
|
15
|
+
height: "100%",
|
|
16
|
+
position: "absolute",
|
|
17
|
+
left: 0,
|
|
18
|
+
top: 0,
|
|
19
|
+
borderRadius: 100,
|
|
20
|
+
},
|
|
21
|
+
progressInner: {
|
|
22
|
+
height: "100%",
|
|
23
|
+
borderRadius: 100,
|
|
24
|
+
},
|
|
25
|
+
});
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { render } from "@testing-library/react-native";
|
|
3
|
+
import { ProgressBar, ProgressBarProps } from ".";
|
|
4
|
+
|
|
5
|
+
const defaultSetupProps = {
|
|
6
|
+
total: 0,
|
|
7
|
+
current: 0,
|
|
8
|
+
inProgress: 0,
|
|
9
|
+
loading: false,
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
type ProgressBarCombinedProps = ProgressBarProps;
|
|
13
|
+
|
|
14
|
+
function renderProgressBarComponent({
|
|
15
|
+
total,
|
|
16
|
+
current,
|
|
17
|
+
inProgress,
|
|
18
|
+
}: ProgressBarCombinedProps) {
|
|
19
|
+
return render(
|
|
20
|
+
<ProgressBar total={total} current={current} inProgress={inProgress} />,
|
|
21
|
+
);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
it("renders blue inProgress bar when 1 or more jobs is in progress", () => {
|
|
25
|
+
const bar = renderProgressBarComponent({
|
|
26
|
+
...defaultSetupProps,
|
|
27
|
+
inProgress: 1,
|
|
28
|
+
}).toJSON();
|
|
29
|
+
expect(bar).toMatchSnapshot();
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it("renders green CompletedProgress bar when 1 or more jobs is completed", () => {
|
|
33
|
+
const current = 1;
|
|
34
|
+
const bar = renderProgressBarComponent({
|
|
35
|
+
...defaultSetupProps,
|
|
36
|
+
current: current,
|
|
37
|
+
total: 2,
|
|
38
|
+
});
|
|
39
|
+
expect(bar).toMatchSnapshot();
|
|
40
|
+
expect(bar.getByLabelText("1 of 2 complete")).toBeDefined();
|
|
41
|
+
});
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { View } from "react-native";
|
|
3
|
+
import { useIntl } from "react-intl";
|
|
4
|
+
import { ProgressBarProps } from "./types";
|
|
5
|
+
import { styles } from "./ProgressBar.style";
|
|
6
|
+
import { ProgressBarInner, calculateWidth } from "./ProgressBarInner";
|
|
7
|
+
import { messages } from "./messages";
|
|
8
|
+
import { tokens } from "../utils/design";
|
|
9
|
+
|
|
10
|
+
export function ProgressBar({
|
|
11
|
+
loading,
|
|
12
|
+
total,
|
|
13
|
+
current,
|
|
14
|
+
inProgress = 0,
|
|
15
|
+
reverseTheme = false,
|
|
16
|
+
header,
|
|
17
|
+
}: ProgressBarProps): JSX.Element {
|
|
18
|
+
const { formatMessage } = useIntl();
|
|
19
|
+
const accessibilityLabel = [];
|
|
20
|
+
accessibilityLabel.push(formatMessage(messages.complete, { current, total }));
|
|
21
|
+
inProgress &&
|
|
22
|
+
accessibilityLabel.push(formatMessage(messages.inProgress, { inProgress }));
|
|
23
|
+
|
|
24
|
+
return (
|
|
25
|
+
<View
|
|
26
|
+
accessible
|
|
27
|
+
accessibilityRole="progressbar"
|
|
28
|
+
accessibilityLabel={accessibilityLabel.join(", ")}
|
|
29
|
+
>
|
|
30
|
+
{header}
|
|
31
|
+
<View style={styles.progressBarContainer}>
|
|
32
|
+
<ProgressBarInner
|
|
33
|
+
width={100}
|
|
34
|
+
animationDuration={0}
|
|
35
|
+
color={reverseTheme ? undefined : tokens["color-surface--background"]}
|
|
36
|
+
/>
|
|
37
|
+
{!loading && (
|
|
38
|
+
<>
|
|
39
|
+
{inProgress && inProgress > 0 ? (
|
|
40
|
+
<ProgressBarInner
|
|
41
|
+
width={calculateWidth(total, current + inProgress)}
|
|
42
|
+
color={tokens["color-informative"]}
|
|
43
|
+
animationDuration={800}
|
|
44
|
+
/>
|
|
45
|
+
) : (
|
|
46
|
+
<></>
|
|
47
|
+
)}
|
|
48
|
+
<ProgressBarInner
|
|
49
|
+
width={calculateWidth(total, current)}
|
|
50
|
+
color={tokens["color-interactive"]}
|
|
51
|
+
animationDuration={600}
|
|
52
|
+
/>
|
|
53
|
+
</>
|
|
54
|
+
)}
|
|
55
|
+
</View>
|
|
56
|
+
</View>
|
|
57
|
+
);
|
|
58
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { View } from "react-native";
|
|
3
|
+
// import Reanimated from "react-native-reanimated";
|
|
4
|
+
// import { useTiming } from "utils/reanimated";
|
|
5
|
+
import { styles } from "./ProgressBar.style";
|
|
6
|
+
|
|
7
|
+
interface ProgressBarInnerProps {
|
|
8
|
+
readonly width: number;
|
|
9
|
+
readonly animationDuration?: number;
|
|
10
|
+
readonly color?: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function ProgressBarInner({
|
|
14
|
+
width,
|
|
15
|
+
// animationDuration = 0,
|
|
16
|
+
color,
|
|
17
|
+
}: ProgressBarInnerProps): JSX.Element {
|
|
18
|
+
// Animation breaking on Android
|
|
19
|
+
// const [animatedOpacity] = useTiming({
|
|
20
|
+
// duration: animationDuration,
|
|
21
|
+
// fromValue: 0,
|
|
22
|
+
// toValue: 1,
|
|
23
|
+
// });
|
|
24
|
+
|
|
25
|
+
return (
|
|
26
|
+
<View
|
|
27
|
+
style={[
|
|
28
|
+
styles.progressBarInner,
|
|
29
|
+
{
|
|
30
|
+
width: `${width}%`,
|
|
31
|
+
// opacity: animatedOpacity,
|
|
32
|
+
...(color && { backgroundColor: color }),
|
|
33
|
+
},
|
|
34
|
+
]}
|
|
35
|
+
/>
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function calculateWidth(total: number, current: number): number {
|
|
40
|
+
if (total <= 0) return 0;
|
|
41
|
+
if (current >= total) return 100;
|
|
42
|
+
|
|
43
|
+
const curr = Math.max(0, current);
|
|
44
|
+
|
|
45
|
+
if (curr >= total) return 100;
|
|
46
|
+
return (curr / total) * 100;
|
|
47
|
+
}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
2
|
+
|
|
3
|
+
exports[`renders blue inProgress bar when 1 or more jobs is in progress 1`] = `
|
|
4
|
+
<View
|
|
5
|
+
accessibilityLabel="0 of 0 complete, 1 in progress"
|
|
6
|
+
accessibilityRole="progressbar"
|
|
7
|
+
accessible={true}
|
|
8
|
+
>
|
|
9
|
+
<View
|
|
10
|
+
style={
|
|
11
|
+
{
|
|
12
|
+
"flexDirection": "row",
|
|
13
|
+
"height": 20,
|
|
14
|
+
"marginBottom": 8,
|
|
15
|
+
"marginTop": 8,
|
|
16
|
+
"position": "relative",
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
>
|
|
20
|
+
<View
|
|
21
|
+
style={
|
|
22
|
+
[
|
|
23
|
+
{
|
|
24
|
+
"backgroundColor": "rgba(255,255,255,0.3)",
|
|
25
|
+
"borderRadius": 100,
|
|
26
|
+
"height": "100%",
|
|
27
|
+
"left": 0,
|
|
28
|
+
"position": "absolute",
|
|
29
|
+
"top": 0,
|
|
30
|
+
"width": "100%",
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
"backgroundColor": "rgb(244, 244, 244)",
|
|
34
|
+
"width": "100%",
|
|
35
|
+
},
|
|
36
|
+
]
|
|
37
|
+
}
|
|
38
|
+
/>
|
|
39
|
+
<View
|
|
40
|
+
style={
|
|
41
|
+
[
|
|
42
|
+
{
|
|
43
|
+
"backgroundColor": "rgba(255,255,255,0.3)",
|
|
44
|
+
"borderRadius": 100,
|
|
45
|
+
"height": "100%",
|
|
46
|
+
"left": 0,
|
|
47
|
+
"position": "absolute",
|
|
48
|
+
"top": 0,
|
|
49
|
+
"width": "100%",
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
"backgroundColor": "rgb(60, 162, 224)",
|
|
53
|
+
"width": "0%",
|
|
54
|
+
},
|
|
55
|
+
]
|
|
56
|
+
}
|
|
57
|
+
/>
|
|
58
|
+
<View
|
|
59
|
+
style={
|
|
60
|
+
[
|
|
61
|
+
{
|
|
62
|
+
"backgroundColor": "rgba(255,255,255,0.3)",
|
|
63
|
+
"borderRadius": 100,
|
|
64
|
+
"height": "100%",
|
|
65
|
+
"left": 0,
|
|
66
|
+
"position": "absolute",
|
|
67
|
+
"top": 0,
|
|
68
|
+
"width": "100%",
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
"backgroundColor": "rgb(125, 176, 14)",
|
|
72
|
+
"width": "0%",
|
|
73
|
+
},
|
|
74
|
+
]
|
|
75
|
+
}
|
|
76
|
+
/>
|
|
77
|
+
</View>
|
|
78
|
+
</View>
|
|
79
|
+
`;
|
|
80
|
+
|
|
81
|
+
exports[`renders green CompletedProgress bar when 1 or more jobs is completed 1`] = `
|
|
82
|
+
<View
|
|
83
|
+
accessibilityLabel="1 of 2 complete"
|
|
84
|
+
accessibilityRole="progressbar"
|
|
85
|
+
accessible={true}
|
|
86
|
+
>
|
|
87
|
+
<View
|
|
88
|
+
style={
|
|
89
|
+
{
|
|
90
|
+
"flexDirection": "row",
|
|
91
|
+
"height": 20,
|
|
92
|
+
"marginBottom": 8,
|
|
93
|
+
"marginTop": 8,
|
|
94
|
+
"position": "relative",
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
>
|
|
98
|
+
<View
|
|
99
|
+
style={
|
|
100
|
+
[
|
|
101
|
+
{
|
|
102
|
+
"backgroundColor": "rgba(255,255,255,0.3)",
|
|
103
|
+
"borderRadius": 100,
|
|
104
|
+
"height": "100%",
|
|
105
|
+
"left": 0,
|
|
106
|
+
"position": "absolute",
|
|
107
|
+
"top": 0,
|
|
108
|
+
"width": "100%",
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
"backgroundColor": "rgb(244, 244, 244)",
|
|
112
|
+
"width": "100%",
|
|
113
|
+
},
|
|
114
|
+
]
|
|
115
|
+
}
|
|
116
|
+
/>
|
|
117
|
+
<View
|
|
118
|
+
style={
|
|
119
|
+
[
|
|
120
|
+
{
|
|
121
|
+
"backgroundColor": "rgba(255,255,255,0.3)",
|
|
122
|
+
"borderRadius": 100,
|
|
123
|
+
"height": "100%",
|
|
124
|
+
"left": 0,
|
|
125
|
+
"position": "absolute",
|
|
126
|
+
"top": 0,
|
|
127
|
+
"width": "100%",
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
"backgroundColor": "rgb(125, 176, 14)",
|
|
131
|
+
"width": "50%",
|
|
132
|
+
},
|
|
133
|
+
]
|
|
134
|
+
}
|
|
135
|
+
/>
|
|
136
|
+
</View>
|
|
137
|
+
</View>
|
|
138
|
+
`;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { defineMessages } from "react-intl";
|
|
2
|
+
|
|
3
|
+
export const messages = defineMessages({
|
|
4
|
+
complete: {
|
|
5
|
+
id: "complete",
|
|
6
|
+
defaultMessage: "{current} of {total} complete",
|
|
7
|
+
description: "Progress bar accessibilityLabel for current/total",
|
|
8
|
+
},
|
|
9
|
+
inProgress: {
|
|
10
|
+
id: "inProgress",
|
|
11
|
+
defaultMessage: "{inProgress} in progress",
|
|
12
|
+
description: "Progress bar accessibilityLabel for inProgress/total",
|
|
13
|
+
},
|
|
14
|
+
});
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { ReactNode } from "react";
|
|
2
|
+
|
|
3
|
+
export interface ProgressBarProps {
|
|
4
|
+
/**
|
|
5
|
+
* The total number of items to be completed
|
|
6
|
+
*/
|
|
7
|
+
readonly total: number;
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* The number of items that are currently completed
|
|
11
|
+
*/
|
|
12
|
+
readonly current: number;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* The number of items in progress (not completed, but to be less than the total)
|
|
16
|
+
*/
|
|
17
|
+
readonly inProgress?: number;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* If the progress bar is loading, the progress indicators aren't rendered on the screen
|
|
21
|
+
*/
|
|
22
|
+
readonly loading?: boolean;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* If the amountFormatted and totalAmountFormatted text needs to appear more visibile because of the
|
|
26
|
+
* background, for example
|
|
27
|
+
*/
|
|
28
|
+
readonly reverseTheme?: boolean;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Component to render above the progress bar.
|
|
32
|
+
*/
|
|
33
|
+
readonly header?: ReactNode;
|
|
34
|
+
}
|
package/src/index.ts
CHANGED